argand-site-registry/docs/PUBLISHING.md

114 lines
5.4 KiB
Markdown

# Dataset publisher runbook
Scheduled acquisition and observation jobs create evidence and candidates. Human
reviewers vote on exact bundles. A separate publisher signs and activates an
accepted generation.
## Prepare trust and state
Keep source caches, captures, writer database, generations, reviewer keys,
publisher keys and consumer trust files outside the checkout. A reviewer
allowed-signers file contains one principal and public key per line. Add OpenSSH
validity options when rotating keys and preserve old keys for retained history.
Create a reviewed policy JSON when the reference policy is not appropriate. The
reference policy requires two independent identities, groups and physical keys
for every name, edge and equivalence; sticky revocations and publisher separation
are mandatory. Record actual group membership in `reviewer_groups`. Optional
`risk_thresholds` can require a larger quorum for `source_conflict` or
`dangerous_drift`; blocking those risks remains separately configurable.
## Build and inspect a candidate
1. Import only manifests whose source, format, license and typed coverage were
checked. Keep the object and acquisition receipt.
2. Build with `--reviewer-trust`; record the returned receipt pin.
3. Run `verify`, `stats`, `diff`, `export-audit` and the fixed evaluation corpus.
4. Inspect `review-queue`, `evidence`, exact entity/domain reverse lookups and
source-separated popularity.
5. Run candidate observations on a bounded schedule and import their manifests.
Review `drift` and `revocation-candidates`; rebuild after imports.
Queue viewing is read-only. Observation import changes evidence bundles but never
route state.
## Create authenticated votes
Use `prepare-vote` for a name or edge, or `prepare-equivalence-vote` for an exact
entity pair. The command writes canonical JSON containing the current evidence
and policy digests. Review those exact bytes, then sign them:
```bash
ssh-keygen -Y sign -n argand-site-registry-vote \
-f /secure/reviewer-one vote.json
argand-site-registry verify-vote \
--generation /data/registry/candidate --pin "$CANDIDATE_PIN" \
--decision vote.json --signature vote.json.sig \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity reviewer-one
argand-site-registry vote \
--database /data/registry/import.sqlite \
--generation /data/registry/candidate --pin "$CANDIDATE_PIN" \
--decision vote.json --signature vote.json.sig \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity reviewer-one
```
Repeat with enough independently controlled identities, groups and keys. Use
`equivalence-vote` to append equivalence votes after
`verify-equivalence-vote`. Rebuild and check the compiled decision. Never share
one private key under several reviewer names.
An approval expires within 90 days and begins no earlier than writer acceptance.
A revocation has no expiry. To restore a revoked subject, every new approval in a
complete quorum must list every active revocation ID in `supersedes`.
## Sign and activate
Run all offline gates and the separate network-enabled dependency audit. The
publisher identity and physical key must not have supplied any reviewer vote.
```bash
argand-site-registry sign --generation /data/registry/reviewed \
--pin "$REVIEWED_PIN" --key /secure/publisher-key \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity registry-publisher
argand-site-registry activate --generation /data/registry/reviewed \
--current /data/registry/current.json \
--allowed-signers /secure/publisher-allowed-signers \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity registry-publisher
```
Record the source-code revision, provider manifest IDs, candidate and reviewed
pins, policy and reviewer-trust digests, diff, evaluation report, publisher
identity, and activation result in an immutable operator log outside Git.
Distribute the complete generation, signature, and independently authenticated
publisher trust root. Confirm every consumer received the new revocation state.
For an incident, preserve the suspect evidence, append a signed revocation,
rebuild with full history, evaluate, sign and activate. Use
`revocation-candidates` only as review input; it never signs or appends a vote.
To protect pinned consumers before the full generation arrives, publish a small
cumulative feed under the distinct publisher namespace:
```bash
argand-site-registry export-revocations \
--generation /data/registry/revoked --pin "$REVOKED_PIN" \
--effective-at 2026-09-13T00:00:00Z --output /data/revocations.json
argand-site-registry sign-revocations \
--generation /data/registry/revoked --pin "$REVOKED_PIN" \
--input /data/revocations.json --output /data/revocations.json.sig \
--key /secure/publisher-key \
--allowed-reviewers /secure/reviewer-allowed-signers \
--identity registry-publisher
```
Signing recomputes the feed from the pinned generation and re-verifies every
reviewer vote. Distribute the exact feed, signature, and publisher trust root.
When replacing a feed, verify it with the prior feed and signature so a mirror
cannot discard a revocation. Refresh feeds before their seven-day deadline. A
newer compatible feed can block an older pinned generation, but clearing that
block requires installing its exact full generation so the consumer can recompute
the authenticated superseding quorum.
Follow [SECURITY.md](../SECURITY.md) for private disclosure and key compromise.