# FOG Simplex Transfer

Status: Draft 0.1

Date: 2026-08-08

## 1. Purpose

This document defines `FOG-SX`, the bounded, medium-independent simplex
transfer contract used to move one committed opaque Composer export from a
physically offline Composer toward an online blind relay.

It fixes:

- the transfer object and frame byte layouts;
- padded transfer-size classes and their leakage;
- profile selection without runtime negotiation;
- forward-error-correction ownership and candidate gates;
- acknowledgment-free sender and receiver state machines;
- parser, memory, CPU, time, and storage ceilings;
- common physical-backend requirements;
- candidate QR, TOSLINK Lightpipe, and MIDI DIN profiles;
- process isolation, failure behavior, and conformance evidence.

This document records two non-active FEC candidates and three non-active
physical-backend candidates. No candidate has an active numeric profile ID.
No FOG-SX transfer is release-conformant until one complete joint profile has
passed the activation gates in Section 22.

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-SX owns the path:

```text
committed Composer RELAY_EXPORT bundle
  -> sandboxed FOG-SX export encoder
  -> physically transmit-only backend
  -> one-way medium
  -> physically receive-only backend
  -> sandboxed FOG-SX transfer receiver
  -> bounded reconstructed Composer bundle
  -> blind-relay queue
```

FOG-SX version 1 carries exactly one complete Composer `RELAY_EXPORT` bundle
per transfer. It does not carry a filename, directory, stream name, MIME type,
URI, archive, compressed object, filesystem, document, script, executable, or
device command.

FOG-SX does not own:

- Composer bundle semantics, record allowlists, or spool transitions;
- KEMSphinx, messaging, storage, PKI, contact, update, or recovery
  authentication;
- blind-relay acceptance or delivery evidence;
- online-to-offline Composer import;
- a removable-media filesystem format;
- generic optical, serial, audio, or camera device control;
- anonymity, cover traffic, or traffic-analysis resistance on the physical
  link.

Online-to-offline input uses a separately controlled receive-only Composer
path. It is not an FOG-SX acknowledgment channel and is not the reverse
direction of the same peripheral.

## 3. Security Boundary

The raw backend stream, every frame header, every symbol, every FEC parameter,
and every reconstructed transfer object are attacker-controlled input.

The transfer receiver is outside the blind relay's trusted protocol state. It
MUST NOT hold:

- relay network credentials or Noise private keys;
- Composer, user identity, messaging, storage, or PKI private keys;
- message plaintext, contacts, capabilities, routes, or application state;
- a shell, compiler, package manager, general browser, or general writable
  filesystem;
- a bidirectional interface to the offline Composer.

The receiver outputs only one bounded byte string that still has to pass the
complete `FOG-COMPOSER` bundle parser and every owning inner authentication
rule. FEC recovery, CRC success, SHA-256 equality, transfer-ID equality,
physical directionality, and operator observation confer no authenticity.

Applicable requirements include `ARC-002`, `ARC-004`, `ARC-007`, `ARC-008`,
`ARC-009`, `IF-01`, `IF-02`, `TM-ENDPOINT-01`, `TM-ENDPOINT-02`,
`TM-OPS-01`, `TM-SUPPLY-01`, `TM-CRYPTO-01`, `TM-CRYPTO-02`, and
`TM-AVAIL-01`.

## 4. Version-1 Invariants

Every active FOG-SX version-1 profile MUST preserve all of these invariants:

1. Data flows in one physical direction during a transfer.
2. The receiver sends no automatic acknowledgment, control, clock, retry,
   negotiation, or completion signal to the sender.
3. One exact joint profile is configured before transfer. There is no
   autodetection, negotiation, opportunistic upgrade, or downgrade.
4. Frames have one fixed size within a joint profile.
5. One transfer contains one padded transfer object and one Composer bundle.
6. Exact bundle length is hidden only within a declared size class.
7. All integers use unsigned network byte order.
8. Reserved bytes and unknown flags are zero. Any other value rejects the
   frame or object.
9. CRC32C and SHA-256 are error-detection and reconstruction checks only.
10. The complete inner Composer bundle is validated before relay state
    changes.
11. Resource limits are checked before allocation or FEC work.
12. The backend cannot introduce filenames, metadata records, control
    messages, or an automatic return path.
13. Unknown profile, frame, size-class, and FEC identifiers fail closed.
14. Profile behavior is immutable for its numeric identifier.

## 5. Terms

- `ComposerBundle`: the byte-exact object defined by `FOG-COMPOSER`.
- `TransferObject`: the 128-byte FOG-SX object header, one ComposerBundle,
  and zero padding to an exact size-class capacity.
- `source symbol`: one fixed-length slice used by the selected FEC.
- `repair symbol`: one FEC-generated symbol that is not an original source
  symbol.
- `source block`: one independently recoverable group of source symbols.
- `frame`: one 96-byte FOG-SX header, one symbol payload, and one trailing
  CRC32C.
- `joint profile`: the immutable tuple of format, backend, FEC, size,
  scheduling, and resource parameters accepted by both endpoints.
- `receive window`: one explicit local operator action that permits the
  receiver to admit a new transfer.
- `completion indication`: local human-visible receiver output. It is not a
  protocol message.

## 6. Profile Registry

### 6.1 Joint profile

An `sx_profile_id` identifies one complete immutable registry entry containing
at least:

- FOG-SX format version;
- permitted transfer direction and Composer bundle kind;
- backend profile ID and hardware assurance level;
- FEC profile ID, exact algorithm revision, and implementation constraints;
- allowed size-class IDs;
- symbol payload length;
- object partitioning into source blocks and symbols;
- encoding-symbol-ID range and mapping;
- systematic, repair, interleaving, and repetition schedule;
- physical framing, modulation, bitrate, clock recovery, and timeout;
- CRC32C representation;
- sender cycle and duration ceilings;
- receiver frame, memory, storage, CPU, conflict, and decode-attempt budgets;
- release, dependency, and test-vector identity.

The separately encoded backend, FEC, and size-class IDs let the receiver
reject inconsistent headers early. They do not permit the sender to assemble
a new tuple. Every field MUST equal the configured joint-profile entry.

### 6.2 Distribution and activation

The registry ships as immutable release data. It is not learned from the raw
stream. Numeric ID zero is invalid. Candidate names in this document are
symbolic and MUST NOT be placed on the wire as numeric IDs.

Changing an algorithm, parameter, schedule, dependency, hardware assumption,
or parser limit requires a new joint profile ID. An implementation MUST NOT
reinterpret an old ID after an update.

The operator selects one backend and one joint profile before opening a
receive window. A decoder MUST NOT scan multiple frame formats, CRC variants,
FEC schemes, or physical modulations to discover what the sender meant.

## 7. Padded Size Classes

### 7.1 Class definition

A size class fixes `bundle_capacity`, the maximum number of ComposerBundle
bytes carried in its TransferObject. The exact FEC source length is:

```text
transfer_object_length = 128 + bundle_capacity
```

The TransferObject is:

```text
128-byte TransferObjectHeader
composer_bundle_length bytes of ComposerBundle
bundle_capacity - composer_bundle_length zero bytes
```

The sender selects the smallest class permitted by the joint profile whose
capacity is at least the exact committed bundle length. The sender MUST NOT
repack, reorder, compress, split, or semantically modify the committed bundle
to obtain another class.

### 7.2 Version-1 structural class table

The structural registry reserves these capacities. A joint profile activates
only an explicit subset.

| Symbolic class | `bundle_capacity` | Intended use |
| --- | ---: | --- |
| `SX-C16K-1` | 16 KiB | small fixtures and constrained visual trials |
| `SX-C64K-1` | 64 KiB | small relay batches |
| `SX-C256K-1` | 256 KiB | ordinary relay batches |
| `SX-C1M-1` | 1 MiB | large relay batches |
| `SX-C4M-1` | 4 MiB | optical-only candidate |
| `SX-C16M-1` | 16 MiB | optical-only candidate |
| `SX-C64M-1` | 64 MiB | Composer relay parser ceiling |

`KiB` and `MiB` mean powers of 1024. No version-1 FOG-SX class exceeds 64 MiB
of bundle capacity. Update, recovery, contact, and import bundles are outside
the version-1 FOG-SX direction even when their Composer limits would fit.

### 7.3 Leakage

Padding hides only the exact bundle length inside the selected class. A
physical observer and the receiver can observe at least the backend, timing,
class, frame count, losses, repetition duration, and operator behavior.

The systematic source symbols of the same committed Composer bundle remain
correlatable across retransfers even when the transfer ID changes. FOG-SX
does not claim rerandomization or unlinkability. A future authenticated and
encrypted local Composer-relay envelope would be a separate Composer profile,
not an implicit property of FOG-SX.

## 8. TransferObject Header

### 8.1 Exact 128-byte layout

```text
offset  length  field
0       8       magic
8       2       sx_format_version
10      1       object_kind
11      1       flags
12      4       sx_profile_id
16      4       backend_profile_id
20      4       fec_profile_id
24      4       size_class_id
28      32      transfer_id
60      8       composer_bundle_length
68      8       transfer_object_length
76      32      composer_bundle_digest
108     16      reserved
124     4       header_checksum
```

`magic` is the eight ASCII octets `FOGSXO1` followed by line feed, with hex
value `46 4f 47 53 58 4f 31 0a`.

`sx_format_version` is 1. `object_kind` is 1 for `RELAY_EXPORT`.
`flags` is zero. `reserved` is sixteen zero octets.

`transfer_id` is exactly 32 bytes sampled from the operating system CSPRNG for
one new transfer attempt. It is not a user identity, authenticity value,
nonce for encryption, replay token, or receipt.

`composer_bundle_length` is the exact byte length of the committed bundle.
It MUST be at least the 128-byte Composer outer header and no greater than the
selected `bundle_capacity` or the Composer `RELAY_EXPORT` limit.

`transfer_object_length` MUST equal `128 + bundle_capacity` for the selected
class. It is redundant by design and MUST match the registry before the
receiver allocates object storage.

`composer_bundle_digest` is SHA-256 over the exact ComposerBundle bytes only,
not over TransferObject padding. It detects reconstruction and storage errors
and supports local duplicate handling. Because it is unkeyed and sent with
the object, an attacker can replace it. It provides no authenticity.

### 8.2 Header checksum

`header_checksum` is CRC32C using the algorithm and wire representation of
RFC 3309. For calculation, the four header-checksum octets are zero. The CRC
covers all 128 header octets and does not cover the bundle or padding.

The decoded header is not trusted merely because its CRC is correct. The
receiver validates it against frame fields and the configured registry before
using lengths or counts.

### 8.3 Canonical padding

Every byte after the exact ComposerBundle and before the end of the selected
TransferObject MUST be zero. Non-zero padding rejects the complete object.
Trailing data beyond `transfer_object_length` is not part of the object and
cannot be delivered to the relay.

## 9. SXFrame

### 9.1 Exact 96-byte header

```text
offset  length  field
0       8       magic
8       2       sx_format_version
10      1       frame_kind
11      1       flags
12      4       sx_profile_id
16      4       backend_profile_id
20      4       fec_profile_id
24      4       size_class_id
28      32      transfer_id
60      4       source_block_number
64      4       source_block_count
68      4       source_symbol_count
72      4       encoding_symbol_id
76      4       symbol_length
80      12      reserved
92      4       header_checksum
```

The fixed frame is:

```text
96-byte SXFrameHeader
symbol_length bytes of symbol_payload
4-byte frame_checksum
```

`magic` is the eight ASCII octets `FOGSXF1` followed by line feed, with hex
value `46 4f 47 53 58 46 31 0a`.

`sx_format_version` is 1. `frame_kind` is 1 for `SYMBOL`. No `END`, `ACK`,
`NAK`, negotiation, capability, metadata, filename, or control frame exists
in version 1. Backend idle and acquisition patterns remain outside SXFrame
and carry no transfer data.

`flags` and `reserved` are zero. `symbol_length` equals the joint profile's
fixed symbol payload length. Every frame in the profile therefore has exactly
`100 + symbol_length` bytes.

### 9.2 Block and symbol fields

`source_block_count` and `source_symbol_count` are redundant values derived
from the size class and FEC profile. They MUST match the registry calculation.

`source_block_number` is less than `source_block_count`.
`encoding_symbol_id` is interpreted only by the configured FEC profile and
MUST be inside that profile's declared range for the block.

The tuple:

```text
(sx_profile_id, transfer_id, source_block_number, encoding_symbol_id)
```

identifies one candidate symbol. It is not authenticated. Two byte-identical
copies are duplicates. Two different payloads for the same tuple are a
conflict and trigger the bounded conflict policy in Section 15.

### 9.3 Checksums

`header_checksum` is CRC32C over the complete 96-byte header with that field
zero. It permits early rejection before symbol allocation.

`frame_checksum` is CRC32C over the transmitted 96-byte header, including its
filled header checksum, followed by the exact symbol payload. The trailing
frame-checksum field is excluded from its own calculation.

Both CRC values use RFC 3309 CRC32C. A mismatch silently discards the frame.
A matching CRC does not authenticate the sender or symbol.

## 10. FEC Contract

### 10.1 Ownership

The FEC profile, not the raw stream, fixes:

- exact standard and revision;
- source-object partition algorithm;
- symbol alignment and length;
- minimum and maximum source symbols per block;
- source-block count calculation;
- source and repair encoding-symbol-ID mapping;
- maximum accepted ESI;
- repair-symbol generation;
- decoder input-selection and conflict rules;
- decode-attempt thresholds and maximum attempts;
- per-block memory, operation, and wall-time budgets;
- exact implementation and license evidence accepted for release;
- deterministic positive and negative vectors.

FEC parameters MUST NOT be inferred from attacker-selected counts. The frame
counts are checked copies of values derived from the configured profile and
size class.

### 10.2 Source partition

The complete padded TransferObject is the FEC source object. The profile
partitions it into ordered source blocks and fixed-length source symbols.
Only the last source symbol of the last block may require FEC-internal zero
fill, and the profile must make this fill byte-exact and distinguish it from
TransferObject padding.

Each source block decodes independently. Receiver code MUST NOT allocate the
entire candidate FEC matrix when one block is being decoded unless the active
profile's reviewed memory bound explicitly permits it.

### 10.3 Corruption and injection

FEC corrects erasures and some physical errors after failed frames are
discarded. It does not provide integrity against a malicious sender. One
forged but CRC-consistent encoding symbol may poison a decode.

After all blocks decode, the receiver therefore validates, in order:

1. exact TransferObject length;
2. exact 128-byte header and header CRC32C;
3. all profile, transfer, length, kind, reserved, and padding fields;
4. SHA-256 over the exact ComposerBundle;
5. exact Composer outer structure and direction;
6. owning inner authentication in the relay or Composer processing path.

A failure at any step discards the reconstructed candidate and makes no relay
state change.

## 11. Non-Active FEC Candidates

### 11.1 RaptorQ candidate

`FOG-SX-CANDIDATE-RAPTORQ-RFC6330-1` evaluates the fully specified RaptorQ
scheme in RFC 6330.

Potential advantages:

- systematic source symbols;
- repair symbols generated as needed without a fixed transmitted total;
- good fit for acknowledgment-free repeated emission;
- substantially larger source blocks than GF(256) Reed-Solomon.

Required review items:

- exact RFC parameter derivation and ESI mapping;
- decoder CPU and memory behavior on malformed or adversarial symbols;
- constant parser ceilings far below RFC maximums where appropriate;
- maintained implementation quality, unsafe-language containment, fuzzing,
  and cross-implementation vectors;
- dependency license and the IETF RaptorQ IPR disclosures, including the
  conditions and defensive-assertion language of disclosure 2554;
- full-object corruption and injection handling before relay delivery.

No implementation may claim that the RFC's large theoretical object limit is
a FOG-SX permission to allocate or process that amount.

### 11.2 Reed-Solomon candidate

`FOG-SX-CANDIDATE-RS-GF256-RFC5510-1` evaluates systematic Reed-Solomon over
GF(2^8) using the fully specified construction in RFC 5510.

Potential advantages:

- mature, deterministic block-code behavior;
- recovery of `k` source symbols from any `k` valid encoding symbols for the
  specified MDS construction;
- simpler finite redundancy and decode scheduling for small blocks.

Constraints:

- GF(2^8) provides at most 255 encoding symbols per source block;
- the profile must fix `k`, `n`, redundancy, block partitioning, and the
  behavior after all `n` symbols have been emitted;
- additional repetition cannot create new repair symbols beyond the fixed
  codeword and therefore handles burst losses less flexibly than a fountain
  schedule;
- poisoned CRC-consistent symbols can still corrupt a decoded block.

### 11.3 Selection rule

Neither candidate is selected by this draft. Selection requires measured
results for all activated size and backend classes, complete license review,
dependency maintenance evidence, bounded hostile-input tests, independent
vectors, and reproducible resource measurements.

An implementation MAY build isolated experimental adapters for both
candidates. It MUST NOT assign a production numeric ID or silently choose one
at runtime.

## 12. Sender State Machine

The sender uses these states:

```text
IDLE
  -> PREPARED
  -> EMITTING
  -> STOPPED

PREPARED or EMITTING
  -> FAILED
```

### 12.1 Prepare

To enter `PREPARED`, the export encoder:

1. receives read-only access to one immutable committed Composer spool item;
2. verifies exact bundle length and the selected size class;
3. samples a fresh 32-byte transfer ID from the OS CSPRNG;
4. creates the canonical TransferObject header;
5. streams the bundle and zero padding into the FEC encoder;
6. derives every block and schedule parameter from the configured registry;
7. confirms sender memory, time, frame, and output-device budgets;
8. closes every input not required for emission.

It does not parse message contents or query Composer state. Failure creates no
partial success indication and does not mutate the committed Composer bundle.

### 12.2 Emit

The joint profile defines one deterministic cycle containing systematic and
repair symbols interleaved across source blocks. The schedule SHOULD disperse
adjacent source data and block repair across time so that one physical burst
does not erase a contiguous object region.

The exact schedule, repair quota, block permutation, and ESI sequence are
profile inputs, not operator options. The sender repeats complete cycles until
one of:

- the human explicitly stops after observing receiver completion;
- the configured maximum cycle count is reached;
- the configured monotonic-duration ceiling is reached;
- the backend or resource monitor fails closed.

The sender never waits for receiver data and never changes its schedule based
on light, sound, serial input, network input, USB control input, or timing
purportedly supplied by the receiver.

### 12.3 Stop and retry

Stopping emission does not mean the relay accepted, queued, or delivered the
bundle. It records only a local transmitter event.

A new manual transfer attempt uses a fresh transfer ID. It MAY reuse the exact
committed ComposerBundle while its spool-retention policy permits. It MUST NOT
rewind message, ratchet, storage, packet, or Composer state merely because the
physical transfer was stopped or failed.

## 13. Receiver State Machine

The receiver uses:

```text
CLOSED
  -> ARMED
  -> COLLECTING
  -> RECONSTRUCTING
  -> COMPLETE

ARMED, COLLECTING, or RECONSTRUCTING
  -> FAILED

COMPLETE or FAILED
  -> CLOSED
```

### 13.1 Arm

`CLOSED` admits no new transfer. An explicit local operator action chooses
the backend, joint profile, and allowed size classes and opens one bounded
receive window.

The high-assurance receiver admits at most one active transfer. It creates no
state from idle patterns, CRC-failed data, unknown IDs, or a frame that does
not match the configured profile.

### 13.2 Collect

The first valid frame may establish the candidate transfer ID and size class
only after all fixed header, CRC, profile, and derived-count checks pass.
Later frames with another transfer ID are silently dropped while the slot is
occupied.

For one symbol tuple, the receiver:

- stores the first CRC-valid payload within budget;
- ignores an exact byte-identical duplicate;
- counts a different CRC-valid payload as a conflict;
- never lets a conflicting later payload silently replace an earlier one;
- aborts the transfer when the profile conflict ceiling is exceeded.

Symbols are stored in bounded per-block structures. Raw physical frames and
failed frames are not retained after the minimal counters needed for the
local status display.

### 13.3 Reconstruct

The decoder attempts one block only at profile-defined unique-symbol
thresholds and intervals. Receipt of duplicates, conflicts, bad CRCs, or
arbitrary ESIs MUST NOT trigger unbounded repeated matrix work.

Decoded blocks are staged in their exact object offsets. The receiver cannot
publish a partial object. After every block is present, it performs the full
validation sequence in Section 10.3 and streams the exact ComposerBundle into
one exclusively created bounded relay-ingress object.

### 13.4 Complete

`COMPLETE` means only that one byte-exact candidate passed FOG-SX structural
validation and was durably handed to the bounded relay-ingress queue. It does
not mean inner authentication, network submission, storage commit, or final
delivery succeeded.

The receiver MAY show a local light, fixed icon, or coarse text indication to
the human. It MUST NOT send a frame, network callback, sound, optical flash,
USB control transfer, or other automatic completion signal to the sender.

## 14. Validation Order Before Allocation

For each backend-delivered candidate frame, the receiver performs:

1. enforce the exact backend unit length;
2. locate the one profile-defined frame boundary without format scanning;
3. validate magic and version;
4. require `frame_kind = SYMBOL`, zero flags, and zero reserved bytes;
5. compare all profile IDs with the configured joint profile;
6. require the exact fixed symbol length;
7. validate the header CRC32C;
8. validate the complete frame CRC32C;
9. derive and compare size, block, source-symbol, and ESI bounds;
10. enforce active-transfer, duplicate, conflict, storage, and work budgets;
11. only then copy the symbol into bounded FEC storage.

All additions and multiplications involving untrusted fields use checked
integer arithmetic. A decoder MUST NOT cast an untrusted 32-bit count to a
smaller type, allocate from it, or multiply it before checking the profile-
derived expected value.

## 15. Version-1 Absolute Ceilings

These are implementation ceilings. Active profiles MUST be equal or stricter.

| Resource | Absolute ceiling |
| --- | ---: |
| Frame header | exactly 96 bytes |
| Symbol payload | 4096 bytes |
| Complete frame | 4196 bytes |
| TransferObject header | exactly 128 bytes |
| Composer bundle capacity | 64 MiB |
| TransferObject length | 64 MiB + 128 bytes |
| Active transfer IDs, high assurance | 1 |
| Active transfer IDs, lower assurance | 2 |
| Source blocks per transfer | 65536 |
| Source symbols per block | 4096 |
| Accepted unique symbols per block | 8192 |
| Conflicting tuples per block | 16 |
| FEC decode attempts per block | 32 |
| Simultaneous block decoders | 2 |
| Staged decoded object bytes | one selected TransferObject |
| Retained failed raw frames | 0 |
| Receive window | 24 monotonic hours |
| Sender cycles | 65535 |
| Parser nesting | forbidden |
| Decompression | forbidden |

The active profile defines lower backend-appropriate duration, cycle, block,
symbol, memory, disk, and CPU budgets. The receiver stops accepting symbols
while a block decode consumes its quota. A timeout, disk-full condition,
memory-pressure event, excessive conflict rate, dependency panic, or budget
exhaustion aborts the candidate and returns to a safe closed state.

Counters used only for resource enforcement saturate rather than wrap. They
are reset when the receive window closes and are not exported as telemetry.

## 16. Duplicate, Replay, and Injection Behavior

FOG-SX has no authenticated replay protection. A malicious source can copy or
recreate all of its public fields and checksums.

The receiver MAY maintain a bounded local cache of recently completed tuples:

```text
(sx_profile_id, transfer_id, composer_bundle_digest,
 composer_bundle_length, size_class_id)
```

An exact completed duplicate can be discarded before a second relay-ingress
write. The cache is a local availability control, not proof that another
transfer with the same ID or digest is authentic.

Composer and the owning inner protocols retain final deduplication and replay
authority. A new transfer ID does not authorize a duplicate message, receipt,
storage write, or state transition.

## 17. Common Physical-Backend Contract

Every backend profile fixes:

- one direction and one physical transmitter/receiver role;
- exact connector, module class, and electrical or optical assumptions;
- raw carrier framing and acquisition pattern;
- modulation, line coding, symbol rate, bitrate, and clock tolerance;
- mapping from one complete SXFrame to carrier units;
- acquisition, frame, idle, loss, and end-of-window timeouts;
- maximum supported size classes and expected transfer duration;
- device-open flags, driver allowlist, and prohibited device capabilities;
- physical teardown, continuity, and direction tests;
- emitted-light, sound, electromagnetic, and human-visible safety constraints;
- deterministic vectors captured above and below the backend boundary.

Backend code transports exact SXFrame bytes. It MUST NOT reinterpret a frame
as text, Base64, a file, MIDI music, audio content, a URL, or a document unless
the specific profile defines one fixed byte mapping solely as carrier coding.

The high-assurance profile requires separate unidirectional components whose
physical construction enforces direction. Software configuration, a disabled
receive API, driver policy, or a supposedly unused bidirectional transceiver
is insufficient.

The offline side exposes only a transmitter data input. The online side
exposes only a receiver data output. No common USB controller, shared debug
UART, management bus, network interface, storage controller, radio, or
bidirectional data cable may bridge the trust domains.

## 18. QR Candidate

`FOG-SX-CANDIDATE-QR-MODEL2-1` uses fixed-version QR Code Model 2 symbols as a
visual carrier from an offline display to an online camera.

Before activation it must fix:

- the ISO/IEC 18004 edition;
- QR version, byte mode, mask selection rule, and error-correction level;
- one exact binary mapping with one complete SXFrame per QR symbol and no QR
  structured append or backend-level SXFrame fragmentation;
- quiet zone, module size, contrast, display refresh, dwell, and blanking;
- camera resolution, frame rate, exposure, focus, decoder, and timeout;
- maximum FOG-SX size classes and operator ergonomics;
- rejection of URLs, text actions, structured append outside the exact
  profile, and general barcode dispatch.

QR Code has its own Reed-Solomon error correction. That layer improves visual
recovery but does not authenticate FOG-SX or replace the frame CRC, object
digest, FEC profile, or inner Composer authentication.

The camera is an attack surface. The online receiver uses a dedicated camera
or capture path with no microphone, speaker, storage automount, network,
vendor cloud service, or automatic barcode action. An online display used for
separate Composer import is not an acknowledgment and must not be driven by
FOG-SX receive state.

## 19. FOG Lightpipe Candidate

`FOG-SX-CANDIDATE-LIGHTPIPE-NRZ-1` is the preferred high-throughput candidate.
It uses a discrete optical transmitting module on the offline side, one fiber,
and a discrete optical receiving module on the online side.

The high-assurance construction requires:

- a transmitter-only module, such as the TOSLINK `TOTX` class;
- a receiver-only module, such as the TOSLINK `TORX` class;
- no `TODX` transceiver, duplex module, second fiber, or receiver on the
  offline board;
- no transmitter, display-controlled return light, or software-controlled
  emitter on the online board;
- galvanically separated power and no data-bearing ground or debug path
  between boards;
- a simple allowlisted hardware interface whose offline driver can only emit
  and whose online driver can only receive;
- schematics, bill of materials, board photographs, continuity tests, optical
  direction tests, and teardown evidence for the exact hardware revision.

TOSLINK defines optical transmitter and receiver device classes, not the
complete FOG-SX modulation. Before activation the candidate must fix the exact
NRZ or self-clocking line code, bitrate, transition density, preamble, clock
recovery, frame delimiter, escaping, idle pattern, light polarity, optical
module, fiber, distance, jitter, and error tests.

Consumer S/PDIF or USB audio adapters are lower assurance. They may contain
bidirectional USB control, opaque firmware, audio clocks, mixers, microphones,
or unexpected device functions. They MUST NOT satisfy the high-assurance
Lightpipe profile merely because their payload leaves through an optical jack.

A second online-to-offline optical system, if ever deployed for Composer
import, is a separately powered, separately controlled path with its own
receive-only offline hardware. It is not simultaneously active, is not
connected to FOG-SX state, and does not turn the export construction into a
duplex protocol.

## 20. MIDI DIN Candidate

`FOG-SX-CANDIDATE-MIDI-DIN-1` uses one MIDI DIN OUT circuit to one optically
isolated MIDI DIN IN circuit as a lower-throughput experimental carrier.

The MIDI 1.0 electrical specification defines a 31.25 kbaud asynchronous
8-N-1 interface, a 5 mA current loop, and receiver opto-isolation. The active
candidate must use that electrical direction, not a bidirectional USB MIDI
device.

Before activation it must fix:

- exact byte transparency and framing above the MIDI serial byte;
- handling or prohibition of status-byte semantics and running status;
- escaping, preamble, frame delimiter, resynchronization, and idle behavior;
- maximum frame payload and size class consistent with transfer duration;
- compliant OUT, IN, cable, shield, grounding, and opto-isolator circuits;
- absence of MIDI THRU or any offline input path;
- hostile jitter, disconnect, stuck-bit, burst-loss, and opto-isolator tests.

The carrier must not expose FOG-SX bytes to a general music application,
synthesizer plugin, device-discovery service, or cloud-connected MIDI stack.

## 21. Other Backends

Visible LED, screen-to-photodiode, audible modem, opto-isolated TX-only serial,
and punched paper tape remain architectural possibilities. None is specified
by this document and none may reuse a QR, Lightpipe, or MIDI backend ID.

Each future backend needs its own threat analysis, exact physical and byte
mapping, hardware-direction proof, resource profile, conformance vectors, and
release gate. A generic runtime driver or modulation plugin system is not a
substitute for separately reviewed profiles.

## 22. Candidate Activation Gates

A joint FOG-SX profile receives a numeric ID only after all of these are
complete:

1. byte-exact frame, object, size, FEC, schedule, and backend parameters;
2. two independent encoders and decoders or one implementation plus an
   independent vector generator;
3. known-answer vectors for every size class and boundary value;
4. dependency, license, IPR, maintenance, and supply-chain review;
5. parser fuzzing with malformed headers, lengths, IDs, CRCs, padding, and
   trailing data;
6. hostile FEC corpus covering duplicates, conflicts, poisoned symbols,
   excessive ESIs, singular decode inputs, and resource exhaustion;
7. reproducible CPU, memory, disk, frame, time, and energy measurements;
8. crash, interruption, power-loss, disk-full, and restart testing;
9. physical directionality inspection and tests for the exact hardware;
10. confirmation that no automatic sender-visible completion path exists;
11. complete Composer and relay integration with inner authentication before
    state change;
12. independent security review of parser, FEC, hardware, and claims.

A local loopback, virtual QR camera, paired serial ports, audio adapter, or
single board can provide functional evidence only. It cannot establish a
physical data-diode or production endpoint-security claim.

## 23. Implementation Shape

The protocol implementation should preserve these logical modules:

```text
protocol/sx/
  frame/       fixed header parsing, serialization, and CRC
  object/      TransferObject construction, padding, and validation
  profile/     immutable registry and derived parameter checks
  fec/         narrow profile-specific encoder and decoder interfaces
  schedule/    deterministic sender schedule
  receiver/    bounded collection and reconstruction state machine
  backend/
    qr/        exact visual carrier edge
    lightpipe/ exact optical carrier edge
    midi/      exact current-loop carrier edge
```

The process boundary is:

```text
offline: fog-compose -> sealed spool -> fog-sx-send -> TX-only device
online:  RX-only device -> fog-sx-receive -> bounded relay ingress
```

`frame`, `object`, and profile validation are pure protocol code and do not
open devices or files. FEC implementations receive already bounded slices and
profile constants. Backend modules do not parse Composer bundles or implement
FEC. The transfer receiver is a separate executable from `fog-client-relay`.

There is no generic plugin loader, dynamic library selected by wire input,
universal device daemon, or in-process backend autodetection. Candidate FEC
libraries written in an unsafe language run behind the narrowest practical
sandbox and process boundary with fixed memory and CPU limits.

## 24. State, Retention, and Logging

The offline sender may read only the selected immutable spool item and its
public transfer profile. It stores no new long-term secret. Transfer IDs are
public ephemeral metadata and follow the spool attempt's bounded lifetime.

The online receiver retains:

- one bounded active symbol set during a receive window;
- one staged decoded TransferObject until complete validation;
- one exact ComposerBundle until durable relay-ingress handoff;
- a bounded recent-completion cache if enabled;
- coarse saturating error counters for the current local session.

It deletes failed symbols, failed objects, padding, and raw frames after the
owning failure or completion path. Deletion is best effort on flash and other
journaled storage and is not claimed as forensic erasure.

Logs and support output MUST NOT contain raw frames, symbols, transfer IDs,
bundle digests, Composer bytes, frame timing traces, device serial numbers,
camera images, audio captures, filesystem paths, or host identity. Local
status may show coarse progress, current class, and a generic failure category
without exporting telemetry.

## 25. Conformance Tests

Before the local PoC, deterministic tests must cover:

- exact 128-byte object and 96-byte frame headers;
- both magic values, version, kind, zero flags, and reserved bytes;
- big-endian integers and checked arithmetic;
- every boundary around each size class and the 64 MiB ceiling;
- exact zero padding and rejection of non-zero or trailing bytes;
- SHA-256 and both CRC32C calculation domains and wire values;
- wrong profile tuple, symbol length, counts, block number, and ESI;
- exact duplicate and conflicting symbols;
- all FEC success, insufficient-symbol, poisoned-symbol, and abort paths;
- deterministic schedule and interleaving across cycles;
- receiver window, transfer-slot, decode-attempt, time, memory, disk, and CPU
  limits;
- no partial output after any frame, block, object, or Composer failure;
- exact one-bundle relay-ingress handoff and duplicate suppression;
- sender stop and retry without state rewind;
- absence of ACK, reverse device access, network callback, and adaptive
  sender behavior;
- each physical backend's acquisition, loss, jitter, disconnect, and
  directionality fixtures;
- mutation, coverage-guided fuzz, property, race, crash, and fault-injection
  testing at every parser and process boundary.

Cross-implementation vectors include exact TransferObject bytes, every source
and repair symbol, frame bytes, CRCs, schedule order, reconstructed bytes, and
expected rejection reason class. Rejection classes are test outputs, not
remote protocol responses.

## 26. Failure Behavior

Malformed, unknown, inconsistent, oversized, stale, conflicting, timed-out,
or resource-exhausting input fails closed. The receiver sends nothing toward
the transmitter and publishes no partial Composer bundle.

The local UI distinguishes only coarse states such as waiting, collecting,
checking, complete, timed out, incompatible profile, and failed. Detailed
parser positions, CRC values, FEC matrices, raw input, transfer IDs, and
digests are unavailable to the physical sender and excluded from ordinary
logs.

If completion is uncertain, the human may stop and later restart a fresh
transfer attempt. Neither endpoint treats uncertainty as permission to bypass
Composer deduplication, inner authentication, or protocol state rules.

## 27. Threat and Architecture Traceability

| Requirement | Primary controls |
| --- | --- |
| `ARC-002` | networkless Composer, TX-only export, no automatic reverse path |
| `ARC-004` | transfer receiver has no relay, user, messaging, or storage keys |
| `ARC-007` | no FOG-SX secret; explicit ephemeral transfer-ID ownership |
| `ARC-008` | exact headers, fixed frames, derived counts, absolute ceilings |
| `ARC-009` | unknown profile, corruption, ambiguity, and exhaustion fail closed |
| `IF-01` | one committed opaque export, sandboxed encoder and receiver |
| `IF-02` | import remains a separate controlled direction, never an ACK path |
| `TM-ENDPOINT-01` | dedicated offline process and directional hardware assumptions |
| `TM-ENDPOINT-02` | bounded binary format, parser sandbox, no archive or filesystem |
| `TM-OPS-01` | no raw transfer logging, device identity, telemetry, or support dump |
| `TM-SUPPLY-01` | exact dependencies, hardware revision, license and release gates |
| `TM-CRYPTO-01` | CSPRNG transfer IDs, SHA-256 limited to error detection |
| `TM-CRYPTO-02` | immutable release registry, no negotiation or downgrade |
| `TM-AVAIL-01` | receive windows, one slot, conflict and FEC work budgets |

## 28. Claims Deliberately Withheld

FOG-SX does not yet establish:

- an active FEC algorithm, implementation, or numeric profile;
- an active physical backend, bitrate, symbol size, or hardware design;
- physical one-way assurance from software configuration alone;
- authenticity, confidentiality, replay protection, or non-repudiation at the
  FOG-SX layer;
- unlinkability of retransferred Composer bundles;
- concealment of transfer occurrence, timing, size class, frame count, or
  physical location;
- resistance to a compromised offline Composer, online receiver, firmware,
  camera, USB controller, optical module, or supply chain;
- elimination of optical, acoustic, electromagnetic, thermal, power, or
  human-mediated covert channels;
- production security from a loopback, animated QR demo, consumer TOSLINK
  adapter, USB MIDI adapter, or local PoC;
- successful network delivery merely because local reconstruction completed.

## 29. Open Dependencies

The structural FOG-SX contract is fixed, but these remain open:

- selection between the RaptorQ and Reed-Solomon candidates or a separately
  reviewed replacement;
- exact FEC parameters, implementation, dependency version, and license
  decision;
- byte-exact joint profile IDs and size-class subsets;
- exact QR geometry, decoder, frame mapping, and transfer-duration limits;
- exact Lightpipe modules, board, line code, bitrate, clock recovery, and
  hardware-direction evidence;
- exact MIDI byte mapping, circuit, frame size, and practical size classes;
- concrete per-profile CPU, memory, disk, cycle, time, and energy limits;
- Composer pairing-envelope decision if rerandomized local transport is later
  required;
- conformance corpus, fault fixtures, benchmark results, and independent
  review.

No implementation convenience may silently resolve these dependencies.

## 30. Primary References

- FOG threat model: `FOG-THREAT-MODEL.md`
- FOG architecture: `FOG-ARCHITECTURE.md`
- FOG Composer: `FOG-COMPOSER.md`
- RFC 6330, RaptorQ Forward Error Correction Scheme for Object Delivery:
  <https://www.rfc-editor.org/rfc/rfc6330.html>
- IETF IPR disclosure 2554 related to RFC 6330:
  <https://datatracker.ietf.org/ipr/2554/>
- RFC 5510, Reed-Solomon Forward Error Correction Schemes:
  <https://www.rfc-editor.org/rfc/rfc5510.html>
- RFC 3309, SCTP Checksum Change, including CRC32C definition:
  <https://www.rfc-editor.org/rfc/rfc3309.html>
- FIPS PUB 180-4, Secure Hash Standard:
  <https://csrc.nist.gov/pubs/fips/180-4/upd1/final>
- ISO/IEC 18004:2024, QR code symbology specification:
  <https://www.iso.org/standard/83389.html>
- DENSO WAVE QR Code error-correction overview:
  <https://www.qrcode.com/en/about/error_correction.html>
- MIDI 1.0 Electrical Specification Update:
  <https://midi.org/5-pin-din-electrical-specs>
- Toshiba TOSLINK transmitter, receiver, transceiver, and directivity naming:
  <https://toshiba.semicon-storage.com/us/semiconductor/design-development/partnumber/opto.html>
