Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Typed States And Validation Boundaries

Nervix represents absence and distinct semantic states in its types. A zero, empty string, empty collection, maximum integer, or all-zero digest is a value in its own right; it does not stand for a missing value or a different state. The owner of each state decides when a value is required, validates it there, and passes the resulting typed value to the next layer. This keeps the registry, execution plans, runtime, clients, and diagnostics from assigning different meanings to the same raw value.

This chapter describes the landed typed-state architecture across those boundaries. The Cluster Interconnect chapter owns node-to-node wire forms, membership, relay delivery, and transport failures. Domain Clock owns clock installation, authority, and time bounds. Shutdown And Recovery owns drain, handoff, and restart semantics. The state rules here apply to those systems without replacing their detailed contracts.

Execution Plans follows the validated values into a complete installed revision.

A State Has One Owner

Text is parsed into a semantic Model, registry validation resolves its references and contracts, and planning produces an execution plan. Each stage passes forward a value whose type expresses what has already been established. Runtime code executes the plan; it does not reinterpret a Model or infer a state from a display label. Shared identities live in the vocabulary so every layer uses the same meaning for a domain, branch, node, timestamp, or schema fingerprint.

Source-owned identity and installation contracts

Gate these reviewable contracts with cfg_attr(nervix_lint, ...):

#[cfg_attr(nervix_lint, nervix::identity(node, reason = "destination cluster member"))]
destination: ClusterNodeName,

#[cfg_attr(nervix_lint, nervix::state(installed, reason = "constructed before branch admission"))]
branches: OnceLock<NamedBranches>,

identity(node, ...) marks shared vocabulary identity types, and declares an identity requirement on an exact field, parameter, type alias or function return. The compiler resolves aliases and normalizes types. References, arrays/slices, Option, Vec, Box and shared Arc wrappers carry their typed identity; Result checks its success type. A tuple or unrelated container containing a typed node does not make another string member an identity. Identity types must belong to the vocabulary. The current vocabulary includes cluster node names, process-incarnation identities, graph node references and domain node references. Ordinary labels and external pass-through strings carry no identity requirement merely because their identifier contains node.

state(installed, ...) describes a field’s installation lifetime and forbids a resolved RwLock anywhere in its normalized representation, including aliases and outer wrappers. Immutable construction, one-time initialization or an appropriate publication primitive preserves the owning lifetime. A field containing RwLock<Option<name or shared handle>> without a state contract emits nervix::state_contract for review. Its type cannot establish whether the value is installed once or replaced repeatedly. A genuinely replaceable field declares state(mutable, ...) with the replacement’s actual owner and reason. The annotation proves neither a runtime lifetime nor a publication ordering; affected runtime corrections still need their owner tests and models.

These are ordinary compiler diagnostics in the complete architecture gate, without numeric allowances or a filename-based identity policy. The developer guide describes qualification and evidence.

The representation depends on the question being asked:

QuestionRepresentationBoundary obligation
May the value be absent?Option<T>Keep None distinct until the owner either permits absence or reports a missing required value.
Which semantic state exists?An enum variant with the data of that stateMatch the variant; do not reconstruct the state from a string, count, or collection shape.
Is a present value valid?A validated type or a fallible conversionReject invalid input where the owner has enough context to explain it.
Can a physical format encode the state?A private wire, storage, Arrow, or atomic encodingDecode at the boundary and expose typed operations to callers.

Consensus replication replies have explicit initial-probe, ordered-stream and finished phases. Leading empty requests confirm a log boundary over management capacity; the first data request transfers the remaining input to one ordered stream. Empty commit updates then remain in that stream’s order. A failed or rejected initial probe ends its input, so no data stream can follow an unconfirmed boundary. These phases are volatile protocol state and are never persisted.

A pure conversion refusal is an ordinary typed outcome, even when it implements std::error::Error for a parsing trait. Its owner states that contract at the exact error type with reason-bearing nervix::error_boundary(outcome, ...) metadata. A contextual operation failure returns a report; a missing value does not silently turn one into a success. The resolved compiler gate and report-carrier obligations are described in Errors And Diagnostics.

Zero work outstanding, an initial sequence value, an empty payload, and a genuinely empty result remain ordinary values. A documented scalar function may return zero for a particular input; that result is part of the function contract. Arrow values under a null or failure validity mask also do not encode absence in the numeric lane: the mask does. An Option or enum is needed when the state is absent or different, not merely because a literal looks special.

The guest protocol keeps an absent branch key and an absent source token distinct from present values. Empty application-state bytes remain present inside the Rust SDK’s snapshot envelope. Reset acceptance, reset refusal, an unusable snapshot envelope and rejected application state have distinct typed ABI verdicts. Protocol decoding checks the complete size-prefixed header before identifier access and verifies offsets and counts before constructing owned values.

Absence And Distinct States

Consensus append input. None from the caller’s request stream means that input has ended; the adapter returns an empty answer stream and opens no transport. Some carries the first typed append request, retained exactly once while setup runs. A membership, admission or transport error after obtaining that request remains a failure naming its peer; it is not inferred from ended input. The caller’s retry and cancellation gate runs before this distinction is resolved.

Runtime checkpoint exchange. A state synchronization answer uses None only when the requester already holds the owner’s current revision. Some carries a typed revision, byte length and digest; zero-length checkpoint bytes remain a present checkpoint. The subsequent bulk request names that exact revision. The receiver verifies the declared and received lengths and digest before it constructs an installable state entry, so a partial stream is a transfer failure rather than a different absence or an empty checkpoint. A handoff carries the same descriptions beside their typed placements and prepares state only after each selected stream verifies.

Node trace export. A tracing guard either has no trace export or owns its provider and resolver publication together. The publication carries Option<DnsResolver>: absence means startup has not installed the node resolver, and presence carries that same resolver’s shared handle. A closed publication before installation is a distinct connection failure, not a choice of another resolver. The lazy connector waits through the publication primitive; its export connection timeout starts only after installation, preserving early startup spans.

Branching. A validated branch declaration is either unbranched or carries its named branch and resolved schema together. The schema supplies the branch fields and their sensitivity, so a runtime plan cannot pair a present branch schema with an independently missing sensitivity set. Unbranched execution has no branch key; a concrete key has a nonempty declared shape. An empty field list or synthetic root identifier does not select a branch. A concrete key holds only finite floats, because the VM turns a non-finite float result into a row error and a non-finite float has no canonical text to key a branch by. A record’s fields are not held to that rule: a payload number rounding past an F32 field’s range, an Avro float or a producer’s Arrow batch can bring a NaN or an infinity in, and every JSON rendering of a record, such as a materialized report, a hash map answer or a hash map key, writes one as the string NaN, Infinity or -Infinity. A key read from a stored checkpoint or a peer that holds one fails with BranchKeyError::NonFiniteFloat, and one holding a datetime that is not RFC 3339 text fails with BranchKeyError::RemoteFieldValue; both name the field. A concrete key is a key of a branch schema when it holds exactly the schema’s fields, each with a value of exactly its declared type; a missing or undeclared field and a value of another type are distinct BranchKeyShapeError states naming the field, never a value converted to fit. The subscription Row encoder holds each key to its relay’s branch with that one check, and a restore holds every archived key it installs to the branching its restored entity declares before staging it; see Backup And Restore. Materialized-state reads use the incoming concrete branch, or the actual unbranched state, and reporting keeps the optional branch identity until the display boundary. The structural ASCII graph projection is domain-free; a serialized graph retains its real typed domain.

An emitter’s buffered Arrow carrier keeps its typed source relay and optional concrete branch key. The relay’s declared branch name is fixed, so the pair identifies the exact source branch even if another relay uses the same key fields and values. Payload assembly compares the pair before combining carriers, and unbranched absence remains None throughout buffering and packing. Each buffered row is one of three states: pending, carried by a batch payload or prepared request the emitter retains, or resolved. A retained payload’s members are therefore neither packed or prepared again nor mistaken for resolved rows, which a delivered flag could not express.

A client emitter’s consumer, delivery identity and ACK attempt are separate typed identities. The optional concrete branch remains an internal BranchKey; the client sees only its opaque fingerprint, never its key values. An attempt is pending or assigned to one consumer with one reference and deadline. Retry, timeout or detach makes that reference stale before another attempt becomes live. Confirmed ACK, retry and rejection results have bounded retention for idempotence and expire independently of the delivery identity. An absent consumer is not encoded as an empty consumer id, and an unbranched batch has no synthetic branch fingerprint.

The Rust client’s desired producer and consumer handles have distinct active, interrupted, restoring, reopen-required and closed states. An attachment belongs to one session exchange; a replacement receives a fresh request-derived identity. The producer’s unresolved sent batch has an unknown outcome, rather than a missing outcome defaulted to not admitted. A consumer reports the interruption before delivery from a replacement attachment. Its prior delivery reference is expired, while a settlement sent before losing its answer is separately uncertain. The domain START generation and endpoint contract fingerprint are required values on every successful consumer open, so absence cannot be mistaken for a matching contract.

Expression scopes and errors. The VM frontend receives a scope policy that says whether a bare field may be read, written, both, or neither. A generated or set-only route reports an unavailable message or input scope during lowering, rather than inventing a namespace that later fails lookup. Message errors carry a MessageErrorOperation variant through evaluation and route handling. Its display text is derived from the variant; changing a label cannot select a different operation. Structured errors identify the operation and affected fields without exposing sensitive payload values.

Progress. A node’s applied schedule revision is optional before its first successful application. Once applied, every u64 revision, including the maximum, is a real revision that suppresses equal or older publications. The revision is recorded under the lock that serializes schedule application, so the decision and its recorded state stay together. Consensus byte-based snapshot retention likewise distinguishes no request from a request made while there was no completed snapshot, and from one made at completed index zero. The trigger holds the optional completed index that existed when the request was made; it suppresses duplicate requests for that same completed snapshot without confusing its absence with index zero.

Remote acknowledgements and admission. A routing position is open with its generation and optional correlation, or permanently closed. A correlation owns either a delivery’s record rows or an admission response channel. Pending rows distinguish waiting for admission from admitted silence; ordered parked progress retains its required-wait guard. The wire number is an opaque position/generation/row encoding, validated behind this owner with the registrar process identity. No numeric value means missing, and an exhausted generation never wraps into a live identity. An authenticated peer is starting, awaiting membership with its bound epoch, live with that epoch, or ended. The admission choice’s private atomic byte exposes only pending, admitted and cancelled; one compare-and-exchange chooses an irreversible verdict. Borrowed admitted work and released transport permits have separate lifetimes. Cluster Interconnect owns their delivery guarantees and bounds.

Client ingestors. An ingestor’s input is either a transport, which carries its source and the codec that decodes it, or a client source, which carries the schema its batches hold and its producer policy. There is no optional codec beside an optional schema, so an ingestor cannot claim both or neither. A producer’s admission is Open or Suspended; a batch’s outcome is one of four variants, each carrying its own typed cause, so a completed batch has no cause and a refused one no failure; and a producer’s end is one typed reason. A producer’s identity is the request identity that opened it, and a forwarded producer’s link key is never reused within its process, so neither has a reserved value meaning none. The client ingestor endpoint’s published counts are genuine zero counts, never markers.

Sources and sinks. A source or a sink is addressed by the connector that serves it and the entity it consumes, and its Model states both in its shape: the union holds one variant per connector, that variant holds one variant per entity, and each entity has its own Model with only the fields its statement writes. A Kafka topic source therefore cannot hold a Pub/Sub channel, and an OpenTelemetry sink is a logs, a traces or a metrics sink, so only a metrics sink carries a metric and no signal value sits beside mappings that might contradict it. The kind that names a pair is read from the Model and never stored beside it. An ingestor alteration is nested the same way: its head selects one connector and entity, and the operations of that entity set a source of that entity’s own Model, so ALTER KAFKA TOPIC INGESTOR cannot carry a Redis channel and no kind field sits beside the source it sets. Only a transport’s operations include the codec that decodes its payloads, so a client producer alteration cannot hold one. A stored ingestor of another pair is refused by comparing the two kinds. The names an external system owns, such as a Kafka topic or a NATS subject, are distinct types from Nervix names: each is checked against its entity’s own rule once, when it is parsed or decoded, and keeps its text exactly as written, case included, so a connector sends what the statement says. What every source or sink of a pair declares, whatever its statement says, is declared once on that entity’s Model in the vocabulary: whether its messages carry headers, the typed metadata namespace they expose, whether it runs on every node, what its body references, and for a sink whether it writes headers, needs a codec, requires batching and which publishing modes it accepts. A client Model names the connector it configures as a typed kind, so a source or a sink is matched with its client by comparing kinds rather than labels. A session producer’s source is no transport, so the transport union holds no Model of it; the kind union still names it, because capability decisions ask about every source.

Endpoint availability. Gossip publication carries an optional typed interconnect endpoint. Parsing a present advertised endpoint checks its host and port syntax. Membership admission requires that validated interconnect endpoint; an incomplete publication cannot become a reachable member through an empty address. Other service advertisements, including the console, may be absent independently. Absence says the service is unavailable; it does not invent a reason. Peer selection and transport handling follow the interconnect contract.

Startup voter evidence. The reconciliation task owns a process-local set of typed node names actually observed live, including observations made while following. An absent voter in that set means no live observation; Chitchat’s current dead verdict does not supply one. A first relayed heartbeat can therefore leave a voter unobserved even though gossip knows its identity. Expiring the ten-second startup grace ends the observation requirement without declaring that voter live, and a leadership change retains the original deadline. The set is discarded after expiry. See Whole-Cluster Restart Keeps Ownership.

Identity Across Scheduling And Recovery

Schema-bound runtime state is keyed by a computed SchemaFingerprint supplied by the committed schedule. Branch aggregate and Kafka offset state that do not depend on a schema identify that independence explicitly. No fingerprint byte pattern means “missing” or “independent”; a computed fingerprint is accepted for its identity even if its bytes happen to be zero. Scheduling must publish the required fingerprint before schema-bound state can be loaded or replicated. Missing required identity is an error, not a default digest.

The runtime Kafka offset key remains schema-independent. A backup archive also records the ingestor’s scheduled fingerprint with those offsets, so restore applies them only to the same ingestor contract after publishing its target schedule.

Kafka replica catch-up describes revision state as Current or Advanced(revision), with typed remote-operation failures for refusal. An advanced revision selects a bulk native checkpoint; its header must name a revision newer than the replica’s request and no earlier than the described revision. Length, digest and the current archived shape are verified before a replacement table is published through the retained replica assignment token. A cancelled or invalid transfer leaves the installed state intact. Every successful synchronization returns the held revision, including a Current answer, after validating replica authority. It is acknowledged again so lost progress reports recover without another transfer; a promoted or replaced assignment rejects reports through a retained token.

The runtime checks a stored state’s schema identity against the current scheduled identity before accepting it. WASM guest state additionally uses its generation for the concrete branch. A state from another schema or generation cannot become current merely because it has a later revision. This identity check is separate from the snapshot and handoff durability rules in WASM State And Recovery, Consensus Storage And Replication, and Shutdown And Recovery. Those chapters define when state is saved, transferred, and recovered; this chapter defines how the current state is identified.

Nervix keeps one current stored and wire shape. Producers and consumers of a changed identity are updated together. A previously stored shape that cannot supply required identity fails to load clearly and must be recreated; it is not defaulted into the current state. Tests construct the current shape and assert its behavior.

Archive Preparation Admission

Archive preparation reads the first physical tar header into the backup crate’s ManifestHeader. That type carries the regular manifest entry’s validated identity and bounded encoded length. Restore uses its length to admit manifest decoding before allocating owned archive values. The full archive reader uses the same boundary and then verifies the manifest and every section; see Backup And Restore.

Archived Counts

Native usize and NonZeroUsize counts use the vocabulary’s CountAsU64 archive adapter. Every count-bearing archived field selects it explicitly, so its stored width is 64 bits independently of the archive’s pointer width. Zero remains valid for an ordinary count; a nonzero count uses the archive’s validated NonZeroU64 representation. Encoding preserves every bit of a supported native count. Decoding converts once with usize::try_from and returns ArchivedCountError if the receiving target cannot represent the value. No narrowing cast, clamp, or default supplies a count.

This contract covers relay capacity, transaction positions and operation numbers, queue limits, application progress and outcomes, plan and report counts, topology counts, WASM inspection totals and omitted-entry counts, and histogram delayed-removal bucket indices. The owning stored namespaces and frame signatures identify the current count-bearing shape before decoding, and the interconnect’s wire fingerprint fences it between nodes. Unrecognized stored state fails clearly and must be recreated. Complete equality properties exercise the production representations at their range boundaries; see Property Testing And Fuzzing.

Atomic States On The Data Plane

An ACK root’s ownership handoff can be tracking a bounded number of active shares or be complete. REQUIRED WAIT can leave a tracking root temporarily idle without completing it. Attachments, wait releases, and final completion race, so the ACK owner stores the state in one atomic word and changes it with compare-and-swap transitions. A reserved word value is private to that owner; callers observe typed tracking, idle, and completion outcomes rather than doing arithmetic on the encoding. Completion cannot be reactivated. This preserves the contentionless ACK path and the root tracker’s accounting without adding a lock. The delivery and handoff boundaries themselves are described in Data-Plane Concurrency and Shutdown And Recovery. Execution Primitives owns which backend supplies the atomic; selecting a modeled atomic does not validate the owner’s encoding or prove its transitions without the corresponding production-owner check.

A source instance owns starting, ready and retired states in a private atomic byte. Its handle alone interprets starting=0, ready=1 and retired=2. Compare-and-swap permits readiness changes only before retirement; a retired source cannot become ready or change a replacement instance. This relaxed scalar publishes no payload or other location. Buffered message-error workers separately own Prepared, Running and Ended lifecycle states; a fallible binding prepares the bounded queue, and successful running publication starts its worker once. An ended worker is never restarted.

The domain clock’s atomic maximum has a different meaning. Its initial i64::MIN is the documented identity for a maximum computation, and zero elapsed time is the value of an elapsed duration clamped at its physical anchor. Neither encodes an absent clock. The Domain Clock chapter defines clock absence, installation states, authority fencing, and overflow handling.

An entity-gate operation owns pending, held, released and failed outcomes. A held operation has closed its admission scope and requested its force flush. Ownership capture also requires a freeze owned by that exact coordination identity. The exact operation’s drain-status query publishes it only after observing no affected admitted work or flush obligations. The operation’s registry guard keeps its hold alive through that observation and publication. Request cancellation leaves the receiver-owned engagement and its original lease intact; retries await the same operation and renew no lease. The preparation deadline separately bounds engagement, drain and capture.

A domain schedule’s planning snapshot keeps its captured consensus cordons with two distinct identity sets: all live voters and eligible placement destinations. Termination of an already cordoned voter leaves both sets unchanged; losing or restarting that voter changes its live identity and invalidates the plan. Schedule and transaction publication validate the composed destination set and retain the independent consensus topology fence. The snapshot also retains the terminating live voters independently for destination diagnostics. After membership and liveness, relocation reports that process state before a committed cordon. Its terminating set is a captured diagnostic fact, while publication continues to fence the composed destination identities; termination of an already cordoned former owner still changes no eligible destination.

External Encodings And Conversion Failure

The stopping-node drain action carries a required remaining Duration budget. Its sender deducts elapsed request time before each leader redirect; the receiving leader owns the typed budget for the handoffs it performs. Preparation and activation deadlines are derived from that one value, and exhaustion produces a failed drain outcome. The stopping-node answer distinguishes a failure while its coordinator still leads from an interrupted drain whose coordinator no longer leads. The latter routes the remaining moves through the next leader without resetting the budget or repeating committed moves. Classification consumes the typed command disposition and consensus leadership observation rather than matching diagnostic text. The interconnect verifies the archived action and fences its current representation with the wire fingerprint. Shutdown And Recovery owns the lifecycle and deadline policy.

At an external boundary, a protocol may require a raw tag, signature, null lane, or optional scalar. The adapter owns that encoding and turns it into a typed internal state. In the other direction it encodes the typed state once. A format signature or syslog boundary marker can remain raw on the wire, while callers see the state the format describes. Arrow batches remain the data-plane payload throughout this conversion; codecs use typed builders and column values, and a single addressed message is a view into a batch.

A relay batch carries its rows’ ingestion watermarks the same way, in two Arrow buffers of Unix-nanosecond timestamps beside the payload. A kernel reads them as i64 lanes; a row addressed on its own, the interconnect wire, and a materialized-state snapshot receive typed timestamps, converted once where the row leaves the batch.

A conversion failure never becomes another valid payload value. The MongoDB sink returns a typed per-record failure if a value cannot be represented in BSON, including an unsigned value above BSON’s signed range. It does not publish that record with a replacement BSON null or a changed conflict key. An actual null remains null, and other valid records in the batch can proceed under the connector’s record outcome contract. See Connector Crates And The Connector Contract for the host’s publish and acknowledgement boundaries.

VM integer count and position operands retain their signedness and full magnitude. A large unsigned input does not narrow to the largest signed integer; an unsupported result size reports a per-row error before allocating it. UUID-v7 construction reports an unsupported pre-epoch time as a row error rather than substituting the epoch. Exact schema types and Arrow validity still govern the rest of the expression. The public function results are documented in Expression Functions.

A submitted client batch is validated as a whole before any row is admitted: a stream that is not exactly one uncompressed record batch of the ingestor’s canonical Arrow schema, with valid columns and within the row and byte limits, is refused with its typed defect. No value is cast, widened, coerced, or defaulted to make a batch fit, and no subset of a malformed batch is admitted. The shared Arrow IPC boundary checks canonical message framing, declared bodies and column buffer ranges before invoking Arrow’s reader. A malformed frame reports ArrowBodyError::Framing for a relay or snapshot body and ClientBatchError::Malformed for a client batch; neither gains a partial row from it.

Session replies carry typed command purpose and outcomes. An upload failure can carry an optional assigned nonzero resource version; before assignment, the version is absent. Diagnostic spans can be absent, while a present span beginning at offset zero is still present. The web console uses the typed outcome for domain-selection dispatch instead of matching reply message text. The FlatBuffers encoding preserves these optional fields and typed variants across the session edge; Client Session Protocol defines how a receiver keeps an absent optional value distinct from a present zero.

The shared C binding gives clock observations their own nx_clock_event_kind and installations their own nx_clock_state. Only NX_CLOCK_PACED has a mapping for nx_clock_event_paced; tick and end-reason accessors likewise require their corresponding event kinds. An interruption or a refused restoration carries a domain but no invented generation or end reason. A mismatched accessor returns NX_ERROR_TYPE without changing its outputs, so absence cannot look like a zero generation or timestamp. The paced and tick accessors allow omitted output pointers for fields a host does not need.

The clock of a followed domain, nx_domain_clock, always has a generation and a state, so those accessors cannot fail. A domain the session does not follow reads as a NULL clock rather than a stopped one, a clock without an accepted tick answers false from nx_domain_clock_tick rather than a zero tick, and an unpaced clock reports no admission window rather than an unbounded one. Only a paced clock has a mapping for nx_domain_clock_paced, and a stopped or uninstalled clock has no logical time, so its projections return NX_ERROR_TYPE instead of a fabricated instant.

Completion replies likewise carry a SuggestionStatus variant for ready, missing, stale, or failed context and an optional continuation. The server resolves typed semantic references from one committed configuration read with the requesting session’s ordered transaction prefix applied; a missing or mismatched transaction binding reports stale context instead of silently discarding queued changes. Each candidate carries an explicit UTF-8 byte-range edit. The CLI and web console apply the edit after checking the cursor boundary, and the web console converts browser UTF-16 selection offsets at its edge. A continuation is bound to the input, domain, revision, and candidate set, so a changed context cannot silently reuse a page.

Structured-control lookups use a separate typed choice boundary. A request names its semantic target and carries each dependency as a ChoiceValue; a placement choice therefore depends on a domain-pace variant rather than on the text PACED. An internal-schema, branch, or relay choice depends on a typed domain reference and returns a kind-qualified Model reference, and a relay-field choice depends on the domain and relay references and returns a typed field reference. Results keep the same typed union for enum variants and domain, resource, model, or field references, with label, detail, and group held separately as presentation. The FlatBuffers discriminant selects behavior. A missing typed dependency is MissingContext, and a page cursor binds the dependencies, revision, candidate values, and presentation so changed form state is StaleContext rather than a silently retargeted page. The browser keeps missing prerequisites, stale context, empty results, loading, and failures as separate choice states. A missing prerequisite carries a hint; stale context offers a fresh lookup; only lookup and transport failures are alerts.

Incomplete schema, branch, relay, and subscription form values stay in browser drafts. The completed conversion creates the current schema, branch, or relay Model, with field order, optionality, sensitivity, wire format and mode intact, or the current subscription client statement. A relay draft’s branching starts unselected, a state distinct from unbranched execution, so a completed relay is never unbranched by omission; its materialized state is absent until LAST BY TIMESTAMP is chosen, because a relay without one is itself valid. A schema, branch, or relay selection retained after its captured domain changes is explicitly invalid until reselected; no empty name or fabricated Model stands for a missing selection.

Junction and reingestor drafts use the same boundary. A junction’s branch is unselected until the operator chooses unbranched execution or a named branch; a reingestor route separately chooses preserve, unbranched, or a named outgoing branch. A materialized dependency remains incomplete until its relay and absence policy are selected. Ordered input, dependency, assignment, and route drafts become the existing semantic Model only when every required choice and expression builds. Changing the captured domain or a dependent reference invalidates selected references while keeping the operator’s draft text visible for correction.

Diagnostic evidence states

The diagnostic owner distinguishes active cycles, potential order and overload. Potential records carry Unreviewed or Reviewed(TriageProof), with a bounded explicit basis, reason and retained regression reference. New source/lifetime context revokes a review. Live, Ended and Unrecorded lock instances preserve different observations; absent construction or acquisition context stays absent. Reused source sites never replace run-local instance identity.

ProcessRecord requires its compile-time/runtime diagnostic selection, and an artifact requires whole-process or selected scope. A selected export cannot qualify a source process whose other findings it omitted. The current version-2 wire conversion checks every required field, bound, identity and review once; unsupported versions fail from their header without another shape or a default. Data-Plane Concurrency owns the current representation, qualification policy and coverage limits.

Validation And Failure Boundaries

Native connection options validate every timeout at setup: one millisecond through 24 hours. The backup command wait has its own required duration, distinct from an optional per-domain quiesce override and the ordinary request and retry bounds. Backup execution identity projects the typed scope, resource inclusion and capture options together with the selected domain; the local output destination remains a client download concern. Recovery may change that destination while the server continues to validate the original semantic request and execution reference.

The registry rejects unresolved or contradictory contracts before a graph becomes active. It resolves branch names, schemas, fields, and sensitivity as one branch state. Scheduling supplies the required runtime-state identity. Runtime owners enforce transitions that depend on concurrent execution or recovery. Connectors and the session edge validate external representations when they decode or publish them. A caller does not compensate for a failed lookup, absent required field, type mismatch, or conversion by supplying a default zero, empty value, or null.

Generated compiler findings carry a required execution-context field. An explicit null means that analysis has not established a source contract; it is an unknown effect, not a cold classification. The report decoder requires that field even though its value is optional. Complete compiler, configuration and worktree identities are also required before generated evidence is reusable.

A vocabulary type that validates its value when it is parsed or constructed validates it again when it is decoded, from JSON and from the archive alike. Every name type, a command execution reference, a resource upload identity, a JSON path, connection-pool bounds, and an emitter’s message and size limits decode through the rule that constructs them, and accept only a value that rule produces unchanged. Stored or received data therefore cannot hold a name with an upper-case letter, a path past its step limit, a minimum above its maximum, or a size that is not a whole number of its unit; such data fails to decode with a typed error and is never normalized into a valid value. A timestamp is its signed Unix nanoseconds, and every conversion into one goes through them, so two spellings of one instant, such as an offset and its UTC equivalent, or a leap second and the second after it, are one timestamp. Every duration Nervix reads from text, whether an NSPL literal, a domain-clock period or skew, a Model’s timeout, interval, retention or TTL, a window aggregate’s delay, or a node’s command-line option, is read by one guarded parser in the vocabulary. It refuses text whose spans could add up to the most seconds a duration holds with a typed error; the grammar library it wraps would panic on such text instead of failing, and Clippy rejects every other way of reaching that library’s parser.

Archive validation establishes the archived structure, then each vocabulary value is checked when it is read back. A refusal in a list can therefore follow values that were already constructed. The archive reader owns each completed value and frees it on refusal, together with the incomplete list or fixed array and any box or shared pointer allocation. No decoded fragment crosses the storage or transport boundary, and a stored record of an invalid current shape still requires recreation.

The current archive readback inventory for containers with a semantic value that may refuse its archived representation is:

BoundaryFallible contents inside archived containers
InterconnectApplicationCompletionPeersResponse.peers; RelayMetadata.acks; PrepareOwnershipHandoffStateRequest.checkpoints; the relays and affected_entities of EntityGateRequest and EntityDrainStatusRequest; the emitter_publishing lists of DomainDrainStatusEnvelope and EntityDrainStatusEnvelope; DescribeRelayRequest.bindings; ownership handoff checkpoint responses. These contain typed node, relay, emitter, model, or domain names.
Consensus replication and persistenceAppendEntriesRecord.entries, including membership configurations and nodes; durable batches of Raft entries and consensus state; the Vec and Box descendants of ConsensusCommand, domain schedules, command execution, transaction plans and reports, and stored models. They contain typed names, references, limits, and operation ranges.
RegistryStored Model variants, including schema fields, nested ParseAsType boxes, processor routes and inputs, connector configuration, and recursive expression vectors and boxes. Their typed names and other checked vocabulary values may refuse after earlier members decode.
Runtime state identityStoredHandoffPreparation.checkpoints and StoredForcedRecoveryPreparation.checkpoints contain placement envelopes with checked domain and model names.
Runtime window snapshotWindowDelayedRemovalSection.removals contains CountAsU64 buckets. A stored count above usize::MAX is refused on a narrower host.

There is no archived shared pointer field at these Nervix boundaries today; names share an Arc only in memory, and archive as text. The shared pointer reader is covered by the same dependency fix and by a refusal test. The deduplicator, Kafka offset, materialized identity, branch LRU and other runtime state snapshot containers, together with backup sections and deadlock evidence, first deserialize primitive or raw string wire values, then validate their meaning after the complete wire value owns its allocations. Their malformed input tests still check that every archive decode frees its allocations.

Constant integer division prepares a SignedDivisor or UnsignedDivisor at the kernel boundary. Its unsigned magnitude is NonZeroU64, and its private reciprocal state distinguishes a power-of-two shift from a multiply-high reciprocal. A zero input produces no prepared divisor; the numeric kernel reports failed lanes with the existing failure mask. Datetime callers already hold validated positive strides, so they can assert that preparation succeeds. These per-call values are execution artifacts and are never persisted; VM Functions owns their arithmetic and failure contracts.

One in-memory domain activation plan resolves each relay’s compiled schema, branch retention and materialized-state presence; each codec’s schema and wire definition; and each endpoint’s VHOST and signaling reference. A missing reference is a typed planning failure before installation. The same plan shape feeds running and passive builds. Passive builds retain the planned materialized relay identities and endpoint routes, while admission remains stopped. A server-side listener stays bound on every live node independently of graph placement or domain leadership.

Materialized origination is an exclusive task capability: moving it transfers the mutable branch selections, while reads and snapshot installation remain independently retainable. Read publications carry an immutable row with its Arrow schema and watermarks. Branch membership and an ended row publication are distinct states; absence in live state owns the answer even when storage retains an earlier checkpoint. Recreating a branch allocates a fresh publication. Installation validates assignment capability, branch generation, captured fence and revision before replacing any row; the current branch lifecycle and revision cannot move backwards.

Server endpoint configuration and source availability are distinct states. The immutable route table contains configured definitions; a bound source lifetime contains an optional prepared intake. Source ending publishes absence through that lifetime before removing its route binding. A retained request or WebSocket cannot interpret absence as a replacement source with the same node identity. A lease loaded before ending may complete; later admission sees absence. Domain replacement and teardown end the domain’s lifetimes and replace all of its route definitions together, preserving other domains. Unbind names the exact binding allocation so a preceding source’s close cannot end its replacement.

A second in-memory decision, the domain’s entrypoint plans, resolves every ingestor’s source, client, codec and routes and every reingestor’s inputs, node filter and routes. It records how a route’s records get their branch key as one of three states: unbranched, keeping the incoming key, or constructing a new key with a lowered program. The two branched states carry the branch and the retention of the relay the route writes, so the branch a route declares and the branch its entrypoint retains are one value, and a route whose declaration disagrees with its relay fails planning. An ingestor’s transport class is read from the one source it declares rather than stored beside it. A Kafka ingestor’s offsets are either a consumer group or domain offsets together with their placement. The planner lowers every filter, route and branch construction before a node binds them, so a bound route always carries its compiled program and a running task has no missing-program or undeclared-branch state to check.

The owner reports a semantic typed error; contextual propagation uses error-stack. A per-record conversion error is reported at the record boundary without formatting a fresh message on every hot-path operation. Diagnostics contain the relevant identity, operation, and field names, while sensitive payload values stay out of errors and logs. A truly optional value continues as Option until its consumer decides whether absence is valid. A label or rendered string is only a presentation of the state and never an input to execution.

Replicated command admission distinguishes a reference that has expired from one bound to a different owner, domain, transaction position, or content in its typed conflict result. The session carries that distinction into the public command disposition; rendering its message does not choose the disposition.

Error-route branch validation carries the node, source route, error relay, and both branch declarations as typed data. Direct emitter VALUES validation identifies a sensitive external target by name and requires explicit leakage; neither error needs the source payload value.

Restore Installation Authority

RestoreLifecycle is a closed Stopped/Resume policy in the semantic restore Model. Text omitting RESUME selects Stopped at the language boundary. The restore plan carries distinct initial stopped state and activation state. Both require the archived start generation and latest start point; paced activation also requires the archived mapping. Required report and DomainInfo generation fields are validated at their wire boundary, including the valid generation zero. Materialized archive descriptors and row identities are archive-owned types. Their raw schema fingerprint binds once to the archived start generation for native storage, independently of the installation authority; payload values stay exact-schema Arrow columns. Typed branch identities, watermark ordering, counts and framing are validated before those values reach the runtime, and each record identity’s branch must be a key of the restored relay’s branching.

A captured archive section carries its publication key, content kind and staged artifact as named fields. Guest capture retains a selected checkpoint handle until its scheduled generation is checked; its admitted storage job records the size for later admission, and opening that handle returns the checkpoint revision with the reader for those exact bytes.

Deduplicator and window capture likewise distinguish a live publication from an unopened stored checkpoint in the captured-state union. A stored selection carries its immutable view and inspected size, and opening it returns its actual revision with an admitted immutable artifact. Only a validated keyspace or window reader exposes counts, boundaries or columns. The control plane selects the scheduled owner and schema before opening; it receives typed conversion results rather than native bytes. A window’s live and stored readers retain their own required lifetime and metadata.

A materialized capture carries either current rows or stored checkpoints as distinct variants. A captured materialized checkpoint is a selected immutable source. Opening it produces a reader whose complete header is required; there is no optional or defaulted generation metadata. Each bounded group retains its scalar identities and original Arrow bytes, and completion checks the whole declared group and row count. Running and paused domains capture current rows; stopped domains capture stored checkpoints. An empty generation still has its descriptor and zero group/row counts. RESTORE resets the stored ownership fence to zero explicitly.

A restored domain has a replicated Pending installation from creation and an Installing authority once its state generation is admitted. Neither state permits START. Completion of the exact current generation removes the installation; terminal command failure does not. Authority carries leader identity and term, execution reference, mutation lease revision and generation. Checkpoint revision remains guest history and cannot grant installation authority. Validation at the applied-state boundary holds its read guard across the storage mutation and handle clearing. The state store validates authority-bound receipts, checkpoint headers and ordered chunks before synchronizing the complete namespace. One small active-generation record then selects that set atomically and is synchronized before completion. It retains both authority and inventory for exact retry and stale-attempt rejection. Cancellation after selection preserves the closed start gate until the same authority completes durability and cleanup.

Runtime storage has distinct initial and restored namespaces; restore installation generation is separate from guest-state generation and checkpoint revision. A current checkpoint is either an inline checkpoint or a segmented checkpoint with required revision, length and digest. A read uses one database view for namespace selection and payload data. A queued checkpoint job retains its selected namespace and validates that it remains current before writing. The storage format marker is required for nonempty checkpoint storage; corruption or absence fails explicitly and requires recreation rather than inventing a namespace for the stored keys.

A branch-aggregate metric checkpoint revision identifies one exact encoded payload. Capture retains its elapsed fields once, so another descriptor, stream or persistence request cannot choose different bytes for that revision. Initial, replica and persisted recovery preserve the received bytes with their revision. A dirty metric update selects the next revision; a snapshot mutex serializes capture and installation at that placement’s cold boundary.

Active chunk maintenance validates the placement and fixed revision/offset coordinates before forming a chunk-set cursor. A set remains referenced only when the same view’s selected header is segmented and names that exact revision. A missing or inline header is an ordinary unreferenced outcome; malformed coordinates or a malformed bounded header remain typed storage failures. Segmented headers have only their fixed archived root, so a size check bounds the caller’s copy before decoding. The required current storage shape makes larger valid values inline; Fjall may still read/cache those values internally. No second persisted liveness field or default is added.

Restore reclamation receives a borrowed RestoreStateRetention from one locked applied revision. Absence of an applied log means catch-up is unknown and retains all generations. A generation ahead of that log is also retained. Once applied, only the exact generation of an applying restore requires unpublished storage; terminal, expired or absent execution records do not. Publication identity remains a separate node-store protection, and reclamation never converts an incomplete installation into a completed one. Key/value usage is reconstructed from current namespace keys, including partial chunks without a receipt, rather than a defaulted persisted counter. Namespace cursors use the vocabulary’s canonical decode entry point for the required domain name. It requires lowercase stored text and retains the typed NameError beneath the storage format failure.

Qualification Evidence

The integration harness’s startup owner classifies a failed attempt once into a terminal outcome or a transient retry carrying its listener family. A listener bind failure names the addresses to replace; a readiness timeout names all listeners. The launcher applies that decision after cleanup within the same absolute startup budget. See Integration Test Lifecycle for its occupied-listener regression and endpoint observation.

The typed states qualification ledger maps each confirmed finding to its owning change, current source path, unit test, public Cucumber scenario, and local validation command. It records the checks on the landed implementation rather than claiming a new behavior change in this documentation chapter.

The focused public selection passed 217 scenarios and 2,784 steps across branch and scope rules, materialized state, error routes, MongoDB emission, VM functions, clock boundaries, membership and recovery, session protocol, and the browser console. The applicable runtime scenarios include one-node and three-node examples; ownership and recovery scenarios use the production sticky scheduler. Owner tests passed 2,399 tests across Models, VM, consensus, interconnect, MongoDB, Client Wire, client core, browser, and server. just test-shuttle passed 70 distinct checks under two schedules for ACK and state-recovery concurrency. The same qualification passed just validate and just ratchet.

These results establish the listed semantic paths and their tested failure boundaries. The ledger distinguishes source-audited findings from demonstrated runtime behavior and records which values remain legitimate zeros, empty content, Arrow masked lanes, and private encodings.

Recurring Task Observations

The paced simulation applications represent endpoint-open intent as CurrentGeneration or FollowingStart. Only the latter permits a bounded retry of DomainStopped after observing a later paced generation; initial and contract-change opens retain the stopped-domain refusal. The opened producer’s generation and its paced clock still own permission to plan readings.

Healthy connector status is absence of a failure; a failure contains its safe error and an optional retry in one publication. Domain-clock publication carries lifecycle pause, generation and start point beside the installation. Entity assignment absence invalidates a retained checkpoint reader; a present assignment contains its state identity, optional primary, executors and replicas together. An absent primary represents an assignment without one primary owner. Replication routes retain that same slot and an optional state intake; ending an intake permanently fences its exact route before the routing publication withdraws it. Assignment absence and ended intake are distinct states: identity removal invalidates every reader, while state retirement may leave the entity’s assignment available for storage-backed synchronization. Force-flush readiness is privately encoded as idle=0, available=1 and closed=2. Only its owning type writes or decodes that byte; the coordinator remains the authority for generation and claim state. The hint has no cross-location data-publication contract.