Fix R11: pin cryptography; prod runbook for SIGIL_ANCHOR + SIGIL_SEAL_PASS #11

Merged
leora merged 1 commits from leora/fix-r11-runbook-deps into sigil-initial 2026-10-06 06:16:06 +08:00
4 changed files with 62 additions and 5 deletions

View File

@ -229,7 +229,7 @@ sessions mintable from a bare agent name, no revocation operation at all, an
unkeyed chain that a database-level attacker could rebuild, and SQLite without unkeyed chain that a database-level attacker could rebuild, and SQLite without
a busy timeout. a busy timeout.
Leora's contracted prod pass (Quarry 18a5d762) closed three remaining review blockers on this branch: rekey no longer un-revokes, dual-bootstrap enrol is exactly-one under race, and redeem rate limits are per-agent (anonymous fails isolated from success). Off-box checkpoint tip publish/verify ships when `anchor_path` / `SIGIL_ANCHOR` is set. SealedStore / `SIGIL_SEAL_PASS` seals the DB file with AES-256-GCM (incremental path short of SQLCipher). Independent review and platform glue remain. Leora's contracted prod pass (Quarry 18a5d762) closed three remaining review blockers on this branch: rekey no longer un-revokes, dual-bootstrap enrol is exactly-one under race, and redeem rate limits are per-agent (anonymous fails isolated from success). Off-box checkpoint tip publish/verify ships when `anchor_path` / `SIGIL_ANCHOR` is set. SealedStore / `SIGIL_SEAL_PASS` seals the DB file with AES-256-GCM (incremental path short of SQLCipher). Independent review returned GO-WITH-FIXES; R1–R8/R11 fixes on this branch. Platform glue remains off.
**Still not production ready**, and the reason is not a to-do list: **Still not production ready**, and the reason is not a to-do list:
@ -252,11 +252,27 @@ The tests show the logic is correct. They do not make it safe.
## Next ## Next
1. Independent security review before this guards anything real. Two hardening 1. ~~Independent security review~~ — independent review returned GO-WITH-FIXES
passes made it reviewable; neither substituted for one. (tip c0027bb); fix PRs for R1–R8/R11 landed on `sigil-initial`. Platform glue
remains off until integration review. See `docs/PROD_RUNBOOK.md`.
2. ~~Anchor the checkpoint head digest outside the database~~ — done via 2. ~~Anchor the checkpoint head digest outside the database~~ — done via
`Store(..., anchor_path=)` / `SIGIL_ANCHOR` (signed tip file + `.log`). `Store(..., anchor_path=)` / `SIGIL_ANCHOR` (signed tip file + `.log`).
**Prod must set it** (see runbook).
3. Secret broker on top — scoped, short-lived leases bound to a key fingerprint. 3. Secret broker on top — scoped, short-lived leases bound to a key fingerprint.
Its issuance and redemption logs *are* the work-attestation substrate, so it Its issuance and redemption logs *are* the work-attestation substrate, so it
is the natural second piece. is the natural second piece.
4. Deprecate passcode login across the platform, then rotate live credentials. 4. Deprecate passcode login across the platform, then rotate live credentials.
### Info / follow-ups (no code change required yet)
- **R9 — `issue_agent_session`:** library helper mints `agent:act` from a name
after the caller claims to have verified. Keep internal; integration must
never mint from headers/names. Consider renaming to `_issue_agent_session`.
- **R10 — challenge domain separation:** signatures currently cover
`nonce.encode()` with no context prefix. Adding
`b"sigil-challenge-v1\0" + nonce` is not backward-compatible with in-flight
challenges; schedule with a protocol version bump (follow-up).
- **R12 — multi-process rate limits:** quotas are per-`Store` / per-process.
Single writer until a shared limiter exists (documented in README + runbook).
- **R13 — opt-in anchor:** without `SIGIL_ANCHOR`, deleting in-DB checkpoints
allows silent history rewrite. Runbook requires the anchor on separate storage.

View File

@ -158,4 +158,9 @@ The tests assert the logic is correct. They do not make it safe.
## See also ## See also
`DESIGN.md` — the design page: rationale, flows, session stamps, the invariant `DESIGN.md` — the design page: rationale, flows, session stamps, the invariant
and its reasoning, and what is deferred. and its reasoning, and what is deferred.
`docs/PROD_RUNBOOK.md` — production checklist: require `SIGIL_SEAL_PASS` and
`SIGIL_ANCHOR` on separate storage, verify-chain alerts, integration sharp edges.
`requirements.txt` — pinned `cryptography>=43.0.0,<45`.

33
docs/PROD_RUNBOOK.md Normal file
View File

@ -0,0 +1,33 @@
# 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.
## 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.

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
# Runtime dependency for Ed25519 + AES-GCM (SealedStore / optional key files).
# Pin a known-good lower bound; upper bound avoids surprise major breaks in CI.
cryptography>=43.0.0,<45