Provision scoped T03 requester custody and native requests
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09cbb-87c6-7900-a145-4ce53ba9f1a6
This commit is contained in:
codex 2026-09-14 02:47:32 +02:00
parent 525664efa3
commit 703d552ee7
10 changed files with 650 additions and 0 deletions

View file

@ -0,0 +1,44 @@
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openbao-keycape-secrets-engine-requester
labels:
app.kubernetes.io/part-of: railiance-gitops
railiance-platform/component: external-secrets
app.kubernetes.io/name: keycape
spec:
provider:
vault:
server: http://openbao.openbao.svc:8200
path: platform
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: external-secrets-keycape-secrets-engine-requester
serviceAccountRef:
name: external-secrets
namespace: external-secrets
conditions:
- namespaces:
- sso
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: keycape-secrets-engine-requester-client
namespace: sso
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-keycape-secrets-engine-requester
target:
name: keycape-secrets-engine-requester-client
creationPolicy: Owner
deletionPolicy: Retain
data:
- secretKey: client-secret
remoteRef:
key: workloads/secrets-engine/approval-requester
property: CLIENT_SECRET

View file

@ -0,0 +1,105 @@
id: CCR-2026-0024
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: T03 create-only requester KeyCape verifier custody
status: applied
created: '2026-09-14'
updated: '2026-09-14'
requester:
agent: codex
reason: User instructed completion of SECRETS-WP-0010-T03 and explicitly confirmed
its scoped human review mandate. A separate create-only requester is required;
the withdrawn combined operator client remains unused.
review:
required: true
required_approvers:
- platform-operator
- key-cape-owner
comments:
- at: '2026-09-14'
reviewer: operator instruction in Codex session
decision: approved
comment: Necessary implementation of the user-authorized T03 completion. Exact
requester has only approval:create, subject secrets-engine matching the existing
evaluator actor, audience approval-engine, tenant:platform, lifetime 15m. No
approval, consume, provider-key access or model-spending scope. Separate reader
and verifier remain exact to this new path; no old credential or registration
is widened.
target:
domain: financials
tenant: platform
workload: secrets-engine
environment: production
purpose: T03 create-only requester KeyCape verifier custody; execute only the three
fixed T03 request records.
openbao:
mount: platform
kv_path: platform/workloads/secrets-engine/approval-requester
fields:
- CLIENT_SECRET
policy_name: workload-kv-read-keycape-secrets-engine-requester
policy_file: openbao/policies/workload-kv-read-keycape-secrets-engine-requester.hcl
auth:
method: kubernetes
mount: kubernetes
role: external-secrets-keycape-secrets-engine-requester
bound_claims:
service_account_names:
- external-secrets
service_account_namespaces:
- external-secrets
bound_claims_confirmed: true
policies:
- workload-kv-read-keycape-secrets-engine-requester
ttl: 15m
access_frontdoor:
type: ops-warden
catalog_id: secrets-engine-requester-login
selector: T03 create-only approval requester
command: warden access secrets-engine-requester-login --exec -- <reviewed-requester-command>
resolvable: false
readiness: pending-review
delivery:
surface: external-secrets
target: sso/keycape-secrets-engine-requester-client via ESO; env KEYCAPE_SECRETS_ENGINE_REQUESTER_CLIENT_SECRET
risk:
classification: high
notes:
- Credential authenticates only the separate approval:create requester. Human disposition
remains mandatory and uses a different public PKCE client.
- The stable subject secrets-engine matches the existing evaluator and Approval
Engine binding.actor check; it is not an alias for consumer subject service:secrets-engine.
verification:
positive:
- Exact scope and 900-second token lifetime; native create of only the reviewed
three records.
negative:
- Approval and consume scopes refused; sibling KV paths and parent listing denied.
activation_conditions:
- Attended platform authority, CAS=0 custody, exact policy/auth readback and synchronized
verifier delivery.
- Separate reader verification and no human entry synthesized.
evidence:
- at: '2026-09-14T00:23:31+00:00'
actor: operator via attended T03 requester custody session
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as operator via attended T03 requester custody
session using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-keycape-secrets-engine-requester'
- 'Auth role metadata write: auth/kubernetes/role/external-secrets-keycape-secrets-engine-requester'
- No secret values were read, written, printed, or accepted in argv.
lifecycle:
deactivate: Disable the secrets-engine-requester KeyCape registration and detach
only the two requester reader roles. Preserve approvals and existing consumer/verifier
lanes.
rotate: Rotate through KeyCape and platform using a new version with predecessor
refusal proof.
compromised: Disable requester issuance first; revoke sessions and rotate under
attended owner authority.
state_hub:
workplan_id: RPF-WP-0035
task_id: RPF-WP-0035-T06
related_request: CCR-2026-0025

View file

@ -0,0 +1,115 @@
id: CCR-2026-0025
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: T03 create-only requester attended operator reader
status: applied
created: '2026-09-14'
updated: '2026-09-14'
requester:
agent: codex
reason: User instructed completion of SECRETS-WP-0010-T03 and explicitly confirmed
its scoped human review mandate. A separate create-only requester is required;
the withdrawn combined operator client remains unused.
review:
required: true
required_approvers:
- platform-operator
- secrets-engine-owner
comments:
- at: '2026-09-14'
reviewer: operator instruction in Codex session
decision: approved
comment: Necessary implementation of the user-authorized T03 completion. Exact
requester has only approval:create, subject secrets-engine matching the existing
evaluator actor, audience approval-engine, tenant:platform, lifetime 15m. No
approval, consume, provider-key access or model-spending scope. Separate reader
and verifier remain exact to this new path; no old credential or registration
is widened.
target:
domain: financials
tenant: platform
workload: secrets-engine
environment: production
purpose: T03 create-only requester attended operator reader; execute only the three
fixed T03 request records.
openbao:
mount: platform
kv_path: platform/workloads/secrets-engine/approval-requester
fields:
- CLIENT_SECRET
policy_name: workload-kv-read-secrets-engine-requester-client
policy_file: openbao/policies/workload-kv-read-secrets-engine-requester-client.hcl
auth:
method: oidc
mount: netkingdom
role: secrets-engine-requester-workload-kv-read
allowed_redirect_uris:
- https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback
- http://localhost:8250/oidc/callback
- http://127.0.0.1:8250/oidc/callback
oidc_scopes:
- openid
- profile
- email
- groups
user_claim: sub
groups_claim: groups
bound_claims:
groups:
- net-kingdom-admins
bound_claims_confirmed: true
policies:
- workload-kv-read-secrets-engine-requester-client
ttl: 15m
access_frontdoor:
type: ops-warden
catalog_id: secrets-engine-requester-login
selector: T03 create-only approval requester
command: warden access secrets-engine-requester-login --exec -- <reviewed-requester-command>
resolvable: false
readiness: pending-review
delivery:
surface: operator-workstation
target: Contained attended reader session; secret stays in memory for native requester
exchange; no retained file or raw output.
risk:
classification: high
notes:
- Credential authenticates only the separate approval:create requester. Human disposition
remains mandatory and uses a different public PKCE client.
- The stable subject secrets-engine matches the existing evaluator and Approval
Engine binding.actor check; it is not an alias for consumer subject service:secrets-engine.
verification:
positive:
- Exact scope and 900-second token lifetime; native create of only the reviewed
three records.
negative:
- Approval and consume scopes refused; sibling KV paths and parent listing denied.
activation_conditions:
- Attended platform authority, CAS=0 custody, exact policy/auth readback and synchronized
verifier delivery.
- Separate reader verification and no human entry synthesized.
evidence:
- at: '2026-09-14T00:23:32+00:00'
actor: operator via attended T03 requester custody session
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as operator via attended T03 requester custody
session using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-secrets-engine-requester-client'
- 'Auth role metadata write: auth/netkingdom/role/secrets-engine-requester-workload-kv-read'
- No secret values were read, written, printed, or accepted in argv.
lifecycle:
deactivate: Disable the secrets-engine-requester KeyCape registration and detach
only the two requester reader roles. Preserve approvals and existing consumer/verifier
lanes.
rotate: Rotate through KeyCape and platform using a new version with predecessor
refusal proof.
compromised: Disable requester issuance first; revoke sessions and rotate under
attended owner authority.
state_hub:
workplan_id: RPF-WP-0035
task_id: RPF-WP-0035-T06
related_request: CCR-2026-0024

View file

@ -0,0 +1,145 @@
{
"observed_at": "2026-09-14T00:33:04.552946+00:00",
"status": "created",
"phase": "three_unapproved_requests_created",
"requests": [
{
"memo_id": "SECRETS-WP-0010-T03-apply",
"action": "apply",
"approval": {
"binding": {
"action": "apply",
"actor": "secrets-engine",
"digest": "sha256:03cc5b37437f14e86b686ce4054f976556334eff3fa260b03e8014ed3d9217e5",
"human_control": true,
"pdp_digest": "sha256:933427642c58c54f65dd4781b8e4c8e2f358eb96497ae35870fff4bd593d2b84",
"pdp_path": true,
"principal": "secrets-engine",
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
"target": {
"attributes": {
"auth_targets": [
"se-prod-openrouter-llm-connect"
],
"fields": [],
"policy_targets": [
"se-prod-openrouter-llm-connect"
],
"stage": "prod"
},
"id": "catalog:openrouter-llm-connect",
"system": "secrets-engine",
"type": "secret-catalog-lane"
}
},
"created_at": "2026-09-14T00:33:07+00:00",
"entries": [],
"id": "09592588-ab15-53e7-89b8-c4e9f29aaacf",
"required_count": 1,
"status": "requested",
"superseded_by": null,
"updated_at": "2026-09-14T00:33:07+00:00",
"validity": {
"expires_at": "2026-09-15T00:33:06.559689+00:00",
"not_before": "2026-09-14T00:33:06.559689+00:00"
}
}
},
{
"memo_id": "SECRETS-WP-0010-T03-verify",
"action": "verify",
"approval": {
"binding": {
"action": "verify",
"actor": "secrets-engine",
"digest": "sha256:72d9267d038c17107c880ffc9009793ce9c70defbddfe2219628854b811a04b2",
"human_control": true,
"pdp_digest": "sha256:9e36cdbf3890cc5a7e550fd57191f9c0f2a6b2180909aac302aa3b999e7e6b25",
"pdp_path": true,
"principal": "secrets-engine",
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
"target": {
"attributes": {
"auth_targets": [
"se-prod-openrouter-llm-connect"
],
"fields": [
"OPENROUTER_API_KEY"
],
"policy_targets": [
"se-prod-openrouter-llm-connect"
],
"stage": "prod"
},
"id": "catalog:openrouter-llm-connect",
"system": "secrets-engine",
"type": "secret-catalog-lane"
}
},
"created_at": "2026-09-14T00:33:07+00:00",
"entries": [],
"id": "9416fa31-fa9e-5603-8289-f35bc9625409",
"required_count": 1,
"status": "requested",
"superseded_by": null,
"updated_at": "2026-09-14T00:33:07+00:00",
"validity": {
"expires_at": "2026-09-15T00:33:06.722887+00:00",
"not_before": "2026-09-14T00:33:06.722887+00:00"
}
}
},
{
"memo_id": "SECRETS-WP-0010-T03-exec",
"action": "exec",
"approval": {
"binding": {
"action": "exec",
"actor": "secrets-engine",
"digest": "sha256:f2cf0fb53b740900756ccde5587c3578fcff44beef2f1edab17b9a198a4033d8",
"human_control": true,
"pdp_digest": "sha256:9f17812750fc8962b0fc58fc09df136850c9935a864fafa998a1c030dfb75bd9",
"pdp_path": true,
"principal": "secrets-engine",
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
"target": {
"attributes": {
"auth_targets": [
"se-prod-openrouter-llm-connect"
],
"fields": [
"OPENROUTER_API_KEY"
],
"policy_targets": [
"se-prod-openrouter-llm-connect"
],
"stage": "prod"
},
"id": "catalog:openrouter-llm-connect",
"system": "secrets-engine",
"type": "secret-catalog-lane"
}
},
"created_at": "2026-09-14T00:33:07+00:00",
"entries": [],
"id": "da678b61-35be-598e-8d95-a7aefa2fdc73",
"required_count": 1,
"status": "requested",
"superseded_by": null,
"updated_at": "2026-09-14T00:33:07+00:00",
"validity": {
"expires_at": "2026-09-15T00:33:06.955168+00:00",
"not_before": "2026-09-14T00:33:06.955168+00:00"
}
}
}
],
"credential_values_emitted": false,
"signature_verified": true,
"excess_scopes_refused": true,
"wrong_secret_refused": true,
"reader_scope_verified": true,
"human_entries_created": false,
"approvals_consumed": false,
"warden_session": "exited_0_after_self_revocation_and_helper_cleanup"
}

View file

@ -0,0 +1,24 @@
{
"observed_at": "2026-09-14T00:23:24.931083+00:00",
"status": "applied",
"phase": "keycape_ready",
"ccrs": [
"CCR-2026-0024",
"CCR-2026-0025"
],
"credential_values_emitted": false,
"approval_mutations": false,
"kv_version": 1,
"request_id": "2f85087b-68af-028a-a9a7-3c0d89c06c03",
"keycape": {
"deployment_uid": "99ddd83c-cb3f-4847-bcf8-35f1aa87627f",
"generation": 51,
"pod_uid": "c4b4b63c-fd5b-45eb-bfa5-59197afe1412",
"single_ready_replica": true
},
"image_unchanged": "forgejo.coulomb.social/coulomb/key-cape@sha256:db2c5a13a47839049349e881c8d19bc39f720ee69d8518f9f2eba2b1f98af9d5",
"unrelated_config_preserved": true,
"verifier_secret_exported": false,
"requester_credential_presented": false,
"warden_session": "exited_0_after_self_revocation_and_helper_cleanup"
}

View file

@ -0,0 +1,7 @@
path "platform/data/workloads/secrets-engine/approval-requester" {
capabilities = ["read"]
}
path "platform/metadata/workloads/secrets-engine/approval-requester" {
capabilities = ["read"]
}

View file

@ -0,0 +1,7 @@
path "platform/data/workloads/secrets-engine/approval-requester" {
capabilities = ["read"]
}
path "platform/metadata/workloads/secrets-engine/approval-requester" {
capabilities = ["read"]
}

View file

@ -0,0 +1,93 @@
"""Silent, single-attempt creation of the three operator-reviewed T03 requests."""
import base64,json,os,stat,subprocess,time
from pathlib import Path
from datetime import datetime,timezone,timedelta
from urllib.request import Request,build_opener,ProxyHandler,HTTPRedirectHandler
from urllib.parse import urlencode
from urllib.error import HTTPError
import jwt
ROOT=Path('/home/worsch/railiance-platform')
RECEIPT=ROOT/'docs/evidence/2026-09-14-t03-native-approval-requests.json'
POLICY='workload-kv-read-secrets-engine-requester-client'
KV='platform/data/workloads/secrets-engine/approval-requester'
ISSUER='https://kc.coulomb.social'
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self,*args,**kwargs): return None
def http(url,*,body=None,headers=None):
req=Request(url,data=body,headers=headers or {})
try:
with build_opener(ProxyHandler({}),NoRedirect()).open(req,timeout=20) as response:
content=response.read(1048577);status=response.status
except HTTPError as error:
status=error.code;content=error.read(1048577);error.close()
if len(content)>1048576:raise ValueError('response_too_large')
return status,json.loads(content)
def bao(*args):
p=subprocess.run(['bao',*args],capture_output=True,text=True,timeout=20)
if p.returncode:raise ValueError('metadata_failed')
return json.loads(p.stdout)
def check_identity(d):
policies=set(d.get('policies',[]))|set(d.get('identity_policies',[]))
if POLICY not in policies or policies-{POLICY,'default'} or not d.get('entity_id') or not 0<d.get('ttl',0)<=900:
raise ValueError('reader_identity_failed')
def requests():
records=json.loads(Path('/home/worsch/flex-auth/examples/informed-decision-t03/records.json').read_text())
evaluations=json.loads(Path('/home/worsch/secrets-engine/docs/evidence/2026-09-14-t03-native-pdp-inputs.json').read_text())
if {r['action'] for r in records.values()}!={'apply','verify','exec'} or len(records)!=3:raise ValueError('exact_three_records_required')
result=[]
for memo,record in records.items():
d=evaluations[record['action']]
if d['provenance']['policy_package_digest']!='sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4' or d['binding']['subject']['id']!='secrets-engine' or record['binding']['actor']!='secrets-engine':raise ValueError('native_evaluator_binding_drift')
digest='sha256:'+__import__('hashlib').sha256(json.dumps(record['binding'],sort_keys=True,separators=(',',':'),ensure_ascii=False).encode()).hexdigest()
if digest!=record['binding_digest']:raise ValueError('native_binding_drift')
result.append((memo,record,d['binding']['request_digest']))
return result
def main(receipt):
prepared=requests()
if Path.home().parent.name!='.warden-attended-login' or os.getenv('BAO_TOKEN') or os.getenv('VAULT_TOKEN'):raise ValueError('attended_reader_required')
check_identity(bao('token','lookup','-format=json')['data'])
for path,expected in [(KV,['read']),('platform/data/workloads/secrets-engine/approval-client',['deny']),('platform/metadata/workloads/secrets-engine',['deny'])]:
if bao('token','capabilities','-format=json',path)!=expected:raise ValueError('reader_scope_failed')
helper=Path.home()/'.vault-token';info=helper.lstat()
if not stat.S_ISREG(info.st_mode) or stat.S_IMODE(info.st_mode)!=0o600 or info.st_uid!=os.getuid():raise ValueError('private_helper_required')
status,data=http('https://bao.coulomb.social/v1/'+KV+'?version=1',headers={'X-Vault-Token':helper.read_text().strip()})
if status!=200 or data['data']['metadata']['version']!=1:raise ValueError('requester_delivery_failed')
secret=data['data']['data']['CLIENT_SECRET'];del data
def exchange(scope,credential=secret):
auth=base64.b64encode(('secrets-engine-requester:'+credential).encode()).decode()
return http(ISSUER+'/token',body=urlencode({'grant_type':'client_credentials','scope':scope}).encode(),headers={'Authorization':'Basic '+auth,'Content-Type':'application/x-www-form-urlencoded'})
status,tokens=exchange('approval:create')
if status!=200:raise ValueError('requester_exchange_failed')
token=tokens['access_token'];status,jwks=http(ISSUER+'/jwks')
if status!=200:raise ValueError('jwks_failed')
header=jwt.get_unverified_header(token)
keys=[key for key in jwks['keys'] if key['kid']==header.get('kid')]
if header.get('alg')!='RS256' or len(keys)!=1:raise ValueError('signing_key_failed')
claims=jwt.decode(token,jwt.PyJWK.from_dict(keys[0]).key,algorithms=['RS256'],issuer=ISSUER,audience='approval-engine',options={'strict_aud':True,'require':['sub','iat','exp','iss','aud']})
expected={'sub':'secrets-engine','tenant':'tenant:platform','principal_type':'service','scope':'approval:create','roles':['secrets-engine-requester'],'groups':[]}
if any(claims.get(k)!=v for k,v in expected.items()) or claims['exp']-claims['iat']!=900:raise ValueError('requester_claims_failed')
for scope in ('approval:approve','approval:consume','approval:read'):
if exchange(scope)[0]!=400:raise ValueError('excess_scope_not_refused')
if exchange('approval:create','invalid-synthetic-credential')[0]!=401:raise ValueError('wrong_secret_not_refused')
receipt.update(phase='requester_verified',signature_verified=True,excess_scopes_refused=True,wrong_secret_refused=True,reader_scope_verified=True)
for memo,record,pdp_digest in prepared:
now=datetime.now(timezone.utc)
body={'id':record['approval_id'],'binding':record['binding'],'validity':{'not_before':now.isoformat(),'expires_at':(now+timedelta(hours=24)).isoformat()},'required_count':1,'human_control':True,'pdp_path':True,'pdp_digest':pdp_digest}
receipt['phase']='create_attempt:'+record['action'];RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')
status,result=http('http://127.0.0.1:18281/v1/approvals',body=json.dumps(body).encode(),headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'})
if status!=201 or result['status']!='requested' or result['entries'] or result['binding']['digest']!=record['binding_digest'] or result['binding']['human_control'] is not True or result['binding']['pdp_digest']!=pdp_digest:raise ValueError('request_creation_requires_reconciliation')
receipt['requests'].append({'memo_id':memo.removeprefix('memo:'),'action':record['action'],'approval':result})
RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')
receipt.update(status='created',phase='three_unapproved_requests_created',human_entries_created=False,approvals_consumed=False)
if __name__=='__main__':
if RECEIPT.exists():raise SystemExit(1)
receipt={'observed_at':datetime.now(timezone.utc).isoformat(),'status':'failed','phase':'preflight','requests':[],'credential_values_emitted':False}
try:main(receipt)
except Exception:raise SystemExit(1) from None
finally:RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')

View file

@ -0,0 +1,75 @@
"""Silent attended provisioning of the separate create-only T03 requester."""
import base64,copy,hashlib,importlib.util,json,os,secrets,sys,time
from pathlib import Path
from datetime import datetime,timezone
import yaml
ROOT=Path('/home/worsch/railiance-platform')
sys.path.insert(0,str(ROOT/'scripts'))
from state_hub_preflight_lane import command,bao,data,assert_cluster,LaneError
from keycape_approval_custody import require,read_optional,BOUNDARY
KUBE=['kubectl','--kubeconfig','/home/worsch/.kube/config-railiance01']
KV='platform/data/workloads/secrets-engine/approval-requester'
META='platform/metadata/workloads/secrets-engine/approval-requester'
CLIENT=json.loads(Path('/home/worsch/key-cape/docs/t03-requester-registration.json').read_text())
RECEIPT=ROOT/'docs/evidence/2026-09-14-t03-requester-provision.json'
def load(name,path):
spec=importlib.util.spec_from_file_location(name,path); m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);return m
rollout=load('requester_rollout','/home/worsch/net-kingdom/sso-mfa/k8s/keycape/approval-clients-rollout.py')
rollout.IDS=('secrets-engine-requester',)
def run(receipt):
require(Path.home().parent.name=='.warden-attended-login' and not os.getenv('BAO_TOKEN') and not os.getenv('VAULT_TOKEN'),'attended_envelope_required')
assert_cluster(KUBE)
identity=data(bao(['token','lookup','-format=json']))['data']
require('platform-admin' in identity['policies'] and 'root' not in identity['policies'],'attended_operator_required')
require(CLIENT['clientId']=='secrets-engine-requester' and CLIENT['allowedScopes']==['approval:create'] and CLIENT['serviceSubject']=='secrets-engine' and CLIENT['audience']=='approval-engine' and CLIENT['tenant']=='tenant:platform','requester_contract_drift')
require(read_optional(META) is None,'existing_requester_custody_requires_reconciliation')
for ref in ('CCR-2026-0024','CCR-2026-0025'):
command(['python3',str(ROOT/'scripts/credential-change.py'),'applier-dry-run',ref,'--json'])
secret=rollout.get(KUBE,'secret','keycape-config')
deployment=rollout.get(KUBE,'deployment','keycape')
config=rollout.replacement(secret,[CLIENT])
spec=copy.deepcopy(deployment['spec'])
require(spec.get('replicas',1)==1 and spec['strategy']['type']=='Recreate','single_recreate_keycape_required')
container=next(c for c in spec['template']['spec']['containers'] if c['name']=='keycape')
image=container['image']; require('@sha256:' in image,'pinned_keycape_image_required')
env_name='KEYCAPE_SECRETS_ENGINE_REQUESTER_CLIENT_SECRET'
require(not any(e['name']==env_name for e in container.setdefault('env',[])),'existing_requester_env')
container['env'].append({'name':env_name,'valueFrom':{'secretKeyRef':{'name':'keycape-secrets-engine-requester-client','key':'client-secret'}}})
rollout.patch_object(KUBE,'secret',secret,'/data/config.yaml',config,dry=True)
rollout.patch_object(KUBE,'deployment',deployment,'/spec',spec,dry=True)
receipt['phase']='metadata_preflight_passed'
boundary=read_optional(BOUNDARY); require(boundary is not None,'agent_boundary_required')
additions=''.join('path "'+p+'" { capabilities = ["deny"] }\n' for p in (KV,META))
require(all('"'+p+'"' not in boundary['policy'] for p in (KV,META)),'boundary_path_requires_reconciliation')
bao(['write',BOUNDARY,'-'],payload={'policy':boundary['policy']+'\n'+additions})
require(read_optional(BOUNDARY)['policy']==boundary['policy']+'\n'+additions,'boundary_readback_failed')
for ref in ('CCR-2026-0024','CCR-2026-0025'):
command(['python3',str(ROOT/'scripts/credential-change.py'),'applier-apply',ref,'--actor','operator via attended T03 requester custody session','--confirm','DELEGATED APPLY '+ref,'--quiet'])
receipt['phase']='reader_roles_applied'
result=data(bao(['write','-format=json',KV,'-'],payload={'options':{'cas':0},'data':{'CLIENT_SECRET':secrets.token_urlsafe(48)}}))
require(result['data']['version']==1,'initial_version_mismatch')
receipt.update(phase='custody_seeded',kv_version=1,request_id=result.get('request_id'))
RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')
command(KUBE+['apply','-f',str(ROOT/'argocd/platform-addons/openbao-secretstore/t03-requester.yaml')])
deadline=time.monotonic()+90
while time.monotonic()<deadline:
obj=rollout.get(KUBE,'externalsecret','keycape-secrets-engine-requester-client')
if any(c.get('type')=='Ready' and c.get('status')=='True' for c in obj.get('status',{}).get('conditions',[])):
break
time.sleep(2)
else:raise LaneError('verifier_sync_failed')
receipt['phase']='verifier_synced'
# UID/resourceVersion preconditions forbid overwriting concurrent owner changes.
rollout.patch_object(KUBE,'secret',secret,'/data/config.yaml',config)
after=rollout.get(KUBE,'secret','keycape-config')
require(after['data']==dict(secret['data'],**{'config.yaml':config}),'unrelated_config_or_key_changed')
rollout.patch_object(KUBE,'deployment',deployment,'/spec',spec)
receipt['keycape']=rollout.ready(KUBE,image)
receipt.update(status='applied',phase='keycape_ready',image_unchanged=image,unrelated_config_preserved=True,verifier_secret_exported=False,requester_credential_presented=False)
if __name__=='__main__':
receipt={'observed_at':datetime.now(timezone.utc).isoformat(),'status':'failed','phase':'preflight','ccrs':['CCR-2026-0024','CCR-2026-0025'],'credential_values_emitted':False,'approval_mutations':False}
try:run(receipt)
except Exception:raise SystemExit(1) from None
finally:RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')

View file

@ -633,3 +633,38 @@ Remaining: an actual nonmember login refusal, real approval claim/consume,
separate narrow requester admission and deployed Informed Decision review with
an explicitly admitted human mandate. The reader group alone grants no review
mandate. T03 and CCR delivery activation remain open; no OpenRouter key was read.
### T03 scoped review deployment — 2026-09-14
The operator explicitly admitted `net-kingdom-admins` as the human review group
for only the T03 apply, verify and read-only key-check records, separately from
its credential-reader membership. The review service is live and ready at
https://decisions.coulomb.social with verified KeyCape groups, fresh MFA and a
dedicated caller-bound Flex Auth policy. Its mandate does not grant consumption.
The new `secrets-engine-requester` client has subject `secrets-engine`, tenant
`tenant:platform`, role `secrets-engine-requester`, and only `approval:create`.
CCR-2026-0024 and CCR-2026-0025 provide distinct verifier and attended reader
custody. Native signature, subject, scope and TTL checks passed; excess scopes
and a wrong secret were refused. Existing consumer identity is unchanged.
Three real requested approvals were created with human control, required count
one, and zero entries. Platform evidence is
`docs/evidence/2026-09-14-t03-native-approval-requests.json`.
Review image: sha256:8f55bcecf37a8d65f96e073510b1ffb4636c0a91d75e1ee7d582ad4bce8b953a.
Policy image: sha256:c9f028b49dfcede930a9cc48757ec8371ecc71d20b1bfee2733e55298dffcc7c.
Review tests: 339 passed, 39 optional integration tests skipped; 11 container
checks and HIGH/CRITICAL image scan passed. Policy checks: 57 local and 6 native
caller checks passed, using synthetic subjects, not human binding evidence.
Approval Engine CPU request was reduced from 25m to 10m after observing 1m use;
review requests 20m and its PDP 5m. Limits are unchanged. Native services ready.
Remaining T03 gate: the operator's exact signed-in account is needed to address
three prepared immutable memos, followed by real acknowledgements and acceptance
in Informed Decision. No human entry or consume has been generated by an agent.
Then execute claim -> validated PDP Check -> CAS consume separately for apply,
verify and exec using scoped attended authority, and capture native denial,
revocation, workload health and key-check evidence. No OpenRouter credential has
been read and no inference or spend was performed. T03 remains waiting; this
entry supersedes earlier statements that requester or group admission is missing.