security: harden registry trust and ingestion
All checks were successful
Standalone registry checks / check (push) Successful in 3m47s

This commit is contained in:
Nic Weyand 2026-09-13 02:31:51 -04:00
commit 9705b01fe4
Signed by: nicweyand
SSH key fingerprint: SHA256:2te+ycJIQON/Wo/dH6+ZkFSQ4HnHWpetV2azx9E65dQ
25 changed files with 846 additions and 144 deletions

View file

@ -2,9 +2,11 @@
## Rust library
Use `argand_site_registry::query::Registry::open(generation, trusted_pin)` once per
immutable generation and reuse the reader. `lookup(query, limit)` returns evidence
and complete ambiguity counts; `resolve_explained` returns a reviewed candidate or
Use `release::verify_signed(generation, publisher_signers, publisher_identity,
reviewer_signers)` once per production generation and reuse the returned reader.
`Registry::open(generation, trusted_pin)` is the lower-level path when the pin
distributor is also trusted for the complete review decision. `lookup(query,
limit)` returns evidence and complete ambiguity counts; `resolve_explained` returns a reviewed candidate or
a typed abstention reason with counts. Exact reverse views cover entity IDs,
URLs/domains, popularity and Curlie categories. Check the compiled example and API
docs for exact types. `selection_context` binds the full alternative set for
@ -39,9 +41,10 @@ omits descriptions and includes fact provenance plus an attribution envelope.
It is an assertion export, not a self-contained signed list of admitted routes.
Raw SQL inspection is useful for audit; it does not implement resolution policy.
Code version 0.2.0 uses schema version 2 and `argand.site-rules/v2`.
It adds authenticated reviewer proofs, exact immutable SQLite opening, typed diffs
and audit/evaluation APIs. Schema/rule contracts remain versioned independently in
Code version 0.3.0 uses schema version 3 and `argand.site-rules/v3`.
It adds reviewer-trust enforcement for consumers, private authenticated SQLite
snapshots, exact-stream import checks, bounded outputs and metadata-bound identity
decisions. Schema/rule contracts remain versioned independently in
receipts. Unsupported contracts fail closed. Pin source releases,
compile consumers and replay fixed fixtures before upgrades. Preserve import and
review history; never mutate complete generations to migrate them.

View file

@ -14,6 +14,12 @@ one accepted principal and public key per line:
operator@example.org ssh-ed25519 REVIEWER_PUBLIC_KEY
```
For rotation, retain an old public key with an OpenSSH `valid-before` option
covering its signed decision times. New decisions are checked at append time, so
an expired key cannot submit backdated reviews; historical release verification
uses each authenticated `reviewed_at`. Remove a retired key only after no retained
generation or review log depends on it.
Distribute the release publisher public key to consumers through an independent
authenticated channel. Do not put private keys, production trust files or source
datasets in Git or CI. The isolated source CI runner has none of these files.
@ -62,6 +68,7 @@ argand-site-registry sign --generation /data/registry/reviewed \
argand-site-registry activate --generation /data/registry/reviewed \
--current /data/registry/current.json \
--allowed-signers /secure/release-allowed-signers \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity registry-publisher
```

View file

@ -18,9 +18,11 @@ writer retains their exact decision/signature bytes in the append-only review lo
Generations bind the database, license document and attribution to a completion
receipt. Consumers provide a trusted hash or verify an external publisher key.
Release signing re-verifies every stored decision against an external reviewer
trust file. Activation checks publisher signatures, rejects structurally incomplete
review proofs and refuses rollback that loses distributed revocations. Updates
build candidates and cannot approve, sign or activate them.
trust file. Activation checks publisher signatures, re-verifies every review
against a separately supplied reviewer trust file and refuses rollback that loses
distributed revocations. Reviewer validity epochs are evaluated at decision time
for retained history while new decisions must pass the trust policy at append
time. Updates build candidates and cannot approve, sign or activate them.
## What a publisher must establish
@ -47,8 +49,11 @@ enforced quorum.
## What consumers must preserve
Authenticate a release before opening it. Keep the full receipt pin and required
attribution with caches and exports. Use `resolve` for reviewed destinations, keep
Authenticate a release before opening it. Consumers that rely on reviewer
separation must use `release::verify_signed` or `activate` with independently
distributed publisher and reviewer trust files; a receipt pin alone delegates the
whole release decision to whoever distributed that pin. Keep the full receipt pin
and required attribution with caches and exports. Use `resolve` for reviewed destinations, keep
null as abstention, and enforce application-specific malware/content/navigation
policy separately. A verified signature authenticates the publisher, not the truth
of every assertion. An official website may later be compromised.