SSM-NET — Canonical subset & Continuity (4C–4D)

Hash exactly what you declare; chain every item linearly.

4C. Canonical subset & digest contract
Declare the exact fields (and order) you’re binding, then hash those byte-for-byte so any receiver can recompute identically.

# sender: canonical subset & digest
subset := ["value","band","manifest_id"]           # optionally add "align_ascii" if align is public
BYTES  := serialize(subset, rules=LF_UTF8_NFC_FIXEDNUM)
HEAD   := SHA256( BYTES [+ raw_body_bytes_on_wire_if_declared] )

Serialization rules (normative).

- Encoding: UTF-8; NFC normalization; no BOM
- Newlines: LF only ("\n")
- Order: exactly as listed in `subset`; no extras; none omitted
- Numbers-as-text: fixed sign/precision (e.g., align_ascii = "+0.732000"); no locale separators
- Escaping: single, profile-defined scheme; no alternate equivalents
- Binary fields: commit raw bytes (not re-encoded text)
- Optional TRIM_WHITESPACE_PER_LINE (if enabled by manifest/profile):
    - After LF normalization, trim leading/trailing ASCII space (0x20) and tab (0x09) per line
    - Do not alter interior spaces; do not apply to binary fields

Body commitment (when a body exists).

raw_body_bytes := EXACT_ON_WIRE_BYTES  # after any transport encoding (e.g., gzip)
BODY_HEAD      := SHA256(raw_body_bytes)
HEAD           := SHA256(BYTES + raw_body_bytes)

Receiver obligations.

HEAD_local := SHA256(serialize_declared_subset(e) [+ raw_body_bytes_on_wire_if_declared])
assert HEAD_local == parsed_head_from(e.stamp)         # no tolerance

Failure patterns (illustrative).

- Reordering declared fields; hashing decoded (not on-wire) body bytes
- Changing numeric text format (missing sign/decimals)
- Emitting CRLFs instead of LF; using non-NFC text


4D. Continuity scopes, genesis, and repairs
Track a single-link, append-only chain per scope so order and edits are provable.

# stamp shell (recap)
SSMCLOCK1|<UTC_ISO>|nonce=<...>|sha256=<HEAD>|prev=<HEX or NONE>

Scope basics.

scope := deployment-declared domain (e.g., resource/endpoint + manifest_id)
genesis: first accepted item uses prev = "NONE"
HEAD   : last accepted digest per scope (may be published for audits)

Acceptance rule (linear chain).

accept if e.stamp.prev == HEAD_for_scope
then HEAD_for_scope := e.stamp.sha256
else reject (non-continuous); append stamped incident (no edits)

Repairs (append-only).

# never rewrite history
emit new stamped note referencing current HEAD
do not edit or remove prior lines

Operational markers.

- Epoch rollover: emit stamped note; prev remains linear across boundary
- Allowed clock skew: accept if |now_utc - UTC_ISO| <= allowed_skew_s (policy-defined)
- Nonce: CSPRNG; no reuse within the same scope

Why this matters.
A precise subset plus a linear prev chain gives byte-for-byte integrity and undeniable ordering—auditable by anyone, independent of vendors or intermediaries.


Navigation
Previous: SSM-NET — Sender & Receiver (4A–4B)
Next: SSM-NET — Branching & Chain IDs (4D.1)