Skip to content

Alcove technical specifications ​

This directory is the technical specification tier of the Alcove documentation. The documents here are written for implementors and security auditors: they cover wire formats, byte encodings, normative constant values, protocol internals, and implementation-level design. The overview tier in docs/ (one level up) stays conceptual and operational, for program officers, security reviewers, compliance officers, IT staff, and new contributors.

A document in this tier always has an overview-tier counterpart it complements, and each states the split in its intro: the overview says what a control or format is for and what it protects against; the spec says how it is constructed. (Two documents, DEPENDENCY_PINS.md and CONTAINER_IMAGES.md, are deliberate exceptions -- see the note below.)

Index ​

Channel security ​

The channel-security controls are specified across these files. CHANNEL_SECURITY.md holds the application-layer encryption and the authenticated abort marker, and lists the others.

FileScopeAudienceDoes not cover
CHANNEL_SECURITY.mdThe application-layer AEAD envelope and per-direction key derivation, the inbound integrity/replay/ordering checks, and the authenticated abort marker.Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the SFTP-stack upgrade checklist (see DEPENDENCY_PINS.md)
TRANSPORT_BOUNDS.mdThe memory bounds the transports hold against what a hostile party writes for them to read, with their constant values: the file-sync inbound frame-size bound with the single-pass per-exchange cap and the bounds on PSI set parts and matched-record lists sent in parts, the directory-listing bound, the rendezvous symlink refusal, and the WebRTC data-channel inbound bound (the chunk reassembly caps and the BinaryPack structural pre-scan).Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the PeerJS-stack upgrade checklist (see DEPENDENCY_PINS.md)
TRANSPORT_LIVENESS.mdThe liveness bounds on the file-sync transport operations, with their constant values: the per-operation deadlines and idle windows, the whole-exchange budget, the send-window liveness guard, the connect-probe bound, the consumer-side terminal-error rule, the slow-operation warning, and the SFTP session heartbeat and TCP keepalive.Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the SFTP-stack upgrade checklist (see DEPENDENCY_PINS.md)
SFTP_CONNECTION.mdThe controls on reaching an SFTP server and keeping its connection safe, with their constant values: the server-provisioning endpoint call (the request, its timeout, the create-mode answer schema, and the exit each answer maps to), the SFTP fatal-packet crash safety, and the SFTP host-key verification (the pinned fingerprints, the fail-closed no-pin default, first-use trust, probe-host-key and the console probe-to-fill, the diagnosis of a non-SSH peer, and the cross-party fingerprint reconciliation).Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the host-key pinning and the Channel security overview in SECURITY_DESIGN.md; the provisioning endpoint's fields (see EXCHANGE_REFERENCE.md); a session dropped mid-exchange (see SFTP_SESSION_RECOVERY.md); the SFTP-stack upgrade checklist (see DEPENDENCY_PINS.md)
SFTP_SESSION_RECOVERY.mdThe SFTP adapter's recovery of a session the server drops mid-exchange, with its constant values: what is re-dialed and what stays terminal, the bounds and what each protects, what the accounting counts, the re-issue of a torn operation, operations concurrent with a re-dial or a release, the outstanding-operation hold on an idle boundary, the deferred cleanup-delete record, the session-transition lock, and the connection's terminal close.Security auditors, implementorsWhen an operator needs a session per poll cycle (see DEPLOYMENT.md); the session heartbeat (see TRANSPORT_LIVENESS.md); the file-sync state machine across an idle boundary (see FILE_SYNC.md); the state-machine model and its design decisions (see sftp-adapter-state-machine.md)
SIGNALING_SERVER_BOUNDS.mdThe PeerJS signaling broker's bounds against an unauthenticated internet client, with their constant values: the inbound frame bound (the ws byte cap and the structural parse bound), the upgrade-handshake timeouts, the liveness reaper, one socket per registered client, the bounded release of a refused or unanswered socket, the relay send-buffer and queue bounds, and the peer-id length cap.Whoever deploys or assesses the broker, security auditors, implementorsWhat each guard protects against and which controls are the reverse proxy's -- that is Hardening the coordination server in DEPLOYMENT.md; the JSON-decode chokepoint the broker reuses (see PARSED_INPUT_BOUNDS.md); the WebRTC data-channel inbound bound (see TRANSPORT_BOUNDS.md); the signaling envelopes (see WEBRTC_TRANSPORT.md)
PARSED_INPUT_BOUNDS.mdThe application-layer bounds on parsed input, with their constant values: the count, length, width and depth bounds on partner-parsed collections and the JSON-decode chokepoint beneath them, the operator-local CSV-read single-line byte ceiling (the lone input bound with no adversary), the CSV header sanitation at ingestion, the linkage-terms name-class character rule, and the web linkage-terms import bounds.Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the transport memory bounds (see TRANSPORT_BOUNDS.md); the transform-regex dialect (see TRANSFORM_REGEX_DIALECT.md) and the transform-parameter bounds (see TRANSFORM_PARAMETER_BOUNDS.md)
TRANSFORM_REGEX_DIALECT.mdThe linear-time regex dialect that transform patterns (raw patterns and the one parse_date expands from its format) execute under, with its constant values: the dialect-conformance gate, the raw pattern length cap and the weighted-size cap, the regex search bound, the compile-cost bounds at the mint and accept boundaries, and the name-constraint character class.Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the normative dialect definition (see PROTOCOL.md); the transform-parameter bounds (see TRANSFORM_PARAMETER_BOUNDS.md)
TRANSFORM_PARAMETER_BOUNDS.mdThe bounds on the transform.params values of a linkage-terms document, with their constant values: the declared type of each param and the refusal of any other, and the caps on the param values that drive unbounded per-row work (pad_left length, parse_date formats, string param length) with the ceilings on the transformed value, the assembled keys, and the per-row transform work.Security auditors, implementorsWhat each control protects against and why it is sufficient -- that is the Channel security overview in SECURITY_DESIGN.md; the count bound on a params record (see PARSED_INPUT_BOUNDS.md); the regex dialect and the raw pattern size cap (see TRANSFORM_REGEX_DIALECT.md)
DISPLAY_ESCAPE.mdThe form in which text reaches an operator: the display sanitization escape format and the one place each fragment takes it, the operator-chosen fragments rendered as typed and the lint ban holding their sites, the partner-origin text type and the abort-route layout, the decode description split per consumer, the routes that still escape twice and the console's relay of CLI warnings, and the compatibility diagnostic value delimiting.Security auditors, implementors, anyone writing an error, log line or promptWhat each control protects against -- that is the Console and log hygiene overview in SECURITY_DESIGN.md; the private-key redaction and the message display budgets (see DISPLAY_REDACTION.md)
DISPLAY_REDACTION.mdWhat is removed from text shown to an operator and how much of it is shown, with their constant values: the private-key redaction, its three sinks and the limits of its reach, the raw-error sink ban and the console sentinel, the per-link and per-value message budgets with their partition by chooser and the cause-depth bound, and the display types of the invitation consent summary.Security auditors, implementors, anyone writing an error, log line or promptWhat each control protects against -- that is the Console and log hygiene overview in SECURITY_DESIGN.md; the display sanitization escape format (see DISPLAY_ESCAPE.md)

Other specifications ​

FileScopeAudienceDoes not cover
PROTOCOL.mdThe PSI and PSI-C algorithms, their composition into a record linkage, and the wire-level P-256 authenticated key exchange (construction, key schedule, message encoding). Also the Self-attested record subsection: where the record sits in the exchange protocol.Security auditors, external implementors, developersThe exchange-agreement format (see EXCHANGE_REFERENCE.md); the threat model and authentication design (see SECURITY_DESIGN.md); the network layer (see COMMUNICATION.md)
FILE_SYNC.mdThe file-sync transport state machine: the directory-as-state-machine, the filename taxonomy, the enforcement sites, the invariants, and the exchange preconditions for the sftp and filedrop channels. Also the invitation token's file-sync material: the split-directory role swap, the retain-mode declaration the token carries, and the version-bump policy each of them takes.Developers, designersThe user-facing configuration reference and the normative filename grammar (see EXCHANGE_REFERENCE.md -- see the tier-inversion note below); the channel/synchronization overview (see COMMUNICATION.md)
WEBRTC_TRANSPORT.mdThe webrtc channel's wire, which two implementations (the browser's PeerJS client and the CLI's direct-werift transport) must match exactly: the rendezvous roles and the handshake role each fixes, the broker socket URL and the defaults an omitted server field takes, the OFFER/ANSWER/CANDIDATE payload shapes, the BinaryPack chunk envelope and close sentinel, what a clean close must wait on before tearing down, the ICE list-replaces-default rule, and the transport's budgets.Implementors of either end, security auditorsThe rendezvous peer-id derivation itself (see PROTOCOL.md); the inbound reassembly bound (see TRANSPORT_BOUNDS.md) and the AEAD envelope (see CHANNEL_SECURITY.md); the library choice and the alternatives weighed (see cli-webrtc-stack.md); the operator-facing configuration (see CLI.md)
WEBSOCKET_RELAY.mdThe WebSocket relay's wire: its endpoint, the hello and start frames, the key table it checks a hello against, pairing by role, forwarding, keepalive, close ordering, the close codes, and the relay's bounds.Implementors of a relay client, whoever deploys the relay, security auditorsThe proof a hello presents (see PROTOCOL.md); the framing of the messages it forwards (see WEBRTC_TRANSPORT.md); the design and the rulings behind it (see web-websocket-transport.md)
CLI_EVENTS.mdThe CLI's opt-in machine-interface event stream (--event-stream): the fixed file descriptor, the NDJSON framing and per-line schema version, every event type and its fields, the four terminal-error categories and their classification rules, the security marker, the single-terminal-event guarantees, the per-field sanitization, and the disclosure digest line the human log records.Implementors of a supervising process, security auditorsThe operator-facing flag description and the exit-code table (see CLI.md); the exchange protocol that produces the stages (see PROTOCOL.md)
CLI_DOCTOR.mdThe alcove doctor verdict emitted under --json: the document's fields, the schema version and the compatibility rule, the overall and per-check status vocabularies, each mode's ordered check-id list, the relay check's bound and outcomes, the human-only fields the JSON withholds together with the bound on the tool-output excerpt, and the exit code each verdict maps to.Implementors of a setup launcher, security auditorsWhat the modes check and the SMB_* inputs they read (see CLI.md); the CLI-wide exit-code table (see CLI.md); the rendezvous semantics the checks exercise (see FILE_SYNC.md)
SERVER_JOB_API.mdThe web server's job API that drives the CLI as a subprocess for the console: the endpoint table and status codes, the injection-closed exchange and zero-setup intent schemas, the operator-authored SFTP connection and its validation, the composed CLI config, the workdir layout and modes, the SSE event relay with full-history replay and trust-boundary re-validation, the exit-code reconciliation and cancellation escalation, the JOB_DATA_ROOT/JOB_CLI_BINARY/JOB_SECRETS_DIR semantics and the startup and reachability rules, the memory-only single-active-exchange lifetime a restart forgets, and the two graduation artifacts beside it: the recurring-run hand-off the API serves and the client-composed partner accept kit it does not.Implementors of a supervising process, security auditorsWhat the feature is for and how an operator enables it (see CONSOLE.md); the single-party console trust invariant (see SECURITY_DESIGN.md); the fd-3 event stream this consumes (see CLI_EVENTS.md)
EXCHANGE_RECORD.mdThe self-attested exchange record format: the record and verification-keys file shapes, the format version, the HMAC commitment scheme and agreed-terms hash, the governance metadata, the disclosure framing, and the record's privacy properties.Security auditors, external implementors, compliance reviewers, developersThe PSI protocol that produces the exchange (see PROTOCOL.md); the exchange-agreement format that supplies the governance fields (see EXCHANGE_REFERENCE.md); the canonical byte encoding (see CANONICAL_ENCODING.md)
EXCHANGE_FILE.mdThe downloadable exchange-file artifact's compatibility contract: that a minted file is the shared CLI config schema (no parallel format), the mint-layer guarantees (no authentication block, no representable credential, the SFTP placeholder username), the web/CLI versioning policy (strict-reject vs strip, breaking changes in scope, no artifact back-compat), the invitation channel-binding rule, and the secret's key-file provisioning path (invite/accept/exchange --invitation).Security auditors, implementorsThe field-level meaning of any config field (see EXCHANGE_REFERENCE.md); the invitation token's wire format (see INVITATION_TOKEN.md); the split-directory role swap and its version-bump policy (see FILE_SYNC.md); the owner-only key-file write discipline (see CREDENTIAL_STORAGE.md)
INVITATION_TOKEN.mdThe invitation token's wire format and the checks on it, with their constant values: the base64url encoding and its 4-byte checksum, the accept link and the whitespace strip, the token's fields and the version policy, the strict per-channel connection endpoint and the cross-field rules, the size bounds, the mint order, the decode order and its failure kinds, and the expiry, endpoint and terms checks an accepting party applies after the decode.Security auditors, implementorsWhat an invitation contains, why it is confidential, and its lifetime policy (see SECURITY_DESIGN.md); the linkage-terms fields and bounds (see EXCHANGE_REFERENCE.md and PARSED_INPUT_BOUNDS.md); the split-directory role swap and the retain-mode declaration's meaning (see FILE_SYNC.md); the relay locator's url grammar (see PROTOCOL.md)
DEFAULT_STANDARDIZATION.mdThe cleaning a configuration gets when it authors none: the per-type default standardization pipelines as ordered steps with their parameters and results, the cross-party invariant that makes a change to one wire-affecting, the date-format inference parameters, and the column-name table that infers a semantic type, role, and payload default.Implementors, security auditors, maintainers changing a pipelineThe step-function catalog and the configuration schemas (see EXCHANGE_REFERENCE.md); the regex dialect and parse_date semantics the steps run under, and the field-to-column binding rule (see PROTOCOL.md)
CANONICAL_ENCODING.mdThe normative RFC 8785 (JCS) byte encoding the receipts, record commitments, and agreed-terms hash are computed over, with worked examples. Written so an independent implementation reproduces byte-identical output.External implementors, security auditorsWhat the encoding is for and what it protects against -- that is the Canonical encoding overview in SECURITY_DESIGN.md; how receipts use these bytes (see PROTOCOL.md); the record format (see EXCHANGE_RECORD.md)
CREDENTIAL_STORAGE.mdThe owner-only on-disk write path shared by the credential, signing-identity, exchange-record, and result-CSV files: the POSIX exclusive-create and atomic-rename discipline, the fsync durability and cross-write crash-ordering guarantee, the macOS F_FULLFSYNC caveat and NFSv4-ACL strip, the writable-and-readable-parent pre-flight, and the Windows ACL-narrowing and load-check internals.Security auditors, implementorsWhat the files contain and the operator-facing required permissions, warnings, and remediation -- that is the Key file security overview in SECURITY_DESIGN.md
MANAGED_EXCHANGE_RECORD.mdThe browser-persisted managed-exchange record shape: this party's exchange-file document plus the local-only fields (the secret, expiry policy, side, label, working-folder handle, schedule, and run bookkeeping) split into what persists across runs versus what is supplied at each run (input content never persists; at most a persisted folder handle, a pointer the app reads one conventioned name from), the credential-free connection composition and its three named implementation pieces, the local side role dispatch, the persist-before-success crash-consistency ordering, the linear-secret single-owner invariant, the derived-never-stored rendezvous-id and rotation values, and the export artifact's custody model, rollback caveats, and CLI-separable format.Security auditors, implementorsThe browser at-rest threat model, rollback and metadata-at-rest analyses, and egress-hardening limits (see SECURITY_DESIGN.md); the managed exchange lifecycle overview (see MANAGED_EXCHANGE.md); the exchange-file artifact contract the document reuses (see EXCHANGE_FILE.md)
DEPENDENCY_PINS.mdWhy the ssh2/ssh2-sftp-client and peerjs/peerjs-js-binarypack stacks are exact-pinned, the internal assumptions the CLI SFTP adapter and the web inbound bound rest on, the per-stack checklist to re-verify them before a bump, the vendored @openmined/psi.js addon, the allowScripts install-script policy (what npm enforces from it, why allows are version-pinned and denials are not), the GitHub Action pin mirror, and the residuals npm's resolver leaves in this workspace.Maintainers upgrading a pinned dependencyThe controls the assumptions support (see CHANNEL_SECURITY.md, SFTP_CONNECTION.md and SFTP_SESSION_RECOVERY.md); how the container images freeze and pin what they install (see CONTAINER_IMAGES.md); the dependency-review requirement (see CONTRIBUTING.md)
CONTAINER_IMAGES.mdHow the shipped CLI image (Dockerfile) and the FIPS variant (Dockerfile.fips, published beside it under -fips tags) freeze their npm tree to the committed lockfile, what each pins by digest, hash, or NVR and what holds each pin, the two reviewed OS-package install lines, what the CMVP certificate behind the variant's provider attests (its tested operational environments and the approved-algorithm rows the variant's measured call shapes rest on, with CAVP certificate ids), and the writable-set and setuid/setgid inventories that are measured by running each built image -- with the descriptive built-image figures behind them kept in a clearly labelled non-normative section.Maintainers building or vetting an image, security auditorsWhy the npm dependencies themselves are exact-pinned and the per-stack upgrade checklists (see DEPENDENCY_PINS.md); the release and SBOM procedure (see RELEASES.md)

Where does my content go? ​

If you are writing a constant value, a byte/wire layout, an HKDF info string or other algorithm step, or the "would only need revisiting if..." rationale behind one of those, it belongs in docs/spec/ - regardless of which doc you currently have open. Overview docs (docs/) stay conceptual and operational, including operational rationale such as the coverage-gate decision.

Within this tier, route by topic:

  • The PSI/PSI-C algorithm or the key-exchange wire format -> PROTOCOL.md.
  • The AEAD envelope, its key derivation, or the authenticated abort marker -> CHANNEL_SECURITY.md.
  • A transport memory bound (inbound frame size, directory listing, rendezvous symlinks, the WebRTC data channel) -> TRANSPORT_BOUNDS.md.
  • A transport liveness bound (per-operation deadlines, the whole-exchange budget, the connect probe, the SFTP heartbeat) -> TRANSPORT_LIVENESS.md.
  • The server-provisioning endpoint call, SFTP crash safety on a fatal packet, or SFTP host-key verification -> SFTP_CONNECTION.md.
  • The SFTP adapter's recovery of a dropped session (re-dial, re-issue, the deferred cleanup-delete record, the session-transition lock, the terminal close) -> SFTP_SESSION_RECOVERY.md.
  • A bound on parsed input (collection counts, the JSON-decode chokepoint, the CSV-read line ceiling, CSV header sanitation, the linkage-terms name rule, the web terms import) -> PARSED_INPUT_BOUNDS.md.
  • The linear-time dialect a transform pattern runs under, its size and search bounds, or the name-constraint character class -> TRANSFORM_REGEX_DIALECT.md.
  • A transform param's declared type, or a bound on a param value or the value a transform derives -> TRANSFORM_PARAMETER_BOUNDS.md.
  • How text is escaped or delimited for an operator (the escape format, operator-chosen fragments, partner-origin text, the routes escaped twice, compatibility diagnostic delimiting) -> DISPLAY_ESCAPE.md.
  • Private-key redaction on an operator display, or a display length budget (per value, per cause link, cause depth) -> DISPLAY_REDACTION.md.
  • A bound the PeerJS signaling broker holds against its clients (frame size, upgrade handshake, liveness, relay queues) -> SIGNALING_SERVER_BOUNDS.md.
  • The file-sync directory state machine, filename taxonomy, or enforcement sites, or the split-directory role swap and the retain-mode declaration an invitation token states -> FILE_SYNC.md.
  • The webrtc channel's signaling envelopes, data-channel framing, close obligation, rendezvous roles, or ICE resolution -> WEBRTC_TRANSPORT.md.
  • The WebSocket relay's hello, start, pairing, forwarding, close ordering, close codes, or bounds -> WEBSOCKET_RELAY.md.
  • The exchange-record on-disk format or commitment scheme -> EXCHANGE_RECORD.md.
  • The downloadable exchange-file artifact's compatibility contract (mint-layer guarantees, web/CLI versioning, channel binding, the secret's key-file provisioning path) -> EXCHANGE_FILE.md.
  • The invitation token's encoding, checksum, fields, connection-endpoint layout, size bounds, or the checks its minter and its receiver apply -> INVITATION_TOKEN.md.
  • A default standardization pipeline's steps, or the column-name aliases and role/payload defaults type inference assigns -> DEFAULT_STANDARDIZATION.md.
  • The canonical byte encoding any of the above commits over -> CANONICAL_ENCODING.md.
  • The owner-only on-disk write path (exclusive-create, atomic rename, fsync durability, ACL narrowing) or its crash-ordering guarantee -> CREDENTIAL_STORAGE.md.
  • The browser-persisted managed-exchange record shape (the persisted exchange-file document plus local fields, persist-before-success ordering, single-owner invariant) or the export artifact's custody model -> MANAGED_EXCHANGE_RECORD.md.
  • The CLI machine-interface event stream (--event-stream): fd, NDJSON framing, event fields, or the terminal-error category rules -> CLI_EVENTS.md.
  • The alcove doctor --json verdict: a field, the version rule, a status/overall value, a check id, or the exit-code mapping -> CLI_DOCTOR.md.
  • The web server's job API (endpoints, the exchange-intent schema, the workdir layout, the SSE relay, the gate/startup rules, the job lifetime) -> SERVER_JOB_API.md.
  • A pinned-dependency internal assumption, its upgrade checklist (ssh2, peerjs), the vendored PSI addon, the allowScripts install-script policy, a GitHub Action pin invariant, or an npm-resolution residual -> DEPENDENCY_PINS.md.
  • A container image's npm/Docker freeze, base-image digest pin, OS-package install line, the FIPS variant's pin table, a row of the CMVP certificate that variant's provider holds (its tested operational environments, its approved-algorithm rows and their CAVP certificate ids), or a runtime posture measured on a built image (its writable set, its setuid/setgid inventory) -> CONTAINER_IMAGES.md.

Two overlaps to disambiguate ​

  • Self-attested record: placement vs format. Its protocol placement -- where it sits in the exchange, beside the separate signed receipt -- lives in PROTOCOL.md (the "Self-attested record" subsection). Its on-disk format -- file shapes, commitment scheme, governance metadata -- lives in EXCHANGE_RECORD.md. Both are spec-tier, so there is no cross-tier break; open the format doc for the bytes and the protocol doc for the placement.
  • Channel security: construction vs key-exchange wire format. The AEAD construction is in CHANNEL_SECURITY.md and the transport bounds are in TRANSPORT_BOUNDS.md and TRANSPORT_LIVENESS.md; the key-exchange wire format that produces the session key those keys derive from is in PROTOCOL.md.

Tier-inversion note: the filename grammar ​

FILE_SYNC.md is a spec-tier document, but the single normative invariant its state machine rests on -- the filename grammar -- is owned by the overview-tier EXCHANGE_REFERENCE.md, because that is the document an operator authoring an alcove.yaml opens. FILE_SYNC.md therefore references up into the overview tier for its central invariant. This is deliberate and recorded: do not "tidy" the filename grammar down into docs/spec/. The grammar stays in EXCHANGE_REFERENCE.md (operators need it) and FILE_SYNC.md defers to it; moving it would silently break FILE_SYNC's invariant references.

Maintainer-runbook exception: DEPENDENCY_PINS.md and CONTAINER_IMAGES.md ​

DEPENDENCY_PINS.md and CONTAINER_IMAGES.md bend the two tier rules above, on purpose. Their counterparts are CONTRIBUTING.md (the dependency-review requirement) and RELEASES.md (the build and release procedure), not a docs/ overview; their content is a re-verification procedure over spec-level assumptions, not a construction; and they add maintainers upgrading a pinned dependency or building an image to the tier's implementor and auditor audience. They live here anyway because their substance is spec-tier -- the numeric SFTP constants, the BinaryPack marker table, and the ssh2 listener assumptions that CHANNEL_SECURITY.md, TRANSPORT_BOUNDS.md, TRANSPORT_LIVENESS.md, SFTP_CONNECTION.md and SFTP_SESSION_RECOVERY.md rest on, and the exact digests, hashes, and version rows that fix what a built image contains -- so they belong beside that doc, not in a separate runbook tier.

CONTAINER_IMAGES.md additionally includes a clearly labelled non-normative measured-inventories section. Those figures record what a built image was observed to contain; they bind no build, and nothing in this tier may cite them as a requirement.

Writing a control ​

A control in this tier is written in this order, each part under its label except the first two:

  1. The rule: what the implementation does or refuses, in one statement.
  2. The mechanism: how the rule is constructed and where it is enforced.
  3. Limits: what the control does not cover, and the cases where it does not hold.
  4. Depends on: one line naming the conditions the guarantee needs from the deploying side -- an operator setting, a host property, a network arrangement.
  5. Held by: the test or check that fails when the rule breaks.
  6. Why: the reason for the rule and the alternatives weighed, or a link to the docs/notes/ record holding them.

A control already in the tier is reshaped into this order when an issue changes that control, not in a pass of its own. The reshape moves sentences without rewording them, keeps each qualifying sentence with the claim it qualifies, and lists any sentence it does reword in the pull request's own file under wording-changes/ (CONTRIBUTING.md).