sigil/docs/PROD_RUNBOOK.md
leora 73b9ab4515 Fix N2: agent_keys history keeps checkpoints verifiable after revoke
Permanent revoke and rekey retired the live pubkey without retaining it,
so historical checkpoints and off-box anchors became permanently
unverifiable. Add append-only agent_keys (public material only); retire
on revoke/rekey; verify against the fingerprint-named historical key.
Document a dedicated checkpoint-signer identity in the runbook.
2026-10-06 06:22:13 +08:00

42 lines
2.5 KiB
Markdown

# Sigil production runbook
Short checklist before Sigil guards anything real. Library-only today — do **not**
enable platform glue until an integration review covers session minting.
## Required environment
| Variable | Purpose | Notes |
|----------|---------|--------|
| `SIGIL_DB` | Path to the store file | Prefer a dedicated volume; backups are sensitive (roster + audit). |
| `SIGIL_SEAL_PASS` | AES-256-GCM seal passphrase | **Required in prod.** ≥12 chars. Without it the DB file is cleartext on disk. Seal-on still uses a plaintext `0600` working copy while the process is open — not SQLCipher. |
| `SIGIL_ANCHOR` | Off-box signed tip path | **Required in prod.** Must be on storage **separate** from `SIGIL_DB` (different volume/host). Every checkpoint publishes here; `verify_external_anchors` / `verify-chain` must alert on failure. |
Optional: agent private keys stay **off** the platform host whenever possible; checkpoint signer key preferably offline.
## Dedicated checkpoint-signer identity
Enrol a separate agent id used **only** for `checkpoint` / `publish_anchor`
(for example `sigil-checkpoint`). Do not use a working agent as the tip signer:
compromising and permanently revoking that agent would otherwise retire its key
(history still verifies, but ops alerting on "key retired" gets noisy). Never
store the checkpoint signer's private key in the Sigil DB — public history only.
## Ops loop
1. Open with seal + anchor configured (CLI respects the env vars above).
2. Periodically run chain verify **and** external-anchor verify; page on failure.
3. After permanent revoke (compromise): bootstrap + `enrol_rekey`, then `reinstate`. Reinstate alone does not restore a wiped key.
4. Single writer process until a shared rate-limit store exists (in-process quotas multiply across processes).
## Integration sharp edges (do not ignore)
- Never mint `issue_agent_session` from a client-supplied name or header. Only after a verified challenge-response. Prefer keeping that helper internal to verified paths.
- Human view codes are ~40 bits; keep TTL short; never log raw codes (already hashed in audit).
- Challenge signatures today sign the raw nonce (no domain separation). Changing the signed payload needs a coordinated version bump — tracked as a follow-up, not a silent break.
## Deferred
- SQLCipher / page-level encryption for multi-tenant co-resident hosts.
- Domain-separated challenge payloads (`sigil-challenge-v1` prefix) — backward-incompatible without a protocol version.
- Shared cross-process rate limiter.