audit-7 + docs: plan systemd units, D13-D15
- cayce-ops-plan.service/.timer (daily): the @ template cannot express publisher plan, so it gets its own unit - DECISIONS: D13 no non-human approvals; D14 signatures bind content + deployment; D15 negation veto classifier
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=cayce-ops publisher plan (fills the content calendar, daily)
|
||||||
|
After=network-online.target postgresql.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User=cayce
|
||||||
|
WorkingDirectory=/srv/cayce-ops
|
||||||
|
EnvironmentFile=/srv/cayce-ops/.env
|
||||||
|
ExecStart=/srv/cayce-ops/.venv/bin/cayceops publisher plan
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
ReadWritePaths=/srv/cayce-ops
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Run cayce-ops publisher plan daily
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 06:00:00
|
||||||
|
RandomizedDelaySec=300
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
@@ -95,3 +95,25 @@ caption hash-bound at approval, disabled channels are terminal (`SKIPPED`),
|
|||||||
publish failures burn a bounded attempt budget before abandonment.
|
publish failures burn a bounded attempt budget before abandonment.
|
||||||
`risk_score` renamed `match_score` (keyword relevance) and auto-approval
|
`risk_score` renamed `match_score` (keyword relevance) and auto-approval
|
||||||
takes the HIGHEST score first.
|
takes the HIGHEST score first.
|
||||||
|
|
||||||
|
## D13 — No non-human approval path (round 2, supersedes D5)
|
||||||
|
Operator signatures are mandatory for approvals AND re-verified at
|
||||||
|
execution/send/publish time against current content + deployment id. With
|
||||||
|
that gate, the AUTONOMOUS_MODE auto-approval path cannot exist: it would
|
||||||
|
produce unsigned approvals the gate refuses. `_auto_approve` is inert and
|
||||||
|
audits `autonomy_disabled` when invoked. *Cost:* AUTONOMOUS_MODE is now
|
||||||
|
inert by design.
|
||||||
|
|
||||||
|
## D14 — Signatures bind content + deployment (round 2)
|
||||||
|
message = sha256("cayce-ops:<type>:<deployment_id>:<id>:<content_hash>").
|
||||||
|
content_hash is canonical-json of the fields that matter per type. Full
|
||||||
|
signatures live on the row (operator_signature) and in the audit detail.
|
||||||
|
Verification happens again at run time: unsigned rows (raw SQL approval)
|
||||||
|
revert to their pre-approval state with an error audit. *Cost:* a deployment
|
||||||
|
id env var is mandatory; signatures must be recomputed if content changes.
|
||||||
|
|
||||||
|
## D15 — Approval classifier veto (round 2)
|
||||||
|
Any negation token anywhere in a mail vetoes an `approval` classification →
|
||||||
|
needs_review. Simpler and strictly conservative vs. per-pattern negation
|
||||||
|
lists. *Cost:* genuinely-positive approvals containing stray negations
|
||||||
|
(e.g. "we have no reason not to welcome you") need human triage.
|
||||||
|
|||||||
Reference in New Issue
Block a user