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

View file

@ -1,73 +1,115 @@
# Trust and evidence policy
Argand Site Registry is designed to fail closed. Imported assertions and crawler
observations become review evidence. Only policy-qualified votes can make a name
or destination resolvable, and only a separately authenticated generation should
reach consumers.
## What the implementation enforces
Inputs use reviewed source adapters and explicit manifests. URL normalization,
PSL parsing and stable identities are deterministic. Fact provenance, conflicting
evidence and source-specific popularity remain separate. Names and similar
hostnames never silently join entities. Invalid URLs and malformed imports fail
validation; a partial import does not replace a complete source selection.
Source adapters accept only documented providers and formats. Manifests bind the
exact object, origin URL, source-native snapshot, license, retrieval time, byte
length, digest, and typed coverage. Full, partition and delta graphs reject gaps,
cycles, overlap, cross-provider replacement and ambiguous active branches. Failed
or incomplete imports cannot replace complete evidence.
Destination and identity decisions bind exact evidence fingerprints, including
names, assertions and normalization context. Reviews expire within 90 days.
Changed evidence invalidates earlier approvals. Resolution abstains on ambiguity,
ties, missing approval or ineligible claims; regional scopes must explicitly
match. Reviewer decisions are signed under a dedicated SSH namespace and the local
writer retains their exact decision/signature bytes in the append-only review log.
URL and domain normalization is deterministic and uses the complete retained
Public Suffix List, including PRIVATE rules. Names and hostnames never merge
entities. Source-specific popularity stays separate from identity. Every fact
keeps source, source identifier, selector, license, retrieval time, confidence and
raw evidence needed for audit.
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, 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.
Names, entity-to-property edges and entity equivalences have independent material
fingerprints. Under the reference policy, `resolve` needs two independent votes
for the matched name and two for the selected edge. Reviewer groups and physical
SSH public keys are deduplicated, so aliases for one person or key do not satisfy
quorum. Regional roles require explicit locale or country scope.
A vote signs exact JSON in the `argand-site-registry-vote` namespace and binds the
current assertion, evidence bundle and policy epoch. The writer supplies
`accepted_at`; effective validity starts at the later of acceptance and the
reviewer's time and ends no later than 90 days after acceptance. Future, expired,
wrong-policy, stale-evidence, malformed, untrusted and altered votes do not count.
A retained authenticated revocation is sticky across policy epochs. It blocks
the exact subject until every member of a complete fresh quorum explicitly
supersedes every active revocation ID. Sequence order alone cannot restore a
route. Activation prevents rollback past retained legacy or vote revocations.
A cumulative emergency feed carries the same granular revocation identities under
a distinct publisher signature namespace. Compatible pinned consumers apply it
before name, equivalence, and edge selection. Replacement feeds cannot discard
previous subjects or vote IDs. Cross-generation feeds can only add blocks; a block
can be cleared only against the exact full generation containing the authenticated
superseding quorum. Feed artifacts expire after seven days and must be refreshed.
The observer accepts only an eligible imported edge. It uses public DNS pinning
for every hop, rejects credentials, private/link-local/reserved targets,
nondefault ports and HTTPS downgrade, and bounds time, redirects, response headers,
raw body bytes, bandwidth and extracted links. It rejects compressed bodies and
redirect loops. Capture replay checks the complete chain and
body digest without network access. HTTP, redirect, canonical, hreflang, JSON-LD,
sitemap, country-selector, DNS, TLS and failure records remain observations. They
cannot approve a name, ownership relationship or role.
The observation contract also accepts rights-reviewed domain-registration state
and malware-policy results without naming a vendor. No such provider is built in;
an operator must verify commercial-reuse terms and preserve its exact source and
rights declaration before importing those records.
Generations bind authenticated SQLite bytes, selected coverage, policy, reviewer
trust bytes, licenses, attribution, and decision-time rules into `COMPLETE.json`.
Readers verify the receipt pin and copy the database into a private unlinked file
before SQLite opens it. Release signing and activation reverify every stored
signature. The strict policy rejects a publisher identity or physical key used for
any reviewer vote.
## What a publisher must establish
The reviewer name and evidence locator in a decision are operator assertions.
The CLI authenticates exact decision bytes to an allowed SSH signer and validates
their structure and evidence binding; it does not retrieve the cited evidence or
prove website ownership.
Protect the writer database and signing key with separate operating permissions.
Restrict who can author decisions and require human review before release signing.
The software verifies evidence integrity and decision authorization. A publisher
still has to determine that the source and observation evidence support the exact
entity, URL, relationship and role. TLS, DNS control, a redirect, `sameAs`, ccTLD,
popularity or source confidence alone is insufficient.
Publish dated evidence supporting the exact entity, URL, relationship, role and
country/locale. Prefer independently corroborated primary evidence with immutable
capture identifiers. Record contrary evidence and uncertainty. TLS, DNS control,
registrable-domain spelling, redirects, `sameAs` or popularity alone cannot
establish every identity or role claim. Future crawler observations remain inputs
to review. Confidence values are assertion scores, not calibrated probabilities.
Publishers should:
Choose expiry based on volatility, within the enforced maximum. Do not renew
blindly on a timer. Expired approval should lead to abstention until evidence is
reviewed. Disclose editorial conflicts and use an independent reviewer for a
disputed claim when possible. The implementation is a local single-writer tool
with externally authenticated reviewer keys; it does not provide accounts or an
enforced quorum.
- keep acquisition, writer, reviewer and release authorities separate;
- protect reviewer and publisher keys outside the repository and CI;
- configure real organizational reviewer groups instead of relying only on unique
identity strings;
- examine conflicts and current independent evidence in each review bundle;
- choose shorter expiries for volatile or high-risk routes;
- refresh observation evidence independently from source import cadence;
- review drift and produce signed emergency revocations promptly;
- run diff, evaluation, license and signature gates before release; and
- preserve source objects, generations, trust roots, pins and revocations for
audit and recovery.
Changing policy or reviewer trust produces a different receipt. It does not
silently reinterpret old votes as decisions under the new policy. Removing a key
can also make retained signature verification fail; plan rotations with OpenSSH
validity epochs and immutable history.
## What consumers must preserve
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.
Authenticate the publisher and reviewer trust roots independently, or obtain the
full receipt pin over a channel that is already trusted for the complete release
decision. A hash beside an untrusted download authenticates nothing.
Deliver revocations to every active consumer and derived catalogue, and bound cache
lifetimes. The resolver checks review expiry at query time; a detached cached URL
does not recheck itself. Preserve the current review history during rollback.
Copying SQLite rows or the JSONL export into a second resolver can bypass these
checks; use the native API or CLI for admission decisions.
Use `resolve` for navigation. `lookup`, exports, raw SQLite rows and observation
views are audit evidence and can include unreviewed, conflicting, superseded or
malicious claims. Preserve null destinations and typed abstention reasons. Apply
application-specific malware, content and destination policy because a legitimate
site can later be compromised.
## Community changes
Keep license and attribution artifacts with caches and derived datasets. Bound
cache lifetime by vote expiry and revocation delivery. A detached URL copied from
an earlier result no longer performs policy, freshness or rollback checks.
Treat public submissions as untrusted evidence. Do not execute submitted content
or copy review decisions into production automatically. Source allowlist and
attribution changes need both implementation tests and documented rights review.
Reject unknown sources until those checks are complete. Every publisher may apply
stricter admission rules, and must state its actual review and incident procedures.
## Community submissions
Treat public issues, manifests, source files, captures and vote proposals as
untrusted input. They may suggest evidence but cannot write the protected store,
approve, publish or activate a generation. Unknown providers remain unsupported
until current commercial-reuse rights, format, lineage, attribution and tests are
reviewed. Public contribution does not imply production admission.