docs(custody): record attended KeyCape first-provision authority proof
Assistant: codex Assistant-Model: gpt-5.6-luna Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
a0bbae842c
commit
a94d06dbcf
5 changed files with 204 additions and 0 deletions
|
|
@ -14,6 +14,7 @@
|
||||||
| workplan | RPF-WP-0029 | blocked | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
| 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-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-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-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-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 |
|
| 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-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-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-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-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-T02 | done | — | workplans/RPF-WP-0036-platform-service-assurance.md |
|
||||||
| task | RPF-WP-0036-T03 | wait | — | 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-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-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-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 |
|
||||||
|
|
|
||||||
|
|
@ -156,3 +156,25 @@ platform side; the window needs roughly 60–90 minutes with both owners present
|
||||||
(KEY-WP-0009-T04) or to RPF-WP-0035-T02's service-JWT lane.
|
(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
|
- No approval for `approval:consume` on the operator client, now or by later
|
||||||
scope edit. Adding it is a new lane decision.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
64
scripts/keycape-approval-custody-preflight.py
Normal file
64
scripts/keycape-approval-custody-preflight.py
Normal 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
|
||||||
|
|
@ -147,6 +147,7 @@ closure: `history/2026-09-05-preflight-signing-activation-complete.md`.
|
||||||
id: RPF-WP-0035-T05
|
id: RPF-WP-0035-T05
|
||||||
status: wait
|
status: wait
|
||||||
priority: high
|
priority: high
|
||||||
|
state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c"
|
||||||
```
|
```
|
||||||
|
|
||||||
Answers KEY-WP-0013-T02 (State Hub message
|
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,
|
stub as a blocker. T02 still needs the accepted service issuer/JWKS, claims,
|
||||||
audience and consumer binding. T03 still needs confirmed operator group/tenant
|
audience and consumer binding. T03 still needs confirmed operator group/tenant
|
||||||
and consumer semantics; T04 is already complete. No new owner acceptance inferred.
|
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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue