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 trailingZ; no offsets/subseconds). - Epoch conversion:
unix_seconds = seconds_since_1970_UTC(iso_utc) - Leap-second ban: reject any
iso_utcwith:60(no stamping at23: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_precfractional digits (default5) 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_algofromkv:algoor defaultsha256. - 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_chainfromkv:chain_algoor defaultsha256 - 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 unknownkv: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); requireh' == h_str. - Clock: recompute from
iso_utc; requirerasi'_idx == rasi_idxand printedtheta_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) )withchain_0 = "0"*64. - KV tail: validate recognized keys/domains; ignore unknown.
7.1.8 Roll-up (anchor) ordering
- Day key (UTC):
YYYY-MM-DDfromiso_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 anykv:tail; no leading/trailing|; emit lowercase64-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_precdigits, 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)