From 0319fe8be846ad0f87e0888f6b1314bc5349f549 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 19 Oct 2026 14:01:28 +0200 Subject: [PATCH] docs: specify disabled Custodian runtime delivery choices Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a15374-f59f-7a31-86d2-d23b5d2ed181 --- docs/custodian-bounded-operations.md | 3 + docs/custodian-runtime-binding-proposal.md | 124 +++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 docs/custodian-runtime-binding-proposal.md diff --git a/docs/custodian-bounded-operations.md b/docs/custodian-bounded-operations.md index c72485a..7170d9c 100644 --- a/docs/custodian-bounded-operations.md +++ b/docs/custodian-bounded-operations.md @@ -71,3 +71,6 @@ also remain. Retain the first unattended activity, report, sink and owner receip tests/test_custodian_operations.py uses temporary fixture commands or mocked dispatch. It never invokes the real security command, Hub or schedule activation. + +Concrete delivery options and unresolved owner choices are recorded in +[custodian-runtime-binding-proposal.md](custodian-runtime-binding-proposal.md). diff --git a/docs/custodian-runtime-binding-proposal.md b/docs/custodian-runtime-binding-proposal.md new file mode 100644 index 0000000..286d168 --- /dev/null +++ b/docs/custodian-runtime-binding-proposal.md @@ -0,0 +1,124 @@ +# Custodian runtime binding proposal + +Review artifact, 2026-10-19. Not a deployment or activation approval. Both native +ActivityDefinitions remain `enabled: false`. No manifests, images or schedules +were changed for this proposal. Read with `custodian-bounded-operations.md`. + +## Verified source boundary + +The worker in `k8s/railiance/20-runtime.yaml` runs as UID/GID 1000 and already +uses `actcore-ops-artefacts` for freshness and owner-return subdirectories. Its +image does not contain the Custodian commands; its current mounts contain +neither the accepted fleet workplans/decisions nor the new private state. +`CUSTODIAN_REPO_ROOT=/var/custodian` only binds existing prompts/working memory; +it does not satisfy any `ACTIVITY_CORE_CUSTODIAN_*` binding. + +The existing immutable ConfigMap plus read-only mount pattern documented in +`k8s/backup-release/README.md` is sufficient for the small command bundle. No +new packaging service is needed. Proposed source pin: +`the-custodian@60d893af1bf77f457504b64ff1c9ffb5c6ae6579`. +These four files total 30,169 bytes and use Python standard-library modules; +the daily command imports/calls the two sibling helper scripts. + +| Path under owner root | SHA-256 | +| --- | --- | +| scripts/security_flow_daily.py | 4a4e84702b3fb38d086695bb6d601430d8914bd79286b4f683794206f110c353 | +| scripts/security_flow_report.py | eac9fdcc56d7f3ff613e6848c7523fb9a421d82a3b564a51c36f8c2b842eef02 | +| scripts/sync_resolved_decisions.py | 182433ca7cd31e2b2773246ec1be02569ba6f089ac009add6543e5e48777b5ec | +| scripts/weekly_allocation_report.py | 93f546243331308d7e60f8db36e988d9847537a2fe46cce49ee2fffba1f7f247 | + +A reviewed immutable ConfigMap can map these four keys to `scripts/` +below `/opt/custodian-commands`. Kubernetes ConfigMap volume projections use +symlinks, which the executor deliberately rejects. Therefore copy the mounted +immutable bundle into a dedicated emptyDir in an init container, verify all four +hashes there, then mount that copy read-only in the worker. Do not bind the +projected ConfigMap directly or weaken executor symlink checks. Alternatively, +copy the same pinned files into the existing worker image during its reviewed +build. The latter avoids the init-container copy and is the narrower runtime +mount boundary, but requires an accepted source-delivery/build input. Neither +alternative has been chosen or implemented here. + +## Exact proposed bindings and outstanding choices + +| Binding | Proposed value / owner decision | +| --- | --- | +| ACTIVITY_CORE_CUSTODIAN_ROOT | `/opt/custodian-commands`, regular files, read-only, hashes above | +| ACTIVITY_CORE_CUSTODIAN_FLEET_ROOT | `/var/lib/custodian-inputs/fleet`, read-only accepted snapshots | +| ACTIVITY_CORE_CUSTODIAN_STATE_ROOT | `/var/lib/activity-core/custodian`, persistent, UID 1000, mode 0700 | +| ACTIVITY_CORE_CUSTODIAN_REPOS | Explicit operator-approved subset of the daily report estate; each must have `workplans/` | +| ACTIVITY_CORE_CUSTODIAN_HUB | `http://state-hub.state-hub.svc.cluster.local:8000`, subject to admitted network verification | +| ACTIVITY_CORE_CUSTODIAN_ALLOCATION_REQUEST | `/var/lib/activity-core/custodian/requests/current.json`, regular file protected against concurrent writers | + +For daily input, preserve `/workplans/**/*.md` including dependency records +and `/decisions/*.md` only for approved decision-sync scope. The decision +helper scans every repo under the fleet root independently of the report list. +Do not mount a whole workstation home, `.git`, credential directories or arbitrary +mutable repositories. Fleet snapshots need per-repo revision, capture time, +refresh owner and an explicit staleness policy. No existing publication contract +for this combined input was found in the worker manifests. Choosing its publisher +is a real prerequisite; a pinned old snapshot alone cannot support daily freshness. + +Weekly input remains the existing retained collector outputs plus request JSON, +not a new collector. Its owner must bind actual input/report paths and evaluation +time, freeze the request across retries, and publish a new request for the next +week. The executor does not advance a static `current.json` automatically. +Snapshot publication must be atomic relative to execution and preserve retained +inputs needed to reproduce reports. Never substitute synthetic readings. + +Storage choice: reuse a new `custodian` subdirectory of existing +`actcore-ops-artefacts` only after its owner accepts capacity, retention and backup +coverage, or provision a dedicated claim with those properties. The existing +rollout document describes a 1Gi local-path claim, and October 4 evidence reports +it Bound; neither proves present capacity or backup coverage. Precreate state, +`security-flow`, `requests` and output/input retention directories with correct +ownership. Do not chown/chmod the whole shared claim. A PVC subPath is acceptable +if actual mounted paths are regular directories and pass executor validation. + +The proposed direct Hub service matches the worker's existing +`STATE_HUB_API_BASE`; the shared config also contains an edge-relay URL. Daily +message delivery requires a central message ID. A relay queued receipt is pending +evidence and is not interchangeable with that ID; do not select relay delivery +without an explicit adapter/replay contract. Needed operations are GET open +decisions, POST decision resolution, POST messages, and the existing progress +sink. Runtime network authorization remains unverified. The shared worker already +has secret env and kube mounts: this proposal does not establish credential isolation. + +Placement choices for owner review: + +1. Existing production worker: choose image-baked scripts or verified copied + immutable bundle, choose fleet publisher and state claim above, then review + normal owner GitOps changes. This reuses the present Temporal task queue. +2. Workstation execution: requires an explicitly routed worker/task queue and + a durable always-on ownership/connectivity contract. Merely starting another + worker on `orchestrator-tq` is unsafe because either worker may receive these + activities. No workstation routing or second scheduler is proposed. + +## Verification and rollback before activation + +Prepare the accepted source bundle and manifest diff outside active kustomization +until the choices above are recorded. Preserve both disabled definitions; native +schedule synchronization creates disabled definitions paused. Verify their DB +versions and Temporal paused state after any later deployment, without firing. +Mount/env changes exceed image-only promotion authority; follow owner-reviewed +GitOps promotion, not a widened image-only helper. + +Local source tests already cover parsing both disabled definitions, missing-binding +refusal before subprocess, fixed commands, symlink rejection, bounded timeouts +and sanitized receipts. At delivery review, independently verify pinned hashes, +worker Python imports, UID/modes, mount read-only flags, free retained capacity, +scoped fleet revision/age and actual request/output confinement. Use fixture inputs +for initial process verification; daily dry-run still reads Hub and therefore is +not an offline test. Obtain separate authorization for real Hub operations. + +After operator-approved runtime placement, retain exact worker image/bundle and +input revisions, operation context, owner report hash, progress sink result and +owner acknowledgment. Scheduled activation and first unattended run remain +ACTIVITY-WP-0047-T02/T03 and CUST-WP-0071-T04/T05 gates. An exit-zero fixture +or a paused schedule does not satisfy them. + +Rollback: keep both schedules paused, restore the previous reviewed worker +image/config/bundle references through GitOps, and keep old bundle objects until +no rollback ReplicaSet references them. Preserve private reports, checkpoints +and requests; do not delete the state claim. Inspect partially delivered daily +checkpoints before retrying, because rollback cannot undo Hub writes. Do not +reuse or overwrite an immutable weekly output for revised inputs.