Status: implemented as a non-published, zero-dependency codec in sealr-worker-protocol. It remains a transport foundation alongside the separate private semantic records used by the Alpha.6 supervisor-worker boundary. It does not start a worker, transfer an operating-system handle, or provide process isolation by itself.
The private semantic-record implementation is a separate internal format with independent SEALRSEM magic. The supported Linux supervisor now uses semantic-record version 2 to carry verified ZIP creator-system and external-attribute evidence. This does not revise or reinterpret the authenticated SLRAB001 worker protocol v1. Deterministic tests reject cross-decoding between semantic planning and completion records; protocol v1 golden and fuzz surfaces remain unchanged.
The protocol has one narrow purpose: carry a bounded operation description and bounded semantic result while the transport transfers authority separately. Archive bytes never appear in a control frame. A transport implementation is conforming only when it associates the declared capability slots with the exact out-of-band handles received for that frame.
- Every integer uses little-endian encoding and every frame names protocol version
1. - A complete frame is at most 4 MiB. Start frames are exactly 212 bytes.
- Counts and fixed minimum encoded sizes are checked before a vector reservation.
- String byte lengths, remaining input, UTF-8, and the string language are checked before a string allocation.
- Unknown enum values, nonzero reserved fields, trailing bytes, absent-value fields with nonzero bytes, and inconsistent counts fail closed.
- Operation IDs are nonzero. A result is accepted only for the supervisor-supplied expected operation ID. The request-bound validator also requires the returned profile identity and manifest resource claims to match the accepted start request.
- Start capability declarations must exactly match the capability count reported by the transport. Result frames cannot carry capabilities.
- Manifest paths are canonical relative paths in strict bytewise order. Duplicates, order changes, and a file that is an ancestor of another object are rejected.
- The decoder is pure. It returns a bounded value or a typed error before any archive or filesystem effect.
The codec contains no unsafe and has no runtime dependency. Allocation uses fallible reservations. ProtocolError contains a fixed error kind, byte offset, and static detail instead of echoing hostile input.
The byte codec cannot validate operating-system handle rights. The future supervisor must enforce the following rules at the transport boundary:
| Mode | Capability slots | Required authority |
|---|---|---|
| Inspect | 0 source |
One read-only immutable snapshot handle |
| Materialize | 0 source, 1 stage |
One read-only immutable snapshot handle and one stage-directory handle |
| Result | none | Results never grant authority back to the supervisor |
The supervisor retains the destination parent, final name, publication, cleanup, staged-tree audit, and recovery authority. The worker does not receive the destination parent or an ambient archive pathname. Slot numbers are local to one received frame and do not identify a global handle table.
Protocol v1 also exposes request-bound result validation. It checks the operation ID, interpretation-profile digest, manifest member count, per-file size, aggregate file size, and canonical path depth against the accepted start request. Aggregate byte overflow fails closed. The result does not echo the source digest or policy digest, so v1 cannot provide complete request/result binding and must not be described that way.
A stream transport should read the fixed 16-byte header, reject a declared payload that would exceed 4 MiB, then read exactly the declared payload. End-of-stream before that point is truncation. Bytes after the declared payload are trailing input, not another implicit frame.
| Offset | Bytes | Field | Rule |
|---|---|---|---|
| 0 | 8 | Magic | ASCII SEALRIPC |
| 8 | 2 | Version | 1 |
| 10 | 1 | Kind | 1 start, 2 result |
| 11 | 1 | Reserved | Zero |
| 12 | 4 | Payload length | Exact bytes after the header |
The payload length excludes the header. No decoder accepts concatenated frames or trailing padding.
The version 1 start payload is exactly 196 bytes.
| Payload offset | Bytes | Field | Rule |
|---|---|---|---|
| 0 | 16 | Operation ID | Nonzero, supervisor generated |
| 16 | 1 | Mode | 0 inspect, 1 materialize |
| 17 | 1 | Interpretation profile | 1 strict ASCII v1, 2 strict ASCII v2 |
| 18 | 1 | Member sync | Boolean 0 or 1 |
| 19 | 1 | Reserved | Zero |
| 20 | 2 | Capability count | At most 2 and equal to the transport count |
| 22 | 2 | Source slot | Available slot |
| 24 | 2 | Stage slot | Available distinct slot, or 0xffff when absent |
| 26 | 2 | Reserved | Zero |
| 28 | 8 | Source length | At most max_archive_bytes |
| 36 | 32 | Source SHA-256 | Digest of the complete immutable snapshot |
| 68 | 32 | Interpretation profile SHA-256 | Exact selected profile identity |
| 100 | 32 | Policy SHA-256 | Opaque supervisor-supplied policy identity; v1 defines no compiled-policy preimage |
| 132 | 8 | Maximum archive bytes | Resource limit |
| 140 | 8 | Maximum files | Resource limit |
| 148 | 8 | Maximum member bytes | Resource limit |
| 156 | 8 | Maximum total expanded bytes | Resource limit |
| 164 | 1 | Ratio present | Boolean 0 or 1 |
| 165 | 7 | Reserved | Zero |
| 172 | 8 | Maximum ratio | Zero when absent |
| 180 | 4 | Maximum path depth | Resource limit |
| 184 | 4 | Reserved | Zero |
| 188 | 8 | Maximum metadata bytes | Resource limit |
Inspect requires exactly the source capability and no stage slot. Materialize requires exactly two distinct valid slots. The archive is referenced by source length and digest; it is not copied into the frame.
The result begins with a 124-byte fixed section.
| Payload offset | Bytes | Field | Rule |
|---|---|---|---|
| 0 | 16 | Operation ID | Must equal the expected operation ID |
| 16 | 1 | Status | 1 complete, 2 rejected, 3 failed |
| 17 | 1 | Root flags | Bit 0 layout, bit 1 content, all other bits zero |
| 18 | 2 | Reserved | Zero |
| 20 | 4 | Manifest count | At most 10,000 |
| 24 | 4 | Finding count | At most 10,000 |
| 28 | 32 | Interpretation profile SHA-256 | Worker-observed profile identity |
| 60 | 32 | Layout root | Zero when absent |
| 92 | 32 | Content root | Zero when absent |
Each manifest entry then contains a u16 path length, u8 kind, zero reserved byte, u64 size, 32-byte SHA-256, and path bytes. Kind 1 is a file and kind 2 is a directory. Directories have zero size and a zero digest. Version 1 paths are 1 through 4,096 ASCII bytes and use the current canonical jail language: relative, slash-separated, no empty, . or .. component, no backslash, colon, control or portable-illegal character, no trailing dot or space, and no Windows reserved device stem.
Each finding contains u16 code length, u16 detail length, u16 optional path length, u8 severity, a zero reserved byte, then code, detail, and optional path bytes. 0xffff means no path. Codes are 1 through 128 ASCII bytes in [a-z][a-z0-9._]*. Details are at most 1,024 UTF-8 bytes without control characters. A finding path follows the manifest path language.
Complete results require both roots and may not contain an error finding. Rejected and failed results have no content root or manifest and contain at least one error finding. A rejected or failed result may retain a layout root when interpretation reached a coherent layout before the later failure.
| Item | Limit |
|---|---|
| Complete frame | 4,194,304 bytes |
| Start frame | Exactly 212 bytes |
| Capabilities | 2 |
| Manifest entries | 10,000 |
| Findings | 10,000 |
| Path | 4,096 bytes |
| Finding code | 128 bytes |
| Finding detail | 1,024 bytes |
Version 1 contains no range list. If a later worker needs ranges, that protocol change receives a new version and an independently bounded encoding.
Version 1 is a non-shipping transport foundation, not the supported supervisor's semantic contract. Its single status is a worker-operation status. It does not preserve the public interpretation, admission, verification, effect, and lifecycle axes independently, and failed or rejected results intentionally discard the manifest and content root. It therefore cannot represent every admitted-but-effect-failed outcome.
The result carries a reduced staged-member manifest, findings, and preview roots. It does not carry a complete ArchiveIR, byte ranges, compressed sizes, methods, CRC32 values, extra-field dispositions, normalization actions, snapshot ownership, or an independently checkable proof that the manifest is the unique meaning of the snapshot. It therefore cannot construct the public Outcome, ArchiveIR, or VerifiedArchive. A supervisor can validate the frame and, after proving that all writers are quiescent, compare a stage with the returned claim. Protocol v1 alone does not let it independently verify archive semantics or preserve bounded later member reads.
The separate authenticated Linux worker boundary introduced in Alpha.6 and extended on current main does not change protocol v1. Normal cases authenticate a distinct child-only helper's exact bytes, sealed executable identity, private hello, helper feature generation, and running process before bootstrap; deliberate fault cases alone use the lab executable. Bounded kernel-sealed memfds carry canonical operation-bound planning, plan-bound completion, completion-bound retained-content, and distinct full-read or prefix-read request records. The private executor binds a source-owning Ready plan to the exact worker descriptor, verifies planned Store and Deflate ranges without structural reparse, and retains handoff authority through observation and reap. The supervisor treats both outputs as untrusted proposals, replays the accepted plan against its retained exact source, and requires byte-for-byte canonical agreement. Each caller-bounded non-retained read spawns a fresh restricted worker with no stage or destination capability. Its bootstrap preserves whether the accepted plan originated from inspect or materialize and carries an explicit prefix flag when required. The worker streams the complete member. The supervisor retains only the requested prefix for prefix reads, and no bytes return before exact pipe EOF, correlated result, complete size, CRC32, SHA-256, clean exit, and reap agree. Helper feature generation 2 makes the additive request kind incompatible with older helpers before source transfer while bootstrap ABI 1 and operation protocol v1 remain unchanged. Supervised materialization passes only a supervisor-created stage root, requires clean exit and exact reap before result validation, replay, or audit, and reserves no-replace publication for the supervisor. Public package smoke preserves IR on destination setup failure and covers effect mapping, retained borrows, full and prefix reads, exact helper packaging, cleanup, and reap. A required pinned-kernel QEMU gate proves public inspect and materialize fail closed on actual Landlock ABI 2 before source transfer.
The authenticated helper's semantic execution is now fixture-independent within the private record boundary. One self-bound generic adapter validates the sealed plan's actual profile, policy identity, budget, target, consumer, effect, member-sync, target identity, and retention, then executes inspect, materialize, or full or prefix read work without reconstructing lab defaults. It preserves canonically stopped verification as semantic output. The supervisor reconstructs owned private outcome and retention state only after its exact-source replay matches completion and retained content byte for byte. This adapter still does not use or revise protocol v1.
The deterministic protocol suite covers valid inspect and materialize round trips, complete and rejected results, every truncation of valid frames, wrong magic, version and kind, trailing input, capability and operation confusion, oversized and impossible counts, root-state confusion, malformed UTF-8, invalid paths, manifest ordering and topology, directory content claims, request-bound profile and resource drift, aggregate-size overflow, and three mutations at every byte position. A decoded value must re-encode canonically and decode to the same value.
The protocol_decoders libFuzzer target exercises arbitrary bytes and up to 64 input-directed mutations of known-valid start and result frames. Successful decodes must round trip to the identical canonical frame. The separate fuzz workspace pins:
| Control | Value |
|---|---|
| Rust toolchain | nightly-2026-08-01 |
cargo-fuzz |
0.13.2 |
libfuzzer-sys |
0.4.13 |
| Maximum input | 4 MiB |
| Campaign time | 600 seconds |
| Per-input timeout | 5 seconds |
| RSS limit | 1,024 MiB |
| Jobs | 1 |
The protocol seed manifest binds every protocol seed and its dictionary by path, byte length, and SHA-256. Required CI verifies that manifest and the workflow bounds. The scheduled fuzz workflow runs this AddressSanitizer campaign weekly and on demand. A crash stops the campaign and preserves the bounded reproducer for seven days. A reproducible failure must become a deterministic regression before the fuzz gate can return to green.
The same workflow contains a separate semantic_records job with its own manifest, corpus, dictionary, and artifact boundary. That Alpha.6 target reaches a hidden private planning and completion codec entry only when its nondefault fuzz feature is enabled. It does not revise protocol v1 and does not yet fuzz either private member-read request kind. Both kinds have deterministic hostile validation coverage. Clean exact-main on-demand and first scheduled-event evidence are recorded in the assurance report; accumulated scheduled history remains pending.
The first exact-main campaign executed 18,277,565 units in 601 seconds, averaged 30,411 executions per second, reached 503 MiB peak RSS under the 1,024 MiB limit, and produced no reproducer.
The Alpha.5 release-gate campaign ran independently on the exact released commit. It executed 17,626,137 units in 601 seconds, averaged 29,328 executions per second, added 1,424 corpus units, reached 505 MiB peak RSS, and produced no reproducer.
Coverage-guided fuzzing is heuristic evidence. A clean bounded campaign does not prove that every frame or parser state is safe.
- This codec does not transfer, duplicate, restrict, or close operating-system handles.
- It does not prove that a worker and every descendant have released writable stage authority before audit.
- It does not authenticate its transport or protect against a malicious supervisor.
- It does not provide confidentiality for hashes, policy identities, paths, or findings.
- It does not implement Landlock, seccomp, AppContainer, a restricted token, or a worker lifecycle.
- It does not make the current in-process parser a sandbox.
The process and authority design is in sandboxing and projection. The private production semantic boundary is documented in semantic-record.md, and remaining closure work is in the near-term assurance track.