# FOG Composer

Status: Draft 0.1

Date: 2026-08-08

## 1. Purpose

This document defines `FOG-COMPOSER`, the networkless endpoint, local-state,
transfer, recovery, and update-verification contract for FOG native services.

It fixes the common Composer security boundary, MicroVM and Portable
deployment profiles, process separation, authenticated encrypted vault,
transaction and rollback rules, hostile import handling, committed export
bundles, identity-safe recovery, update verification, local rendering,
resource limits, and conformance gates.

It also records four non-active implementation candidates:

- `FOG-COMPOSER-CANDIDATE-LINUX-VAULT-1` for a Linux read-only system image,
  LUKS2 defense-in-depth volume encryption, a transactional embedded
  database, and object-level authenticated encryption;
- `FOG-COMPOSER-CANDIDATE-MICROVM-QUBES-1` for a Qubes-style networkless VM
  with narrowly allowlisted qrexec transfer services;
- `FOG-COMPOSER-CANDIDATE-PORTABLE-LINUX-1` for a signed read-only Linux image
  on dedicated physically offline hardware;
- `FOG-COMPOSER-CANDIDATE-UPDATE-TUF-1` for offline update metadata derived
  from The Update Framework.

These candidates have no active numeric profile IDs, do not select final
libraries or cryptographic parameters, are not authorized for public release,
and do not establish deployed endpoint-security claims.

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY describe
normative requirements in the sense of BCP 14 when they appear in uppercase.

## 2. Scope

`FOG-COMPOSER` owns:

- the networkless Composer runtime and its local privilege boundaries;
- common, MicroVM, Portable, and lower-assurance transfer profiles;
- booted-image verification requirements visible to the Composer;
- encrypted mutable state, key wrapping, object protection, and state
  migration;
- local atomic transactions spanning messaging, storage, PKI, imports,
  exports, recovery, and application state;
- local state commitments and optional external monotonic anchors;
- fixed Composer bundle framing and direction-specific record allowlists;
- import quarantine, complete validation, deduplication, and state release;
- transactional export creation and duplicate-export behavior;
- identity recovery packages and non-resumable restored sessions;
- offline release and update verification on Composer systems;
- safe local rendering and native application module boundaries;
- local retention, deletion, diagnostic, and resource-limit behavior;
- Composer-specific conformance and fault-injection evidence.

This document does not own:

- message handshake, ratchet, envelope, acknowledgment, or fragmentation
  cryptography;
- storage capabilities, replica envelopes, receipts, retention, or polling;
- KEMSphinx packet or SURB construction;
- adjacent online Noise links or blind-relay queue behavior;
- FOG-PKI consensus production, authority recovery, or transparency proofs;
- FOG-SX framing, FEC, physical signaling, or optical hardware;
- entry capsule and return-rendezvous constructions;
- release-repository production, signing ceremonies, or build provenance;
- a native multi-device protocol or automatic account recovery service.

Those contracts belong to `FOG-MESSAGING`, `FOG-STORAGE`,
`FOG-SPHINX-PROFILES`, `FOG-WIRE`, `FOG-PKI`, `FOG-SX`, the entry and return
specifications, a future `FOG-UPDATE` release contract, and future
multi-device work.

## 3. Security Boundary and Threats

### 3.1 Assets

The Composer holds the highest-value user assets in FOG:

- message plaintext, drafts, permitted attachments, and rendered history;
- pairwise identity roots, handshake identities, prekeys, ratchets, and
  skipped-message keys;
- storage read and write capabilities, recovery tombstones, and outboxes;
- contacts, private labels, verification decisions, and conversation state;
- PKI trust anchors, accepted epochs, checkpoints, manifests, and
  equivocation evidence;
- KEMSphinx routes, ephemeral secrets, SURBs, reply tokens, and pending
  network work;
- vault, object, transfer-pairing, backup, recovery, and local anchor keys;
- installed release state, trusted release roots, and rollback floors.

Compromise of an unlocked Composer can expose or alter all local assets. No
storage, boot, VM, or transfer mechanism can preserve confidentiality against
an attacker that controls the code currently using the plaintext and keys.

### 3.2 Adversaries

The contract considers:

- theft or forensic copying of powered-off storage;
- malicious, malformed, replayed, truncated, reordered, or oversized import;
- a compromised blind relay, transfer receiver, removable medium, QR reader,
  FOG-SX decoder, or update distributor;
- partial database corruption, torn writes, power failure, disk-full faults,
  and stale filesystem snapshots;
- rollback or cloning of a complete internally consistent Composer vault;
- a hostile MicroVM host, hypervisor, firmware, peripheral, DMA device, boot
  chain, or system update;
- malicious contacts and authenticated but adversarial message content;
- physical observation, evil-maid access, side channels, and secret remnants;
- dependency, compiler, build, release-key, or update-metadata compromise.

### 3.3 Trust distinctions

Object-level authenticated encryption protects stored object confidentiality
and integrity under its exact key assumptions. It does not prove freshness.

A hash-chained local journal detects missing, reordered, partially restored,
or corrupted state relative to the latest state still available locally. It
cannot detect replacement of the complete vault, journal, and keys by an older
coherent copy.

Complete rollback detection requires a monotonic anchor outside the rollback
domain. A virtual TPM controlled by the same hostile VM host is not independent
of that host. A counter alone also does not automatically bind the intended
state commitment unless the selected anchor protocol proves that binding.

Networklessness prevents direct network access by the guest or portable
runtime. It does not prevent a hostile host, firmware, peripheral, or human
from observing or modifying the endpoint.

## 4. Protocol Invariants

### COMPOSER-INV-01: No network interface

A conforming Composer has no network adapter, route, network namespace access,
socket activation, proxy, update proxy, loopback service, HTTP server, RPC
server, or plugin listener. A convenience mode with networking is not a FOG
Composer profile.

### COMPOSER-INV-02: One active mutable instance

One Composer identity vault has exactly one active mutable instance. Copying a
vault, VM private volume, database, USB state partition, or live backup does
not create a second device. Any suspected clone freezes affected ratchets,
capabilities, prekeys, outboxes, and monotonic state.

### COMPOSER-INV-03: Random data keys, human unlock

Bulk state is encrypted under random vault and object keys. A passphrase or
recovery phrase is processed only by the profile's reviewed memory-hard KDF to
unlock or rewrap random key material. It is never used directly as an AEAD
key, identity key, ratchet seed, storage capability, or backup key.

### COMPOSER-INV-04: Every sensitive object is authenticated

Identity, contact, draft, message, ratchet, capability, outbox, inbox,
deduplication, PKI monotonic, recovery, and update state has object-level
authenticated encryption or an equally reviewed authenticated container.
Whole-volume encryption is defense in depth and is not accepted as the sole
object-integrity control.

### COMPOSER-INV-05: Persist and anchor before effect

A security-critical transition is not externally exportable and its plaintext
is not renderable until the complete local transaction is durable. Where the
profile claims full rollback detection, the corresponding external monotonic
anchor transition must also be durable before export or rendering.

### COMPOSER-INV-06: Local chain is not full anti-rollback

Documentation and UI MUST distinguish local consistency verification from
independent monotonic anchoring. A self-contained vault without an external
anchor MUST NOT claim detection of a complete coherent rollback.

### COMPOSER-INV-07: Every import is hostile

Filename, label, QR presentation, media filesystem, MIME type, transport
checksum, FEC result, relay origin, and operator statement confer no
authenticity. Complete bounded parsing and the owning inner cryptographic
verification occur before state transition or rendering.

### COMPOSER-INV-08: Export contains committed opaque work only

An export bundle contains only already committed public objects or opaque
protocol work. It never contains message plaintext, drafts, identity private
keys, contact labels, ratchet state, capability roots, database keys, backup
keys, crash diagnostics, or a long-term Composer signature visible to the
relay.

### COMPOSER-INV-09: Transfer signatures do not create a public identity

FOG does not sign relay-facing bundles with a long-term user or Composer key.
Each inner object supplies its owning authentication. A local transfer-pairing
authenticator MAY reject random injection but does not replace inner
verification and does not become a remote network identity.

### COMPOSER-INV-10: Recovery never silently resumes live state

An identity recovery package can preserve explicitly allowed long-term
identity and contact verification material. Restored live ratchets,
capability streams, prekeys, reply tokens, outboxes, and deduplication windows
remain frozen. They are replaced through authenticated recovery transitions,
not resumed from a stale snapshot.

### COMPOSER-INV-11: Update verification is offline and monotonic

An update installs only after threshold signature, metadata chain, target
hash, target length, platform, compatibility, expiry, version, and rollback
floor validation. No online fetch, local administrator override, unsigned
emergency image, or boot failure authorizes a downgrade.

### COMPOSER-INV-12: Immutable runtime image

The booted operating-system and Composer image are read-only and verified by a
root authenticated outside that mutable image. Writable application state,
temporary data, logs, and update staging cannot replace executable content.

### COMPOSER-INV-13: No active imported content

Initial native applications render bounded plain text and fixed local UI
objects only. HTML, scripts, macros, fonts, office files, PDFs, media codecs,
shell commands, desktop launchers, and automatic external resource loading are
not valid message content.

### COMPOSER-INV-14: High-assurance paths are physically directional

The high-assurance export and import paths use separate transmit-only and
receive-only mechanisms. A removable device alternated between online and
offline systems is a named lower-assurance profile, never an invisible
fallback.

### COMPOSER-INV-15: No secret-bearing diagnostics

Logs, metrics, crash dumps, support bundles, command arguments, environment
variables, shell history, swap, hibernation, thumbnails, previews, clipboard,
and generic desktop indexes contain no Composer secrets or plaintext.

### COMPOSER-INV-16: No runtime extension mechanism

The Composer loads no third-party plugin, interpreted script, external
renderer, generic parser, dynamic protocol module, or operator-selected crypto
provider. New functionality requires a reviewed release and an authenticated
profile transition.

## 5. Deployment Profiles

### 5.1 Common profile

Every Composer profile MUST:

- boot an authenticated read-only software image;
- omit or disable all network and radio devices and drivers;
- use one dedicated authenticated encrypted mutable vault;
- separate import quarantine and export spool from active vault state;
- disable swap, hibernation, core dumps, automatic crash reporting, previews,
  indexing, and host clipboard integration;
- mount no internal disk or general removable filesystem automatically;
- expose only the minimum display, human input, import, export, state, and
  optional monotonic-anchor devices;
- enforce the exact bundle profiles, limits, and direction allowlists;
- require explicit human unlock and explicit update or recovery ceremonies;
- show the current assurance profile and lost assumptions locally.

### 5.2 MicroVM profile

The MicroVM definition contains no virtual NIC. Network absence is enforced at
the hypervisor configuration, guest kernel configuration, process sandbox,
and conformance-test levels.

Host integration is limited to:

- a minimal display path;
- explicit keyboard and pointing input;
- one bounded import data channel;
- one separately authorized bounded export data channel;
- one dedicated mutable state block device;
- an optional external monotonic-anchor interface.

Shared directories, host filesystem mounts, arbitrary qrexec, drag-and-drop,
clipboard, audio, camera, USB passthrough, generic guest agents, shell
services, and bidirectional device forwarding are forbidden.

The host and hypervisor remain inside the endpoint trust assumption. A
MicroVM profile can reduce accidental network exposure and contain some
application failures, but cannot protect unlocked memory or execution from a
host that can inspect or replace the guest.

The Qubes candidate uses a dedicated no-NetVM qube and two exact qrexec
services with fixed direction and byte bounds. General qrexec command
execution, file-copy services, URL opening, clipboard, and update proxy access
remain denied. Qubes is an integration candidate, not a runtime dependency or
an automatic security claim.

### 5.3 Portable profile

The Portable profile boots signed immutable media on a physically offline
computer. Its kernel and initramfs omit network, Bluetooth, cellular, NFC,
Thunderbolt networking, and unnecessary radio drivers. Firmware setup and
physical switches disable available radios where supported.

It MUST:

- verify the bootloader, kernel, initramfs, command line, root-image digest,
  and Composer release identity before vault unlock;
- use a read-only verified root image and a separate encrypted mutable state
  partition;
- refuse automatic internal-disk, network-share, and foreign-filesystem
  mounting;
- use dedicated receive-only and transmit-only transfer devices in its
  high-assurance form;
- keep Composer state media away from online machines;
- warn locally when Secure Boot, measured boot, immutable-root verification,
  external anchoring, or physical directionality is absent.

Portable means the signed system and encrypted state can be carried. It does
not mean the same active state may be cloned or used concurrently. A profile
that binds rollback protection to one machine TPM is machine-bound even if its
boot media is removable.

### 5.4 Portable shuttle profile

`PORTABLE_SHUTTLE` permits one explicitly labeled removable transfer medium to
move opaque bundles between online and offline systems. It is lower assurance
because the online system can attack the medium controller, filesystem, and
subsequent offline parser and because the medium provides a physical return
channel.

This profile still requires the fixed Composer bundle parser, separate import
quarantine, no automatic execution, no general file browsing, and complete
inner authentication. It MUST NOT inherit the high-assurance simplex or
peripheral-compromise claim.

### 5.5 Claim matrix

| Property | MicroVM | Portable high assurance | Portable shuttle |
| --- | --- | --- | --- |
| Composer process has no network | required | required | required |
| Host compromise protection | not claimed | not applicable while dedicated offline hardware is honest | not claimed for online transfer host |
| Read-only verified system image | required | required | required |
| Separate directional transfer hardware | profile-dependent | required | absent by definition |
| Complete rollback detection | only with an anchor outside the hostile host | only with independent anchor | only with independent anchor |
| Physical peripheral isolation | host-dependent | required and measured | weakened |
| Endpoint compromise protection while unlocked | not claimed | not claimed | not claimed |

## 6. Process and Module Architecture

### 6.1 Security domains

The Composer image contains these local domains:

1. `fog-compose`: the only process that unlocks vault keys, performs protocol
   state transitions, and renders authenticated plaintext;
2. import decoder: an unprivileged sandbox that reads one raw transfer stream,
   validates only outer framing and limits, and writes one quarantine object;
3. export encoder: an unprivileged sandbox that reads one already sealed
   opaque export and drives one transmit-only backend;
4. update verifier: a maintenance environment that has release roots and
   inactive image access but no unlocked Composer vault;
5. optional anchor adapter: a minimal process or device interface that exposes
   only the profile's monotonic prepare, advance, and read operations.

The import decoder does not receive vault keys, identity state, contact state,
message plaintext, network configuration, a shell, or writable executable
paths. Its output remains untrusted when `fog-compose` opens it.

The export encoder cannot query the vault or create new protocol work. It can
read only one immutable export spool item selected by `fog-compose` and cannot
write to import quarantine.

### 6.2 Internal modules

Inside the `fog-compose` trust domain, responsibilities remain explicit:

```text
ui
  -> native applications
     -> messaging and storage coordinators
        -> transaction service
           -> encrypted vault

import coordinator -> protocol verifiers -> transaction service
export coordinator -> committed protocol outbox -> export spool
PKI verifier -------^                         |
anchor coordinator ---------------------------^
```

The initial implementation SHOULD use modules named by responsibility:

- `composer/vault`: key hierarchy, encrypted objects, schema, transactions;
- `composer/anchor`: state commitments and monotonic-anchor protocol;
- `composer/import`: bundle validation, quarantine, deduplication, dispatch;
- `composer/export`: committed selection, sealing, spool lifecycle;
- `composer/update`: trusted metadata and installed-version state;
- `composer/recovery`: recovery package creation and restore freeze;
- `composer/ui`: safe presentation and explicit user decisions;
- `apps/drop`, `apps/mailbox`, and `apps/im`: native state machines only.

Protocol modules do not import UI, filesystem, database, qrexec, removable
media, or platform code. Platform adapters do not implement messaging,
storage, PKI, or cryptographic state transitions.

### 6.3 What not to split

The initial implementation does not create:

- separate network services for native applications;
- one database per application;
- a generic plugin host or IPC bus;
- a background indexing or search service with plaintext access;
- a universal crypto, filesystem, archive, or document adapter;
- concurrent writable Composer processes.

One transaction owner and one encrypted database simplify the required
cross-layer atomic commits. Process separation is used only where it removes
raw transfer or update parsing from the vault-bearing process.

## 7. Boot and Runtime Hardening

### 7.1 Verified immutable image

The profile authenticates the complete boot path and one immutable root-image
digest. The Linux candidate uses a signed boot artifact and `dm-verity` for
read-only block verification. The authenticated root digest must be inside the
signed boot chain, not supplied by mutable kernel arguments or the state
volume.

Verification failure stops before vault unlock. An integrity error after boot
locks the vault, produces no export, and enters recovery. Ignore-corruption and
continue-on-verification-failure modes are forbidden.

### 7.2 Writable mounts

The runtime permits only:

- the dedicated encrypted state volume;
- a bounded encrypted or memory-backed import quarantine;
- a bounded export spool containing opaque committed bundles;
- bounded memory-backed temporary directories;
- explicit update staging only in maintenance mode.

Executable, setuid, device, and interpreter behavior is disabled on mutable
mounts where the platform supports it. Imported filenames never become local
paths. The Composer does not traverse a foreign filesystem supplied by a
transfer medium.

### 7.3 Runtime controls

The active Composer profile requires:

- no swap or hibernation;
- disabled core dumps and process-memory crash capture;
- locked-down debugging, tracing, performance counters, and ptrace;
- no shell or package manager in the user session;
- no automatic login or vault unlock;
- strict process, file-descriptor, memory, CPU, and disk quotas;
- default-deny device and syscall policy, including network socket creation;
- memory-backed plaintext staging with bounded lifetime;
- explicit lock on suspend, display loss, anchor loss, or integrity fault.

Memory locking and explicit zeroization are best-effort implementation
controls. They do not prove that compilers, kernels, caches, firmware, DMA,
hibernation remnants, or physical memory retained no copy.

## 8. Vault and Key Hierarchy

### 8.1 Vault layers

The Composer uses both:

1. full-volume encryption to hide filesystem metadata, database pages,
   journals, temporary files, and free space while powered off;
2. object-level authenticated encryption for every sensitive logical record.

The Linux candidate evaluates LUKS2 for layer 1. It does not rely on ordinary
sector encryption to authenticate logical records. Any LUKS2 integrity mode
requires separate maturity, performance, recovery, and power-failure review.

### 8.2 Key hierarchy

The minimum hierarchy is:

```text
human unlock secret
  -> profile-fixed memory-hard KDF
     -> unlock KEK
        -> unwrap random vault key
           -> profile-fixed KDF/exporter
              -> identity-object key epoch
              -> contact-object key epoch
              -> messaging-state key epoch
              -> storage-state key epoch
              -> PKI-state key epoch
              -> draft/content key epoch
              -> outbox/import/export key epoch
              -> local-state-authentication key epoch
```

The backup or recovery key hierarchy is generated independently. It never
derives from the live vault key, a contact root, message ratchet, storage
capability, transfer-pairing key, release key, or monotonic-anchor key.

The unlock KDF stores its algorithm identifier, salt, memory cost, time cost,
parallelism, and output length in authenticated keyslot metadata. Parameters
are benchmarked per supported hardware class and may be raised through a
versioned rewrap without reencrypting all logical objects.

The deployment profile states whether volume unlock and object-vault unlock
use one human secret or separate factors. If one human secret is used, each
layer has independent salts, context, KDF output, and wrapping key. Raw keys
are never reused between the LUKS2 and object-vault layers.

### 8.3 Keyslot rules

A keyslot wraps only random vault or recovery key material. Adding, removing,
or changing a passphrase is an authenticated transaction. The previous slot
remains in the live header only until the new slot and replacement header
backup are durably verified.

A memory-hard KDF raises guessing cost but does not turn a weak passphrase into
a high-entropy secret. The UI requires a profile-appropriate secret and states
the offline-guessing risk.

Removing a LUKS2 keyslot does not revoke an old passphrase against an attacker
who retained an earlier header backup containing that slot and the same volume
key. True revocation against copied old headers requires a reviewed full
volume-key and vault-key rotation, reencrypted data, retirement of old object
keys, and controlled destruction of obsolete headers and media.

Unlock secrets are accepted only through the trusted local UI or a narrowly
specified hardware-token protocol. They never appear in command arguments,
environment variables, files in the export bundle, logs, clipboard, or shell
input history.

Failed unlock attempts have bounded memory and CPU cost. The local UI may
apply a coarse delay, but denial-of-service resistance cannot depend on an
attacker-writable on-disk failure counter.

### 8.4 Object envelope

Every encrypted logical object has a canonical profile-fixed header containing
at least:

```text
[
  vault_format_version,
  vault_profile_id,
  network_id,
  composer_instance_id,
  object_type,
  object_id,
  object_generation,
  transaction_generation,
  key_epoch,
  plaintext_length,
  padded_length,
  nonce,
  ciphertext
]
```

All fields preceding `ciphertext` are authenticated associated data. The
profile fixes lengths, encoding, nonce construction, padding classes, AEAD,
KDF, maximum plaintext, and key epoch. Unknown fields, alternate encodings,
nonce reuse, invalid padding, counter wrap, or authentication failure reject
the object.

`composer_instance_id` is a random local domain separator. It is never placed
in relay-facing bundles, contact cards, messages, PKI, storage records, public
logs, or release metadata.

### 8.5 Object classes

The vault separates at least these object classes and key purposes:

| Class | Examples | Restore rule |
| --- | --- | --- |
| Identity | contact roots, handshake identities | only through identity recovery policy |
| Contact | public roots, fingerprints, local labels, verification decisions | public and local metadata may be recovered |
| Messaging live state | ratchets, prekeys, skipped keys, ACK and dedup windows | stale copy never resumes |
| Storage live state | capabilities, indexes, tombstones, receipts, retry generations | stale copy never resumes |
| Content | drafts, inbox, sent plaintext, reassembly | optional local retention, not required for identity recovery |
| Protocol outbox | immutable envelopes, boxes, packets, reply material | exact live instance only |
| PKI state | genesis root, highest consensus, log checkpoint, manifests | monotonic verification required |
| Release state | trusted roots, metadata versions, installed target, rollback floor | monotonic verification required |
| Local control | transaction journal, state commitment, anchor receipt | never exported or identity-recovered as live state |

### 8.6 Candidate primitives

`FOG-COMPOSER-CANDIDATE-LINUX-VAULT-1` evaluates Argon2id for unlock key
derivation and XChaCha20-Poly1305 for object protection through maintained
reviewed libraries. The candidate uses random nonces from the OS CSPRNG and
purpose-separated KDF outputs.

No primitive, parameter, library, ABI, database, or vault profile becomes
active merely because it appears here. Activation requires exact versions,
byte-level vectors, nonce analysis, crash tests, benchmarks, dependency
review, and independent security review.

## 9. Transactional State Model

### 9.1 One transaction owner

Exactly one `fog-compose` process opens the mutable vault for writing. It uses
one transaction engine capable of atomic durable commit across every logical
object participating in a protocol transition.

Messaging ratchet state, storage capability state, outbox objects, PKI
monotonic state, application queue state, import deduplication, and export
eligibility MUST NOT be committed through independent databases or eventually
consistent workers.

### 9.2 State commitment

Every security-critical transaction produces a canonical `StateCommitment`:

```text
[
  commitment_format_version,
  vault_profile_id,
  network_id,
  composer_instance_id,
  transaction_generation,
  previous_commitment,
  encrypted_catalog_root,
  highest_consensus_epoch,
  consensus_hash,
  transparency_tree_size,
  transparency_root_hash,
  release_root_version,
  installed_release_version,
  import_generation,
  export_generation,
  transaction_class
]
```

The commitment uses a profile-fixed authenticated hash or MAC construction.
It contains no plaintext, contact identifier, message identifier, capability,
box ID, or application type. It remains local except for a private external
anchor that is explicitly part of the same Composer trust domain.

### 9.3 Unanchored commit

An unanchored profile:

1. stages all new encrypted objects and the next catalog separately;
2. validates cross-object invariants and resource bounds;
3. writes and syncs the transaction journal;
4. atomically selects the new catalog and state commitment;
5. syncs the database and containing filesystem metadata;
6. only then releases export eligibility or authenticated plaintext.

This detects ordinary partial writes and local history discontinuity. A
complete older vault copy containing its matching keys and journal can still
pass.

### 9.4 Externally anchored commit

An anchored profile uses a prepared generation so the external effect never
precedes the anchor:

1. retain generation `N` as the active catalog;
2. stage generation `N+1`, its encrypted objects, undo information, and exact
   commitment in a durable `PREPARED` namespace;
3. sync the complete prepared namespace without exposing its work;
4. ask the independent anchor to advance from the exact accepted generation
   and commitment to `N+1` and the new commitment;
5. receive and verify one anchor receipt bound to the instance, generations,
   old commitment, and new commitment;
6. atomically select `N+1` as active and persist the receipt;
7. sync the active selector and journal;
8. only then export work or render newly accepted plaintext.

The anchor operation is compare-and-advance, not an unchecked write. It must
reject a wrong old generation, wrong old commitment, repeated alternate next
commitment, counter wrap, unauthorized reset, or another instance.
An exact retry of an already completed compare-and-advance is idempotent and
returns the same authenticated successor state without another increment.

### 9.5 Crash reconciliation

At startup:

- anchor equals latest finalized local commitment: open normally;
- anchor equals the one exact durable prepared successor: finalize it before
  any other operation;
- anchor remains at the finalized predecessor and no external effect was
  released: discard the prepared successor using its durable staging state;
- anchor is ahead without the exact prepared successor: enter
  `RECOVERY_REQUIRED`;
- anchor has the same generation but another commitment: enter
  `CLONE_OR_TAMPER_DETECTED`;
- local state is ahead of, behind, or unrelated to the anchor outside the
  permitted one-step reconciliation: enter `RECOVERY_REQUIRED`.

No user confirmation, clock change, file rename, or import bundle overrides a
mismatch.

### 9.6 Anchor assurance levels

The registry defines:

- `LOCAL_CHAIN`: no external anchor and no complete-rollback claim;
- `HOST_BOUND_ANCHOR`: useful against accidental snapshot restore but not a
  hostile MicroVM host controlling the anchor;
- `INDEPENDENT_ANCHOR`: a separate hardware or physically controlled state
  that is outside the vault and host rollback domain.

A TPM 2.0 NV counter is only a candidate building block. The active anchor
profile must prove reset authorization, endurance, atomic crash behavior,
binding between generation and commitment, device replacement, backup,
recovery, and denial-of-service behavior. A bare increment command is not by
itself the FOG anchor protocol.

The anchor has no network interface and receives only its private local
instance handle, generation numbers, and opaque fixed-length commitments. It
does not receive the commitment body, object catalog, contact, message,
capability, application type, plaintext, or vault key. It necessarily observes
local anchor-operation count and timing, which remains an endpoint metadata
risk.

### 9.7 Database candidate

The Linux candidate evaluates one SQLite database with one writer and an exact
durability profile. The selected journal mode, synchronization level,
filesystem, block device, locking behavior, power-loss assumptions, and backup
API become immutable profile inputs.

Copying an SQLite main file while a transaction or hot journal exists is not a
backup. The implementation uses the reviewed backup API or a fully quiescent
profile-specific snapshot and preserves every required journal and metadata
file. Database integrity checks do not replace object authentication or an
external monotonic anchor.

## 10. Composer Transfer Bundle

### 10.1 Fixed outer header

Every Composer bundle starts with this exact 128-byte header:

```text
offset  length  field
0       8       magic
8       2       bundle_format_version
10      1       bundle_kind
11      1       flags
12      4       bundle_profile_id
16      32      network_id
48      32      bundle_nonce
80      8       payload_length
88      4       record_count
92      4       record_table_length
96      32      payload_digest
```

`magic`, version, kind, flags, profile, counts, and lengths have one canonical
encoding. `bundle_nonce` contains 256 CSPRNG bits and is unique to the bundle;
it is not an identity or protocol replay token. `payload_digest` provides
bounded corruption detection and canonical deduplication only. It does not
authenticate the producer.

### 10.2 Fixed record header

Each record starts with this exact 48-byte header:

```text
offset  length  field
0       2       record_type
2       2       record_version
4       4       flags
8       8       actual_length
16      8       padded_length
24      16      record_id
40      8       reserved
```

The body contains `actual_length` bytes followed by zero padding to
`padded_length`. The record table lists exact ordered offsets and types before
any body is dispatched. `record_id` is random and bundle-local. Reserved bits,
duplicate IDs, overlap, gaps outside canonical padding, non-zero padding,
integer overflow, inconsistent lengths, and trailing data reject the complete
bundle.

Bundles contain no nested bundle, archive, directory, symlink, device node,
filesystem image, filename, URI, MIME type, compression stream, or executable
metadata.

### 10.3 Bundle kinds

The registry defines separate allowlists for:

- `RELAY_EXPORT`: committed KEMSphinx submissions and bounded public relay
  scheduling hints already authorized by the Composer;
- `RELAY_IMPORT`: complete signed PKI objects, opaque KEMSphinx replies,
  conflict evidence, and bounded public relay state;
- `CONTACT_EXPORT` and `CONTACT_IMPORT`: one bounded contact card, voucher, or
  authenticated contact transition;
- `RECOVERY_EXPORT` and `RECOVERY_IMPORT`: one encrypted recovery package and
  its public format metadata;
- `UPDATE_IMPORT`: signed release metadata and exact target artifacts handled
  only by the maintenance environment.

Wrong-direction records reject the bundle. `UPDATE_IMPORT` is never parsed by
the unlocked ordinary Composer process, and ordinary relay or contact bundles
cannot contain an executable target.

### 10.4 Absolute version-1 limits

These are parser ceilings, not recommended operational batch sizes:

| Item | Absolute limit |
| --- | --- |
| Outer header | exactly 128 bytes |
| Record header | exactly 48 bytes |
| Nesting | forbidden |
| Relay bundle | 64 MiB |
| Relay records | 2048 |
| One relay record | 256 KiB |
| Contact bundle | 1 MiB |
| Contact records | 64 |
| Recovery bundle | 64 MiB |
| Recovery records | 256 |
| Update metadata | 64 MiB |
| Complete update bundle | 16 GiB, streamed only |
| Update records | 4096 |
| Unknown record type or flag | reject complete bundle |

FOG-SX and deployment profiles set lower transport and memory limits. An
update target is streamed to an inactive verified image and never allocated as
one memory buffer.

### 10.5 Authentication ownership

The outer bundle is a transport container. Authentication remains owned by
each embedded protocol:

- PKI objects use authority signatures and monotonic consensus rules;
- KEMSphinx replies use their packet, SURB, token, storage, and message
  authentication;
- contact objects use the exact contact-root or voucher signature rules;
- recovery objects use the recovery envelope and separately held key;
- updates use the release metadata threshold and target hashes.

A Composer-relay pairing key MAY authenticate a local bundle envelope to
reduce random injection and accidental cross-user delivery. The relay is
still untrusted, a pairing MAC is never accepted as message or PKI
authenticity, and the pairing handle is not exported into the FOG network.

## 11. Import Processing

### 11.1 Quarantine

Raw input first enters a new size-limited quarantine object created with an
unpredictable local name and exclusive creation. The decoder streams the
input, enforces the outer limit, calculates the digest, syncs the completed
object, and closes the input before `fog-compose` can open it.

The decoder never extracts files or follows a path supplied by input. Partial,
oversized, timed-out, or multiply opened inputs are deleted without entering
the vault.

### 11.2 Validation order

The Composer:

1. opens the quarantine object read-only without following links;
2. validates exact total size and the 128-byte header;
3. validates bundle direction, network, profile, kind, count, and limits;
4. validates the complete record table and non-overlap before allocation;
5. streams every record through its owning strict parser into staged state;
6. verifies every inner signature, AEAD, hash, token, generation, expiry, and
   monotonic rule required by that record type;
7. compares conflicting complete PKI views and preserves evidence rather than
   merging them;
8. computes all cross-record and cross-protocol state transitions;
9. commits import digest, deduplication, new protocol state, inbox, and any
   resulting outbox through Section 9;
10. only after final commit and required anchor advance, releases plaintext or
    marks resulting work exportable;
11. destroys staged plaintext and expires the quarantine object.

One invalid critical record rejects the complete bundle. The parser does not
continue in order to collect attacker-selected diagnostic detail.

### 11.3 Duplicate and replay handling

The Composer stores a keyed local import identifier derived from the complete
bundle digest and profile. An exact duplicate is idempotent and does not repeat
rendering, ratchet advancement, capability advancement, voucher consumption,
update installation, or recovery.

The bundle identifier is only an outer deduplication aid. Each embedded
protocol still performs its own replay and generation checks. Repacking the
same records into another bundle cannot bypass those checks.

### 11.4 Failure privacy

Detailed failure remains local and bounded. The Composer does not
automatically export a parse error, invalid-contact error, decryption error,
missing-message error, stale-state error, or update-verification oracle.

The UI maps failures to coarse classes such as `INVALID_IMPORT`,
`AUTHENTICATION_FAILED`, `STALE_OR_ROLLED_BACK`, `RESOURCE_LIMIT`,
`RECOVERY_REQUIRED`, and `UNSUPPORTED_PROFILE`. Secret values and attacker
bytes are not copied into diagnostics.

## 12. Export Processing

### 12.1 Export transaction

For every export generation, the Composer:

1. selects only committed eligible outbox objects under the active schedule;
2. validates their protocol profile, lifetime, retry, geometry, and state;
3. generates any fresh KEMSphinx, SURB, route, entry, rendezvous, and reply
   material required for this network transmission;
4. stages the exact immutable bundle, random bundle nonce, record table,
   digest, export generation, and outbox transitions;
5. commits all state and advances the required external anchor;
6. creates a new export spool object with exclusive creation;
7. writes, syncs, seals read-only, and reopens the spool object to verify its
   exact bytes and digest;
8. only then authorizes the export encoder to transmit that one object.

A crash before step 5 creates no exportable bytes. A crash after step 5
recovers the exact committed bundle. A crash during spool creation rebuilds
only those same committed bytes and does not advance a ratchet, capability, or
packet generation again.

### 12.2 Duplicate physical export

Copying or replaying one already sealed bundle can cause duplicate relay
submission. Bundle, packet, courier, storage, and message deduplication remain
required. The Composer never assumes physical transfer occurred merely
because it authorized the encoder.

If the outcome is unknown, later retry creates the fresh outer packet material
required by the owning packet and storage profiles from already committed
inner state. It does not reconstruct an end-to-end message envelope or reuse a
single-use reply secret contrary to those profiles.

### 12.3 Export contents

Relay-facing export MUST NOT contain:

- plaintext, local UI strings, application names, contact labels, drafts, or
  message history;
- long-term user signatures over the bundle, stable Composer instance IDs, or
  vault generations;
- message, session, capability, box, or receipt identifiers outside their
  required opaque cryptographic layer;
- private PKI, release, recovery, backup, state, or transfer keys;
- filesystem paths, usernames, hostnames, locale, timezone, device model, or
  software diagnostics.

Export size class and timing remain observable to the physical transfer path
and blind relay. Cover and scheduling profiles, not the bundle container
alone, govern those metadata claims.

### 12.4 Spool retention

An opaque export spool item remains until one of:

- an explicitly lower-assurance local transfer profile returns an
  authenticated acceptance permitted by that profile;
- a bounded re-export window ends;
- the owning protocol produces authenticated terminal evidence;
- the operation is explicitly cancelled before a forbidden state transition;
- recovery freezes the entire instance.

The high-assurance simplex profile has no automatic receiver acceptance path.
Its Composer therefore relies on bounded spool retention and later owning-
protocol evidence, not an FOG-SX acknowledgment.

Deletion of a spool item never rewinds its protocol state. Sensitive reply
material and ephemeral packet keys follow their shorter owning lifetimes.

## 13. Backup and Recovery

### 13.1 Recovery goals

Composer recovery is designed to preserve the minimum long-term authority
needed to reestablish an identity and verify known contacts. It is not a
transparent snapshot restore and does not promise recovery of undelivered
messages, forward-secret message keys, live storage positions, consumed
prekeys, pending acknowledgments, or current network work.

The default `IdentityRecoveryPackage` MAY contain:

- the FOG network ID and genesis trust-anchor material;
- the long-term pairwise or accountless identity roots explicitly selected
  for recovery;
- contact public roots, verified fingerprints, and verification status;
- encrypted local contact labels when the user includes them;
- release trust roots and minimum accepted release version;
- the latest public PKI checkpoint and consistency metadata as a recovery
  starting point, never as permission to roll backward;
- identity-generation and recovery-package sequence metadata;
- a declaration that every messaging session and storage stream must be
  replaced before use.

The default package MUST NOT contain live ratchets, chain keys, message keys,
skipped keys, one-time prekeys, active storage read or write capabilities,
outbox ciphertexts, SURBs, reply tokens, pending packets, deduplication
windows, transfer-pairing keys, local anchor credentials, or an active
Composer instance ID.

### 13.2 Recovery envelope

The recovery plaintext is one canonical bounded object with an explicit
format version, network, identity set, package sequence, creation release,
key profile, content allowlist, and restore policy. It is padded and
authenticated under a random recovery data key.

That random key is wrapped by a distinct recovery key hierarchy. Recovery key
material is stored separately from the recovery ciphertext. A recovery
passphrase, if supported, uses its own profile-fixed memory-hard KDF, salt, and
parameters and does not reuse the live-vault keyslot or passphrase verifier.

Recovery filenames, QR labels, media labels, and transport checksums are not
authenticated metadata. Every field that affects identity, version, content,
or restore behavior is inside the authenticated envelope.

### 13.3 Recovery export

Recovery creation requires explicit local user confirmation and a dedicated
ceremony outside normal message export. The Composer:

1. validates that the selected identities and contact metadata are eligible;
2. generates a fresh recovery package ID and random data key;
3. constructs and encrypts the exact canonical package;
4. atomically records the package sequence and digest in live state;
5. advances the external anchor when required by the active profile;
6. exports ciphertext and recovery key material through distinct controlled
   paths;
7. verifies one complete test decryption before reporting success;
8. erases transient recovery plaintext and wrapping material.

Normal relay export, contact exchange, and FOG-SX network work MUST NOT carry a
recovery package or recovery key.

### 13.4 Restore

Restore occurs into a fresh verified Composer image and a newly initialized
vault with a new random `composer_instance_id`, vault key, object key epochs,
transfer-pairing keys, and local anchor state.

After verifying and decrypting the package, the new Composer:

- imports the allowed identity roots and contact verification history;
- refuses any recovered PKI, release, or rollback state lower than the trusted
  state embedded in the verified recovery image or independent anchor;
- marks every historical messaging session and storage stream
  `RECOVERY_REQUIRED` or `CLOSED`;
- creates no message, packet, prekey, voucher, read, write, or ACK from restored
  mutable protocol bytes;
- obtains a current PKI view through the full long-offline consistency path;
- verifies the current release chain and rollback floor;
- uses the recovered identity authority to authenticate fresh contact-session
  and storage-stream transitions;
- warns that contacts may need independent fingerprint confirmation when
  compromise, identity change, or ambiguous recovery is suspected.

The old instance is not automatically revoked merely because a new vault was
created. If the old device may still operate, identity compromise and clone
procedures apply and contacts require an authenticated identity transition.

### 13.5 Full-state archives

A routine full copy of a live Composer vault is forbidden as a resumable
backup. A profile MAY create a separately encrypted forensic archive for
disaster analysis, but it is marked `NON_RESUMABLE`, contains no unlock or
anchor key beside its ciphertext, and cannot be opened as an active vault.

Copying a VM private volume, SQLite file, LUKS device, portable state
partition, or suspended memory image is not recovery. Such a copy is clone
evidence and freezes all live state if discovered.

### 13.6 Deletion limits

Deleting an object key or recovery key can make surviving ciphertext
inaccessible under the stated assumptions. It does not prove removal from
RAM, flash translation layers, snapshots, filesystem journals, controller
caches, old media, recipient devices, or adversarial copies.

The UI describes deletion as local best effort with explicit retained-copy
limits. It never reports cryptographic erasure as physical proof.

## 14. Offline Update Verification

### 14.1 Separation of authority

Release authority is separate from user identity, FOG-PKI authority, node,
relay, storage, backup, recovery, and Composer state authority. Runtime images
contain only public release roots and current trusted metadata, never a
release signing key.

An update distributor, relay, mirror, removable medium, QR label, or package
manager is an untrusted transport. It cannot authorize code.

### 14.2 Update candidate

`FOG-COMPOSER-CANDIDATE-UPDATE-TUF-1` evaluates an exact future TUF revision
and maintained client implementation. The candidate uses distinct threshold
roles for root, targets, snapshot, and timestamp metadata, consistent target
hashes and lengths, version monotonicity, expiry, and sequential root
rotation.

The selected release profile MUST pin:

- exact TUF specification and implementation revisions;
- root, targets, snapshot, timestamp, and delegated-role thresholds;
- key algorithms, key IDs, role separation, and offline-key requirements;
- canonical metadata encoding and absolute size limits;
- trusted-time and maximum-clock-uncertainty behavior;
- target naming, architecture, deployment profile, and compatibility fields;
- installed-version, minimum-version, revocation, and rollback-floor rules;
- root rotation, repository recovery, and emergency response ceremonies.

TUF metadata transport security is not release authenticity. A valid older
but unexpired view is still subject to the Composer's highest accepted
versions, rollback floor, and freeze policy.

### 14.3 Update bundle validation

The maintenance environment:

1. verifies the fixed Composer `UPDATE_IMPORT` framing and streaming limits;
2. starts from the currently trusted release root stored in monotonic state;
3. applies every intermediate root version sequentially with the required old
   and new thresholds;
4. verifies timestamp, snapshot, targets, delegations, versions, expiry,
   hashes, lengths, and consistent-snapshot rules;
5. rejects metadata below any locally trusted version or rollback floor;
6. verifies target architecture, deployment profile, state-schema range,
   boot profile, and hardware requirements;
7. streams each target to inactive storage while hashing and enforcing its
   exact declared length;
8. verifies the complete inactive image and its signed boot and root digest;
9. records a signed-metadata-bound prepared boot transition without opening
   the Composer vault;
10. activates the new boot slot for one bounded trial;
11. lets only the verified target image, after explicit user unlock, validate
    the prepared transition, migrate state if required, commit the installed
    release and rollback floor through Section 9, and mark boot success.

No target is executed, mounted writable, or parsed by its own code before its
owning metadata, hash, and length have been verified.

### 14.4 Trusted time and freeze

Update expiry requires a trusted update-start time with a stated uncertainty.
File modification times, removable-media clocks, relay timestamps, target
timestamps, HTTP headers, and unauthenticated user input are not trusted time.

If time uncertainty prevents expiry validation, the Composer stops update
installation and invokes a separately authenticated time-recovery ceremony.
It does not disable expiry. Highest accepted metadata versions reduce rollback
risk but do not independently prove that a distributor has supplied the
latest release.

### 14.5 A/B image and boot failure

The Portable candidate uses inactive-image installation and a bounded boot
trial. Automatic fallback is permitted only to an image still above the
authenticated rollback floor and not explicitly revoked.

If the new image and the prior image are both unauthorized or incompatible,
the system enters signed recovery media rather than booting an older vulnerable
release. A boot-success marker is not trusted if it can be rolled back without
the profile's monotonic control.

### 14.6 State migration

A release declares the exact source and target vault schema range. Migration:

- runs in a dedicated mode of the verified target image after explicit user
  unlock; the maintenance update verifier never receives vault keys;
- runs offline with network and ordinary import/export disabled;
- opens the old state through the old reviewed reader and writes a separately
  staged new catalog;
- authenticates and validates every source object before transformation;
- rejects unknown-critical object types and counter or size overflow;
- preserves no old live-state copy as a resumable second Composer;
- commits the new schema and release version through Section 9;
- cannot be reversed after external effect or anchored finalization.

If migration fails before finalization, the old still-authorized image and
state remain active. If the anchor or state has advanced but reconciliation
cannot prove the exact prepared migration, recovery is required.

### 14.7 Emergency response

Emergency metadata may revoke a target or raise the minimum release version,
but uses the normal authenticated root and delegated authority rules. There is
no unsigned rescue build, universal operator password, hidden update URL,
network bypass, or local force-install flag.

## 15. PKI, Time, and Monotonic Consumer State

### 15.1 PKI import

The Composer persists the complete trusted PKI consumer state required by
`FOG-PKI` in the same security-critical transaction as any route, profile,
message, or storage work that first depends on it.

It accepts a newer view only after validating:

- network and trust-anchor identity;
- canonical full consensus and independent authority quorum;
- sequential authority-set transitions;
- epoch, validity, freshness, and clock uncertainty;
- archive inclusion and append-only consistency from the stored checkpoint;
- active packet, wire, messaging, storage, entry, cover, and Composer profiles;
- complete current storage manifests and key windows;
- split-view, equivocation, and conflict evidence.

A bundle containing multiple valid conflicting views freezes affected work and
preserves evidence. It does not select the numerically highest view or merge
descriptors.

### 15.2 Offline time

The Composer maintains separate notions of:

- monotonic process time for one boot session;
- authenticated protocol epoch and version progression;
- profile-approved civil time with explicit uncertainty;
- release-metadata update-start time.

An RTC can be a candidate input but is not trusted merely because it is
battery-backed. Clock rollback, implausible jump, uncertainty overflow, or
disagreement with authenticated epoch bounds stops new time-sensitive work.

The UI permits a user to report the clock problem, not to declare an arbitrary
time valid. Exact offline time recovery remains a profile activation gate.

## 16. Native Applications and Safe Rendering

### 16.1 Common application boundary

`fog-drop`, `fog-mailbox`, and `fog-im` are modules inside the Composer trust
domain. They receive authenticated bounded application frames only after
messaging, storage, import, and state commit. They do not parse raw transfer,
KEMSphinx, storage, or ratchet bytes.

Applications cannot select packet geometry, route length, storage replica
count, retry timing, cover class, cryptographic primitive, update channel, or
external renderer.

### 16.2 Initial content profile

The initial content profile supports bounded UTF-8 plain text with canonical
normalization rules and a small fixed set of non-active local presentation
attributes. It rejects invalid UTF-8, control-character abuse, bidirectional
text policy violations, oversized grapheme sequences, unknown critical
fields, and active content.

No content triggers:

- network or filesystem access;
- contact creation or verification change;
- command execution, URL opening, media decoding, font installation, or
  external process launch;
- automatic reply, read receipt, typing indicator, preview, or notification
  containing plaintext outside the unlocked Composer;
- import, update, recovery, profile, or key transition.

### 16.3 Local UI status

The UI distinguishes at least:

- locally queued but not exported;
- exported with unknown relay outcome;
- courier accepted, replica quorum committed, and degraded storage;
- authenticated recipient Composer commit acknowledgment;
- expired or uncertain delivery;
- contact fingerprint verified, unverified, changed, or recovery pending;
- PKI fresh, stale but valid, expired, split, or recovery required;
- vault locally consistent, externally anchored, unanchored, or mismatched;
- installed release verified, update available, revoked, or time-blocked.

It never labels courier acceptance as delivery, replica commit as human read,
encryption as anonymity, networklessness as host integrity, or local hash-chain
verification as complete anti-rollback.

### 16.4 Plaintext lifetime

Plaintext is decrypted only for the active operation or visible bounded view.
Search indexes, caches, undo history, previews, clipboard, recent-file lists,
accessibility bridges, screenshots, and notifications are disabled unless a
later profile explicitly bounds and protects them.

Lock, suspend, inactivity timeout, display detachment, update mode, integrity
failure, anchor failure, or fatal parser fault closes views and erases active
keys and staging memory on a best-effort basis.

## 17. State and Key Lifecycle

| Material | Owner | Persistence | Transition or destruction |
| --- | --- | --- | --- |
| Human unlock secret | user | never stored as plaintext | replace through authenticated keyslot rewrap |
| Unlock KDF output or KEK | Composer unlock transaction | memory only | erase after vault key unwrap or lock |
| Random vault key | one Composer instance | wrapped keyslot plus unlocked memory | rotate by profile; never export or identity-recover |
| Object key epoch | Composer vault | wrapped or derived encrypted state | rotate by object class; retain only for live objects |
| Local state-authentication key | Composer vault | one instance | erase on instance retirement; never use for backup |
| Composer instance ID | Composer vault | lifetime of one active instance | replace on restore or reinitialization; never export |
| State commitment chain | Composer vault | permanent for one instance | preserve until explicit retirement |
| External anchor key or handle | independent anchor domain | profile-specific monotonic lifetime | controlled replacement requires recovery ceremony |
| Import quarantine bytes | sandbox and Composer | one bounded import | delete after commit or rejection |
| Import dedup identifier | Composer vault | maximum bundle replay window | expire by authenticated profile, not input time |
| Export spool ciphertext | export encoder and Composer | bounded transfer or retry window | delete without rewinding protocol state |
| Transfer-pairing key | Composer and local blind relay boundary | local pairing generation | rotate on pairing compromise; never authenticate messages |
| Recovery data key | recovery transaction | package creation or restore only | erase after verified wrap or unwrap |
| Recovery wrapping key | user recovery domain | separate from package ciphertext | rotate by creating and testing a new package |
| Identity root in recovery | encrypted recovery package | explicit identity lifetime | revoke or replace through identity protocol after compromise |
| Live ratchet and capability state | current Composer instance only | encrypted mutable state | freeze on restore, clone, rollback, or compromise |
| Release trust roots | Composer maintenance state | sequential root lifetime | rotate only through authenticated old and new thresholds |
| Installed-release floor | Composer and external anchor where claimed | monotonic installation lifetime | only increase through authenticated metadata |
| Temporary plaintext and message keys | Composer process | one transaction or view | best-effort erase immediately after owning commit or close |

Purpose-separated keys MUST NOT be converted, copied, or relabeled to satisfy a
different row.

## 18. Failure and Recovery States

### 18.1 Minimum vault states

The Composer state machine includes:

- `UNINITIALIZED`: no identity or mutable vault exists;
- `LOCKED`: image verified, vault keys absent from active memory;
- `UNLOCKING`: bounded keyslot and state verification in progress;
- `READY_UNANCHORED`: locally consistent, no complete-rollback claim;
- `READY_ANCHORED`: local and independent anchor state match;
- `IMPORT_STAGED`: one bounded import is parsed but has no effect;
- `EXPORT_PREPARED`: exact export state is durable but not yet released;
- `UPDATE_STAGED`: inactive release verified but not activated;
- `RECOVERY_REQUIRED`: ordinary protocol actions forbidden;
- `CLONE_OR_TAMPER_DETECTED`: local and anchor history conflict;
- `LOCKDOWN`: integrity, runtime, or secret-lifetime policy failed;
- `RETIRED`: no further use of instance keys or live protocol state.

### 18.2 Failure table

| Condition | Required response |
| --- | --- |
| Boot signature or root-image verification failure | stop before vault unlock |
| Vault keyslot authentication failure | generic local failure, no object parsing |
| Object AEAD or canonical encoding failure | quarantine object or vault, no partial use |
| Database integrity or durability uncertainty | lock and enter authenticated recovery |
| Local commitment-chain break | freeze all mutable protocol state |
| External anchor mismatch | `RECOVERY_REQUIRED` or `CLONE_OR_TAMPER_DETECTED` |
| Missing anchor in an anchor-required profile | no export, render, or state advancement |
| Malformed or oversized import | reject complete bundle and delete quarantine |
| One invalid critical bundle record | reject complete bundle |
| Duplicate valid import | idempotent success without repeated effect |
| Export spool partial write | rebuild exact committed bytes or discard partial file |
| PKI split or consistency failure | freeze new network work and preserve evidence |
| Clock uncertainty outside profile | stop time-sensitive PKI and update acceptance |
| Update signature, expiry, hash, length, or version failure | retain verified non-revoked version or stop |
| Migration failure before finalization | keep old still-authorized state and image |
| Migration or anchor ambiguity after advance | recovery required, no downgrade |
| Recovery package failure | no identity import and no detailed oracle |
| Lock, suspend, display loss, or runtime policy failure | erase active keys best effort and stop |

User-visible diagnostics remain local, coarse, and free of attacker-controlled
secret bytes. A failure never opens networking, mounts an internal disk,
enables a general shell, skips verification, accepts an older profile, or
exports an automatic error.

## 19. Resource Limits and Abuse Resistance

Every active Composer profile defines lower limits within the absolute bundle
ceilings for:

- vault objects, object bytes, transaction objects, and staged generations;
- identities, contacts, sessions, prekeys, skipped keys, capabilities, and
  storage streams;
- drafts, messages, fragments, reassembly groups, history, and attachments;
- protocol outbox, inbox, deduplication, ACK, receipt, retry, and tombstone
  state;
- quarantine items, bundle bytes, record count, parser depth, and parse time;
- export spool items, bytes, re-export attempts, and retention;
- PKI objects, consensus views, proof nodes, manifests, conflicts, and history;
- update metadata, targets, stream bytes, staging space, and migration work;
- recovery identities, contacts, labels, package bytes, and attempts;
- Argon2 memory, CPU, lanes, attempts, and concurrent KDF calls;
- UI text bytes, graphemes, lines, rendering time, and notification queue;
- anchor operations, prepared generations, reconciliation attempts, and
  device timeouts;
- memory, file descriptors, processes, threads, temporary files, and disk
  reserve.

Limits are enforced before allocation or expensive cryptography where the
owning format permits. Authenticated contacts remain untrusted for resource
purposes. A valid signature or ciphertext does not authorize unbounded local
storage, rendering, KDF work, or notifications.

Disk-full handling preserves the latest finalized catalog and anchor state.
The Composer does not evict security-critical replay, ratchet, capability,
commitment, or rollback state according to least-recently-used behavior. It
stops new work or applies an authenticated retention policy.

## 20. Logging and Local Observability

The default release logs only coarse boot, lock, integrity, capacity, and
failure-class counters needed to operate the local device. Logs are bounded,
stored inside the encrypted vault or volatile memory, and deleted by a fixed
policy.

The Composer MUST NOT log or export:

- plaintext, drafts, rendered content, contact labels, or fingerprints;
- private keys, unlock material, recovery keys, capabilities, or ratchets;
- message, session, box, receipt, packet, SURB, reply, voucher, or bundle
  identifiers;
- routes, replica selection, entry sets, import timing histories, or per-
  contact activity;
- object ciphertext samples, failed attacker input, decrypted fragments, or
  detailed cryptographic errors;
- filesystem paths containing user identity, hostnames, locale, timezone, or
  device serial numbers;
- state commitments or anchor receipts in a generic support bundle.

There is no automatic telemetry, update check, crash upload, or remote
diagnostic channel. A manually exported diagnostic report uses an explicit
reviewed schema, contains only coarse redacted status selected by the user,
and never includes a raw log or vault object.

## 21. Candidate Implementation Profiles

### 21.1 Linux vault candidate

`FOG-COMPOSER-CANDIDATE-LINUX-VAULT-1` combines:

- an authenticated boot artifact and read-only `dm-verity` root image;
- a dedicated LUKS2 mutable volume with Argon2id keyslots;
- object-level XChaCha20-Poly1305 authenticated encryption;
- one transactional SQLite database with one writer;
- immutable import quarantine and export spool files;
- disabled network stack, swap, hibernation, core dumps, and active-content
  desktop services.

This combination is a review target, not a composed security proof. LUKS2,
dm-verity, AEAD, SQLite, boot firmware, filesystem, storage hardware, and the
Composer transaction protocol have different failure and trust assumptions.

### 21.2 Qubes MicroVM candidate

`FOG-COMPOSER-CANDIDATE-MICROVM-QUBES-1` evaluates:

- a dedicated persistent Composer qube with no NetVM;
- an immutable reviewed template or standalone image measurement;
- one private encrypted state volume unlocked inside the guest;
- exact qrexec policies for bounded import and export services only;
- separate untrusted transfer qubes where physical device support requires
  them;
- explicit denial of file copy, clipboard, URL opening, general command,
  update proxy, audio, camera, block, USB, and arbitrary qrexec services.

qrexec is a host-mediated data channel and the Qubes host remains trusted for
guest confidentiality and integrity. A host-controlled vTPM is not an
independent anchor against that host.

### 21.3 Portable Linux candidate

`FOG-COMPOSER-CANDIDATE-PORTABLE-LINUX-1` reuses the Linux vault profile but
boots a signed read-only image on dedicated offline hardware. It requires
driver removal, internal-disk automount denial, separate RX/TX devices,
physical inspection, and a profile-selected independent monotonic anchor for
any complete-rollback claim.

Secure Boot without a narrowly controlled FOG release root, root-image
verification without an authenticated root digest, or a TPM without a reviewed
state-binding protocol does not satisfy the complete candidate.

### 21.4 Activation gates

Before any candidate receives an active numeric profile, FOG MUST freeze and
verify:

1. exact operating system, kernel, bootloader, firmware assumptions, image
   format, and immutable-root construction;
2. exact LUKS2, Argon2id, AEAD, KDF, hash, database, filesystem, and library
   revisions and parameters;
3. byte-exact vault object, commitment, bundle, record, recovery, and update
   serialization;
4. nonce uniqueness, key-purpose separation, wrapping, rotation, and deletion;
5. database atomicity, sync, power-loss, disk-full, corruption, and backup
   behavior on supported hardware;
6. external-anchor state binding, crash protocol, endurance, reset, clone,
   replacement, and recovery;
7. exact MicroVM device model and qrexec or equivalent policy;
8. exact Portable driver set, mounts, Secure Boot ownership, dm-verity chain,
   and physical transfer direction;
9. exact TUF revision, client, metadata encoding, thresholds, trusted time,
   root rotation, rollback floor, revocation, and offline repository workflow;
10. parser fuzzing, UI rendering, import/export duplication, hostile media,
    migration, recovery, and update fault injection;
11. reproducible or independently verifiable builds, dependency provenance,
    release ceremony, and rollback rehearsal;
12. independent endpoint, cryptographic integration, and implementation
    review before public claims.

## 22. Conformance and Adversarial Tests

Before the local PoC, FOG-COMPOSER requires deterministic positive and
negative tests for:

- image signature, boot argument, root digest, read-only root, and failure
  before vault unlock;
- absence of NICs, network drivers, network syscalls, listeners, proxies, and
  undeclared devices;
- MicroVM clipboard, shared directory, qrexec, device, and guest-agent denial;
- Portable radio, internal-disk mount, foreign-filesystem, and directional
  device denial;
- keyslot creation, unlock, wrong secret, rewrap, rotation, and partial header
  update;
- object AEAD, associated data, nonce, padding, generation, key epoch, wrong
  instance, corruption, truncation, and unknown-critical fields;
- atomic messaging, storage, PKI, import, export, and application commits;
- every crash point before and after prepared state, anchor advance,
  finalization, export release, and plaintext rendering;
- local-chain rollback, complete coherent rollback, clone, split generation,
  anchor reset, missing anchor, same-generation conflict, and reconciliation;
- exact 128-byte bundle and 48-byte record headers;
- every bundle kind, record allowlist, direction, size, count, padding,
  overlap, gap, duplicate ID, integer overflow, and trailing byte;
- malformed QR, FOG-SX, removable-medium, contact, PKI, reply, recovery, and
  update inputs as data only;
- exact duplicate import and export, repacking, reordered records, replay,
  interrupted transfer, and stale result;
- recovery creation, separate-key handling, test decrypt, restore into a new
  instance, and refusal to resume live state;
- rejection of a copied VM volume, database, portable partition, or full-state
  archive as an active restore;
- TUF thresholds, sequential root rotation, expiry, freeze, rollback,
  fast-forward, mix-and-match, wrong target, hash, length, platform,
  compatibility, and revocation;
- update stream interruption, inactive-image verification, A/B trial,
  unauthorized fallback, migration failure, and recovery media;
- safe text rendering, Unicode edge cases, active content, external resource,
  notification, clipboard, and parser resource abuse;
- disk full, fake-capacity media, I/O error, fsync failure, hot journal,
  corrupted database, low memory, KDF exhaustion, and anchor timeout;
- lock, inactivity, suspend, display loss, update mode, and best-effort key
  erasure;
- absence of prohibited data from logs, crash artifacts, swap, hibernation,
  temporary files, export, and diagnostics.

Testing MUST include parser fuzzing, property tests, transaction fault
injection, simulated power loss, race detection, hostile peripheral fixtures,
resource exhaustion, cross-version migrations, restore exercises, dependency
audits, and byte-identical vectors across independent implementations.

Platform evidence MUST distinguish simulator, VM, dedicated offline hardware,
and production-profile results.

## 23. Threat and Architecture Traceability

| Requirement | Primary controls |
| --- | --- |
| `ARC-002` | no NIC, no socket service, bounded transfer only, conformance network tests |
| `ARC-004` | local vault, messaging, KEMSphinx, storage, and Noise keys remain separate |
| `ARC-005` | full PKI verification and monotonic consensus state before route construction |
| `ARC-006` | common opaque bundle and packet classes across native applications |
| `ARC-007` | explicit vault, object, transfer, backup, anchor, release, and protocol key ownership |
| `ARC-008` | exact headers, absolute parser ceilings, object and transaction bounds |
| `ARC-009` | fail closed on image, state, anchor, import, PKI, update, and recovery uncertainty |
| `IF-01` | committed opaque export only, sealed spool, no stable Composer signature |
| `IF-02` | hostile quarantine, complete parsing, owning inner authentication, atomic import |
| `IF-12` | threshold release metadata, target verification, inactive image, rollback floor |
| `TM-PKI-02` | persisted consensus and checkpoint monotonic state, split freeze, external anchor where claimed |
| `TM-ENDPOINT-01` | MicroVM and Portable profiles, immutable image, encrypted vault, no network or active content |
| `TM-ENDPOINT-02` | separate bounded binary directions, sandboxed decoder, no archive or filesystem import |
| `TM-ENDPOINT-03` | separate recovery hierarchy, identity-only default, no stale live-state resume or file-copy multi-device |
| `TM-APP-01` | authenticated commit before bounded plain-text rendering, no automatic actions |
| `TM-OPS-01` | no telemetry or secret-bearing log, crash, support, or export artifacts |
| `TM-SUPPLY-01` | separate release authority, TUF candidate, immutable verified images, provenance gates |
| `TM-CRYPTO-01` | random data keys, memory-hard unlock, purpose-separated object keys, lifecycle table |
| `TM-CRYPTO-02` | immutable profile registry, no runtime crypto selection or downgrade |
| `TM-AVAIL-01` | absolute limits, staged streaming, bounded KDF and parser work, disk reserve and safe stop |

## 24. Claims Deliberately Withheld

FOG-COMPOSER does not yet establish:

- protection of plaintext or keys from a compromised unlocked Composer;
- protection of a MicroVM from its malicious host or hypervisor;
- detection of a complete coherent rollback without an independent anchor;
- safe binding or endurance of a concrete TPM, secure element, or token;
- secure deletion from every RAM, flash, snapshot, backup, or physical copy;
- a final operating system, database, AEAD, KDF, filesystem, or library;
- correctness of firmware, Secure Boot implementation, peripheral, DMA, or
  hardware randomness;
- that network driver removal eliminates every physical or side channel;
- that TUF alone proves the distributor supplied the latest update while the
  Composer is isolated;
- transparent recovery of forward-secret sessions, pending delivery, or live
  capability streams;
- safe multi-device state, cloud recovery, or server-held recovery secrets;
- production security from a Qubes fixture, portable USB prototype, or local
  fault test.

## 25. Open Dependencies

The structural Composer contract is fixed, but these dependencies remain open
before an active profile or implementation:

- exact supported Linux distribution, kernel, boot, immutable-image,
  filesystem, and hardware profiles;
- exact LUKS2, Argon2id, AEAD, KDF, database, and secure-memory selections;
- byte-exact vault, state commitment, bundle records, recovery envelope, and
  update metadata integration;
- an independent monotonic-anchor construction with proven state binding,
  crash reconciliation, endurance, replacement, and recovery;
- a trusted offline-time and clock-uncertainty recovery ceremony;
- exact Qubes version, qube type, template lifecycle, qrexec services, and
  host policy for the MicroVM candidate;
- exact Secure Boot root ownership, firmware requirements, driver manifest,
  RX/TX devices, and media policy for Portable;
- the full `FOG-UPDATE` repository, signing, provenance, reproducible-build,
  revocation, and recovery contract;
- activation of one byte-exact numeric `FOG-SX` joint profile after its fixed
  structural frame, object, padding, parser, no-ACK, and physical-direction
  contract passes FEC, implementation, license and IPR, resource, vector,
  hardware, and independent review;
- entry capsule and return-rendezvous bundles needed for complete relay
  import/export;
- identity compromise, revocation, contact recovery UX, and fresh-session
  transition vectors;
- future native attachment, full-text search, group, and multi-device
  protocols.

No implementation convenience may silently resolve these dependencies.

## 26. Primary References

- FOG threat model: `FOG-THREAT-MODEL.md`
- FOG architecture: `FOG-ARCHITECTURE.md`
- FOG public key infrastructure: `FOG-PKI.md`
- FOG wire protocol: `FOG-WIRE.md`
- FOG Sphinx profile framework: `FOG-SPHINX-PROFILES.md`
- FOG messaging protocol: `FOG-MESSAGING.md`
- FOG storage protocol: `FOG-STORAGE.md`
- FOG simplex transfer protocol: `FOG-SX.md`
- Qubes OS qrexec architecture:
  <https://doc.qubes-os.org/en/r4.3/developer/services/qrexec.html>
- Qubes OS device handling:
  <https://doc.qubes-os.org/en/latest/user/how-to-guides/how-to-use-devices.html>
- Linux kernel `dm-verity` documentation:
  <https://docs.kernel.org/admin-guide/device-mapper/verity.html>
- cryptsetup and LUKS2 specification resources:
  <https://gitlab.com/cryptsetup/cryptsetup/-/wikis/Specification>
- RFC 9106, Argon2 Memory-Hard Function:
  <https://www.rfc-editor.org/rfc/rfc9106.html>
- libsodium XChaCha20-Poly1305 documentation:
  <https://doc.libsodium.org/secret-key_cryptography/aead/chacha20-poly1305/xchacha20-poly1305_construction>
- SQLite atomic commit documentation:
  <https://sqlite.org/atomiccommit.html>
- SQLite database-corruption and backup guidance:
  <https://sqlite.org/howtocorrupt.html>
- Trusted Computing Group TPM 2.0 Library specification:
  <https://trustedcomputinggroup.org/resource/tpm-library-specification/>
- The Update Framework specification and security model:
  <https://theupdateframework.io/spec/>
  <https://theupdateframework.io/docs/security/>

These references supply maintained formats, mechanisms, and failure lessons.
They do not make the combined FOG endpoint secure by inheritance. FOG still
requires exact profiles, integration analysis, hardware measurement, vectors,
fault testing, build provenance, update and recovery rehearsal, and
independent review.
