Canonical, provider-neutral wire protocol for Ota crossing authority.
This crate publishes the versioned message model, framing rules, semantic identity helpers, and conformance vectors used by Ota Core, trusted launchers, and independently operated authority brokers. Cross-repository conformance becomes established only when those consumers pin and test the same immutable crate revision.
This repository owns:
- protocol version and message-kind constants;
- exact serialized request, attestation, decision, lease, and consumption types;
- additive runtime-boundary attestation v2 types and canonical protected-launcher profiles;
- immutable principal-mapping, Ota process-posture, and systemd launcher-profile records used by the production protected-launcher adapter;
- immutable systemd Launcher V3 and V4 profiles, where V4 retains the V3 procfs restriction and adds exact named listener and manager-opened read-only boot-ID descriptor roles;
- an additive protected-launcher capability record binding one exact request, launcher installation, root service, systemd/cgroup invocation, unprivileged Ota subject, and the closed retained-descriptor set without carrying paths, file content, tokens, or provider responses;
- closed administrator-authority, protected Launcher/Ota implementation-subject, and authority- context records, including a 256-bit administrator-generated authority-instance identifier, plus domain-separated invocation-nonce and non-nil canonical Linux boot identities for a future installer-owned capability context;
- closed challenge, public capability-observation projection, and administrator-installed verifier records that bind one fresh workflow invocation without publishing the raw protected-capability identity or its transitive private correlation inputs;
- a closed protected Launcher-to-Attestor signing envelope that binds the exact private capability, public payload, producer binding, verifier, and projection identity while returning only the signed public projection, with cross-record reconciliation against the retained request;
- a closed same-execution secret-delivery transaction-binding exchange. Core sends the exact Launcher request identity retained in its startup continuation, not caller-reconstructed request content. Protocol reconciles that request to the retained continuation before protected derivation, signing, or replay mutation. Launcher then privately reconciles capability evidence before returning the private binding and signed public projection; Core separately reconciles that response against its retained request and independently loaded verifier and installation identities before signature policy;
- a closed private protected-authority snapshot challenge, request, payload, and response, plus an additive snapshot-bound V2 transaction-binding exchange. The snapshot binds exact selected-child request/startup/session, protected store descriptor metadata and bytes, and the current signed verifier/bundle state; Core treats transferred bytes as untrusted semantic input and must independently reconstruct its selected Step 1-6 truth. V1 remains immutable. Protocol neither opens stores nor verifies their live provenance, reserves replay state, parses provider bindings, contacts a provider, or activates delivery or execution;
- an additive snapshot-bound V3 transaction-binding exchange that preserves V2 unchanged and binds one exact transport-dependency-record identity into both the request and private binding. Protocol validates only that closed identity relationship. Core retains ownership of the complete expected dependency graph and record, Cargo resolution, semantic comparison, and candidate derivation; the V3 exchange grants no installation authority and opens no transport or provider path;
- additive V2 protected-authority snapshot records that retain descriptor-bound verifier and binding stores only as canonical raw bytes, avoiding V1's duplicate parsed carriers while retaining the fixed one-frame bound. Protocol structurally decodes and reconciles those records only; it does not verify the bundle signature, load stores, compare administrator dependency expectations, or authorize a V4 transaction, network request, provider operation, delivery, or execution;
- additive V4 transaction-binding records that require the exact V2 snapshot identity, schema, and kind across request, private binding, and response, while retaining V3's same-child and transport-dependency reconciliation. These are structural records; Launcher and Core still own their respective authority, signature, candidate, and one-use runtime checks;
- closed protected secret-delivery verifier-store and binding-bundle records. The store admits exactly one verifier and pins exactly one current signed bundle generation; the bundle binds an opaque, bounded payload identity and domain-separated Ed25519 signature envelope without making provider bindings, paths, or secret material public;
- the bounded Linux systemd-launcher client/service request, output, and terminal frames;
- bounded four-byte big-endian framing;
- JCS plus SHA-256 message identities; and
- compatibility and adversarial conformance tests.
It defines canonical projection and binding-bundle signature bytes but does not own repository contracts, semantic-scope derivation, admission policy, signing keys, challenge replay persistence, signature verification policy, protected-store loading, approval workflows, broker persistence, transport credentials, execution, receipt creation, protected archive storage, or semantic archive verification. Those remain with Ota Core, the authority launcher, and the chosen broker implementation. A structurally valid public projection is neither authority nor evidence of provider contact, delivery, execution approval, or cleanup. The authority-context records are canonical structural truth only: Protocol does not install them, establish filesystem ownership, observe procfs, generate runtime nonces, or reconcile installed executables. A structurally valid binding bundle is likewise not provider authority and does not establish cryptographic verification, current protected-store bytes, replay state, provider contact, delivery, execution approval, receipt, or assurance.
sequenceDiagram
autonumber
participant Core as Ota Core
participant Launcher as Trusted launcher
participant Attestor as Protected attestation producer
participant Broker as Authority broker
Core->>Core: Freeze contract, semantic scope, work unit, and nonce commitment
Core->>Launcher: challenge_request
Launcher->>Attestor: Submit challenge-bound observed claims
Attestor-->>Launcher: attestation_response (signed)
Launcher-->>Core: Relay signed attestation
Core->>Core: Verify challenge, scope, work unit, origin, and freshness
Core->>Launcher: authorization_request
Launcher->>Broker: Relay exact-scope request
Broker-->>Launcher: authorization_decision (signed)
Launcher-->>Core: Relay signed decision
Core-->>Launcher: authorization_decision_admission (identity-bound acknowledgement)
alt Authorization is allowed
Broker-->>Launcher: lease_issuance (signed)
Launcher-->>Core: Relay signed one-use lease
Core->>Core: Create pending crossing transaction
Core->>Launcher: lease_consume
Launcher->>Broker: Atomically validate and consume lease
Broker-->>Launcher: lease_consume_response (signed)
Launcher-->>Core: Relay transaction-bound consumption result
alt Lease is verified as consumed
Core->>Core: Execute only the exact authorized work unit
Core->>Core: Finalize crossing transaction and receipt
Core->>Launcher: execution_completion
Launcher->>Launcher: Persist exact completion before child exit
Launcher-->>Core: execution_completion_persistence
Core-->>Launcher: Exit after receipt/archive work
Launcher->>Launcher: Reap child and remove exact scope/cgroup/active slot
Launcher-->>Core: Terminal finalization is emitted to the outer client
else Consumption is refused or ambiguous
Core->>Core: Refuse before governed execution
end
else Authorization is denied, stale, or ambiguous
Core->>Core: Refuse before governed execution
end
opt Consume acknowledgement is uncertain
Core->>Launcher: Fresh challenge_request
Launcher-->>Core: Fresh attestation_response (signed)
Core->>Launcher: lease_consumption_query
Launcher->>Broker: Query exact prior consume request
Broker-->>Launcher: lease_consumption_status (signed)
Launcher-->>Core: Relay status and original signed consume response when consumed
Core->>Core: Finalize old work unit as incomplete and never resume its execution
end
The seven authority-exchange messages, in order, are challenge_request, attestation_response,
authorization_request, authorization_decision, lease_issuance, lease_consume, and
lease_consume_response. The protected local launcher session additionally carries
authorization_decision_admission: a Core-authored acknowledgement that binds the exact verified
signed decision before the launcher journals relay evidence. It is integrity evidence, not a
second authority decision and not a lease. Recovery adds lease_consumption_query and
lease_consumption_status. Ota may execute the governed work unit only after it verifies a signed
lease_consume_response bound to the pending crossing transaction. Recovery never resumes that
old work unit: it reconciles the broker result, finalizes the abandoned local transaction as
incomplete, and requires a new authorization for any later execution.
sequenceDiagram
autonumber
participant Operator as Installed non-root client
participant History as Protected history service
participant Store as Launcher-owned catalog
participant Core as Ota Core verifier
Operator->>History: Nonce-bound query with optional archive identity
History->>History: Verify pidfd, executable, process posture, and repository mapping
History->>Store: Freeze ordered catalog snapshot
Store-->>History: Archive, immutable contract snapshot, and signed sidecar
History-->>Operator: Manifest with operator, repository, and catalog identities
loop Each selected catalog entry
History-->>Operator: Entry and three ordered content-addressed objects
History-->>Operator: Bounded identity-checked chunks
end
History->>History: Reverify the complete operator session
History-->>Operator: Completed manifest terminal
Operator->>Core: Exact reconstructed objects and protected selection evidence
Core->>Core: Re-derive contract, scope, authority, transaction, cleanup, and archive truth
The first protected-history profile is one complete bounded snapshot with no pagination. A pre-query refusal carries no invented query or manifest identity; a valid-query refusal carries no manifest identity; a successful terminal requires the exact query and manifest identities. Object identities derive from manifest, entry ordinal, catalog, kind, content identity, length, and chunk count before the entry binds the three object identities, avoiding a circular hash dependency. Repository and protected storage paths never cross this wire boundary.
For the protected systemd carrier, selected execution adds two private Core-to-launcher messages.
launcher_execution_completion binds the terminal crossing transaction, receipt posture, exact
work unit, and consumed-lease admission. The launcher durably journals that record before replying
with launcher_execution_completion_persistence. After Core exits, the launcher reaps the exact
child, removes the exact scope and cgroup, removes the active slot, and emits one
LauncherExecutionFinalizationV1 inside the outer terminal frame. Completion is not cleanup
evidence. A live finalization is valid only when all four removal checks are true and the launcher-
observed child exit matches Core's completion. Schema v2 can instead record
recovered_absent_completion_bound after a launcher restart: it binds verified child absence to
Core's durable completion while explicitly carrying no observed exit code and no child-reaped
claim. Selected execution additionally uses an identity-bound terminal
persistence acknowledgement; the launcher must retain and replay the exact terminal until that
acknowledgement is received.
The original LauncherAttestationPayload and v1 response domain remain immutable. They prove a
fresh launcher session bound to the challenge, work unit, and semantic scope, but they do not prove
strong runtime separation.
The additive LauncherAttestationPayloadV2 uses the distinct
ota-crossing-broker/attestation-response/v2 response domain and
ota.crossing-broker.attestation.v2\0 identity domain. It carries one signed runtime-boundary
record with a stable profile ID, content-addressed profile identity, protected-launcher attestor
identity, launcher-session binding, and an ordered closed set of observations.
This crate publishes two canonical profile definitions:
ota.runtime-boundary.protected-launcher/v1requires eleven launcher and runtime-separation observations.ota.runtime-boundary.protected-launcher-image/v1adds bound runner-image and hardening-profile identities.
Every required observation must be represented with its profile-defined evidence method. The profile also requires bounded semantic identities for launcher binary/config measurements and, for the image profile, image/hardening-profile measurements; it forbids arbitrary identities on the remaining observations. Core, not this wire crate, owns trust-root selection, signature verification, refusal semantics, and archive reconciliation. Provider attestation is not part of these profiles.
The distinct LauncherAttestationPayloadV3 uses
ota-crossing-broker/attestation-response/v3 only for
systemd_protected_launcher/v1. It carries a complete, content-addressed
SystemdProtectedLauncherInstanceEvidenceV2; its identity helper refuses a missing,
substituted, incomplete, or non-verified instance. V3 does not reinterpret v1 or v2 archives.
V3 production signing uses two additional launcher-to-producer envelopes. The launcher derives
LauncherAttestationClaimsV3 from the frozen challenge and complete observed instance, then binds
those JCS-normalized claims under
ota.authority-launcher.attestation-claims.v3\0 in one
LauncherAttestationSigningRequestV1. The producer returns one
LauncherAttestationSigningResponseV1 that binds the exact request, claims identity, and signed V3
attestation. Projecting the signed response back to launcher claims removes only producer-owned
freshness and signature-wrapper fields. These protocol records neither authenticate the launcher
peer nor own signing-key, clock, replay-state, or transport policy; the protected producer must
enforce those runtime boundaries. The protected producer binding carries the public verification
key and its identity, key interval, and both producer and verifier maximum-age bounds so launcher
and producer independently derive the same narrowest validity window without exposing signing
credentials.
Every JSON payload is carried in one frame: a four-byte unsigned big-endian payload length followed by at most 64 KiB of UTF-8 JSON. Signed-message and identity domains are fixed protocol constants; this crate canonicalizes bytes and publishes profile identities but does not select trust roots.
The implemented systemd_protected_launcher/v1 adapter keeps broker semantics unchanged. This
crate publishes only the immutable records that Core and the launcher must agree on before that
adapter can execute:
LauncherPrincipalMappingV1binds one protected job-peer identity to one distinct execution identity plus the fixed job-principal profile and launcher-session binding. Its identity is used as the existing brokerrunner_principal, so authorization covers the complete mapping rather than one caller label. The outer instance evidence separately binds the launcher profile.OtaProcessPostureV1is an adapter-local pre-authority record for measuredno_new_privs, non-dumpable, and ptracer-clear posture. A launcher must corroborate it; the Ota-authored record is never sufficient authority by itself.SystemdProtectedLauncherInstanceEvidenceV1carries the immutable mapping, process posture, fixed profile identities, and bounded invocation identities. The additiveSystemdProtectedLauncherInstanceEvidenceV2binds that V1 record to the complete ordered launcher and job-principal observation sets. Its identity derivation rejects missing, reordered, failed, substituted, or unrecognized observations before an attestation can claim the closed profile.ota.authority-launcher.systemd/v1fixes the ordered service/socket hardening semantics and evidence sources for the legacy launcher-owned attestor credential posture. Its profile identity issha256:32c49f19799e065d341c900a4ce0d7756669c0c0d4e990ffe81bbcda06291930.ota.authority-launcher.systemd/v2preserves those evidence sources while moving signing credentials exclusively into the separately protected producer service. The launcher binds only producer socket metadata and the public verifier set. Its profile identity issha256:c816a49e01120bf1f793aedcfec094ca0f23a8ee80f1c7e5bed4c2d9c797cb42.ota.authority-launcher.systemd/v3preserves the separated producer boundary, adds boundedCAP_SYS_PTRACEfor protected job and stopped-child inspection, and grants only ambientCAP_SETUIDfor the launcher's verified transition to the non-root target principal. That transition clears the ambient capability before selected code can execute. The profile also makes effective systemd runtime configuration read-only inside the launcher boundary and replaces/proc/net/unixpath observation with protected socket metadata and descriptor identity. Its profile identity issha256:1d0ef44c24b6ec21dc0c462edd52c5197ae35a4a1728a98cd93b92d6f106dfaf.ota.authority-launcher.systemd/v4preserves V3's procfs restrictions and adds exactly one manager-opened read-only boot-ID descriptor plus one canonical launcher-listener descriptor name. Its profile identity issha256:bdac5f965aa56d44de8581e194ac0364b2d4c98183fff0cbb223574fd78197a8.ota.authority-job-principal.systemd/v1fixes the ordered job-peer, execution-principal, privilege, process-containment, and process-inspection requirements. Its profile identity issha256:e69ef375070bbb4f5616ba46b6f29b9a987372909016d1a1dfa40a5d4daae93d.ota.authority-job-principal.systemd/v2permits only the protected primary GID when systemd represents that GID in the kernel supplementary-group vector. Every additional group remains a refusal, and V1 retains its original archive meaning. Its profile identity issha256:ee6ea951aff4a80f8a4f93c576a93e3b29245b87d162726c2401c124a7a78659.
These definitions do not implement systemd, inspect a host, hold an attestor key, or create a provider claim. Core and authority-launcher must pin the same immutable protocol revision and independently verify their respective boundaries before the adapter can be enabled.
ProtectedLauncherCapabilityV1 is an additive protocol foundation for that independent
verification. It canonicalizes exactly one launcher-session socket, verifier store, binding store,
and invocation-cgroup descriptor; binds each store to a role-specific protected content identity;
and derives the cgroup identity from the exact retained descriptor and systemd scope. It is not
authority, does not prove that the descriptors were securely opened, and does not activate OIDC,
provider contact, secret delivery, or execution. This protocol revision includes a semantic
reconciliation API over independently observed launcher records and store bytes. No released or
current authority-launcher emits the record, and no released or current Core/runtime consumes it.
Those implementations and their hosted proof remain separate subsequent work.
ota-authority-launcher/systemd/v1 adds the local client/service envelope for the Linux-only
adapter. A client sends one launcher_invocation_request containing only an authority label,
bounded Ota arguments, and an absolute logical repository path. It is an untrusted proposal, not
authority: the root-owned service derives the Unix peer, chooses the configured mapping, and mints
the invocation identity. After exact process-posture admission, an identity-bound
launcher_startup_continuation binds the exact invocation, child, working directory, process
posture, and principal mapping while unlocking CLI parsing only; it is not crossing authority. The
service returns ordered binary-safe launcher_output frames followed by exactly one
launcher_terminal frame. New V1 terminals may add a typed stage that distinguishes refusal before
boundary creation, posture admission followed by exact boundary removal, authority refusal
followed by exact boundary removal, pre-authorization protocol refusal followed by exact boundary
removal, V3 attestation admission before authorization followed by exact boundary removal,
selected execution completion/failure/interruption followed by exact boundary removal, and
boundary failure. Selected-execution terminals require an identity-bound finalization record;
refusal terminals cannot carry one. The field is additive so legacy V1 terminals remain readable;
consumers must require the specific stage needed for any stronger proof claim rather than
inferring it from an exit code.
The protocol also publishes content-addressed identities for that exact request, the retained working-directory device/inode, the stopped fixed-binary child, and its exact non-delegated transient systemd scope. Those identities let the launcher durably reconcile preparation and cleanup without treating a PID, path string, or caller request as authority. They do not represent systemd-scope admission, execution, or broker authorization.
The envelope carries no broker credential, caller identity assertion, semantic scope, or grant. Core and the launcher establish those values through the protected session and signed broker protocol after the service has admitted the request.
Ota Core and Authority Launcher must use the same reviewed immutable revision. The Ota v1.6.26
carrier pins protocol implementation commit
04a199a1eddd72b5b61958e0fe7f2d4e662e05cf:
ota-authority-protocol = { git = "https://github.com/ota-run/authority-protocol.git", rev = "04a199a1eddd72b5b61958e0fe7f2d4e662e05cf" }Changing that pin is a protocol compatibility change and requires both consumers to be repinned
and revalidated together. Verify this crate with Rust 1.95.0:
cargo fmt --check
cargo check --locked --all-targets
cargo clippy --locked --all-targets -- -D warnings
cargo test --locked --all-targetsThe protocol used by the bounded Linux/systemd carrier is implemented and conformance-tested across Ota Core and Ota Authority Launcher. This crate is currently source-distributed rather than published as a stable crate release. Consumers must pin the exact immutable revision used by both peers; branch references do not establish protocol compatibility.
The public operator model and deployment boundaries are documented in the Broker Crossing Authority reference. Provider attestation, hosted approval operation, and non-Linux carriers remain outside this protocol release posture.
Apache License 2.0. See LICENSE.