SSM-Clock Stamp – Canonical Formatting & Parsing (7.1)

Goal. Make every implementation emit and verify identical ASCII for the same inputs. The rules below are normative.


7.1.1 Parse iso_utc (UTC only)

  • Required shape: YYYY-MM-DDTHH:MM:SSZ (exact trailing Z; no offsets/subseconds).
  • Epoch conversion: unix_seconds = seconds_since_1970_UTC(iso_utc)
  • Leap-second ban: reject any iso_utc with :60 (no stamping at 23:59:60).
  • Non-UTC forms (e.g., +05:30, -0700, .123) → FAIL.

7.1.2 Deterministic clock (from UTC only)

  • Angle math (IEEE-754 binary64):
    wrap360(x) = x - 360*floor(x/360)
    theta_deg = wrap360( (unix_seconds / 86400) * 360 )
    rasi_idx = floor(theta_deg / 30)

7.1.3 Canonical rounding for theta_deg

  • Fixed digits: print with exactly theta_prec fractional digits (default 5) using round-half-to-even (banker’s rounding).
    theta_str = format_half_even(theta_deg, frac_digits=theta_prec)
  • Preferred check: string equality with the recorded field.
  • Tolerance (SHOULD-only fallback): abs(theta_recomputed - theta_recorded) <= 0.5 * 10^(-theta_prec) when strict print policy mismatch is suspected.

7.1.4 File hash (lowercase hex; streaming OK)

  • Algorithm: H_algo from kv:algo or default sha256.
  • Compute: h_file = H_algo(file_bytes) (streaming permitted; must equal monolithic).
  • Emit: lowercase 64-hex: h_str = hex_lower(h_file).

7.1.5 Build stamp_core and final line (ASCII)

  • Core (no spaces):
    stamp_core = "SSMCLOCK1|" + iso_utc + "|" + rasi_idx + "|" + theta_str + "|" + h_str
  • Chain seed: chain_0 = "0"*64
  • Chain algorithm: H_chain from kv:chain_algo or default sha256
  • Recurrence:
    chain_k = H_chain( ascii(chain_{k-1} + "|" + stamp_core) )chain_str = hex_lower(chain_k)
  • Final stamp (single ASCII line):
    SSMCLOCK1|iso_utc|rasi_idx|theta_str|h_str|chain_str[|kv:...]
    (Parsers MUST ignore unknown kv: keys; recognized keys MUST be validated.)
  • Defaults if kv: absent: algo=sha256; chain_algo=sha256; theta_prec=5; float=ieee75464; time_mode=derived_utc.

7.1.6 ASCII discipline (no Unicode punctuation)

  • All hashed inputs use 7-bit ASCII: ascii(x).
  • Replace typographic punctuation with ASCII: — -> -, ’ -> '
  • Only | separates fields; no spaces; no leading/trailing separators.
  • All digests are lowercase 64-hex.

7.1.7 Canonical equality checks (verifier side)

  • Hash: recompute h' = H_algo(file_bytes); require h' == h_str.
  • Clock: recompute from iso_utc; require rasi'_idx == rasi_idx and printed theta_str' == theta_str (or the numeric fallback noted above).
  • Chain (if ledger present): rewalk strictly with per-row H_chain:
    chain_k ?= H_chain( ascii(chain_{k-1} + "|" + stamp_core_k) ) with chain_0 = "0"*64.
  • KV tail: validate recognized keys/domains; ignore unknown.

7.1.8 Roll-up (anchor) ordering

  • Day key (UTC): YYYY-MM-DD from iso_utc.
  • Canonical sort key: (iso_utc, stamp_core, chain_str) (ascending, string-compare).
  • Digest (fixed):
    rollup_D = sha256( ascii(Stamp_1 "|" ... "|" Stamp_n) )
    (Include each full line exactly as recorded, including any kv: tail; no leading/trailing |; emit lowercase 64-hex.)

7.1.9 Common pitfalls (and fixes)

  • Offset/locale in iso_utc: reject anything not ...Z.
  • Float print drift: enforce binary64, half-even, exact theta_prec digits, decimal point . only.
  • Uppercase hex: always downcase.
  • Hidden Unicode: normalize to pure ASCII before hashing/emit.
  • Whitespace: none around separators.
  • Leap second: reject ...:60Z.
  • KV misuse: malformed values for recognized keys → FAIL; unknown keys → ignore.

Navigation
Back: SSM-Clock Stamp – Backdating Cost & Anchoring Cadence (6.4)
Next: SSM-Clock Stamp – Worked Example (7.2)