release: implement site registry v0.4 trust pipeline

This commit is contained in:
Nic Weyand 2026-09-13 12:22:05 -04:00
commit e26efc19fa
Signed by: nicweyand
SSH key fingerprint: SHA256:2te+ycJIQON/Wo/dH6+ZkFSQ4HnHWpetV2azx9E65dQ
67 changed files with 10698 additions and 640 deletions

83
docs/ARCHITECTURE.md Normal file
View file

@ -0,0 +1,83 @@
# Architecture
Argand Site Registry is a local Rust library and CLI around a mutable SQLite
writer and immutable, content-pinned reader generations. Source acquisition,
evidence normalization, editorial decisions, and release authority remain
separate.
```mermaid
flowchart LR
S[Allowlisted source objects] --> I[Streaming adapters]
I --> W[(Writer store)]
O[Bounded candidate observer] --> B[Immutable observation batches]
B --> W
W --> G[Candidate generation]
G --> Q[Evidence bundles and review queue]
Q --> V[Signed reviewer votes]
V --> W
W --> R[Reviewed generation]
R --> P[Separate publisher signature]
P --> C[Verified lookup and resolve]
R --> E[Signed cumulative revocation feed]
E --> C
```
## Data boundaries
`sources`, `records`, and `facts` preserve provider-native evidence. Typed
coverage selects a coherent active set without deleting older snapshots.
`selected_sources` and `active_records` record that derivation. Names, entities,
web properties, edges, popularity, and rejected facts are deterministic
projections.
Names, website edges, and entity equivalences have separate material
fingerprints. Adding an alias therefore cannot inherit an approved destination,
and changing unrelated entity metadata does not invalidate an unchanged website
edge. Every evidence bundle contains the exact current assertion, provenance, and
attached observations that a vote signs.
Observation batches are append-only. Redirects, canonicals, hreflang, JSON-LD
`sameAs`, sitemaps, country selectors, HTTP state, public DNS-set hashes, TLS
certificate hashes, and bounded failures remain observations. They never create
an entity, ownership edge, role, or approval.
Votes are exact signed JSON documents. The writer records its own `accepted_at`,
the SSH signature, physical public-key digest, evidence-bundle digest, policy
digest, scope, expiry, and any explicitly superseded revocation IDs. Policy
compilation counts independent identities, groups, and physical keys. The
reference policy requires two independent approvals and makes one revocation
sticky.
## Trust boundaries
- Source HTTPS and a content digest establish what was imported, not whether the
assertion is true.
- Reviewer signatures establish who made an exact decision, not site safety.
- Publisher signatures authenticate a complete generation, not every assertion.
- `lookup` is an audit surface. `resolve` is the policy-enforced navigation
surface.
- Automated acquisition, observation, and builds stop at candidates. They have no
review, publisher, or activation authority.
Strict generation receipts bind database bytes, license and attribution files,
selected coverage, the review policy, reviewer trust-root bytes, and the trusted
acceptance-time rule. Readers copy authenticated SQLite bytes into a private
unlinked snapshot before opening them.
## Main modules
| Module | Responsibility |
| --- | --- |
| `download`, `crux` | Allowlisted, bounded source acquisition and resumable cache |
| `source`, `store`, adapters | Manifest validation and streaming source-specific import |
| `coverage` | Full/partition/delta graph validation and active-record masking |
| `normalize` | Deterministic URL, hostname, registrable-domain, suffix, and name normalization |
| `build` | Canonical immutable generation and receipt creation |
| `bundle`, `policy`, `vote` | Review evidence, policy epochs, authenticated quorum, revocation |
| `observer`, `observation`, `queue` | Candidate-only collection, replay/import, reverse lookup, drift and queues |
| `query`, `resolution`, `identity`, `catalog` | Audit lookup, equivalence, resolution, statistics |
| `release`, `revocation`, `generation`, `ssh` | Export, signature verification, emergency overlays, activation, rollback protection |
The database schema lives in ordered migrations. JSON and receipt contracts have
their own schema strings and fail closed on unknown versions. See
[FORMATS.md](FORMATS.md) and [MIGRATING-0.4.md](MIGRATING-0.4.md).