Skip to main content

Transit native protocol v1

Transit v1 provides paged durable catalogs and state through bounded commands and queries. The node, shared client, Station and SDKs use this single definition. Growth.zig owns its types and transit-v1.schema.json is generated by the contract tasks. Their drift check compares the generated schema with the checked-in definition. The service contract owns HTTP framing and routes.

Representation and compatibility​

Every request/query carries version 1, the current contract definition and its realm. The generated schema's x-transit.definition owns that identifier. Signatures bind it; query responses and persisted authority heads require it. Missing or foreign persisted definitions reject before reading their catalogs. The definition is the exact identifier string; enum ordinals, numeric strings, all-zero fingerprints and JSON numbers are not alternate spellings. Principal, process, resource, view, receipt, output and effect identities use 64-bit fields, with the public numeric address space capped at 2^53−1. They are values, never resident array offsets. Commands cannot infer an identity from a catalog slot. Sequence zero is invalid for mutations; read queries use a separate signed type/domain.

Mutation signing hashes transit.request.v1 followed by a NUL and canonical typed JSON. Read signing uses transit.query.v1 followed by a NUL. Ed25519 signs that SHA-256 digest. Include defaults/nulls, retain declaration order and use compact UTF-8 JSON with decimal integers and single-key union objects. Opaque values use the existing owned lowercase-hex encoding. Validators reject unknown versions, oversized integers, malformed values, duplicate mutation keys and ambiguous key/ cursor queries before signing. Canonical logical requests are bounded at 16 KiB, including the immutable block descriptors. Fixed byte arrays remain JSON arrays regardless of whether their contents happen to be UTF-8. Large block bodies use a separate transport budget and are excluded from authority journal records.

Incompatible signatures, histories, checkpoints, cursors and saved operations reject; no fallback decoder, alternate route or automatic migration exists. The versioning policy requires matching builds and preservation of original recovery material across a hard cutover.

Current identity observation​

The declarative_authorization capability exposes the shared role, credential and grant model. Its signed authorization command/query variants provide revision-checked administration, current decisions and scoped inspection. Credential and privilege records are separate; native permission masks are derived from current graph grants.

The identity read returns the authenticated principal, current coarse permission bits, optional PID scope and policy revision, at the enclosing response's authority position. It requires current inspect permission and uses the normal v1 signed-query domain. It exposes no signing key or resource grant and does not authorize a later operation by itself.

Inspection clients can require exactly read-only permissions, then request bounded catalog pages at that same position. A grant change expires that cut; clients must not join the old identity observation to a newer page. Current resource grants continue to filter resource discovery independently. Grant expansion and revocation invalidate existing cuts; stale cuts fail explicitly. Board uses real signed HTTP for these observations; its scoped inspection profile does not acquire mutation authority.

Bounded operations over growing collections​

A turn proposes up to four small metadata mutations and sixteen immutable block mutations in one writable associated resource, four view identities and four outputs, with optional captured effect intent. The block batch contains at most 128 KiB, with at most 64 KiB per block. The block contract defines checksums, ownership, source-qualified reads and publication semantics. Keys and association names are 1–32 bytes; individual values retain their 256-byte bound. These are per-operation bounds, not limits on resource rows, processes, principals, retained calls or receipts. Large logical results require explicit segments and complete-result evidence above these bounded records.

Capabilities must report the configured required-resource and lifetime-owner graph validation budgets. This profile requires quiescence of an owner and its borrowers before changing that owner's required dependency topology; it rejects changes that could invalidate an existing borrower's admitted work budget. These are explicit operation/admission constraints, not limits on total realm catalogs. The core guide describes the current defaults and restrictions.

Entry reads select exactly one basis: a caller-owned durable view ID, or a resource ID with an explicit current revision. The authority owns the root corresponding to a view; clients never supply roots. Each view read rechecks current grants, activation, dependencies and view lifetime. Current-resource reads recheck grants, scope and lifetime and reject a changed resource revision. They do not pin old state. Direct key lookup and an exclusive key continuation are mutually exclusive.

With retained_read_versions, a turn can atomically retain committed source views for later inputs and replacement activations. The turn_with_versions contract supplies bounded, currently authorized historical reads. Retaining a version does not extend owner/source expiry or grant access.

Pages contain at most eight records. A non-null cursor permits another read; only a null cursor establishes completion. Catalog continuations require the first response's authority position; any change expires that cut rather than mixing revisions. Association listing uses revision IDs as cursors so filtering cannot disclose hidden names in a continuation. Filtered pages may be empty with a non-null cursor. Resource and association metadata require resource inspection rights; reading values additionally requires read rights. A retained root/view is never a bearer capability. Each successful response validates that its authority tail still matches the policy/read basis before disclosure. The response may arrive after a later revocation; it grants no subsequent read authority.

With the association_lookup capability, a query can resolve one association by PID and exact name without a catalog continuation. It enforces current PID scope and target inspection rights, returning null for either absence or a hidden target. It uses the same final authority-tail fence as paged discovery. The client validates the returned PID, name, resource and association revision.

With resource_read_access, the read_access: resource_id query returns current active resource metadata only after checking both inspect and read resource rights, the caller's current native identity/PID association scope, and resource/dependency lifetime. It uses the normal signed-query domain and final authority-tail fence. It neither reads entries nor retains a version. The signature may be retained and resubmitted as evidence of the caller's current read authority; every submission rechecks current keys and grants. Revoking read denies this query even when resource metadata remains readable. It grants no authority to a later read or mutation. Clients must require the capability and reject a peer that does not supply it.

With resource_read_batch, read_entries acquires one to eight distinct keys from one resource in a single authorized observation. Its fixed eight-slot keys array is a nonempty contiguous prefix followed by nulls. The response contains active resource metadata and eight corresponding optional entries; null at a requested slot means that key was absent at the returned revision. Unrequested slots are null. Input order is preserved, without sorting or a continuation. Optional revision requires that exact current revision; null selects the current cut. This does not retain a version or permit stale reads. An optional view selects an existing captured owner view while resource and optional revision bind its exact resource. The response includes that view. This path checks current process scope, executable ownership, generation, resource authorization and view lifetime before reading and again before returning. Keys are evaluated together at the captured catalog root; current resource revisions do not replace the captured cut. A null view selects current resource reads and returns a null view. Neither form grants or retains authority.

The query uses the existing signed-query domain, native PID association scope, current resource inspect/read permissions, dependency/lifetime checks and final authority-tail fence. Its memory and read work use the existing eight-entry page budget; mutation limits are unchanged. Clients validate slot/key identity, entry revisions and active resource metadata. They require the capability and reject a peer that does not supply it. Acquired bytes are one observation, not an authorization cache for later disclosure.

Process lists expose recorded metadata. An individual process read checks current execution eligibility before releasing its next mailbox input. Required dependency expiry may fence execution before background work materializes terminal metadata; these two observations must not be presented as equivalent readiness claims.

With leased_snapshots, open_snapshot, snapshot_entries and close_snapshot provide bounded, volatile read snapshots independently of worker ownership and durable retained versions. Current authorization still gates every read. The interactive query contract specifies tokens, leases, admission quotas, restart and cancellation semantics.

With scoped_retry, a current PID-scoped administrator can retry a blocked input using retry: {pid, expected_generation, failure_input}. Process.failure identifies the failed input in this profile; the generation distinguishes repeated failed attempts at that same input. Retry clears the block, advances the generation and removes ownership without consuming input or publishing application state. It rechecks current work lifetime and required dependencies, cannot revive a retired process, and does not authorize execution. Fresh ownership is a separate operation. Permission, generation or failure-identity mismatches reject atomically. Current inspection may disclose blocked process metadata with input: null; that observation grants no permission to execute the retained head input. A blocked handler does not close its mailbox: current send permission, work lifetime and required state still govern admission behind the failed head. Retry cannot move those later messages ahead of it.

Framework code should read individual keys or bounded batches through this interface, retaining private mutations for one final authority decision. It must not fetch the entire resource as a prerequisite to invoking a handler. Query computation remains in the caller. The kernel validates dependencies and effects; it does not execute application computations.

Integration obligations​

Finite deployments may configure a journal admission ceiling and a separate control-reserve band in genesis. These fields are exposed in signed capabilities; they are independent of row cardinality, retention and resident pages. At the ceiling new obligations fail with AdmissionClosed; at the end of the reserve new control mutations also fail with ControlCapacity. Exact accepted retries and currently authorized reads remain available. Neither trim nor restart resets this accounting. The authority guide defines allowed reserve operations, capacity limits and failure behavior.

Delivery resolves one retained output under current courier authority. Pending route order is per source/destination pair; a later output cannot bypass an unresolved predecessor. Admission or terminal disposition releases that route. Process termination/known expiry immediately fences unattempted work; individual outbox/effect metadata may await bounded disposition. cancel_effect is an administrative operation restricted to an unattempted intent of a terminal caller. It cannot cancel an authorized attempt or claim that external work stopped.

Authorized effects retain their executor, attempt, observation budget and optional deadline independently of caller retirement. Finite callers require a finite reconciliation deadline. The executor's current effect permission is required for new observations; an administrator with effect permission can close an orphaned attempt. A result after caller retirement remains evidence and cannot revive that PID. The native effect record retains the authorization grant revision, the last observation's input and grant revision, and terminal closure provenance. Closure distinguishes observed, observation_budget, abandoned, deadline and unattempted_cancel; it records the resolving principal and grant revision. Deadline closure additionally retains the trusted sample's lower bound, which must meet the original reconciliation deadline. These fields are committed with the phase and closure position. Reads reject inconsistent phase/observation/closure combinations. Current policy changes, exact retries and checkpoint recovery do not replace the original evidence. Opaque result bytes remain connector-owned. Closed attempts reject new results; exact historical retries still require current permission. The growing engine currently enforces these rules internally; the explicit HTTP profile exposes them. A separate node maintenance process materializes terminal dispositions with bounded scans. Maintenance latency depends on scan budgets and catalog size; there is no fixed lag bound. See deployment for runtime requirements.

The immutable catalog is the storage basis. One conditional journal decision must publish state roots, mailbox progress, outputs, principal sequence and retry evidence together. Staging does not accept work. Recovery must consume published roots without dispatching effects or executing handlers. Unlimited retention requires growing durable receipt, wait and result history; cache eviction cannot authorize deletion.

The checkpoint command requires explicit realm/application allow_history_trim genesis opt-in; unlimited journal history remains the default. Capabilities distinguish support for root-history reclamation from the selected retained-history policy. The checkpoint publication records a monotonic floor that retains its own complete root-bearing journal entry. Trusted maintenance verifies committed intent and root snapshot before advancing that floor. It does not delete catalog pages, receipts, accepted inputs, values or captured roots. Checkpointing does not expose a public history query. Physical segment collection uses the separate storage fence and ownership traversal described below.

Conditional local worker replacement​

create_principal and capability-gated rotate_worker both require root authorization. create_principal takes the existing Grant fields but refuses any previously allocated subject, including a revoked one. Exact retries retain their original receipt; a fresh operation cannot overwrite another installation's identity.

rotate_worker requires an executable PID, its exact prior generation and a PID-scoped worker with the expected current public key and permission mask. The worker must retain inspect/execute rights. One native decision replaces its key, advances ownership and records its policy revision. Its signed sequence and private role remain unchanged, while its credential epoch advances: rotation cannot renew a removed resource permission. It rejects an unchanged key, revoked worker, foreign scope, stale generation, blocked process or permanent retirement. A revocation racing prepared activation fences its conditional journal append.

This operation preserves PID, resources, mailbox, state, permit and outputs; it is eligible for the existing finite control reserve. It neither launches a worker nor declares application compatibility. The local manager attributes bootstrap evidence and checks artifact/configuration compatibility separately. Ordinary direct-native grant replacement retires the previous private role and binds a new one, invalidating its old resource rights. Named logical roles use the explicit credential-binding and rotation operations instead.

Capabilities report runtime bindings, resource and retained-read support, configured dependency budgets and history-reclamation policy. Only genesis opt-in allows a public checkpoint. A trusted --maintain process authenticates current realm-wide control authority, verifies committed intent and performs physical journal trimming. Its interval cannot authorize retention by itself. The station capability identifies support for the native ownership, resource and retained-read operations used by Station. Station runs above native authority; the kernel does not execute or validate application handlers.

Runtime binding and readiness​

runtime_intent, runtime_observe, runtime_upgrade and activate bind physical placement to a recorded process operation, revision and provider incarnation. Resource names remain permanently reserved after retirement. Activation fences stale observations, replaces the scoped worker key while preserving its signed sequence/resource-grant epoch, and records the current generation. A bound PID cannot use direct own or rotate_worker. The runtime contract owns provider attribution.

create declares up to four required association names and starts uninitialized. initialize validates those resources and fences the generation before execution. suspend records a finite resume deadline and revokes execution; resume requires that generation, current dependencies and a stopped provider binding. Expired suspensions retire permanently and account for unconsumed input as cancelled. A failed turn fences the owner and activation while preserving its pending input. An explicit retry validates the recorded failure and current dependencies.

Payloads and working-catalog collection​

declare_payload records an immutable digest, byte length and publisher. Values are limited to 64 KiB and finite process lifetimes reject standalone payloads. Only that publisher can record payload_ready. Deletion requires creation-time allow_delete, process retirement, retire_payload and confirmed payload_deleted evidence. Physical I/O belongs to the backend payload store.

spawn.allow_collection or create.process.allow_collection opts into working catalog collection before admission; the default is false. collect identifies one process and an output, effect, payload, resource or process record. Pending outputs, unresolved effects and payloads without confirmed deletion reject. Delivered inputs own their values and origins, so collecting an output cannot erase an accepted destination message.

Resources must be retired. Live views, retained read versions and associations from running consumers block removal. Cleanup detaches retired associations and removes at most eight entries or grants in one command. Process collection requires permanent retirement, a stopped provider operation, resolved related work and removed owned/written resources. It closes unusable views, releases retired caller versions and removes mailbox pages before leaving a permanent identity tombstone. Maintenance rotates bounded scans and rechecks every gate through a signed command. Restart resumes from committed catalog state.

Collection does not delete journal receipts or immutable storage pages, and cannot recycle a PID or provider reservation. History trimming remains an independent genesis opt-in. Neither capacity pressure nor storage failure grants retention permission.

HTTP boundary​

POST /v1/command accepts SignedRequest and returns the shared positive-position Receipt. POST /v1/query accepts the separately signed SignedQuery and returns Response. Generated route/type metadata owns both. Requests remain bounded by the service body/deadline limits, and no legacy-route fallback occurs. Typed rejection responses distinguish conflict, denial, invalid proposals and uncertain service/clock failures. Transport loss, malformed success and response allocation failure after acceptance cannot authorize a new mutation sequence.

Both signed envelopes require the body's explicit current definition field. Decoding rejects a missing or foreign definition before authentication or execution; it never fills one from the current build. This also applies to signed envelopes nested in saved caller artifacts. The construction defaults on unsigned authoring types apply only before signing a new request.

The growing listener uses the bounded HTTP serving profile with sequential connection reuse. A client can send X-Transit-Control: snapshot for close_snapshot or snapshot_read with finish: true to use reserved control admission. Other query kinds with that hint reject as InvalidRequest; unknown values and duplicate hint headers reject. The hint is unsigned scheduling metadata, never permission or evidence that release succeeded. Signed checks and uncertain transport outcomes are unchanged.

Client response validation checks version/realm, query variant, requested IDs, resource/view revision basis, safe integer range, dense ordered pages and advancing continuations. Empty filtered catalog pages can legitimately advance. Output IDs have their own sequence and are not journal coordinates. These checks reject a malformed response; they do not replace an authenticated deployment boundary or prove that a compromised authority reports truthful application data.

The snapshot_read capability combines bounded captured data and current metadata with snapshot acquisition or final validation/release. Its range budget is independent of the ordinary eight-record page and mutation budgets. See combined snapshot reads for exact bounds, separate source/current bases and final authority validation.

Physical storage maintenance​

storage_fence requires current realm-wide administrative authority and trusted time. It advances the stored storage epoch in one normal signed acceptance. Prepared candidates use the observed epoch and position; an intervening fence makes their original publication fail. A later fence can record elapsed read lease grace before physical deletion. Neither operation changes retention.

storage_compact requires current realm-wide administrative authority. One acceptance relocates one block or one catalog/policy leaf and path, advancing the head's durable compaction cursor. It preserves logical values, resource revisions and retained read versions. It consumes ordinary physical allocation capacity. Old accepted roots retain their original placement until independently released.

Stored heads require the current definition, storage epoch and compaction cursor. Page/block locations have one current 32-byte opaque definition. There is no preceding-format decoder or implied epoch for an old stored head. Configuration, provider placement and maintenance ledgers never authorize execution or expiry.