docs(custody): record attended KeyCape first-provision authority proof
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-luna
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-08 22:40:04 +02:00
parent a0bbae842c
commit a94d06dbcf
5 changed files with 204 additions and 0 deletions

View file

@ -14,6 +14,7 @@
| workplan | RPF-WP-0029 | blocked | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
| workplan | RPF-WP-0035 | blocked | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
| workplan | RPF-WP-0036 | blocked | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| workplan | RPF-WP-0038 | active | — | workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md |
| task | RPF-WP-0015-T01 | done | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md |
| task | RPF-WP-0015-T02 | wait | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md |
| task | RPF-WP-0015-T03 | wait | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md |
@ -34,6 +35,7 @@
| task | RPF-WP-0035-T02 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
| task | RPF-WP-0035-T03 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
| task | RPF-WP-0035-T04 | done | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
| task | RPF-WP-0035-T05 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
| task | RPF-WP-0036-T01 | done | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| task | RPF-WP-0036-T02 | done | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| task | RPF-WP-0036-T03 | wait | — | workplans/RPF-WP-0036-platform-service-assurance.md |
@ -41,3 +43,7 @@
| task | RPF-WP-0036-T05 | done | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| task | RPF-WP-0036-T06 | wait | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| task | RPF-WP-0036-T07 | done | — | workplans/RPF-WP-0036-platform-service-assurance.md |
| task | RPF-WP-0038-T01 | done | — | workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md |
| task | RPF-WP-0038-T02 | done | — | workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md |
| task | RPF-WP-0038-T03 | done | — | workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md |
| task | RPF-WP-0038-T04 | progress | — | workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md |

View file

@ -156,3 +156,25 @@ platform side; the window needs roughly 6090 minutes with both owners present
(KEY-WP-0009-T04) or to RPF-WP-0035-T02's service-JWT lane.
- No approval for `approval:consume` on the operator client, now or by later
scope edit. Adding it is a new lane decision.
## Attended authority return — 2026-09-08
The metadata-only first-provision preflight is now observed on the exact six
policy/role/data paths: create/update capabilities are present. The successful
session self-revoked and its helper was removed. This settles the availability
of the named operator authority, not the CCR approvals or the upstream issuer
precondition. See
[the receipt](../evidence/2026-09-08-keycape-approval-custody-preflight.json).
For a repeat after a role/policy change, use the existing contained WSL wrapper:
```bash
python3 scripts/openbao-attended-exec.py -- /usr/bin/python3 \
scripts/keycape-approval-custody-preflight.py --receipt /tmp/<new-private-receipt>.json
```
Use an absolute path to the owner command if invoking from another directory.
It emits no output or values; inspect its allowlisted capability metadata only
after Warden has completed revocation and cleanup. No custody activation or
approval is performed by this preflight.

View file

@ -0,0 +1,86 @@
{
"observed_at": "2026-09-08T20:36:47.042499+00:00",
"requests": [
"CCR-2026-0017",
"CCR-2026-0018"
],
"operation": "capabilities-self only",
"credential_data_read": false,
"metadata_applied": false,
"custody_activated": false,
"upstream_issuer_proven": false,
"status": "observed",
"capabilities": {
"sys/policies/acl/workload-kv-read-keycape-secrets-engine-approval": [
"create",
"delete",
"list",
"read",
"sudo",
"update"
],
"sys/policies/acl/workload-kv-read-keycape-approval-engine-operator": [
"create",
"delete",
"list",
"read",
"sudo",
"update"
],
"auth/kubernetes/role/external-secrets-keycape-secrets-engine-approval": [
"create",
"delete",
"list",
"read",
"sudo",
"update"
],
"auth/kubernetes/role/external-secrets-keycape-approval-engine-operator": [
"create",
"delete",
"list",
"read",
"sudo",
"update"
],
"platform/data/workloads/secrets-engine/approval-client": [
"create",
"delete",
"list",
"read",
"update"
],
"platform/data/workloads/approval-engine/operator-client": [
"create",
"delete",
"list",
"read",
"update"
]
},
"required_metadata_capabilities_present": true,
"paths_verified": 6,
"login_lane": "openbao-platform-admin-login",
"launcher": "scripts/openbao-attended-exec.py",
"command": "scripts/keycape-approval-custody-preflight.py --receipt <new-private-file>",
"wrapper_exit": 0,
"session_self_revoked": true,
"helper_root_removed": true,
"attempt_notes": [
{
"attempt": 1,
"result": "direct launcher unavailable; no child handoff; revocation unconfirmed",
"credential_data_read": false
},
{
"attempt": 2,
"result": "owner wrapper login/self-revocation succeeded; capability command rejected unsupported multiple-path syntax",
"credential_data_read": false
},
{
"attempt": 3,
"result": "six single-path capability queries succeeded; session self-revoked and helper removed",
"credential_data_read": false
}
]
}

View file

@ -0,0 +1,64 @@
"""Read-only, silent owner preflight inside Warden's attended login envelope.
Queries only token capabilities for the exact two reviewed CCR targets. Reads
no secret data, applies no metadata, and does not record an approval. Warden
owns the temporary token helper and self-revokes after this command returns.
"""
import argparse
import json
import os
import subprocess
from datetime import datetime, timezone
from pathlib import Path
PATHS = [
'sys/policies/acl/workload-kv-read-keycape-secrets-engine-approval',
'sys/policies/acl/workload-kv-read-keycape-approval-engine-operator',
'auth/kubernetes/role/external-secrets-keycape-secrets-engine-approval',
'auth/kubernetes/role/external-secrets-keycape-approval-engine-operator',
'platform/data/workloads/secrets-engine/approval-client',
'platform/data/workloads/approval-engine/operator-client',
]
ALLOWED = {'create', 'read', 'update', 'patch', 'delete', 'list', 'sudo', 'deny', 'root'}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--receipt", type=Path, required=True)
args = parser.parse_args()
receipt = {'observed_at': datetime.now(timezone.utc).isoformat(),
'requests': ['CCR-2026-0017', 'CCR-2026-0018'],
'operation': 'capabilities-self only', 'credential_data_read': False,
'metadata_applied': False, 'custody_activated': False,
'upstream_issuer_proven': False}
caps = {}
for path in PATHS:
# This installed CLI accepts one PATH. Supplying several positional
# arguments selects a different TOKEN/PATH form or refuses the call.
result = subprocess.run(['bao', 'token', 'capabilities', '-format=json', path],
capture_output=True, text=True, timeout=20)
if result.returncode:
receipt['status'] = 'capability-query-failed'
break
payload = json.loads(result.stdout)
values = payload if isinstance(payload, list) else payload.get('capabilities')
if not isinstance(values, list) or any(v not in ALLOWED for v in values):
raise ValueError('unexpected capability response shape')
caps[path] = sorted(set(values))
else:
receipt['status'] = 'observed'
receipt['capabilities'] = caps
receipt['required_metadata_capabilities_present'] = all(
{'create', 'update'}.issubset(values) for values in caps.values())
receipt['paths_verified'] = len(caps)
fd = os.open(args.receipt, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, 'w') as stream:
json.dump(receipt, stream, indent=2)
stream.write('\n')
if __name__ == '__main__':
try:
main()
except Exception:
raise SystemExit(1) from None

View file

@ -147,6 +147,7 @@ closure: `history/2026-09-05-preflight-signing-activation-complete.md`.
id: RPF-WP-0035-T05
status: wait
priority: high
state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c"
```
Answers KEY-WP-0013-T02 (State Hub message
@ -194,3 +195,28 @@ and access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old loca
stub as a blocker. T02 still needs the accepted service issuer/JWKS, claims,
audience and consumer binding. T03 still needs confirmed operator group/tenant
and consumer semantics; T04 is already complete. No new owner acceptance inferred.
### 2026-09-08 attended capability preflight
HFACT-WP-0001's continued execution verified the existing first-provision
front door without provisioning anything. `warden plan` selected
`openbao-platform-admin-login` / founder_required / one oidc_login. The native
`scripts/openbao-attended-exec.py` supplied the existing WSL browser launcher;
a direct attempt had no launcher and failed before handoff. Its first revocation
result was unconfirmed and is preserved in the receipt rather than silently
reclassified. The two subsequent contained sessions completed self-revocation
and helper cleanup.
`scripts/keycape-approval-custody-preflight.py --receipt <new-private-file>` is
a silent, read-only command for that envelope. The installed Bao CLI supports
one path per `token capabilities` call; the final run used six single-path calls.
Create/update authority is present on both exact policy paths, both Kubernetes
auth-role paths and both KV data paths from CCR-2026-0017/0018. This is authority
metadata, not a secret-data read or policy/role/KV mutation. Receipt:
`docs/evidence/2026-09-08-keycape-approval-custody-preflight.json`.
T05 remains wait: both CCRs are still proposed, the actual upstream ID-token
issuer precondition remains open, and no verifier-side credential is provisioned.
Client-side retrieval and audit-sender custody are still separate owner returns.
The capability receipt is not a review approval or service readiness proof.