Skip to main content

Module client

Module client 

Source
Expand description

Transport-agnostic client participant state and sealed effects.

The client aggregate owns correlation, detach replay, and the durability barrier for one outstanding operation. The authorized round-3 order is commit-seal, persist the committed resume record, then release executable authority; pending has no durable form.

§LP-CLIENT-GOAL API-shape rationale

The Phase 1 brief requires authority-safe shapes rather than caller-owned state parts. The resulting public shape is deliberate:

  1. Replay and reconnect transitions consume and return the root aggregate so their facts are persisted atomically; standalone state-part recomposition is not representable.
  2. ReconnectAggregate has no public constructor because fresh detached reconnect state would separate permit identity from participant facts.
  3. recover_reconnect_permit exists because an unissued committed cold record must release its permit once without making permits cloneable.
  4. Only the commit seal exposes a durable record; pending has no encoder. The authorized round-3 order is commit-seal, persist committed LPCR, release.
  5. The retained name crate::outcome::ReconnectDelayResult carries an event, never a delay: the brief explicitly supersedes timer scheduling.
  6. A different retained detach is refused while live, but terminal or attach-superseded replay yields only to an exact newer-generation detach.
  7. Terminalized-detach fixture construction remains cfg(test) only; wire authority construction is not weakened in production.
  8. Detach recording is atomic with record_operation, so no public raw envelope-to-replay mint or second caller-owned persistence step exists.
  9. DetachTransportFate is closed to response unavailability because this protocol crate owns no socket, runtime, or transport handle.
  10. DetachReplayOutcome is exhaustive so a generic server value cannot be relabeled by a caller as one of the three terminal detach outcomes.
  11. Reconnect fresh-event producers are separate typed functions rather than a generic event-injection seam, limiting minting to the brief’s classes.
  12. recover_expected_operation is the one-use post-restore counterpart to the pending-to-commit barrier; detach recovery also marks replay in flight.
  13. Replay inspection returns None only for its named Empty state; terminal payloads remain lossless and distinct.
  14. There is no speculative persistence format. A pending-window crash means the operation did not happen and restart may record it again.
  15. RecordAdmission responses are always ambiguous because wire identity is insufficient; ObserverRecovery compares its echoed list. As the M7 companion rule, both tokenless classes resolve as typed abandoned on every restore and are never re-released. A later sealed-transport-context SDK leg may add outbound attempt tokens and lift this restriction.
  16. A crash or restore that destroys live authority mints a serialized, take-once LostAuthorityTestimony with no public constructor (LP-CLIENT-GOAL piece 4, r2, 2026-07-18). Every public fate or recovery entry point consumes either a live one-use correlation, a one-use sealed attempt authority, or the pending serialized testimony; no publicly constructible process-fate value exists, so a fate that consumes neither is unrepresentable at the API surface.
  17. Detached bindings retain the attach secret because the complete client record must remain capable of a later credential attach after restart.
  18. Expected recovery and replay-start atomically share one detach issuance bit, guaranteeing one first-send authority in either call order.
  19. Both pending atoms use the retain-in-bytes encode shape (LP-CLIENT-GOAL piece 2, r2, 2026-07-18): encoding an aggregate that holds a pending testimony or abandonment emits bytes that carry the atom, so encode-without-take loses nothing and no checkpoint window is refused. The refuse-while-pending shape was rejected because piece 4 requires the testimony to round-trip losslessly through the aggregate encoding.
  20. Re-recording the retained detach envelope requires replay-status compatibility with a fresh first send: only Parked admits; superseded, Leave-superseded, terminal, and in-flight statuses refuse with typed ClientOperationRecordRefusalReason::DetachReplayIncompatible (r2, 2026-07-18), closing the round-4 door that revived expected-detach authority over an inactive replay.

§Exhaustive constructible-state audit

Every state accepted by restore or reachable through a public apply path is listed here. The exhaustive conservation property test mechanically covers the live authority and typed consumption columns across 610 applied paths from a 4-operation × 11-action alphabet through depth 7, attempting every action at every step: 1041 attempts end in the crate’s typed refusal and 1748 are unrepresentable because the consumed one-use value does not exist at the type level. Every row below is either reachable-and-tested or refused-by-construction with the refusing type named.

Owned stateRestore/apply acceptanceLive authorityTyped consumption / exit
Binding Unboundnew, restore0enrollment/attach → Bound; identity-bound requests refuse
Binding Boundenrollment/attach, restore0detach result → Detached; Leave/Retired → Left
Binding Detacheddetach result, restore0exact-secret attach → Bound; Leave/Retired → Left
Binding Leftcorrelated Leave/Retired, restore0permanent; inbound/outbound return AlreadyDead
Expected Nonenew, abort, consumed outcome/fate, restore0one record_operation admission
Tokenless expected, live process onlyrecord/commit/release0 or 1exact response remains conservative; fate consumes; every restore converts it into the durable TokenlessAfterCrash abandonment atom below
Token-bearing non-detach, unissuedcommitted LPCR, restore0recover_expected_operation issues once
Token-bearing non-detach, issuedrelease/recovery, restore1 live, or serialized testimony after restorecorrelated outcome/fate consumes the live correlation; restore mints the take-once testimony consumed only by resolve_lost_operation_authority
Expected detach + replay Parkedcommit, live fate, testimony resolution, restore only when exact and unissued0recovery or replay start issues exactly one effect
Expected detach + replay InFlightrelease/start, restore only when exact and issued1 live, or serialized testimony after restorecorrelated outcome/fate consumes the live correlation; restore mints the take-once testimony whose resolve_lost_operation_authority resolution parks exact-token replay
Expected detach + replay Empty, Superseded, LeaveSuperseded, or terminalnever accepted, unreachable by construction0refused at restore by ClientResumeRestoreError::ExpectedDetachActiveReplayMismatch and in live code by ClientOperationRecordRefusalReason::DetachReplayIncompatible, which closes the only door that could re-couple an expected detach to an inactive replay
Active replay without exact expected detachnever accepted0typed ActiveReplayExpectedDetachMismatch restore refusal
Replay Emptynew, abort, restore without expected detach0admitted detach records Parked atomically
Replay Supersededauthority-consuming matching attach, restore0old generation terminal; exact newer generation may replace; same-envelope re-record refused by construction (DetachReplayIncompatible)
Replay LeaveSupersededauthority-consuming matching durable Leave, restore0proves only that matching Leave/retirement superseded replay; public apply_leave_durable does not change binding to Left; same-envelope re-record refused by construction (DetachReplayIncompatible)
Replay terminal (three exact payload arms)authority-consuming exact outcome, restore0lossless terminal; exact newer-generation detach may replace; same-envelope re-record refused by construction (DetachReplayIncompatible)
Restored-loss testimony, operation slotminted only by validated restore of an issued token-bearing operation; carried losslessly by encode/decodecounts as the destroyed authorityconsumed exactly once by resolve_lost_operation_authority; coupling refusals in both directions: a serialized atom without its issued state (or with the wrong kind) is refused by construction by ClientResumeRestoreError::LostAuthorityTestimonyMismatch, and every live consumption of the testified state is refused reachable-and-tested by the typed LostAuthorityPending reasons on decide_correlated_inbound, record_expected_operation_fate, transport_fate, apply_attach, apply_leave_durable, and apply_detach_outcome
Restored-loss testimony, reconnect slotminted only by validated restore of an issued permit or in-progress attempt; carried losslessly by encode/decodecounts as the destroyed authorityconsumed exactly once by resolve_lost_reconnect_authority; coupling refusals in both directions: a serialized atom without its matching machine state is refused by construction by ClientResumeRestoreError::LostAuthorityTestimonyMismatch, and prior-process handles are refused reachable-and-tested by ReconnectAttemptRefusalReason::LostAuthorityPending and ReconnectAttemptFateRefusalReason::LostAuthorityPending
Pending TokenlessAfterCrash abandonmentminted by restore of a tokenless expected operation; carried losslessly by encode/decode with its issued flagwas_issued marks a destroyed authoritytaken exactly once by ClientParticipantAggregate::take_restored_operation_abandonment; a second take observes nothing; coupling refusals in both directions: a serialized abandonment beside a tokenless expected operation is refused by construction by ClientResumeRestoreError::PendingAbandonmentConflict, and tokenless admission while pending is refused reachable-and-tested by ClientOperationRecordRefusalReason::AbandonmentPending
Reconnect Parkednew/failure/loss resolution, restore0typed fresh event → permit
Reconnect permit unissuedcommitted restore testimony0one recover_reconnect_permit issue
Reconnect permit issuedevent/recovery, restore1 live, or serialized testimony after restoreheld permit → attempt; restore mints the take-once testimony consumed only by resolve_lost_reconnect_authority
Reconnect attemptpermit redemption, restore1 live, or serialized testimony after restoreheld fate → Online/Parked; restore mints the take-once testimony consumed only by resolve_lost_reconnect_authority
Reconnect Onlinesuccessful fate, restore0later typed fresh event → permit

Structs§

ClientContinuousOperation
Continuous acknowledgement that bypasses the write-ahead slot.
ClientCorrelatedInboundRefusal
Refused body-omitting response with the exact local correlation retained.
ClientInboundApplied
Applied inbound value and resulting aggregate.
ClientInboundRefusal
Refused inbound value paired with the unchanged aggregate.
ClientOperationCommit
Committed operation decision that still seals aggregate and execution authority.
ClientOperationRecordRefusal
Unchanged aggregate and request refused before persistence.
ClientParticipantAggregate
Non-cloneable client participant state shell.
ClientPendingOperationRecord
Pending decision whose successor and executable parts remain unreachable.
ClientResponseCorrelation
Non-cloneable local correlation for responses that omit request body identity.
ClientResumeRecord
Private-field, inert, canonical client persistence record.
DetachReplayApplied
Applied detach replay transition.
DetachReplayRefusal
Refused detach replay transition with unchanged aggregate and input.
DetachTransportAttempt
Sealed effect authorizing one transport send of the exact detach.
ExpectedParticipantOperation
Sealed, non-cloneable authority to execute exactly the committed operation.
LostAuthorityTestimony
Serialized, take-once testimony that live process-local authority was destroyed by crash or restore (LP-CLIENT-GOAL piece 4, r2, 2026-07-18).
ReconnectAggregate
Non-cloneable reconnect producer and single-attempt state shell.
ReconnectAttemptPermit
Sealed, non-cloneable authority for one real connection attempt.
ReconnectInProgressAttempt
Sealed in-progress authority held while the binding opens a real connection.
ReconnectPermitRefusal
Fresh-event refusal with unchanged aggregate and retained event.
RestoredExpectedOperationAbandonment
Typed restore resolution for an operation that cannot safely be re-issued.
SdkDetachReplayAggregate
Non-cloneable owner of the exact detach replay envelope and lifecycle.

Enums§

ApplyAttachDecision
Decision for applying a matching newer attach to replay.
ApplyDetachOutcomeDecision
Decision for terminalizing detach replay.
ApplyLeaveDecision
Decision for applying a durable Leave to replay.
ClientBindingStatus
Coarse client binding state without exposing credential-bearing state parts.
ClientCorrelatedInboundDecision
Inbound decision for response classes whose wire envelopes omit request identity.
ClientInboundDecision
Exhaustive inbound correlation decision.
ClientInboundRefusalReason
Closed refusal classes for inbound semantic values.
ClientOperationRecordDecision
Complete write-ahead admission decision.
ClientOperationRecordRefusalReason
Reason an operation could not enter the write-ahead slot.
ClientResumeRecordDecodeError
Typed canonical client-record decode failure.
ClientResumeRecordEncodeError
Failure while creating a canonical record from live client state.
ClientResumeRecordSection
Section whose tag or nested canonical frame was invalid.
ClientResumeRestoreError
Validated cold-restore invariant failure.
DetachReplayOutcome
Typed terminal detach outcome accepted by replay.
DetachReplayRefusalReason
Reason a detach replay input was refused unchanged.
DetachReplayStatus
Closed, lossless detach replay status vocabulary.
DetachReplayTerminal
Typed terminal detach replay outcomes retained without projection.
DetachTransportAttemptDecision
Decision for starting a detach transport attempt.
DetachTransportFate
Typed transport fate for an outstanding detach send.
DetachTransportFateDecision
Decision for returning an in-flight detach to parked replay.
EstablishedConnectionTransportFate
Established-connection transport fate authorizing one reconnect attempt.
ExpectedOperationFateDecision
Complete typed fate decision for an issued non-detach operation.
ExpectedOperationFateRefusalReason
Reason an expected-operation transport fate was refused.
ExpectedOperationTransportFate
Typed transport fate for an issued non-detach operation awaiting a response.
ExplicitReconnectAction
Explicit caller action authorizing one reconnect attempt.
LostAuthorityKind
Closed description of which live process-local authority was destroyed.
LostAuthorityResolutionRefusalReason
Reason a lost-authority resolution was refused.
LostOperationAuthorityDecision
Complete decision for resolving a restored operation-authority loss.
LostReconnectAuthorityDecision
Complete decision for resolving restored reconnect-authority loss.
ProvedOnlineTransition
Proved online transition authorizing one reconnect attempt.
ReconnectAttemptDecision
Complete permit redemption decision.
ReconnectAttemptFate
Typed fate of one real connection attempt.
ReconnectAttemptFateDecision
Complete attempt-fate decision.
ReconnectAttemptFateRefusalReason
Reason an attempt fate was refused.
ReconnectAttemptRefusalReason
Reason a permit redemption was refused unchanged.
ReconnectFreshEvent
Closed fresh-event classes that may mint one reconnect permit.
ReconnectPermitDecision
Complete fresh-event permit decision.
ReconnectPermitRefusalReason
Reason a fresh event did not mint another permit.
RecoveredExpectedOperationDecision
Decision for releasing a committed cold-restored operation exactly once.
RecoveredReconnectPermitDecision
Decision for releasing a validated cold-restored permit exactly once.
RestoredExpectedOperationAbandonmentReason
Why a persisted expected operation was deliberately not re-released.

Functions§

apply_attach
Applies attach supersession without treating attach as transport fate.
apply_detach_outcome
Validates a typed detach outcome against the retained exact request.
apply_leave_durable
Applies durable Leave supersession.
decide_correlated_inbound
Attempts correlation while retaining the process-local handle on refusal.
decide_inbound
Correlates and applies one server value inside the client aggregate.
record_attempt_fate
Records typed success or failure for one in-progress real attempt.
record_expected_operation_fate
Records transport loss for the exact issued non-detach operation.
record_explicit_reconnect
Records explicit caller action and mints at most one permit.
record_online_transition
Records a proved online transition and mints at most one permit.
record_operation
Records one operation behind the client durability barrier.
record_transport_fate
Records established-connection transport fate and mints at most one permit.
recover_expected_operation
Releases an unissued operation from a validated committed cold restore.
recover_reconnect_permit
Releases an unissued permit created only by a committed cold record.
redeem_attempt
Redeems one fresh permit into one in-progress real connection attempt.
resolve_lost_operation_authority
Consumes the pending operation-domain lost-authority testimony exactly once.
resolve_lost_reconnect_authority
Consumes the pending reconnect-domain lost-authority testimony exactly once.
transport_attempt_started
Moves a parked detach to in-flight and releases its exact send effect.
transport_fate
Consumes the outstanding send authority with typed transport fate.