--- id: CUST-WP-0079 type: workplan title: "Deterministic security flow: standing authorizations, flow report, and agent re-engagement" domain: infotech repo: the-custodian status: blocked owner: claude-code topic_slug: custodian created: "2026-10-11" updated: "2026-10-13" flavor: implementation depends_on: [] state_hub_workstream_id: "ab288f92-d364-5c24-9362-aee451f266c3" --- Follow-up to `history/20261011-netkingdom-security-progress-assessment.md`. About 80 % of the security estate's open tasks were `wait`, and agent time went into re-reading waits and producing evidence packets. This plan replaces that loop with (1) standing founder authorizations, (2) deterministic reports and sync, and (3) a narrow, re-scoped coding-agent goal. Critical path (everything else is residual until promoted): identity (key-cape, user-engine) → authorization (access-engine + policy-nexus guardrails) → secrets (secrets-engine over OpenBao, response-wrapped delivery) → SecurityCase execution (ops-mason → ops-warden / ArgoCD), proven first on oidc-browser-relying-party (NK-WP-0048-T06, KEY-WP-0038). ## Founder decision batch and hub/repo decision sync ```task id: CUST-WP-0079-T01 status: done priority: high state_hub_task_id: "618b32bb-3b30-5c31-b054-65b455d62b0b" ``` 2026-10-11: D1, D2, D3 resolved, plus round 2 (standing build-mode change rule; D10 MFA remainder; D4 + D5). Recorded in `docs/decisions/2026-10-11-security-unblock-decisions.md`. 31 open hub decisions were already resolved in repo decision logs (gate-house, kings-guard, tenant-engine, security-canon, repo-manager) and were synced. Open hub decisions went from 61 to 22. 26 tasks were requalified, including fixes for tasks mislabeled as human gates. 10 workplans were demoted to residual. ## Deterministic tooling ```task id: CUST-WP-0079-T02 status: done priority: high state_hub_task_id: "2764581a-ff8f-5a05-90bd-3dc6bd058ae5" ``` `scripts/security_flow_report.py` (READY / UNBLOCKED / ATTENDED / STALLED from workplan files), `scripts/requalify_tasks.py` (apply task requalifications from a JSON plan), `scripts/sync_resolved_decisions.py` (resolve hub decisions that repo logs already record as resolved or accepted). ## Schedule the flow report and decision sync ```task id: CUST-WP-0079-T03 status: wait priority: high state_hub_task_id: "1be0569c-221d-5925-a0ff-fd2af88e52b1" depends_on: [ACTIVITY-WP-0047] blocking_reason: "Activity Core accepted the schedule in ACTIVITY-WP-0047. Await claiming rein workstation/hub acceptance, owner activation and the first unassisted fire with report/checkpoint evidence." ``` Run `sync_resolved_decisions.py --apply` and `security_flow_report.py --json` daily (activity-core schedule, or a workstation timer until activity-core has the lane). Post a hub message to the coding agent only when UNBLOCKED or READY changed, and to the founder only when ATTENDED is non-empty. Agents must not poll wait tasks themselves. Implementation (2026-10-11): `scripts/security_flow_daily.py` runs both commands, includes `the-custodian` in the default security estate, checkpoints each delivered recipient, and notifies the coding agent only when READY/UNBLOCKED changes. Empty ATTENDED lists never message the founder. User timer units are in `infra/security-flow/`; `make security-flow-check` passes nine tests including interrupted delivery and retry. Live hub dry-run succeeds. Schedule activation handoff `117e538e-da06-48b8-ba68-b82300a832e7` to `activity-core` is attached to `case:cross-owner:CUST-WP-0079-T03:activity-core` (`infra/security-flow/scheduling-handoff.json`); no owner acceptance or foreign dependency is invented. Schedule activation remains pending: workstation `systemctl --user` cannot connect to its user bus (`No data available`), so checked-in units alone do not establish daily execution. 2026-10-13 owner return: Activity Core accepted the handoff in message `00704319-97b2-469c-977e-6168ef20b9f9`. Verified owner record `ACTIVITY-WP-0047` (implementation, active) and committed definition `activity-definitions/daily-security-flow.md`: daily 07:30 Europe/Berlin, misfire skip, fixed `python3 scripts/security_flow_daily.py --apply` command, correlation CUST-WP-0079-T03, no repository grant. Definition remains `enabled: false`; source acceptance is complete, activation is not. The existing coordination case now names ACTIVITY-WP-0047 as obligor. T03 remains wait until its claiming rein can reach workstation checkouts/the hub, the owner activates the schedule, and the first unassisted fire proves completed ops_run, report delivery and checkpoint behavior. No scheduler was enabled and no foreign owner task was changed by this reconciliation. ## Encode the standing change rule as a policy-nexus guardrail ```task id: CUST-WP-0079-T04 status: wait depends_on: [PNEX-WP-0006] blocking_reason: "policy-nexus owns guardrail publication; handoff written as PNEX-WP-0006." priority: high state_hub_task_id: "5dd52156-09a8-5781-b288-99ae822f59a6" ``` Canon source written 2026-10-11: `canon/standards/build-mode-change-authorization_v0.1.md` (founder-decided). Closes when PNEX-WP-0006 publishes it. ## Stop agent-authored index and sync commits ```task id: CUST-WP-0079-T05 status: wait blocked_on: message-from:repo-manager blocking_reason: "Local guard and repeatable shared-hook installation are implemented. Fleet generator adoption and the required full week of clean history remain unverified; repo-manager owner acceptance is needed." priority: medium state_hub_task_id: "8a3dc219-8982-5903-9407-e1b549d4544c" ``` WORK-RECORDS.md, source inventories, publication indexes and "projection refresh" files must be regenerated by a `make` target in a pre-commit hook or a Forgejo Action, not by agent commits. Start with the security repos. Done when a week of git log shows no standalone index-only commits from agents. Implementation (2026-10-11): `scripts/check_generated_only_commit.py` checks staged files or every commit in a revision range. Forgejo workflow `generated-commit-guard.yaml` rejects standalone WORK-RECORDS, source-inventory, publication-index, projection-refresh, generated briefs and explicit evidence/decision-packet commits regardless of author; a later source commit cannot hide an earlier generated-only commit. `make generated-commit-check` provides the local hook entry point. The CI suite covers the rejection using a real temporary git repository. Consumer generator adoption and the required week of clean logs remain open; this task is not claimed complete. The local guard is installed; `make generated-commit-hook` reproduces that installation and refuses to replace a different hook. The consistency CLI has no no-commit/no-push mode: its first invocation unexpectedly published brief-only `ebaa38b`, retained as a failed acceptance observation. Its subsequent invocation committed the already reviewed, staged implementation as `6fe7201`; that commit includes source code. Future generated-only commits are rejected locally and in CI. The full Custodian suite passes 77 tests. The default flow report now includes Custodian and activity-core, both required by the renewed critical path. Cross-owner completion can therefore unblock the platform activation task without an agent polling its wait body. Human gates also retain their intervention note in the generated report instead of a blank reason. CLI regression checks cover the actual owner completion transition and the default Custodian lane. The report also excludes todo/progress tasks with unresolved explicit task dependencies, an owner gate or a human flag from READY. They remain visible under DEPENDENT or ATTENDED, without agent polling of wait bodies. Regression tests prove that owner completion admits the successor and that an unknown predecessor or stale progress label cannot produce readiness. This is queue qualification, not evidence that the corresponding live work has finished. `scripts/install_shared_generated_guard.py` now checks or installs the guard in the repository's already configured shared hook directory. It preserves existing hook routing and other hooks, and refuses a differing or redirected pre-commit hook. Real temporary-repository tests prove rejection and source-change acceptance. The missing shared guard was installed for the existing repo-manager hook path; the week's fleet evidence and generator adoption still remain open. The generated attended list now retains unresolved ordered dependencies. An owner token session following the first SecurityCase can therefore be listed as a future attended act without implying it is ready to run now. CLI regression coverage checks this boundary. 2026-10-12 closeout: `make generated-commit-hook` now recognizes the existing shared hook and preserves its routing and other owner hooks. A real Git/Make regression test checks repeat installation and rejection of a generated-only commit. Local implementation is complete; T05 remains waiting for fleet generator adoption and the originally required week of clean history. Neither one day of observations nor this local repair satisfies that acceptance condition. Session closeout reviewed all three open Custodian plans. CUST-WP-0071 and CUST-WP-0073 remain blocked on their existing named owner/founder returns. CUST-WP-0079 is now blocked because all remaining tasks wait on scheduling-owner acceptance, policy publication, fleet/time-based acceptance or attended actions. No tasks or workplans were added, and CUST-WP-0076 remains finished. The cross-repo critical-path goal was paused by the operator; this bounded closeout does not resume it or claim native estate completion. ## Attended window #1 ```task id: CUST-WP-0079-T06 status: wait needs_human: true blocking_reason: "Partly done 2026-10-11: list cut from 14 to 3; U05-U07 accepted, U08 waits on KEY-WP-0040-T01. Remaining founder acts: USER-WP-0026-T03 readback, RPF-WP-0044-T08 coulombcore check, the U08 re-run, and Sol's added RPF-WP-0044-T04 issuer login." priority: high state_hub_task_id: "e3da807f-9a6e-513f-82dc-3714a489e7bf" ``` ## Re-engage the coding agent with the renewed goal ```task id: CUST-WP-0079-T07 status: done priority: high state_hub_task_id: "91ec924c-b305-5a63-925d-087a3b927d60" ``` Replace the Sol goal with the renewed text in the assessment history file (section "Renewed goal"). Re-engage now for the READY lane. It does not depend on T06. Completed 2026-10-11: the renewed critical-path goal is active in thread `01a126e1-76f8-7643-8cf3-e93336539ade`; its attached text was read before execution. Work resumed from READY/UNBLOCKED, with three workers pinned to eligible workplans and the accepted build-mode authorization in force. This closes re-engagement only, not the live critical-path goal.