Security Sign-off Rubric — Stargraph v1¶
Status: Phase-5 prerequisite. A Stargraph release cannot ship to a cleared deployment until every item below is checked by a non-author reviewer and the signoff template at the bottom is filled in.
Spec ref: stargraph-serve-and-bosun §12.2 (FR-64, FR-67, AC-8.4).
This document is the canonical 13-check rubric. Each check has a verifier (the command/test/observation that proves the check) and an owner (the code-area maintainer responsible if the check regresses).
Pre-release checks¶
-
STRIDE matrix completeness —
docs/security/threat-model.mdhas all 36 cells filled (noTBD, no???). Every documented gap has a tracked post-1.0 issue link. Verifier: visual review +grep -c '|' docs/security/threat-model.md | awk '$1 >= 36'. Owner: security lead. -
Capability-deny audit emission (task 3.22) — denying a capability at the route gate emits a
request_auditevent withstatus="denied"andcapability=<name>. Verifier:tests/integration/test_capability_deny_audit.pygreen; manual curl probe against aclearedprofile returns 403 + audit row visible in JSONL sink. Owner: serve-API maintainer. -
Pack signing alg-strict (task 3.21) — the Bosun pack signature verifier rejects
none, HS256, and RS256 algorithms; only Ed25519 is accepted. Verifier:tests/unit/bosun/test_signing_alg_strict.pycovers the three rejected algs + the accepted Ed25519 path. Owner: Bosun maintainer. -
TOFU + static allow-list pubkey distribution (task 2.27) — first-pin records the pubkey to
~/.stargraph/known_packs.json; subsequent loads compare to the pinned value; static allow-list instargraph.tomloverrides TOFU when present. Verifier:tests/integration/test_pack_tofu.pygreen. Owner: Bosun maintainer. -
Replay isolation (task 3.22) — cf-runs forked via
GraphRun.counterfactualdo NOT execute side-effecting nodes (HTTP, file-write, broker-emit). The replay context blocks them at the side-effect gate. Verifier:tests/integration/test_replay_isolation.pycovers the 3 side- effect categories. Owner: replay maintainer. -
NFS refusal at bootstrap (task 3.31) — Stargraph refuses to start when the configured state directory lives on NFS/SMB/AFP (POSIX
statfs(2)lookup). Verifier:tests/unit/serve/test_lifecycle_fs_refusal.pycovers the four refused FS types + the accepted ext4/xfs/btrfs path. Owner: serve- lifecycle maintainer. -
Profile default-deny enforcement (task 2.36) — under the
clearedprofile, the 7 mutation routes (cancel/pause/respond/counterfactual/artifacts r+w/broker) return 403 when the request does not carry the matching capability grant. Verifier:tests/integration/test_profile_default_deny.pyparametrized over the 7 routes. Owner: serve-API maintainer. -
--allow-side-effectsstartup gate under cleared (task 2.37) —stargraph serve --profile clearedrefuses to start unless the operator passes--allow-side-effects(or the equivalentstargraph.tomlflag). The gate is profile-conditional; OSS-default does not require the flag. Verifier:tests/unit/cli/test_serve_side_effects_gate.py. Owner: CLI maintainer. -
WebSocket 1011 disconnect on slow consumer (task 3.19) — the broadcast emit timeout (5s) closes the WS with code 1011 when a subscriber backs up past the timeout. Verifier:
tests/integration/test_ws_slow_consumer.py(parametrized over 3 consumer-stall scenarios). Owner: serve-broadcast maintainer. -
HITL audit body-hash NOT body-content (task 3.13) — the HITL
respondflow records a SHA-256 hash of the response body in the audit fact; never the body itself. Verifier:tests/integration/test_hitl_body_hash.pyasserts the hash field is present and the body field is absent in the JSONL line. Owner: HITL maintainer. -
cf-respond fact carries
source=cf:<actor>(task 3.23, locked Decision #2) — replay-side respond facts emit with thecf:prefix onsource. Verifier:tests/integration/test_cf_respond_provenance.py. Owner: replay maintainer. -
Audit walker pyright/ruff clean —
scripts/lineage_audit.pyscripts/regen_openapi.pypassuv run ruff check scriptsanduv run pyright scriptswith zero findings. Verifier:make lint-scripts(Makefile target). Owner: docs+scripts maintainer.
-
Lineage audit script passes against a real run — given a JSONL audit log from a non-trivial integration test run,
python scripts/lineage_audit.py --strictexits 0. Verifier: capture the audit log fromtests/integration/test_full_run_with_hitl_and_cf.py, thenpython scripts/lineage_audit.py --audit-path <log> --strict. Owner: security lead.
Sign-off template¶
Copy this section into the release ticket. Reviewer fills in the checklist with name, date, and observations. Reviewer must NOT be the author of any of the changes shipping in the release.
Reviewer: ____________________________________________
Email: ____________________________________________
Review date: ____________________________________________
Release tag: v________________________________________
Auditor signature (Ed25519 hex): ____________________________
Pre-release checks
[ ] 1. STRIDE matrix complete (36/36 cells)
[ ] 2. Capability-deny audit emission verified
[ ] 3. Pack signing alg-strict (none/HS256/RS256 rejected)
[ ] 4. TOFU + static allow-list pubkey distribution
[ ] 5. Replay isolation (no side-effects)
[ ] 6. NFS refusal at bootstrap
[ ] 7. Profile default-deny enforcement (7 routes)
[ ] 8. --allow-side-effects startup gate under cleared
[ ] 9. WebSocket 1011 disconnect on slow consumer
[ ] 10. HITL audit body-hash (not body-content)
[ ] 11. cf-respond fact carries source=cf:<actor>
[ ] 12. Audit walker pyright/ruff clean
[ ] 13. Lineage audit script passes against a real run
Observations / open issues:
______________________________________________________________
______________________________________________________________
______________________________________________________________
Recommendation: [ ] APPROVE [ ] BLOCK
Rationale:
______________________________________________________________
______________________________________________________________
Audit retention¶
- Sign-off forms are committed to
docs/security/signoffs/<tag>.mdalongside the release tag. - Reviewer Ed25519 signature pinned per release; the static allow-
list in
stargraph.tomlis updated when a reviewer rotates. - A failed sign-off (BLOCK) does NOT prevent merging the source branch — it prevents tagging + publishing the release. The blocking observations are tracked as issues against the next patch release.