informed-decision/tools/prepare_provisioning_window_batch.py

291 lines
14 KiB
Python
Raw Permalink Normal View History

"""Draft the unsigned 2026-10-03 provisioning-window sitting (hub decision D1, CUST-WP-0075).
Five candidate lanes were reviewed against owner source. Only lanes whose sole
missing step is a human act get a memo; the others are recorded as excluded in
the batch index with the owner-source reason. One question per memo. No secret
values. Does not submit, present, create approvals or bind.
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from prepare_compact_batches import REVIEW_GROUP, _memo, _sha # noqa: E402
from informed_decision.memo import Scope # noqa: E402
from informed_decision.records import dumps, memo_from # noqa: E402
SITTING = "2026-10-03-provisioning-window"
ROOT = Path(__file__).resolve().parents[1] / "docs" / "batches" / SITTING
SITTING_ID = "infd-sitting-2026-10-03-provisioning-window"
BATCH = "provisioning"
HUB_DECISION = "62aa95e4-3ccc-4867-8806-5e3db005b483"
MEMOS = [
{
"id": "infd-20261003-p01",
"workplan": "RPF-WP-0035",
"task": "RPF-WP-0035-T06",
"hub_task_prefix": "68bff751",
"question": (
"Accept the passed 2026-09-13 scoped delivery proof for the CCR-2026-0019 "
"secrets-engine approval-client reader as that reader's native delivery acceptance?"
),
"brief": (
"Reader 1 (CCR-2026-0019, applied 2026-09-14) already ran its scoped delivery proof "
"under the attended reader lane and the receipts say passed. RPF-WP-0035-T06 waits only "
"on a human accepting that proof. Accepting runs nothing, delivers no credential and "
"changes no OpenBao object. It does not close T06 by itself."
),
"highlight": (
"Known gaps you accept: the wrong-group human login is untested, and the read check used a "
"nonexistent approval id (HTTP 404 proves authenticated routing, not a usable claim). The "
"proof is from 2026-09-13 and is not re-run. Accepting does not close RPF-WP-0035-T06: the "
"CCR-2026-0018 coordinated disablement still needs KeyCape and Approval Engine confirmation, "
"and the file-delivered secret's removal depends on operator hygiene."
),
"target": Scope(
"credential-lane",
"ccr:CCR-2026-0019-delivery-proof",
"secrets-engine approval-client reader, scoped delivery proof",
"prod",
),
"binding": {
"action": "accept",
"actor": "informed-decision",
"principal": "railiance-platform",
"purpose": "Accept the 2026-09-13 scoped delivery proof for the CCR-2026-0019 secrets-engine approval-client reader",
"target": {
"id": "ccr:CCR-2026-0019-delivery-proof",
"type": "credential-lane",
"system": "railiance-platform",
},
},
"packet": """# RPF-WP-0035-T06 — accept the CCR-2026-0019 scoped delivery proof
Blocking workplan: RPF-WP-0035 (railiance-platform)
Blocking task: RPF-WP-0035-T06 (hub prefix 68bff751)
Hub decision: 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1, attended provisioning window)
Design: railiance-platform `docs/credential-lane-designs/keycape-approval-client-side-readers.md`
Request: railiance-platform `credential-change-requests/CCR-2026-0019-secrets-engine-approval-client-read.yaml` (status `applied`)
## Question
Accept the passed 2026-09-13 scoped delivery proof for the CCR-2026-0019
secrets-engine approval-client reader as that reader's native delivery acceptance?
## One act
Record a human acceptance of a proof that has already run. Nothing executes
because of this memo. No OpenBao, KeyCape or cluster object changes.
## What already ran (reference only)
Both under the attended reader lane, never the platform-admin lane:
```sh
warden access secrets-engine-approval-client-login --exec -- \\
python3 /home/worsch/railiance-platform/scripts/approval-client-reader-preflight.py
warden access secrets-engine-approval-client-login --exec -- \\
/home/worsch/secrets-engine/.venv/bin/python -B \\
/home/worsch/railiance-platform/scripts/approval-client-delivery-check.py
```
## Non-secret receipts (railiance-platform `docs/evidence/`)
- `2026-09-14-ccr0019-operator-binding.json` — role/policy apply and readback
- `2026-09-14-ccr0019-reader-preflight.json` — `status: passed`, `secret_values_read: false`
- `2026-09-14-ccr0019-delivery-check.json` — `status: passed`, `approval_mutations: false`, `cleanup: true`
## Positive evidence the owner expects
- Exact read of `platform/data|metadata/workloads/secrets-engine/approval-client`
- Private delivery of the existing version-1 value; private runtime file removed
- `approval:read` token reaches Approval Engine authenticated (HTTP 404 on a fresh id)
- Warden session exited 0 after self-revocation and helper cleanup
## Negative evidence the owner expects
- Denied: sibling `approval-engine/operator-client`, parent metadata/listing,
an unrelated workload path, policy read, role read
- `approval:consume` token refused on the read route (HTTP 403); no real approval consumed
## Known gaps (required acknowledgement)
- Wrong-group human login untested.
- The 404 read proves routing, not a usable claim on a real approval.
- File delivery outlives the reading process; removal is operator hygiene.
## Rollback / revocation (CCR-2026-0019 lifecycle)
- Deactivate: detach policy `workload-kv-read-secrets-engine-approval-client` from
role `secrets-engine-approval-client-workload-kv-read`; disable the ops-warden
catalog entry. The KeyCape verifier lane is unaffected.
- Compromise: KeyCape disables the `secrets-engine-approval` registration first,
then the value is rotated (shared with CCR-2026-0017) and the policy detached.
## Not decided here
- CCR-2026-0018 retention or coordinated disablement (KeyCape + Approval Engine
+ Platform). T06 stays open until both owners confirm that sequence.
- Any rotation, reseed, `approval:consume` grant, or CCR-2026-0020 (cancelled).
## Must not
- Display or paste the client secret
- Re-run the proof as a substitute for this acceptance
- Treat acceptance as authority for any other lane in the D1 window
""",
},
]
EXCLUDED = [
{
"workplan": "MASON-WP-0007",
"task": "MASON-WP-0007-T05",
"owner_repo": "ops-mason",
"reason": (
"Half the act has no reviewed command. The policy + Kubernetes-auth role script "
"railiance-platform scripts/openbao-tenant-engine-audit-core-sender-eso-attended.sh exists "
"(silent, idempotent, exit 3 on drift), but the row-7 wrapped seed that copies the tenant-engine "
"sender token from the registry to platform/workloads/tenant-engine/audit-core-sender has no "
"script: railiance-platform says it has no helper and the plan only names 'the user-engine "
"migration technique'. A placeholder child must not be approved. Also MASON-WP-0007-T01 "
"(metadata survey: path unused, no conflicting names) is still todo, and ESO's right to create "
"serviceaccounts/token in namespace tenant-engine is unverified (MASON-WP-0007-T06)."
),
"ready_when": (
"ops-mason or railiance-platform commits a reviewed silent seed helper, T01 survey is recorded, "
"then one memo covers policy/role apply plus seed."
),
},
{
"workplan": "RPF-WP-0035",
"task": "RPF-WP-0035-T02",
"owner_repo": "railiance-platform",
"reason": (
"Design docs/credential-lane-designs/secrets-engine-service-jwt.md is 'proposed, not provisioned'. "
"Its 2026-09-27 return supplies inputs (openbao/auth/keycape-services-config.json, "
"openbao/auth/secrets-engine-jwt-role.json, openbao/policies/secrets-engine-login-self.hcl) but "
"no reviewed child command and says 'Do not execute a placeholder command'. Live KeyCape client "
"registration and protected client-side custody remain unverified, and first-lane apply is "
"gated on SECRETS-WP-0007-T04. The earlier sitting memo infd-20260914-c02 for this task was "
"created 2026-09-15 and expired unbound 2026-09-16."
),
"ready_when": (
"railiance-platform accepts the design, commits the reviewed silent install/verify child, and "
"records KeyCape registration + custody."
),
},
{
"workplan": "RPF-WP-0035",
"task": "RPF-WP-0035-T08",
"owner_repo": "railiance-platform",
"reason": (
"The attended first-provision already happened. factory-audit-senders-review.md 'Current "
"execution status': both version-1 credentials provisioned (seed receipt "
"2026-09-11-factory-audit-sender-seed.json) and delivered (2026-09-11-factory-audit-delivery-live.json, "
"delivered_and_scope_verified_pending_producer_acceptance); CCR-2026-0021/0022 applied; 'Do not "
"repeat provisioning or delivery'. What remains is owner acceptance (independent archive readback, "
"audit bearer-revocation), not an attended OpenBao act. The task's blocking_reason is stale."
),
"ready_when": "railiance-platform re-qualifies T08 to its real remaining owner acceptance work.",
},
{
"workplan": "RAPPCOREHUB-WP-0003",
"task": "RAPPCOREHUB-WP-0003-T04",
"owner_repo": "rapp-core-hub",
"reason": (
"No credential change request, design or provisioning script exists for a dedicated "
"read:repository Forgejo identity for the core-hub publisher (the only read:repository lane, "
"CCR-2026-0014, belongs to policy-nexus and must not be reused). The task also needs Repo "
"Manager to fix the identity-canon registry identity and publish a corrected image before the "
"123/0 snapshot can pass."
),
"ready_when": (
"The Forgejo identity/custody owner drafts the CCR and silent provisioning child; Repo Manager "
"ships the identity-canon correction."
),
},
]
def main() -> None:
directory = ROOT / BATCH
directory.mkdir(parents=True, exist_ok=True)
ordinal = []
intents = []
for n, spec in enumerate(MEMOS, start=1):
packet_path = directory / f"{spec['id']}.packet.md"
packet_path.write_text(spec["packet"], encoding="utf-8")
digest = _sha(spec["packet"])
memo = _memo(
memo_id=spec["id"],
question=spec["question"],
brief=spec["brief"],
target=spec["target"],
packet_id=spec["id"] + "-packet",
packet_hash=digest,
highlight=spec["highlight"],
workplan=spec["workplan"],
task=spec["task"],
)
if memo_from(json.loads(dumps(memo))).question != spec["question"]:
raise RuntimeError("round-trip failed")
memo_path = directory / f"{spec['id']}.memo.json"
memo_path.write_text(dumps(memo) + "\n", encoding="utf-8")
ordinal.append(
{
"n": n,
"memo_id": spec["id"],
"workplan": spec["workplan"],
"task": spec["task"],
"hub_task_prefix": spec["hub_task_prefix"],
"question": spec["question"],
"memo": memo_path.name,
"packet": packet_path.name,
"packet_hash": digest,
"required_highlight": f"{spec['id']}-h1",
}
)
intents.append({"memo_id": spec["id"], "create_client": "informed-decision-sitting-requester", "binding": spec["binding"]})
index = {
"kind": "informed-decision-batch",
"id": f"infd-batch-{SITTING}",
"review_group": REVIEW_GROUP,
"status": "draft-unsigned",
"submitted": False,
"one_question_per_memo": True,
"approve_all_forbidden": True,
"agent_disposition_forbidden": True,
"hub_decision": HUB_DECISION,
"ordinal": ordinal,
"excluded": EXCLUDED,
}
(directory / "index.json").write_text(json.dumps(index, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
create = {
"kind": "informed-decision-approval-create-intents",
"sitting_id": SITTING_ID,
"status": "not-posted",
"posted": False,
"requester_client": "informed-decision-sitting-requester",
"human_control": True,
"pdp_path": False,
"required_count": 1,
"note": "Intents only. Digests are computed by approval-engine at create; do not invent them here.",
"intents": intents,
}
(ROOT / "approval-create-intents.json").write_text(json.dumps(create, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
sitting = {
"kind": "informed-decision-sitting",
"id": SITTING_ID,
"review_group": REVIEW_GROUP,
"principal": "pending-human-session",
"status": "draft-unsigned",
"hub_decision": HUB_DECISION,
"batches": [index["id"]],
"memo_count": len(MEMOS),
"excluded_count": len(EXCLUDED),
"bind_path": "create approval (attended), Flex Auth exact-record admission, load store, human accept",
"note": "Unsigned draft. Live bind substitutes pending-human-session with the authenticated key-cape subject.",
}
(ROOT / "sitting.json").write_text(json.dumps(sitting, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
print(f"Wrote {len(MEMOS)} unsigned memo(s), {len(EXCLUDED)} excluded lane(s) under {ROOT}")
if __name__ == "__main__":
main()