Skip to content

Bind extension config file hashes in the manifest projection#79

Merged
gvonnessi merged 1 commit into
mainfrom
phase7c-bind-config-file-hashes
Jun 29, 2026
Merged

Bind extension config file hashes in the manifest projection#79
gvonnessi merged 1 commit into
mainfrom
phase7c-bind-config-file-hashes

Conversation

@gvonnessi

Copy link
Copy Markdown
Collaborator

Summary

  • Three auxiliary files drive integrity-significant rendered output — academic/numbering.json (cross-reference numbers), semantic/bibliography.json and semantic/glossary.json (rendered citations/definitions) — yet the manifest referenced each by path only, with no hash. They were in neither the document hash nor the signed manifest projection, so a repackager could renumber, re-cite, or redefine a frozen/signed document while every signature still verified and the document id was unchanged.
  • Declare these references as {path, hash} objects and bind their hashes through the manifest projection. The binding is generic: the projector collects every {path, hash} reference declared in an extension config slot — keyed on the shape, not on a field name — into a sorted, deduplicated configFiles set, so a manifest-covering signature now attests each file's content and a newly defined hashed config file is covered without changing the projector. Advisory configuration that is not a file reference is left unbound.
  • The normative projection definition (security §9.7/§9.8), the integrity-status disclosures (academic §13, semantic §11, the shared integrity-tier framework), and the academic/semantic config schemas are updated to match. The example loader now verifies each declared config-file hash against the file's bytes.

Re-freeze

  • No example document id moves — config slots are outside the document id.
  • Both signed manifest projections are byte-unchanged — neither signed example declares a config file, so configFiles is omitted (never emitted empty).

Test plan

  • npm test (now also verifies config-file declared hashes against the real files), npm run test:canonicalize.
  • New projection KAT vector config-file-references (expected JCS + sha256 independently derived) + a conflicting-hash error vector; check:manifest-projection green and both signed projections unmoved.
  • check:manifest-extension-config requires {path,hash} (bare-string and missing-hash rejection vectors).
  • Seed-and-revert: a bare-string config → schema gate exit 1; a wrong declared hash → validate:examples exit 1.
  • All 19 gates green from a clean npm ci (verified by exit code); npx tsc --noEmit clean; npm audit 0 high.

Three auxiliary files drive integrity-significant rendered output —
academic/numbering.json supplies cross-reference numbers, and
semantic/bibliography.json and semantic/glossary.json supply rendered
citations and definitions — yet the manifest referenced each by path only,
with no hash. They were therefore in neither the document hash nor the
signed manifest projection: a repackager could renumber, re-cite, or
redefine a frozen or signed document, silently changing what it displays,
while every signature still verified and the document id was unchanged.

Declare these references as {path, hash} objects and bind their hashes
through the manifest projection. The binding is generic: the projector
collects every {path, hash} reference declared in an extension config slot
— keyed on the shape, not on a field name — into a sorted, deduplicated
configFiles set, so a manifest-covering signature now attests each file's
content and a newly defined hashed config file is covered without changing
the projector. Advisory configuration that is not a file reference is left
unbound. A document-ID-only verifier, or a document with no manifest-
covering signature, still sees these files unauthenticated.

The academic and semantic config schemas now require the {path, hash}
shape; the manifest-projection normative definition (security §9.7/§9.8),
the integrity-status disclosures, and the example manifests are updated to
match, and the example loader verifies each declared config-file hash
against the file's bytes. No example document id moves — config slots are
outside the document id — and both signed manifest projections are
unchanged, since neither declares a config file.
@gvonnessi gvonnessi merged commit b550c10 into main Jun 29, 2026
2 checks passed
@gvonnessi gvonnessi deleted the phase7c-bind-config-file-hashes branch June 29, 2026 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant