2.5 Digests and the digest gate (TPS 0.5.0)
Instruction artifact, machine-optimized text: TPS, section 2.5 Digests and the digest gate. Part of TPS and the TPM hub. Human-only edit (TPS 5.13). TPS 0.1.0 was declared final at revision 4 on 2026-09-22, a version declaration recorded in the foundations record; the chain begins at TPX's first landing (TPS 5.6.7). TPS 0.1.1, which changed only the status lines, was declared final on 2026-09-26, TPS 0.3.0, revision 6, on 2026-09-28, and TPS 0.4.0, revision 7, on 2026-09-30. This page is revision 8 of the tree, declared final as TPS 0.5.0 by H-DECL on 2026-10-03 (naming TPS_0.5.0.txt by its file digest and its D(TPS)); revision 7 is carried whole, and revision 5, proposed as 0.2.0, stays undeclared. The text below is this section of the TPS artifact at 0.5.0, verbatim; the whole artifact and its file digest are on The Principia Machina/TPS. Human readers: the contents page is the map.
TPS 2.5 DIGESTS AND THE DIGEST GATE
purpose: D(TPK), D(TrM), D(TMS), D(TFK); TPX the sole implementation;
the digest convention; the zone serialization and the
text-safety rules; the gate before every write and at every
CAC; RESTORE or FORK by human declaration
governs: 2.5 | version: 0.5.0 (proposed) | class: instruction artifact
audience: operator, agent
2.5.1 Digests D(TPK), D(TrM), D(TMS) and D(TFK) are computed at CAC by
TPX, the sole implementation of every digest, written into the
CAC certificate that assigns the UUID, and appended as a BUILD
CHAIN line (see 5.6). [I-062]
2.5.2 A hand-transcribed digest is not a digest (D9). [I-062]
2.5.3 D(TFK) is computed over the three zone digests in fixed order
under the convention of 2.5.10. The container binds to D(TFK).
[I-033] [D97.1]
C-02, the combination rule, and C-03, the cross-implementation
hash tests, are DISCHARGED: the convention is stated at 2.5.10
and both residences of TPC reproduce the published digest corpus
byte for byte, checked against an external SHA-256. [D97.1]
2.5.4 Chain link hash SHA-256; page hash may be MediaWiki's SHA-1 (see
5.6). [I-063]
2.5.5 A content digest is verified before every write and at every CAC.
A digest-gate failure halts writes. [I-064]
2.5.6 The gate reports which of the three zones mismatched. [B-05]
2.5.7 Recovery is a human declaration between RESTORE (return the TFK
pages to the revision whose content hash matches the chain; writes
resume only after the digest matches) and FORK (copy-forward
under a newly declared TFK). Never a CA-GTP's choice. [I-064]
2.5.8 Before every write, TPX recomputes D(TFK) and matches it against
the certificate; on mismatch it halts the write and names the
zone (see 4.2, row 1). [B-18]
2.5.9 D(TrM) is computed over the TrM header first and then the
entries, in fixed order (see 2.3.10). [D39.1]
2.5.10 DIGEST CONVENTION. A digest is SHA-256 over the netstring
encoding of an ordered field list: enc([b1..bn]) is the
concatenation, field by field, of decimal(bytelen(bi)), ":" and
bi, a string as its UTF-8 bytes and an integer in base-10 ASCII.
The output is 64 lowercase hexadecimal characters. D(TFK) =
SHA-256(enc([D(TPK), D(TrM), D(TMS)])), in that order. The
encoding is self-delimiting, so no whitespace, delimiter,
number-format or escaping drift is possible; one byte sequence
stands for one ordered field list, identical in both residences.
[D97.1]
2.5.11 ZONE SERIALIZATION. Each zone is turned into a tree of strings,
integers and lists, and the tree is encoded on the 2.5.10
primitive with a one-byte type tag per node: a string "s" plus
its UTF-8 bytes after 2.5.12's text normalization; an integer
"i" plus base-10 ASCII; a list "l" plus enc(children). The tag
makes the encoding injective over every tree, validated or not;
without it a list and a string could encode alike and a tampered
page that swapped one for the other would pass the digest gate.
Tree shapes, the zone tag and the schema version opening every
zone so that a digest of one zone can never equal a digest of
another or of another schema:
TPK ["TPK", "0.5.0", ["PARAMETERS", entry], [kind,
[entry...]] for each of the six kinds in fixed order]
TrM ["TrM", "0.5.0", ["HEADER", ["ENVIRONMENT_INVENTORY",
...], ["SIGNATURE", ...], ["TRANSFORMATIONS", ...]],
["ENTRIES", ...]]
TMS ["TMS", "0.5.0", ["PARAMETERS", entry], ["CONSTANTS",
...], ["YARDSTICKS", ...]]
An entry is the flat list [field, value, field, value, ...] over
its kind's fields in schema order, present fields only, the
optional fields (UNIT; a DOF's ROLE; EQUATION, CONDITION, FORM,
IMAGE_FORM) entering after their kind's required fields, a
LAW's ROLE, required, after its REFS; the TPK's PARAMETERS entry
always carries D_VARIABLES, an absent part or field entering as
ONE. ORDER: entries sort
by NAME (by ENVIRONMENT_QUANTITY in the inventory, by DOMAIN in
LIMITING) in code-point order after text normalization; set
fields (REFS, OVER, BEARS) sort the same way; a KEY keeps its
order. The schema version is 0.5.0; a change of schema version
moves every zone digest, the TMS's included, whether or not an
entry carries a form. No UWC existed under an earlier schema, so
no digest of record has moved; the fixtures' digests moved once
at 0.3.0, once at 0.4.0 and once at 0.5.0, which added ROLE, the
TPK's PARAMETERS part and STRUCTURE_CHECK together. [D98.1]
[D99.1] [D104.1] [D132.1] [D176.1] [D177.1]
2.5.12 NORMALIZED, NOT REFUSED. Before encoding: text takes LF line
endings (CRLF and lone CR become LF), then Unicode NFC, so a page
read back digests as its draft did; DIMENSION takes its canonical
form: accepted "1" or tokens <BASE><exponent> separated by single
spaces, BASE one of L M T I TH N J, exponent an integer of at most
four digits, in any order, repeats adding, zero allowed;
a DIMENSION whose repeated bases sum to an exponent outside
-9999..9999 is refused, "DIMENSION <D>: an exponent is out of
range": its canonical form would lie outside this grammar, and
what does not parse is refused, never altered (D99);
canonical, bases in the order L M T I TH N J, each once, zero
exponents dropped, "1" if none remain; decimals (VALUE,
UNCERTAINTY, K) take their canonical form: accepted
-?digits(.digits)?([eE][-+]?d{1,4})?, canonical "0" for zero,
otherwise [-]M with "e"E appended when E is not 0, M an integer
without leading or trailing zeros, by string arithmetic, no
floating point entering a digest; UNIT takes its canonical
spelling (3.2.11), only the spelling, "5" in "cm" and "0.05" in
"m" being different statements; yardstick terms take their
canonical spelling, WSUM weights sorted by atom and NEG:NEG:t
written t; a declared form takes the canonical spelling of
2.2.14; an absent IC2_POLICY serializes as GAP, an absent
PROMOTION_FLOOR as F2, an absent STRUCTURE_CHECK as ON and an
absent TPK PARAMETERS part or D_VARIABLES as ONE. Two spellings
of one meaning digest alike,
so a respelled decimal, dimension, unit, term or form is an
IDENTICAL successor and not a new kernel (2.1.5); anything that
does not parse is refused, never altered. What TPX writes to the
TFK pages is the draft as entered; the digest is over the
canonical tree. NFC is not NFKC: superscripts, ligatures and
mathematical letters stay distinct. [D99.1] [D104.1] [D132.1]
[S15] [D176.1] [D177.1]
2.5.13 TEXT SAFETY RULE. Every string field is refused if, after
line-ending normalization, it holds a code point of Unicode
general category C (Cc control, Cf format, Cs surrogate, Co
private use, Cn unassigned, noncharacters included) other than
TAB and LF, or U+2028 or U+2029; a string that is not valid UTF-8
is refused first. The rule catches bidi overrides and isolates,
zero-width characters, tag characters, the soft hyphen, NUL and
every other control; the problem names the first such code
point. These characters have no spelling of one meaning to
normalize to: dropping a bidi override changes what a reader
sees, and keeping it hides what is stored, so refusal is the only
form under which the text H-DECL inspects is the text that is
hashed. Look-alike letters in prose are ordinary text and are not
refused; names, where a look-alike would change a citation, are
ASCII identifiers (2.2.7). A residence's Unicode version belongs
in its conformance declaration; TPX's ICU decides for the record,
and a string both residences accept digests alike. [D99.1]
2.5.14 ECHO SAFETY. Problem messages quote input: names, values, unknown
field names. Every disallowed code point in a message is shown as
<U+XXXX>, and every invalid byte as <0xHH>, so a message cannot
carry hidden or reordering text to its reader. Every validator
applies the text-safety rule to every string and never raises on
malformed input; problems are sorted, de-duplicated and name
their component ("LAW:N: REFS q does not resolve"), which is the
per-component rejection form of 5.5.7. [D99.1]
2.5.15 DIGESTS ARE DEFINED OVER WELL-FORMED ZONES ONLY. TPX runs the
zone's checks first; a zone with a problem is returned to its
author and has no digest. Successor classes (2.1.5), read from
the digests: KERNEL_CHANGED, D(TPK) moved; CORRESPONDENCE_CHANGED,
D(TPK) equal and D(TrM) moved; YARDSTICK_ONLY, D(TPK) and D(TrM)
equal and D(TMS) moved; IDENTICAL, all three equal. A reordered
operand or an added or removed form is KERNEL_CHANGED; a
signature form added or removed is CORRESPONDENCE_CHANGED.
[D99.1] [D132.1]
2.5.16 D(TFK) is blind to meaning-preserving byte edits by design
(2.5.12); the manifest's page-hash check stays in force on TFK
pages as the detector of any edit at all (5.11.5). What TPX and
PRB owe around the serialization is stated at 5.3.20 and 5.4.11.
[D99.1]