From d9a1fdabc3465d9d393d18ae5c0445fb7ff117d5 Mon Sep 17 00:00:00 2001 From: codex Date: Sun, 1 Nov 2026 23:12:40 +0100 Subject: [PATCH] docs: preserve reviewed NetKingdom session artifacts --- .../scripts/flex_auth_signer_native.py | 384 +++++ .../tests/test_flex_auth_signer_native.py | 214 +++ ...-WP-0035-credential-lane-implementation.md | 1367 +++++++++++++++++ .../native-adapter-r2/r1-to-r2.patch | 331 ++++ .../native-adapter-r2/timing-assessment.json | 17 + .../native-adapter-r2/validation.json | 35 + .../native-owner-boundary-r3/README.md | 11 + .../implementation.patch | 92 ++ .../native-owner-boundary-r3/manifest.json | 33 + .../native-owner-boundary-r3/validation.json | 8 + .../native-owner-boundary-r4/README.md | 11 + .../native-owner-boundary-r4/manifest.json | 34 + .../native-owner-boundary-r4/r3-ccr.yaml | 128 ++ .../native-owner-boundary-r4/r3-plan.json | 158 ++ .../native-owner-boundary-r4/validation.json | 11 + .../native-owner-boundary-r5/README.md | 7 + .../implementation-r5-full.patch | 176 +++ .../native-owner-boundary-r5/manifest.json | 25 + .../native-owner-boundary-r5/scanner.json | 8 + .../native-owner-boundary-r5/validation.json | 13 + .../native-preparation-r1/README.md | 19 + .../access-interface-coordination.json | 16 + .../implementation.patch | 477 ++++++ .../native-preparation-r1/manifest.json | 41 + .../native-preparation-r1/owner-review.json | 22 + ...-WP-0035-credential-lane-implementation.md | 1346 ++++++++++++++++ .../native-preparation-r1/validation.json | 22 + .../owner-source-review-r1.json | 8 + ...protected-recovery-next-owner-task-r1.json | 46 + .../route-public-metadata-r1.json | 48 + .../source-proposal-r1.patch | 345 +++++ .../validation-r1.json | 51 + .../writer-r2/README.md | 21 + .../writer-r2/implementation.patch | 655 ++++++++ .../writer-r2/manifest.json | 43 + .../writer-r2/owner-review.json | 32 + ...-WP-0035-credential-lane-implementation.md | 1332 ++++++++++++++++ .../writer-r2/validation.json | 33 + .../writer-r3/manifest.json | 27 + .../writer-r3/owner-review.json | 13 + ...-envelope-signing-projection.yaml.proposed | 50 + .../flex-auth-envelope-signing.md | 161 ++ .../flex-auth-envelope-signing.proposal.json | 118 ++ ...-WP-0035-credential-lane-implementation.md | 1342 ++++++++++++++++ .../writer-r3/r2-to-r3.patch | 73 + .../progress-browser-source.json | 14 + .../progress-preparation-successors.json | 14 + 47 files changed, 9432 insertions(+) create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/scripts/flex_auth_signer_native.py create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/tests/test_flex_auth_signer_native.py create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/workplans/RPF-WP-0035-credential-lane-implementation.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/r1-to-r2.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/timing-assessment.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/README.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/implementation.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/README.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-ccr.yaml create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-plan.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/README.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/implementation-r5-full.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/scanner.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/README.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/access-interface-coordination.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/implementation.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/owner-review.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/owner-source-review-r1.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/protected-recovery-next-owner-task-r1.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/route-public-metadata-r1.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/source-proposal-r1.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/validation-r1.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/README.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/implementation.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/owner-review.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/validation.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/manifest.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/owner-review.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md create mode 100644 docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/r2-to-r3.patch create mode 100644 docs/changes/netkingdom-target-2026-10-16/progress-browser-source.json create mode 100644 docs/changes/netkingdom-target-2026-10-16/progress-preparation-successors.json diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/scripts/flex_auth_signer_native.py b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/scripts/flex_auth_signer_native.py new file mode 100644 index 00000000..0cd7a349 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/scripts/flex_auth_signer_native.py @@ -0,0 +1,384 @@ +#!/usr/bin/env python3 +"""Silent attended retained-lifecycle signer custody; never a credential front door. + +Invoke only through the reviewed warden platform-admin envelope. The externally +reviewed admission SHA is an exact-command input, not approval by JSON shape. +No private value crosses stdout/stderr, argv, receipt or persistent local storage. +""" +from __future__ import annotations +import argparse +import base64 +from datetime import datetime,timezone +import fcntl +import hashlib +import hmac +import http.client +import importlib.util +import json +import os +from pathlib import Path +import re +import selectors +import shlex +import subprocess +import sys +import time + +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from flex_auth_signer_custody import SignerWriter,PATH,FIELDS,BINDINGS,encoded,b64 +from task_execution_journal import Journal,Refused +from task_execution_native_fixture import _absolute_budget +from task_execution_recovery import _json_unique,_invalid_constant,_policy_absent,_same_policy + +ROOT=Path(__file__).resolve().parents[1] +META='platform/metadata/workloads/flex-auth/envelope-signing' +CCR='credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml' +PLAN='docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json' +CLUSTER='a553c742-0115-43d4-99a4-a5ca56fe0786' +BAO_CLUSTER='fd28df5d-98ec-57dd-42ec-9b3e4f4e53bf' +NAME='flex-auth-secrets-engine' +SECRET='flex-auth-secrets-engine-envelope-signing' +ROLE='external-secrets-flex-auth-envelope-signing' +LIFECYCLE='sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4' +REVIEWS={'founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-gitops-owner'} +SOURCE_FILES={'scripts/flex_auth_signer_native.py','scripts/flex_auth_signer_custody.py','scripts/task_execution_native_fixture.py','scripts/task_execution_journal.py','scripts/task_execution_recovery.py','scripts/credential-change.py'} + + +def require(ok,reason): + if not ok:raise Refused(reason) + + +def digest(raw):return 'sha256:'+hashlib.sha256(raw).hexdigest() +def is_digest(value):return type(value) is str and re.fullmatch(r'sha256:[0-9a-f]{64}',value) is not None + +def private_read(path,limit=65536): + path=Path(path) + require(path.is_absolute() and path.absolute()==path.resolve() and not path.is_symlink(),'indirect private input') + Journal._private(path.parent.stat(),directory=True) + fd=os.open(path,os.O_RDONLY|os.O_NOFOLLOW|os.O_NONBLOCK) + try: + before=os.fstat(fd);Journal._private(before) + raw=os.read(fd,limit+1);after=os.fstat(fd) + require((before.st_dev,before.st_ino,before.st_size,before.st_mtime_ns,before.st_ctime_ns)== + (after.st_dev,after.st_ino,after.st_size,after.st_mtime_ns,after.st_ctime_ns) + and len(raw)==before.st_size and len(raw)<=limit,'private input changed or oversized') + return raw + finally:os.close(fd) + + +def parsed(raw): + try:return json.loads(raw,object_pairs_hook=_json_unique,parse_constant=_invalid_constant) + except Exception:raise Refused('invalid closed JSON input') from None + + +def validate_admission(value): + fields={'schema','action','operation_id','kid','expires_at','founder_entity_id','ccr_sha256','source_bundle','bindings', + 'producer_image','caller_binding','deployment_projection_sha256','authority','routing','owner_reviews', + 'exclusive_window_sha256','consumer_trust_sha256','original_receipt_sha256'} + require(type(value) is dict and set(value)==fields,'exact admission schema required') + require(value['schema']=='railiance-platform.signer-native-admission.v1' and value['action'] in {'bootstrap','recover'},'native admission action refused') + require(type(value['operation_id']) is str and re.fullmatch(r'[A-Za-z0-9_-]{1,80}',value['operation_id']) and + type(value['kid']) is str and re.fullmatch(r'[A-Za-z0-9_-]{1,80}',value['kid']),'native operation identity required') + require(type(value['founder_entity_id']) is str and re.fullmatch(r'[a-f0-9-]{36}',value['founder_entity_id']),'explicit attended identity required') + require(all(is_digest(value[x]) for x in ['ccr_sha256','deployment_projection_sha256','exclusive_window_sha256','consumer_trust_sha256']),'explicit custody/image/trust selections required') + require(type(value['producer_image']) is str and re.fullmatch(r'forgejo\.coulomb\.social/coulomb/flex-auth@sha256:[a-f0-9]{64}',value['producer_image']),'immutable producer image required') + require(value['caller_binding']=='secrets-engine=system:serviceaccount:secrets-engine:secrets-engine','retained caller binding required') + require(value['authority']=='founder-attended-exact-source-scope; no standing grant','independent attended authority required') + route=value['routing'];require(type(route) is dict and set(route)=={'lane_id','verdict','founder_act','receipt_sha256'} and + route['lane_id']=='openbao-platform-admin-login' and route['verdict']=='founder_required' and route['founder_act']=='oidc_login' and is_digest(route['receipt_sha256']),'routing mismatch refused') + reviews=value['owner_reviews'];require(type(reviews) is dict and set(reviews)==REVIEWS,'distinct owner reviews required') + for role,review in reviews.items(): + require(type(review) is dict and set(review)=={'approved_admission_sha256','approval_ref'} and + is_digest(review['approved_admission_sha256']) and type(review['approval_ref']) is str and + 00,'absolute custody command timeout') + for item,_ in sel.select(remaining): + chunk=os.read(item.fileobj.fileno(),65536) + if not chunk:sel.unregister(item.fileobj) + else: + data[item.fileobj].extend(chunk) + require(sum(map(len,data.values()))<=1048576,'custody command output bound') + code=proc.wait(timeout=max(.001,deadline-time.monotonic())) + require(code in allowed,'custody command unconfirmed') + return code,bytes(data[proc.stdout]) + finally:sel.close() + except BaseException: + proc.kill();proc.wait(timeout=2);raise Refused('custody command unconfirmed') from None + finally: + proc.stdout.close();proc.stderr.close() + def bao(self,args,payload=None,allowed=(0,)): + with _absolute_budget(2): + code,raw=self.captured(['bao',*args],payload,allowed=allowed) + return code,parsed(raw) + def kube(self,resource,name=None): + args=['kubectl','--request-timeout=2s'] + if resource!='namespace':args+=['-n','flex-auth'] + args+=['get',resource] + if name:args.append(name) + args+=['-o','json'] + with _absolute_budget(2): + _,raw=self.captured(['ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=2','railiance01',shlex.join(args)]) + return parsed(raw) + def http(self,method,path,body=None): + require(method in {'GET','POST'} and path in {META,PATH,PATH+'?version=1'},'fixed custody path required') + require(type(getattr(self,'_token',None)) is str and self._token,'contained attended session required') + with _absolute_budget(2): + conn=http.client.HTTPConnection('127.0.0.1',18200,timeout=2) + try: + conn.request(method,'/v1/'+path,body=None if body is None else encoded(body), + headers={'X-Vault-Token':self._token,'Content-Type':'application/json'}) + response=conn.getresponse();raw=response.read(1048577) + require(len(raw)<=1048576,'custody response bound') + return response.status,parsed(raw) if raw else {} + finally:conn.close() + + +def deployment_projection(deployment): + spec=deployment['spec']['template']['spec'];containers=spec.get('containers',[]) + require(type(containers) is list and len(containers)==1 and not spec.get('initContainers'),'single fixed signer container required') + item=containers[0] + # Never hash arbitrary env values or an entire Secret/spec response. + return {'service_account':spec.get('serviceAccountName'),'image':item.get('image'), + 'args':item.get('args'),'volume_mounts':item.get('volumeMounts',[]), + 'volumes':spec.get('volumes',[]),'security_context':spec.get('securityContext')} + + +def fence(io,contract): + namespace=io.kube('namespace','kube-system') + require(namespace.get('metadata',{}).get('uid')==CLUSTER,'wrong target cluster') + deployment=io.kube('deployment',NAME);spec=deployment.get('spec',{});meta=deployment.get('metadata',{}) + require(type(spec.get('replicas')) is int and spec['replicas']==0 and + deployment.get('status',{}).get('observedGeneration',-1)==meta.get('generation') and + not deployment.get('status',{}).get('replicas',0),'all signer replicas must be stopped') + projection=deployment_projection(deployment) + require(digest(encoded(projection))==contract['deployment_projection_sha256'] and + projection['service_account']==NAME and projection['image']==contract['producer_image'],'fenced deployment source/image mismatch') + args=projection['args'];require(type(args) is list and all(type(x) is str for x in args),'exact signer args required') + def option(flag): + require(args.count(flag)==1 and args.index(flag)+1=3:self.pods=[{'spec':{'serviceAccountName':m.NAME}}] + return deepcopy(self.dep) + return {'items':deepcopy({'pods':self.pods,'hpa':self.hpas,'replicasets':self.rs}[resource])} + def http(self,method,path,body=None): + self.calls.append(('http',method,path)) + if self.denied and path in {m.PATH,m.PATH+'?version=1'} and method=='GET':return 403,{'errors':['secret backend detail']} + result=call(method,path,body) + if self.lost and method=='POST' and path==m.PATH:raise OSError('secret response lost') + return result + io=IO() + c={'schema':'railiance-platform.signer-native-admission.v1','action':'bootstrap','operation_id':'synthetic-native-operation','kid':'synthetic-native-kid', + 'expires_at':(datetime.now(timezone.utc)+timedelta(seconds=100)).isoformat(),'founder_entity_id':io.entity, + 'ccr_sha256':m.digest((source/m.CCR).read_bytes()),'source_bundle':{n:m.digest((source/n).read_bytes()) for n in m.SOURCE_FILES}, + 'bindings':{k:'sha256:'+'2'*64 for k in m.BINDINGS},'producer_image':image,'caller_binding':'secrets-engine=system:serviceaccount:secrets-engine:secrets-engine', + 'deployment_projection_sha256':m.digest(m.encoded(m.deployment_projection(dep))), + 'authority':'founder-attended-exact-source-scope; no standing grant', + 'routing':{'lane_id':'openbao-platform-admin-login','verdict':'founder_required','founder_act':'oidc_login','receipt_sha256':'sha256:'+'3'*64}, + 'owner_reviews':{},'exclusive_window_sha256':'sha256:'+'4'*64,'consumer_trust_sha256':'sha256:'+'5'*64,'original_receipt_sha256':None} + c['bindings'].update(proposal_sha256=m.digest((source/m.PLAN).read_bytes()),policy_sha256=m.LIFECYCLE,image_sha256='sha256:'+'1'*64,trust_sha256=c['consumer_trust_sha256'],deployment_sha256=c['deployment_projection_sha256'],executed_revision_sha256=m.digest(m.encoded(c['source_bundle']))) + def approve(value): + scope=m.digest(m.encoded({k:v for k,v in value.items() if k!='owner_reviews'})) + value['owner_reviews']={role:{'approved_admission_sha256':scope,'approval_ref':'synthetic-fixture-'+role} for role in m.REVIEWS} + return value + approve(c) + return c,io,directory,call,approve,source + + +def test_actual_native_bootstrap_exact_readback_and_no_retry(native): + c,io,directory,call,approve,source=native + result=m.execute(c,directory,io=io) + assert result['status']=='custody-verified-pending-independent-public-admission' and result['exact_readback'] + assert call('GET',m.META)[1]['data']['current_version']==1 + assert [(x[1],x[2]) for x in io.calls if x[0]=='http' and x[1]=='POST']==[('POST',m.META),('POST',m.PATH)] + private=call('GET',m.PATH)[1]['data']['data']['ED25519_PRIVATE_KEY'] + raw=(directory/(c['operation_id']+'.json')).read_bytes();assert private.encode() not in raw + before=len(io.calls) + with pytest.raises(FileExistsError):m.execute(c,directory,io=io) + assert not any(x[0]=='http' and x[1]=='POST' for x in io.calls[before:]) + + +def test_actual_process_loss_unknown_fresh_recovery_read_only(native): + c,io,directory,call,approve,source=native + child=os.fork() + if child==0: + original_http=io.http + def die_after_native_write(method,path,body=None): + result=original_http(method,path,body) + if method=='POST' and path==m.PATH:os._exit(73) + return result + io.http=die_after_native_write + try:m.execute(c,directory,io=io) + except BaseException:os._exit(74) + os._exit(75) + _,status=os.waitpid(child,0) + assert os.waitstatus_to_exitcode(status)==73 + old=directory/(c['operation_id']+'.json');original=old.read_bytes();assert json.loads(original)['status']=='write-intent-unknown' + recovery=deepcopy(c);recovery.update(action='recover',operation_id='synthetic-independent-recovery',original_receipt_sha256=m.digest(original));approve(recovery) + io.lost=False;io.calls.clear() + result=m.execute(recovery,directory,io=io,original_receipt=old) + assert result['status']=='custody-reconciled-pending-independent-public-admission' + assert result['no_write_or_remint'] and old.read_bytes()==original + assert not any(x[0]=='http' and x[1]=='POST' for x in io.calls) + assert call('GET',m.META)[1]['data']['current_version']==1 + assert (directory/(recovery['operation_id']+'.json')).stat().st_mode&0o777==0o600 + io.calls.clear() + with pytest.raises(FileExistsError):m.execute(recovery,directory,io=io,original_receipt=old) + assert not any(x[0]=='http' for x in io.calls) + + +@pytest.mark.parametrize('case',['missing-image','missing-trust','mismatched-source','bad-review','bad-route','expired','wrong-entity','wrong-backend','wrong-cluster','root','pod','terminating-pod','hpa','replicas','image-drift','role-drift','pod-after-metadata']) +def test_refusals_no_seed_effect(native,case): + c,io,directory,call,approve,source=native + if case=='missing-image':c['producer_image']='' + elif case=='missing-trust':c['consumer_trust_sha256']='' + elif case=='mismatched-source':(source/'scripts/flex_auth_signer_custody.py').write_text('changed source') + elif case=='bad-review':c['owner_reviews']['founder']['approved_admission_sha256']='sha256:'+'f'*64 + elif case=='bad-route':c['routing']['lane_id']='openbao-structure-survey';approve(c) + elif case=='expired':c['expires_at']=(datetime.now(timezone.utc)-timedelta(seconds=1)).isoformat();approve(c) + elif case=='wrong-entity':io.entity='other' + elif case=='wrong-backend':io.backend='other' + elif case=='wrong-cluster':io.cluster='other' + elif case=='root':io.root=True + elif case=='pod':io.pods=[{'spec':{'serviceAccountName':m.NAME}}] + elif case=='terminating-pod':io.pods=[{'metadata':{'deletionTimestamp':'now'},'spec':{'volumes':[{'secret':{'secretName':m.SECRET}}]}}] + elif case=='hpa':io.hpas=[{'spec':{'scaleTargetRef':{'name':m.NAME}}}] + elif case=='replicas':io.dep['spec']['replicas']=1 + elif case=='image-drift':io.dep['spec']['template']['spec']['containers'][0]['image']='unreviewed' + elif case=='role-drift':io.role_drift=True + elif case=='pod-after-metadata':io.pod_on_recheck=True + with pytest.raises(Refused):m.execute(c,directory,io=io) + assert not any(x[0]=='http' and x[1]=='POST' and x[2]==m.PATH for x in io.calls) + assert call('GET',m.PATH)[0]==404 + + +@pytest.mark.parametrize('case',['damaged-receipt','typed-damaged-receipt','changed-version','read-denied','no-fresh-review']) +def test_recovery_refuses_without_new_effect(native,case): + c,io,directory,call,approve,source=native;io.lost=True + with pytest.raises(Refused):m.execute(c,directory,io=io) + old=directory/(c['operation_id']+'.json');recovery=deepcopy(c);recovery.update(action='recover',operation_id='recovery',original_receipt_sha256=m.digest(old.read_bytes()));approve(recovery) + if case=='damaged-receipt':old.write_text('{}') + elif case=='typed-damaged-receipt': + damaged=json.loads(old.read_text());damaged['expected_version']=False;old.write_text(json.dumps(damaged));recovery['original_receipt_sha256']=m.digest(old.read_bytes());approve(recovery) + elif case=='changed-version': + doc=call('GET',m.PATH)[1]['data']['data'];assert call('POST',m.PATH,{'options':{'cas':1},'data':doc})[0]==200 + elif case=='read-denied':io.denied=True + elif case=='no-fresh-review':recovery['owner_reviews']['founder']['approved_admission_sha256']='sha256:'+'f'*64 + io.calls.clear();io.lost=False + with pytest.raises(Refused):m.execute(recovery,directory,io=io,original_receipt=old) + assert not any(x[0]=='http' and x[1]=='POST' for x in io.calls) + + +@pytest.mark.parametrize('bad_args',[False,True]) +def test_main_missing_approval_silent_and_no_io(tmp_path,capsys,bad_args): + if bad_args: + assert m.main(['--unrecognized'])==1 + output=capsys.readouterr();assert output.out==output.err=='' + return + assert m.main(['--admission',str(tmp_path/'missing'),'--admission-sha256','sha256:'+'0'*64,'--receipt-directory',str(tmp_path)])==1 + output=capsys.readouterr();assert output.out==output.err=='' + + +def test_native_command_byte_and_elapsed_bounds_no_output(capsys): + io=m.NativeIO() + with pytest.raises(Refused):io.captured([sys.executable,'-c',"import sys;sys.stdout.write('x'*1048577)"]) + import time + started=time.monotonic() + with pytest.raises(Refused):io.captured([sys.executable,'-c',"import time;time.sleep(10)"]) + assert time.monotonic()-started<3 + output=capsys.readouterr();assert output.out==output.err=='' + + +def test_exclusive_native_window_refuses_second_writer(native): + import fcntl + c,io,directory,call,approve,source=native + fd=os.open(directory/'.signer-window.lock',os.O_RDWR|os.O_CREAT,0o600) + try: + fcntl.flock(fd,fcntl.LOCK_EX|fcntl.LOCK_NB) + with pytest.raises(BlockingIOError):m.execute(c,directory,io=io) + assert io.calls==[] + finally:os.close(fd) + + +def test_native_fixed_http_transport_against_disposable_backend(bao_dev,monkeypatch,capsys): + origin,token,call,process=bao_dev + assert call('POST','sys/mounts/platform',{'type':'kv','options':{'version':'2'}})[0] in {200,204} + factory=m.http.client.HTTPConnection;port=int(origin.rsplit(':',1)[1]);destinations=[] + def fixture_socket(host,requested_port,*args,**kwargs): + destinations.append((host,requested_port)) + return factory(host,port if requested_port==18200 else requested_port,*args,**kwargs) + monkeypatch.setattr(m.http.client,'HTTPConnection',fixture_socket) + io=m.NativeIO();io._token=token + assert io.http('GET',m.META)==(404,{'errors':[]}) + assert io.http('POST',m.META,{'cas_required':True,'max_versions':2,'delete_version_after':'0s'})[0] in {200,204} + m.exact_metadata(*io.http('GET',m.META),created=False) + assert all(host=='127.0.0.1' and selected_port==18200 for host,selected_port in destinations) + with pytest.raises(Refused):io.http('GET','other/path') + output=capsys.readouterr();assert output.out==output.err=='' diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/workplans/RPF-WP-0035-credential-lane-implementation.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/workplans/RPF-WP-0035-credential-lane-implementation.md new file mode 100644 index 00000000..9c0e5c55 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/preimages-r1/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -0,0 +1,1367 @@ +--- +id: RPF-WP-0035 +type: workplan +title: "Implement reviewed credential lanes with separate owner gates" +domain: financials +repo: railiance-platform +status: blocked +flavor: implementation +owner: codex +created: "2026-09-05" +updated: "2026-10-13" +related: + - RPF-WP-0032 + - RPF-WP-0033 + - RPF-WP-0034 +state_hub_workstream_id: "975db491-5412-5e27-8e34-14a2417bb039" +--- + +# Credential lane implementation + +One S3 queue for three designed lanes; each task keeps its own approval, +execution and closure boundary. This replaces the implementation tasks in the +three completed design workplans, not the designs themselves. No approval is +inherited by consolidation. INTENT binding: secure custody, dependable delivery, +stable consumer interfaces. Incident custody remains in RPF-WP-0027/0029. + +## Consolidate completed designs and owner dependencies + +```task +id: RPF-WP-0035-T01 +status: done +priority: medium +state_hub_task_id: "0f3606bb-e95b-5484-8a57-bcdd6e3916fd" +``` + +Completed 2026-09-05. Preserved the three designs under +`docs/credential-lane-designs/`, identified native owner responsibilities and +linked each superseded task below. Owners have not been sent new requests and +no new external acceptance is claimed. STATE-WP-0085-T09 is already done; +the signing dependency belongs to the proposed FLEX-WP-0020-T05 cutover. + +## Accept and provision secrets-engine service JWT login + +```task +id: RPF-WP-0035-T02 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +depends_on: [KEY-WP-0039-T02, MASON-WP-0009-T05] +blocking_reason: "Agent work, not a human gate: claim refusals (KEY-WP-0039-T02 probe) and capabilities-self deny, then ops-mason MASON-WP-0009-T05." +priority: high +state_hub_task_id: "e0c82ea9-05a5-537e-8fbf-67534263572e" +``` + +2026-10-11: requalified — the remaining waits are other owners' tasks, not a human gate. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0032-T02. Design: +`docs/credential-lane-designs/secrets-engine-service-jwt.md`. + +Platform owns the exact JWT mount/role/policy, effective-policy negative tests +and a metadata-only custody receipt. KeyCape owns issuer/JWKS and service +registration (KEY-WP-0009); secrets-engine owns service authentication and +authority consumption (SECRETS-WP-0008-T06, SECRETS-WP-0007-T04). + +**Unblock:** live registration and protected client custody, reviewed exact source +and attended apply authority. Issuer/JWKS and consumer source claims now agree; +see the 2026-09-27 return below. A service login does +not grant lane mutation authority. Do not build another identity provider or +lifecycle engine here. + +**Done when:** approved exact role succeeds for the intended service, wrong +issuer/audience/subject/claims and unrelated secret access fail, bounded TTL +and revocation are proven, the consumer explicitly opts into the verified +contract, and rollback/cleanup receipts contain no secret material. + +2026-10-09 (T03 source): founder ruled the tenant segment stays `coulomb` +(ops-mason `b72ff77d`). New CCR request type `workload-kv-operator-matrix` +(`scripts/operator_matrix_lane.py`): exact per-entry capabilities, OIDC role on +the existing `netkingdom` mount only, and exact agent denies on all four data +and metadata paths appended to the live `agent-high-risk-boundary` (live content +preserved; partial presence refused). `scripts/fluid_telegram_custody_move.py` +copies the four undocumented `infotech` entries with CAS 0, verifies all, then +metadata-deletes the sources. `scripts/kv_duplicate_retire.py` retires +`activity-core/default/llm-connect-provider-secrets` only if no live non-admin +policy grants it. Founder session (each helper prints nothing; read the receipts): + +```bash +cd ~/railiance-platform +export BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 +W='warden access openbao-platform-admin-login --exec --' +# 1. dry-runs (no value reads, no writes) +$W python3 scripts/fluid_telegram_custody_move.py --dry-run --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move-dry.json +$W python3 scripts/kv_duplicate_retire.py --dry-run --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire-dry.json +# 2. lane: approve, confirm binding, apply +python3 scripts/credential-change.py approve CCR-2026-0039 --reviewer "platform-owner, fluid-telegram-owner, key-cape-owner (founder Bernd Worsch)" --comment "Approve ops-mason plan fluid-telegram-operator-credential-lane (spec 41a0ca27): four-entry matrix at coulomb/fluid-telegram/hall-of-helix, OIDC role on netkingdom, agent denies." \ + && python3 scripts/credential-change.py confirm-binding CCR-2026-0039 --reviewer founder --comment "groups=[fluid-telegram-operators] (LLDAP, member tegwick) and /assurance/level=aal2 match key-cape b2ed890f." \ + && $W python3 scripts/credential-change.py applier-apply CCR-2026-0039 --confirm "DELEGATED APPLY CCR-2026-0039" --actor founder --record-state-hub --quiet +# 3. custody move, then duplicate retirement +$W python3 scripts/fluid_telegram_custody_move.py --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move.json +$W python3 scripts/kv_duplicate_retire.py --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire.json +``` + +2026-10-09 (T03 founder session): CCR-2026-0039 applied at 10:30Z; readback +matched for the 8 boundary denies, policy and role. Custody move `moved`: all +four entries copied at coulomb v1 (operator-session from infotech v4) and the +infotech entries metadata-deleted. Duplicate +`activity-core/default/llm-connect-provider-secrets` retired; its first dry-run +refused on mount-wide `platform/metadata/*` survey grants, after which the check +was narrowed to data-path grants (`64ae594`). Receipts: +`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +2026-10-03 (CUST-WP-0075): gate check. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named in the design is open. It is not the last one: the design says to confirm the exact live client registration and protected client-side custody before writing, and positive-login proof needs a real KeyCape service JWT. KeyCape's contract (`openbao-service-auth-contract.md`) and KEY-WP-0009 claim source registration only; the live registration of `secrets-engine-openbao` and its client-credential custody are "a separate approved custody action" that no workplan task owns yet (SECRETS-WP-0008-T06 waits on this task). Re-qualified with `blocked_on: message-from:key-cape`; key-cape was asked for the owning task id, which will replace it as `depends_on`. The design stays proposed and no child command was written. Not approvable in D1 yet. + +2026-10-04: Founder authorized the prepared coordination request. Sent +`b4fc62ea-f92c-4410-919a-9f3cce2d406b` to key-cape on preparation thread +`f84637fa-2355-4971-a2dc-7f1fd01710a8`, referencing platform source +`6b91d510395215d178d60ee8884e7fc00930a0cf`. Requested actual registration and +protected-custody owning tasks/status/revisions and non-secret receipts. Source +registration is not live custody; no value fetch or live registration was +requested. T02 remains waiting on the owner return and separate execution gates. + +2026-10-04 blocked-task review: KeyCape returns 58826056/eb20a78c now identify +KEY-WP-0037-T02/T03/T04, replacing the unowned-registration wait with real +dependencies. Prepared proposed CCR-2026-0033 and exact-path issuer policy/auth, +sso-only ESO and evidence checklist from the returned candidate coordinates. +No issuer/consumer value, registration or native issuance is supplied by them. +secrets-engine must return independent source acceptance of consumer host/path, +protected delivery and rotation/revocation ownership; awaiting that source phase +does not depend on its full live service-login task. KeyCape's exact-primary sync +remains pending its scoped historical identity repair. Requirements and acceptance +boundaries: `docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`. +This workplan was already blocked and remains blocked on its open owner/live gates. + +2026-10-06: secrets-engine returned consumer custody source acceptance +(message 680136e2, SECRETS-WP-0012, commit a3897c2). CCR-2026-0033 finalized as +**proposed**: KV path corrected to `platform/workloads/keycape/secrets-engine-openbao` +(applier scope), consumer copy coordinates with D1-D4 pending founder choice, +rotation/revocation ownership, live order and rollback. Attended custody child +`scripts/keycape_secrets_engine_openbao_custody.py` with fake-only tests +(`tests/test_keycape_secrets_engine_openbao_custody.py`) refuses without an exact +founder decision id recorded in the approved CCR. Nothing executed, generated or +applied; nothing added to active GitOps. The founder approval it needs is T09. + +2026-10-09: KEY-WP-0037 finished 2026-10-07 (registration live, issuance +verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Source for this +lane is now complete as **CCR-2026-0038** (proposed, +`credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml`). +The delegated applier gained a narrow `service-jwt-login` request type +(`scripts/service_jwt_lane.py`): auth mount fixed to `keycape-services`, policy +must equal the generated login-self policy, role/config keys allow-listed, +TTLs at most 15m, uses 1..16, `token_no_default_policy`, refusal if the mount +exists with another type, and a value-free readback compare after the writes. +Policy `secrets-engine-login-self` now also carries explicit `deny` on +`platform/{data,metadata}/workloads/keycape/secrets-engine-openbao` so +ops-mason invariant (ii) (no capability on the client-secret path) holds even +if identity groups were ever attached. Tests: `tests/test_service_jwt_lane.py` +(8) plus the updated contract test; full suite unchanged apart from 5 +pre-existing failures unrelated to this lane. + +Founder apply (one line; approval, binding confirmation and silent apply): + +```bash +cd /home/worsch/railiance-platform && python3 scripts/credential-change.py approve CCR-2026-0038 --reviewer "platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd Worsch)" --comment "Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self (self endpoints + deny on the client-secret path)." && python3 scripts/credential-change.py confirm-binding CCR-2026-0038 --reviewer founder --comment "Bound claims match KeyCape registration: aud secrets-engine-openbao, sub service:secrets-engine, principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social RS256." && warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/credential-change.py applier-apply CCR-2026-0038 --confirm "DELEGATED APPLY CCR-2026-0038" --actor founder --record-state-hub --quiet +``` + +Done after that: login proof with a real KeyCape service JWT +(SECRETS-WP-0012-T03 probe-openbao; policies exactly +[secrets-engine-login-self], capabilities-self deny on the guarded paths, +revoke-self), negative claim checks, then publish the consumer contract file +and ops-mason MASON-WP-0009-T05 rechecks invariant (ii). + +## Implement the platform operator-write CCR contract and Fluid lane + +```task +id: RPF-WP-0035-T03 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +blocking_reason: "Founder session done 2026-10-09; waits on ops-mason verification (MASON-WP-0005-T05) and the FT-WP-0002 owner salt CAS probe." +priority: high +depends_on: [MASON-WP-0005-T05, FT-WP-0002] +state_hub_task_id: "f47e5bc5-6f3c-54bb-aa35-260ad03892ba" +``` + +2026-10-11: requalified — founder part done; remaining waits are owner tasks. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0033-T02. Design: +`docs/credential-lane-designs/fluid-telegram-operator-kv.md`. + +Platform owns the per-path capability schema/validator, exact OpenBao policy +and accepted custody coordinates. MASON-WP-0005 owns construction coordination +and engine integration; KeyCape/NetKingdom own OIDC/MFA and group membership; +FT-WP-0002 owns client CAS, prefix correction, output containment and Telegram +application acceptance. Retain the existing read-only CCR semantics. + +**Unblock:** accept tenant/path and per-entry field/capability matrix; confirm +actual group/assurance and callbacks, reviewed construction contract and writer +authority. Contract review can proceed without a live credential; the final +schema cannot be treated as accepted solely because a draft exists. + +**Done when:** validation rejects broad/unsupported grants, the consumer proves +CAS=0 first-write behavior and no value output, approved identities can perform +only the exact matrix, negative/expiry/revocation checks pass, custody is seeded +through the separate writer, and the verified route has a safe handoff receipt. +The unattended adapter remains a separate demand and gets no operator session. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Accept the needed signing lane and deliver it to the owning runtime + +```task +id: RPF-WP-0035-T04 +status: done +priority: medium +state_hub_task_id: "35a85846-61d5-54ce-8b18-ede45733d53c" +``` + +Supersedes RPF-WP-0034-T02. Design: +`docs/credential-lane-designs/state-hub-preflight-signing.md`. + +Platform owns signing-key custody, exact read policy/role and scoped delivery +acceptance. State Hub owns API chart/env wiring, all-replica rotation fencing +and health. FLEX-WP-0020-T05 owns the rename preflight/cutover dependency; +STATE-WP-0085-T09's adoption-plan delivery is already complete. + +**Unblock:** State Hub/repo-manager and the consuming migration owner confirm +that this transitional State Hub lane is still needed during retirement; +record the target runtime, namespace/SA/auth audience and an executable +rotation fence, plus approved writer and deployment window. Do not broaden the +lane into a general repository-rename authority or provision for a stale demand. + +**Done when:** protected one-time generation, API-only ESO delivery, negative +access checks and a non-mutating signed preflight pass; every API replica uses +the accepted version; rotation/invalidation and recovery are evidenced. No +repository rename is part of S3 lane acceptance. If demand is withdrawn, record +the owning decision and cancel this task explicitly rather than provision it. + +2026-09-05 continuation: verified the live primary cluster identity and healthy +single API replica; the signing ExternalSecret is still absent. Added a writer +guard against wrong-cluster kubeconfigs before any OpenBao access. The default +workstation kubeconfig's local port-forward listener was unavailable. Activation +still needs the contained attended OIDC/MFA login and the acceptance evidence +above; source preparation is not live completion. See +`history/2026-09-05-preflight-signing-activation-readiness.md`. + + +Completed 2026-09-05: user-led attended activation generated version 1 and +rotated to version 2 with every API replica stopped. Exact access and negative +identity checks passed; ESO delivery and API-only exposure passed; the recovered +single API replica accepts new signed preflight and rejects its predecessor by +signature, with healthy primary identity and no preflight blockers. State Hub +chart commit `49e3182`, Helm revision 59. No repository rename executed. +Evidence: `docs/evidence/RPF-WP-0035-T04-signing-activation-2026-09-05.json`; +closure: `history/2026-09-05-preflight-signing-activation-complete.md`. + +## Admit KeyCape approval-engine client custody and delivery + +```task +id: RPF-WP-0035-T05 +status: done +needs_human: false +intervention_note: "" +priority: high +state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c" +``` + +Answers KEY-WP-0013-T02 (State Hub message +`278a3ebe-b529-49f6-bd1a-e3ebcf318260`). Admission: +`docs/credential-lane-designs/keycape-approval-clients.md`; requests +`CCR-2026-0017` (secrets-engine-approval) and `CCR-2026-0018` +(approval-engine-operator). + +Platform owns the two custody paths, exact-path read policies, Kubernetes auth +roles and the KeyCape-side ESO delivery. KeyCape owns the client registrations, +issuance, claim set and disablement; approval-engine owns approval semantics and +audit of emitted actions. + +2026-09-08 admission response: both proposed KV paths confirmed unchanged; field +`client_secret` corrected to `CLIENT_SECRET` for the uppercase KV convention and +CCR validator. Kubernetes delivery references confirmed against the live `sso` +namespace, which already resolves `KEYCAPE_RAPP_QONTO_CLIENT_SECRET` through the +same `secretKeyRef{key: client-secret}` shape on image `main-153258b`. Attended +authority named as the governed `openbao-platform-admin-login` lane +(`founder_required`); KeyCape's refusal to treat its generic `warden plan` +database match as authorization was correct. Rollout agreed as one attended +session with the KeyCape reading build pinned but undeployed, ordered after the +Authelia issuer precondition in message `c8b1ad10-dae8-48fb-a0ea-7e2a101c54bf`. +Policies, ClusterSecretStores and ExternalSecrets are written and validated, +none applied. + +**Unblock:** owner approval of both CCRs, a KeyCape image that reads both +environment names, the settled Authelia `iss` pin, and a founder-attended window +date. Verifier-side custody only — no client-side read lane is admitted, and no +scope beyond the two declared sets. + +**Done when:** both CCRs are approved, the attended window seeds both KV paths +with CAS=0, policies/roles/stores/ExternalSecrets apply and sync, the KeyCape +build resolves both environment names, KeyCape evidences live JWKS signature and +exact claim bindings with excess scopes denied (operator `consume`, human +`consume`), platform evidences cross-path/wrong-identity/out-of-namespace denial, +and every receipt is metadata-only. If either registration is abandoned, KeyCape +disables it before the KV version is destroyed. + +### 2026-09-08 actual upstream issuer returned + +The admitted KeyCape one-shot probe verified the actual signed upstream issuer +as **`https://auth.coulomb.social`** at 21:44:44 UTC. Signature, audience, +validity window and nonce checks passed and the pinned Job exited 0. All +five temporary resources and the Pod were removed; normal KeyCape Deployment +and config Secret metadata are unchanged. See +`docs/evidence/2026-09-08-keycape-upstream-issuer-proof.json`. + +T05's unknown-issuer input is resolved. The configuration owner still ensures +`authelia.issuer` equals that exact HTTPS value before the custody window. +Both CCRs remain proposed and await the named reviews; this probe grants no +custody mutation or client-side read. Keep the current authority preflight and +this signed-token proof as separate receipts. Live ESO/client/approval and +separate audit/client-side custody acceptance remain open. + + +2026-09-09 configuration and review-queue return: NetKingdom pinned the verified +HTTPS issuer, using an atomic UID/resourceVersion test and independent readback. +Secret revision `58713343`; unrelated configuration and signing key unchanged; +no Deployment rollout. Receipt: `docs/evidence/2026-09-09-keycape-upstream-issuer-pin.json`. + +The two existing CCRs remain proposed. They now link to concrete pending review +decisions, with platform-operator and key-cape-owner named explicitly. See +`docs/credential-lane-designs/keycape-approval-clients-review.md`. T05 owns this +human dependency; HFACT consumes it without a duplicate approval request. +Custody/ESO activation, client verification and the separate client-side/audit +lanes remain open. Current CLI apply plans refuse the proposed requests. + + +2026-09-09 admission: the user explicitly approved both CCRs in the named +platform-operator and key-cape-owner roles. Both source requests are approved +and both linked Hub decisions are resolved. Receipt: +`docs/evidence/2026-09-09-keycape-approval-admission.json`. The completed review +intervention is cleared; T05 is progress while the contained first-provision +procedure is exercised and the admitted attended rollout is carried through. +Verifier-side scope, separate client-side/audit lanes and live acceptance remain +as defined in the reviewed requests. + +2026-09-09 verifier-side return: both CCRs are verified after recorded user approval, +CAS=0 version-1 custody, native read/auth denials and revocation, Valid stores, +SecretSynced delivery, compatible KeyCape rollout and live positive/negative +service checks. Existing human OpenBao login passed again on the new image. +Receipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. Failed attempts restored the compatible +configuration/image and detached delivery; final resume reused version 1. + +T05 is done against its verifier-only acceptance criteria. Its former +"remains progress for client-side reads" statement expanded the task past its +reviewed scope; that residual now has the live owner task RPF-WP-0035-T06 below. +Neither Warden fetch selector is resolvable through these verifier-only CCRs. +Do not re-request the completed two named reviews or reseed these paths. +Rotation is a distinct, version-guarded operation. + +## Dispose of the ungoverned whynot-design npm duplicate + +```task +id: RPF-WP-0035-T07 +status: wait +decision_id: 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa +blocking_reason: "Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish." +priority: high +depends_on: [SECRETS-WP-0006-T06] +state_hub_task_id: "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b" +``` + +2026-10-11: requalified after founder decision D3 (trust root, build-mode default) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Found by the attended session on 2026-09-10 while settling the npm field +question. `secret/coulomb/whynot-design/npm/publish` exists at version 1, +created 2026-07-03T15:00:44Z and never updated — five days after the governed +lane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified +(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and +outside any CCR here. Receipt: +`docs/evidence/2026-09-10-npm-lane-field-resolution.json`. + +Only metadata was read. Its field names were not enumerated, its value was not +read, and nothing was deleted — a location holding real credential material is +disposed of deliberately, not tidied away in the session that found it. + +The likely explanation, unconfirmed: secrets-engine reports the lane's field +under a lowercase name that is absent from the governed path, and their catalog +declares this legacy location. If their proven pilot publish read from here, +then a working production lane has been running off an ungoverned duplicate, +and the governed lane's acceptance evidence describes a path the consumer does +not use. That is worth establishing before anything is removed. + +**Operator decision, 2026-09-15:** destroy the legacy path after confirming the +governed lane is the live consumer. Do not wrap `secret/coulomb/whynot-design/npm/publish` +in a CCR. Value remains unread. Platform will ask secrets-engine which path +publish actually reads before any attended destroy. + +**Unblock:** admit the governed exact-path AppRole policy and coordinated catalog +path/field migration under SECRETS-WP-0006-T06; prove native delivery from the +governed lane before the attended legacy destroy. secrets-engine confirmed the +legacy source path on 2026-09-21 (message `355424d4-17ab-435e-9e1d-6921775cb4a2`). +No comparison of values, fingerprints, lengths or shapes is needed or authorized. + +**Done when:** the legacy path's provenance and consumer are established, the +governed lane is confirmed as the one in use or the consumer is moved to it as a +reviewed lane change, the duplicate is destroyed under the September 15 operator decision and the +disposition is recorded. Do not bring the legacy duplicate under a CCR. If the value proves to be live and +ungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027: +never record the value, fingerprint, length or shape. + +2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here. + +## Admit the separate approval client-side readers + +```task +id: RPF-WP-0035-T06 +status: done +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +priority: high +intervention_note: "" +state_hub_task_id: "68bff751-e48b-548b-8fb4-dfb3b16210c2" +``` + +2026-10-11: requalified after founder decision D1 (attended window standing rule) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +**Current return, 2026-09-10:** CCR-2026-0020 is cancelled on the requesting +Approval Engine owner's explicit withdrawal, source +`849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md`. +No presenter exists and no reader is wanted. The validator now accepts terminal +cancellation of an incomplete request only with owner/source/reason evidence, +retained declared omissions and a disabled, non-resolvable front door. Apply +remains refused. No live identity, policy, role, custody or verifier was changed. +Human approval follows existing INFD-WP-0001-T07/T08; future service requesters +need a separate narrow registration, not this withdrawn bundle. + +**Operator binding confirmed, 2026-09-14:** The user explicitly selected +`net-kingdom-admins` and authorized applying CCR-2026-0019. Its OIDC role is +`secrets-engine-approval-client-workload-kv-read`, aligned with the platform +applier naming rule; policy and exact KV scope are unchanged. The metadata dry +run passes with no warnings. Attended apply and exact role/policy readback passed; the enclosing Warden +command exited successfully after its self-revocation/cleanup. Receipt: +`docs/evidence/2026-09-14-ccr0019-operator-binding.json`. Scoped delivery proof +remains pending; the front door stays non-resolvable. Completed CCR-2026-0017/0018 +remain closed and T06 stays `wait`. + +Consumer procedure returned in source, 2026-09-10: +`secrets-engine@98d72ceb1dbcff2d2a80fb8c3058d76777a0ac93:docs/approval-service-auth.md` +specifies the requested private 0700 runtime directory, 0600 file outside Git, +path-only use, claim/consume lifetime and attended cleanup including hard-stop +residual inspection. CCR-2026-0019 retains this source-review comment without +changing admission status. Exact group, required-owner review, attended apply and +native positive/negative/cleanup evidence remain. No role or credential changed. + +Separate retained owner decision: KeyCape's 2026-09-10 return +`21427688-725f-4dea-aab4-7c78fd4328d2` identifies the already-live, unpresented +CCR-2026-0018 registration. Approval Engine, KeyCape and Platform must explicitly +decide retention/expiry or coordinated disablement. Reader cancellation neither +disables that live registration nor accepts indefinite retention. Keep this +disposition in T06; it is separate from the wanted CCR-2026-0019 factory reader. +No unilateral issuer/config/Secret change is authorized by this closeout. + +**Operator decision, 2026-09-15:** coordinated disablement with KeyCape and +Approval Engine. Platform will not disable the live registration or verifier +delivery unilaterally. T06 stays `wait` until both owners confirm the joint +disablement sequence. + +Residual handoff from RPF-WP-0035-T05; consumes the completed verifier custody +without extending CCR-2026-0017/0018. Owner: railiance-platform with the named +secrets-engine and approval-engine operator consumers. + +Prepare separate exact-reader admissions for existing version-1 paths: +`platform/workloads/secrets-engine/approval-client` and +`platform/workloads/approval-engine/operator-client`, field `CLIENT_SECRET`. +Name each actual actor/placement, bounded authentication/reader policy, protected +consumer delivery, cleanup/revocation and rollback, then obtain the required +owner reviews for those concrete requests. No reseeding, rotation, shared reader, +reuse of the sso verifier Secret, or implicit operator consume grant. + +2026-09-09 preparation return: both exact-reader admissions are prepared as +`CCR-2026-0019` (secrets-engine) and `CCR-2026-0020` (approval-engine-operator), +with their exact-path read policies written and committed. Design: +`docs/credential-lane-designs/keycape-approval-client-side-readers.md`. Both +reuse existing version-1 custody; no reseed, rotation, shared reader or verifier +Secret reuse. Both are `in_flight` and unapproved; nothing is applied. + +Read-only survey findings that decided the two shapes. Namespace +`secrets-engine` holds only ServiceAccount `secrets-engine` with no workload, +and `flex-auth/flex-auth-secrets-engine` is that consumer's PDP, not the +service; secrets-engine consumes the client secret through an operator-run CLI +reading `SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE` (SECRETS-WP-0009-T03, +revision `9eb07fd`). So reader 1 is an attended operator-workstation OIDC lane, +not an ESO lane. approval-engine has no namespace, workload or Service; its +manifest is unapplied, and no owner source names who presents the operator +client — approval-engine verifies these tokens and never holds them. + +**Unblock:** reader 1 needs the exact NetKingdom/KeyCape group claim for the +authorized operator, plus secrets-engine confirming the file mode and removal +step; `openbao.auth` is declared missing rather than filled with a placeholder +that would later read as a confirmed binding. Reader 2 needs its owner to name +the presenting actor and placement, or to record that no client-side reader is +wanted so the request is cancelled. Naming a reader for the widest approval +scope without that decision is the failure this task exists to avoid. + +**Done when:** each reader has a named actor and placement, a completed and +reviewed auth binding, admitted delivery, and its owner approvals; positive and +negative checks pass, including cross-path, wrong-identity and parent-list +denial and operator `consume` denial; or the request is explicitly cancelled by +its owner. Rotation stays a distinct version-guarded operation shared with +CCR-2026-0017/0018. + + +Consumer input supplied 2026-09-09: secrets-engine now implements per-request +`secrets-engine-approval` exchange from a protected temporary client-secret file, +with exact approval-engine / tenant:platform / read-or-consume scope, no token +file and no fallback. The pinned KeyCape image and actual Approval Engine source +passed its disposable component exercise; only the PDP was a sequencing double. +See `secrets-engine/docs/approval-service-auth.md` and the metadata receipt +`secrets-engine/docs/evidence/2026-09-09-approval-identity-exercise.json`. + +Routing check: `warden route show keycape-secrets-engine-approval-client` is +unknown; generic `openbao-api-key` routes ownership only and is not a delegable +lane. Do not advertise a working fetch command before this task supplies its +own accepted native delivery return. Client-side admission is not ready for a +new human decision until exact requests and contained execution/rollback checks +are reviewable; the completed verifier reviews must not recur in that queue. + +**Done when:** each retained consumer admission is approved and implemented, or +its requesting owner explicitly cancels it (CCR-2026-0020 now satisfies that branch); +actual consumer authentication/delivery succeeds; sibling/listing/wrong-reader +and scope refusals plus reader expiry/revocation/cleanup are evidenced; version-1 +custody and verifier availability remain intact. Return the source and metadata +receipts to HFACT-WP-0001-T03, SECRETS-WP-0009-T03 and APPROVAL-WP-0002-T01/T05. +Audit receiver/sender custody remains AUDIT-WP-0009-T09 and must not be folded +into this client-identity grant. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Admit the two factory audit-sender custody lanes + +```task +id: RPF-WP-0035-T08 +status: wait +decision_id: "ab85ae8a-12a0-4945-ae64-1d3d86d5b26f" +blocking_reason: "Approved conditionally (ab85ae8a, standing change rule): executes once independent archive readback and the interim bearer revocation receipt exist; owner work with audit-core." +priority: high +assignee: railiance-platform +intervention_note: null +blocked_on: message-from:audit-core +state_hub_task_id: "0ef52c26-2669-5cd1-8149-b1f6fcdda6cb" +``` + +2026-10-11: requalified — ab85ae8a resolved under the standing build-mode change rule. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +2026-10-03 correction (CUST-WP-0075, informed-decision sitting draft `55fb078`): the D1 routing was wrong. First provision and delivery already ran on 2026-09-11, with seed and delivery receipts, and the review packet says not to repeat them. The task is not a provisioning-window act. It was taken off decision D1, and its blocking_reason now names what actually remains. railiance-platform should re-qualify it further if the receiver rollout has since happened. + +2026-10-03 (CUST-WP-0075): re-qualified. The receiver rollout already happened: Audit Core c82e0442de0f carries evidence_kind and native producer accepted/duplicate and scope/read-refusal checks passed 2026-09-11 10:42 UTC (`docs/credential-lane-designs/factory-audit-senders-review.md`, `factory-native-acceptance.md`). Remaining: independent archive readback and audit bearer-revocation acceptance. Still not a provisioning-window act. + +Consume AUDIT-WP-0009-T09/T11's exact declarations for approval-engine and +informed-decision: tenant:platform, write-only, load-bearing, redact. Source +preparation supplies two approved CCRs, independent exact-path policies/ESO +projections, and the attended `factory_audit_custody.py` first-provision helper. +Its CAS and request-provenance checks preserve unrelated senders and recover +interrupted writes without generating replacements. The user approved all named review roles on 2026-09-11. Native +provision/delivery/receiver-ingestion acceptance remains open. + +The 2026-09-11 native read-only check found an additional deployment dependency: +receiver image c2fe39a is 1/1 Ready but does not support evidence_kind. The +synthetic native probe now refuses before any credential read. Current receiver +source passes. AUDIT T09/T11 retain compatible release/source-manifest rollout; +Approval Engine's missing namespace remains its owner prerequisite. + +[Review packet](../docs/credential-lane-designs/factory-audit-senders-review.md). +[Preparation evidence](../docs/evidence/2026-09-11-factory-audit-custody.json). +Do not fold these senders into CCR-2026-0019 or the cancelled CCR-2026-0020. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Dependency review — 2026-09-06 + +### 2026-09-09 tenant question resolved — no change needed + +The `tenant:coulomb` / `tenant:platform` discrepancy raised against T02 is not a +discrepancy. KeyCape confirms decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6` +binds the *approval chain* to the landlord zone and was applied to exactly two +registrations, `secrets-engine-approval` and `approval-engine-operator`. +`codex-railiance-platform` is not in that chain and correctly stays +`tenant:coulomb`, as do `secrets-engine-openbao` and the human directory default. +KEY-WP-0013-T04 records this and their +`TestServiceRegistrationTenantsAreExactPerDecision` pins every reviewed client's +tenant against the real fixture, so a reintroduced alias fails their build. + +`docs/credential-lane-designs/secrets-engine-service-jwt.md` already says +`tenant:coulomb` and is therefore correct as written. Bind the exact role to +`tenant:coulomb`. Do not "correct" it to `tenant:platform` later; that would +break the issued claim. + +SECRETS-WP-0008-T02 now records the local PIP claim/validation join implemented +and tested. Its remaining gate is the unreachable approval-engine claim endpoint +and access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old local +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 ` 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. + +### Sender approval recorded — 2026-09-11 + +The user replied "good, go on" to the explicit CCR-2026-0021/0022 question naming +platform-operator, audit-core-owner and both producer owners. Both exact requests +are approved; their existing State Hub decisions are resolved. This clears the +review request only. Receiver rollout, namespace readiness, attended custody and +positive/negative native evidence remain the execution gates. + +### Native receiver and attended execution return — 2026-09-11 + +Audit Core c82e0442de0f is deployed and passes the native synthetic contract. +Its existing 32-event chain/head is unchanged. The owner Approval Engine +namespace now exists and all four ESO objects pass strict server dry-run. +The two exact ingress rules are applied; sender custody/ESO application is not. + +Warden selected founder_required/oidc_login and attempted the reviewed silent +seed command through the contained wrapper. Login failed before command +handoff; no custody receipt was created. Warden could not confirm remote +session revocation. Await operator browser/MFA feedback and login/session +resolution. Approvals remain valid; T08 waits for the identity act, not review. + +The receiver check now selects component=receiver, so retained attestation-job +pods cannot falsely block a stable receiver. Eighteen custody tests pass. +[Native return](../docs/evidence/2026-09-11-factory-receiver-live.json). + +### Attended custody retry succeeded — 2026-09-11 + +The user requested a retry and completed the attended identity act. Both CCRs +are applied: independent version-1 custody and registry CAS 7→8 succeeded, +preserving other senders/fields. Warden exited 0 with self-revocation confirmed +for this session. This does not retrospectively attest the earlier failed +login's remote session state. The old login wait is cleared; T08 is progress +for ESO delivery, exact native reader/namespace refusals, receiver reload and +producer acceptance. No token is reseeded or rotated on continuation. +[Seed receipt](../docs/evidence/2026-09-11-factory-audit-sender-seed.json). + +### Delivery prepared; fresh login did not hand off — 2026-09-11 + +The delivery helper and custody receipt are committed at `44314ca` and exactly +projected on primary/railiance01. Seven delivery tests and 18 custody tests +(including 11 actual disposable OpenBao cases) pass. The fresh attended +delivery invocation exited 5 before command handoff; no native delivery +receipt exists, no ESO application or receiver restart ran. The receiver +remains 1/1 Ready on c82e0442de0f. Warden could not confirm revocation for this +failed login; that is separate from the successful seed session. T08 now waits +for this delivery identity act. Neither CCR review nor first provision reopens. + +[Delivery return](../docs/evidence/2026-09-11-factory-audit-delivery-login.json). +Use the reviewed delivery command with a new receipt after login feedback. +Actual producer ingestion/duplicate/refusal and bearer revocation acceptance +remain open under AUDIT-WP-0009-T09/T11. + +### Native delivery accepted — 2026-09-11 08:27 UTC + +The user returned and requested another login attempt. It succeeded and the +reviewed delivery command completed in 28 seconds. Both native ESO readers +passed exact-path access and explicit sibling/registry/metadata/listing denials, +wrong-SA/namespace refusal and the coding-agent deny check. Each 900-second +reader session was revoked and lookup refusal verified. Both intended +ExternalSecrets are Ready; exact producer value and ESO ownership match. The +disallowed namespace produced an explicit store restriction and no Secret; +the uniquely owned namespace is now absent. + +Registry version 8 matches the delivered receiver JSON. Audit Core reloaded +and remains 1/1 Ready on c82e0442de0f; /readyz reports operational/durable with +tamper_evidence=false, as bounded by AUDIT-WP-0009-T12. Warden exited 0 and +confirmed self-revocation for this successful session. Earlier failed login +receipts remain historical and are not retroactively attested. + +The login wait is cleared. T08 remains progress and CCR21/22 remain applied +for native producer ingestion/duplicate/scope/read-refusal and bearer +revocation acceptance under AUDIT T09/T11. No credentials were reseeded or +rotated. No producer was deployed and no factory attempt or paid call ran. +[Native delivery receipt](../docs/evidence/2026-09-11-factory-audit-delivery-live.json). + +### Native producer return — 2026-09-11 10:42 UTC + +Both actual source adapters used their own ESO-delivered credential inside a +bounded native Job. Each synthetic event received 202, retained its durable +outbox after an injected lost receipt, and received duplicate 200 after a fresh +process reopened the outbox. Each source's reconciliation reported exactly one +record for its unique probe class. Wrong source/tenant, seven archive read +routes, sibling reconciliation and invalid-bearer requests were refused. + +The first Informed Decision probe exposed a private-store startup defect: +fsGroup volumes add inherited setgid to a newly created 0700 directory. +Informed Decision `1a12223` corrects creation without repairing unsafe existing +data. The regression failed before the fix; the available suite now passes +335 tests with 39 optional checks skipped. Native retry verifies the exact +corrected helper. Six probe tests and eleven rebuilt-container checks pass, +including actual setgid-volume startup, restart/restore and cleanup. + +All temporary probe Jobs, Pods, ConfigMaps and NetworkPolicies are verified +absent. Receiver c82e0442 remains operational/durable; tamper_evidence=false. +Producer verification requires no operator registry read or new OpenBao login. +Independent readback is a separate attended command consuming the successful +receipt; it must not rerun the producer jobs. Both attended verification-login +attempts this session ended before handoff (exit 5; remote revocation +unconfirmed), so independent archive readback remains pending. + +This proves synthetic outbox delivery/recovery with native sender credentials, +not domain-transaction atomicity, deployed producer services or human binding. +An invalid bearer is not a revoked formerly valid bearer. AUDIT T09/T11 and +RPF T08 remain progress for independent readback and audit bearer-revocation +acceptance; CCR21/22 remain applied. Service/policy/human admission and native +runtime/spend gates remain separate. Factory attempts and paid calls remain 0. + +[Native producer receipt](../docs/evidence/2026-09-11-factory-native-producers.json). + + +## Independent audit readback — 2026-09-11 13:11 UTC + +The existing attended readback command completed with exit 0 while the user +was present. Independent read-only identity `operator` found both retained +`factory-audit-20260911104152-94aced` producer events with exact source and +`tenant:platform`; receiver integrity is intact across 36 events. The wrapper +confirmed this session's self-revocation and private-helper cleanup. Prior +failed sessions' unconfirmed revocation remains historical unresolved evidence. + +This supersedes the earlier readback-login wait. No producer jobs were rerun, +no credentials were reseeded and no event was written by the reader. The +inherited zero registry-read count belongs to the producer phase; the attended +reader did consume registry version 8. CCR21/22 stay applied and owner tasks +stay progress pending formerly-valid audit-bearer revocation acceptance. +Service/domain-transaction/human and factory runtime/spend admission remain +separate; factory attempts and paid model calls remain zero. + +Receipt: [native readback](../docs/evidence/2026-09-11-factory-native-readback.json). + + +### T06 native reader acceptance — 2026-09-14 + +The scoped Warden login lane `secrets-engine-approval-client-login` now routes +to the applied OIDC reader and the platform's silent preflight. The installed +Warden package still carries an older catalog; use the explicit source catalog +`WARDEN_ROUTING_CATALOG=/home/worsch/ops-warden/registry/routing/catalog.yaml` +until its next normal installation refresh. This lane authenticates the reader; +it is not a raw secret fetch or retained-file delivery interface. + +Live effective-policy and capability checks passed: only exact data/metadata +read, no sibling secret, parent listing, write or control-plane authority. +A second contained session read existing version 1 into an operator-owned 0600 +file in a private 0700 runtime tmpfs directory. The native consumer exchanged +separate read and consume scopes; Approval Engine verified the read token before +returning 404 for a fresh nonexistent approval, and refused the consume-only +token's read request with 403. No approval was created, bound or consumed. +Both Warden sessions exited 0 after self-revocation/helper cleanup; temporary +credential file and directory were removed. Four refusal/path/redirect tests +pass. Receipts are in platform `docs/evidence/2026-09-14-ccr0019-{reader-preflight,delivery-check}.json`. + +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. + +### 2026-09-27 T02/T07 source follow-up + +T02 now has the exact proposed RS256 configuration, bounded JWT role and +self-only policy in `openbao/`. Operator correction: platform infrastructure +belongs to `tenant:platform`; KeyCape registration and consumer preflight are +corrected together. Existing live registrations must be migrated and verified. +Public discovery confirms issuer/JWKS/token endpoint. Registration/custody, +attended provisioning and live rejection/cleanup evidence remain required; +T02 stays wait. No service credential or backend entitlement was issued. + +T07 consumed the confirmed legacy consumer return. The stale value-comparison +ask is removed. WARDEN-WP-0037-T03's no-rotation hold stays in force until the +governed native migration is evidenced. Legacy destruction follows migration; +neither source reconciliation nor the historical pilot is that evidence. + +## Loose-end review — 2026-09-27 + +T08 now explicitly waits for formerly-valid audit-bearer revocation acceptance from AUDIT-WP-0009-T09/T11. Native delivery, producer checks and independent readback already passed; do not reopen login, seed or review gates. T02/T03/T06/T07 retain their latest exact service registration, signed-in human acceptance, owner delivery/disposition and governed-consumer migration dependencies. No credential value was read or changed. + +## Founder approval of the CCR-2026-0033 custody child + +```task +id: RPF-WP-0035-T09 +status: done +needs_human: false +priority: high +decision_id: 2ab717e1-7881-491e-aed4-28946550c289 +depends_on: [] +state_hub_task_id: "7c753be6-42f1-58a6-a4a4-a7ed686f461f" +``` + +Packets: `credential-change-requests/CCR-2026-0033.yaml` (custody child, KV +metadata, issuer ESO reader, live_order, rollback) and `CCR-2026-0034.yaml` +(attended operator OIDC reader, in-memory, 5m/4 uses). Revised 2026-10-06 per +founder direction; the consumer file is removed. Exact founder commands: +`docs/provisioning-windows/2026-10-04-1000/keycape/founder-runbook.md`. Live +order: custody child → platform applies policies/roles/ESO (Secret +sso/keycape-secrets-engine-openbao-client exists) → NetKingdom env patch +(NK-WP-0046) → KeyCape registration merge (KEY-WP-0037-T03) → KeyCape restart +immediately → live issuance check (KEY-WP-0037-T04) → OpenBao JWT role/login +proof (RPF-WP-0035-T02). Each live step after the custody run needs its own go. + + +2026-10-11 evidence reconciliation: T09's approval obligation is complete. +Authoritative founder decision 2ab717e1-7881-491e-aed4-28946550c289 is resolved, +decided by Bernd Worsch at2026-10-06T13:07:18.627943Z, and explicitly covers +A1 design, A2 CCR33/CCR34 plus owner reviews/bound claims, and A3 one custody run. +The approval comments in both CCRs record those exact grants; both source records +are applied. MASON-WP-0009-T02/T03 additionally record the October8 approval/owner-delivery +reconciliation and reference KeyCape +`docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`. Closing this approval task clears +its obsolete human gate. It grants no new run, credential access, rotation or +service execution: RPF35T02/T12, MASON9T05 and SECRETS8T06 retain their actual +native/adoption obligations. Historical per-step exclusions remain above. + +## Retire the approval-engine-operator client delivery and custody (CCR-2026-0018) + +```task +id: RPF-WP-0035-T10 +status: wait +priority: medium +blocked_on: message-from:approval-engine +blocking_reason: "Blue lane under the standing change rule (removing access, with reviewed order, rollback and receipts): executes once approval-engine confirms there is no presenter. No founder window needed." +state_hub_task_id: "af2d4dba-f83a-5819-9a8b-671bae799364" +``` + +2026-10-11: access removal is blue lane (canon build-mode-change-authorization_v0.1); no founder window. + +key-cape proposed a joint disablement on 2026-10-10 (message `7f2128fb`). +Precondition: approval-engine reconfirms there is no presenter. The order is the +reverse of provisioning, so KeyCape never starts with a client whose secret is +missing. key-cape removes the registration and restarts (1), checks that +`invalid_client` is returned (2), and net-kingdom removes +`KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET` from Deployment `sso/keycape` +(3). Platform steps, amended from the proposal: + +4. **Delivery.** In one commit, remove ExternalSecret + `sso/keycape-approval-engine-operator-client` from + `argocd/platform-addons/openbao-secretstore/keycape-approval-clients.externalsecrets.yaml` + and ClusterSecretStore `openbao-keycape-approval-engine-operator` from + `openbao-keycape-approval-clients.clustersecretstore.yaml`. Keep the + secrets-engine-approval objects. Then bump `targetRevision` of + `argocd/railiance01/applications/openbao-secretstore.application.yaml`. + The app is pinned and has no automated sync, so nothing changes live until + an attended `argocd app sync openbao-secretstore --prune` runs after step 3. + Verify, value-free, that the ExternalSecret, the store and Secret + `sso/keycape-approval-engine-operator-client` are gone. The target is + `creationPolicy: Owner` and `deletionPolicy: Retain`, so the Secret should + follow its owner; delete it explicitly if it does not. Then delete OpenBao + role `auth/kubernetes/role/external-secrets-keycape-approval-engine-operator` + and policy `workload-kv-read-keycape-approval-engine-operator`, and remove + their source files. Also remove policy + `workload-kv-read-approval-engine-operator-client` (CCR-2026-0020, cancelled) + if it exists live. +5. **Custody.** Run the metadata delete of + `platform/workloads/approval-engine/operator-client`, the destruction + foreseen in `docs/credential-lane-designs/keycape-approval-clients.md`. A + disabled client's secret has no recovery value; a narrowed successor gets a + fresh secret through the mint-secret lane at `platform/workloads/keycape/`. + Only after step 2's `invalid_client` receipt. Keep the agent boundary denies + for that path until the delete is verified, then drop them. + +2026-10-10: key-cape agreed the amended steps 4 and 5 (message `59304e33`, +KEY-WP-0013 c528daa). Waits on approval-engine confirming there is no presenter, +and on the founder's window. + +The manifest edits wait for the scheduled window, so a stray `targetRevision` +bump cannot remove KeyCape's secret before step 3. + + +## Complete independent service-JWT source preparation and execution design + +```task +id: RPF-WP-0035-T11 +status: done +priority: high +state_hub_task_id: "7952c8cd-c066-5b72-a025-78d24341c1ab" +``` + +2026-10-11: Platform-scoped agent loaded this checkout's AGENTS.md and INTENT, +RPF35-T02, actual CCR38/login contract/typed applier and Secrets Engine's native +claim/PDP/CAS/provider/apply flow. Frozen Secrets v2 manifest and all named staged +bytes/proof were hash-verified. Independent tests reproduced three source +counterexamples while retaining the frozen files: close exception can coexist +with native_verified=true; successful result needs no source/session fingerprints; +HTTP200 mixed errors+data envelope is accepted. Original 37 tests plus the three +counterexample tests pass (40 cases, synthetic/local only). Proposed owner design +`docs/credential-lane-designs/secrets-engine-task-execution-entitlement.md` binds +an explicit metadata-only execute-ccr action, immutable typed owner bodies, +CAS/journal replay control, 120s/12-use owner-held task token, independent payload +validation, native ACL endpoint bounds, revoke/readback and recovery. This completed +preparation record is established before the formal source review. It grants no +live authority and does not close T02 or represent acceptance by another owner. +Formal review artifact follows under this work item; all implementation/live +obligations are retained in T12 and existing T02 rather than a finished residual. + +## Implement and prove the separately approved task execution entitlement + +```task +id: RPF-WP-0035-T12 +status: progress +priority: high +depends_on: [RPF-WP-0035-T11] +state_hub_task_id: "914bf383-c13f-5247-9af0-91d7e3a4784a" +``` + +Review the proposed task-execution-grant schema and exact metadata-only execute-ccr +backend with Secrets Engine/access-engine/approval-engine; implement trusted service +subject and served consume verification, durable one-shot reservation, bounded +owner-held token issuer/middleware and exact source/payload enforcement. Obtain +separate exact founder approval/attendance before provisioning or live actions. +Prove disposable intended result and identity/action/target/body/time/replay/crash/ +cleanup negatives, and return owner-native acceptance. Existing service login policy +and defaults stay unchanged. T02 still owns login/claim/TTL/use/MASON acceptance; +Secrets T06 separately owns dispatcher adoption and steady-state default migration. + + +2026-10-16 T12 wave 5 source preparation: disposable adapter now binds owner +canonical before/after metadata snapshots to existing descriptor hashes, rejects +per-target baseline/readback mismatch, and records readback/verified evidence. +Mediator reports cleanup-confirmed only after independent fixed cleanup receipts. +Complete role metadata and policy name/HCL/version/cas are compared; validated +modification timestamp alone is excluded. This is sequential fixture acceptance, +not aggregate CAS, concurrent-writer exclusion or native production completion. +Role conflict may follow a policy write. Restart refuses dispatch and cannot +recover memory-only token/accessor cleanup handles. T12 remains progress; actual +fresh CCR/catalog/grant, source/trust/caller/policy admission, isolated owner custody, +scoped recovery and attended native acceptance remain explicit prerequisites. + + +2026-10-11 T11 refinement (same source-review trial): the exact Secrets Engine +v3 manifest `6bb05bac74e4939c3e42db2ae95c5f9fb4616bb20cc285811a315c26669ebce1` +and all named bytes/proof were verified and independently re-reviewed. The three +v2 counterexamples are corrected: close exceptions cannot pass through stale true +flags, complete typed source/session/attempted/revoke evidence is required, and +mixed HTTP200 errors/data fails closed. 49 maker/current-provider tests plus three +independent regressions passed (52, synthetic/local only). Platform source review +`docs/reviews/2026-10-11-secrets-service-jwt-v3-platform-review.json` approves only +the corrected boundary verifier and truthful packet. Prior changes-requested v2 +review is retained; this is not a second native success or changed authority. +No native or founder go is granted. T02, T12 and Secrets T06 remain open; the +metadata-only execute-ccr pilot is explicitly insufficient for generic lifecycle +adoption. All consume-verification/journal/action/body/backend implementation and +native acceptance gates remain real prerequisites, not architecture promises. + + +2026-10-11 T11 readiness refinement: independently reviewed frozen consumer +manifest `709b9dddd1c8f00a995b1ff14264323fbe080ed95df244270ce9607528878fa7`. +Platform source review `docs/reviews/2026-10-11-secrets-execution-readiness-v2-platform-review.json` +approves the local fail-closed guard and proposed consumer contract direction only. +All ten current protected backend handlers pass provider args through readiness +before authorization/consume; session revoke checks before handle reads. Configured +auto/explicit service-jwt therefore cannot burn a protected-action approval or +open the insufficient login-self backend. Explicit env/bootstrap and self-only +probes retain their existing contracts; local compromise/reactivate and disabled +destroy remain separate. Existing ambient-token route readiness reads are unchanged, +not claimed governed by this guard. 58 isolated tests passed: original36 plus20 +provider/action cases, handler enumeration and actual session-revoke ordering. +Prior v2 changes-requested and v3 boundary source reviews remain unchanged, same +T11 trial. No runtime grant, native acceptance, new Access/Approval semantics, +backend entitlement or full Lifecycle adoption is approved. T02/T12/SecretsT06 and +WP13 implementation/native gates remain open; the metadata pilot substitutes for +none of the ordinary generic lifecycle outcomes. + + +## Complete independent KEY39 v4 lifecycle source review preparation + +```task +id: RPF-WP-0035-T13 +status: done +priority: high +state_hub_task_id: "8f6966fa-6e9a-58b2-8b40-c47340ec19d1" +``` + +2026-10-11: Platform agent loaded its owner instructions/INTENT and RPF35-T02, +actual applied CCR38, exact native role/policy source and frozen KEY39 lifecycle +v4 manifest `d079f85c47d5c2635e1ee633ea4d1346b1737ce2be9ca273f22a38e620f418d8`. +All staged entry hashes were verified without changing the reviewed inputs. +Source role omits expiration_leeway: its observed actual default must be confirmed +natively, with -1→0 and 0→150 normalization preserved as a bounded model. Source +claims and login-only policy are unchanged. The supplied 41 lifecycle tests pass; +five independent cases also pass, including a new exceptional-response-close +elapsed-bound counterexample and four current-leeway normalization checks. +A 10ms HTTP request can take over70ms because exceptional finally response.close +runs outside the hard elapsed timer. Unknown native login is correctly recorded, +but source total elapsed enforcement is incomplete. This completed owner +preparation record exists before the formal exact source review entry. No +credential was requested/read, native action run, owner checkout edited or native +session grant inherited. T02 retains native role/policy/leeway, negative claims, +cleanup acceptance and MASON gates; KEY39 producer handoff and founder attendance +remain prerequisites. Source correction/re-review is required, not a native success. + + +2026-10-11 T13 correction preparation (same trial): exact KEY39 v5 manifest +`d1f997624db46693a7126a6eb6435f6b3a353d5bd67dcc8a539683e4b7147285` +and all entry hashes verified. The v4 exceptional-close finding is addressed: +one 20ms abort is clipped to original remaining time and the nonresettable +aggregate cleanup budget; zero calls after aggregate expiry; failed abort stays +unconfirmed/unknown with signal state restored. 46 supplied lifecycle checks and +five independent regressions pass; the unchanged runner's earlier17 tests remain +valid against identical source SHA. Existing T13 preparation record is retained +before the formal v5 exact source review. V4 changes-requested review and earlier +failed history remain retained, with no native success, inherited grant or scope +promotion. Actual private producer admission, fresh installed role/leeway/policy +observation, authenticated founder window and native refusal/cleanup remain gates. + + +2026-10-11 T11 journal preparation refinement (source-only): independently +inspected frozen root-maker v2 manifest +`341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7`, +verified all input hashes, and ran14 supplied tests plus5 independent checks. +The actual four-process race admits once; a separately forked process exiting +immediately after pending intent leaves durable unknown/nonresumable state. +Private SQLite modes, lock admission and binding/replay protections remain guarded. +Three independent counterexamples show after_call accepts False,0.0 or text'0' +as persisted integer ordinal0, contrary to before_call's exact integer validation. +Completed preparation under this existing done ownerT11 record precedes formal +review; require identical ordinal/call-digest validation before confirmation so +malformed calls cannot clear pending outcome. RPF35-T12 retains caller/PDP/consume +validation, exact body compiler/adapter and owner-private cleanup/recovery after +unknown; this unintegrated primitive proves none of those or full contract/native +acceptance. Inputs/prior reviews are preserved; no privileged/native action occurred. + + +2026-10-11 T11 journal v3 correction preparation (same trial): frozen manifest +`905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d` +verified against every file. Strict after_call integer0..63 and64hex string digest +validation now precedes SQLite confirmation; False,0.0 or text'0' cannot clear +pending external outcome.15 supplied tests plus5 independent regressions pass, +including realfork abrupt exit after durable intent and privatefile checks. +This existing completed ownerT11 refinement precedes the formal corrected-source +review. Prior v2 refusal is retained; no extra success/authority trial is counted. +Acceptance is only unintegrated journal source. Actual caller/PDP/consume validation, +independently compiled body/ordinal plan, restricted adapter, owner-private unknown +cleanup recovery and native/whole-contract adoption remain live RPF35-T12 gates. + + +2026-10-11 T13 node-route source preparation refinement (same trial): exact +successor manifest `23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035` +verified against all entries. Platform Service openbao-ui-gateway8080 and its +nginx /v1 proxy agree with the proposed bounded founder-held node port-forward; +workstation tunnel/DNS assumptions are not reused as node evidence.54 supplied +lifecycle/route checks plus6 independent public-health/abort checks pass, offline. +Initial execute/recovery health pin and repeated pre-create check fail before +native/Secret effects; public-preflight reads neither stdin nor Kubernetes. +Completed ownT13 preparation precedes this fresh exact source review, not reuse +of v5 acknowledgment. Main execute currently reads private stdin before execute's +health gate; the packet's pre-token-input phrase is not accepted. Private producer +handoff must preserve actual ordering or move the health gate before credential +input when implemented. Public cluster digest detects drift, not authenticated +estate identity. No route was opened or observed; no source packet authenticates +a founder approval. Native role/plugin version and raw/effective expiration, +clock-skew and not-before leeways require actual owner observation/semantic proof. +Issuer readiness_state/Argo ownership is not established by the inspected source; +unmapped means production-tier. If adopted/production-approved, temporary direct +CAS requires an explicit reviewed one-use maintenance exception and close-down +entry, plus reconciliation, before native go. No helper/source acknowledgment +waives that gate. Private token producer/callback/client/custody admission and +actual native negative/revoke/restoration/cleanup remain prerequisites. + + +2026-10-11 T13 v7 node-route preparation refinement (same trial): exact frozen +manifest `90aabec336008d7d51e37c04b5ff96ba8ed6630821cca1a4c333d803367247f7` +and all entries verified.58 supplied lifecycle/route checks plus9 independent +checks pass offline. Actual main now verifies source/public health before private +stdin; execute preserves the original wall/monotonic window rather than renewing +it. Actual child-process partial-pipe counterexample shows unbounded stdin.read +remains blocked beyond a synthetic20ms original window (still alive after100ms +without EOF). No credential/native/provider access is involved. Before private +producer admission, require byte-capped, deadline-bounded JSON input and EOF within +the original window, with fail-closed fixed receipt and no protected effects. +This completed ownT13 preparation precedes formal v7 source changes-requested +review. Retain v6 qualified health-gate agreement and all prior reviews; neither +v7 health ordering nor any source acknowledgment establishes custody completion, +actual route/plugin/leeway/readiness/Argo identity or founder/runtime authority. +Native and private-producer gates remain open; no owner checkout write occurred. + + +2026-10-11 T13 v8 bounded-input correction preparation (same trial): exact +frozen manifest `316fd6005cc4cb7fe14ea69a5fd408aed13e6122afef60afd13d97952b27cf4a` +and all entry hashes verified.65 supplied tests plus12 fresh independent checks +pass offline, including a standard buffered stdin pipe with complete JSON/noEOF +interrupted within original20ms window and restored SIGALRM state; exact64KiB +JSON/EOF accepted and extra byte refused, UTF8 token bytecap enforced, original +wall deadline clips longer monotonic budget. Original preinput window is retained. +Completed ownT13 preparation precedes fresh exact source review; v7 refusal and +v6 qualified agreement/prior reviews retained. This accepts child bounded-input +source only. No parent-ready handshake exists: producer must not eagerly pipe +private inputs, and producer/session/window readiness protocol remains an +unimplemented admission gate. No custody/native completion, sourcepacket approval +authentication, route/plugin/leeway/readiness/Argo observation or inherited grant. +Native prerequisites and producer handoff remain open; no owner checkout changed. + + +2026-10-11 T11 journal v4 canonical-format preparation refinement (same trial): +exact frozen manifest `22c6d225d393b994ab7b44a43904ced1b6d7f74e0e2bebf71ffe99f87191ef4c` +and entry hashes verified. Actual access-engine pkg/api/canonical.go RequestDigest/ +CanonicalDigest, Approval binding.py and Secrets authorization/approval_consume +all use sha256:<64 lowercase hex> request digests. V4 now preserves this exact +request value without prefix stripping; plan/call/evidence content hashes remain +explicit bare64hex.15 supplied checks plus15 fresh independent checks pass, +including malformed prefix/bare/uppercase/trailing whitespace refusal before +reservation, exact persistent value/reopen/mismatch replay, private-file mode, +real child crash after pending intent, ill-typed confirmations and pending-unknown +refusal. Completed ownT11 preparation precedes formal v4 source review; prior v2 +refusal/v3 approval and T13 v7 refusal/v8 source acknowledgment retained. +Acceptance is unintegrated primitive source only; no data migration/native use +of v3 journal has occurred. RPF35-T12 caller/PDP/consume validation, independent +owner plan compiler/restricted adapter, private runtime custody, bounded execution +and owner-private unknown cleanup recovery remain open. No checkout/native writes. + + +2026-10-11 T13 paired ready-child/launcher preparation refinement (same trial): +exact NetV9 manifest `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +and KeyproducerV2 `55a8e794af983ca2202e7a0054d0415a120d2c95018fb03fdb5f28313a109d58` +verified against all entries.74 Net checks plus31 Key checks and10 independent +checks pass offline including a truthful-unknown counterexample: adapter uncertain +private delivery with confirmed=false is copied into launcher receipt, but +consumer_outcome_unknown incorrectly remains false after local SSH teardown. +Complete bytes may have reached remote child before adapter timeout/EOF; local +terminate does not establish remote no-effects. Require sticky propagation of +uncertain delivery into consumer outcome before early return, retain unknown +unless independently established native outcome/recovery. Bad markers/source +pins/injection reject before private reads; extra marker authority/lines reject; +prohibited child output never forwards. Child-ready synchronization is not +authentication/approval. Proposed founder directSSH profile is incompatible with +warden quiet-output lane and not admitted here. Completed ownT13 preparation +precedes formal paired source review; preserve v7 refusal/v8 acknowledgment and +journal histories. No transport grant, coding-agent/private custody admission, +live SSH, credential/native action or owner checkout write. All native role/plugin/ +leeway/route/issuer readiness/Argo/maintenanceexception gates remain prerequisites. + + +2026-10-11 T13 paired producerV4 correction preparation (same trial): exact +producer manifest `d6f641dc1e4aae7d36658d4199d89af14d2fd7a4bd4e526856eb340234f2d33e` +and unchanged NetV9 `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +entry hashes verified.74 Net tests,40 producer checks,9 actual local fakeSSH/ +realwrapper/child synthetic roundtrip regressions and12 fresh Platform checks +pass (135 total). V2 deliveryunknown now remains sticky consumerunknown with +completion=false after earlyreturn/localteardown. V3 Net FIFO acquisition finding +and originalbudgetreset are corrected: actualCLI starts original5s timer before +regular/nofollow/bytebounded contract acquisition, each later preparation phase +clips remaining time. ActualCLI FIFO refuses promptly; expired original budget +never validates/spawns/reads private files. Completed ownT13 preparation precedes +formal corrected pair source agreement. Preserve V2 Platform refusal, Key old +exactV2 acknowledgment and NetV3 refusal; no old acknowledgment repinned. +Agreement is only reviewed source synchronization/launcher behavior, not admission. +Founder authenticated SSH host/profile/channel/runtime pins, exclusive sameUID +file custody and explicit tmpfs file allowance/cleanup, verified human and +coding-agent producer/client/source, native role/plugin/leeway/route/issuer +readiness/Argo/maintenanceexception, refusal/revoke/restoration/readback and +unknown owner recovery remain prerequisites. Warden quietlane cannot carry ready +controlstdout; no transport/custody/native grant. No owner checkout/liveSSH/native. + + +2026-10-11 RPF35-T12 source implementation progress: durable journal source v4 +was independently accepted/committed; owner-derived typed plan compiler component +v2 is prepared at immutable manifest +`41cda74ab32384c789ea8a760475671aadad4e5121335c8f60567ff53d66665b` +with40 offline tests. Completed own bounded source-preparation ADHOCT02 anchor +was persisted at7adbcb4 before the qualified Platform contract/readiness receipt. +T12 progresses for actual source implementation underway, not native acceptance +or full descriptor/authority readiness. The compiler derives local CCR/HCL/role +bodies, matches actual independently pinned Secrets catalogue and revalidates +source/body before fixed calls; no body/target chosen by service is dispatched. +Independent technical integration review and exact full ExecutionContract/owner +grant/baseline/estate/deadline matching, initiating human/User/Tenant PIP/transport +representation/service identity, served PDP/claim/consume correspondence, journal +call dispatch/restricted adapter, native token TTL/uses/custody/revoke/cleanup and +owner-private unknown recovery remain unimplemented integration/native gates. +Actual CCR42 has no eligible approved pilot/catalogue; no source metadata is +invented. T02 and original negative/capability/native evidence remain unchanged; +T11/T13 history retained, no defaultflip/nativego or SecretsT06 closure follows. + + +2026-10-13 T12 source correction: the compiler hashed the catalogue sources but +used cached Python modules with matching paths, which did not establish executing +those exact bytes. A failing regression reproduced the substitution. Catalogue, +package and dependencies now execute from the verified snapshot in temporary +private modules; ambient modules remain untouched and cleanup runs on refusal. +45 compiler plus 15 journal tests pass. The v2 source review remains historical; +this change needs its own integration review. T12 retains all existing full +contract, identity/consume, dispatch, custody and native acceptance requirements. +RPF-IN-0012 remains open for the independent contract/wrapped-delivery return; +this code correction does not authorize either operation. + +2026-10-16 T12 source preparation (isolated owner checkout; not owner delivery): +added durable precommitted cleanup obligations and separate outcome evidence to +the existing Journal, plus a fixed three-method owner cleanup driver. Same live +postconsume admission can clean after a business timeout/failed/unknown outcome; +cleanup closes business dispatch and cannot replay or restore admission after a +crash. Empty obligations no longer produce cleanup-confirmed. Real SQLite +multiprocess races and abrupt process death before/after a separately durable +synthetic effect verify refusal on reopen. Current compiler/journal/cleanup suite: +73 passed, local source/fixture only. Details: docs/task-execution-cleanup.md. +No native adapter or production mediator exists; full grant/request/cleanup binding, +authenticated consume/identity, ephemeral token issuance, deadline/use checks, +native effect/revoke/absence, audit and protected recovery remain prerequisites. +T12 remains progress. No CCR38 default/entitlement or live grant was changed. + +2026-10-16 T12 second source package: Compiler Plans now bind deterministic cleanup +commitments and can bind the complete independently installed engine execution +descriptor. A fixed disposable-loopback native adapter actually materializes exact +per-operation metadata ACL/task token, executes six source-derived metadata calls, +and verifies self-revocation/accessor invalidation and policy retirement. Each +cleanup request has its own durable intent. Native fault tests cover lost response +after real write and policy deletion while task revoke fails. All initiating +identity/approval/consume/grant/state/source admission in this fixture is synthetic; +no production authority or complete native owner acceptance is claimed. Exact +remaining owner schema/admission and mediator work: docs/task-execution-native-fixture.md. +T12 stays progress; no live grant, credential/default change or owner sync performed. + +2026-10-16 T12 third source package: implemented proposed task-execution-grant +immutable projection and exact compiler/native-fixture integration through the +existing descriptor grant ID/SHA fields. Only typed review.comments/evidence.events +are excluded; separate append-only checks reject removal/rewrite/reordering and +unknown guessed evidence exclusions refuse. Owner-pinned grant bytes and validator +source must match independently reconstructed descriptor/source/cleanup/ACL/token +bodies before a native fixture can materialize. Proposed source records gain no +execution authority; no real grant, policy or legacy applier registration added. +Details and remaining production gates: docs/task-execution-grant-projection.md. +T12 remains progress; no owner sync or production effect performed by this package. + +2026-10-16 T12 fourth source package: connected the Secrets-owned strict task +handoff to actual Approval ExecutionConfirmationClient independent GET before +consume-confirmed/native fixture work. Platform accepts no supplied authorization +boolean/object/callback and preserves its exact owner descriptor/grant/Plan join. +Durable CAS/GET intents precede native ordinals through the repaired journal +prefix API. Actual source-server fixture uses signed Access/enforced synthetic +TokenReview, real Approval WSGI/SQLite with distinct synthetic human/service +identities, actual strict Secrets signature/CAS validation and disposable native +OpenBao. Untouched actual task policy remains signed DENY; separately named +synthetic fixture policy is never production admission. Read-scope denial after +CAS records consumed/unknown with zero native effects. Exact dependency/source +hashes, tests and remaining gates are retained with the source package and in +docs/task-execution-mediator-seam.md. No real grant/custody, policy default, owner +sync or native production acceptance is performed; T12 stays progress. + +2026-10-16 T12 recovery successor source preparation: optional independently +installed fixture custody durably retains operation-bound private accessors and +issuance checkpoints. Fresh cleanup-only owner permits can reconcile after actual +executor process death using fixed revoke/readback and policy delete/readback, +without restoring business/consume admission. Separate durable attempt evidence +retains original unknown outcomes. Lost token-create response remains unresolved +when no accessor was committed. Source-only process-loss fixtures are not native +production custody or recovery-role admission; T12 remains progress. + +2026-10-16 T12 recovery R2 source refinement retains R1's overbroad 404 failure: +policy cleanup now requires exact native empty-errors absence before/after delete; +HCL uses only documented single optional terminal LF normalization. Private +capsules are owner-key HMAC authenticated, strict nested schemas/ordered cleanup +commitments reject damage, and journal history prevents stale prepared capsules +from hiding issuance. Fixture process-loss source proof remains separate from +unadmitted production custody, integrity-key storage and recovery-role scope. + +2026-10-16 T12 independently reviewable budget/source slice: bound native HTTP +header/body/close, compiler work and cleanup through fixed owner main-thread +absolute budgets, with actual task expiry narrowing global authority. Actual v2 +mediator now verifies each independently installed source_bundle byte hash before +authorization/effects. No deadline/TTL extension, remint or generic service added. +Retained registry actual-provider proof still refuses Approval correspondence +before CAS/native; normalized pre-approval + precise immediate CAS whole-stack +positive remains live owner follow-up under CUST-WP-0080. T12 stays progress. + +2026-10-16 T12 actual v2 successor source proof: retained registry signed DENY +normalization from the real Secrets prepare_task_approval builder precedes actual +Approval issue/human approval. Actual Access v2 then signs ALLOW; strict Secrets +CAS and independent confirmation GET precede six disposable native calls, exact +readback and confirmed token/policy cleanup. Approval precision source permits +immediate CAS without sleeps/backdating. The 60-second immutable deadline, +30-second backend TTL, 120-second synthetic observation and existing cleanup +reserve remain bound; issued credential expiry narrows business time. Source, +caller, revoke, source-reader, registry drift and expiry refusals cause no native +effects; revoke between ALLOW/CAS retains unknown without business dispatch. +This owner fixture uses separately installed synthetic identity/key/trust and +loopback OpenBao, grants no production authority and keeps T12 progress. Prior +failed temporal/normalization proofs remain retained. + +2026-10-16 T12 signer custody R3 source preparation rebases the proposal to +integrated Access919ce25 and preserves current workplan state. Added protected +in-memory Ed25519 CAS/readback primitive with durable closed metadata receipts +and fixed disposable-only owner adapter. Actual synthetic OpenBao bootstrap, +rotation, conflict/unknown/readback/receipt/private-output and admission failures +are tested. Production direct entry refuses: exact CCR/founder scope, protected +executor/fencing/receipt custody, independent consumer public admission, migration +debt and native deployment prerequisites remain open. No live key/grant or CCR +admission; RPF-WP-0035-T12 remains progress. + +R3 source metadata correction aligns proposal IDs across JSON/docs/Secret +annotation and documents existing base64url-ASCII public fingerprint hashing. +Frozen R2 source/evidence is preserved; no writer behavior or admission changes. + +2026-10-16 T12 native signer preparation: proposed CCR-2026-0050 and generated +read-only HCL pass real schema checks; current proposed status/unconfirmed claims +keep apply refused. Native candidate uses existing external-secrets-* role +convention with dedicated SA unchanged and projected private field only. Exact +attended CAS0/metadata/fence/receipt/forward-recovery action plan is separate from +read-grant authority; production adapter implementation/independent tests and +founder plus distinct owner reviews remain necessary. Access observed zero PVCs; +new outbox storage/retention/runtime bounds remain separate Access/cluster scope. +No live credentials, grants, roles, key or deployment changed. T12 stays progress. + +2026-10-16 T12 native signer adapter source: silent fixed-scope attended child +checks exact independent admission/source/CCR/image/caller/trust/identity inputs, +actual backend/reader role/policy, signer fence and private exclusive receipt +custody before fixed metadata/CAS0 effects. Separate fresh read-only recovery +reconciles real process loss after native write without remint/retry/new effects. +Disposable tests exercise actual KV while owner reviews/identity/fence facts are +explicitly synthetic. Current warden plan dispatch selects structure-survey, not +OIDC admin login; mismatch remains a live refusal. Canonical proposed CCR, native +owner/founder approval and Access/cluster/outbox/PVC gates stay open; no live +key, credential read, grant, role, storage or deployment action performed. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/r1-to-r2.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/r1-to-r2.patch new file mode 100644 index 00000000..64a5aaa0 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-adapter-r2/r1-to-r2.patch @@ -0,0 +1,331 @@ +--- a/scripts/flex_auth_signer_native.py ++++ b/scripts/flex_auth_signer_native.py +@@ -75,7 +75,7 @@ + def validate_admission(value): + fields={'schema','action','operation_id','kid','expires_at','founder_entity_id','ccr_sha256','source_bundle','bindings', + 'producer_image','caller_binding','deployment_projection_sha256','authority','routing','owner_reviews', +- 'exclusive_window_sha256','consumer_trust_sha256','original_receipt_sha256'} ++ 'exclusive_window_sha256','consumer_trust_sha256','original_receipt_sha256','original_execution'} + require(type(value) is dict and set(value)==fields,'exact admission schema required') + require(value['schema']=='railiance-platform.signer-native-admission.v1' and value['action'] in {'bootstrap','recover'},'native admission action refused') + require(type(value['operation_id']) is str and re.fullmatch(r'[A-Za-z0-9_-]{1,80}',value['operation_id']) and +@@ -104,6 +104,15 @@ + and value['bindings']['executed_revision_sha256']==digest(encoded(value['source_bundle'])),'immutable lifecycle/image/trust/source mismatch') + require((value['action']=='bootstrap' and value['original_receipt_sha256'] is None) or + (value['action']=='recover' and is_digest(value['original_receipt_sha256'])),'separate recovery disposition required') ++ original=value['original_execution'] ++ if value['action']=='bootstrap':require(original is None,'bootstrap cannot import execution lineage') ++ else: ++ require(type(original) is dict and set(original)=={'bindings','writer_sha256','source_ccr_sha256'} and ++ is_digest(original['writer_sha256']) and is_digest(original['source_ccr_sha256']) and ++ type(original['bindings']) is dict and set(original['bindings'])==BINDINGS and ++ all(is_digest(x) for x in original['bindings'].values()),'independently reviewed original execution lineage required') ++ require(all(original['bindings'][key]==value['bindings'][key] for key in BINDINGS-{'proposal_sha256','executed_revision_sha256'}), ++ 'recovery cannot change original image/deployment/policy/trust authority') + try:expires=datetime.fromisoformat(value['expires_at'].replace('Z','+00:00'));remaining=(expires-datetime.now(timezone.utc)).total_seconds() + except Exception:raise Refused('invalid authority expiry') from None + require(expires.utcoffset().total_seconds()==0 and 55 ++ old=deepcopy(c) ++ old['owner_reviews']['cluster-gitops-owner']=old['owner_reviews'].pop('cluster-runtime-storage-owner') ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(old) ++ missing=deepcopy(c);missing['owner_reviews'].pop('cluster-runtime-storage-owner') ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(missing) ++ extra=deepcopy(c);extra['owner_reviews']['railiance-enablement-owner']=next(iter(extra['owner_reviews'].values())) ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(extra) ++ assert io.calls==[] diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/manifest.json new file mode 100644 index 00000000..4e0b601c --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/manifest.json @@ -0,0 +1,33 @@ +{ + "proposal_id": "RPF35-PDP-SIGNER-OWNER-BOUNDARY-20261016-R3", + "base_commit": "a3e8eb64bae110393ba0aeab043de03a92b8421a", + "role_replacement": { + "old": "cluster-gitops-owner", + "new": "cluster-runtime-storage-owner" + }, + "before_sha256": { + "scripts/flex_auth_signer_native.py": "sha256:5a3b3b33bcad45ef2939413bfd3db76e5ee70e3b815d0d64af53147851aa3a0d", + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": "sha256:72fd6e84e866a72f4768dabd66326aebe1fdd00013b2314de961ca72a632679f", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": "sha256:5f8c37a7d9781884bf06050be80ca192a3b92eab2d20e28f9b304e57e7456844", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md": "sha256:0e185a651fbbef96996c38ff18ce338f4d6c0117c3fb069a43e766816e56d5db", + "tests/test_flex_auth_signer_native.py": "sha256:8a99d1819c54fc20660cd6d16e8b429e2fc9f30cf4cefc90704201a588c825a6" + }, + "files_sha256": { + "scripts/flex_auth_signer_native.py": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f", + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": "sha256:23e4e008144350547c4726ca01e579b583b179b7a767d9406c4c176c1a645343", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": "sha256:1865083d8382da4d987ef33586919a262970776c71b523c8cb027c027b550ece", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md": "sha256:0e2e431dcd2df66e65434ce4060a4d5b52941f50928be80a075e4f972229d3a9", + "tests/test_flex_auth_signer_native.py": "sha256:f74a2316506737966e2ea539799cb477a9cec2718a6679f417478f9972731b3e" + }, + "patch_sha256": "sha256:266a5ac36b291c40e7c8a6d3da9b03169d454fac6c277ebc5f5f1c8faba9b810", + "source_review_role": "railiance-platform-owner", + "disposition": "approve-source-correction-only-pending-independent-review", + "native_authority": false, + "frozen_p1_p2_changed": false, + "lineage": "R3 is a new source revision, not retrospective approval or reinterpretation of original reviews", + "artifact_files_sha256": { + "README.md": "sha256:176e0d75de9adf23804b220b21528a077bfdb8e97edc0fe7e39296b7bb1f50a2", + "validation.json": "sha256:7a6cc839b749f48aaee96eb53d83e9c5c2da5dc392b5e1b735c0bbbd55c9c11e", + "implementation.patch": "sha256:266a5ac36b291c40e7c8a6d3da9b03169d454fac6c277ebc5f5f1c8faba9b810" + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/validation.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/validation.json new file mode 100644 index 00000000..d27e2265 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r3/validation.json @@ -0,0 +1,8 @@ +{ + "command": "python3 -m pytest tests/test_flex_auth_signer_native.py tests/test_flex_auth_signer_native_preparation.py -q", + "result": "45 passed", + "seconds": 33.66, + "git_apply_check": "passed against canonical Platform checkout", + "test_scope": "Disposable native state machine uses synthetic owner approvals/cluster/identity; no native authority inferred", + "new_check": "Correct exact five-role set accepted, conflated/missing/blanket-sixth roles rejected before IO" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/README.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/README.md new file mode 100644 index 00000000..5e0e1a3d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/README.md @@ -0,0 +1,11 @@ +# Platform owner-boundary source reconciliation R4 + +R4 preserves the frozen R3 artifact and provides a full six-file patch against a3e8eb64 plus a three-file R3 delta (native plan, proposed CCR0050, existing workplan). Native executor and tests are unchanged from R3; no runtime grant or implementation behavior changed. + +The plan now records native adapter implementation/tests at a3e8 rather than claiming implementation remains required. It records published84c78e0/image09a83b successful normal CI402 and source OS-lock/64MiB/startup hardening, while keeping actual mounted-runtime/durability/fence evidence open. It records established canonical local draft package d52/tree d4fb, frozen source2b/current05a; no missing-local-declaration waiver is requested. Remote publication/placement and actual runtime/package join remain open. Proposed CCR risk/activation conditions use the same current facts and retain proposed/unconfirmed state. + +Concurrency distinguishes Access workload/Helm release writers, Platform GitOps Applications/sync-freeze integration, cluster runtime/storage/headroom, and Enablement only for separately proposed actual ArgoCD installation/controller changes. No synthetic combined assent. Native corrected role slot remains cluster-runtime-storage-owner, as R3. + +An appended bounded RPF35-T13 preparation note records this source correction without changing task status, historical reviews/outcomes or T12 native gates. Independent current CCR/plan/source and native owner/founder admissions remain mandatory. No secrets/login/native fence/custody or remote publication performed. + +Validation: exact CCR schema passes, status proposed and bound claims false. Full patch applies cleanly to current canonical Platform. R3's45tests remain the execution-source evidence; unchanged source/test hashes are pinned, no unnecessary full retest for metadata-only delta. Root may independently test the full corrected tree. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/manifest.json new file mode 100644 index 00000000..5e72bcd3 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/manifest.json @@ -0,0 +1,34 @@ +{ + "proposal_id": "RPF35-PDP-SIGNER-OWNER-BOUNDARY-20261016-R4", + "base_commit": "a3e8eb64bae110393ba0aeab043de03a92b8421a", + "predecessor_r3_manifest_sha256": "sha256:6d1f5d81921cc872073b20554e07a94fdaa3b5b5b9f1509c260c3c58cb92cf93", + "before_sha256": { + "scripts/flex_auth_signer_native.py": "sha256:5a3b3b33bcad45ef2939413bfd3db76e5ee70e3b815d0d64af53147851aa3a0d", + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": "sha256:72fd6e84e866a72f4768dabd66326aebe1fdd00013b2314de961ca72a632679f", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": "sha256:5f8c37a7d9781884bf06050be80ca192a3b92eab2d20e28f9b304e57e7456844", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md": "sha256:0e185a651fbbef96996c38ff18ce338f4d6c0117c3fb069a43e766816e56d5db", + "tests/test_flex_auth_signer_native.py": "sha256:8a99d1819c54fc20660cd6d16e8b429e2fc9f30cf4cefc90704201a588c825a6", + "workplans/RPF-WP-0035-credential-lane-implementation.md": "sha256:180731a9ac1a2b4ccb4458c6cee54151f43e63008e2c35a33db7f01ea9e9d768" + }, + "files_sha256": { + "scripts/flex_auth_signer_native.py": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f", + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": "sha256:1dfcdf206d2bdfcb9b7a21c132e7e3902ad98659dd023bb3993b0825d903c1c7", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": "sha256:d7b3322d105cdde10ab3003b81b34b8356fdfa1ac08858f6464984ce1c253402", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md": "sha256:0e2e431dcd2df66e65434ce4060a4d5b52941f50928be80a075e4f972229d3a9", + "tests/test_flex_auth_signer_native.py": "sha256:f74a2316506737966e2ea539799cb477a9cec2718a6679f417478f9972731b3e", + "workplans/RPF-WP-0035-credential-lane-implementation.md": "sha256:20451474d84be986f7be1e2ff8c48e3a754e981718949f0e9d771081ae15d25b" + }, + "full_patch_sha256": "sha256:25bbff23421121836625e0081213fa2d1535e69a6123fbac21b62163b94293db", + "delta_patch_sha256": "sha256:022281a1db4d1cbcad0a1485b57f4ddc1fbca3b9503efe6ef266912f592d2569", + "disposition": "Platform source/metadata preparation only; no native grant", + "frozen_prior_artifacts_changed": false, + "tests_source_unchanged_from_r3": true, + "artifact_files_sha256": { + "README.md": "sha256:72af2f502890d9f23d82cd3135aaa21346e6ab7d961d5e669bf0183e4ec55c41", + "implementation-r4-full.patch": "sha256:25bbff23421121836625e0081213fa2d1535e69a6123fbac21b62163b94293db", + "r3-ccr.yaml": "sha256:23e4e008144350547c4726ca01e579b583b179b7a767d9406c4c176c1a645343", + "r3-plan.json": "sha256:1865083d8382da4d987ef33586919a262970776c71b523c8cb027c027b550ece", + "r3-to-r4.patch": "sha256:022281a1db4d1cbcad0a1485b57f4ddc1fbca3b9503efe6ef266912f592d2569", + "validation.json": "sha256:9e42fb14c30f959e817ec5b185cfdc79b16dd712639c52dc0899874e9570a08a" + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-ccr.yaml b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-ccr.yaml new file mode 100644 index 00000000..7abaca5c --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-ccr.yaml @@ -0,0 +1,128 @@ +id: CCR-2026-0050 +kind: credential-change-request +schema_version: 1 +request_type: workload-kv-read +title: Retained flex-auth lifecycle PDP Ed25519 seed ESO read lane +status: proposed +created: '2026-10-16' +updated: '2026-10-16' +requester: + agent: railiance-platform + reason: CUST-WP-0080 / RPF-WP-0035-T12 / FLEX-WP-0024-T06 source proposal. Exact + new custody/read scope requires founder review; no approval or native binding + is inferred. +review: + required: true + required_approvers: + - founder + - railiance-platform-owner + - access-engine-owner + - secrets-engine-owner + - cluster-runtime-storage-owner + comments: [] +target: + domain: infotech + tenant: platform + workload: flex-auth-secrets-engine + environment: production + purpose: Deliver the Ed25519 seed only to the retained lifecycle PDP startup file. + No taskpilot enablement, caller policy changes or private consumer trust discovery. +openbao: + mount: platform + kv_path: platform/workloads/flex-auth/envelope-signing + fields: + - ED25519_PRIVATE_KEY + metadata_read: false + token_self_lifecycle: true + policy_name: workload-kv-read-flex-auth-envelope-signing + policy_file: openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl + auth: + method: kubernetes + mount: kubernetes + role: external-secrets-flex-auth-envelope-signing + bound_claims: + service_account_names: + - flex-auth-envelope-signing-eso + service_account_namespaces: + - flex-auth + bound_claims_confirmed: false + policies: + - workload-kv-read-flex-auth-envelope-signing + ttl: 15m + audience: openbao + token_max_ttl: 15m + token_explicit_max_ttl: 15m + token_no_default_policy: true +access_frontdoor: + type: external-secrets + catalog_id: flex-auth-decision-envelope-signing-key + selector: Retained flex-auth/flex-auth-secrets-engine signer only + readiness: pending-review + resolvable: false +delivery: + surface: external-secrets + target: Namespace flex-auth; dedicated SA flex-auth-envelope-signing-eso; SecretStore + openbao-flex-auth-envelope-signing; ExternalSecret/Secret flex-auth-secrets-engine-envelope-signing; + seed property only -> startup file /var/run/secrets/decision-envelope-signing/seed0440, + readOnly uid/gid/fsGroup65532; no envFrom + bootstrap_command: Attended writer is a distinct exact-source action proposal in + docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json; this + read CCR authorizes neither seed writes nor any execution by itself. +risk: + classification: high + notes: + - Possession of seed can forge lifecycle PDP envelopes; independent consumer public + trust admission and fixed policy pins remain required. + - 'KV read is document-granular: dedicated ESO identity can read all three fields; + only private field is projected. Signer and Secrets consumer have no KV read role.' + - No parent/list/metadata/write/delete capability on ESO role. No token/Secret read + or ExternalSecret mutation granted to signer/consumer. + - Dedicated role is new scope; founder approval required. No workload rapp tuple + invented; absent managed package declaration remains explicit migration debt. + - Controlled outage fence stops every signer pod and disables autoscaling before + creation/rotation. Recreate single writer and retained PVC remain Access-owned + review gates. + - fields declares only projected ED25519_PRIVATE_KEY. The same KV document also + has public key/kid, and OpenBao data-read is not field-filtered; do not claim + field-level authorization. +verification: + positive: + - Exact SA/namespace/audience login; native exact data read; ESO Ready/SecretSynced; + safe metadata resourceVersion and admitted KV version correspondence. + - All retained signer replicas restart with admitted kid/source/image and seed/public + correspondence; signed non-effect lifecycle allow/deny with durable originals + and independent consumer signature verification. + negative: + - Wrong SA/namespace/audience login refused; sibling/list/metadata/write/delete + denied; signer/consumer TokenRequest and Secret/ExternalSecret mutation denied. + - Unknown/old kid, wrong policy, tamper, expired/unsigned envelope, wrong caller + and missing seed refuse; no taskpilot activation. + - Receipt write failure/lost backend response retained unknown; no blind retry/remint; + stale CAS cannot overwrite version. + activation_conditions: + - All five required approvers independently dispose the exact CCR and native writer/fence + proposal; founder exact new custody scope approved. + - Current retained identity919ce25, immutable published producer image and explicit + new flex-auth-secrets-engine-outbox PVC1Gi/local-path, retention/reclaim and bounded-runtime + plan reviewed by Access; missing managed package migration debt explicitly accepted + for this retained workload only. + - Exact native bound claims verified without printing JWT/Secret; read grant policy + and role native readback match source. + - Protected child source pinned, silent attended OIDC context verified, target cluster/backend + pinned, fence verified and durable receipt custody installed. + - Consumer independently admits owner-authenticated public receipt and exact policy/image/trust + pins before protected acceptance. + evidence: [] +lifecycle: + deactivate: Fence all retained signer processes, stop consumers, disable delivery + role/ESO and online trust; retain private KV and audit receipts under explicit + owner retention until reviewed destruction. + rotate: Pre-admit successor public receipt offline; fence consumers/all signer replicas/no + HPA; CAS exact version with new in-memory seed; wait exact ESO version, restart + single writer, verify native allow/deny and old-key refusal before reopening. + compromised: Immediately remove old online trust and stop all signer processes; + forward-only CAS recovery with independently approved successor. Never restore + compromised seed; archive historical public keys for offline audit only. +state_hub: + workplan_id: RPF-WP-0035 + task_id: RPF-WP-0035-T12 diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-plan.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-plan.json new file mode 100644 index 00000000..7c51e98d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/r3-plan.json @@ -0,0 +1,158 @@ +{ + "schema": "railiance-platform.signer-native-action-proposal.v1", + "proposal_id": "RPF35-PDP-SIGNER-NATIVE-20261016-R1", + "status": "prepared-unapproved", + "read_ccr": "CCR-2026-0050", + "proposal_scope": "attended bootstrap of retained lifecycle PDP seed; no taskpilot enablement, rotation requires a new exact-version action revision", + "actor": "founder attended OIDC via warden openbao-platform-admin-login; reviewed silent Platform custody child", + "executor_ownership": "railiance-platform; founder executes exact child; agent receives closed metadata only", + "abort_owner": "founder; Platform preserves unknown custody/evidence, Access keeps signer/consumers fenced", + "target": { + "cluster": "primary/railiance01", + "kube_system_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786", + "openbao_cluster_id": "fd28df5d-98ec-57dd-42ec-9b3e4f4e53bf", + "openbao_origin": "http://127.0.0.1:18200", + "namespace": "flex-auth", + "deployment": "flex-auth-secrets-engine", + "signer_sa": "flex-auth-secrets-engine" + }, + "credential_route": "openbao-platform-admin-login; flex-auth-decision-envelope-signing-key remains draft/nonresolvable; route is not a seed vending service", + "bootstrap": { + "action": "CAS0 fresh in-memory Ed25519 seed", + "kid": "flex-auth-lifecycle-20261016-r1", + "expected_version": 0, + "data_path": "platform/data/workloads/flex-auth/envelope-signing", + "document_fields": [ + "ED25519_PRIVATE_KEY", + "ED25519_PUBLIC_KEY", + "kid" + ], + "metadata_path": "platform/metadata/workloads/flex-auth/envelope-signing", + "metadata_contract": { + "cas_required": true, + "max_versions": 2, + "delete_version_after": "0s" + }, + "allowed_native_methods": [ + { + "method": "POST", + "path": "platform/metadata/workloads/flex-auth/envelope-signing", + "purpose": "CAS-required/version-retention configuration after absence/no-drift validation" + }, + { + "method": "GET", + "path": "platform/metadata/workloads/flex-auth/envelope-signing", + "purpose": "exact metadata readback, no private value output" + }, + { + "method": "POST", + "path": "platform/data/workloads/flex-auth/envelope-signing", + "purpose": "single CAS0 seed document write" + }, + { + "method": "GET", + "path": "platform/data/workloads/flex-auth/envelope-signing?version=1", + "purpose": "exact private readback in custody, closed public receipt only" + } + ], + "source_primitive_sha256": "sha256:f169ad12f90d729b647085c3bed2c0d8d005db23a2341b6d3d5f1793bcfd110c", + "historical_source_primitive_sha256": "sha256:8ed281a49c1f1cdb23772efe3593e75c62572a12b8d7a6a4c574f27b38722e75", + "source_lineage_rule": "source_primitive_sha256 must equal current admitted source_bundle[scripts/flex_auth_signer_custody.py] and exact writer receipt; historical_source_primitive_sha256 is non-authoritative R1 evidence only" + }, + "fencing": { + "before_key_generation": [ + "Verify cluster/backend IDs, exact current source/CCR and founder disposition hashes.", + "Read exact deployment/ReplicaSets/pods by ownerReference and SA; refuse a second workload/pod using signer SA or selecting signer Secret.", + "Access stops protected consumers and scales retained deployment0 through its reviewed release path; this child does not mutate replicas.", + "Verify deployment spec replicas0, observed generation caught up, no live or terminating owned ReplicaSet/pods, no matching signer-SA pods and no HPA targeting deployment.", + "Reject a differing/previously existing KV entry at bootstrap. Hold exclusive owner action receipt lock and recheck fence immediately before CAS." + ], + "after_cas": "Keep consumers/signer stopped until independent public admission and exact ESO/readback/source/image verification. Recreate1 is Access-owned; any drift or uncertain outcome keeps fence closed. Access reports current outbox lacks OS process lock, byte ceiling and bounded startup/compaction; Recreate1 alone is not bounded durable acceptance. Keep protected acceptance closed until reviewed source hardening or explicit bounded attended fixture disposition.", + "concurrency": "Single attended owner window/exclusive receipt; GitOps/Helm autosync/other writers must be paused by Access/cluster owner under distinct reviewed action. Plan is not a Kubernetes atomic fence or same-UID isolation." + }, + "protected_adapter": { + "state": "implementation/independent tests still required before executable approval; fixture code must never be promoted by removing its dev-process check", + "reuse": [ + "scripts/state_hub_preflight_lane.py attended silent child/cluster/platform-admin/fencing patterns", + "scripts/flex_auth_signer_custody.py protected Ed25519 CAS/readback and receipt state machine", + "scripts/task_execution_native_fixture.py absolute main-thread2s I/O budget", + "scripts/task_execution_recovery.py strict bounded JSON/no-follow/private custody patterns" + ], + "requirements": [ + "New fixed native adapter consumes exact approved CCR/source/native-action digest; cannot accept arbitrary URL/path/command/payload/seed.", + "Read OIDC token only within warden child from attended context; require platform-admin and reject root; never print/store bearer. No credential comes back to agent.", + "Pin exact kube-system/OpenBao cluster IDs before private calls, refuse ambient address override; enforce2s absolute reads and1MiB cap; no redirect/shell/tracing.", + "Verify metadata absence/exact admitted values before CAS-required change; any differing existing object refuses. Exact response contracts and duplicate/nonfinite JSON rejection.", + "Private seed is generated once, never imported or persisted outside OpenBao; no subprocess argv/env seed; readback compares exact version/fields and derived public correspondence.", + "Receipt intent is durable before native effect; final success requires exact KV/metadata correspondence and receipt fsync. Process loss/error remains unknown without remint/retry." + ] + }, + "receipts": { + "directory": "/home/worsch/.local/state/railiance-platform/flex-auth-envelope-signing", + "mode_directory": "0700", + "mode_file": "0600", + "native_execution_location": "founder workstation inside reviewed warden child; no agent-owned shared /tmp custody", + "basename": "RPF35-PDP-SIGNER-NATIVE-20261016-R1.json", + "maximum_bytes": 65536, + "atomic": "exclusive initial receipt, fsync-before-effect, atomic replacement and directory fsync, no-follow/owner/mode/nlink validation", + "public_fields": [ + "proposal/executed source/CCR/identity/cluster/image/policy/trust digests", + "actor/time", + "closed phase/status", + "exact KV path/version/kid", + "public key and explicitly encoded fingerprint", + "fence/metadata/readback checks", + "rollback or unknown recovery disposition" + ], + "fingerprint": "sha256: lowercase SHA256 of canonical unpadded base64url public-key ASCII, exactly43bytes; independent Secrets owner agreement before admission", + "delivery": "Founder/Platform separately authenticate metadata receipt to Secrets owner; public receipt shape/file does not create consumer trust; raw private receipt directory is not a shared agent intake" + }, + "rollback": { + "before_cas": "Abort without private write; retain receipt/fence; restore prior Access image/values only via reviewed Access action.", + "after_cas_unknown": "Retain unknown and fence; independently attended owner reconciles exact metadata/version/public correspondence. Never rerun CAS0 or restore prior seed automatically.", + "compromise": "Remove online old public key immediately; stop signer, independent new reviewed forward-only action; old private seed never restored." + }, + "requested_scope": { + "read_lane": "Exact CCR0050 policy/role/delivery source only after separate founder review. No extra ESO RBAC permitted.", + "custody_writer": "One attended exact-target CAS0 plus fixed KV metadata setup/readback; no standing writer grant or broker role. This authority is separate from read CCR.", + "kubernetes": "Metadata-only fence observations by child; Access/cluster separately approve stop/restart/delivery manifests and sync control.", + "new_infrastructure_spend_eur": 0, + "new_resources": "Platform creates no storage resources. Access reports zero flex-auth PVCs; Access proposes separate exact new flex-auth-secrets-engine-outbox1Gi local-path Helmkeep. Provisioning, PV reclaim/Delete/WaitForFirstConsumer retention and runtime log bounds require separate founder/cluster/Access review; no durable outbox acceptance yet.", + "risk_bound": "Controlled loss of retained PDP availability during explicit attended fence; seed compromise can forge lifecycle decisions until independent public trust withdrawal; founder must approve this concrete high-risk scope." + }, + "reviews_required": [ + { + "role": "railiance-platform-owner", + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { + "role": "access-engine-owner", + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { + "role": "secrets-engine-owner", + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { + "role": "cluster-runtime-storage-owner", + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { + "role": "founder", + "disposition": "pending exact source/artifact review; no approval recorded" + } + ], + "authority_granted": false, + "candidate_delivery_amendments": { + "supersedes_unadmitted_R3_role": "external-secrets-flex-auth-envelope-signing replaces flex-auth-envelope-signing-eso to fit existing delegated-applier role convention; dedicated SA unchanged", + "read_ccr_field_projection": "Only ED25519_PRIVATE_KEY is delivered; public sibling fields remain visible to dedicated document-reader identity but never become consumer trust discovery", + "projection_source": "docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed", + "managed_declaration": "Missing rapp declaration remains migration debt; retain actual Access919ce25 workload identity, do not create package tuple" + }, + "owner_review_scope": { + "railiance-platform-owner": "OpenBao custody/read lane; existing GitOps Applications and their sync/freeze/controller ownership; covers explicitly identified workload/Helm competing-writer integration with Access, not Access workload semantic ownership.", + "access-engine-owner": "Retained workload/release source, Helm values, candidate image, signer delivery/mount and process/outbox fencing/rollback.", + "cluster-runtime-storage-owner": "railiance-cluster: cluster identity/runtime/storage/headroom, local-path provisioning and actual PV retention; excludes workload and GitOps Application ownership.", + "enablement_condition": "railiance-enablement additional exact review required only if proposed action changes ArgoCD installation/controller configuration; this fixed custody action authorizes no such change. Changed scope needs a separately reviewed exact revision rather than blanket extra reviewer." + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/validation.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/validation.json new file mode 100644 index 00000000..0a5d5ffc --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r4/validation.json @@ -0,0 +1,11 @@ +{ + "scope": "R3-to-R4 metadata/work-record only; execution source/tests unchanged from R3", + "ccr_schema_errors": [], + "ccr_schema_warnings": [ + "OIDC/Kubernetes bound claim is not confirmed; apply is blocked" + ], + "ccr_status": "proposed", + "bound_claims_confirmed": false, + "native_grant": false, + "r3_tests": "45passed; unchanged executor and tests; not rerun for metadata-only delta" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/README.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/README.md new file mode 100644 index 00000000..cd9e7ed7 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/README.md @@ -0,0 +1,7 @@ +# Platform typed metadata repair R5 + +R5 preserves R4 and changes only two metadata postimages. It labels the public source hash as `source Git revision 84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0` and the public image digest as the full typed immutable OCI reference `forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f`. + +Normal pinned Gitleaks8.30.1 scanned all six staged postimage blobs clean using unchanged default rules, empty ignore file and ignore-gitleaks-allow. No suppression/config exception/bypass. Diagnosis retained: Git revision spacing alone still blocked; CCR line108's bare `flex-auth image sha256:` matched generic-api-key because auth and colon preceded the public digest. Full typed OCI reference removes the ambiguous prose and preserves the exact image identity. + +Full six-file patch applies against original a3e8; R4 delta changes only proposed CCR0050 and native plan. Delta git apply --check passes against current canonical R4 staged worktree, which was not mutated. All R4 six-postimage hashes verified before deriving successor. Proposed CCR0050 schema passes and remains proposed/unconfirmed; unrelated baseline CCR0035 validation errors are not changed. Executor/tests/workplan unchanged; R3 45 tests and coordinator independent54 remain applicable source evidence. No native action, custody, deployment, approval or authority upgrade. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/implementation-r5-full.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/implementation-r5-full.patch new file mode 100644 index 00000000..4f33ee72 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/implementation-r5-full.patch @@ -0,0 +1,176 @@ +--- a/scripts/flex_auth_signer_native.py ++++ b/scripts/flex_auth_signer_native.py +@@ -41,7 +41,7 @@ + SECRET='flex-auth-secrets-engine-envelope-signing' + ROLE='external-secrets-flex-auth-envelope-signing' + LIFECYCLE='sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4' +-REVIEWS={'founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-gitops-owner'} ++REVIEWS={'founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-runtime-storage-owner'} + SOURCE_FILES={'scripts/flex_auth_signer_native.py','scripts/flex_auth_signer_custody.py','scripts/task_execution_native_fixture.py','scripts/task_execution_journal.py','scripts/task_execution_recovery.py','scripts/credential-change.py'} + + +--- a/credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml ++++ b/credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml +@@ -18,7 +18,7 @@ + - railiance-platform-owner + - access-engine-owner + - secrets-engine-owner +- - cluster-gitops-owner ++ - cluster-runtime-storage-owner + comments: [] + target: + domain: infotech +@@ -77,8 +77,10 @@ + only private field is projected. Signer and Secrets consumer have no KV read role.' + - No parent/list/metadata/write/delete capability on ESO role. No token/Secret read + or ExternalSecret mutation granted to signer/consumer. +- - Dedicated role is new scope; founder approval required. No workload rapp tuple +- invented; absent managed package declaration remains explicit migration debt. ++ - Dedicated role is new scope; founder approval required. Canonical local draft ++ rapp-flex-auth-secrets-engine declaration committed d52f811ed5ec0be27c9c367e71d476125b3228be ++ (tree d4fbad71bdc8ef870603526ccd1f53195d0322af) resolves locally. Remote publication, ++ placement and actual runtime/package join remain open; no missing-declaration waiver. + - Controlled outage fence stops every signer pod and disables autoscaling before + creation/rotation. Recreate single writer and retained PVC remain Access-owned + review gates. +@@ -102,10 +104,15 @@ + activation_conditions: + - All five required approvers independently dispose the exact CCR and native writer/fence + proposal; founder exact new custody scope approved. +- - Current retained identity919ce25, immutable published producer image and explicit +- new flex-auth-secrets-engine-outbox PVC1Gi/local-path, retention/reclaim and bounded-runtime +- plan reviewed by Access; missing managed package migration debt explicitly accepted +- for this retained workload only. ++ - Exact proposed candidate source Git revision 84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0 and immutable ++ OCI reference forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f ++ published by successful ordinary CI402; source OS-lock/64MiB/startup hardening present. ++ Access reviews exact workload/Helm image/mount/outbox source and actual stopped fence; ++ Platform reviews existing GitOps Application sync/freeze; cluster reviews runtime, ++ headroom and new PVC1Gi/local-path actual PV retention. Local draft package d52 ++ remains source2b/current05a, not candidate84 adoption; remote placement/runtime join ++ and native mounted-runtime acceptance remain open. Enablement only if separately ++ proposed ArgoCD installation/controller configuration changes; none granted here. + - Exact native bound claims verified without printing JWT/Secret; read grant policy + and role native readback match source. + - Protected child source pinned, silent attended OIDC context verified, target cluster/backend +--- a/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json +@@ -67,11 +67,11 @@ + "Verify deployment spec replicas0, observed generation caught up, no live or terminating owned ReplicaSet/pods, no matching signer-SA pods and no HPA targeting deployment.", + "Reject a differing/previously existing KV entry at bootstrap. Hold exclusive owner action receipt lock and recheck fence immediately before CAS." + ], +- "after_cas": "Keep consumers/signer stopped until independent public admission and exact ESO/readback/source/image verification. Recreate1 is Access-owned; any drift or uncertain outcome keeps fence closed. Access reports current outbox lacks OS process lock, byte ceiling and bounded startup/compaction; Recreate1 alone is not bounded durable acceptance. Keep protected acceptance closed until reviewed source hardening or explicit bounded attended fixture disposition.", +- "concurrency": "Single attended owner window/exclusive receipt; GitOps/Helm autosync/other writers must be paused by Access/cluster owner under distinct reviewed action. Plan is not a Kubernetes atomic fence or same-UID isolation." ++ "after_cas": "Keep consumers/signer stopped until independent public admission and exact ESO/readback/source/image verification. Access published source Git revision 84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0 with OS process lock,64MiB capacity/startup bounds and ordinary CI402 success, immutable OCI reference forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f. This supplies reviewed-source/publication evidence, not native mounted-runtime/durable-record acceptance. Access owns Recreate1 activation; actual stopped fence, single writer, PV retention and protected consumer acceptance remain open.", ++ "concurrency": "Single attended owner window/exclusive receipt; Access owns workload/Helm release and freeze of competing workload writers; Platform owns existing GitOps Applications and sync/freeze integration; cluster owner reviews runtime/storage/headroom only. Enablement reviews actual ArgoCD installation/controller configuration changes only, which this action excludes. Actual competing creator IDs/revisions and stopped signer fence need separately reviewed authenticated observations. Plan is not a Kubernetes atomic fence or same-UID isolation." + }, + "protected_adapter": { +- "state": "implementation/independent tests still required before executable approval; fixture code must never be promoted by removing its dev-process check", ++ "state": "Native adapter bootstrap/phase-aware read-only recovery source implemented and tested at published Platform a3e8eb64bae110393ba0aeab043de03a92b8421a; owner-boundary source R3/R4 is a successor exact review revision, not a native execution approval. Exact source/CCR, distinct owner/founder dispositions, entity/window/expiry and actual backend/fence remain mandatory. Fixture dev-process gate remains preserved.", + "reuse": [ + "scripts/state_hub_preflight_lane.py attended silent child/cluster/platform-admin/fencing patterns", + "scripts/flex_auth_signer_custody.py protected Ed25519 CAS/readback and receipt state machine", +@@ -115,9 +115,9 @@ + "requested_scope": { + "read_lane": "Exact CCR0050 policy/role/delivery source only after separate founder review. No extra ESO RBAC permitted.", + "custody_writer": "One attended exact-target CAS0 plus fixed KV metadata setup/readback; no standing writer grant or broker role. This authority is separate from read CCR.", +- "kubernetes": "Metadata-only fence observations by child; Access/cluster separately approve stop/restart/delivery manifests and sync control.", ++ "kubernetes": "Metadata-only fence observations by child; Access separately reviews workload/Helm stop/restart/delivery; Platform owns GitOps Application sync/freeze integration; cluster owner reviews runtime/storage/headroom/PV retention; no ArgoCD installation/controller configuration mutation included.", + "new_infrastructure_spend_eur": 0, +- "new_resources": "Platform creates no storage resources. Access reports zero flex-auth PVCs; Access proposes separate exact new flex-auth-secrets-engine-outbox1Gi local-path Helmkeep. Provisioning, PV reclaim/Delete/WaitForFirstConsumer retention and runtime log bounds require separate founder/cluster/Access review; no durable outbox acceptance yet.", ++ "new_resources": "Platform creates no storage resources. Access proposes separate exact new flex-auth-secrets-engine-outbox1Gi local-path Helmkeep. Actual provisioning/PV identity, StorageClass Delete/WaitForFirstConsumer to reviewed PV Retain disposition and native bounded-runtime evidence remain open. Source lock/64MiB/startup bounds are published in candidate84, not evidence of native mounted-runtime acceptance.", + "risk_bound": "Controlled loss of retained PDP availability during explicit attended fence; seed compromise can forge lifecycle decisions until independent public trust withdrawal; founder must approve this concrete high-risk scope." + }, + "reviews_required": [ +@@ -134,7 +134,7 @@ + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { +- "role": "cluster-gitops-owner", ++ "role": "cluster-runtime-storage-owner", + "disposition": "pending exact source/artifact review; no approval recorded" + }, + { +@@ -147,6 +147,12 @@ + "supersedes_unadmitted_R3_role": "external-secrets-flex-auth-envelope-signing replaces flex-auth-envelope-signing-eso to fit existing delegated-applier role convention; dedicated SA unchanged", + "read_ccr_field_projection": "Only ED25519_PRIVATE_KEY is delivered; public sibling fields remain visible to dedicated document-reader identity but never become consumer trust discovery", + "projection_source": "docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed", +- "managed_declaration": "Missing rapp declaration remains migration debt; retain actual Access919ce25 workload identity, do not create package tuple" ++ "managed_declaration": "Canonical local rapp-flex-auth-secrets-engine declaration committed d52f811ed5ec0be27c9c367e71d476125b3228be, exact13file tree d4fbad71bdc8ef870603526ccd1f53195d0322af; tuple rapp-flex-auth-secrets-engine/flex-auth-secrets-engine/flex-auth-secrets-engine resolves locally as draft. Frozen source2b/current05a package baseline does not adopt candidate84/signing. Remote publication/placement and actual runtime/package join remain open. No missing-declaration claim or migration-debt waiver is applicable to the established local declaration." ++ }, ++ "owner_review_scope": { ++ "railiance-platform-owner": "OpenBao custody/read lane; existing GitOps Applications and their sync/freeze/controller ownership; covers explicitly identified workload/Helm competing-writer integration with Access, not Access workload semantic ownership.", ++ "access-engine-owner": "Retained workload/release source, Helm values, candidate image, signer delivery/mount and process/outbox fencing/rollback.", ++ "cluster-runtime-storage-owner": "railiance-cluster: cluster identity/runtime/storage/headroom, local-path provisioning and actual PV retention; excludes workload and GitOps Application ownership.", ++ "enablement_condition": "railiance-enablement additional exact review required only if proposed action changes ArgoCD installation/controller configuration; this fixed custody action authorizes no such change. Changed scope needs a separately reviewed exact revision rather than blanket extra reviewer." + } + } +--- a/docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md +@@ -185,3 +185,21 @@ + reviews or start a general window-grant service. An alternative authority/window + contract would itself require separate owner/founder design and is not supplied + by R2. Current native admission remains unapproved. ++ ++## R3 precise owner review boundary ++ ++The native review slot is now `cluster-runtime-storage-owner`, held by ++railiance-cluster for runtime/storage/headroom only. The previous ++`cluster-gitops-owner` slot conflated separate authorities and is rejected; ++no historic review is reinterpreted as a combined assent. Platform's existing ++review covers its custody/read lane and existing GitOps Applications/freeze ++integration. Access retains workload/release/Helm-values and signer/outbox ++ownership. Enablement review is needed only when the action actually changes ++ArgoCD installation/controller configuration; this action does not authorize ++that. Changed scope requires a separate exact revision and any affected owner. ++ ++This is a source-schema correction, not a new approval. Existing R1/R2 source ++reviews and P1/P2 packets remain frozen. A successor packet must pin the new ++executor/source-bundle/plan/CCR hashes and collect five exact fresh dispositions ++under the corrected role set. Admission-file digest approval and CCR ++approved/binding-confirmed status/native checks remain unchanged. +--- a/tests/test_flex_auth_signer_native.py ++++ b/tests/test_flex_auth_signer_native.py +@@ -316,3 +316,20 @@ + assert result['public_key'] is None and result['public_fingerprint'] is None + assert old.read_bytes()==raw + assert not any(x[0]=='http' and x[1]=='POST' for x in io.calls) ++ ++ ++def test_exact_runtime_storage_owner_slot_replaces_conflated_role(native): ++ c,io,directory,call,approve,source=native ++ assert m.REVIEWS=={'founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-runtime-storage-owner'} ++ assert m.validate_admission(c)>5 ++ old=deepcopy(c) ++ old['owner_reviews']['cluster-gitops-owner']=old['owner_reviews'].pop('cluster-runtime-storage-owner') ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(old) ++ missing=deepcopy(c);missing['owner_reviews'].pop('cluster-runtime-storage-owner') ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(missing) ++ extra=deepcopy(c);extra['owner_reviews']['railiance-enablement-owner']=next(iter(extra['owner_reviews'].values())) ++ with pytest.raises(Refused,match='distinct owner reviews'): ++ m.validate_admission(extra) ++ assert io.calls==[] +--- a/workplans/RPF-WP-0035-credential-lane-implementation.md ++++ b/workplans/RPF-WP-0035-credential-lane-implementation.md +@@ -1375,3 +1375,19 @@ + external reviews and unbounded OIDC require a pre-reviewed exact scheduled + window, otherwise refuse/new explicit revision. No native or owner approval + inferred; no live action. ++ ++ ++2026-10-16 T13 bounded source-review preparation note (no status/scope closure): ++Native signer owner-boundary R3/R4 preparation replaces conflated ++cluster-gitops-owner with cluster-runtime-storage-owner. Platform retains ++OpenBao and existing GitOps Applications/sync-freeze integration; Access owns ++workload/Helm release semantics; cluster reviews runtime/storage/headroom; ++Enablement participates only for actual ArgoCD installation/controller changes. ++Source facts reconcile implemented/tested native adapter a3e8eb64, canonical ++local draft package d52f811/tree d4fbad7 (frozen source2b/current05a) and ++ordinary CI402 published candidate84c78e0/image09a83b with OS lock/64MiB/startup ++hardening. Prior R1/R2/R3 and packetP1/P2 reviews/failures remain frozen. ++No missing-local-declaration waiver, remote placement, actual stopped fence, ++PV retention, native custody, independent post-key trust or founder/owner ++approval is inferred. Exact successor source/CCR/plan pins and fresh scoped ++reviews remain required; T12 native gates and historical T13 outcome unchanged. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/manifest.json new file mode 100644 index 00000000..d67aafd3 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/manifest.json @@ -0,0 +1,25 @@ +{ + "proposal_id": "RPF35-PDP-SIGNER-OWNER-BOUNDARY-20261016-R5", + "base_commit": "a3e8eb64bae110393ba0aeab043de03a92b8421a", + "predecessor_r4_manifest_sha256": "sha256:835b00b582e3cdd56a4a2aa45e803dd8f619e4c53cd2e3b3997053fc1c5926f4", + "files_sha256": { + "scripts/flex_auth_signer_native.py": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f", + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": "sha256:44bbbf4aff84c3b085afdb14708106fd9a12ac03a0c47774913931a87fb94ada", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": "sha256:22306d50e082fc35c5ff22c31e739a53c7584176969063f7907bc01d77e506e5", + "docs/credential-lane-designs/flex-auth-envelope-signing-native-adapter.md": "sha256:0e2e431dcd2df66e65434ce4060a4d5b52941f50928be80a075e4f972229d3a9", + "tests/test_flex_auth_signer_native.py": "sha256:f74a2316506737966e2ea539799cb477a9cec2718a6679f417478f9972731b3e", + "workplans/RPF-WP-0035-credential-lane-implementation.md": "sha256:20451474d84be986f7be1e2ff8c48e3a754e981718949f0e9d771081ae15d25b" + }, + "full_patch_sha256": "sha256:43264f13da5ff20267dea424a7c7d8d911f7601edca6871f31394e0c292fcd59", + "r4_delta_patch_sha256": "sha256:8115c72cd7d14d870f39acb71ef9e819c40e835f56c30226128ace552cd5d5f9", + "disposition": "Platform typed public metadata correction only; no authority grant", + "r4_preserved": true, + "native_action": false, + "artifact_files_sha256": { + "README.md": "sha256:532d21e88312b0e0ded0325cdab3fa67974c91fdfac0cc0197c45df16837088b", + "implementation-r5-full.patch": "sha256:43264f13da5ff20267dea424a7c7d8d911f7601edca6871f31394e0c292fcd59", + "r4-to-r5.patch": "sha256:8115c72cd7d14d870f39acb71ef9e819c40e835f56c30226128ace552cd5d5f9", + "scanner.json": "sha256:b61a8aec0ad5012993fa615c9222ccdac35aa98bf78d3c2112cf21a5fedbbf1d", + "validation.json": "sha256:82acae7bf5dd4ecb29ee36b51c69e2c8c8af8c02ef14698079c66102141067fe" + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/scanner.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/scanner.json new file mode 100644 index 00000000..89f0f3ab --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/scanner.json @@ -0,0 +1,8 @@ +{ + "blocked_blob_ids": [], + "scanned_blobs": 6, + "scanner_sha256": "88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509", + "scanner_version": "8.30.1", + "scope": "changed-staged-blobs", + "status": "clean" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/validation.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/validation.json new file mode 100644 index 00000000..8c7c2a2f --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-owner-boundary-r5/validation.json @@ -0,0 +1,13 @@ +{ + "ccr0050_errors": [], + "ccr0050_warnings": [ + "OIDC/Kubernetes bound claim is not confirmed; apply is blocked" + ], + "status": "proposed", + "bound_claims_confirmed": false, + "delta_scope": "two metadata files only; executor/tests/workplan unchanged from R4", + "tests": "R3 45+coordinator independent54 retained; no runtime retest for metadata wording", + "canonical_modified": false, + "scanner_config": "normal pinned adapter default useDefault=true; empty ignores; --ignore-gitleaks-allow; no suppression/bypass", + "diagnosis": "Git revision spacing alone still blocked. Actual bare flex-auth image sha256 digest matches auth-sensitive generic-api-key expression. Full typed immutable OCI reference avoids ambiguity and retains exact digest." +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/README.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/README.md new file mode 100644 index 00000000..2870c0ed --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/README.md @@ -0,0 +1,19 @@ +# Native signer preparation R1 + +Apply after writer R2 and metadata R3. This adds proposed CCR-2026-0050, +generated exact ESO read policy, native candidate projection, and the concrete +attended writer/fencing/receipt plan. The real validator passes; real apply +refuses proposed status/unconfirmed bindings. Three preparation tests passed. +Exact preimages, hashes, validation and source-only owner review are retained. + +This read CCR grants no write custody. The separate native action specifies +target cluster/backend, CAS0/new kid, exact metadata/data methods, protected +child, fence, receipts and forward-only unknown recovery. Its native production +adapter still requires implementation/independent tests before executable approval. +No credential, secret, policy, role, deployment, route or PVC was changed live. + +Native candidate amends the unadmitted R3 role to fit existing applier conventions +and declares only the projected private field; KV read remains document-granular. +Access confirmed the encoding/fingerprint interface only, not custody or deploy. +Access observed zero existing PVCs; its new storage/runtime scope requires +separate owner/founder review. Required reviews remain distinct and unfilled. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/access-interface-coordination.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/access-interface-coordination.json new file mode 100644 index 00000000..47708f28 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/access-interface-coordination.json @@ -0,0 +1,16 @@ +{ + "source": "Access owner agent message during delegated review, not native approval", + "agreement": [ + "strict unpadded base64url32byte seed, Secret seed0440 startup-only", + "public fingerprint SHA256 canonical base64url ASCII43bytes, not raw decoded key", + "candidate kid flex-auth-lifecycle-20261016-r1", + "candidate role external-secrets-flex-auth-envelope-signing" + ], + "separate_Access_proposal": [ + "new PVC flex-auth-secrets-engine-outbox1Gi local-path Helmkeep", + "source flex-auth.secrets-engine, initial auditDelivery disabled", + "explicit PVreclaim Retain review needed because current SC Delete", + "process lock/byte ceiling/bounded startup/compaction runtime work still required" + ], + "native_custody_CCR_deploy_assent": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/implementation.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/implementation.patch new file mode 100644 index 00000000..fd5a31d7 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/implementation.patch @@ -0,0 +1,477 @@ +diff --git a/credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml b/credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml +new file mode 100644 +index 0000000..ccccdb2 +--- /dev/null ++++ b/credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml +@@ -0,0 +1,128 @@ ++id: CCR-2026-0050 ++kind: credential-change-request ++schema_version: 1 ++request_type: workload-kv-read ++title: Retained flex-auth lifecycle PDP Ed25519 seed ESO read lane ++status: proposed ++created: '2026-10-16' ++updated: '2026-10-16' ++requester: ++ agent: railiance-platform ++ reason: CUST-WP-0080 / RPF-WP-0035-T12 / FLEX-WP-0024-T06 source proposal. Exact ++ new custody/read scope requires founder review; no approval or native binding ++ is inferred. ++review: ++ required: true ++ required_approvers: ++ - founder ++ - railiance-platform-owner ++ - access-engine-owner ++ - secrets-engine-owner ++ - cluster-gitops-owner ++ comments: [] ++target: ++ domain: infotech ++ tenant: platform ++ workload: flex-auth-secrets-engine ++ environment: production ++ purpose: Deliver the Ed25519 seed only to the retained lifecycle PDP startup file. ++ No taskpilot enablement, caller policy changes or private consumer trust discovery. ++openbao: ++ mount: platform ++ kv_path: platform/workloads/flex-auth/envelope-signing ++ fields: ++ - ED25519_PRIVATE_KEY ++ metadata_read: false ++ token_self_lifecycle: true ++ policy_name: workload-kv-read-flex-auth-envelope-signing ++ policy_file: openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl ++ auth: ++ method: kubernetes ++ mount: kubernetes ++ role: external-secrets-flex-auth-envelope-signing ++ bound_claims: ++ service_account_names: ++ - flex-auth-envelope-signing-eso ++ service_account_namespaces: ++ - flex-auth ++ bound_claims_confirmed: false ++ policies: ++ - workload-kv-read-flex-auth-envelope-signing ++ ttl: 15m ++ audience: openbao ++ token_max_ttl: 15m ++ token_explicit_max_ttl: 15m ++ token_no_default_policy: true ++access_frontdoor: ++ type: external-secrets ++ catalog_id: flex-auth-decision-envelope-signing-key ++ selector: Retained flex-auth/flex-auth-secrets-engine signer only ++ readiness: pending-review ++ resolvable: false ++delivery: ++ surface: external-secrets ++ target: Namespace flex-auth; dedicated SA flex-auth-envelope-signing-eso; SecretStore ++ openbao-flex-auth-envelope-signing; ExternalSecret/Secret flex-auth-secrets-engine-envelope-signing; ++ seed property only -> startup file /var/run/secrets/decision-envelope-signing/seed0440, ++ readOnly uid/gid/fsGroup65532; no envFrom ++ bootstrap_command: Attended writer is a distinct exact-source action proposal in ++ docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json; this ++ read CCR authorizes neither seed writes nor any execution by itself. ++risk: ++ classification: high ++ notes: ++ - Possession of seed can forge lifecycle PDP envelopes; independent consumer public ++ trust admission and fixed policy pins remain required. ++ - 'KV read is document-granular: dedicated ESO identity can read all three fields; ++ only private field is projected. Signer and Secrets consumer have no KV read role.' ++ - No parent/list/metadata/write/delete capability on ESO role. No token/Secret read ++ or ExternalSecret mutation granted to signer/consumer. ++ - Dedicated role is new scope; founder approval required. No workload rapp tuple ++ invented; absent managed package declaration remains explicit migration debt. ++ - Controlled outage fence stops every signer pod and disables autoscaling before ++ creation/rotation. Recreate single writer and retained PVC remain Access-owned ++ review gates. ++ - fields declares only projected ED25519_PRIVATE_KEY. The same KV document also ++ has public key/kid, and OpenBao data-read is not field-filtered; do not claim ++ field-level authorization. ++verification: ++ positive: ++ - Exact SA/namespace/audience login; native exact data read; ESO Ready/SecretSynced; ++ safe metadata resourceVersion and admitted KV version correspondence. ++ - All retained signer replicas restart with admitted kid/source/image and seed/public ++ correspondence; signed non-effect lifecycle allow/deny with durable originals ++ and independent consumer signature verification. ++ negative: ++ - Wrong SA/namespace/audience login refused; sibling/list/metadata/write/delete ++ denied; signer/consumer TokenRequest and Secret/ExternalSecret mutation denied. ++ - Unknown/old kid, wrong policy, tamper, expired/unsigned envelope, wrong caller ++ and missing seed refuse; no taskpilot activation. ++ - Receipt write failure/lost backend response retained unknown; no blind retry/remint; ++ stale CAS cannot overwrite version. ++ activation_conditions: ++ - All five required approvers independently dispose the exact CCR and native writer/fence ++ proposal; founder exact new custody scope approved. ++ - Current retained identity919ce25, immutable published producer image and explicit ++ new flex-auth-secrets-engine-outbox PVC1Gi/local-path, retention/reclaim and bounded-runtime ++ plan reviewed by Access; missing managed package migration debt explicitly accepted ++ for this retained workload only. ++ - Exact native bound claims verified without printing JWT/Secret; read grant policy ++ and role native readback match source. ++ - Protected child source pinned, silent attended OIDC context verified, target cluster/backend ++ pinned, fence verified and durable receipt custody installed. ++ - Consumer independently admits owner-authenticated public receipt and exact policy/image/trust ++ pins before protected acceptance. ++ evidence: [] ++lifecycle: ++ deactivate: Fence all retained signer processes, stop consumers, disable delivery ++ role/ESO and online trust; retain private KV and audit receipts under explicit ++ owner retention until reviewed destruction. ++ rotate: Pre-admit successor public receipt offline; fence consumers/all signer replicas/no ++ HPA; CAS exact version with new in-memory seed; wait exact ESO version, restart ++ single writer, verify native allow/deny and old-key refusal before reopening. ++ compromised: Immediately remove old online trust and stop all signer processes; ++ forward-only CAS recovery with independently approved successor. Never restore ++ compromised seed; archive historical public keys for offline audit only. ++state_hub: ++ workplan_id: RPF-WP-0035 ++ task_id: RPF-WP-0035-T12 +diff --git a/openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl b/openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl +new file mode 100644 +index 0000000..57425e7 +--- /dev/null ++++ b/openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl +@@ -0,0 +1,11 @@ ++path "platform/data/workloads/flex-auth/envelope-signing" { ++ capabilities = ["read"] ++} ++ ++path "auth/token/lookup-self" { ++ capabilities = ["read"] ++} ++ ++path "auth/token/revoke-self" { ++ capabilities = ["update"] ++} +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json b/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json +new file mode 100644 +index 0000000..ed8c74f +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json +@@ -0,0 +1,150 @@ ++{ ++ "schema": "railiance-platform.signer-native-action-proposal.v1", ++ "proposal_id": "RPF35-PDP-SIGNER-NATIVE-20261016-R1", ++ "status": "prepared-unapproved", ++ "read_ccr": "CCR-2026-0050", ++ "proposal_scope": "attended bootstrap of retained lifecycle PDP seed; no taskpilot enablement, rotation requires a new exact-version action revision", ++ "actor": "founder attended OIDC via warden openbao-platform-admin-login; reviewed silent Platform custody child", ++ "executor_ownership": "railiance-platform; founder executes exact child; agent receives closed metadata only", ++ "abort_owner": "founder; Platform preserves unknown custody/evidence, Access keeps signer/consumers fenced", ++ "target": { ++ "cluster": "primary/railiance01", ++ "kube_system_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786", ++ "openbao_cluster_id": "fd28df5d-98ec-57dd-42ec-9b3e4f4e53bf", ++ "openbao_origin": "http://127.0.0.1:18200", ++ "namespace": "flex-auth", ++ "deployment": "flex-auth-secrets-engine", ++ "signer_sa": "flex-auth-secrets-engine" ++ }, ++ "credential_route": "openbao-platform-admin-login; flex-auth-decision-envelope-signing-key remains draft/nonresolvable; route is not a seed vending service", ++ "bootstrap": { ++ "action": "CAS0 fresh in-memory Ed25519 seed", ++ "kid": "flex-auth-lifecycle-20261016-r1", ++ "expected_version": 0, ++ "data_path": "platform/data/workloads/flex-auth/envelope-signing", ++ "document_fields": [ ++ "ED25519_PRIVATE_KEY", ++ "ED25519_PUBLIC_KEY", ++ "kid" ++ ], ++ "metadata_path": "platform/metadata/workloads/flex-auth/envelope-signing", ++ "metadata_contract": { ++ "cas_required": true, ++ "max_versions": 2, ++ "delete_version_after": "0s" ++ }, ++ "allowed_native_methods": [ ++ { ++ "method": "POST", ++ "path": "platform/metadata/workloads/flex-auth/envelope-signing", ++ "purpose": "CAS-required/version-retention configuration after absence/no-drift validation" ++ }, ++ { ++ "method": "GET", ++ "path": "platform/metadata/workloads/flex-auth/envelope-signing", ++ "purpose": "exact metadata readback, no private value output" ++ }, ++ { ++ "method": "POST", ++ "path": "platform/data/workloads/flex-auth/envelope-signing", ++ "purpose": "single CAS0 seed document write" ++ }, ++ { ++ "method": "GET", ++ "path": "platform/data/workloads/flex-auth/envelope-signing?version=1", ++ "purpose": "exact private readback in custody, closed public receipt only" ++ } ++ ], ++ "source_primitive_sha256": "sha256:8ed281a49c1f1cdb23772efe3593e75c62572a12b8d7a6a4c574f27b38722e75" ++ }, ++ "fencing": { ++ "before_key_generation": [ ++ "Verify cluster/backend IDs, exact current source/CCR and founder disposition hashes.", ++ "Read exact deployment/ReplicaSets/pods by ownerReference and SA; refuse a second workload/pod using signer SA or selecting signer Secret.", ++ "Access stops protected consumers and scales retained deployment0 through its reviewed release path; this child does not mutate replicas.", ++ "Verify deployment spec replicas0, observed generation caught up, no live or terminating owned ReplicaSet/pods, no matching signer-SA pods and no HPA targeting deployment.", ++ "Reject a differing/previously existing KV entry at bootstrap. Hold exclusive owner action receipt lock and recheck fence immediately before CAS." ++ ], ++ "after_cas": "Keep consumers/signer stopped until independent public admission and exact ESO/readback/source/image verification. Recreate1 is Access-owned; any drift or uncertain outcome keeps fence closed. Access reports current outbox lacks OS process lock, byte ceiling and bounded startup/compaction; Recreate1 alone is not bounded durable acceptance. Keep protected acceptance closed until reviewed source hardening or explicit bounded attended fixture disposition.", ++ "concurrency": "Single attended owner window/exclusive receipt; GitOps/Helm autosync/other writers must be paused by Access/cluster owner under distinct reviewed action. Plan is not a Kubernetes atomic fence or same-UID isolation." ++ }, ++ "protected_adapter": { ++ "state": "implementation/independent tests still required before executable approval; fixture code must never be promoted by removing its dev-process check", ++ "reuse": [ ++ "scripts/state_hub_preflight_lane.py attended silent child/cluster/platform-admin/fencing patterns", ++ "scripts/flex_auth_signer_custody.py protected Ed25519 CAS/readback and receipt state machine", ++ "scripts/task_execution_native_fixture.py absolute main-thread2s I/O budget", ++ "scripts/task_execution_recovery.py strict bounded JSON/no-follow/private custody patterns" ++ ], ++ "requirements": [ ++ "New fixed native adapter consumes exact approved CCR/source/native-action digest; cannot accept arbitrary URL/path/command/payload/seed.", ++ "Read OIDC token only within warden child from attended context; require platform-admin and reject root; never print/store bearer. No credential comes back to agent.", ++ "Pin exact kube-system/OpenBao cluster IDs before private calls, refuse ambient address override; enforce2s absolute reads and1MiB cap; no redirect/shell/tracing.", ++ "Verify metadata absence/exact admitted values before CAS-required change; any differing existing object refuses. Exact response contracts and duplicate/nonfinite JSON rejection.", ++ "Private seed is generated once, never imported or persisted outside OpenBao; no subprocess argv/env seed; readback compares exact version/fields and derived public correspondence.", ++ "Receipt intent is durable before native effect; final success requires exact KV/metadata correspondence and receipt fsync. Process loss/error remains unknown without remint/retry." ++ ] ++ }, ++ "receipts": { ++ "directory": "/home/worsch/.local/state/railiance-platform/flex-auth-envelope-signing", ++ "mode_directory": "0700", ++ "mode_file": "0600", ++ "native_execution_location": "founder workstation inside reviewed warden child; no agent-owned shared /tmp custody", ++ "basename": "RPF35-PDP-SIGNER-NATIVE-20261016-R1.json", ++ "maximum_bytes": 65536, ++ "atomic": "exclusive initial receipt, fsync-before-effect, atomic replacement and directory fsync, no-follow/owner/mode/nlink validation", ++ "public_fields": [ ++ "proposal/executed source/CCR/identity/cluster/image/policy/trust digests", ++ "actor/time", ++ "closed phase/status", ++ "exact KV path/version/kid", ++ "public key and explicitly encoded fingerprint", ++ "fence/metadata/readback checks", ++ "rollback or unknown recovery disposition" ++ ], ++ "fingerprint": "sha256: lowercase SHA256 of canonical unpadded base64url public-key ASCII, exactly43bytes; independent Secrets owner agreement before admission", ++ "delivery": "Founder/Platform separately authenticate metadata receipt to Secrets owner; public receipt shape/file does not create consumer trust; raw private receipt directory is not a shared agent intake" ++ }, ++ "rollback": { ++ "before_cas": "Abort without private write; retain receipt/fence; restore prior Access image/values only via reviewed Access action.", ++ "after_cas_unknown": "Retain unknown and fence; independently attended owner reconciles exact metadata/version/public correspondence. Never rerun CAS0 or restore prior seed automatically.", ++ "compromise": "Remove online old public key immediately; stop signer, independent new reviewed forward-only action; old private seed never restored." ++ }, ++ "requested_scope": { ++ "read_lane": "Exact CCR0050 policy/role/delivery source only after separate founder review. No extra ESO RBAC permitted.", ++ "custody_writer": "One attended exact-target CAS0 plus fixed KV metadata setup/readback; no standing writer grant or broker role. This authority is separate from read CCR.", ++ "kubernetes": "Metadata-only fence observations by child; Access/cluster separately approve stop/restart/delivery manifests and sync control.", ++ "new_infrastructure_spend_eur": 0, ++ "new_resources": "Platform creates no storage resources. Access reports zero flex-auth PVCs; Access proposes separate exact new flex-auth-secrets-engine-outbox1Gi local-path Helmkeep. Provisioning, PV reclaim/Delete/WaitForFirstConsumer retention and runtime log bounds require separate founder/cluster/Access review; no durable outbox acceptance yet.", ++ "risk_bound": "Controlled loss of retained PDP availability during explicit attended fence; seed compromise can forge lifecycle decisions until independent public trust withdrawal; founder must approve this concrete high-risk scope." ++ }, ++ "reviews_required": [ ++ { ++ "role": "railiance-platform-owner", ++ "disposition": "pending exact source/artifact review; no approval recorded" ++ }, ++ { ++ "role": "access-engine-owner", ++ "disposition": "pending exact source/artifact review; no approval recorded" ++ }, ++ { ++ "role": "secrets-engine-owner", ++ "disposition": "pending exact source/artifact review; no approval recorded" ++ }, ++ { ++ "role": "cluster-gitops-owner", ++ "disposition": "pending exact source/artifact review; no approval recorded" ++ }, ++ { ++ "role": "founder", ++ "disposition": "pending exact source/artifact review; no approval recorded" ++ } ++ ], ++ "authority_granted": false, ++ "candidate_delivery_amendments": { ++ "supersedes_unadmitted_R3_role": "external-secrets-flex-auth-envelope-signing replaces flex-auth-envelope-signing-eso to fit existing delegated-applier role convention; dedicated SA unchanged", ++ "read_ccr_field_projection": "Only ED25519_PRIVATE_KEY is delivered; public sibling fields remain visible to dedicated document-reader identity but never become consumer trust discovery", ++ "projection_source": "docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed", ++ "managed_declaration": "Missing rapp declaration remains migration debt; retain actual Access919ce25 workload identity, do not create package tuple" ++ } ++} +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.md b/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.md +new file mode 100644 +index 0000000..01853bb +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.md +@@ -0,0 +1,37 @@ ++# Native signer action preparation ++ ++CCR-2026-0050 is a schema-valid proposed ESO read grant. It does not authorize ++secret writes. The separate exact native-action JSON requests one attended CAS0 ++and fixed metadata setup/readback; founder disposition is still pending. No ++standing writer/broker grant, private consumer lookup, rapp declaration or policy ++change is introduced. Native private custody remains in the founder's reviewed ++warden child, not an agent prompt or temporary file. ++ ++The JSON fixes the target/cluster/backend, new kid, CAS version, exact native ++methods, retention/CAS metadata, existing custody machinery, signer fence, ++receipt location/encoding, abort owner and forward-only recovery. It separately ++identifies Access/cluster-owned stop/restart/ESO/PVC and Secrets-owned independent ++public admission. These owners must review their exact inputs; Platform cannot ++sign their dispositions. The program that enforces this native contract still ++requires source implementation and independent tests before executable approval. ++The existing fixture adapter must not be promoted by deleting its process check. ++ ++Source preparation validated the real credential-change schema and generated ++HCL. The expected unconfirmed-bound-claims warning and proposed status preserve ++apply refusal. No live observation/identity confirmation, credential read, CAS, ++policy write, role, Kubernetes or route mutation occurred. Missing managed ++package declaration remains explicit migration debt for the retained workload. ++ ++The native candidate explicitly amends two unadmitted R3 read-lane choices: ++role `external-secrets-flex-auth-envelope-signing` follows the existing delegated ++applier convention; read CCR fields names the projected ED25519_PRIVATE_KEY only. ++The same document has public sibling fields; document-granular read means ESO ++can read those too, so this is not field-level authorization. The sibling native ++projection proposal and CCR agree on the new role. Historical R3 is not mutated. ++ ++Access metadata observation found zero PVCs in flex-auth. Its exact proposed ++new outbox PVC1Gi/local-path is a separate resource/retention scope, with Delete/ ++WaitForFirstConsumer PV behavior needing explicit treatment. Existing outbox code ++lacks process locking/byte ceiling/bounded startup and compaction. Neither ++Recreate1 nor Helmkeep supplies these guarantees; production durable acceptance ++remains closed until Access-owned hardening and cluster/storage review. +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed b/docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed +new file mode 100644 +index 0000000..589a7ca +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed +@@ -0,0 +1,50 @@ ++# SOURCE PROPOSAL ONLY: no CCR admission, no apply, no plaintext key. ++apiVersion: v1 ++kind: ServiceAccount ++metadata: ++ name: flex-auth-envelope-signing-eso ++ namespace: flex-auth ++automountServiceAccountToken: false ++--- ++apiVersion: external-secrets.io/v1 ++kind: SecretStore ++metadata: ++ name: openbao-flex-auth-envelope-signing ++ namespace: flex-auth ++spec: ++ provider: ++ vault: ++ server: http://openbao.openbao.svc:8200 ++ path: platform ++ version: v2 ++ auth: ++ kubernetes: ++ mountPath: kubernetes ++ role: external-secrets-flex-auth-envelope-signing ++ serviceAccountRef: ++ name: flex-auth-envelope-signing-eso ++ audiences: [openbao] ++--- ++apiVersion: external-secrets.io/v1 ++kind: ExternalSecret ++metadata: ++ name: flex-auth-secrets-engine-envelope-signing ++ namespace: flex-auth ++spec: ++ refreshInterval: 5m ++ secretStoreRef: ++ kind: SecretStore ++ name: openbao-flex-auth-envelope-signing ++ target: ++ name: flex-auth-secrets-engine-envelope-signing ++ creationPolicy: Owner ++ deletionPolicy: Retain ++ template: ++ metadata: ++ annotations: ++ railiance.io/custody-proposal: RPF35-PDP-SIGNER-NATIVE-20261016-R1 ++ data: ++ - secretKey: seed ++ remoteRef: ++ key: workloads/flex-auth/envelope-signing ++ property: ED25519_PRIVATE_KEY +diff --git a/tests/test_flex_auth_signer_native_preparation.py b/tests/test_flex_auth_signer_native_preparation.py +new file mode 100644 +index 0000000..bd1b357 +--- /dev/null ++++ b/tests/test_flex_auth_signer_native_preparation.py +@@ -0,0 +1,49 @@ ++"""Real CCR schema/applier contract, no credentials or backend invocation.""" ++from copy import deepcopy ++import importlib.util ++import json ++from pathlib import Path ++import yaml ++ROOT=Path(__file__).resolve().parents[1] ++spec=importlib.util.spec_from_file_location('signer_ccr',ROOT/'scripts/credential-change.py') ++ccr_module=importlib.util.module_from_spec(spec);spec.loader.exec_module(ccr_module) ++CCR=ROOT/'credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml' ++ ++ ++def test_real_schema_and_apply_refusal(): ++ ccr,errors,warnings=ccr_module.validate_ccr(CCR) ++ assert errors==[] ++ assert warnings==['OIDC/Kubernetes bound claim is not confirmed; apply is blocked'] ++ blockers=ccr_module.applier_readiness_blockers(ccr) ++ assert len(blockers)==2 ++ assert any('status, got proposed' in x for x in blockers) ++ assert any('confirmed OpenBao auth binding' in x for x in blockers) ++ assert ccr['review']['comments']==[] and ccr['access_frontdoor']['resolvable'] is False ++ # Pure synthetic candidate only: ensure admitted-pattern scope has no latent ++ # schema/applier role/field failures once the real owners eventually approve. ++ admitted=deepcopy(ccr);admitted['status']='approved';admitted['openbao']['auth']['bound_claims_confirmed']=True ++ assert ccr_module.applier_readiness_blockers(admitted)==[] ++ ++ ++def test_generated_read_scope_and_projection_join(): ++ ccr,_,_=ccr_module.validate_ccr(CCR) ++ assert (ROOT/ccr['openbao']['policy_file']).read_text()==ccr_module.generated_policy_hcl(ccr) ++ hcl=ccr_module.generated_policy_hcl(ccr) ++ assert 'metadata/' not in hcl and 'list' not in hcl and 'create' not in hcl ++ assert ccr['openbao']['fields']==['ED25519_PRIVATE_KEY'] ++ docs=list(yaml.safe_load_all((ROOT/'docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed').read_text())) ++ store=next(x for x in docs if x['kind']=='SecretStore') ++ assert store['spec']['provider']['vault']['auth']['kubernetes']['role']==ccr['openbao']['auth']['role'] ++ external=next(x for x in docs if x['kind']=='ExternalSecret') ++ assert external['spec']['data']==[{'secretKey':'seed','remoteRef':{'key':'workloads/flex-auth/envelope-signing','property':'ED25519_PRIVATE_KEY'}}] ++ ++ ++def test_native_scope_separates_read_grant_and_unadmitted_execution(): ++ plan=json.loads((ROOT/'docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json').read_text()) ++ assert plan['authority_granted'] is False and plan['status']=='prepared-unapproved' ++ assert plan['bootstrap']['expected_version']==0 ++ assert all(x['disposition'].startswith('pending ') for x in plan['reviews_required']) ++ assert 'implementation/independent tests still required' in plan['protected_adapter']['state'] ++ assert plan['receipts']['maximum_bytes']==65536 ++ assert all('platform/' in x['path'] for x in plan['bootstrap']['allowed_native_methods']) ++ assert 'zero flex-auth PVCs' in plan['requested_scope']['new_resources'] +--- a/workplans/RPF-WP-0035-credential-lane-implementation.md ++++ b/workplans/RPF-WP-0035-credential-lane-implementation.md +@@ -1344,3 +1344,13 @@ + R3 source metadata correction aligns proposal IDs across JSON/docs/Secret + annotation and documents existing base64url-ASCII public fingerprint hashing. + Frozen R2 source/evidence is preserved; no writer behavior or admission changes. ++ ++2026-10-16 T12 native signer preparation: proposed CCR-2026-0050 and generated ++read-only HCL pass real schema checks; current proposed status/unconfirmed claims ++keep apply refused. Native candidate uses existing external-secrets-* role ++convention with dedicated SA unchanged and projected private field only. Exact ++attended CAS0/metadata/fence/receipt/forward-recovery action plan is separate from ++read-grant authority; production adapter implementation/independent tests and ++founder plus distinct owner reviews remain necessary. Access observed zero PVCs; ++new outbox storage/retention/runtime bounds remain separate Access/cluster scope. ++No live credentials, grants, roles, key or deployment changed. T12 stays progress. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/manifest.json new file mode 100644 index 00000000..37bf021d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/manifest.json @@ -0,0 +1,41 @@ +{ + "schema": "railiance-platform.signer-native-preparation-source.v1", + "proposal_id": "RPF35-PDP-SIGNER-NATIVE-20261016-R1", + "requires_writer_R2_patch_sha256": "b0c190060f5a41d6002e1fb7b49f047fd4874a51576f29f3c127a8634c2616f6", + "requires_writer_R3_delta_sha256": "a29cdbd2ac92fd09bc6c79144e9aeb84bb6abcd303df997c0f01c0223cf1a508", + "canonical_budget_revision": "76fdc0b", + "isolated_source": "/tmp/netkingdom-platform-signer-native-preparation-20261016", + "patch_sha256": "a9d4631d3320ac3fa56f5a61965005c546eae241d2004cc1e6385e04668b7f7f", + "files": { + "credential-change-requests/CCR-2026-0050-flex-auth-envelope-signing.yaml": { + "before_sha256": null, + "after_sha256": "72fd6e84e866a72f4768dabd66326aebe1fdd00013b2314de961ca72a632679f" + }, + "openbao/policies/workload-kv-read-flex-auth-envelope-signing.hcl": { + "before_sha256": null, + "after_sha256": "b9f816da25c7770863a5fc7b3b873e9da90b087e71a9052e766bf0a187ff85ef" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.json": { + "before_sha256": null, + "after_sha256": "abc7c97eee8c059ee1d93b6e48e6f6277c4b8810623510d5cede20fd889feb44" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-native-plan.md": { + "before_sha256": null, + "after_sha256": "241e3e46d7823c1fb0dd62ce2d61dadf659d109286acea872e0aaad9cac26760" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-native-projection.yaml.proposed": { + "before_sha256": null, + "after_sha256": "4972402b6d6490eb4dd540525b5ce475443d6b99373c28eda197c932438d745f" + }, + "tests/test_flex_auth_signer_native_preparation.py": { + "before_sha256": null, + "after_sha256": "8b05c5f519e69f66be9dc1ac942f5a7a8fe60edda63d4c38daaba7e15a166314" + }, + "workplans/RPF-WP-0035-credential-lane-implementation.md": { + "before_sha256": "d3cbe2ba5e344c1e8fc7e9f422d89030616b98abd53df4b9327f44fcaca865d3", + "after_sha256": "bab368699a4f80ac0f9092a467c7f4b50c9831c4543dc86a3f51eabb82fdf320" + } + }, + "native_writer_source": "fixture core pinned in native plan; production adapter implementation/independent tests still required", + "authority_granted": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/owner-review.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/owner-review.json new file mode 100644 index 00000000..2bf84418 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/owner-review.json @@ -0,0 +1,22 @@ +{ + "reviewer_role": "railiance-platform-owner", + "agent": "railiance-platform (codex)", + "reviewed_revision_sha256": "a9d4631d3320ac3fa56f5a61965005c546eae241d2004cc1e6385e04668b7f7f", + "disposition": "approve-source-preparation-only", + "assessment": "Schema-valid proposed read CCR, generated exact data-only policy and concrete native action/fence/receipt plan reuse existing custody machinery. Corrected existing delegated-applier convention failures without widening verifier. Required external/native approvals remain distinct. New protected production adapter must still implement/test the exact native plan; source preparation is not executable/live approval.", + "required_distinct_reviews": [ + "Access source/image/caller/stop-restart/outbox/PVC", + "Secrets independent owner-authenticated public receipt/trust/fingerprint/native consumer acceptance", + "cluster/GitOps delivery identity/RBAC/ESO/sync/storage", + "founder new custody scope and exact executed revision", + "Platform native protected adapter/readback/receipt/fence implementation" + ], + "preserved": [ + "writer R2", + "metadata R3", + "CCR0048", + "CCR0049", + "WORK-RECORDS.md" + ], + "authority_granted": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md new file mode 100644 index 00000000..0a89a2b9 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -0,0 +1,1346 @@ +--- +id: RPF-WP-0035 +type: workplan +title: "Implement reviewed credential lanes with separate owner gates" +domain: financials +repo: railiance-platform +status: blocked +flavor: implementation +owner: codex +created: "2026-09-05" +updated: "2026-10-13" +related: + - RPF-WP-0032 + - RPF-WP-0033 + - RPF-WP-0034 +state_hub_workstream_id: "975db491-5412-5e27-8e34-14a2417bb039" +--- + +# Credential lane implementation + +One S3 queue for three designed lanes; each task keeps its own approval, +execution and closure boundary. This replaces the implementation tasks in the +three completed design workplans, not the designs themselves. No approval is +inherited by consolidation. INTENT binding: secure custody, dependable delivery, +stable consumer interfaces. Incident custody remains in RPF-WP-0027/0029. + +## Consolidate completed designs and owner dependencies + +```task +id: RPF-WP-0035-T01 +status: done +priority: medium +state_hub_task_id: "0f3606bb-e95b-5484-8a57-bcdd6e3916fd" +``` + +Completed 2026-09-05. Preserved the three designs under +`docs/credential-lane-designs/`, identified native owner responsibilities and +linked each superseded task below. Owners have not been sent new requests and +no new external acceptance is claimed. STATE-WP-0085-T09 is already done; +the signing dependency belongs to the proposed FLEX-WP-0020-T05 cutover. + +## Accept and provision secrets-engine service JWT login + +```task +id: RPF-WP-0035-T02 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +depends_on: [KEY-WP-0039-T02, MASON-WP-0009-T05] +blocking_reason: "Agent work, not a human gate: claim refusals (KEY-WP-0039-T02 probe) and capabilities-self deny, then ops-mason MASON-WP-0009-T05." +priority: high +state_hub_task_id: "e0c82ea9-05a5-537e-8fbf-67534263572e" +``` + +2026-10-11: requalified — the remaining waits are other owners' tasks, not a human gate. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0032-T02. Design: +`docs/credential-lane-designs/secrets-engine-service-jwt.md`. + +Platform owns the exact JWT mount/role/policy, effective-policy negative tests +and a metadata-only custody receipt. KeyCape owns issuer/JWKS and service +registration (KEY-WP-0009); secrets-engine owns service authentication and +authority consumption (SECRETS-WP-0008-T06, SECRETS-WP-0007-T04). + +**Unblock:** live registration and protected client custody, reviewed exact source +and attended apply authority. Issuer/JWKS and consumer source claims now agree; +see the 2026-09-27 return below. A service login does +not grant lane mutation authority. Do not build another identity provider or +lifecycle engine here. + +**Done when:** approved exact role succeeds for the intended service, wrong +issuer/audience/subject/claims and unrelated secret access fail, bounded TTL +and revocation are proven, the consumer explicitly opts into the verified +contract, and rollback/cleanup receipts contain no secret material. + +2026-10-09 (T03 source): founder ruled the tenant segment stays `coulomb` +(ops-mason `b72ff77d`). New CCR request type `workload-kv-operator-matrix` +(`scripts/operator_matrix_lane.py`): exact per-entry capabilities, OIDC role on +the existing `netkingdom` mount only, and exact agent denies on all four data +and metadata paths appended to the live `agent-high-risk-boundary` (live content +preserved; partial presence refused). `scripts/fluid_telegram_custody_move.py` +copies the four undocumented `infotech` entries with CAS 0, verifies all, then +metadata-deletes the sources. `scripts/kv_duplicate_retire.py` retires +`activity-core/default/llm-connect-provider-secrets` only if no live non-admin +policy grants it. Founder session (each helper prints nothing; read the receipts): + +```bash +cd ~/railiance-platform +export BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 +W='warden access openbao-platform-admin-login --exec --' +# 1. dry-runs (no value reads, no writes) +$W python3 scripts/fluid_telegram_custody_move.py --dry-run --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move-dry.json +$W python3 scripts/kv_duplicate_retire.py --dry-run --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire-dry.json +# 2. lane: approve, confirm binding, apply +python3 scripts/credential-change.py approve CCR-2026-0039 --reviewer "platform-owner, fluid-telegram-owner, key-cape-owner (founder Bernd Worsch)" --comment "Approve ops-mason plan fluid-telegram-operator-credential-lane (spec 41a0ca27): four-entry matrix at coulomb/fluid-telegram/hall-of-helix, OIDC role on netkingdom, agent denies." \ + && python3 scripts/credential-change.py confirm-binding CCR-2026-0039 --reviewer founder --comment "groups=[fluid-telegram-operators] (LLDAP, member tegwick) and /assurance/level=aal2 match key-cape b2ed890f." \ + && $W python3 scripts/credential-change.py applier-apply CCR-2026-0039 --confirm "DELEGATED APPLY CCR-2026-0039" --actor founder --record-state-hub --quiet +# 3. custody move, then duplicate retirement +$W python3 scripts/fluid_telegram_custody_move.py --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move.json +$W python3 scripts/kv_duplicate_retire.py --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire.json +``` + +2026-10-09 (T03 founder session): CCR-2026-0039 applied at 10:30Z; readback +matched for the 8 boundary denies, policy and role. Custody move `moved`: all +four entries copied at coulomb v1 (operator-session from infotech v4) and the +infotech entries metadata-deleted. Duplicate +`activity-core/default/llm-connect-provider-secrets` retired; its first dry-run +refused on mount-wide `platform/metadata/*` survey grants, after which the check +was narrowed to data-path grants (`64ae594`). Receipts: +`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +2026-10-03 (CUST-WP-0075): gate check. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named in the design is open. It is not the last one: the design says to confirm the exact live client registration and protected client-side custody before writing, and positive-login proof needs a real KeyCape service JWT. KeyCape's contract (`openbao-service-auth-contract.md`) and KEY-WP-0009 claim source registration only; the live registration of `secrets-engine-openbao` and its client-credential custody are "a separate approved custody action" that no workplan task owns yet (SECRETS-WP-0008-T06 waits on this task). Re-qualified with `blocked_on: message-from:key-cape`; key-cape was asked for the owning task id, which will replace it as `depends_on`. The design stays proposed and no child command was written. Not approvable in D1 yet. + +2026-10-04: Founder authorized the prepared coordination request. Sent +`b4fc62ea-f92c-4410-919a-9f3cce2d406b` to key-cape on preparation thread +`f84637fa-2355-4971-a2dc-7f1fd01710a8`, referencing platform source +`6b91d510395215d178d60ee8884e7fc00930a0cf`. Requested actual registration and +protected-custody owning tasks/status/revisions and non-secret receipts. Source +registration is not live custody; no value fetch or live registration was +requested. T02 remains waiting on the owner return and separate execution gates. + +2026-10-04 blocked-task review: KeyCape returns 58826056/eb20a78c now identify +KEY-WP-0037-T02/T03/T04, replacing the unowned-registration wait with real +dependencies. Prepared proposed CCR-2026-0033 and exact-path issuer policy/auth, +sso-only ESO and evidence checklist from the returned candidate coordinates. +No issuer/consumer value, registration or native issuance is supplied by them. +secrets-engine must return independent source acceptance of consumer host/path, +protected delivery and rotation/revocation ownership; awaiting that source phase +does not depend on its full live service-login task. KeyCape's exact-primary sync +remains pending its scoped historical identity repair. Requirements and acceptance +boundaries: `docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`. +This workplan was already blocked and remains blocked on its open owner/live gates. + +2026-10-06: secrets-engine returned consumer custody source acceptance +(message 680136e2, SECRETS-WP-0012, commit a3897c2). CCR-2026-0033 finalized as +**proposed**: KV path corrected to `platform/workloads/keycape/secrets-engine-openbao` +(applier scope), consumer copy coordinates with D1-D4 pending founder choice, +rotation/revocation ownership, live order and rollback. Attended custody child +`scripts/keycape_secrets_engine_openbao_custody.py` with fake-only tests +(`tests/test_keycape_secrets_engine_openbao_custody.py`) refuses without an exact +founder decision id recorded in the approved CCR. Nothing executed, generated or +applied; nothing added to active GitOps. The founder approval it needs is T09. + +2026-10-09: KEY-WP-0037 finished 2026-10-07 (registration live, issuance +verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Source for this +lane is now complete as **CCR-2026-0038** (proposed, +`credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml`). +The delegated applier gained a narrow `service-jwt-login` request type +(`scripts/service_jwt_lane.py`): auth mount fixed to `keycape-services`, policy +must equal the generated login-self policy, role/config keys allow-listed, +TTLs at most 15m, uses 1..16, `token_no_default_policy`, refusal if the mount +exists with another type, and a value-free readback compare after the writes. +Policy `secrets-engine-login-self` now also carries explicit `deny` on +`platform/{data,metadata}/workloads/keycape/secrets-engine-openbao` so +ops-mason invariant (ii) (no capability on the client-secret path) holds even +if identity groups were ever attached. Tests: `tests/test_service_jwt_lane.py` +(8) plus the updated contract test; full suite unchanged apart from 5 +pre-existing failures unrelated to this lane. + +Founder apply (one line; approval, binding confirmation and silent apply): + +```bash +cd /home/worsch/railiance-platform && python3 scripts/credential-change.py approve CCR-2026-0038 --reviewer "platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd Worsch)" --comment "Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self (self endpoints + deny on the client-secret path)." && python3 scripts/credential-change.py confirm-binding CCR-2026-0038 --reviewer founder --comment "Bound claims match KeyCape registration: aud secrets-engine-openbao, sub service:secrets-engine, principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social RS256." && warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/credential-change.py applier-apply CCR-2026-0038 --confirm "DELEGATED APPLY CCR-2026-0038" --actor founder --record-state-hub --quiet +``` + +Done after that: login proof with a real KeyCape service JWT +(SECRETS-WP-0012-T03 probe-openbao; policies exactly +[secrets-engine-login-self], capabilities-self deny on the guarded paths, +revoke-self), negative claim checks, then publish the consumer contract file +and ops-mason MASON-WP-0009-T05 rechecks invariant (ii). + +## Implement the platform operator-write CCR contract and Fluid lane + +```task +id: RPF-WP-0035-T03 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +blocking_reason: "Founder session done 2026-10-09; waits on ops-mason verification (MASON-WP-0005-T05) and the FT-WP-0002 owner salt CAS probe." +priority: high +depends_on: [MASON-WP-0005-T05, FT-WP-0002] +state_hub_task_id: "f47e5bc5-6f3c-54bb-aa35-260ad03892ba" +``` + +2026-10-11: requalified — founder part done; remaining waits are owner tasks. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0033-T02. Design: +`docs/credential-lane-designs/fluid-telegram-operator-kv.md`. + +Platform owns the per-path capability schema/validator, exact OpenBao policy +and accepted custody coordinates. MASON-WP-0005 owns construction coordination +and engine integration; KeyCape/NetKingdom own OIDC/MFA and group membership; +FT-WP-0002 owns client CAS, prefix correction, output containment and Telegram +application acceptance. Retain the existing read-only CCR semantics. + +**Unblock:** accept tenant/path and per-entry field/capability matrix; confirm +actual group/assurance and callbacks, reviewed construction contract and writer +authority. Contract review can proceed without a live credential; the final +schema cannot be treated as accepted solely because a draft exists. + +**Done when:** validation rejects broad/unsupported grants, the consumer proves +CAS=0 first-write behavior and no value output, approved identities can perform +only the exact matrix, negative/expiry/revocation checks pass, custody is seeded +through the separate writer, and the verified route has a safe handoff receipt. +The unattended adapter remains a separate demand and gets no operator session. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Accept the needed signing lane and deliver it to the owning runtime + +```task +id: RPF-WP-0035-T04 +status: done +priority: medium +state_hub_task_id: "35a85846-61d5-54ce-8b18-ede45733d53c" +``` + +Supersedes RPF-WP-0034-T02. Design: +`docs/credential-lane-designs/state-hub-preflight-signing.md`. + +Platform owns signing-key custody, exact read policy/role and scoped delivery +acceptance. State Hub owns API chart/env wiring, all-replica rotation fencing +and health. FLEX-WP-0020-T05 owns the rename preflight/cutover dependency; +STATE-WP-0085-T09's adoption-plan delivery is already complete. + +**Unblock:** State Hub/repo-manager and the consuming migration owner confirm +that this transitional State Hub lane is still needed during retirement; +record the target runtime, namespace/SA/auth audience and an executable +rotation fence, plus approved writer and deployment window. Do not broaden the +lane into a general repository-rename authority or provision for a stale demand. + +**Done when:** protected one-time generation, API-only ESO delivery, negative +access checks and a non-mutating signed preflight pass; every API replica uses +the accepted version; rotation/invalidation and recovery are evidenced. No +repository rename is part of S3 lane acceptance. If demand is withdrawn, record +the owning decision and cancel this task explicitly rather than provision it. + +2026-09-05 continuation: verified the live primary cluster identity and healthy +single API replica; the signing ExternalSecret is still absent. Added a writer +guard against wrong-cluster kubeconfigs before any OpenBao access. The default +workstation kubeconfig's local port-forward listener was unavailable. Activation +still needs the contained attended OIDC/MFA login and the acceptance evidence +above; source preparation is not live completion. See +`history/2026-09-05-preflight-signing-activation-readiness.md`. + + +Completed 2026-09-05: user-led attended activation generated version 1 and +rotated to version 2 with every API replica stopped. Exact access and negative +identity checks passed; ESO delivery and API-only exposure passed; the recovered +single API replica accepts new signed preflight and rejects its predecessor by +signature, with healthy primary identity and no preflight blockers. State Hub +chart commit `49e3182`, Helm revision 59. No repository rename executed. +Evidence: `docs/evidence/RPF-WP-0035-T04-signing-activation-2026-09-05.json`; +closure: `history/2026-09-05-preflight-signing-activation-complete.md`. + +## Admit KeyCape approval-engine client custody and delivery + +```task +id: RPF-WP-0035-T05 +status: done +needs_human: false +intervention_note: "" +priority: high +state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c" +``` + +Answers KEY-WP-0013-T02 (State Hub message +`278a3ebe-b529-49f6-bd1a-e3ebcf318260`). Admission: +`docs/credential-lane-designs/keycape-approval-clients.md`; requests +`CCR-2026-0017` (secrets-engine-approval) and `CCR-2026-0018` +(approval-engine-operator). + +Platform owns the two custody paths, exact-path read policies, Kubernetes auth +roles and the KeyCape-side ESO delivery. KeyCape owns the client registrations, +issuance, claim set and disablement; approval-engine owns approval semantics and +audit of emitted actions. + +2026-09-08 admission response: both proposed KV paths confirmed unchanged; field +`client_secret` corrected to `CLIENT_SECRET` for the uppercase KV convention and +CCR validator. Kubernetes delivery references confirmed against the live `sso` +namespace, which already resolves `KEYCAPE_RAPP_QONTO_CLIENT_SECRET` through the +same `secretKeyRef{key: client-secret}` shape on image `main-153258b`. Attended +authority named as the governed `openbao-platform-admin-login` lane +(`founder_required`); KeyCape's refusal to treat its generic `warden plan` +database match as authorization was correct. Rollout agreed as one attended +session with the KeyCape reading build pinned but undeployed, ordered after the +Authelia issuer precondition in message `c8b1ad10-dae8-48fb-a0ea-7e2a101c54bf`. +Policies, ClusterSecretStores and ExternalSecrets are written and validated, +none applied. + +**Unblock:** owner approval of both CCRs, a KeyCape image that reads both +environment names, the settled Authelia `iss` pin, and a founder-attended window +date. Verifier-side custody only — no client-side read lane is admitted, and no +scope beyond the two declared sets. + +**Done when:** both CCRs are approved, the attended window seeds both KV paths +with CAS=0, policies/roles/stores/ExternalSecrets apply and sync, the KeyCape +build resolves both environment names, KeyCape evidences live JWKS signature and +exact claim bindings with excess scopes denied (operator `consume`, human +`consume`), platform evidences cross-path/wrong-identity/out-of-namespace denial, +and every receipt is metadata-only. If either registration is abandoned, KeyCape +disables it before the KV version is destroyed. + +### 2026-09-08 actual upstream issuer returned + +The admitted KeyCape one-shot probe verified the actual signed upstream issuer +as **`https://auth.coulomb.social`** at 21:44:44 UTC. Signature, audience, +validity window and nonce checks passed and the pinned Job exited 0. All +five temporary resources and the Pod were removed; normal KeyCape Deployment +and config Secret metadata are unchanged. See +`docs/evidence/2026-09-08-keycape-upstream-issuer-proof.json`. + +T05's unknown-issuer input is resolved. The configuration owner still ensures +`authelia.issuer` equals that exact HTTPS value before the custody window. +Both CCRs remain proposed and await the named reviews; this probe grants no +custody mutation or client-side read. Keep the current authority preflight and +this signed-token proof as separate receipts. Live ESO/client/approval and +separate audit/client-side custody acceptance remain open. + + +2026-09-09 configuration and review-queue return: NetKingdom pinned the verified +HTTPS issuer, using an atomic UID/resourceVersion test and independent readback. +Secret revision `58713343`; unrelated configuration and signing key unchanged; +no Deployment rollout. Receipt: `docs/evidence/2026-09-09-keycape-upstream-issuer-pin.json`. + +The two existing CCRs remain proposed. They now link to concrete pending review +decisions, with platform-operator and key-cape-owner named explicitly. See +`docs/credential-lane-designs/keycape-approval-clients-review.md`. T05 owns this +human dependency; HFACT consumes it without a duplicate approval request. +Custody/ESO activation, client verification and the separate client-side/audit +lanes remain open. Current CLI apply plans refuse the proposed requests. + + +2026-09-09 admission: the user explicitly approved both CCRs in the named +platform-operator and key-cape-owner roles. Both source requests are approved +and both linked Hub decisions are resolved. Receipt: +`docs/evidence/2026-09-09-keycape-approval-admission.json`. The completed review +intervention is cleared; T05 is progress while the contained first-provision +procedure is exercised and the admitted attended rollout is carried through. +Verifier-side scope, separate client-side/audit lanes and live acceptance remain +as defined in the reviewed requests. + +2026-09-09 verifier-side return: both CCRs are verified after recorded user approval, +CAS=0 version-1 custody, native read/auth denials and revocation, Valid stores, +SecretSynced delivery, compatible KeyCape rollout and live positive/negative +service checks. Existing human OpenBao login passed again on the new image. +Receipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. Failed attempts restored the compatible +configuration/image and detached delivery; final resume reused version 1. + +T05 is done against its verifier-only acceptance criteria. Its former +"remains progress for client-side reads" statement expanded the task past its +reviewed scope; that residual now has the live owner task RPF-WP-0035-T06 below. +Neither Warden fetch selector is resolvable through these verifier-only CCRs. +Do not re-request the completed two named reviews or reseed these paths. +Rotation is a distinct, version-guarded operation. + +## Dispose of the ungoverned whynot-design npm duplicate + +```task +id: RPF-WP-0035-T07 +status: wait +decision_id: 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa +blocking_reason: "Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish." +priority: high +depends_on: [SECRETS-WP-0006-T06] +state_hub_task_id: "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b" +``` + +2026-10-11: requalified after founder decision D3 (trust root, build-mode default) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Found by the attended session on 2026-09-10 while settling the npm field +question. `secret/coulomb/whynot-design/npm/publish` exists at version 1, +created 2026-07-03T15:00:44Z and never updated — five days after the governed +lane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified +(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and +outside any CCR here. Receipt: +`docs/evidence/2026-09-10-npm-lane-field-resolution.json`. + +Only metadata was read. Its field names were not enumerated, its value was not +read, and nothing was deleted — a location holding real credential material is +disposed of deliberately, not tidied away in the session that found it. + +The likely explanation, unconfirmed: secrets-engine reports the lane's field +under a lowercase name that is absent from the governed path, and their catalog +declares this legacy location. If their proven pilot publish read from here, +then a working production lane has been running off an ungoverned duplicate, +and the governed lane's acceptance evidence describes a path the consumer does +not use. That is worth establishing before anything is removed. + +**Operator decision, 2026-09-15:** destroy the legacy path after confirming the +governed lane is the live consumer. Do not wrap `secret/coulomb/whynot-design/npm/publish` +in a CCR. Value remains unread. Platform will ask secrets-engine which path +publish actually reads before any attended destroy. + +**Unblock:** admit the governed exact-path AppRole policy and coordinated catalog +path/field migration under SECRETS-WP-0006-T06; prove native delivery from the +governed lane before the attended legacy destroy. secrets-engine confirmed the +legacy source path on 2026-09-21 (message `355424d4-17ab-435e-9e1d-6921775cb4a2`). +No comparison of values, fingerprints, lengths or shapes is needed or authorized. + +**Done when:** the legacy path's provenance and consumer are established, the +governed lane is confirmed as the one in use or the consumer is moved to it as a +reviewed lane change, the duplicate is destroyed under the September 15 operator decision and the +disposition is recorded. Do not bring the legacy duplicate under a CCR. If the value proves to be live and +ungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027: +never record the value, fingerprint, length or shape. + +2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here. + +## Admit the separate approval client-side readers + +```task +id: RPF-WP-0035-T06 +status: done +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +priority: high +intervention_note: "" +state_hub_task_id: "68bff751-e48b-548b-8fb4-dfb3b16210c2" +``` + +2026-10-11: requalified after founder decision D1 (attended window standing rule) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +**Current return, 2026-09-10:** CCR-2026-0020 is cancelled on the requesting +Approval Engine owner's explicit withdrawal, source +`849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md`. +No presenter exists and no reader is wanted. The validator now accepts terminal +cancellation of an incomplete request only with owner/source/reason evidence, +retained declared omissions and a disabled, non-resolvable front door. Apply +remains refused. No live identity, policy, role, custody or verifier was changed. +Human approval follows existing INFD-WP-0001-T07/T08; future service requesters +need a separate narrow registration, not this withdrawn bundle. + +**Operator binding confirmed, 2026-09-14:** The user explicitly selected +`net-kingdom-admins` and authorized applying CCR-2026-0019. Its OIDC role is +`secrets-engine-approval-client-workload-kv-read`, aligned with the platform +applier naming rule; policy and exact KV scope are unchanged. The metadata dry +run passes with no warnings. Attended apply and exact role/policy readback passed; the enclosing Warden +command exited successfully after its self-revocation/cleanup. Receipt: +`docs/evidence/2026-09-14-ccr0019-operator-binding.json`. Scoped delivery proof +remains pending; the front door stays non-resolvable. Completed CCR-2026-0017/0018 +remain closed and T06 stays `wait`. + +Consumer procedure returned in source, 2026-09-10: +`secrets-engine@98d72ceb1dbcff2d2a80fb8c3058d76777a0ac93:docs/approval-service-auth.md` +specifies the requested private 0700 runtime directory, 0600 file outside Git, +path-only use, claim/consume lifetime and attended cleanup including hard-stop +residual inspection. CCR-2026-0019 retains this source-review comment without +changing admission status. Exact group, required-owner review, attended apply and +native positive/negative/cleanup evidence remain. No role or credential changed. + +Separate retained owner decision: KeyCape's 2026-09-10 return +`21427688-725f-4dea-aab4-7c78fd4328d2` identifies the already-live, unpresented +CCR-2026-0018 registration. Approval Engine, KeyCape and Platform must explicitly +decide retention/expiry or coordinated disablement. Reader cancellation neither +disables that live registration nor accepts indefinite retention. Keep this +disposition in T06; it is separate from the wanted CCR-2026-0019 factory reader. +No unilateral issuer/config/Secret change is authorized by this closeout. + +**Operator decision, 2026-09-15:** coordinated disablement with KeyCape and +Approval Engine. Platform will not disable the live registration or verifier +delivery unilaterally. T06 stays `wait` until both owners confirm the joint +disablement sequence. + +Residual handoff from RPF-WP-0035-T05; consumes the completed verifier custody +without extending CCR-2026-0017/0018. Owner: railiance-platform with the named +secrets-engine and approval-engine operator consumers. + +Prepare separate exact-reader admissions for existing version-1 paths: +`platform/workloads/secrets-engine/approval-client` and +`platform/workloads/approval-engine/operator-client`, field `CLIENT_SECRET`. +Name each actual actor/placement, bounded authentication/reader policy, protected +consumer delivery, cleanup/revocation and rollback, then obtain the required +owner reviews for those concrete requests. No reseeding, rotation, shared reader, +reuse of the sso verifier Secret, or implicit operator consume grant. + +2026-09-09 preparation return: both exact-reader admissions are prepared as +`CCR-2026-0019` (secrets-engine) and `CCR-2026-0020` (approval-engine-operator), +with their exact-path read policies written and committed. Design: +`docs/credential-lane-designs/keycape-approval-client-side-readers.md`. Both +reuse existing version-1 custody; no reseed, rotation, shared reader or verifier +Secret reuse. Both are `in_flight` and unapproved; nothing is applied. + +Read-only survey findings that decided the two shapes. Namespace +`secrets-engine` holds only ServiceAccount `secrets-engine` with no workload, +and `flex-auth/flex-auth-secrets-engine` is that consumer's PDP, not the +service; secrets-engine consumes the client secret through an operator-run CLI +reading `SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE` (SECRETS-WP-0009-T03, +revision `9eb07fd`). So reader 1 is an attended operator-workstation OIDC lane, +not an ESO lane. approval-engine has no namespace, workload or Service; its +manifest is unapplied, and no owner source names who presents the operator +client — approval-engine verifies these tokens and never holds them. + +**Unblock:** reader 1 needs the exact NetKingdom/KeyCape group claim for the +authorized operator, plus secrets-engine confirming the file mode and removal +step; `openbao.auth` is declared missing rather than filled with a placeholder +that would later read as a confirmed binding. Reader 2 needs its owner to name +the presenting actor and placement, or to record that no client-side reader is +wanted so the request is cancelled. Naming a reader for the widest approval +scope without that decision is the failure this task exists to avoid. + +**Done when:** each reader has a named actor and placement, a completed and +reviewed auth binding, admitted delivery, and its owner approvals; positive and +negative checks pass, including cross-path, wrong-identity and parent-list +denial and operator `consume` denial; or the request is explicitly cancelled by +its owner. Rotation stays a distinct version-guarded operation shared with +CCR-2026-0017/0018. + + +Consumer input supplied 2026-09-09: secrets-engine now implements per-request +`secrets-engine-approval` exchange from a protected temporary client-secret file, +with exact approval-engine / tenant:platform / read-or-consume scope, no token +file and no fallback. The pinned KeyCape image and actual Approval Engine source +passed its disposable component exercise; only the PDP was a sequencing double. +See `secrets-engine/docs/approval-service-auth.md` and the metadata receipt +`secrets-engine/docs/evidence/2026-09-09-approval-identity-exercise.json`. + +Routing check: `warden route show keycape-secrets-engine-approval-client` is +unknown; generic `openbao-api-key` routes ownership only and is not a delegable +lane. Do not advertise a working fetch command before this task supplies its +own accepted native delivery return. Client-side admission is not ready for a +new human decision until exact requests and contained execution/rollback checks +are reviewable; the completed verifier reviews must not recur in that queue. + +**Done when:** each retained consumer admission is approved and implemented, or +its requesting owner explicitly cancels it (CCR-2026-0020 now satisfies that branch); +actual consumer authentication/delivery succeeds; sibling/listing/wrong-reader +and scope refusals plus reader expiry/revocation/cleanup are evidenced; version-1 +custody and verifier availability remain intact. Return the source and metadata +receipts to HFACT-WP-0001-T03, SECRETS-WP-0009-T03 and APPROVAL-WP-0002-T01/T05. +Audit receiver/sender custody remains AUDIT-WP-0009-T09 and must not be folded +into this client-identity grant. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Admit the two factory audit-sender custody lanes + +```task +id: RPF-WP-0035-T08 +status: wait +decision_id: "ab85ae8a-12a0-4945-ae64-1d3d86d5b26f" +blocking_reason: "Approved conditionally (ab85ae8a, standing change rule): executes once independent archive readback and the interim bearer revocation receipt exist; owner work with audit-core." +priority: high +assignee: railiance-platform +intervention_note: null +blocked_on: message-from:audit-core +state_hub_task_id: "0ef52c26-2669-5cd1-8149-b1f6fcdda6cb" +``` + +2026-10-11: requalified — ab85ae8a resolved under the standing build-mode change rule. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +2026-10-03 correction (CUST-WP-0075, informed-decision sitting draft `55fb078`): the D1 routing was wrong. First provision and delivery already ran on 2026-09-11, with seed and delivery receipts, and the review packet says not to repeat them. The task is not a provisioning-window act. It was taken off decision D1, and its blocking_reason now names what actually remains. railiance-platform should re-qualify it further if the receiver rollout has since happened. + +2026-10-03 (CUST-WP-0075): re-qualified. The receiver rollout already happened: Audit Core c82e0442de0f carries evidence_kind and native producer accepted/duplicate and scope/read-refusal checks passed 2026-09-11 10:42 UTC (`docs/credential-lane-designs/factory-audit-senders-review.md`, `factory-native-acceptance.md`). Remaining: independent archive readback and audit bearer-revocation acceptance. Still not a provisioning-window act. + +Consume AUDIT-WP-0009-T09/T11's exact declarations for approval-engine and +informed-decision: tenant:platform, write-only, load-bearing, redact. Source +preparation supplies two approved CCRs, independent exact-path policies/ESO +projections, and the attended `factory_audit_custody.py` first-provision helper. +Its CAS and request-provenance checks preserve unrelated senders and recover +interrupted writes without generating replacements. The user approved all named review roles on 2026-09-11. Native +provision/delivery/receiver-ingestion acceptance remains open. + +The 2026-09-11 native read-only check found an additional deployment dependency: +receiver image c2fe39a is 1/1 Ready but does not support evidence_kind. The +synthetic native probe now refuses before any credential read. Current receiver +source passes. AUDIT T09/T11 retain compatible release/source-manifest rollout; +Approval Engine's missing namespace remains its owner prerequisite. + +[Review packet](../docs/credential-lane-designs/factory-audit-senders-review.md). +[Preparation evidence](../docs/evidence/2026-09-11-factory-audit-custody.json). +Do not fold these senders into CCR-2026-0019 or the cancelled CCR-2026-0020. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Dependency review — 2026-09-06 + +### 2026-09-09 tenant question resolved — no change needed + +The `tenant:coulomb` / `tenant:platform` discrepancy raised against T02 is not a +discrepancy. KeyCape confirms decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6` +binds the *approval chain* to the landlord zone and was applied to exactly two +registrations, `secrets-engine-approval` and `approval-engine-operator`. +`codex-railiance-platform` is not in that chain and correctly stays +`tenant:coulomb`, as do `secrets-engine-openbao` and the human directory default. +KEY-WP-0013-T04 records this and their +`TestServiceRegistrationTenantsAreExactPerDecision` pins every reviewed client's +tenant against the real fixture, so a reintroduced alias fails their build. + +`docs/credential-lane-designs/secrets-engine-service-jwt.md` already says +`tenant:coulomb` and is therefore correct as written. Bind the exact role to +`tenant:coulomb`. Do not "correct" it to `tenant:platform` later; that would +break the issued claim. + +SECRETS-WP-0008-T02 now records the local PIP claim/validation join implemented +and tested. Its remaining gate is the unreachable approval-engine claim endpoint +and access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old local +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 ` 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. + +### Sender approval recorded — 2026-09-11 + +The user replied "good, go on" to the explicit CCR-2026-0021/0022 question naming +platform-operator, audit-core-owner and both producer owners. Both exact requests +are approved; their existing State Hub decisions are resolved. This clears the +review request only. Receiver rollout, namespace readiness, attended custody and +positive/negative native evidence remain the execution gates. + +### Native receiver and attended execution return — 2026-09-11 + +Audit Core c82e0442de0f is deployed and passes the native synthetic contract. +Its existing 32-event chain/head is unchanged. The owner Approval Engine +namespace now exists and all four ESO objects pass strict server dry-run. +The two exact ingress rules are applied; sender custody/ESO application is not. + +Warden selected founder_required/oidc_login and attempted the reviewed silent +seed command through the contained wrapper. Login failed before command +handoff; no custody receipt was created. Warden could not confirm remote +session revocation. Await operator browser/MFA feedback and login/session +resolution. Approvals remain valid; T08 waits for the identity act, not review. + +The receiver check now selects component=receiver, so retained attestation-job +pods cannot falsely block a stable receiver. Eighteen custody tests pass. +[Native return](../docs/evidence/2026-09-11-factory-receiver-live.json). + +### Attended custody retry succeeded — 2026-09-11 + +The user requested a retry and completed the attended identity act. Both CCRs +are applied: independent version-1 custody and registry CAS 7→8 succeeded, +preserving other senders/fields. Warden exited 0 with self-revocation confirmed +for this session. This does not retrospectively attest the earlier failed +login's remote session state. The old login wait is cleared; T08 is progress +for ESO delivery, exact native reader/namespace refusals, receiver reload and +producer acceptance. No token is reseeded or rotated on continuation. +[Seed receipt](../docs/evidence/2026-09-11-factory-audit-sender-seed.json). + +### Delivery prepared; fresh login did not hand off — 2026-09-11 + +The delivery helper and custody receipt are committed at `44314ca` and exactly +projected on primary/railiance01. Seven delivery tests and 18 custody tests +(including 11 actual disposable OpenBao cases) pass. The fresh attended +delivery invocation exited 5 before command handoff; no native delivery +receipt exists, no ESO application or receiver restart ran. The receiver +remains 1/1 Ready on c82e0442de0f. Warden could not confirm revocation for this +failed login; that is separate from the successful seed session. T08 now waits +for this delivery identity act. Neither CCR review nor first provision reopens. + +[Delivery return](../docs/evidence/2026-09-11-factory-audit-delivery-login.json). +Use the reviewed delivery command with a new receipt after login feedback. +Actual producer ingestion/duplicate/refusal and bearer revocation acceptance +remain open under AUDIT-WP-0009-T09/T11. + +### Native delivery accepted — 2026-09-11 08:27 UTC + +The user returned and requested another login attempt. It succeeded and the +reviewed delivery command completed in 28 seconds. Both native ESO readers +passed exact-path access and explicit sibling/registry/metadata/listing denials, +wrong-SA/namespace refusal and the coding-agent deny check. Each 900-second +reader session was revoked and lookup refusal verified. Both intended +ExternalSecrets are Ready; exact producer value and ESO ownership match. The +disallowed namespace produced an explicit store restriction and no Secret; +the uniquely owned namespace is now absent. + +Registry version 8 matches the delivered receiver JSON. Audit Core reloaded +and remains 1/1 Ready on c82e0442de0f; /readyz reports operational/durable with +tamper_evidence=false, as bounded by AUDIT-WP-0009-T12. Warden exited 0 and +confirmed self-revocation for this successful session. Earlier failed login +receipts remain historical and are not retroactively attested. + +The login wait is cleared. T08 remains progress and CCR21/22 remain applied +for native producer ingestion/duplicate/scope/read-refusal and bearer +revocation acceptance under AUDIT T09/T11. No credentials were reseeded or +rotated. No producer was deployed and no factory attempt or paid call ran. +[Native delivery receipt](../docs/evidence/2026-09-11-factory-audit-delivery-live.json). + +### Native producer return — 2026-09-11 10:42 UTC + +Both actual source adapters used their own ESO-delivered credential inside a +bounded native Job. Each synthetic event received 202, retained its durable +outbox after an injected lost receipt, and received duplicate 200 after a fresh +process reopened the outbox. Each source's reconciliation reported exactly one +record for its unique probe class. Wrong source/tenant, seven archive read +routes, sibling reconciliation and invalid-bearer requests were refused. + +The first Informed Decision probe exposed a private-store startup defect: +fsGroup volumes add inherited setgid to a newly created 0700 directory. +Informed Decision `1a12223` corrects creation without repairing unsafe existing +data. The regression failed before the fix; the available suite now passes +335 tests with 39 optional checks skipped. Native retry verifies the exact +corrected helper. Six probe tests and eleven rebuilt-container checks pass, +including actual setgid-volume startup, restart/restore and cleanup. + +All temporary probe Jobs, Pods, ConfigMaps and NetworkPolicies are verified +absent. Receiver c82e0442 remains operational/durable; tamper_evidence=false. +Producer verification requires no operator registry read or new OpenBao login. +Independent readback is a separate attended command consuming the successful +receipt; it must not rerun the producer jobs. Both attended verification-login +attempts this session ended before handoff (exit 5; remote revocation +unconfirmed), so independent archive readback remains pending. + +This proves synthetic outbox delivery/recovery with native sender credentials, +not domain-transaction atomicity, deployed producer services or human binding. +An invalid bearer is not a revoked formerly valid bearer. AUDIT T09/T11 and +RPF T08 remain progress for independent readback and audit bearer-revocation +acceptance; CCR21/22 remain applied. Service/policy/human admission and native +runtime/spend gates remain separate. Factory attempts and paid calls remain 0. + +[Native producer receipt](../docs/evidence/2026-09-11-factory-native-producers.json). + + +## Independent audit readback — 2026-09-11 13:11 UTC + +The existing attended readback command completed with exit 0 while the user +was present. Independent read-only identity `operator` found both retained +`factory-audit-20260911104152-94aced` producer events with exact source and +`tenant:platform`; receiver integrity is intact across 36 events. The wrapper +confirmed this session's self-revocation and private-helper cleanup. Prior +failed sessions' unconfirmed revocation remains historical unresolved evidence. + +This supersedes the earlier readback-login wait. No producer jobs were rerun, +no credentials were reseeded and no event was written by the reader. The +inherited zero registry-read count belongs to the producer phase; the attended +reader did consume registry version 8. CCR21/22 stay applied and owner tasks +stay progress pending formerly-valid audit-bearer revocation acceptance. +Service/domain-transaction/human and factory runtime/spend admission remain +separate; factory attempts and paid model calls remain zero. + +Receipt: [native readback](../docs/evidence/2026-09-11-factory-native-readback.json). + + +### T06 native reader acceptance — 2026-09-14 + +The scoped Warden login lane `secrets-engine-approval-client-login` now routes +to the applied OIDC reader and the platform's silent preflight. The installed +Warden package still carries an older catalog; use the explicit source catalog +`WARDEN_ROUTING_CATALOG=/home/worsch/ops-warden/registry/routing/catalog.yaml` +until its next normal installation refresh. This lane authenticates the reader; +it is not a raw secret fetch or retained-file delivery interface. + +Live effective-policy and capability checks passed: only exact data/metadata +read, no sibling secret, parent listing, write or control-plane authority. +A second contained session read existing version 1 into an operator-owned 0600 +file in a private 0700 runtime tmpfs directory. The native consumer exchanged +separate read and consume scopes; Approval Engine verified the read token before +returning 404 for a fresh nonexistent approval, and refused the consume-only +token's read request with 403. No approval was created, bound or consumed. +Both Warden sessions exited 0 after self-revocation/helper cleanup; temporary +credential file and directory were removed. Four refusal/path/redirect tests +pass. Receipts are in platform `docs/evidence/2026-09-14-ccr0019-{reader-preflight,delivery-check}.json`. + +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. + +### 2026-09-27 T02/T07 source follow-up + +T02 now has the exact proposed RS256 configuration, bounded JWT role and +self-only policy in `openbao/`. Operator correction: platform infrastructure +belongs to `tenant:platform`; KeyCape registration and consumer preflight are +corrected together. Existing live registrations must be migrated and verified. +Public discovery confirms issuer/JWKS/token endpoint. Registration/custody, +attended provisioning and live rejection/cleanup evidence remain required; +T02 stays wait. No service credential or backend entitlement was issued. + +T07 consumed the confirmed legacy consumer return. The stale value-comparison +ask is removed. WARDEN-WP-0037-T03's no-rotation hold stays in force until the +governed native migration is evidenced. Legacy destruction follows migration; +neither source reconciliation nor the historical pilot is that evidence. + +## Loose-end review — 2026-09-27 + +T08 now explicitly waits for formerly-valid audit-bearer revocation acceptance from AUDIT-WP-0009-T09/T11. Native delivery, producer checks and independent readback already passed; do not reopen login, seed or review gates. T02/T03/T06/T07 retain their latest exact service registration, signed-in human acceptance, owner delivery/disposition and governed-consumer migration dependencies. No credential value was read or changed. + +## Founder approval of the CCR-2026-0033 custody child + +```task +id: RPF-WP-0035-T09 +status: done +needs_human: false +priority: high +decision_id: 2ab717e1-7881-491e-aed4-28946550c289 +depends_on: [] +state_hub_task_id: "7c753be6-42f1-58a6-a4a4-a7ed686f461f" +``` + +Packets: `credential-change-requests/CCR-2026-0033.yaml` (custody child, KV +metadata, issuer ESO reader, live_order, rollback) and `CCR-2026-0034.yaml` +(attended operator OIDC reader, in-memory, 5m/4 uses). Revised 2026-10-06 per +founder direction; the consumer file is removed. Exact founder commands: +`docs/provisioning-windows/2026-10-04-1000/keycape/founder-runbook.md`. Live +order: custody child → platform applies policies/roles/ESO (Secret +sso/keycape-secrets-engine-openbao-client exists) → NetKingdom env patch +(NK-WP-0046) → KeyCape registration merge (KEY-WP-0037-T03) → KeyCape restart +immediately → live issuance check (KEY-WP-0037-T04) → OpenBao JWT role/login +proof (RPF-WP-0035-T02). Each live step after the custody run needs its own go. + + +2026-10-11 evidence reconciliation: T09's approval obligation is complete. +Authoritative founder decision 2ab717e1-7881-491e-aed4-28946550c289 is resolved, +decided by Bernd Worsch at2026-10-06T13:07:18.627943Z, and explicitly covers +A1 design, A2 CCR33/CCR34 plus owner reviews/bound claims, and A3 one custody run. +The approval comments in both CCRs record those exact grants; both source records +are applied. MASON-WP-0009-T02/T03 additionally record the October8 approval/owner-delivery +reconciliation and reference KeyCape +`docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`. Closing this approval task clears +its obsolete human gate. It grants no new run, credential access, rotation or +service execution: RPF35T02/T12, MASON9T05 and SECRETS8T06 retain their actual +native/adoption obligations. Historical per-step exclusions remain above. + +## Retire the approval-engine-operator client delivery and custody (CCR-2026-0018) + +```task +id: RPF-WP-0035-T10 +status: wait +priority: medium +blocked_on: message-from:approval-engine +blocking_reason: "Blue lane under the standing change rule (removing access, with reviewed order, rollback and receipts): executes once approval-engine confirms there is no presenter. No founder window needed." +state_hub_task_id: "af2d4dba-f83a-5819-9a8b-671bae799364" +``` + +2026-10-11: access removal is blue lane (canon build-mode-change-authorization_v0.1); no founder window. + +key-cape proposed a joint disablement on 2026-10-10 (message `7f2128fb`). +Precondition: approval-engine reconfirms there is no presenter. The order is the +reverse of provisioning, so KeyCape never starts with a client whose secret is +missing. key-cape removes the registration and restarts (1), checks that +`invalid_client` is returned (2), and net-kingdom removes +`KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET` from Deployment `sso/keycape` +(3). Platform steps, amended from the proposal: + +4. **Delivery.** In one commit, remove ExternalSecret + `sso/keycape-approval-engine-operator-client` from + `argocd/platform-addons/openbao-secretstore/keycape-approval-clients.externalsecrets.yaml` + and ClusterSecretStore `openbao-keycape-approval-engine-operator` from + `openbao-keycape-approval-clients.clustersecretstore.yaml`. Keep the + secrets-engine-approval objects. Then bump `targetRevision` of + `argocd/railiance01/applications/openbao-secretstore.application.yaml`. + The app is pinned and has no automated sync, so nothing changes live until + an attended `argocd app sync openbao-secretstore --prune` runs after step 3. + Verify, value-free, that the ExternalSecret, the store and Secret + `sso/keycape-approval-engine-operator-client` are gone. The target is + `creationPolicy: Owner` and `deletionPolicy: Retain`, so the Secret should + follow its owner; delete it explicitly if it does not. Then delete OpenBao + role `auth/kubernetes/role/external-secrets-keycape-approval-engine-operator` + and policy `workload-kv-read-keycape-approval-engine-operator`, and remove + their source files. Also remove policy + `workload-kv-read-approval-engine-operator-client` (CCR-2026-0020, cancelled) + if it exists live. +5. **Custody.** Run the metadata delete of + `platform/workloads/approval-engine/operator-client`, the destruction + foreseen in `docs/credential-lane-designs/keycape-approval-clients.md`. A + disabled client's secret has no recovery value; a narrowed successor gets a + fresh secret through the mint-secret lane at `platform/workloads/keycape/`. + Only after step 2's `invalid_client` receipt. Keep the agent boundary denies + for that path until the delete is verified, then drop them. + +2026-10-10: key-cape agreed the amended steps 4 and 5 (message `59304e33`, +KEY-WP-0013 c528daa). Waits on approval-engine confirming there is no presenter, +and on the founder's window. + +The manifest edits wait for the scheduled window, so a stray `targetRevision` +bump cannot remove KeyCape's secret before step 3. + + +## Complete independent service-JWT source preparation and execution design + +```task +id: RPF-WP-0035-T11 +status: done +priority: high +state_hub_task_id: "7952c8cd-c066-5b72-a025-78d24341c1ab" +``` + +2026-10-11: Platform-scoped agent loaded this checkout's AGENTS.md and INTENT, +RPF35-T02, actual CCR38/login contract/typed applier and Secrets Engine's native +claim/PDP/CAS/provider/apply flow. Frozen Secrets v2 manifest and all named staged +bytes/proof were hash-verified. Independent tests reproduced three source +counterexamples while retaining the frozen files: close exception can coexist +with native_verified=true; successful result needs no source/session fingerprints; +HTTP200 mixed errors+data envelope is accepted. Original 37 tests plus the three +counterexample tests pass (40 cases, synthetic/local only). Proposed owner design +`docs/credential-lane-designs/secrets-engine-task-execution-entitlement.md` binds +an explicit metadata-only execute-ccr action, immutable typed owner bodies, +CAS/journal replay control, 120s/12-use owner-held task token, independent payload +validation, native ACL endpoint bounds, revoke/readback and recovery. This completed +preparation record is established before the formal source review. It grants no +live authority and does not close T02 or represent acceptance by another owner. +Formal review artifact follows under this work item; all implementation/live +obligations are retained in T12 and existing T02 rather than a finished residual. + +## Implement and prove the separately approved task execution entitlement + +```task +id: RPF-WP-0035-T12 +status: progress +priority: high +depends_on: [RPF-WP-0035-T11] +state_hub_task_id: "914bf383-c13f-5247-9af0-91d7e3a4784a" +``` + +Review the proposed task-execution-grant schema and exact metadata-only execute-ccr +backend with Secrets Engine/access-engine/approval-engine; implement trusted service +subject and served consume verification, durable one-shot reservation, bounded +owner-held token issuer/middleware and exact source/payload enforcement. Obtain +separate exact founder approval/attendance before provisioning or live actions. +Prove disposable intended result and identity/action/target/body/time/replay/crash/ +cleanup negatives, and return owner-native acceptance. Existing service login policy +and defaults stay unchanged. T02 still owns login/claim/TTL/use/MASON acceptance; +Secrets T06 separately owns dispatcher adoption and steady-state default migration. + + +2026-10-16 T12 wave 5 source preparation: disposable adapter now binds owner +canonical before/after metadata snapshots to existing descriptor hashes, rejects +per-target baseline/readback mismatch, and records readback/verified evidence. +Mediator reports cleanup-confirmed only after independent fixed cleanup receipts. +Complete role metadata and policy name/HCL/version/cas are compared; validated +modification timestamp alone is excluded. This is sequential fixture acceptance, +not aggregate CAS, concurrent-writer exclusion or native production completion. +Role conflict may follow a policy write. Restart refuses dispatch and cannot +recover memory-only token/accessor cleanup handles. T12 remains progress; actual +fresh CCR/catalog/grant, source/trust/caller/policy admission, isolated owner custody, +scoped recovery and attended native acceptance remain explicit prerequisites. + + +2026-10-11 T11 refinement (same source-review trial): the exact Secrets Engine +v3 manifest `6bb05bac74e4939c3e42db2ae95c5f9fb4616bb20cc285811a315c26669ebce1` +and all named bytes/proof were verified and independently re-reviewed. The three +v2 counterexamples are corrected: close exceptions cannot pass through stale true +flags, complete typed source/session/attempted/revoke evidence is required, and +mixed HTTP200 errors/data fails closed. 49 maker/current-provider tests plus three +independent regressions passed (52, synthetic/local only). Platform source review +`docs/reviews/2026-10-11-secrets-service-jwt-v3-platform-review.json` approves only +the corrected boundary verifier and truthful packet. Prior changes-requested v2 +review is retained; this is not a second native success or changed authority. +No native or founder go is granted. T02, T12 and Secrets T06 remain open; the +metadata-only execute-ccr pilot is explicitly insufficient for generic lifecycle +adoption. All consume-verification/journal/action/body/backend implementation and +native acceptance gates remain real prerequisites, not architecture promises. + + +2026-10-11 T11 readiness refinement: independently reviewed frozen consumer +manifest `709b9dddd1c8f00a995b1ff14264323fbe080ed95df244270ce9607528878fa7`. +Platform source review `docs/reviews/2026-10-11-secrets-execution-readiness-v2-platform-review.json` +approves the local fail-closed guard and proposed consumer contract direction only. +All ten current protected backend handlers pass provider args through readiness +before authorization/consume; session revoke checks before handle reads. Configured +auto/explicit service-jwt therefore cannot burn a protected-action approval or +open the insufficient login-self backend. Explicit env/bootstrap and self-only +probes retain their existing contracts; local compromise/reactivate and disabled +destroy remain separate. Existing ambient-token route readiness reads are unchanged, +not claimed governed by this guard. 58 isolated tests passed: original36 plus20 +provider/action cases, handler enumeration and actual session-revoke ordering. +Prior v2 changes-requested and v3 boundary source reviews remain unchanged, same +T11 trial. No runtime grant, native acceptance, new Access/Approval semantics, +backend entitlement or full Lifecycle adoption is approved. T02/T12/SecretsT06 and +WP13 implementation/native gates remain open; the metadata pilot substitutes for +none of the ordinary generic lifecycle outcomes. + + +## Complete independent KEY39 v4 lifecycle source review preparation + +```task +id: RPF-WP-0035-T13 +status: done +priority: high +state_hub_task_id: "8f6966fa-6e9a-58b2-8b40-c47340ec19d1" +``` + +2026-10-11: Platform agent loaded its owner instructions/INTENT and RPF35-T02, +actual applied CCR38, exact native role/policy source and frozen KEY39 lifecycle +v4 manifest `d079f85c47d5c2635e1ee633ea4d1346b1737ce2be9ca273f22a38e620f418d8`. +All staged entry hashes were verified without changing the reviewed inputs. +Source role omits expiration_leeway: its observed actual default must be confirmed +natively, with -1→0 and 0→150 normalization preserved as a bounded model. Source +claims and login-only policy are unchanged. The supplied 41 lifecycle tests pass; +five independent cases also pass, including a new exceptional-response-close +elapsed-bound counterexample and four current-leeway normalization checks. +A 10ms HTTP request can take over70ms because exceptional finally response.close +runs outside the hard elapsed timer. Unknown native login is correctly recorded, +but source total elapsed enforcement is incomplete. This completed owner +preparation record exists before the formal exact source review entry. No +credential was requested/read, native action run, owner checkout edited or native +session grant inherited. T02 retains native role/policy/leeway, negative claims, +cleanup acceptance and MASON gates; KEY39 producer handoff and founder attendance +remain prerequisites. Source correction/re-review is required, not a native success. + + +2026-10-11 T13 correction preparation (same trial): exact KEY39 v5 manifest +`d1f997624db46693a7126a6eb6435f6b3a353d5bd67dcc8a539683e4b7147285` +and all entry hashes verified. The v4 exceptional-close finding is addressed: +one 20ms abort is clipped to original remaining time and the nonresettable +aggregate cleanup budget; zero calls after aggregate expiry; failed abort stays +unconfirmed/unknown with signal state restored. 46 supplied lifecycle checks and +five independent regressions pass; the unchanged runner's earlier17 tests remain +valid against identical source SHA. Existing T13 preparation record is retained +before the formal v5 exact source review. V4 changes-requested review and earlier +failed history remain retained, with no native success, inherited grant or scope +promotion. Actual private producer admission, fresh installed role/leeway/policy +observation, authenticated founder window and native refusal/cleanup remain gates. + + +2026-10-11 T11 journal preparation refinement (source-only): independently +inspected frozen root-maker v2 manifest +`341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7`, +verified all input hashes, and ran14 supplied tests plus5 independent checks. +The actual four-process race admits once; a separately forked process exiting +immediately after pending intent leaves durable unknown/nonresumable state. +Private SQLite modes, lock admission and binding/replay protections remain guarded. +Three independent counterexamples show after_call accepts False,0.0 or text'0' +as persisted integer ordinal0, contrary to before_call's exact integer validation. +Completed preparation under this existing done ownerT11 record precedes formal +review; require identical ordinal/call-digest validation before confirmation so +malformed calls cannot clear pending outcome. RPF35-T12 retains caller/PDP/consume +validation, exact body compiler/adapter and owner-private cleanup/recovery after +unknown; this unintegrated primitive proves none of those or full contract/native +acceptance. Inputs/prior reviews are preserved; no privileged/native action occurred. + + +2026-10-11 T11 journal v3 correction preparation (same trial): frozen manifest +`905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d` +verified against every file. Strict after_call integer0..63 and64hex string digest +validation now precedes SQLite confirmation; False,0.0 or text'0' cannot clear +pending external outcome.15 supplied tests plus5 independent regressions pass, +including realfork abrupt exit after durable intent and privatefile checks. +This existing completed ownerT11 refinement precedes the formal corrected-source +review. Prior v2 refusal is retained; no extra success/authority trial is counted. +Acceptance is only unintegrated journal source. Actual caller/PDP/consume validation, +independently compiled body/ordinal plan, restricted adapter, owner-private unknown +cleanup recovery and native/whole-contract adoption remain live RPF35-T12 gates. + + +2026-10-11 T13 node-route source preparation refinement (same trial): exact +successor manifest `23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035` +verified against all entries. Platform Service openbao-ui-gateway8080 and its +nginx /v1 proxy agree with the proposed bounded founder-held node port-forward; +workstation tunnel/DNS assumptions are not reused as node evidence.54 supplied +lifecycle/route checks plus6 independent public-health/abort checks pass, offline. +Initial execute/recovery health pin and repeated pre-create check fail before +native/Secret effects; public-preflight reads neither stdin nor Kubernetes. +Completed ownT13 preparation precedes this fresh exact source review, not reuse +of v5 acknowledgment. Main execute currently reads private stdin before execute's +health gate; the packet's pre-token-input phrase is not accepted. Private producer +handoff must preserve actual ordering or move the health gate before credential +input when implemented. Public cluster digest detects drift, not authenticated +estate identity. No route was opened or observed; no source packet authenticates +a founder approval. Native role/plugin version and raw/effective expiration, +clock-skew and not-before leeways require actual owner observation/semantic proof. +Issuer readiness_state/Argo ownership is not established by the inspected source; +unmapped means production-tier. If adopted/production-approved, temporary direct +CAS requires an explicit reviewed one-use maintenance exception and close-down +entry, plus reconciliation, before native go. No helper/source acknowledgment +waives that gate. Private token producer/callback/client/custody admission and +actual native negative/revoke/restoration/cleanup remain prerequisites. + + +2026-10-11 T13 v7 node-route preparation refinement (same trial): exact frozen +manifest `90aabec336008d7d51e37c04b5ff96ba8ed6630821cca1a4c333d803367247f7` +and all entries verified.58 supplied lifecycle/route checks plus9 independent +checks pass offline. Actual main now verifies source/public health before private +stdin; execute preserves the original wall/monotonic window rather than renewing +it. Actual child-process partial-pipe counterexample shows unbounded stdin.read +remains blocked beyond a synthetic20ms original window (still alive after100ms +without EOF). No credential/native/provider access is involved. Before private +producer admission, require byte-capped, deadline-bounded JSON input and EOF within +the original window, with fail-closed fixed receipt and no protected effects. +This completed ownT13 preparation precedes formal v7 source changes-requested +review. Retain v6 qualified health-gate agreement and all prior reviews; neither +v7 health ordering nor any source acknowledgment establishes custody completion, +actual route/plugin/leeway/readiness/Argo identity or founder/runtime authority. +Native and private-producer gates remain open; no owner checkout write occurred. + + +2026-10-11 T13 v8 bounded-input correction preparation (same trial): exact +frozen manifest `316fd6005cc4cb7fe14ea69a5fd408aed13e6122afef60afd13d97952b27cf4a` +and all entry hashes verified.65 supplied tests plus12 fresh independent checks +pass offline, including a standard buffered stdin pipe with complete JSON/noEOF +interrupted within original20ms window and restored SIGALRM state; exact64KiB +JSON/EOF accepted and extra byte refused, UTF8 token bytecap enforced, original +wall deadline clips longer monotonic budget. Original preinput window is retained. +Completed ownT13 preparation precedes fresh exact source review; v7 refusal and +v6 qualified agreement/prior reviews retained. This accepts child bounded-input +source only. No parent-ready handshake exists: producer must not eagerly pipe +private inputs, and producer/session/window readiness protocol remains an +unimplemented admission gate. No custody/native completion, sourcepacket approval +authentication, route/plugin/leeway/readiness/Argo observation or inherited grant. +Native prerequisites and producer handoff remain open; no owner checkout changed. + + +2026-10-11 T11 journal v4 canonical-format preparation refinement (same trial): +exact frozen manifest `22c6d225d393b994ab7b44a43904ced1b6d7f74e0e2bebf71ffe99f87191ef4c` +and entry hashes verified. Actual access-engine pkg/api/canonical.go RequestDigest/ +CanonicalDigest, Approval binding.py and Secrets authorization/approval_consume +all use sha256:<64 lowercase hex> request digests. V4 now preserves this exact +request value without prefix stripping; plan/call/evidence content hashes remain +explicit bare64hex.15 supplied checks plus15 fresh independent checks pass, +including malformed prefix/bare/uppercase/trailing whitespace refusal before +reservation, exact persistent value/reopen/mismatch replay, private-file mode, +real child crash after pending intent, ill-typed confirmations and pending-unknown +refusal. Completed ownT11 preparation precedes formal v4 source review; prior v2 +refusal/v3 approval and T13 v7 refusal/v8 source acknowledgment retained. +Acceptance is unintegrated primitive source only; no data migration/native use +of v3 journal has occurred. RPF35-T12 caller/PDP/consume validation, independent +owner plan compiler/restricted adapter, private runtime custody, bounded execution +and owner-private unknown cleanup recovery remain open. No checkout/native writes. + + +2026-10-11 T13 paired ready-child/launcher preparation refinement (same trial): +exact NetV9 manifest `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +and KeyproducerV2 `55a8e794af983ca2202e7a0054d0415a120d2c95018fb03fdb5f28313a109d58` +verified against all entries.74 Net checks plus31 Key checks and10 independent +checks pass offline including a truthful-unknown counterexample: adapter uncertain +private delivery with confirmed=false is copied into launcher receipt, but +consumer_outcome_unknown incorrectly remains false after local SSH teardown. +Complete bytes may have reached remote child before adapter timeout/EOF; local +terminate does not establish remote no-effects. Require sticky propagation of +uncertain delivery into consumer outcome before early return, retain unknown +unless independently established native outcome/recovery. Bad markers/source +pins/injection reject before private reads; extra marker authority/lines reject; +prohibited child output never forwards. Child-ready synchronization is not +authentication/approval. Proposed founder directSSH profile is incompatible with +warden quiet-output lane and not admitted here. Completed ownT13 preparation +precedes formal paired source review; preserve v7 refusal/v8 acknowledgment and +journal histories. No transport grant, coding-agent/private custody admission, +live SSH, credential/native action or owner checkout write. All native role/plugin/ +leeway/route/issuer readiness/Argo/maintenanceexception gates remain prerequisites. + + +2026-10-11 T13 paired producerV4 correction preparation (same trial): exact +producer manifest `d6f641dc1e4aae7d36658d4199d89af14d2fd7a4bd4e526856eb340234f2d33e` +and unchanged NetV9 `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +entry hashes verified.74 Net tests,40 producer checks,9 actual local fakeSSH/ +realwrapper/child synthetic roundtrip regressions and12 fresh Platform checks +pass (135 total). V2 deliveryunknown now remains sticky consumerunknown with +completion=false after earlyreturn/localteardown. V3 Net FIFO acquisition finding +and originalbudgetreset are corrected: actualCLI starts original5s timer before +regular/nofollow/bytebounded contract acquisition, each later preparation phase +clips remaining time. ActualCLI FIFO refuses promptly; expired original budget +never validates/spawns/reads private files. Completed ownT13 preparation precedes +formal corrected pair source agreement. Preserve V2 Platform refusal, Key old +exactV2 acknowledgment and NetV3 refusal; no old acknowledgment repinned. +Agreement is only reviewed source synchronization/launcher behavior, not admission. +Founder authenticated SSH host/profile/channel/runtime pins, exclusive sameUID +file custody and explicit tmpfs file allowance/cleanup, verified human and +coding-agent producer/client/source, native role/plugin/leeway/route/issuer +readiness/Argo/maintenanceexception, refusal/revoke/restoration/readback and +unknown owner recovery remain prerequisites. Warden quietlane cannot carry ready +controlstdout; no transport/custody/native grant. No owner checkout/liveSSH/native. + + +2026-10-11 RPF35-T12 source implementation progress: durable journal source v4 +was independently accepted/committed; owner-derived typed plan compiler component +v2 is prepared at immutable manifest +`41cda74ab32384c789ea8a760475671aadad4e5121335c8f60567ff53d66665b` +with40 offline tests. Completed own bounded source-preparation ADHOCT02 anchor +was persisted at7adbcb4 before the qualified Platform contract/readiness receipt. +T12 progresses for actual source implementation underway, not native acceptance +or full descriptor/authority readiness. The compiler derives local CCR/HCL/role +bodies, matches actual independently pinned Secrets catalogue and revalidates +source/body before fixed calls; no body/target chosen by service is dispatched. +Independent technical integration review and exact full ExecutionContract/owner +grant/baseline/estate/deadline matching, initiating human/User/Tenant PIP/transport +representation/service identity, served PDP/claim/consume correspondence, journal +call dispatch/restricted adapter, native token TTL/uses/custody/revoke/cleanup and +owner-private unknown recovery remain unimplemented integration/native gates. +Actual CCR42 has no eligible approved pilot/catalogue; no source metadata is +invented. T02 and original negative/capability/native evidence remain unchanged; +T11/T13 history retained, no defaultflip/nativego or SecretsT06 closure follows. + + +2026-10-13 T12 source correction: the compiler hashed the catalogue sources but +used cached Python modules with matching paths, which did not establish executing +those exact bytes. A failing regression reproduced the substitution. Catalogue, +package and dependencies now execute from the verified snapshot in temporary +private modules; ambient modules remain untouched and cleanup runs on refusal. +45 compiler plus 15 journal tests pass. The v2 source review remains historical; +this change needs its own integration review. T12 retains all existing full +contract, identity/consume, dispatch, custody and native acceptance requirements. +RPF-IN-0012 remains open for the independent contract/wrapped-delivery return; +this code correction does not authorize either operation. + +2026-10-16 T12 source preparation (isolated owner checkout; not owner delivery): +added durable precommitted cleanup obligations and separate outcome evidence to +the existing Journal, plus a fixed three-method owner cleanup driver. Same live +postconsume admission can clean after a business timeout/failed/unknown outcome; +cleanup closes business dispatch and cannot replay or restore admission after a +crash. Empty obligations no longer produce cleanup-confirmed. Real SQLite +multiprocess races and abrupt process death before/after a separately durable +synthetic effect verify refusal on reopen. Current compiler/journal/cleanup suite: +73 passed, local source/fixture only. Details: docs/task-execution-cleanup.md. +No native adapter or production mediator exists; full grant/request/cleanup binding, +authenticated consume/identity, ephemeral token issuance, deadline/use checks, +native effect/revoke/absence, audit and protected recovery remain prerequisites. +T12 remains progress. No CCR38 default/entitlement or live grant was changed. + +2026-10-16 T12 second source package: Compiler Plans now bind deterministic cleanup +commitments and can bind the complete independently installed engine execution +descriptor. A fixed disposable-loopback native adapter actually materializes exact +per-operation metadata ACL/task token, executes six source-derived metadata calls, +and verifies self-revocation/accessor invalidation and policy retirement. Each +cleanup request has its own durable intent. Native fault tests cover lost response +after real write and policy deletion while task revoke fails. All initiating +identity/approval/consume/grant/state/source admission in this fixture is synthetic; +no production authority or complete native owner acceptance is claimed. Exact +remaining owner schema/admission and mediator work: docs/task-execution-native-fixture.md. +T12 stays progress; no live grant, credential/default change or owner sync performed. + +2026-10-16 T12 third source package: implemented proposed task-execution-grant +immutable projection and exact compiler/native-fixture integration through the +existing descriptor grant ID/SHA fields. Only typed review.comments/evidence.events +are excluded; separate append-only checks reject removal/rewrite/reordering and +unknown guessed evidence exclusions refuse. Owner-pinned grant bytes and validator +source must match independently reconstructed descriptor/source/cleanup/ACL/token +bodies before a native fixture can materialize. Proposed source records gain no +execution authority; no real grant, policy or legacy applier registration added. +Details and remaining production gates: docs/task-execution-grant-projection.md. +T12 remains progress; no owner sync or production effect performed by this package. + +2026-10-16 T12 fourth source package: connected the Secrets-owned strict task +handoff to actual Approval ExecutionConfirmationClient independent GET before +consume-confirmed/native fixture work. Platform accepts no supplied authorization +boolean/object/callback and preserves its exact owner descriptor/grant/Plan join. +Durable CAS/GET intents precede native ordinals through the repaired journal +prefix API. Actual source-server fixture uses signed Access/enforced synthetic +TokenReview, real Approval WSGI/SQLite with distinct synthetic human/service +identities, actual strict Secrets signature/CAS validation and disposable native +OpenBao. Untouched actual task policy remains signed DENY; separately named +synthetic fixture policy is never production admission. Read-scope denial after +CAS records consumed/unknown with zero native effects. Exact dependency/source +hashes, tests and remaining gates are retained with the source package and in +docs/task-execution-mediator-seam.md. No real grant/custody, policy default, owner +sync or native production acceptance is performed; T12 stays progress. + +2026-10-16 T12 recovery successor source preparation: optional independently +installed fixture custody durably retains operation-bound private accessors and +issuance checkpoints. Fresh cleanup-only owner permits can reconcile after actual +executor process death using fixed revoke/readback and policy delete/readback, +without restoring business/consume admission. Separate durable attempt evidence +retains original unknown outcomes. Lost token-create response remains unresolved +when no accessor was committed. Source-only process-loss fixtures are not native +production custody or recovery-role admission; T12 remains progress. + +2026-10-16 T12 recovery R2 source refinement retains R1's overbroad 404 failure: +policy cleanup now requires exact native empty-errors absence before/after delete; +HCL uses only documented single optional terminal LF normalization. Private +capsules are owner-key HMAC authenticated, strict nested schemas/ordered cleanup +commitments reject damage, and journal history prevents stale prepared capsules +from hiding issuance. Fixture process-loss source proof remains separate from +unadmitted production custody, integrity-key storage and recovery-role scope. + +2026-10-16 T12 independently reviewable budget/source slice: bound native HTTP +header/body/close, compiler work and cleanup through fixed owner main-thread +absolute budgets, with actual task expiry narrowing global authority. Actual v2 +mediator now verifies each independently installed source_bundle byte hash before +authorization/effects. No deadline/TTL extension, remint or generic service added. +Retained registry actual-provider proof still refuses Approval correspondence +before CAS/native; normalized pre-approval + precise immediate CAS whole-stack +positive remains live owner follow-up under CUST-WP-0080. T12 stays progress. + +2026-10-16 T12 actual v2 successor source proof: retained registry signed DENY +normalization from the real Secrets prepare_task_approval builder precedes actual +Approval issue/human approval. Actual Access v2 then signs ALLOW; strict Secrets +CAS and independent confirmation GET precede six disposable native calls, exact +readback and confirmed token/policy cleanup. Approval precision source permits +immediate CAS without sleeps/backdating. The 60-second immutable deadline, +30-second backend TTL, 120-second synthetic observation and existing cleanup +reserve remain bound; issued credential expiry narrows business time. Source, +caller, revoke, source-reader, registry drift and expiry refusals cause no native +effects; revoke between ALLOW/CAS retains unknown without business dispatch. +This owner fixture uses separately installed synthetic identity/key/trust and +loopback OpenBao, grants no production authority and keeps T12 progress. Prior +failed temporal/normalization proofs remain retained. + +2026-10-16 T12 signer custody R3 source preparation rebases the proposal to +integrated Access919ce25 and preserves current workplan state. Added protected +in-memory Ed25519 CAS/readback primitive with durable closed metadata receipts +and fixed disposable-only owner adapter. Actual synthetic OpenBao bootstrap, +rotation, conflict/unknown/readback/receipt/private-output and admission failures +are tested. Production direct entry refuses: exact CCR/founder scope, protected +executor/fencing/receipt custody, independent consumer public admission, migration +debt and native deployment prerequisites remain open. No live key/grant or CCR +admission; RPF-WP-0035-T12 remains progress. + +R3 source metadata correction aligns proposal IDs across JSON/docs/Secret +annotation and documents existing base64url-ASCII public fingerprint hashing. +Frozen R2 source/evidence is preserved; no writer behavior or admission changes. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/validation.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/validation.json new file mode 100644 index 00000000..28ff6908 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/native-preparation-r1/validation.json @@ -0,0 +1,22 @@ +{ + "patch_sha256": "a9d4631d3320ac3fa56f5a61965005c546eae241d2004cc1e6385e04668b7f7f", + "test_command": "pytest -q tests/test_flex_auth_signer_native_preparation.py", + "result": "3 passed in 0.07s", + "real_CCR_validation_errors": [], + "expected_warning": "OIDC/Kubernetes bound claim is not confirmed; apply is blocked", + "real_applier_blockers": [ + "proposed status", + "unconfirmed OpenBao auth binding" + ], + "original_candidate_failures_preserved": [ + "unsafe lowercase kid field declaration for delegated applier", + "role did not match existing delegated-applier convention" + ], + "candidate_corrections": [ + "private projected field only; document reader can still read public sibling fields", + "external-secrets-flex-auth-envelope-signing role; dedicated SA unchanged" + ], + "synthetic_approved_bound_copy_gate": "zero scope-shape blockers; pure local candidate only, never persisted as approved", + "apply_check": "pass exact preimages/new-file absence", + "live_actions": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/owner-source-review-r1.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/owner-source-review-r1.json new file mode 100644 index 00000000..75708d2a --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/owner-source-review-r1.json @@ -0,0 +1,8 @@ +{ + "reviewer": "railiance-platform-owner (agent railiance-platform, codex)", + "decision": "approved", + "scope": "Exact source-only proposal for integration review; no credential scope/admission or execution approval.", + "comment": "Platform INTENT Mission and principles 3 Durable by Default, 4 Secure Custody, 5 Operable and Observable: exact-path private delivery and independent public admission reuse existing owner patterns, retain recovery/durability gaps rather than declaring acceptance. Work item RPF-WP-0035-T12; reviewed patch sha256:0f31567718023cdf2e2c1b3a5d8c8916312fd44b039b9bc32a2e404011fe4a57 at base 5f30ddd90c33e7eb1b9efa1093c7324d83210cf2. Prepared and reviewed in isolated owner checkout with owner instructions and INTENT read; only Platform owner role reviewed.", + "authority_unchanged": true, + "missing_gates": "Proposal lists null key, public admission, CCR/exact human scope decision, writer command, CI image, package debt, installed consumer, durability, capacity, diff/dryrun, costs/risk and abort-owner receipts." +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/protected-recovery-next-owner-task-r1.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/protected-recovery-next-owner-task-r1.json new file mode 100644 index 00000000..14d7a24d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/protected-recovery-next-owner-task-r1.json @@ -0,0 +1,46 @@ +{ + "schema": "railiance-platform.protected-execution-recovery-assessment.v1", + "work_item": "RPF-WP-0035-T12", + "scope": "Assessment only. Not signer admission, recovery implementation or production acceptance.", + "finding": "Wave5 SQLite persistence provides restart refusal and durable cleanup debt, not protected cleanup recovery.", + "evidence": [ + { + "path": "scripts/task_execution_native_fixture.py", + "sha256": "60abb78634038ca9422a35265c7a21b6653fed8ef5b85c4d50e846f4e3da4edf", + "details": "PrivateSession token/accessor, FixtureAdmission owner/identity tokens and Popen reference, task handle and cleanup-step counters live in memory. _revoke needs retained session; no protected durable recovery reference is implemented." + }, + { + "path": "scripts/task_execution_journal.py", + "sha256": "507b41a790e678dfd16af747bd851f5abc2fed5a8fb70bca05449d9e5ac674e8", + "details": "reserve INSERT rejects reused approval/operation; _admission/_consumed_admission reset outside invocation; _cleanup_admission requires same live consumed admission. observe never creates authority; before_cleanup explicitly excludes restart recovery." + }, + { + "path": "tests/test_task_execution_native_fixture.py", + "sha256": "0127b2cb84570e27c9fd70560e8088a7ad531497ee4a83a8917632e8c02982c2", + "details": "Explicit synthetic owner recovery is not adapter retry/resumption or independently admitted production recovery." + } + ], + "next_owner_task": { + "id": "RPF-WP-0035-T12 recovery successor source work; retain through CUST-WP-0080", + "owner": "railiance-platform", + "title": "Specify and implement independently admitted protected cleanup recovery without business resumption", + "inputs": [ + "Owner-controlled protected durable handle/reference custody and recovery executor; never place token/accessor values in public journal/Hub/artifacts.", + "Exact original plan/source/target/cleanup obligations and ambiguous issuance boundary; independent recovery admission bound to interrupted operation.", + "Secrets/Access/Approval owner correspondence for original consumed operation and recovery proof; no new request flag enables cleanup.", + "Concrete proposal/exact scope reviews before any production recovery authority is granted." + ], + "acceptance": [ + "Crash before and after policy PUT, token-create response, handle custody commit, each of six effects, revoke and policy delete; preserve unknown/pending states.", + "Restart refuses every business dispatch and original approval reuse.", + "Independently admitted recovery can only verify/revoke the exact interrupted sessions and remove the exact operation policy; no fresh token mint or business mutation.", + "If token creation response/handle is lost, prove bounded expiry plus independent owner reconciliation or a reviewed exact recovery mechanism; inability to identify/revoke is unresolved cleanup debt, never success.", + "Verify actual revocation/invalidation and exact policy absence using safe closed metadata; keep failed/uncertain outcomes and original receipt.", + "Disposable fixture recovery terminates and verifies the owner-spawned backend through independent owner custody; passing fixture teardown is not estate backend acceptance." + ], + "exclusions": [ + "No implementation in signer proposal.", + "No new grant, accessor exposure, broad revoke/list privilege or resume-from-SQLite authority." + ] + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/route-public-metadata-r1.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/route-public-metadata-r1.json new file mode 100644 index 00000000..5b3f1231 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/route-public-metadata-r1.json @@ -0,0 +1,48 @@ +{ + "id": "flex-auth-decision-envelope-signing-key", + "title": "Ed25519 key that signs flex-auth decision envelopes", + "owner_repo": "railiance-platform", + "subsystem": "OpenBao + flex-auth", + "warden_executes": false, + "warden_role": "route", + "exec_capable": false, + "resolvable": false, + "wiki_ref": "wiki/playbooks/flex-auth-decision-envelope-signing-key.md#worker-checklist", + "canon_ref": "flex-auth/docs/decision-envelope-signature.md", + "reviewed": "2026-09-14", + "status": "draft", + "risk": "high", + "high_risk": true, + "workload_ref": { + "applicability": "applicable", + "rapp_id": null, + "name": null, + "deployable": null, + "declaration_ref": null, + "reason": null, + "unknown_reason": "flex-auth has not published an authoritative workload identity declaration for envelope signing.", + "resolution": "unknown" + }, + "has_rotation": false, + "delegation": { + "mode": "interim", + "intended_owner": "railiance-platform", + "blocked_on": "Shape is chosen in flex-auth (FLEX-WP-0024-T02). OpenBao KV path, Kubernetes auth role, and paste_once_provision of the private seed are not built. Testdata key in flex-auth is not this lane.", + "reviewed": "2026-09-14", + "verified": "unverified", + "is_verified": false, + "implicit": false + }, + "need_keywords": [ + "flex-auth", + "decision", + "envelope", + "signing", + "signature", + "ed25519", + "responder", + "authenticity", + "FLEX-WP-0024" + ], + "next_action": "next action on `railiance-platform` \u2014 see `wiki/playbooks/flex-auth-decision-envelope-signing-key.md#worker-checklist`" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/source-proposal-r1.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/source-proposal-r1.patch new file mode 100644 index 00000000..eac132c8 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/source-proposal-r1.patch @@ -0,0 +1,345 @@ +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed b/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed +new file mode 100644 +index 0000000..e96f5f9 +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed +@@ -0,0 +1,10 @@ ++# SOURCE PROPOSAL ONLY. New scope remains founder-gated; no metadata/list/write. ++path "platform/data/workloads/flex-auth/envelope-signing" { ++ capabilities = ["read"] ++} ++path "auth/token/lookup-self" { ++ capabilities = ["read"] ++} ++path "auth/token/revoke-self" { ++ capabilities = ["update"] ++} +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed b/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed +new file mode 100644 +index 0000000..ad8181e +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed +@@ -0,0 +1,50 @@ ++# SOURCE PROPOSAL ONLY: no CCR admission, no apply, no plaintext key. ++apiVersion: v1 ++kind: ServiceAccount ++metadata: ++ name: flex-auth-envelope-signing-eso ++ namespace: flex-auth ++automountServiceAccountToken: false ++--- ++apiVersion: external-secrets.io/v1 ++kind: SecretStore ++metadata: ++ name: openbao-flex-auth-envelope-signing ++ namespace: flex-auth ++spec: ++ provider: ++ vault: ++ server: http://openbao.openbao.svc:8200 ++ path: platform ++ version: v2 ++ auth: ++ kubernetes: ++ mountPath: kubernetes ++ role: flex-auth-envelope-signing-eso ++ serviceAccountRef: ++ name: flex-auth-envelope-signing-eso ++ audiences: [openbao] ++--- ++apiVersion: external-secrets.io/v1 ++kind: ExternalSecret ++metadata: ++ name: flex-auth-secrets-engine-envelope-signing ++ namespace: flex-auth ++spec: ++ refreshInterval: 5m ++ secretStoreRef: ++ kind: SecretStore ++ name: openbao-flex-auth-envelope-signing ++ target: ++ name: flex-auth-secrets-engine-envelope-signing ++ creationPolicy: Owner ++ deletionPolicy: Retain ++ template: ++ metadata: ++ annotations: ++ railiance.io/custody-proposal: RPF35-PDP-SIGNER-CUSTODY-20261016-R1 ++ data: ++ - secretKey: seed ++ remoteRef: ++ key: workloads/flex-auth/envelope-signing ++ property: ED25519_PRIVATE_KEY +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing.md b/docs/credential-lane-designs/flex-auth-envelope-signing.md +new file mode 100644 +index 0000000..667f056 +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.md +@@ -0,0 +1,134 @@ ++# Retained lifecycle PDP signer custody proposal ++ ++Proposal ID: RPF35-PDP-SIGNER-CUSTODY-20261016-R1. Preparation under ++RPF-WP-0035-T12, beneficiary FLEX-WP-0024-T06, coordinated by CUST-WP-0080. ++Status: source proposal only; no key generated, credential read, CCR admission, ++policy scope granted, package published or deployment changed. ++ ++Platform INTENT principles 3–5 require durable custody, recovery and bounded ++interfaces. Platform is Staff/PEP-shaped and is not an authorization authority. ++The exact candidate contract is `flex-auth-envelope-signing.proposal.json`. ++Sibling `.proposed` files are review inputs outside deployment discovery; they ++carry no approved CCR id and MUST NOT be applied as an admitted lane. ++ ++## Existing workload and custody boundary ++ ++Retain namespace/release/deployment `flex-auth/flex-auth-secrets-engine`, signer ++SA `system:serviceaccount:flex-auth:flex-auth-secrets-engine`, and the twelve-action ++`secrets-engine.catalog-lane.lifecycle` v2 policy. The consumer SA remains ++`system:serviceaccount:secrets-engine:secrets-engine`; retained caller audience is ++`flex-auth`. Neither consumer nor TokenReview credentials confer seed read rights. ++Access R2 proposes `tenancy.yaml#/workload_identity`; it is not yet an integrated ++runtime admission. An authoritative rapp declaration remains explicit managed ++package migration debt, with reference null; no synthetic rapp tuple is created. ++Legacy image package remains `forgejo.coulomb.social/coulomb/flex-auth`. ++ ++Reuse CCR-2026-0015's dedicated namespace SecretStore, exact data-only policy, ++short-lived Kubernetes delivery login and separate protected CAS writer patterns. ++The dedicated delivery SA is NOT the signer SA. No RoleBinding, Secret read, ++TokenRequest or ExternalSecret-create permission is given to the signer/consumer. ++The controller's existing ability to mint only the delivery-SA token and namespace ++mutation restrictions must be independently proven before activation; source YAML ++does not establish those facts. Do not silently broaden ESO RBAC. ++ ++KV data `platform/data/workloads/flex-auth/envelope-signing` is read only by the ++reviewed ESO delivery role. There is no parent/list/metadata/write permission. ++Lookup-self/read and revoke-self/update support bounded session lifecycle. If ESO ++needs metadata, retain a failing receipt and review that exact scope amendment. ++The KV document has private `ED25519_PRIVATE_KEY` and public `ED25519_PUBLIC_KEY`, ++`kid`; only the private property is projected to the Secret. A public receipt ++contains kid, public key/fingerprint, KV version and exact source/deployment/policy ++bindings, authenticated independently through reviewed owner custody. Consumers ++must never read the private KV document to obtain the public key, trust `/v1/keys`, ++or derive authority from receipt shape, policy digest or this proposal. ++ ++## Seed, projection and protected writer ++ ++The attended protected writer generates a fresh 32-byte CSPRNG Ed25519 seed IN ++MEMORY in the custody process and writes unpadded strict base64url via CAS zero. ++It derives the public key there, verifies correspondence, and emits metadata only. ++No seed in argv, environment, temporary files, logs, diffs, chat, Hub or CI. ++Rotation requires exact current-version CAS. No fixture seed is promotable. ++`state_hub_preflight_lane.py` is a reusable design pattern, not an Ed25519 writer; ++a reviewed signer-specific receipt-producing command is still necessary owner work. ++Do not run the HMAC writer unchanged or claim D1 admission without that command. ++The read lane does not authorize writer scope. Use the existing attended ++OpenBao/warden access route; ops-warden routes and never vends this seed. ++ ++Proposed namespace SecretStore uses dedicated SA, audience `openbao`, TTL/max/ ++explicit max 15m, no default policy, no periodic token. Proposed Secret name ++`flex-auth-secrets-engine-envelope-signing`, key `seed`; owner creation and Retain ++deletion policy avoid implicit removal on custody outage. Retain also means a ++compromised seed survives until explicit cleanup: disabling ESO is not revocation. ++The current Access chart supplies readOnly volume, defaultMode 0440 and uid/gid/ ++fsGroup 65532. Seed path is `/var/run/secrets/decision-envelope-signing/seed`; ++private data is never envFrom. Runtime validates file mode and reads once at ++startup, so ESO refresh alone cannot rotate process memory. Freeze exact Secret ++resourceVersion, KV version, public admission and startup kid together; require ++all replicas loaded the same admitted version before probes. No extra key reload ++mechanism is proposed. ++ ++## Durable evidence and output limits ++ ++Reuse current Access `outbox.enabled`, existingClaim and source support: ++`--outbox-dir` plus `--emission-source`, replicaCount 1, Recreate, one writer/PVC. ++Do not combine with `--log`. Outbox AppendBatch fsyncs the source envelope before ++returning; ordinary JSONL alone does not prove native independent custody. ++Existing outbox has no total-byte retention ceiling: chart size 1Gi is requested ++storage, NOT an enforced log quota. Before rollout name admitted existing PVC, ++capacity/headroom, alerts, bounded export/retention, disk-full fail-closed behavior, ++restart/partial-write readback tests and independent receiver/audit receipt. ++Audit sender credential/receiver admission is separate, not created by this lane. ++Do not silently create a PVC/spend commitment or enable arbitrary audit egress. ++No current native durable/audit acceptance follows from the source feature. ++ ++Protected writer success/failure receipts must be closed metadata objects, at ++most 64KiB, stored owner-only mode 0600 with atomic durable writes. Fields: proposal ++and executed revision digests, actor/time, exact path, CAS version, kid/public ++fingerprint, deployment/image/policy/trust digests, boolean checks, rollback outcome. ++Never include response bodies, seed, bearer tokens, accessors, wrapped values, ++process environment or exception text. Bound backend reads to 1MiB and safe error ++codes; no shell tracing. Public admission may carry the public key and must have ++independent authenticated delivery. Access R2 native proof reader bounds receipt ++reads to 524289 bytes, rejecting >524288; that is not a durable writer quota. ++ ++## Rotation, revocation and rollback ++ ++Admit successor public key to each consumer first through independent custody ++and verify seed/public correspondence in the protected custody writer. Fence ++protected consumers and stop every signer replica, prove no old-key process ++remains, CAS-rotate, wait ESO version, restart the one-writer pin, then verify ++successor-signed non-effect lifecycle allow/deny and durable originals before ++reopening protected consumers. ++After last old issuance retain old key online no longer than actual maximum allow ++TTL plus a reviewed bounded uncertainty margin (default TTL is not a guarantee). ++Keep archived historical keys for offline audit separate from online trust; verify ++expired envelopes remain refused. Emergency compromise removes the old online key ++immediately, stops old processes, and recovers forward; never restore revoked seed. ++No scope/admission change to task policy: service pilot stays hard DENY and ++execute-ccr stays unknown_action on lifecycle policy. ++ ++On signer rollout failure, stop protected consumers and restore exact previous ++producer image/values only as availability rollback; enforcing consumers continue ++to reject unsigned decisions. Outbox/PVC and source receipts are retained. Revert ++seed only for independently reviewed non-compromise recovery with corresponding ++public admission; otherwise forward recovery. If grant or effect outcome is unknown, ++retain unknown and reconcile; never auto-retry or translate it to success. ++ ++## Gates and next owner work ++ ++The JSON lists exact missing inputs and approvals. Oct11 D1 preapproves a reviewed ++receipt-producing lane for an attended window; it does not create an unbuilt lane. ++Oct11 standing build-mode rule permits qualifying non-destructive rollout after ++reviewed diff/dry-run, rollback, abort owner and receipts; new secret/access scope ++still needs founder approval. Source reviews are not human approval. Supervision ++record remains supervised; costs/risk and exact executor must be admitted for the ++executable revision. Source preparation costs EUR 0 incremental infrastructure; ++future resource/custody loss bounds are null rather than guessed or self-approved. ++ ++Next Platform source task under RPF-WP-0035-T12: implement/test the protected ++Ed25519 CAS writer plus fail-closed metadata receipt and exact version readback, ++stage schema-valid proposed CCR through existing credential-change tooling after ++Access identity source and required approvers are confirmed. Reuse existing lane ++machinery. A receipt-producing command does not grant its write/read scope. ++Keep CCR-2026-0048/0049, WORK-RECORDS and unrelated work unchanged. +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json b/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json +new file mode 100644 +index 0000000..06ceeb8 +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json +@@ -0,0 +1,110 @@ ++{ ++ "schema": "railiance-platform.signer-custody-proposal.v1", ++ "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R1", ++ "status": "source-proposal-unadmitted", ++ "owner": "railiance-platform", ++ "work_item": "RPF-WP-0035-T12", ++ "coordination": "CUST-WP-0080", ++ "beneficiary": "FLEX-WP-0024-T06", ++ "scope": { ++ "namespace": "flex-auth", ++ "release": "flex-auth-secrets-engine", ++ "signer_principal": "system:serviceaccount:flex-auth:flex-auth-secrets-engine", ++ "consumer_principal": "system:serviceaccount:secrets-engine:secrets-engine", ++ "rapp_declaration_ref": null, ++ "migration_debt": "Managed package declaration not established; retained Helm workload is not an exemption.", ++ "access_identity_source": "Access source-preparation-r2.patch tenancy.yaml#/workload_identity; proposal only" ++ }, ++ "proposed_lane": { ++ "catalog_id": "flex-auth-decision-envelope-signing-key", ++ "route_status": "draft/nonresolvable", ++ "kv_mount": "platform", ++ "kv_path": "workloads/flex-auth/envelope-signing", ++ "private_field": "ED25519_PRIVATE_KEY", ++ "public_fields": [ ++ "ED25519_PUBLIC_KEY", ++ "kid" ++ ], ++ "policy": "workload-kv-read-flex-auth-envelope-signing", ++ "auth_mount": "kubernetes", ++ "auth_role": "flex-auth-envelope-signing-eso", ++ "delivery_sa": "flex-auth-envelope-signing-eso", ++ "audience": "openbao", ++ "token_ttl": "15m", ++ "token_max_ttl": "15m", ++ "token_explicit_max_ttl": "15m", ++ "token_no_default_policy": true, ++ "secret_store": "openbao-flex-auth-envelope-signing", ++ "secret_name": "flex-auth-secrets-engine-envelope-signing", ++ "secret_key": "seed", ++ "mount_path": "/var/run/secrets/decision-envelope-signing/seed", ++ "mode": "0440", ++ "private_encoding": "unpadded strict base64url of 32-byte Ed25519 seed", ++ "seed_load": "startup only" ++ }, ++ "independent_public_admission": { ++ "kid": null, ++ "public_key": null, ++ "fingerprint": null, ++ "custody_receipt": null, ++ "consumer_trust_digest": null, ++ "rule": "Owner-authenticated public receipt independently installed with exact evaluator/mode/policy pins; no self-discovery or private KV read by consumer." ++ }, ++ "required_approvals": [ ++ { ++ "actor": "founder", ++ "scope": "New exact KV read/write custody policy scope and dedicated delivery role; exact proposed CCR/revision and owner reviews required; no approval inferred." ++ }, ++ { ++ "actor": "Access owner", ++ "scope": "Exact retained workload identity/source, signer interface, unchanged policy/caller binding, image provenance and producer rollout." ++ }, ++ { ++ "actor": "Platform owner", ++ "scope": "Custody path, protected CAS writer, delivery identity/role and recovery receipts; this source review only." ++ }, ++ { ++ "actor": "Secrets owner", ++ "scope": "Independent public key/trust pins, installed helper provenance and fail-closed native consumer acceptance." ++ }, ++ { ++ "actor": "cluster/GitOps owner", ++ "scope": "Namespace SecretStore/ESO TokenRequest restrictions, manifests, rollout/headroom, existing PVC and recovery." ++ } ++ ], ++ "missing_deployment_inputs": { ++ "schema_valid_reviewed_CCR": null, ++ "human_exact_scope_decision": null, ++ "protected_signer_writer_command_digest": null, ++ "approved_executor_and_abort_owner": null, ++ "access_identity_integrated_revision": null, ++ "managed_package_admission_or_explicit_debt_disposition": null, ++ "CI_source_to_image_receipt": null, ++ "candidate_image_digest": null, ++ "KV_and_Secret_safe_version_receipt": null, ++ "native_identity_and_negative_scope_receipt": null, ++ "consumer_native_allow_deny_receipts": null, ++ "PVC_and_capacity_retention_admission": null, ++ "durable_original_and_independent_audit_receipt": null, ++ "reviewed_diff_server_dryrun_and_headroom": null, ++ "rotation_revocation_and_recovery_receipts": null, ++ "activation_cost_bound_eur": null, ++ "activation_risk_bound_eur": null ++ }, ++ "unchanged_policy": { ++ "package": "secrets-engine.catalog-lane.lifecycle", ++ "version": "v2", ++ "digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4", ++ "caller_auth": "enforce", ++ "caller_audience": "flex-auth", ++ "execute_ccr": "DENY unknown_action", ++ "service_pilot": "runtime_admission false" ++ }, ++ "execution": { ++ "authorized_by_this_proposal": false, ++ "key_created": false, ++ "route_promoted": false, ++ "live_changes": false, ++ "preparation_incremental_spend_eur": 0 ++ } ++} +diff --git a/workplans/RPF-WP-0035-credential-lane-implementation.md b/workplans/RPF-WP-0035-credential-lane-implementation.md +index 4ea8015..7223fef 100644 +--- a/workplans/RPF-WP-0035-credential-lane-implementation.md ++++ b/workplans/RPF-WP-0035-credential-lane-implementation.md +@@ -1277,3 +1277,12 @@ CAS records consumed/unknown with zero native effects. Exact dependency/source + hashes, tests and remaining gates are retained with the source package and in + docs/task-execution-mediator-seam.md. No real grant/custody, policy default, owner + sync or native production acceptance is performed; T12 stays progress. ++ ++2026-10-16 T12 signer prerequisite source proposal: prepared exact-path private seed ++ESO projection and separate independently admitted public verification material for ++the existing flex-auth-secrets-engine lifecycle PDP. Proposal ++RPF35-PDP-SIGNER-CUSTODY-20261016-R1 is source only; no seed, grant, live mutation ++or deployment admission. See docs/credential-lane-designs/flex-auth-envelope-signing.md ++and its JSON/.proposed companions. New custody scope, protected receipt-producing ++Ed25519 writer, managed-package migration debt, native outbox capacity/audit and ++exact producer/consumer acceptance remain explicit gates. T12 stays progress. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/validation-r1.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/validation-r1.json new file mode 100644 index 00000000..3905a895 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/validation-r1.json @@ -0,0 +1,51 @@ +{ + "scope": "Offline source checks only. No key minted, no credentials, no network/live calls, no manifests applied. Helm used public placeholder kid only, no seed.", + "checks": [ + { + "name": "new custody scope remains unadmitted with missing key/provenance/executor inputs", + "passed": true + }, + { + "name": "namespace-scoped delivery only, no RBAC or raw Secret object", + "passed": true + }, + { + "name": "private field alone projected; public admission separate", + "passed": true + }, + { + "name": "exact KV data path and bounded self lifecycle; no metadata/list/write grant", + "passed": true + }, + { + "name": "owner create and Retain explicit", + "passed": true + }, + { + "name": "existing chart refuses missing independently admitted kid/Secret", + "passed": true + }, + { + "name": "existing chart renders source-only signer/outbox interfaces", + "passed": true + }, + { + "name": "rendered seed read-only 0440 exact item and uid/fsGroup 65532", + "passed": true + }, + { + "name": "rendered single-writer Recreate existing PVC without new claim", + "passed": true + }, + { + "name": "rendered lifecycle package caller enforce retained and no task enablement", + "passed": true + }, + { + "name": "patch applies cleanly to exact owner base", + "passed": true + } + ], + "passed": 11, + "failed": 0 +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/README.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/README.md new file mode 100644 index 00000000..65c45c30 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/README.md @@ -0,0 +1,21 @@ +# Signer custody source R2 + +This full source patch supersedes the proposed R1 files while retaining R1 evidence. +Apply after the budget/source slice; its workplan preimage also includes the +actual full-chain successor note. Exact dependencies, preimages and hashes are in +manifest.json. All canonical source changes remain the coordinator's integration. + +The source implements an in-memory Ed25519 CAS writer and exact-version native +readback with public-only, exclusive, atomic/fsynced receipts. It reuses existing +protected native fixture private-file and absolute HTTP budget machinery. Twelve +actual disposable OpenBao cases passed. Read or write uncertainty, including a +failed final success receipt, remains unknown; no automatic remint/retry/rollback +is possible. The original proposal was rebased to integrated Access919ce25. + +This is a fixed disposable-only adapter. Direct module execution refuses live +use. Production must independently admit the exact schema-valid CCR/revision, +new custody scope, protected execution/isolation, replica fencing, receipt custody, +public receipt delivery/trust and rotation/recovery gates before adding a native +adapter. No founder approval, role, key, live credential, managed package tuple, +ESO binding or production grant is inferred. Missing managed declaration remains +explicit migration debt. Source approval is not production admission. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/implementation.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/implementation.patch new file mode 100644 index 00000000..d12da2e6 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/implementation.patch @@ -0,0 +1,655 @@ +diff --git a/scripts/flex_auth_signer_custody.py b/scripts/flex_auth_signer_custody.py +new file mode 100644 +index 0000000..1783a6f +--- /dev/null ++++ b/scripts/flex_auth_signer_custody.py +@@ -0,0 +1,149 @@ ++#!/usr/bin/env python3 ++"""Protected signer CAS primitive. Disposable owner fixture only; no live entry. ++ ++This module deliberately cannot admit production custody. A reviewed native CCR, ++protected executor, fencing and founder scope are prerequisites for that adapter. ++""" ++from __future__ import annotations ++from dataclasses import dataclass,field ++from datetime import datetime,timezone ++import base64 ++import hashlib ++import hmac ++import http.client ++import json ++import os ++from pathlib import Path ++import re ++import secrets ++import subprocess ++ ++from cryptography.hazmat.primitives import serialization ++from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey ++from task_execution_journal import Journal,Refused ++from task_execution_native_fixture import _absolute_budget ++from task_execution_recovery import _json_unique,_invalid_constant ++ ++PATH='platform/data/workloads/flex-auth/envelope-signing' ++FIELDS={'ED25519_PRIVATE_KEY','ED25519_PUBLIC_KEY','kid'} ++BINDINGS={'proposal_sha256','executed_revision_sha256','deployment_sha256','image_sha256','policy_sha256','trust_sha256'} ++ ++ ++def encoded(value):return json.dumps(value,sort_keys=True,separators=(',',':'),allow_nan=False).encode() ++def b64(value):return base64.urlsafe_b64encode(value).decode().rstrip('=') ++ ++ ++@dataclass(frozen=True) ++class FixtureWriterAdmission: ++ port:int ++ owner_token:str=field(repr=False) ++ server_process:subprocess.Popen=field(repr=False) ++ fenced:bool=False ++ ++ ++class SignerWriter: ++ """Single attempted operation; failed/unknown writes never retry or remint. ++ ++ File permissions are accidental-disclosure guards, not same-UID isolation. ++ The receipt directory must be independent owner custody in a native adapter. ++ Python cannot promise seed zeroization; process lifetime is the boundary. ++ """ ++ def __init__(self,admission:FixtureWriterAdmission,directory:Path,operation_id:str,*,kid:str,expected_version:int,bindings:dict): ++ if (type(admission) is not FixtureWriterAdmission or type(admission.port) is not int ++ or not 1<=admission.port<=65535 or type(admission.owner_token) is not str ++ or not admission.owner_token or type(admission.fenced) is not bool or not admission.fenced): ++ raise Refused('exact fenced fixture custody required') ++ process=admission.server_process ++ if (type(process) is not subprocess.Popen or process.poll() is not None or type(process.args) is not list ++ or '-dev' not in process.args or '-dev-no-store-token' not in process.args ++ or '-dev-listen-address=127.0.0.1:'+str(admission.port) not in process.args): ++ raise Refused('live owner-spawned disposable dev process required') ++ if (type(operation_id) is not str or not re.fullmatch(r'[a-zA-Z0-9_-]{1,80}',operation_id) ++ or type(kid) is not str or not re.fullmatch(r'[a-zA-Z0-9_-]{1,80}',kid) ++ or type(expected_version) is not int or not 0<=expected_version<2**31 ++ or type(bindings) is not dict or set(bindings)!=BINDINGS ++ or any(type(v) is not str or not re.fullmatch(r'sha256:[0-9a-f]{64}',v) for v in bindings.values())): ++ raise Refused('exact signer operation contract required') ++ if directory.absolute()!=directory.resolve() or directory.is_symlink():raise Refused('indirect receipt custody refused') ++ Journal._private(directory.stat(),directory=True) ++ self.admission=admission;self.directory=directory;self.path=directory/(operation_id+'.json') ++ self.expected_version=expected_version;self.kid=kid;self.attempted=False ++ self.receipt={'schema':'railiance-platform.signer-cas-receipt.v1','operation_id':operation_id, ++ 'bindings':dict(bindings),'writer_sha256':'sha256:'+hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), ++ 'actor':'synthetic-owner-fixture','created_at':datetime.now(timezone.utc).isoformat(),'path':PATH,'expected_version':expected_version,'kid':kid, ++ 'status':'prepared','production_admission':False,'rollback':'forward-recovery-only', ++ 'public_key':None,'public_fingerprint':None,'kv_version':None,'exact_readback':False} ++ self._save(initial=True) ++ ++ def _save(self,*,initial=False): ++ raw=encoded(self.receipt) ++ if len(raw)>65536:raise Refused('receipt bound exceeded') ++ if initial: ++ target=self.path ++ else: ++ fd=os.open(self.path,os.O_RDONLY|os.O_NOFOLLOW|os.O_NONBLOCK) ++ try:Journal._private(os.fstat(fd)) ++ finally:os.close(fd) ++ target=self.directory/('.pending-'+secrets.token_hex(16)) ++ fd=os.open(target,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600) ++ try: ++ with os.fdopen(fd,'wb',closefd=False) as stream:stream.write(raw);stream.flush();os.fsync(fd) ++ finally:os.close(fd) ++ if not initial:os.replace(target,self.path) ++ fd=os.open(self.directory,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW) ++ try:os.fsync(fd) ++ finally:os.close(fd) ++ ++ def _http(self,method,path,body=None): ++ # Fixed loopback owner process and fixed data path; never arbitrary URL. ++ if self.admission.server_process.poll() is not None:raise Refused('fixture custody backend unavailable') ++ with _absolute_budget(2.0): ++ conn=http.client.HTTPConnection('127.0.0.1',self.admission.port,timeout=2) ++ try: ++ conn.request(method,'/v1/'+path,body=None if body is None else encoded(body),headers={ ++ 'X-Vault-Token':self.admission.owner_token,'Content-Type':'application/json'}) ++ response=conn.getresponse();raw=response.read(1048577) ++ if len(raw)>1048576:raise Refused('backend response bound exceeded') ++ value=json.loads(raw,object_pairs_hook=_json_unique,parse_constant=_invalid_constant) if raw else {} ++ return response.status,value ++ finally:conn.close() ++ ++ def write(self): ++ if self.attempted:raise Refused('signer operation already attempted') ++ self.attempted=True ++ # All source/receipt checks precede generation; no seed import, argv, ++ # environment, temporary file or public output interface exists. ++ private=Ed25519PrivateKey.generate() ++ seed=b64(private.private_bytes(serialization.Encoding.Raw,serialization.PrivateFormat.Raw,serialization.NoEncryption())) ++ public=b64(private.public_key().public_bytes(serialization.Encoding.Raw,serialization.PublicFormat.Raw)) ++ document={'ED25519_PRIVATE_KEY':seed,'ED25519_PUBLIC_KEY':public,'kid':self.kid} ++ self.receipt.update(status='write-intent-unknown',public_key=public, ++ public_fingerprint='sha256:'+hashlib.sha256(public.encode()).hexdigest()) ++ self._save() # A durable intent must exist before any possible effect. ++ try: ++ status,result=self._http('POST',PATH,{'options':{'cas':self.expected_version},'data':document}) ++ if status!=200 or type(result) is not dict:raise Refused('signer write unconfirmed') ++ version=result.get('data',{}).get('version') ++ if type(version) is not int or version!=self.expected_version+1:raise Refused('signer write version unconfirmed') ++ self.receipt['kv_version']=version ++ status,result=self._http('GET',PATH+'?version='+str(version)) ++ if status!=200 or type(result) is not dict:raise Refused('signer readback unconfirmed') ++ data=result.get('data',{});stored=data.get('data') if type(data) is dict else None ++ metadata=data.get('metadata') if type(data) is dict else None ++ if (type(stored) is not dict or set(stored)!=FIELDS or any(type(v) is not str for v in stored.values()) ++ or type(metadata) is not dict or type(metadata.get('version')) is not int or metadata['version']!=version ++ or any(not hmac.compare_digest(stored[name],document[name]) for name in FIELDS)): ++ raise Refused('signer readback mismatch') ++ self.receipt.update(status='custody-verified-pending-independent-public-admission',exact_readback=True) ++ self._save() ++ return dict(self.receipt) ++ except BaseException: ++ # Persist only closed metadata; unknown never implies absence or retry. ++ # If receipt storage fails, the durable earlier intent remains unknown. ++ self.receipt.update(status='write-intent-unknown',exact_readback=False) ++ self._save() ++ raise Refused('signer custody outcome unconfirmed') from None ++ ++ ++if __name__=='__main__': ++ raise SystemExit('production signer custody unadmitted; no live entry point') +diff --git a/tests/test_flex_auth_signer_custody.py b/tests/test_flex_auth_signer_custody.py +new file mode 100644 +index 0000000..797b657 +--- /dev/null ++++ b/tests/test_flex_auth_signer_custody.py +@@ -0,0 +1,115 @@ ++"""Actual disposable KV CAS/readback; no estate key, identity or grants.""" ++from dataclasses import replace ++import base64 ++import json ++from pathlib import Path ++import sys ++ ++import pytest ++from cryptography.hazmat.primitives import serialization ++from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey ++sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'scripts')) ++from test_task_execution_native_fixture import bao_dev ++from flex_auth_signer_custody import SignerWriter,FixtureWriterAdmission,BINDINGS,PATH ++from task_execution_journal import Refused ++ ++ ++@pytest.fixture ++def fixture(bao_dev,tmp_path): ++ origin,root,call,process=bao_dev ++ assert call('POST','sys/mounts/platform',{'type':'kv','options':{'version':'2'}})[0] in {200,204} ++ directory=tmp_path/'receipts';directory.mkdir(mode=0o700) ++ admission=FixtureWriterAdmission(int(origin.rsplit(':',1)[1]),root,process,True) ++ def writer(operation='first',version=0,**kwargs): ++ return SignerWriter(admission,directory,operation,kid=kwargs.pop('kid','synthetic-key-'+str(version)), ++ expected_version=version,bindings={key:'sha256:'+'a'*64 for key in BINDINGS},**kwargs) ++ return writer,call,directory,admission ++ ++ ++def test_actual_bootstrap_rotation_public_correspondence_and_cas_conflict(fixture): ++ writer,call,directory,admission=fixture ++ first=writer();receipt=first.write() ++ assert receipt['status']=='custody-verified-pending-independent-public-admission' ++ assert receipt['kv_version']==1 and receipt['exact_readback'] ++ document=call('GET',PATH)[1]['data']['data'] ++ seed=base64.urlsafe_b64decode(document['ED25519_PRIVATE_KEY']+'=') ++ public=Ed25519PrivateKey.from_private_bytes(seed).public_key().public_bytes(serialization.Encoding.Raw,serialization.PublicFormat.Raw) ++ assert len(seed)==32 ++ assert base64.urlsafe_b64encode(public).decode().rstrip('=')==receipt['public_key']==document['ED25519_PUBLIC_KEY'] ++ raw=(directory/'first.json').read_bytes() ++ assert document['ED25519_PRIVATE_KEY'].encode() not in raw and admission.owner_token.encode() not in raw ++ assert (directory/'first.json').stat().st_mode&0o777==0o600 ++ with pytest.raises(Refused):first.write() ++ with pytest.raises(FileExistsError):writer() ++ conflict=writer('conflict',0) ++ with pytest.raises(Refused,match='outcome unconfirmed'):conflict.write() ++ assert json.loads((directory/'conflict.json').read_bytes())['status']=='write-intent-unknown' ++ assert call('GET',PATH)[1]['data']['metadata']['version']==1 ++ second=writer('rotation',1,kid='synthetic-successor').write() ++ assert second['kv_version']==2 and second['public_key']!=receipt['public_key'] ++ assert call('GET',PATH+'?version=1')[1]['data']['data']==document ++ assert call('GET',PATH)[1]['data']['data']['kid']=='synthetic-successor' ++ ++ ++@pytest.mark.parametrize('case',['lost-response','readback-mismatch','read-denied','write-denied']) ++def test_unknown_is_durable_and_no_retry_or_private_output(fixture,monkeypatch,case): ++ factory,call,directory,admission=fixture ++ writer=factory();original=writer._http;seen=[] ++ def fault(method,path,body=None): ++ seen.append((method,path)) ++ if case=='write-denied' and method=='POST':return 403,{'errors':['synthetic secret backend detail']} ++ if case=='read-denied' and method=='GET':return 403,{'errors':['synthetic secret backend detail']} ++ result=original(method,path,body) ++ if case=='lost-response' and method=='POST':raise OSError('synthetic secret backend detail') ++ if case=='readback-mismatch' and method=='GET':result[1]['data']['data']['kid']='different' ++ return result ++ monkeypatch.setattr(writer,'_http',fault) ++ with pytest.raises(Refused,match='^signer custody outcome unconfirmed$'):writer.write() ++ raw=(directory/'first.json').read_bytes();receipt=json.loads(raw) ++ assert receipt['status']=='write-intent-unknown' and receipt['exact_readback'] is False ++ assert b'synthetic secret backend detail' not in raw and admission.owner_token.encode() not in raw ++ if case!='write-denied': ++ document=call('GET',PATH)[1]['data']['data'] ++ assert document['ED25519_PRIVATE_KEY'].encode() not in raw ++ before=list(seen) ++ with pytest.raises(Refused):writer.write() ++ assert seen==before ++ with pytest.raises(FileExistsError):factory() ++ ++ ++def test_durable_intent_failure_prevents_effect(fixture,monkeypatch): ++ factory,call,directory,admission=fixture ++ writer=factory() ++ def fail(**kwargs):raise OSError('private storage failed') ++ monkeypatch.setattr(writer,'_save',fail) ++ with pytest.raises(OSError):writer.write() ++ assert call('GET',PATH)[0]==404 ++ ++ ++@pytest.mark.parametrize('case',['unfenced','wrong-port','bool-version','indirect-directory','unsafe-directory']) ++def test_invalid_custody_contract_before_generation_or_http(fixture,case): ++ factory,call,directory,admission=fixture ++ expected=0 ++ if case=='unfenced':admission=replace(admission,fenced=False) ++ elif case=='wrong-port':admission=replace(admission,port=admission.port+1) ++ elif case=='bool-version':expected=True ++ elif case=='indirect-directory': ++ link=directory.parent/'indirect';link.symlink_to(directory,target_is_directory=True);directory=link ++ elif case=='unsafe-directory':directory.chmod(0o755) ++ with pytest.raises(Refused):SignerWriter(admission,directory,'bad',kid='synthetic',expected_version=expected, ++ bindings={key:'sha256:'+'a'*64 for key in BINDINGS}) ++ assert call('GET',PATH)[0]==404 ++ ++ ++def test_failed_success_receipt_retains_unknown_after_actual_write(fixture,monkeypatch): ++ factory,call,directory,admission=fixture ++ writer=factory();original=writer._save ++ def fail_success_only(**kwargs): ++ if writer.receipt['status']=='custody-verified-pending-independent-public-admission': ++ raise OSError('synthetic receipt failure') ++ return original(**kwargs) ++ monkeypatch.setattr(writer,'_save',fail_success_only) ++ with pytest.raises(Refused,match='outcome unconfirmed'):writer.write() ++ assert call('GET',PATH)[1]['data']['metadata']['version']==1 ++ assert json.loads((directory/'first.json').read_bytes())['status']=='write-intent-unknown' ++ with pytest.raises(Refused):writer.write() +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing.md b/docs/credential-lane-designs/flex-auth-envelope-signing.md +new file mode 100644 +index 0000000..440999f +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.md +@@ -0,0 +1,161 @@ ++# Retained lifecycle PDP signer custody proposal ++ ++Proposal ID: RPF35-PDP-SIGNER-CUSTODY-20261016-R2. Preparation under ++RPF-WP-0035-T12, beneficiary FLEX-WP-0024-T06, coordinated by CUST-WP-0080. ++Status: source proposal only; no key generated, credential read, CCR admission, ++policy scope granted, package published or deployment changed. ++ ++Platform INTENT principles 3–5 require durable custody, recovery and bounded ++interfaces. Platform is Staff/PEP-shaped and is not an authorization authority. ++The exact candidate contract is `flex-auth-envelope-signing.proposal.json`. ++Sibling `.proposed` files are review inputs outside deployment discovery; they ++carry no approved CCR id and MUST NOT be applied as an admitted lane. ++ ++## Existing workload and custody boundary ++ ++Retain namespace/release/deployment `flex-auth/flex-auth-secrets-engine`, signer ++SA `system:serviceaccount:flex-auth:flex-auth-secrets-engine`, and the twelve-action ++`secrets-engine.catalog-lane.lifecycle` v2 policy. The consumer SA remains ++`system:serviceaccount:secrets-engine:secrets-engine`; retained caller audience is ++`flex-auth`. Neither consumer nor TokenReview credentials confer seed read rights. ++Access source revision `919ce25` integrates `tenancy.yaml#/workload_identity`; ++this source declaration remains separate from runtime admission. An authoritative rapp declaration remains explicit managed ++package migration debt, with reference null; no synthetic rapp tuple is created. ++Legacy image package remains `forgejo.coulomb.social/coulomb/flex-auth`. ++ ++Reuse CCR-2026-0015's dedicated namespace SecretStore, exact data-only policy, ++short-lived Kubernetes delivery login and separate protected CAS writer patterns. ++The dedicated delivery SA is NOT the signer SA. No RoleBinding, Secret read, ++TokenRequest or ExternalSecret-create permission is given to the signer/consumer. ++The controller's existing ability to mint only the delivery-SA token and namespace ++mutation restrictions must be independently proven before activation; source YAML ++does not establish those facts. Do not silently broaden ESO RBAC. ++ ++KV data `platform/data/workloads/flex-auth/envelope-signing` is read only by the ++reviewed ESO delivery role. There is no parent/list/metadata/write permission. ++Lookup-self/read and revoke-self/update support bounded session lifecycle. If ESO ++needs metadata, retain a failing receipt and review that exact scope amendment. ++The KV document has private `ED25519_PRIVATE_KEY` and public `ED25519_PUBLIC_KEY`, ++`kid`; only the private property is projected to the Secret. A public receipt ++contains kid, public key/fingerprint, KV version and exact source/deployment/policy ++bindings, authenticated independently through reviewed owner custody. Consumers ++must never read the private KV document to obtain the public key, trust `/v1/keys`, ++or derive authority from receipt shape, policy digest or this proposal. ++ ++## Seed, projection and protected writer ++ ++The attended protected writer generates a fresh 32-byte CSPRNG Ed25519 seed IN ++MEMORY in the custody process and writes unpadded strict base64url via CAS zero. ++It derives the public key there, verifies correspondence, and emits metadata only. ++No seed in argv, environment, temporary files, logs, diffs, chat, Hub or CI. ++Rotation requires exact current-version CAS. No fixture seed is promotable. ++`state_hub_preflight_lane.py` is a reusable design pattern, not an Ed25519 writer; ++the signer-specific primitive now exists in `scripts/flex_auth_signer_custody.py`, ++with a fixed disposable-only adapter. Production command/CCR admission is still ++missing and the module rejects direct live execution. ++Do not run the HMAC writer unchanged or claim D1 admission without that command. ++The read lane does not authorize writer scope. Use the existing attended ++OpenBao/warden access route; ops-warden routes and never vends this seed. ++ ++Proposed namespace SecretStore uses dedicated SA, audience `openbao`, TTL/max/ ++explicit max 15m, no default policy, no periodic token. Proposed Secret name ++`flex-auth-secrets-engine-envelope-signing`, key `seed`; owner creation and Retain ++deletion policy avoid implicit removal on custody outage. Retain also means a ++compromised seed survives until explicit cleanup: disabling ESO is not revocation. ++The current Access chart supplies readOnly volume, defaultMode 0440 and uid/gid/ ++fsGroup 65532. Seed path is `/var/run/secrets/decision-envelope-signing/seed`; ++private data is never envFrom. Runtime validates file mode and reads once at ++startup, so ESO refresh alone cannot rotate process memory. Freeze exact Secret ++resourceVersion, KV version, public admission and startup kid together; require ++all replicas loaded the same admitted version before probes. No extra key reload ++mechanism is proposed. ++ ++## Durable evidence and output limits ++ ++Reuse current Access `outbox.enabled`, existingClaim and source support: ++`--outbox-dir` plus `--emission-source`, replicaCount 1, Recreate, one writer/PVC. ++Do not combine with `--log`. Outbox AppendBatch fsyncs the source envelope before ++returning; ordinary JSONL alone does not prove native independent custody. ++Existing outbox has no total-byte retention ceiling: chart size 1Gi is requested ++storage, NOT an enforced log quota. Before rollout name admitted existing PVC, ++capacity/headroom, alerts, bounded export/retention, disk-full fail-closed behavior, ++restart/partial-write readback tests and independent receiver/audit receipt. ++Audit sender credential/receiver admission is separate, not created by this lane. ++Do not silently create a PVC/spend commitment or enable arbitrary audit egress. ++No current native durable/audit acceptance follows from the source feature. ++ ++Protected writer success/failure receipts must be closed metadata objects, at ++most 64KiB, stored owner-only mode 0600 with atomic durable writes. Fields: proposal ++and executed revision digests, actor/time, exact path, CAS version, kid/public ++fingerprint, deployment/image/policy/trust digests, boolean checks, rollback outcome. ++Never include response bodies, seed, bearer tokens, accessors, wrapped values, ++process environment or exception text. Bound backend reads to 1MiB and safe error ++codes; no shell tracing. Public admission may carry the public key and must have ++independent authenticated delivery. Access R2 native proof reader bounds receipt ++reads to 524289 bytes, rejecting >524288; that is not a durable writer quota. ++ ++## Rotation, revocation and rollback ++ ++Admit successor public key to each consumer first through independent custody ++and verify seed/public correspondence in the protected custody writer. Fence ++protected consumers and stop every signer replica, prove no old-key process ++remains, CAS-rotate, wait ESO version, restart the one-writer pin, then verify ++successor-signed non-effect lifecycle allow/deny and durable originals before ++reopening protected consumers. ++After last old issuance retain old key online no longer than actual maximum allow ++TTL plus a reviewed bounded uncertainty margin (default TTL is not a guarantee). ++Keep archived historical keys for offline audit separate from online trust; verify ++expired envelopes remain refused. Emergency compromise removes the old online key ++immediately, stops old processes, and recovers forward; never restore revoked seed. ++No scope/admission change to task policy: service pilot stays hard DENY and ++execute-ccr stays unknown_action on lifecycle policy. ++ ++On signer rollout failure, stop protected consumers and restore exact previous ++producer image/values only as availability rollback; enforcing consumers continue ++to reject unsigned decisions. Outbox/PVC and source receipts are retained. Revert ++seed only for independently reviewed non-compromise recovery with corresponding ++public admission; otherwise forward recovery. If grant or effect outcome is unknown, ++retain unknown and reconcile; never auto-retry or translate it to success. ++ ++## Gates and next owner work ++ ++The JSON lists exact missing inputs and approvals. Oct11 D1 preapproves a reviewed ++receipt-producing lane for an attended window; it does not create an unbuilt lane. ++Oct11 standing build-mode rule permits qualifying non-destructive rollout after ++reviewed diff/dry-run, rollback, abort owner and receipts; new secret/access scope ++still needs founder approval. Source reviews are not human approval. Supervision ++record remains supervised; costs/risk and exact executor must be admitted for the ++executable revision. Source preparation costs EUR 0 incremental infrastructure; ++future resource/custody loss bounds are null rather than guessed or self-approved. ++ ++Next Platform admission task under RPF-WP-0035-T12: stage a schema-valid proposed ++CCR through existing credential-change tooling and independently admit the ++protected production executor/fencing/receipt adapter after required approvers ++confirm the exact new custody scope. The primitive is source-tested only. Reuse existing lane ++machinery. A receipt-producing command does not grant its write/read scope. ++Keep CCR-2026-0048/0049, WORK-RECORDS and unrelated work unchanged. ++ ++## Executable source primitive R2 ++ ++The fixed disposable owner adapter reuses the native fixture's absolute two-second ++transport/body/close bound and private receipt checks. It generates a new Ed25519 ++seed only in the custody process, derives its public key, CAS-writes the exact ++three-field document, and independently reads that exact KV version. The private ++value is compared in memory; receipts carry public key/fingerprint and version ++only. Rotation must CAS the expected current version and uses a fresh seed/kid. ++The fixture requires explicit owner fencing and a still-live exact loopback dev ++process. It cannot establish production fencing, process isolation or grant scope. ++ ++The owner-only receipt is exclusive per operation, bounded64KiB, fsynced before ++any effect, atomically replaced and directory-fsynced. Once write intent exists, ++any denied/malformed/lost response or mismatched readback retains unknown. Neither ++a repeated object call nor process restart using that operation receipt can retry. ++There is no automatic reconciliation, rollback or seed restore. A public receipt ++requires independent authenticated owner delivery before any consumer admits it. ++Python cannot guarantee seed zeroization; the protected process lifetime remains ++the custody boundary. Same-UID code is not isolated by0600 files. ++ ++Actual disposable tests prove bootstrap CAS0, versioned readback, seed/public ++correspondence, rotation CAS1, stale CAS conflict, response-loss uncertainty, ++read denial/mismatch, pre-effect durable-intent failure, receipt secrecy, retry ++refusal and invalid admission/fencing rejection. No fixture key is promotable. +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json b/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json +new file mode 100644 +index 0000000..cc10da1 +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json +@@ -0,0 +1,118 @@ ++{ ++ "schema": "railiance-platform.signer-custody-proposal.v1", ++ "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R2", ++ "status": "source-proposal-unadmitted", ++ "owner": "railiance-platform", ++ "work_item": "RPF-WP-0035-T12", ++ "coordination": "CUST-WP-0080", ++ "beneficiary": "FLEX-WP-0024-T06", ++ "scope": { ++ "namespace": "flex-auth", ++ "release": "flex-auth-secrets-engine", ++ "signer_principal": "system:serviceaccount:flex-auth:flex-auth-secrets-engine", ++ "consumer_principal": "system:serviceaccount:secrets-engine:secrets-engine", ++ "rapp_declaration_ref": null, ++ "migration_debt": "Managed package declaration not established; retained Helm workload is not an exemption.", ++ "access_identity_source": "access-engine integrated source revision 919ce25 tenancy.yaml#/workload_identity; runtime admission remains separate" ++ }, ++ "proposed_lane": { ++ "catalog_id": "flex-auth-decision-envelope-signing-key", ++ "route_status": "draft/nonresolvable", ++ "kv_mount": "platform", ++ "kv_path": "workloads/flex-auth/envelope-signing", ++ "private_field": "ED25519_PRIVATE_KEY", ++ "public_fields": [ ++ "ED25519_PUBLIC_KEY", ++ "kid" ++ ], ++ "policy": "workload-kv-read-flex-auth-envelope-signing", ++ "auth_mount": "kubernetes", ++ "auth_role": "flex-auth-envelope-signing-eso", ++ "delivery_sa": "flex-auth-envelope-signing-eso", ++ "audience": "openbao", ++ "token_ttl": "15m", ++ "token_max_ttl": "15m", ++ "token_explicit_max_ttl": "15m", ++ "token_no_default_policy": true, ++ "secret_store": "openbao-flex-auth-envelope-signing", ++ "secret_name": "flex-auth-secrets-engine-envelope-signing", ++ "secret_key": "seed", ++ "mount_path": "/var/run/secrets/decision-envelope-signing/seed", ++ "mode": "0440", ++ "private_encoding": "unpadded strict base64url of 32-byte Ed25519 seed", ++ "seed_load": "startup only" ++ }, ++ "independent_public_admission": { ++ "kid": null, ++ "public_key": null, ++ "fingerprint": null, ++ "custody_receipt": null, ++ "consumer_trust_digest": null, ++ "rule": "Owner-authenticated public receipt independently installed with exact evaluator/mode/policy pins; no self-discovery or private KV read by consumer." ++ }, ++ "required_approvals": [ ++ { ++ "actor": "founder", ++ "scope": "New exact KV read/write custody policy scope and dedicated delivery role; exact proposed CCR/revision and owner reviews required; no approval inferred." ++ }, ++ { ++ "actor": "Access owner", ++ "scope": "Exact retained workload identity/source, signer interface, unchanged policy/caller binding, image provenance and producer rollout." ++ }, ++ { ++ "actor": "Platform owner", ++ "scope": "Custody path, protected CAS writer, delivery identity/role and recovery receipts; this source review only." ++ }, ++ { ++ "actor": "Secrets owner", ++ "scope": "Independent public key/trust pins, installed helper provenance and fail-closed native consumer acceptance." ++ }, ++ { ++ "actor": "cluster/GitOps owner", ++ "scope": "Namespace SecretStore/ESO TokenRequest restrictions, manifests, rollout/headroom, existing PVC and recovery." ++ } ++ ], ++ "missing_deployment_inputs": { ++ "schema_valid_reviewed_CCR": null, ++ "human_exact_scope_decision": null, ++ "protected_signer_writer_command_digest": null, ++ "approved_executor_and_abort_owner": null, ++ "access_identity_integrated_revision": "919ce25", ++ "managed_package_admission_or_explicit_debt_disposition": null, ++ "CI_source_to_image_receipt": null, ++ "candidate_image_digest": null, ++ "KV_and_Secret_safe_version_receipt": null, ++ "native_identity_and_negative_scope_receipt": null, ++ "consumer_native_allow_deny_receipts": null, ++ "PVC_and_capacity_retention_admission": null, ++ "durable_original_and_independent_audit_receipt": null, ++ "reviewed_diff_server_dryrun_and_headroom": null, ++ "rotation_revocation_and_recovery_receipts": null, ++ "activation_cost_bound_eur": null, ++ "activation_risk_bound_eur": null ++ }, ++ "unchanged_policy": { ++ "package": "secrets-engine.catalog-lane.lifecycle", ++ "version": "v2", ++ "digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4", ++ "caller_auth": "enforce", ++ "caller_audience": "flex-auth", ++ "execute_ccr": "DENY unknown_action", ++ "service_pilot": "runtime_admission false" ++ }, ++ "execution": { ++ "authorized_by_this_proposal": false, ++ "key_created": false, ++ "route_promoted": false, ++ "live_changes": false, ++ "preparation_incremental_spend_eur": 0 ++ }, ++ "source_writer": { ++ "path": "scripts/flex_auth_signer_custody.py", ++ "scope": "protected in-memory Ed25519 CAS/readback primitive, disposable-only fixed owner fixture adapter", ++ "production_entry": "refused pending exact CCR/founder scope/protected runtime/fencing/receipt admission", ++ "independent_public_admission": "required after custody verification; receipt shape supplies no trust authority", ++ "retry": "none after durable intent; unknown requires independent reconciliation, no remint", ++ "rollback": "forward recovery; no seed restore primitive" ++ } ++} +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed b/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed +new file mode 100644 +index 0000000..e96f5f9 +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed +@@ -0,0 +1,10 @@ ++# SOURCE PROPOSAL ONLY. New scope remains founder-gated; no metadata/list/write. ++path "platform/data/workloads/flex-auth/envelope-signing" { ++ capabilities = ["read"] ++} ++path "auth/token/lookup-self" { ++ capabilities = ["read"] ++} ++path "auth/token/revoke-self" { ++ capabilities = ["update"] ++} +diff --git a/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed b/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed +new file mode 100644 +index 0000000..ad8181e +--- /dev/null ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed +@@ -0,0 +1,50 @@ ++# SOURCE PROPOSAL ONLY: no CCR admission, no apply, no plaintext key. ++apiVersion: v1 ++kind: ServiceAccount ++metadata: ++ name: flex-auth-envelope-signing-eso ++ namespace: flex-auth ++automountServiceAccountToken: false ++--- ++apiVersion: external-secrets.io/v1 ++kind: SecretStore ++metadata: ++ name: openbao-flex-auth-envelope-signing ++ namespace: flex-auth ++spec: ++ provider: ++ vault: ++ server: http://openbao.openbao.svc:8200 ++ path: platform ++ version: v2 ++ auth: ++ kubernetes: ++ mountPath: kubernetes ++ role: flex-auth-envelope-signing-eso ++ serviceAccountRef: ++ name: flex-auth-envelope-signing-eso ++ audiences: [openbao] ++--- ++apiVersion: external-secrets.io/v1 ++kind: ExternalSecret ++metadata: ++ name: flex-auth-secrets-engine-envelope-signing ++ namespace: flex-auth ++spec: ++ refreshInterval: 5m ++ secretStoreRef: ++ kind: SecretStore ++ name: openbao-flex-auth-envelope-signing ++ target: ++ name: flex-auth-secrets-engine-envelope-signing ++ creationPolicy: Owner ++ deletionPolicy: Retain ++ template: ++ metadata: ++ annotations: ++ railiance.io/custody-proposal: RPF35-PDP-SIGNER-CUSTODY-20261016-R1 ++ data: ++ - secretKey: seed ++ remoteRef: ++ key: workloads/flex-auth/envelope-signing ++ property: ED25519_PRIVATE_KEY +--- a/workplans/RPF-WP-0035-credential-lane-implementation.md ++++ b/workplans/RPF-WP-0035-credential-lane-implementation.md +@@ -1330,3 +1330,13 @@ + This owner fixture uses separately installed synthetic identity/key/trust and + loopback OpenBao, grants no production authority and keeps T12 progress. Prior + failed temporal/normalization proofs remain retained. ++ ++2026-10-16 T12 signer custody R2 source preparation rebases the proposal to ++integrated Access919ce25 and preserves current workplan state. Added protected ++in-memory Ed25519 CAS/readback primitive with durable closed metadata receipts ++and fixed disposable-only owner adapter. Actual synthetic OpenBao bootstrap, ++rotation, conflict/unknown/readback/receipt/private-output and admission failures ++are tested. Production direct entry refuses: exact CCR/founder scope, protected ++executor/fencing/receipt custody, independent consumer public admission, migration ++debt and native deployment prerequisites remain open. No live key/grant or CCR ++admission; RPF-WP-0035-T12 remains progress. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/manifest.json new file mode 100644 index 00000000..3cfd35bf --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/manifest.json @@ -0,0 +1,43 @@ +{ + "schema": "railiance-platform.signer-writer-source.v1", + "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R2", + "canonical_base": "b9eaa200601f1226d13efe82472dfec81c2999aa", + "isolated_base": "87efed36e8af6ae78247fb2d725f303a68110a18", + "isolated_source": "/tmp/netkingdom-platform-signer-writer-20261016", + "requires_budget_source_slice_sha256": "7c17f607dacc9ed4f24fd8032ddac5f4fc9ae2f24555cf87a0b73c871ec8eb19", + "workplan_preimage_requires_fullchain_patch_sha256": "a26c68ff224663129757fd43d0a5364762180131030e4dda22975935be89f99d", + "preserves_signer_R1_patch_sha256": "0f31567718023cdf2e2c1b3a5d8c8916312fd44b039b9bc32a2e404011fe4a57", + "Access_identity_integrated_revision": "919ce25", + "files": { + "scripts/flex_auth_signer_custody.py": { + "before_sha256": null, + "after_sha256": "8ed281a49c1f1cdb23772efe3593e75c62572a12b8d7a6a4c574f27b38722e75" + }, + "tests/test_flex_auth_signer_custody.py": { + "before_sha256": null, + "after_sha256": "cd47c33bda7a2a18808e0daa027e8a66b2a55eaf0ee79e603337f3c2eb2c3761" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing.md": { + "before_sha256": null, + "after_sha256": "43c80cafaae1cfeee76324d15def9006553de7e1e90a98252fac9aaf778fd445" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json": { + "before_sha256": null, + "after_sha256": "6e798b51c25526463aa0401aa5df6e9d1a0bb754a67c7c5d96876c02dfe03266" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-policy.hcl.proposed": { + "before_sha256": null, + "after_sha256": "a8ae0ea97e5bde8a9e5d785fc87b8095e4cc24b5fcf358a4b7b1568ab1dd07ee" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed": { + "before_sha256": null, + "after_sha256": "4fde665568dedc5dd800e16f11e6dbfca83ea41d955efdb1fccef3976f35d6dc" + }, + "workplans/RPF-WP-0035-credential-lane-implementation.md": { + "before_sha256": "9a669a7ff80345885edc6ac6a6333c3bdb3587a862a81fe672b1057a40940598", + "after_sha256": "65a4350d5720acc476bf5ae8e366ce37d9e3b47f7f339e8834eba3e84c1c8b65" + } + }, + "production_admission": false, + "patch_sha256": "b0c190060f5a41d6002e1fb7b49f047fd4874a51576f29f3c127a8634c2616f6" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/owner-review.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/owner-review.json new file mode 100644 index 00000000..faf7c331 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/owner-review.json @@ -0,0 +1,32 @@ +{ + "schema": "railiance-platform.owner-source-review.v1", + "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R2", + "reviewer_role": "railiance-platform-owner", + "agent": "railiance-platform (codex)", + "reviewed_revision_sha256": "b0c190060f5a41d6002e1fb7b49f047fd4874a51576f29f3c127a8634c2616f6", + "disposition": "approve-source-only", + "basis": "RPF-WP-0035-T12, existing Platform INTENT custody/recovery/bounded-interface principles and delegated source authorization", + "assessment": "Signer-specific in-memory Ed25519 primitive and exact CAS/readback now execute against disposable OpenBao; exclusive durable metadata receipts precede effects and preserve unknown. No private material is exposed by receipt or direct command. Proposal references integrated Access919ce25 without creating runtime admission or managed package declaration.", + "limitations": [ + "production entry deliberately refuses; reviewed native protected adapter still required", + "exact schema-valid CCR and new custody scope founder decision absent", + "fixture fenced boolean is synthetic owner input, not proof of stopped production replicas", + "0600 custody does not isolate hostile same-UID code", + "Python seed zeroization not guaranteed; protected process lifetime/isolation must be admitted", + "public receipt is not independent authenticated consumer trust admission", + "no role/ESO/Kubernetes/GitOps mutation or native scope acceptance", + "no rollback/seed restore/retry; unknown requires independently admitted reconciliation" + ], + "preserved": [ + "original signer R1", + "frozen recovery R2", + "budget/source slice", + "fullchain successor proof/workplan", + "CCR-2026-0048", + "CCR-2026-0049", + "WORK-RECORDS.md" + ], + "preparation_incremental_eur": 0, + "production_cost_risk_bound": null, + "authority_granted": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md new file mode 100644 index 00000000..0c4eace2 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -0,0 +1,1332 @@ +--- +id: RPF-WP-0035 +type: workplan +title: "Implement reviewed credential lanes with separate owner gates" +domain: financials +repo: railiance-platform +status: blocked +flavor: implementation +owner: codex +created: "2026-09-05" +updated: "2026-10-13" +related: + - RPF-WP-0032 + - RPF-WP-0033 + - RPF-WP-0034 +state_hub_workstream_id: "975db491-5412-5e27-8e34-14a2417bb039" +--- + +# Credential lane implementation + +One S3 queue for three designed lanes; each task keeps its own approval, +execution and closure boundary. This replaces the implementation tasks in the +three completed design workplans, not the designs themselves. No approval is +inherited by consolidation. INTENT binding: secure custody, dependable delivery, +stable consumer interfaces. Incident custody remains in RPF-WP-0027/0029. + +## Consolidate completed designs and owner dependencies + +```task +id: RPF-WP-0035-T01 +status: done +priority: medium +state_hub_task_id: "0f3606bb-e95b-5484-8a57-bcdd6e3916fd" +``` + +Completed 2026-09-05. Preserved the three designs under +`docs/credential-lane-designs/`, identified native owner responsibilities and +linked each superseded task below. Owners have not been sent new requests and +no new external acceptance is claimed. STATE-WP-0085-T09 is already done; +the signing dependency belongs to the proposed FLEX-WP-0020-T05 cutover. + +## Accept and provision secrets-engine service JWT login + +```task +id: RPF-WP-0035-T02 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +depends_on: [KEY-WP-0039-T02, MASON-WP-0009-T05] +blocking_reason: "Agent work, not a human gate: claim refusals (KEY-WP-0039-T02 probe) and capabilities-self deny, then ops-mason MASON-WP-0009-T05." +priority: high +state_hub_task_id: "e0c82ea9-05a5-537e-8fbf-67534263572e" +``` + +2026-10-11: requalified — the remaining waits are other owners' tasks, not a human gate. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0032-T02. Design: +`docs/credential-lane-designs/secrets-engine-service-jwt.md`. + +Platform owns the exact JWT mount/role/policy, effective-policy negative tests +and a metadata-only custody receipt. KeyCape owns issuer/JWKS and service +registration (KEY-WP-0009); secrets-engine owns service authentication and +authority consumption (SECRETS-WP-0008-T06, SECRETS-WP-0007-T04). + +**Unblock:** live registration and protected client custody, reviewed exact source +and attended apply authority. Issuer/JWKS and consumer source claims now agree; +see the 2026-09-27 return below. A service login does +not grant lane mutation authority. Do not build another identity provider or +lifecycle engine here. + +**Done when:** approved exact role succeeds for the intended service, wrong +issuer/audience/subject/claims and unrelated secret access fail, bounded TTL +and revocation are proven, the consumer explicitly opts into the verified +contract, and rollback/cleanup receipts contain no secret material. + +2026-10-09 (T03 source): founder ruled the tenant segment stays `coulomb` +(ops-mason `b72ff77d`). New CCR request type `workload-kv-operator-matrix` +(`scripts/operator_matrix_lane.py`): exact per-entry capabilities, OIDC role on +the existing `netkingdom` mount only, and exact agent denies on all four data +and metadata paths appended to the live `agent-high-risk-boundary` (live content +preserved; partial presence refused). `scripts/fluid_telegram_custody_move.py` +copies the four undocumented `infotech` entries with CAS 0, verifies all, then +metadata-deletes the sources. `scripts/kv_duplicate_retire.py` retires +`activity-core/default/llm-connect-provider-secrets` only if no live non-admin +policy grants it. Founder session (each helper prints nothing; read the receipts): + +```bash +cd ~/railiance-platform +export BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 +W='warden access openbao-platform-admin-login --exec --' +# 1. dry-runs (no value reads, no writes) +$W python3 scripts/fluid_telegram_custody_move.py --dry-run --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move-dry.json +$W python3 scripts/kv_duplicate_retire.py --dry-run --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire-dry.json +# 2. lane: approve, confirm binding, apply +python3 scripts/credential-change.py approve CCR-2026-0039 --reviewer "platform-owner, fluid-telegram-owner, key-cape-owner (founder Bernd Worsch)" --comment "Approve ops-mason plan fluid-telegram-operator-credential-lane (spec 41a0ca27): four-entry matrix at coulomb/fluid-telegram/hall-of-helix, OIDC role on netkingdom, agent denies." \ + && python3 scripts/credential-change.py confirm-binding CCR-2026-0039 --reviewer founder --comment "groups=[fluid-telegram-operators] (LLDAP, member tegwick) and /assurance/level=aal2 match key-cape b2ed890f." \ + && $W python3 scripts/credential-change.py applier-apply CCR-2026-0039 --confirm "DELEGATED APPLY CCR-2026-0039" --actor founder --record-state-hub --quiet +# 3. custody move, then duplicate retirement +$W python3 scripts/fluid_telegram_custody_move.py --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move.json +$W python3 scripts/kv_duplicate_retire.py --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire.json +``` + +2026-10-09 (T03 founder session): CCR-2026-0039 applied at 10:30Z; readback +matched for the 8 boundary denies, policy and role. Custody move `moved`: all +four entries copied at coulomb v1 (operator-session from infotech v4) and the +infotech entries metadata-deleted. Duplicate +`activity-core/default/llm-connect-provider-secrets` retired; its first dry-run +refused on mount-wide `platform/metadata/*` survey grants, after which the check +was narrowed to data-path grants (`64ae594`). Receipts: +`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +2026-10-03 (CUST-WP-0075): gate check. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named in the design is open. It is not the last one: the design says to confirm the exact live client registration and protected client-side custody before writing, and positive-login proof needs a real KeyCape service JWT. KeyCape's contract (`openbao-service-auth-contract.md`) and KEY-WP-0009 claim source registration only; the live registration of `secrets-engine-openbao` and its client-credential custody are "a separate approved custody action" that no workplan task owns yet (SECRETS-WP-0008-T06 waits on this task). Re-qualified with `blocked_on: message-from:key-cape`; key-cape was asked for the owning task id, which will replace it as `depends_on`. The design stays proposed and no child command was written. Not approvable in D1 yet. + +2026-10-04: Founder authorized the prepared coordination request. Sent +`b4fc62ea-f92c-4410-919a-9f3cce2d406b` to key-cape on preparation thread +`f84637fa-2355-4971-a2dc-7f1fd01710a8`, referencing platform source +`6b91d510395215d178d60ee8884e7fc00930a0cf`. Requested actual registration and +protected-custody owning tasks/status/revisions and non-secret receipts. Source +registration is not live custody; no value fetch or live registration was +requested. T02 remains waiting on the owner return and separate execution gates. + +2026-10-04 blocked-task review: KeyCape returns 58826056/eb20a78c now identify +KEY-WP-0037-T02/T03/T04, replacing the unowned-registration wait with real +dependencies. Prepared proposed CCR-2026-0033 and exact-path issuer policy/auth, +sso-only ESO and evidence checklist from the returned candidate coordinates. +No issuer/consumer value, registration or native issuance is supplied by them. +secrets-engine must return independent source acceptance of consumer host/path, +protected delivery and rotation/revocation ownership; awaiting that source phase +does not depend on its full live service-login task. KeyCape's exact-primary sync +remains pending its scoped historical identity repair. Requirements and acceptance +boundaries: `docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`. +This workplan was already blocked and remains blocked on its open owner/live gates. + +2026-10-06: secrets-engine returned consumer custody source acceptance +(message 680136e2, SECRETS-WP-0012, commit a3897c2). CCR-2026-0033 finalized as +**proposed**: KV path corrected to `platform/workloads/keycape/secrets-engine-openbao` +(applier scope), consumer copy coordinates with D1-D4 pending founder choice, +rotation/revocation ownership, live order and rollback. Attended custody child +`scripts/keycape_secrets_engine_openbao_custody.py` with fake-only tests +(`tests/test_keycape_secrets_engine_openbao_custody.py`) refuses without an exact +founder decision id recorded in the approved CCR. Nothing executed, generated or +applied; nothing added to active GitOps. The founder approval it needs is T09. + +2026-10-09: KEY-WP-0037 finished 2026-10-07 (registration live, issuance +verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Source for this +lane is now complete as **CCR-2026-0038** (proposed, +`credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml`). +The delegated applier gained a narrow `service-jwt-login` request type +(`scripts/service_jwt_lane.py`): auth mount fixed to `keycape-services`, policy +must equal the generated login-self policy, role/config keys allow-listed, +TTLs at most 15m, uses 1..16, `token_no_default_policy`, refusal if the mount +exists with another type, and a value-free readback compare after the writes. +Policy `secrets-engine-login-self` now also carries explicit `deny` on +`platform/{data,metadata}/workloads/keycape/secrets-engine-openbao` so +ops-mason invariant (ii) (no capability on the client-secret path) holds even +if identity groups were ever attached. Tests: `tests/test_service_jwt_lane.py` +(8) plus the updated contract test; full suite unchanged apart from 5 +pre-existing failures unrelated to this lane. + +Founder apply (one line; approval, binding confirmation and silent apply): + +```bash +cd /home/worsch/railiance-platform && python3 scripts/credential-change.py approve CCR-2026-0038 --reviewer "platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd Worsch)" --comment "Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self (self endpoints + deny on the client-secret path)." && python3 scripts/credential-change.py confirm-binding CCR-2026-0038 --reviewer founder --comment "Bound claims match KeyCape registration: aud secrets-engine-openbao, sub service:secrets-engine, principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social RS256." && warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/credential-change.py applier-apply CCR-2026-0038 --confirm "DELEGATED APPLY CCR-2026-0038" --actor founder --record-state-hub --quiet +``` + +Done after that: login proof with a real KeyCape service JWT +(SECRETS-WP-0012-T03 probe-openbao; policies exactly +[secrets-engine-login-self], capabilities-self deny on the guarded paths, +revoke-self), negative claim checks, then publish the consumer contract file +and ops-mason MASON-WP-0009-T05 rechecks invariant (ii). + +## Implement the platform operator-write CCR contract and Fluid lane + +```task +id: RPF-WP-0035-T03 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +blocking_reason: "Founder session done 2026-10-09; waits on ops-mason verification (MASON-WP-0005-T05) and the FT-WP-0002 owner salt CAS probe." +priority: high +depends_on: [MASON-WP-0005-T05, FT-WP-0002] +state_hub_task_id: "f47e5bc5-6f3c-54bb-aa35-260ad03892ba" +``` + +2026-10-11: requalified — founder part done; remaining waits are owner tasks. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0033-T02. Design: +`docs/credential-lane-designs/fluid-telegram-operator-kv.md`. + +Platform owns the per-path capability schema/validator, exact OpenBao policy +and accepted custody coordinates. MASON-WP-0005 owns construction coordination +and engine integration; KeyCape/NetKingdom own OIDC/MFA and group membership; +FT-WP-0002 owns client CAS, prefix correction, output containment and Telegram +application acceptance. Retain the existing read-only CCR semantics. + +**Unblock:** accept tenant/path and per-entry field/capability matrix; confirm +actual group/assurance and callbacks, reviewed construction contract and writer +authority. Contract review can proceed without a live credential; the final +schema cannot be treated as accepted solely because a draft exists. + +**Done when:** validation rejects broad/unsupported grants, the consumer proves +CAS=0 first-write behavior and no value output, approved identities can perform +only the exact matrix, negative/expiry/revocation checks pass, custody is seeded +through the separate writer, and the verified route has a safe handoff receipt. +The unattended adapter remains a separate demand and gets no operator session. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Accept the needed signing lane and deliver it to the owning runtime + +```task +id: RPF-WP-0035-T04 +status: done +priority: medium +state_hub_task_id: "35a85846-61d5-54ce-8b18-ede45733d53c" +``` + +Supersedes RPF-WP-0034-T02. Design: +`docs/credential-lane-designs/state-hub-preflight-signing.md`. + +Platform owns signing-key custody, exact read policy/role and scoped delivery +acceptance. State Hub owns API chart/env wiring, all-replica rotation fencing +and health. FLEX-WP-0020-T05 owns the rename preflight/cutover dependency; +STATE-WP-0085-T09's adoption-plan delivery is already complete. + +**Unblock:** State Hub/repo-manager and the consuming migration owner confirm +that this transitional State Hub lane is still needed during retirement; +record the target runtime, namespace/SA/auth audience and an executable +rotation fence, plus approved writer and deployment window. Do not broaden the +lane into a general repository-rename authority or provision for a stale demand. + +**Done when:** protected one-time generation, API-only ESO delivery, negative +access checks and a non-mutating signed preflight pass; every API replica uses +the accepted version; rotation/invalidation and recovery are evidenced. No +repository rename is part of S3 lane acceptance. If demand is withdrawn, record +the owning decision and cancel this task explicitly rather than provision it. + +2026-09-05 continuation: verified the live primary cluster identity and healthy +single API replica; the signing ExternalSecret is still absent. Added a writer +guard against wrong-cluster kubeconfigs before any OpenBao access. The default +workstation kubeconfig's local port-forward listener was unavailable. Activation +still needs the contained attended OIDC/MFA login and the acceptance evidence +above; source preparation is not live completion. See +`history/2026-09-05-preflight-signing-activation-readiness.md`. + + +Completed 2026-09-05: user-led attended activation generated version 1 and +rotated to version 2 with every API replica stopped. Exact access and negative +identity checks passed; ESO delivery and API-only exposure passed; the recovered +single API replica accepts new signed preflight and rejects its predecessor by +signature, with healthy primary identity and no preflight blockers. State Hub +chart commit `49e3182`, Helm revision 59. No repository rename executed. +Evidence: `docs/evidence/RPF-WP-0035-T04-signing-activation-2026-09-05.json`; +closure: `history/2026-09-05-preflight-signing-activation-complete.md`. + +## Admit KeyCape approval-engine client custody and delivery + +```task +id: RPF-WP-0035-T05 +status: done +needs_human: false +intervention_note: "" +priority: high +state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c" +``` + +Answers KEY-WP-0013-T02 (State Hub message +`278a3ebe-b529-49f6-bd1a-e3ebcf318260`). Admission: +`docs/credential-lane-designs/keycape-approval-clients.md`; requests +`CCR-2026-0017` (secrets-engine-approval) and `CCR-2026-0018` +(approval-engine-operator). + +Platform owns the two custody paths, exact-path read policies, Kubernetes auth +roles and the KeyCape-side ESO delivery. KeyCape owns the client registrations, +issuance, claim set and disablement; approval-engine owns approval semantics and +audit of emitted actions. + +2026-09-08 admission response: both proposed KV paths confirmed unchanged; field +`client_secret` corrected to `CLIENT_SECRET` for the uppercase KV convention and +CCR validator. Kubernetes delivery references confirmed against the live `sso` +namespace, which already resolves `KEYCAPE_RAPP_QONTO_CLIENT_SECRET` through the +same `secretKeyRef{key: client-secret}` shape on image `main-153258b`. Attended +authority named as the governed `openbao-platform-admin-login` lane +(`founder_required`); KeyCape's refusal to treat its generic `warden plan` +database match as authorization was correct. Rollout agreed as one attended +session with the KeyCape reading build pinned but undeployed, ordered after the +Authelia issuer precondition in message `c8b1ad10-dae8-48fb-a0ea-7e2a101c54bf`. +Policies, ClusterSecretStores and ExternalSecrets are written and validated, +none applied. + +**Unblock:** owner approval of both CCRs, a KeyCape image that reads both +environment names, the settled Authelia `iss` pin, and a founder-attended window +date. Verifier-side custody only — no client-side read lane is admitted, and no +scope beyond the two declared sets. + +**Done when:** both CCRs are approved, the attended window seeds both KV paths +with CAS=0, policies/roles/stores/ExternalSecrets apply and sync, the KeyCape +build resolves both environment names, KeyCape evidences live JWKS signature and +exact claim bindings with excess scopes denied (operator `consume`, human +`consume`), platform evidences cross-path/wrong-identity/out-of-namespace denial, +and every receipt is metadata-only. If either registration is abandoned, KeyCape +disables it before the KV version is destroyed. + +### 2026-09-08 actual upstream issuer returned + +The admitted KeyCape one-shot probe verified the actual signed upstream issuer +as **`https://auth.coulomb.social`** at 21:44:44 UTC. Signature, audience, +validity window and nonce checks passed and the pinned Job exited 0. All +five temporary resources and the Pod were removed; normal KeyCape Deployment +and config Secret metadata are unchanged. See +`docs/evidence/2026-09-08-keycape-upstream-issuer-proof.json`. + +T05's unknown-issuer input is resolved. The configuration owner still ensures +`authelia.issuer` equals that exact HTTPS value before the custody window. +Both CCRs remain proposed and await the named reviews; this probe grants no +custody mutation or client-side read. Keep the current authority preflight and +this signed-token proof as separate receipts. Live ESO/client/approval and +separate audit/client-side custody acceptance remain open. + + +2026-09-09 configuration and review-queue return: NetKingdom pinned the verified +HTTPS issuer, using an atomic UID/resourceVersion test and independent readback. +Secret revision `58713343`; unrelated configuration and signing key unchanged; +no Deployment rollout. Receipt: `docs/evidence/2026-09-09-keycape-upstream-issuer-pin.json`. + +The two existing CCRs remain proposed. They now link to concrete pending review +decisions, with platform-operator and key-cape-owner named explicitly. See +`docs/credential-lane-designs/keycape-approval-clients-review.md`. T05 owns this +human dependency; HFACT consumes it without a duplicate approval request. +Custody/ESO activation, client verification and the separate client-side/audit +lanes remain open. Current CLI apply plans refuse the proposed requests. + + +2026-09-09 admission: the user explicitly approved both CCRs in the named +platform-operator and key-cape-owner roles. Both source requests are approved +and both linked Hub decisions are resolved. Receipt: +`docs/evidence/2026-09-09-keycape-approval-admission.json`. The completed review +intervention is cleared; T05 is progress while the contained first-provision +procedure is exercised and the admitted attended rollout is carried through. +Verifier-side scope, separate client-side/audit lanes and live acceptance remain +as defined in the reviewed requests. + +2026-09-09 verifier-side return: both CCRs are verified after recorded user approval, +CAS=0 version-1 custody, native read/auth denials and revocation, Valid stores, +SecretSynced delivery, compatible KeyCape rollout and live positive/negative +service checks. Existing human OpenBao login passed again on the new image. +Receipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. Failed attempts restored the compatible +configuration/image and detached delivery; final resume reused version 1. + +T05 is done against its verifier-only acceptance criteria. Its former +"remains progress for client-side reads" statement expanded the task past its +reviewed scope; that residual now has the live owner task RPF-WP-0035-T06 below. +Neither Warden fetch selector is resolvable through these verifier-only CCRs. +Do not re-request the completed two named reviews or reseed these paths. +Rotation is a distinct, version-guarded operation. + +## Dispose of the ungoverned whynot-design npm duplicate + +```task +id: RPF-WP-0035-T07 +status: wait +decision_id: 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa +blocking_reason: "Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish." +priority: high +depends_on: [SECRETS-WP-0006-T06] +state_hub_task_id: "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b" +``` + +2026-10-11: requalified after founder decision D3 (trust root, build-mode default) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Found by the attended session on 2026-09-10 while settling the npm field +question. `secret/coulomb/whynot-design/npm/publish` exists at version 1, +created 2026-07-03T15:00:44Z and never updated — five days after the governed +lane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified +(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and +outside any CCR here. Receipt: +`docs/evidence/2026-09-10-npm-lane-field-resolution.json`. + +Only metadata was read. Its field names were not enumerated, its value was not +read, and nothing was deleted — a location holding real credential material is +disposed of deliberately, not tidied away in the session that found it. + +The likely explanation, unconfirmed: secrets-engine reports the lane's field +under a lowercase name that is absent from the governed path, and their catalog +declares this legacy location. If their proven pilot publish read from here, +then a working production lane has been running off an ungoverned duplicate, +and the governed lane's acceptance evidence describes a path the consumer does +not use. That is worth establishing before anything is removed. + +**Operator decision, 2026-09-15:** destroy the legacy path after confirming the +governed lane is the live consumer. Do not wrap `secret/coulomb/whynot-design/npm/publish` +in a CCR. Value remains unread. Platform will ask secrets-engine which path +publish actually reads before any attended destroy. + +**Unblock:** admit the governed exact-path AppRole policy and coordinated catalog +path/field migration under SECRETS-WP-0006-T06; prove native delivery from the +governed lane before the attended legacy destroy. secrets-engine confirmed the +legacy source path on 2026-09-21 (message `355424d4-17ab-435e-9e1d-6921775cb4a2`). +No comparison of values, fingerprints, lengths or shapes is needed or authorized. + +**Done when:** the legacy path's provenance and consumer are established, the +governed lane is confirmed as the one in use or the consumer is moved to it as a +reviewed lane change, the duplicate is destroyed under the September 15 operator decision and the +disposition is recorded. Do not bring the legacy duplicate under a CCR. If the value proves to be live and +ungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027: +never record the value, fingerprint, length or shape. + +2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here. + +## Admit the separate approval client-side readers + +```task +id: RPF-WP-0035-T06 +status: done +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +priority: high +intervention_note: "" +state_hub_task_id: "68bff751-e48b-548b-8fb4-dfb3b16210c2" +``` + +2026-10-11: requalified after founder decision D1 (attended window standing rule) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +**Current return, 2026-09-10:** CCR-2026-0020 is cancelled on the requesting +Approval Engine owner's explicit withdrawal, source +`849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md`. +No presenter exists and no reader is wanted. The validator now accepts terminal +cancellation of an incomplete request only with owner/source/reason evidence, +retained declared omissions and a disabled, non-resolvable front door. Apply +remains refused. No live identity, policy, role, custody or verifier was changed. +Human approval follows existing INFD-WP-0001-T07/T08; future service requesters +need a separate narrow registration, not this withdrawn bundle. + +**Operator binding confirmed, 2026-09-14:** The user explicitly selected +`net-kingdom-admins` and authorized applying CCR-2026-0019. Its OIDC role is +`secrets-engine-approval-client-workload-kv-read`, aligned with the platform +applier naming rule; policy and exact KV scope are unchanged. The metadata dry +run passes with no warnings. Attended apply and exact role/policy readback passed; the enclosing Warden +command exited successfully after its self-revocation/cleanup. Receipt: +`docs/evidence/2026-09-14-ccr0019-operator-binding.json`. Scoped delivery proof +remains pending; the front door stays non-resolvable. Completed CCR-2026-0017/0018 +remain closed and T06 stays `wait`. + +Consumer procedure returned in source, 2026-09-10: +`secrets-engine@98d72ceb1dbcff2d2a80fb8c3058d76777a0ac93:docs/approval-service-auth.md` +specifies the requested private 0700 runtime directory, 0600 file outside Git, +path-only use, claim/consume lifetime and attended cleanup including hard-stop +residual inspection. CCR-2026-0019 retains this source-review comment without +changing admission status. Exact group, required-owner review, attended apply and +native positive/negative/cleanup evidence remain. No role or credential changed. + +Separate retained owner decision: KeyCape's 2026-09-10 return +`21427688-725f-4dea-aab4-7c78fd4328d2` identifies the already-live, unpresented +CCR-2026-0018 registration. Approval Engine, KeyCape and Platform must explicitly +decide retention/expiry or coordinated disablement. Reader cancellation neither +disables that live registration nor accepts indefinite retention. Keep this +disposition in T06; it is separate from the wanted CCR-2026-0019 factory reader. +No unilateral issuer/config/Secret change is authorized by this closeout. + +**Operator decision, 2026-09-15:** coordinated disablement with KeyCape and +Approval Engine. Platform will not disable the live registration or verifier +delivery unilaterally. T06 stays `wait` until both owners confirm the joint +disablement sequence. + +Residual handoff from RPF-WP-0035-T05; consumes the completed verifier custody +without extending CCR-2026-0017/0018. Owner: railiance-platform with the named +secrets-engine and approval-engine operator consumers. + +Prepare separate exact-reader admissions for existing version-1 paths: +`platform/workloads/secrets-engine/approval-client` and +`platform/workloads/approval-engine/operator-client`, field `CLIENT_SECRET`. +Name each actual actor/placement, bounded authentication/reader policy, protected +consumer delivery, cleanup/revocation and rollback, then obtain the required +owner reviews for those concrete requests. No reseeding, rotation, shared reader, +reuse of the sso verifier Secret, or implicit operator consume grant. + +2026-09-09 preparation return: both exact-reader admissions are prepared as +`CCR-2026-0019` (secrets-engine) and `CCR-2026-0020` (approval-engine-operator), +with their exact-path read policies written and committed. Design: +`docs/credential-lane-designs/keycape-approval-client-side-readers.md`. Both +reuse existing version-1 custody; no reseed, rotation, shared reader or verifier +Secret reuse. Both are `in_flight` and unapproved; nothing is applied. + +Read-only survey findings that decided the two shapes. Namespace +`secrets-engine` holds only ServiceAccount `secrets-engine` with no workload, +and `flex-auth/flex-auth-secrets-engine` is that consumer's PDP, not the +service; secrets-engine consumes the client secret through an operator-run CLI +reading `SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE` (SECRETS-WP-0009-T03, +revision `9eb07fd`). So reader 1 is an attended operator-workstation OIDC lane, +not an ESO lane. approval-engine has no namespace, workload or Service; its +manifest is unapplied, and no owner source names who presents the operator +client — approval-engine verifies these tokens and never holds them. + +**Unblock:** reader 1 needs the exact NetKingdom/KeyCape group claim for the +authorized operator, plus secrets-engine confirming the file mode and removal +step; `openbao.auth` is declared missing rather than filled with a placeholder +that would later read as a confirmed binding. Reader 2 needs its owner to name +the presenting actor and placement, or to record that no client-side reader is +wanted so the request is cancelled. Naming a reader for the widest approval +scope without that decision is the failure this task exists to avoid. + +**Done when:** each reader has a named actor and placement, a completed and +reviewed auth binding, admitted delivery, and its owner approvals; positive and +negative checks pass, including cross-path, wrong-identity and parent-list +denial and operator `consume` denial; or the request is explicitly cancelled by +its owner. Rotation stays a distinct version-guarded operation shared with +CCR-2026-0017/0018. + + +Consumer input supplied 2026-09-09: secrets-engine now implements per-request +`secrets-engine-approval` exchange from a protected temporary client-secret file, +with exact approval-engine / tenant:platform / read-or-consume scope, no token +file and no fallback. The pinned KeyCape image and actual Approval Engine source +passed its disposable component exercise; only the PDP was a sequencing double. +See `secrets-engine/docs/approval-service-auth.md` and the metadata receipt +`secrets-engine/docs/evidence/2026-09-09-approval-identity-exercise.json`. + +Routing check: `warden route show keycape-secrets-engine-approval-client` is +unknown; generic `openbao-api-key` routes ownership only and is not a delegable +lane. Do not advertise a working fetch command before this task supplies its +own accepted native delivery return. Client-side admission is not ready for a +new human decision until exact requests and contained execution/rollback checks +are reviewable; the completed verifier reviews must not recur in that queue. + +**Done when:** each retained consumer admission is approved and implemented, or +its requesting owner explicitly cancels it (CCR-2026-0020 now satisfies that branch); +actual consumer authentication/delivery succeeds; sibling/listing/wrong-reader +and scope refusals plus reader expiry/revocation/cleanup are evidenced; version-1 +custody and verifier availability remain intact. Return the source and metadata +receipts to HFACT-WP-0001-T03, SECRETS-WP-0009-T03 and APPROVAL-WP-0002-T01/T05. +Audit receiver/sender custody remains AUDIT-WP-0009-T09 and must not be folded +into this client-identity grant. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Admit the two factory audit-sender custody lanes + +```task +id: RPF-WP-0035-T08 +status: wait +decision_id: "ab85ae8a-12a0-4945-ae64-1d3d86d5b26f" +blocking_reason: "Approved conditionally (ab85ae8a, standing change rule): executes once independent archive readback and the interim bearer revocation receipt exist; owner work with audit-core." +priority: high +assignee: railiance-platform +intervention_note: null +blocked_on: message-from:audit-core +state_hub_task_id: "0ef52c26-2669-5cd1-8149-b1f6fcdda6cb" +``` + +2026-10-11: requalified — ab85ae8a resolved under the standing build-mode change rule. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +2026-10-03 correction (CUST-WP-0075, informed-decision sitting draft `55fb078`): the D1 routing was wrong. First provision and delivery already ran on 2026-09-11, with seed and delivery receipts, and the review packet says not to repeat them. The task is not a provisioning-window act. It was taken off decision D1, and its blocking_reason now names what actually remains. railiance-platform should re-qualify it further if the receiver rollout has since happened. + +2026-10-03 (CUST-WP-0075): re-qualified. The receiver rollout already happened: Audit Core c82e0442de0f carries evidence_kind and native producer accepted/duplicate and scope/read-refusal checks passed 2026-09-11 10:42 UTC (`docs/credential-lane-designs/factory-audit-senders-review.md`, `factory-native-acceptance.md`). Remaining: independent archive readback and audit bearer-revocation acceptance. Still not a provisioning-window act. + +Consume AUDIT-WP-0009-T09/T11's exact declarations for approval-engine and +informed-decision: tenant:platform, write-only, load-bearing, redact. Source +preparation supplies two approved CCRs, independent exact-path policies/ESO +projections, and the attended `factory_audit_custody.py` first-provision helper. +Its CAS and request-provenance checks preserve unrelated senders and recover +interrupted writes without generating replacements. The user approved all named review roles on 2026-09-11. Native +provision/delivery/receiver-ingestion acceptance remains open. + +The 2026-09-11 native read-only check found an additional deployment dependency: +receiver image c2fe39a is 1/1 Ready but does not support evidence_kind. The +synthetic native probe now refuses before any credential read. Current receiver +source passes. AUDIT T09/T11 retain compatible release/source-manifest rollout; +Approval Engine's missing namespace remains its owner prerequisite. + +[Review packet](../docs/credential-lane-designs/factory-audit-senders-review.md). +[Preparation evidence](../docs/evidence/2026-09-11-factory-audit-custody.json). +Do not fold these senders into CCR-2026-0019 or the cancelled CCR-2026-0020. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Dependency review — 2026-09-06 + +### 2026-09-09 tenant question resolved — no change needed + +The `tenant:coulomb` / `tenant:platform` discrepancy raised against T02 is not a +discrepancy. KeyCape confirms decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6` +binds the *approval chain* to the landlord zone and was applied to exactly two +registrations, `secrets-engine-approval` and `approval-engine-operator`. +`codex-railiance-platform` is not in that chain and correctly stays +`tenant:coulomb`, as do `secrets-engine-openbao` and the human directory default. +KEY-WP-0013-T04 records this and their +`TestServiceRegistrationTenantsAreExactPerDecision` pins every reviewed client's +tenant against the real fixture, so a reintroduced alias fails their build. + +`docs/credential-lane-designs/secrets-engine-service-jwt.md` already says +`tenant:coulomb` and is therefore correct as written. Bind the exact role to +`tenant:coulomb`. Do not "correct" it to `tenant:platform` later; that would +break the issued claim. + +SECRETS-WP-0008-T02 now records the local PIP claim/validation join implemented +and tested. Its remaining gate is the unreachable approval-engine claim endpoint +and access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old local +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 ` 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. + +### Sender approval recorded — 2026-09-11 + +The user replied "good, go on" to the explicit CCR-2026-0021/0022 question naming +platform-operator, audit-core-owner and both producer owners. Both exact requests +are approved; their existing State Hub decisions are resolved. This clears the +review request only. Receiver rollout, namespace readiness, attended custody and +positive/negative native evidence remain the execution gates. + +### Native receiver and attended execution return — 2026-09-11 + +Audit Core c82e0442de0f is deployed and passes the native synthetic contract. +Its existing 32-event chain/head is unchanged. The owner Approval Engine +namespace now exists and all four ESO objects pass strict server dry-run. +The two exact ingress rules are applied; sender custody/ESO application is not. + +Warden selected founder_required/oidc_login and attempted the reviewed silent +seed command through the contained wrapper. Login failed before command +handoff; no custody receipt was created. Warden could not confirm remote +session revocation. Await operator browser/MFA feedback and login/session +resolution. Approvals remain valid; T08 waits for the identity act, not review. + +The receiver check now selects component=receiver, so retained attestation-job +pods cannot falsely block a stable receiver. Eighteen custody tests pass. +[Native return](../docs/evidence/2026-09-11-factory-receiver-live.json). + +### Attended custody retry succeeded — 2026-09-11 + +The user requested a retry and completed the attended identity act. Both CCRs +are applied: independent version-1 custody and registry CAS 7→8 succeeded, +preserving other senders/fields. Warden exited 0 with self-revocation confirmed +for this session. This does not retrospectively attest the earlier failed +login's remote session state. The old login wait is cleared; T08 is progress +for ESO delivery, exact native reader/namespace refusals, receiver reload and +producer acceptance. No token is reseeded or rotated on continuation. +[Seed receipt](../docs/evidence/2026-09-11-factory-audit-sender-seed.json). + +### Delivery prepared; fresh login did not hand off — 2026-09-11 + +The delivery helper and custody receipt are committed at `44314ca` and exactly +projected on primary/railiance01. Seven delivery tests and 18 custody tests +(including 11 actual disposable OpenBao cases) pass. The fresh attended +delivery invocation exited 5 before command handoff; no native delivery +receipt exists, no ESO application or receiver restart ran. The receiver +remains 1/1 Ready on c82e0442de0f. Warden could not confirm revocation for this +failed login; that is separate from the successful seed session. T08 now waits +for this delivery identity act. Neither CCR review nor first provision reopens. + +[Delivery return](../docs/evidence/2026-09-11-factory-audit-delivery-login.json). +Use the reviewed delivery command with a new receipt after login feedback. +Actual producer ingestion/duplicate/refusal and bearer revocation acceptance +remain open under AUDIT-WP-0009-T09/T11. + +### Native delivery accepted — 2026-09-11 08:27 UTC + +The user returned and requested another login attempt. It succeeded and the +reviewed delivery command completed in 28 seconds. Both native ESO readers +passed exact-path access and explicit sibling/registry/metadata/listing denials, +wrong-SA/namespace refusal and the coding-agent deny check. Each 900-second +reader session was revoked and lookup refusal verified. Both intended +ExternalSecrets are Ready; exact producer value and ESO ownership match. The +disallowed namespace produced an explicit store restriction and no Secret; +the uniquely owned namespace is now absent. + +Registry version 8 matches the delivered receiver JSON. Audit Core reloaded +and remains 1/1 Ready on c82e0442de0f; /readyz reports operational/durable with +tamper_evidence=false, as bounded by AUDIT-WP-0009-T12. Warden exited 0 and +confirmed self-revocation for this successful session. Earlier failed login +receipts remain historical and are not retroactively attested. + +The login wait is cleared. T08 remains progress and CCR21/22 remain applied +for native producer ingestion/duplicate/scope/read-refusal and bearer +revocation acceptance under AUDIT T09/T11. No credentials were reseeded or +rotated. No producer was deployed and no factory attempt or paid call ran. +[Native delivery receipt](../docs/evidence/2026-09-11-factory-audit-delivery-live.json). + +### Native producer return — 2026-09-11 10:42 UTC + +Both actual source adapters used their own ESO-delivered credential inside a +bounded native Job. Each synthetic event received 202, retained its durable +outbox after an injected lost receipt, and received duplicate 200 after a fresh +process reopened the outbox. Each source's reconciliation reported exactly one +record for its unique probe class. Wrong source/tenant, seven archive read +routes, sibling reconciliation and invalid-bearer requests were refused. + +The first Informed Decision probe exposed a private-store startup defect: +fsGroup volumes add inherited setgid to a newly created 0700 directory. +Informed Decision `1a12223` corrects creation without repairing unsafe existing +data. The regression failed before the fix; the available suite now passes +335 tests with 39 optional checks skipped. Native retry verifies the exact +corrected helper. Six probe tests and eleven rebuilt-container checks pass, +including actual setgid-volume startup, restart/restore and cleanup. + +All temporary probe Jobs, Pods, ConfigMaps and NetworkPolicies are verified +absent. Receiver c82e0442 remains operational/durable; tamper_evidence=false. +Producer verification requires no operator registry read or new OpenBao login. +Independent readback is a separate attended command consuming the successful +receipt; it must not rerun the producer jobs. Both attended verification-login +attempts this session ended before handoff (exit 5; remote revocation +unconfirmed), so independent archive readback remains pending. + +This proves synthetic outbox delivery/recovery with native sender credentials, +not domain-transaction atomicity, deployed producer services or human binding. +An invalid bearer is not a revoked formerly valid bearer. AUDIT T09/T11 and +RPF T08 remain progress for independent readback and audit bearer-revocation +acceptance; CCR21/22 remain applied. Service/policy/human admission and native +runtime/spend gates remain separate. Factory attempts and paid calls remain 0. + +[Native producer receipt](../docs/evidence/2026-09-11-factory-native-producers.json). + + +## Independent audit readback — 2026-09-11 13:11 UTC + +The existing attended readback command completed with exit 0 while the user +was present. Independent read-only identity `operator` found both retained +`factory-audit-20260911104152-94aced` producer events with exact source and +`tenant:platform`; receiver integrity is intact across 36 events. The wrapper +confirmed this session's self-revocation and private-helper cleanup. Prior +failed sessions' unconfirmed revocation remains historical unresolved evidence. + +This supersedes the earlier readback-login wait. No producer jobs were rerun, +no credentials were reseeded and no event was written by the reader. The +inherited zero registry-read count belongs to the producer phase; the attended +reader did consume registry version 8. CCR21/22 stay applied and owner tasks +stay progress pending formerly-valid audit-bearer revocation acceptance. +Service/domain-transaction/human and factory runtime/spend admission remain +separate; factory attempts and paid model calls remain zero. + +Receipt: [native readback](../docs/evidence/2026-09-11-factory-native-readback.json). + + +### T06 native reader acceptance — 2026-09-14 + +The scoped Warden login lane `secrets-engine-approval-client-login` now routes +to the applied OIDC reader and the platform's silent preflight. The installed +Warden package still carries an older catalog; use the explicit source catalog +`WARDEN_ROUTING_CATALOG=/home/worsch/ops-warden/registry/routing/catalog.yaml` +until its next normal installation refresh. This lane authenticates the reader; +it is not a raw secret fetch or retained-file delivery interface. + +Live effective-policy and capability checks passed: only exact data/metadata +read, no sibling secret, parent listing, write or control-plane authority. +A second contained session read existing version 1 into an operator-owned 0600 +file in a private 0700 runtime tmpfs directory. The native consumer exchanged +separate read and consume scopes; Approval Engine verified the read token before +returning 404 for a fresh nonexistent approval, and refused the consume-only +token's read request with 403. No approval was created, bound or consumed. +Both Warden sessions exited 0 after self-revocation/helper cleanup; temporary +credential file and directory were removed. Four refusal/path/redirect tests +pass. Receipts are in platform `docs/evidence/2026-09-14-ccr0019-{reader-preflight,delivery-check}.json`. + +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. + +### 2026-09-27 T02/T07 source follow-up + +T02 now has the exact proposed RS256 configuration, bounded JWT role and +self-only policy in `openbao/`. Operator correction: platform infrastructure +belongs to `tenant:platform`; KeyCape registration and consumer preflight are +corrected together. Existing live registrations must be migrated and verified. +Public discovery confirms issuer/JWKS/token endpoint. Registration/custody, +attended provisioning and live rejection/cleanup evidence remain required; +T02 stays wait. No service credential or backend entitlement was issued. + +T07 consumed the confirmed legacy consumer return. The stale value-comparison +ask is removed. WARDEN-WP-0037-T03's no-rotation hold stays in force until the +governed native migration is evidenced. Legacy destruction follows migration; +neither source reconciliation nor the historical pilot is that evidence. + +## Loose-end review — 2026-09-27 + +T08 now explicitly waits for formerly-valid audit-bearer revocation acceptance from AUDIT-WP-0009-T09/T11. Native delivery, producer checks and independent readback already passed; do not reopen login, seed or review gates. T02/T03/T06/T07 retain their latest exact service registration, signed-in human acceptance, owner delivery/disposition and governed-consumer migration dependencies. No credential value was read or changed. + +## Founder approval of the CCR-2026-0033 custody child + +```task +id: RPF-WP-0035-T09 +status: done +needs_human: false +priority: high +decision_id: 2ab717e1-7881-491e-aed4-28946550c289 +depends_on: [] +state_hub_task_id: "7c753be6-42f1-58a6-a4a4-a7ed686f461f" +``` + +Packets: `credential-change-requests/CCR-2026-0033.yaml` (custody child, KV +metadata, issuer ESO reader, live_order, rollback) and `CCR-2026-0034.yaml` +(attended operator OIDC reader, in-memory, 5m/4 uses). Revised 2026-10-06 per +founder direction; the consumer file is removed. Exact founder commands: +`docs/provisioning-windows/2026-10-04-1000/keycape/founder-runbook.md`. Live +order: custody child → platform applies policies/roles/ESO (Secret +sso/keycape-secrets-engine-openbao-client exists) → NetKingdom env patch +(NK-WP-0046) → KeyCape registration merge (KEY-WP-0037-T03) → KeyCape restart +immediately → live issuance check (KEY-WP-0037-T04) → OpenBao JWT role/login +proof (RPF-WP-0035-T02). Each live step after the custody run needs its own go. + + +2026-10-11 evidence reconciliation: T09's approval obligation is complete. +Authoritative founder decision 2ab717e1-7881-491e-aed4-28946550c289 is resolved, +decided by Bernd Worsch at2026-10-06T13:07:18.627943Z, and explicitly covers +A1 design, A2 CCR33/CCR34 plus owner reviews/bound claims, and A3 one custody run. +The approval comments in both CCRs record those exact grants; both source records +are applied. MASON-WP-0009-T02/T03 additionally record the October8 approval/owner-delivery +reconciliation and reference KeyCape +`docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`. Closing this approval task clears +its obsolete human gate. It grants no new run, credential access, rotation or +service execution: RPF35T02/T12, MASON9T05 and SECRETS8T06 retain their actual +native/adoption obligations. Historical per-step exclusions remain above. + +## Retire the approval-engine-operator client delivery and custody (CCR-2026-0018) + +```task +id: RPF-WP-0035-T10 +status: wait +priority: medium +blocked_on: message-from:approval-engine +blocking_reason: "Blue lane under the standing change rule (removing access, with reviewed order, rollback and receipts): executes once approval-engine confirms there is no presenter. No founder window needed." +state_hub_task_id: "af2d4dba-f83a-5819-9a8b-671bae799364" +``` + +2026-10-11: access removal is blue lane (canon build-mode-change-authorization_v0.1); no founder window. + +key-cape proposed a joint disablement on 2026-10-10 (message `7f2128fb`). +Precondition: approval-engine reconfirms there is no presenter. The order is the +reverse of provisioning, so KeyCape never starts with a client whose secret is +missing. key-cape removes the registration and restarts (1), checks that +`invalid_client` is returned (2), and net-kingdom removes +`KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET` from Deployment `sso/keycape` +(3). Platform steps, amended from the proposal: + +4. **Delivery.** In one commit, remove ExternalSecret + `sso/keycape-approval-engine-operator-client` from + `argocd/platform-addons/openbao-secretstore/keycape-approval-clients.externalsecrets.yaml` + and ClusterSecretStore `openbao-keycape-approval-engine-operator` from + `openbao-keycape-approval-clients.clustersecretstore.yaml`. Keep the + secrets-engine-approval objects. Then bump `targetRevision` of + `argocd/railiance01/applications/openbao-secretstore.application.yaml`. + The app is pinned and has no automated sync, so nothing changes live until + an attended `argocd app sync openbao-secretstore --prune` runs after step 3. + Verify, value-free, that the ExternalSecret, the store and Secret + `sso/keycape-approval-engine-operator-client` are gone. The target is + `creationPolicy: Owner` and `deletionPolicy: Retain`, so the Secret should + follow its owner; delete it explicitly if it does not. Then delete OpenBao + role `auth/kubernetes/role/external-secrets-keycape-approval-engine-operator` + and policy `workload-kv-read-keycape-approval-engine-operator`, and remove + their source files. Also remove policy + `workload-kv-read-approval-engine-operator-client` (CCR-2026-0020, cancelled) + if it exists live. +5. **Custody.** Run the metadata delete of + `platform/workloads/approval-engine/operator-client`, the destruction + foreseen in `docs/credential-lane-designs/keycape-approval-clients.md`. A + disabled client's secret has no recovery value; a narrowed successor gets a + fresh secret through the mint-secret lane at `platform/workloads/keycape/`. + Only after step 2's `invalid_client` receipt. Keep the agent boundary denies + for that path until the delete is verified, then drop them. + +2026-10-10: key-cape agreed the amended steps 4 and 5 (message `59304e33`, +KEY-WP-0013 c528daa). Waits on approval-engine confirming there is no presenter, +and on the founder's window. + +The manifest edits wait for the scheduled window, so a stray `targetRevision` +bump cannot remove KeyCape's secret before step 3. + + +## Complete independent service-JWT source preparation and execution design + +```task +id: RPF-WP-0035-T11 +status: done +priority: high +state_hub_task_id: "7952c8cd-c066-5b72-a025-78d24341c1ab" +``` + +2026-10-11: Platform-scoped agent loaded this checkout's AGENTS.md and INTENT, +RPF35-T02, actual CCR38/login contract/typed applier and Secrets Engine's native +claim/PDP/CAS/provider/apply flow. Frozen Secrets v2 manifest and all named staged +bytes/proof were hash-verified. Independent tests reproduced three source +counterexamples while retaining the frozen files: close exception can coexist +with native_verified=true; successful result needs no source/session fingerprints; +HTTP200 mixed errors+data envelope is accepted. Original 37 tests plus the three +counterexample tests pass (40 cases, synthetic/local only). Proposed owner design +`docs/credential-lane-designs/secrets-engine-task-execution-entitlement.md` binds +an explicit metadata-only execute-ccr action, immutable typed owner bodies, +CAS/journal replay control, 120s/12-use owner-held task token, independent payload +validation, native ACL endpoint bounds, revoke/readback and recovery. This completed +preparation record is established before the formal source review. It grants no +live authority and does not close T02 or represent acceptance by another owner. +Formal review artifact follows under this work item; all implementation/live +obligations are retained in T12 and existing T02 rather than a finished residual. + +## Implement and prove the separately approved task execution entitlement + +```task +id: RPF-WP-0035-T12 +status: progress +priority: high +depends_on: [RPF-WP-0035-T11] +state_hub_task_id: "914bf383-c13f-5247-9af0-91d7e3a4784a" +``` + +Review the proposed task-execution-grant schema and exact metadata-only execute-ccr +backend with Secrets Engine/access-engine/approval-engine; implement trusted service +subject and served consume verification, durable one-shot reservation, bounded +owner-held token issuer/middleware and exact source/payload enforcement. Obtain +separate exact founder approval/attendance before provisioning or live actions. +Prove disposable intended result and identity/action/target/body/time/replay/crash/ +cleanup negatives, and return owner-native acceptance. Existing service login policy +and defaults stay unchanged. T02 still owns login/claim/TTL/use/MASON acceptance; +Secrets T06 separately owns dispatcher adoption and steady-state default migration. + + +2026-10-16 T12 wave 5 source preparation: disposable adapter now binds owner +canonical before/after metadata snapshots to existing descriptor hashes, rejects +per-target baseline/readback mismatch, and records readback/verified evidence. +Mediator reports cleanup-confirmed only after independent fixed cleanup receipts. +Complete role metadata and policy name/HCL/version/cas are compared; validated +modification timestamp alone is excluded. This is sequential fixture acceptance, +not aggregate CAS, concurrent-writer exclusion or native production completion. +Role conflict may follow a policy write. Restart refuses dispatch and cannot +recover memory-only token/accessor cleanup handles. T12 remains progress; actual +fresh CCR/catalog/grant, source/trust/caller/policy admission, isolated owner custody, +scoped recovery and attended native acceptance remain explicit prerequisites. + + +2026-10-11 T11 refinement (same source-review trial): the exact Secrets Engine +v3 manifest `6bb05bac74e4939c3e42db2ae95c5f9fb4616bb20cc285811a315c26669ebce1` +and all named bytes/proof were verified and independently re-reviewed. The three +v2 counterexamples are corrected: close exceptions cannot pass through stale true +flags, complete typed source/session/attempted/revoke evidence is required, and +mixed HTTP200 errors/data fails closed. 49 maker/current-provider tests plus three +independent regressions passed (52, synthetic/local only). Platform source review +`docs/reviews/2026-10-11-secrets-service-jwt-v3-platform-review.json` approves only +the corrected boundary verifier and truthful packet. Prior changes-requested v2 +review is retained; this is not a second native success or changed authority. +No native or founder go is granted. T02, T12 and Secrets T06 remain open; the +metadata-only execute-ccr pilot is explicitly insufficient for generic lifecycle +adoption. All consume-verification/journal/action/body/backend implementation and +native acceptance gates remain real prerequisites, not architecture promises. + + +2026-10-11 T11 readiness refinement: independently reviewed frozen consumer +manifest `709b9dddd1c8f00a995b1ff14264323fbe080ed95df244270ce9607528878fa7`. +Platform source review `docs/reviews/2026-10-11-secrets-execution-readiness-v2-platform-review.json` +approves the local fail-closed guard and proposed consumer contract direction only. +All ten current protected backend handlers pass provider args through readiness +before authorization/consume; session revoke checks before handle reads. Configured +auto/explicit service-jwt therefore cannot burn a protected-action approval or +open the insufficient login-self backend. Explicit env/bootstrap and self-only +probes retain their existing contracts; local compromise/reactivate and disabled +destroy remain separate. Existing ambient-token route readiness reads are unchanged, +not claimed governed by this guard. 58 isolated tests passed: original36 plus20 +provider/action cases, handler enumeration and actual session-revoke ordering. +Prior v2 changes-requested and v3 boundary source reviews remain unchanged, same +T11 trial. No runtime grant, native acceptance, new Access/Approval semantics, +backend entitlement or full Lifecycle adoption is approved. T02/T12/SecretsT06 and +WP13 implementation/native gates remain open; the metadata pilot substitutes for +none of the ordinary generic lifecycle outcomes. + + +## Complete independent KEY39 v4 lifecycle source review preparation + +```task +id: RPF-WP-0035-T13 +status: done +priority: high +state_hub_task_id: "8f6966fa-6e9a-58b2-8b40-c47340ec19d1" +``` + +2026-10-11: Platform agent loaded its owner instructions/INTENT and RPF35-T02, +actual applied CCR38, exact native role/policy source and frozen KEY39 lifecycle +v4 manifest `d079f85c47d5c2635e1ee633ea4d1346b1737ce2be9ca273f22a38e620f418d8`. +All staged entry hashes were verified without changing the reviewed inputs. +Source role omits expiration_leeway: its observed actual default must be confirmed +natively, with -1→0 and 0→150 normalization preserved as a bounded model. Source +claims and login-only policy are unchanged. The supplied 41 lifecycle tests pass; +five independent cases also pass, including a new exceptional-response-close +elapsed-bound counterexample and four current-leeway normalization checks. +A 10ms HTTP request can take over70ms because exceptional finally response.close +runs outside the hard elapsed timer. Unknown native login is correctly recorded, +but source total elapsed enforcement is incomplete. This completed owner +preparation record exists before the formal exact source review entry. No +credential was requested/read, native action run, owner checkout edited or native +session grant inherited. T02 retains native role/policy/leeway, negative claims, +cleanup acceptance and MASON gates; KEY39 producer handoff and founder attendance +remain prerequisites. Source correction/re-review is required, not a native success. + + +2026-10-11 T13 correction preparation (same trial): exact KEY39 v5 manifest +`d1f997624db46693a7126a6eb6435f6b3a353d5bd67dcc8a539683e4b7147285` +and all entry hashes verified. The v4 exceptional-close finding is addressed: +one 20ms abort is clipped to original remaining time and the nonresettable +aggregate cleanup budget; zero calls after aggregate expiry; failed abort stays +unconfirmed/unknown with signal state restored. 46 supplied lifecycle checks and +five independent regressions pass; the unchanged runner's earlier17 tests remain +valid against identical source SHA. Existing T13 preparation record is retained +before the formal v5 exact source review. V4 changes-requested review and earlier +failed history remain retained, with no native success, inherited grant or scope +promotion. Actual private producer admission, fresh installed role/leeway/policy +observation, authenticated founder window and native refusal/cleanup remain gates. + + +2026-10-11 T11 journal preparation refinement (source-only): independently +inspected frozen root-maker v2 manifest +`341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7`, +verified all input hashes, and ran14 supplied tests plus5 independent checks. +The actual four-process race admits once; a separately forked process exiting +immediately after pending intent leaves durable unknown/nonresumable state. +Private SQLite modes, lock admission and binding/replay protections remain guarded. +Three independent counterexamples show after_call accepts False,0.0 or text'0' +as persisted integer ordinal0, contrary to before_call's exact integer validation. +Completed preparation under this existing done ownerT11 record precedes formal +review; require identical ordinal/call-digest validation before confirmation so +malformed calls cannot clear pending outcome. RPF35-T12 retains caller/PDP/consume +validation, exact body compiler/adapter and owner-private cleanup/recovery after +unknown; this unintegrated primitive proves none of those or full contract/native +acceptance. Inputs/prior reviews are preserved; no privileged/native action occurred. + + +2026-10-11 T11 journal v3 correction preparation (same trial): frozen manifest +`905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d` +verified against every file. Strict after_call integer0..63 and64hex string digest +validation now precedes SQLite confirmation; False,0.0 or text'0' cannot clear +pending external outcome.15 supplied tests plus5 independent regressions pass, +including realfork abrupt exit after durable intent and privatefile checks. +This existing completed ownerT11 refinement precedes the formal corrected-source +review. Prior v2 refusal is retained; no extra success/authority trial is counted. +Acceptance is only unintegrated journal source. Actual caller/PDP/consume validation, +independently compiled body/ordinal plan, restricted adapter, owner-private unknown +cleanup recovery and native/whole-contract adoption remain live RPF35-T12 gates. + + +2026-10-11 T13 node-route source preparation refinement (same trial): exact +successor manifest `23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035` +verified against all entries. Platform Service openbao-ui-gateway8080 and its +nginx /v1 proxy agree with the proposed bounded founder-held node port-forward; +workstation tunnel/DNS assumptions are not reused as node evidence.54 supplied +lifecycle/route checks plus6 independent public-health/abort checks pass, offline. +Initial execute/recovery health pin and repeated pre-create check fail before +native/Secret effects; public-preflight reads neither stdin nor Kubernetes. +Completed ownT13 preparation precedes this fresh exact source review, not reuse +of v5 acknowledgment. Main execute currently reads private stdin before execute's +health gate; the packet's pre-token-input phrase is not accepted. Private producer +handoff must preserve actual ordering or move the health gate before credential +input when implemented. Public cluster digest detects drift, not authenticated +estate identity. No route was opened or observed; no source packet authenticates +a founder approval. Native role/plugin version and raw/effective expiration, +clock-skew and not-before leeways require actual owner observation/semantic proof. +Issuer readiness_state/Argo ownership is not established by the inspected source; +unmapped means production-tier. If adopted/production-approved, temporary direct +CAS requires an explicit reviewed one-use maintenance exception and close-down +entry, plus reconciliation, before native go. No helper/source acknowledgment +waives that gate. Private token producer/callback/client/custody admission and +actual native negative/revoke/restoration/cleanup remain prerequisites. + + +2026-10-11 T13 v7 node-route preparation refinement (same trial): exact frozen +manifest `90aabec336008d7d51e37c04b5ff96ba8ed6630821cca1a4c333d803367247f7` +and all entries verified.58 supplied lifecycle/route checks plus9 independent +checks pass offline. Actual main now verifies source/public health before private +stdin; execute preserves the original wall/monotonic window rather than renewing +it. Actual child-process partial-pipe counterexample shows unbounded stdin.read +remains blocked beyond a synthetic20ms original window (still alive after100ms +without EOF). No credential/native/provider access is involved. Before private +producer admission, require byte-capped, deadline-bounded JSON input and EOF within +the original window, with fail-closed fixed receipt and no protected effects. +This completed ownT13 preparation precedes formal v7 source changes-requested +review. Retain v6 qualified health-gate agreement and all prior reviews; neither +v7 health ordering nor any source acknowledgment establishes custody completion, +actual route/plugin/leeway/readiness/Argo identity or founder/runtime authority. +Native and private-producer gates remain open; no owner checkout write occurred. + + +2026-10-11 T13 v8 bounded-input correction preparation (same trial): exact +frozen manifest `316fd6005cc4cb7fe14ea69a5fd408aed13e6122afef60afd13d97952b27cf4a` +and all entry hashes verified.65 supplied tests plus12 fresh independent checks +pass offline, including a standard buffered stdin pipe with complete JSON/noEOF +interrupted within original20ms window and restored SIGALRM state; exact64KiB +JSON/EOF accepted and extra byte refused, UTF8 token bytecap enforced, original +wall deadline clips longer monotonic budget. Original preinput window is retained. +Completed ownT13 preparation precedes fresh exact source review; v7 refusal and +v6 qualified agreement/prior reviews retained. This accepts child bounded-input +source only. No parent-ready handshake exists: producer must not eagerly pipe +private inputs, and producer/session/window readiness protocol remains an +unimplemented admission gate. No custody/native completion, sourcepacket approval +authentication, route/plugin/leeway/readiness/Argo observation or inherited grant. +Native prerequisites and producer handoff remain open; no owner checkout changed. + + +2026-10-11 T11 journal v4 canonical-format preparation refinement (same trial): +exact frozen manifest `22c6d225d393b994ab7b44a43904ced1b6d7f74e0e2bebf71ffe99f87191ef4c` +and entry hashes verified. Actual access-engine pkg/api/canonical.go RequestDigest/ +CanonicalDigest, Approval binding.py and Secrets authorization/approval_consume +all use sha256:<64 lowercase hex> request digests. V4 now preserves this exact +request value without prefix stripping; plan/call/evidence content hashes remain +explicit bare64hex.15 supplied checks plus15 fresh independent checks pass, +including malformed prefix/bare/uppercase/trailing whitespace refusal before +reservation, exact persistent value/reopen/mismatch replay, private-file mode, +real child crash after pending intent, ill-typed confirmations and pending-unknown +refusal. Completed ownT11 preparation precedes formal v4 source review; prior v2 +refusal/v3 approval and T13 v7 refusal/v8 source acknowledgment retained. +Acceptance is unintegrated primitive source only; no data migration/native use +of v3 journal has occurred. RPF35-T12 caller/PDP/consume validation, independent +owner plan compiler/restricted adapter, private runtime custody, bounded execution +and owner-private unknown cleanup recovery remain open. No checkout/native writes. + + +2026-10-11 T13 paired ready-child/launcher preparation refinement (same trial): +exact NetV9 manifest `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +and KeyproducerV2 `55a8e794af983ca2202e7a0054d0415a120d2c95018fb03fdb5f28313a109d58` +verified against all entries.74 Net checks plus31 Key checks and10 independent +checks pass offline including a truthful-unknown counterexample: adapter uncertain +private delivery with confirmed=false is copied into launcher receipt, but +consumer_outcome_unknown incorrectly remains false after local SSH teardown. +Complete bytes may have reached remote child before adapter timeout/EOF; local +terminate does not establish remote no-effects. Require sticky propagation of +uncertain delivery into consumer outcome before early return, retain unknown +unless independently established native outcome/recovery. Bad markers/source +pins/injection reject before private reads; extra marker authority/lines reject; +prohibited child output never forwards. Child-ready synchronization is not +authentication/approval. Proposed founder directSSH profile is incompatible with +warden quiet-output lane and not admitted here. Completed ownT13 preparation +precedes formal paired source review; preserve v7 refusal/v8 acknowledgment and +journal histories. No transport grant, coding-agent/private custody admission, +live SSH, credential/native action or owner checkout write. All native role/plugin/ +leeway/route/issuer readiness/Argo/maintenanceexception gates remain prerequisites. + + +2026-10-11 T13 paired producerV4 correction preparation (same trial): exact +producer manifest `d6f641dc1e4aae7d36658d4199d89af14d2fd7a4bd4e526856eb340234f2d33e` +and unchanged NetV9 `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +entry hashes verified.74 Net tests,40 producer checks,9 actual local fakeSSH/ +realwrapper/child synthetic roundtrip regressions and12 fresh Platform checks +pass (135 total). V2 deliveryunknown now remains sticky consumerunknown with +completion=false after earlyreturn/localteardown. V3 Net FIFO acquisition finding +and originalbudgetreset are corrected: actualCLI starts original5s timer before +regular/nofollow/bytebounded contract acquisition, each later preparation phase +clips remaining time. ActualCLI FIFO refuses promptly; expired original budget +never validates/spawns/reads private files. Completed ownT13 preparation precedes +formal corrected pair source agreement. Preserve V2 Platform refusal, Key old +exactV2 acknowledgment and NetV3 refusal; no old acknowledgment repinned. +Agreement is only reviewed source synchronization/launcher behavior, not admission. +Founder authenticated SSH host/profile/channel/runtime pins, exclusive sameUID +file custody and explicit tmpfs file allowance/cleanup, verified human and +coding-agent producer/client/source, native role/plugin/leeway/route/issuer +readiness/Argo/maintenanceexception, refusal/revoke/restoration/readback and +unknown owner recovery remain prerequisites. Warden quietlane cannot carry ready +controlstdout; no transport/custody/native grant. No owner checkout/liveSSH/native. + + +2026-10-11 RPF35-T12 source implementation progress: durable journal source v4 +was independently accepted/committed; owner-derived typed plan compiler component +v2 is prepared at immutable manifest +`41cda74ab32384c789ea8a760475671aadad4e5121335c8f60567ff53d66665b` +with40 offline tests. Completed own bounded source-preparation ADHOCT02 anchor +was persisted at7adbcb4 before the qualified Platform contract/readiness receipt. +T12 progresses for actual source implementation underway, not native acceptance +or full descriptor/authority readiness. The compiler derives local CCR/HCL/role +bodies, matches actual independently pinned Secrets catalogue and revalidates +source/body before fixed calls; no body/target chosen by service is dispatched. +Independent technical integration review and exact full ExecutionContract/owner +grant/baseline/estate/deadline matching, initiating human/User/Tenant PIP/transport +representation/service identity, served PDP/claim/consume correspondence, journal +call dispatch/restricted adapter, native token TTL/uses/custody/revoke/cleanup and +owner-private unknown recovery remain unimplemented integration/native gates. +Actual CCR42 has no eligible approved pilot/catalogue; no source metadata is +invented. T02 and original negative/capability/native evidence remain unchanged; +T11/T13 history retained, no defaultflip/nativego or SecretsT06 closure follows. + + +2026-10-13 T12 source correction: the compiler hashed the catalogue sources but +used cached Python modules with matching paths, which did not establish executing +those exact bytes. A failing regression reproduced the substitution. Catalogue, +package and dependencies now execute from the verified snapshot in temporary +private modules; ambient modules remain untouched and cleanup runs on refusal. +45 compiler plus 15 journal tests pass. The v2 source review remains historical; +this change needs its own integration review. T12 retains all existing full +contract, identity/consume, dispatch, custody and native acceptance requirements. +RPF-IN-0012 remains open for the independent contract/wrapped-delivery return; +this code correction does not authorize either operation. + +2026-10-16 T12 source preparation (isolated owner checkout; not owner delivery): +added durable precommitted cleanup obligations and separate outcome evidence to +the existing Journal, plus a fixed three-method owner cleanup driver. Same live +postconsume admission can clean after a business timeout/failed/unknown outcome; +cleanup closes business dispatch and cannot replay or restore admission after a +crash. Empty obligations no longer produce cleanup-confirmed. Real SQLite +multiprocess races and abrupt process death before/after a separately durable +synthetic effect verify refusal on reopen. Current compiler/journal/cleanup suite: +73 passed, local source/fixture only. Details: docs/task-execution-cleanup.md. +No native adapter or production mediator exists; full grant/request/cleanup binding, +authenticated consume/identity, ephemeral token issuance, deadline/use checks, +native effect/revoke/absence, audit and protected recovery remain prerequisites. +T12 remains progress. No CCR38 default/entitlement or live grant was changed. + +2026-10-16 T12 second source package: Compiler Plans now bind deterministic cleanup +commitments and can bind the complete independently installed engine execution +descriptor. A fixed disposable-loopback native adapter actually materializes exact +per-operation metadata ACL/task token, executes six source-derived metadata calls, +and verifies self-revocation/accessor invalidation and policy retirement. Each +cleanup request has its own durable intent. Native fault tests cover lost response +after real write and policy deletion while task revoke fails. All initiating +identity/approval/consume/grant/state/source admission in this fixture is synthetic; +no production authority or complete native owner acceptance is claimed. Exact +remaining owner schema/admission and mediator work: docs/task-execution-native-fixture.md. +T12 stays progress; no live grant, credential/default change or owner sync performed. + +2026-10-16 T12 third source package: implemented proposed task-execution-grant +immutable projection and exact compiler/native-fixture integration through the +existing descriptor grant ID/SHA fields. Only typed review.comments/evidence.events +are excluded; separate append-only checks reject removal/rewrite/reordering and +unknown guessed evidence exclusions refuse. Owner-pinned grant bytes and validator +source must match independently reconstructed descriptor/source/cleanup/ACL/token +bodies before a native fixture can materialize. Proposed source records gain no +execution authority; no real grant, policy or legacy applier registration added. +Details and remaining production gates: docs/task-execution-grant-projection.md. +T12 remains progress; no owner sync or production effect performed by this package. + +2026-10-16 T12 fourth source package: connected the Secrets-owned strict task +handoff to actual Approval ExecutionConfirmationClient independent GET before +consume-confirmed/native fixture work. Platform accepts no supplied authorization +boolean/object/callback and preserves its exact owner descriptor/grant/Plan join. +Durable CAS/GET intents precede native ordinals through the repaired journal +prefix API. Actual source-server fixture uses signed Access/enforced synthetic +TokenReview, real Approval WSGI/SQLite with distinct synthetic human/service +identities, actual strict Secrets signature/CAS validation and disposable native +OpenBao. Untouched actual task policy remains signed DENY; separately named +synthetic fixture policy is never production admission. Read-scope denial after +CAS records consumed/unknown with zero native effects. Exact dependency/source +hashes, tests and remaining gates are retained with the source package and in +docs/task-execution-mediator-seam.md. No real grant/custody, policy default, owner +sync or native production acceptance is performed; T12 stays progress. + +2026-10-16 T12 recovery successor source preparation: optional independently +installed fixture custody durably retains operation-bound private accessors and +issuance checkpoints. Fresh cleanup-only owner permits can reconcile after actual +executor process death using fixed revoke/readback and policy delete/readback, +without restoring business/consume admission. Separate durable attempt evidence +retains original unknown outcomes. Lost token-create response remains unresolved +when no accessor was committed. Source-only process-loss fixtures are not native +production custody or recovery-role admission; T12 remains progress. + +2026-10-16 T12 recovery R2 source refinement retains R1's overbroad 404 failure: +policy cleanup now requires exact native empty-errors absence before/after delete; +HCL uses only documented single optional terminal LF normalization. Private +capsules are owner-key HMAC authenticated, strict nested schemas/ordered cleanup +commitments reject damage, and journal history prevents stale prepared capsules +from hiding issuance. Fixture process-loss source proof remains separate from +unadmitted production custody, integrity-key storage and recovery-role scope. + +2026-10-16 T12 independently reviewable budget/source slice: bound native HTTP +header/body/close, compiler work and cleanup through fixed owner main-thread +absolute budgets, with actual task expiry narrowing global authority. Actual v2 +mediator now verifies each independently installed source_bundle byte hash before +authorization/effects. No deadline/TTL extension, remint or generic service added. +Retained registry actual-provider proof still refuses Approval correspondence +before CAS/native; normalized pre-approval + precise immediate CAS whole-stack +positive remains live owner follow-up under CUST-WP-0080. T12 stays progress. + +2026-10-16 T12 actual v2 successor source proof: retained registry signed DENY +normalization from the real Secrets prepare_task_approval builder precedes actual +Approval issue/human approval. Actual Access v2 then signs ALLOW; strict Secrets +CAS and independent confirmation GET precede six disposable native calls, exact +readback and confirmed token/policy cleanup. Approval precision source permits +immediate CAS without sleeps/backdating. The 60-second immutable deadline, +30-second backend TTL, 120-second synthetic observation and existing cleanup +reserve remain bound; issued credential expiry narrows business time. Source, +caller, revoke, source-reader, registry drift and expiry refusals cause no native +effects; revoke between ALLOW/CAS retains unknown without business dispatch. +This owner fixture uses separately installed synthetic identity/key/trust and +loopback OpenBao, grants no production authority and keeps T12 progress. Prior +failed temporal/normalization proofs remain retained. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/validation.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/validation.json new file mode 100644 index 00000000..622be155 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r2/validation.json @@ -0,0 +1,33 @@ +{ + "patch_sha256": "b0c190060f5a41d6002e1fb7b49f047fd4874a51576f29f3c127a8634c2616f6", + "checks": [ + { + "command": "SECRETS_ENGINE_SOURCE_ROOT=/tmp/netkingdom-secrets-trusted-successor PYTHONPATH=/tmp/netkingdom-secrets-trusted-successor/src pytest -q tests/test_flex_auth_signer_custody.py", + "result": "12 passed in 8.28s", + "backend": "fresh disposable loopback OpenBao KV v2 per case" + }, + { + "command": "git apply --check implementation.patch against exact preimages/new-file absence", + "result": "pass" + } + ], + "previous_run": "11 passed in 7.57s before adding receipt-finalization failure test and receipt actor/time/source digest", + "actual_live_actions": false, + "fixture_generated_keys": "synthetic disposable only, no promotion interface", + "fixture_cases": [ + "CAS0 bootstrap", + "exact KV version readback", + "derived public key correspondence", + "CAS1 rotation leaves historical version", + "stale CAS conflict no overwrite", + "same-operation retry/restart refusal", + "durable intent before effect", + "lost actual write response remains unknown", + "denied write/read remains unknown", + "mismatched readback remains unknown", + "success receipt failure retains unknown", + "receipt contains no seed/bearer/backend detail", + "0600 fsynced receipt custody", + "unfenced/foreign-port/bool-version/symlink/unsafe-directory refusal" + ] +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/manifest.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/manifest.json new file mode 100644 index 00000000..a97ed12e --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/manifest.json @@ -0,0 +1,27 @@ +{ + "schema": "railiance-platform.signer-writer-metadata-delta.v1", + "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R3", + "requires_R2_patch_sha256": "b0c190060f5a41d6002e1fb7b49f047fd4874a51576f29f3c127a8634c2616f6", + "patch_sha256": "a29cdbd2ac92fd09bc6c79144e9aeb84bb6abcd303df997c0f01c0223cf1a508", + "files": { + "docs/credential-lane-designs/flex-auth-envelope-signing.md": { + "before_sha256": "43c80cafaae1cfeee76324d15def9006553de7e1e90a98252fac9aaf778fd445", + "after_sha256": "35a2ad5b86e54c5432eeb28f755086f057ba889a44412ab83ac1a52ea8548ac6" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json": { + "before_sha256": "6e798b51c25526463aa0401aa5df6e9d1a0bb754a67c7c5d96876c02dfe03266", + "after_sha256": "de7855693c424246c2e6c63e5b15f1d5d4509e6b64f3f1b234d10e675525d314" + }, + "docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed": { + "before_sha256": "4fde665568dedc5dd800e16f11e6dbfca83ea41d955efdb1fccef3976f35d6dc", + "after_sha256": "74be3565948d4a70c5b01c24d2e5886c06e8c1a884e4e355517cbcf77a03f514" + }, + "workplans/RPF-WP-0035-credential-lane-implementation.md": { + "before_sha256": "65a4350d5720acc476bf5ae8e366ce37d9e3b47f7f339e8834eba3e84c1c8b65", + "after_sha256": "d3cbe2ba5e344c1e8fc7e9f422d89030616b98abd53df4b9327f44fcaca865d3" + } + }, + "isolated_source": "/tmp/netkingdom-platform-signer-writer-r3-20261016", + "writer_behavior_changed": false, + "production_admission": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/owner-review.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/owner-review.json new file mode 100644 index 00000000..ea648204 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/owner-review.json @@ -0,0 +1,13 @@ +{ + "reviewer_role": "railiance-platform-owner", + "reviewed_revision_sha256": "a29cdbd2ac92fd09bc6c79144e9aeb84bb6abcd303df997c0f01c0223cf1a508", + "disposition": "approve-source-only", + "checks": [ + "exact preimage apply-check pass", + "JSON/docs/YAML current proposal ID equality pass", + "R1/R2 proposal IDs absent from current files", + "writer source and tests byte-identical to frozen R2" + ], + "fingerprint": "SHA256 canonical unpadded base64url public-key ASCII, not decoded bytes; consumer agreement still required", + "authority_granted": false +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed new file mode 100644 index 00000000..ad8181ed --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed @@ -0,0 +1,50 @@ +# SOURCE PROPOSAL ONLY: no CCR admission, no apply, no plaintext key. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: flex-auth-envelope-signing-eso + namespace: flex-auth +automountServiceAccountToken: false +--- +apiVersion: external-secrets.io/v1 +kind: SecretStore +metadata: + name: openbao-flex-auth-envelope-signing + namespace: flex-auth +spec: + provider: + vault: + server: http://openbao.openbao.svc:8200 + path: platform + version: v2 + auth: + kubernetes: + mountPath: kubernetes + role: flex-auth-envelope-signing-eso + serviceAccountRef: + name: flex-auth-envelope-signing-eso + audiences: [openbao] +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: flex-auth-secrets-engine-envelope-signing + namespace: flex-auth +spec: + refreshInterval: 5m + secretStoreRef: + kind: SecretStore + name: openbao-flex-auth-envelope-signing + target: + name: flex-auth-secrets-engine-envelope-signing + creationPolicy: Owner + deletionPolicy: Retain + template: + metadata: + annotations: + railiance.io/custody-proposal: RPF35-PDP-SIGNER-CUSTODY-20261016-R1 + data: + - secretKey: seed + remoteRef: + key: workloads/flex-auth/envelope-signing + property: ED25519_PRIVATE_KEY diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.md new file mode 100644 index 00000000..440999fb --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.md @@ -0,0 +1,161 @@ +# Retained lifecycle PDP signer custody proposal + +Proposal ID: RPF35-PDP-SIGNER-CUSTODY-20261016-R2. Preparation under +RPF-WP-0035-T12, beneficiary FLEX-WP-0024-T06, coordinated by CUST-WP-0080. +Status: source proposal only; no key generated, credential read, CCR admission, +policy scope granted, package published or deployment changed. + +Platform INTENT principles 3–5 require durable custody, recovery and bounded +interfaces. Platform is Staff/PEP-shaped and is not an authorization authority. +The exact candidate contract is `flex-auth-envelope-signing.proposal.json`. +Sibling `.proposed` files are review inputs outside deployment discovery; they +carry no approved CCR id and MUST NOT be applied as an admitted lane. + +## Existing workload and custody boundary + +Retain namespace/release/deployment `flex-auth/flex-auth-secrets-engine`, signer +SA `system:serviceaccount:flex-auth:flex-auth-secrets-engine`, and the twelve-action +`secrets-engine.catalog-lane.lifecycle` v2 policy. The consumer SA remains +`system:serviceaccount:secrets-engine:secrets-engine`; retained caller audience is +`flex-auth`. Neither consumer nor TokenReview credentials confer seed read rights. +Access source revision `919ce25` integrates `tenancy.yaml#/workload_identity`; +this source declaration remains separate from runtime admission. An authoritative rapp declaration remains explicit managed +package migration debt, with reference null; no synthetic rapp tuple is created. +Legacy image package remains `forgejo.coulomb.social/coulomb/flex-auth`. + +Reuse CCR-2026-0015's dedicated namespace SecretStore, exact data-only policy, +short-lived Kubernetes delivery login and separate protected CAS writer patterns. +The dedicated delivery SA is NOT the signer SA. No RoleBinding, Secret read, +TokenRequest or ExternalSecret-create permission is given to the signer/consumer. +The controller's existing ability to mint only the delivery-SA token and namespace +mutation restrictions must be independently proven before activation; source YAML +does not establish those facts. Do not silently broaden ESO RBAC. + +KV data `platform/data/workloads/flex-auth/envelope-signing` is read only by the +reviewed ESO delivery role. There is no parent/list/metadata/write permission. +Lookup-self/read and revoke-self/update support bounded session lifecycle. If ESO +needs metadata, retain a failing receipt and review that exact scope amendment. +The KV document has private `ED25519_PRIVATE_KEY` and public `ED25519_PUBLIC_KEY`, +`kid`; only the private property is projected to the Secret. A public receipt +contains kid, public key/fingerprint, KV version and exact source/deployment/policy +bindings, authenticated independently through reviewed owner custody. Consumers +must never read the private KV document to obtain the public key, trust `/v1/keys`, +or derive authority from receipt shape, policy digest or this proposal. + +## Seed, projection and protected writer + +The attended protected writer generates a fresh 32-byte CSPRNG Ed25519 seed IN +MEMORY in the custody process and writes unpadded strict base64url via CAS zero. +It derives the public key there, verifies correspondence, and emits metadata only. +No seed in argv, environment, temporary files, logs, diffs, chat, Hub or CI. +Rotation requires exact current-version CAS. No fixture seed is promotable. +`state_hub_preflight_lane.py` is a reusable design pattern, not an Ed25519 writer; +the signer-specific primitive now exists in `scripts/flex_auth_signer_custody.py`, +with a fixed disposable-only adapter. Production command/CCR admission is still +missing and the module rejects direct live execution. +Do not run the HMAC writer unchanged or claim D1 admission without that command. +The read lane does not authorize writer scope. Use the existing attended +OpenBao/warden access route; ops-warden routes and never vends this seed. + +Proposed namespace SecretStore uses dedicated SA, audience `openbao`, TTL/max/ +explicit max 15m, no default policy, no periodic token. Proposed Secret name +`flex-auth-secrets-engine-envelope-signing`, key `seed`; owner creation and Retain +deletion policy avoid implicit removal on custody outage. Retain also means a +compromised seed survives until explicit cleanup: disabling ESO is not revocation. +The current Access chart supplies readOnly volume, defaultMode 0440 and uid/gid/ +fsGroup 65532. Seed path is `/var/run/secrets/decision-envelope-signing/seed`; +private data is never envFrom. Runtime validates file mode and reads once at +startup, so ESO refresh alone cannot rotate process memory. Freeze exact Secret +resourceVersion, KV version, public admission and startup kid together; require +all replicas loaded the same admitted version before probes. No extra key reload +mechanism is proposed. + +## Durable evidence and output limits + +Reuse current Access `outbox.enabled`, existingClaim and source support: +`--outbox-dir` plus `--emission-source`, replicaCount 1, Recreate, one writer/PVC. +Do not combine with `--log`. Outbox AppendBatch fsyncs the source envelope before +returning; ordinary JSONL alone does not prove native independent custody. +Existing outbox has no total-byte retention ceiling: chart size 1Gi is requested +storage, NOT an enforced log quota. Before rollout name admitted existing PVC, +capacity/headroom, alerts, bounded export/retention, disk-full fail-closed behavior, +restart/partial-write readback tests and independent receiver/audit receipt. +Audit sender credential/receiver admission is separate, not created by this lane. +Do not silently create a PVC/spend commitment or enable arbitrary audit egress. +No current native durable/audit acceptance follows from the source feature. + +Protected writer success/failure receipts must be closed metadata objects, at +most 64KiB, stored owner-only mode 0600 with atomic durable writes. Fields: proposal +and executed revision digests, actor/time, exact path, CAS version, kid/public +fingerprint, deployment/image/policy/trust digests, boolean checks, rollback outcome. +Never include response bodies, seed, bearer tokens, accessors, wrapped values, +process environment or exception text. Bound backend reads to 1MiB and safe error +codes; no shell tracing. Public admission may carry the public key and must have +independent authenticated delivery. Access R2 native proof reader bounds receipt +reads to 524289 bytes, rejecting >524288; that is not a durable writer quota. + +## Rotation, revocation and rollback + +Admit successor public key to each consumer first through independent custody +and verify seed/public correspondence in the protected custody writer. Fence +protected consumers and stop every signer replica, prove no old-key process +remains, CAS-rotate, wait ESO version, restart the one-writer pin, then verify +successor-signed non-effect lifecycle allow/deny and durable originals before +reopening protected consumers. +After last old issuance retain old key online no longer than actual maximum allow +TTL plus a reviewed bounded uncertainty margin (default TTL is not a guarantee). +Keep archived historical keys for offline audit separate from online trust; verify +expired envelopes remain refused. Emergency compromise removes the old online key +immediately, stops old processes, and recovers forward; never restore revoked seed. +No scope/admission change to task policy: service pilot stays hard DENY and +execute-ccr stays unknown_action on lifecycle policy. + +On signer rollout failure, stop protected consumers and restore exact previous +producer image/values only as availability rollback; enforcing consumers continue +to reject unsigned decisions. Outbox/PVC and source receipts are retained. Revert +seed only for independently reviewed non-compromise recovery with corresponding +public admission; otherwise forward recovery. If grant or effect outcome is unknown, +retain unknown and reconcile; never auto-retry or translate it to success. + +## Gates and next owner work + +The JSON lists exact missing inputs and approvals. Oct11 D1 preapproves a reviewed +receipt-producing lane for an attended window; it does not create an unbuilt lane. +Oct11 standing build-mode rule permits qualifying non-destructive rollout after +reviewed diff/dry-run, rollback, abort owner and receipts; new secret/access scope +still needs founder approval. Source reviews are not human approval. Supervision +record remains supervised; costs/risk and exact executor must be admitted for the +executable revision. Source preparation costs EUR 0 incremental infrastructure; +future resource/custody loss bounds are null rather than guessed or self-approved. + +Next Platform admission task under RPF-WP-0035-T12: stage a schema-valid proposed +CCR through existing credential-change tooling and independently admit the +protected production executor/fencing/receipt adapter after required approvers +confirm the exact new custody scope. The primitive is source-tested only. Reuse existing lane +machinery. A receipt-producing command does not grant its write/read scope. +Keep CCR-2026-0048/0049, WORK-RECORDS and unrelated work unchanged. + +## Executable source primitive R2 + +The fixed disposable owner adapter reuses the native fixture's absolute two-second +transport/body/close bound and private receipt checks. It generates a new Ed25519 +seed only in the custody process, derives its public key, CAS-writes the exact +three-field document, and independently reads that exact KV version. The private +value is compared in memory; receipts carry public key/fingerprint and version +only. Rotation must CAS the expected current version and uses a fresh seed/kid. +The fixture requires explicit owner fencing and a still-live exact loopback dev +process. It cannot establish production fencing, process isolation or grant scope. + +The owner-only receipt is exclusive per operation, bounded64KiB, fsynced before +any effect, atomically replaced and directory-fsynced. Once write intent exists, +any denied/malformed/lost response or mismatched readback retains unknown. Neither +a repeated object call nor process restart using that operation receipt can retry. +There is no automatic reconciliation, rollback or seed restore. A public receipt +requires independent authenticated owner delivery before any consumer admits it. +Python cannot guarantee seed zeroization; the protected process lifetime remains +the custody boundary. Same-UID code is not isolated by0600 files. + +Actual disposable tests prove bootstrap CAS0, versioned readback, seed/public +correspondence, rotation CAS1, stale CAS conflict, response-loss uncertainty, +read denial/mismatch, pre-effect durable-intent failure, receipt secrecy, retry +refusal and invalid admission/fencing rejection. No fixture key is promotable. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json new file mode 100644 index 00000000..cc10da14 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json @@ -0,0 +1,118 @@ +{ + "schema": "railiance-platform.signer-custody-proposal.v1", + "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R2", + "status": "source-proposal-unadmitted", + "owner": "railiance-platform", + "work_item": "RPF-WP-0035-T12", + "coordination": "CUST-WP-0080", + "beneficiary": "FLEX-WP-0024-T06", + "scope": { + "namespace": "flex-auth", + "release": "flex-auth-secrets-engine", + "signer_principal": "system:serviceaccount:flex-auth:flex-auth-secrets-engine", + "consumer_principal": "system:serviceaccount:secrets-engine:secrets-engine", + "rapp_declaration_ref": null, + "migration_debt": "Managed package declaration not established; retained Helm workload is not an exemption.", + "access_identity_source": "access-engine integrated source revision 919ce25 tenancy.yaml#/workload_identity; runtime admission remains separate" + }, + "proposed_lane": { + "catalog_id": "flex-auth-decision-envelope-signing-key", + "route_status": "draft/nonresolvable", + "kv_mount": "platform", + "kv_path": "workloads/flex-auth/envelope-signing", + "private_field": "ED25519_PRIVATE_KEY", + "public_fields": [ + "ED25519_PUBLIC_KEY", + "kid" + ], + "policy": "workload-kv-read-flex-auth-envelope-signing", + "auth_mount": "kubernetes", + "auth_role": "flex-auth-envelope-signing-eso", + "delivery_sa": "flex-auth-envelope-signing-eso", + "audience": "openbao", + "token_ttl": "15m", + "token_max_ttl": "15m", + "token_explicit_max_ttl": "15m", + "token_no_default_policy": true, + "secret_store": "openbao-flex-auth-envelope-signing", + "secret_name": "flex-auth-secrets-engine-envelope-signing", + "secret_key": "seed", + "mount_path": "/var/run/secrets/decision-envelope-signing/seed", + "mode": "0440", + "private_encoding": "unpadded strict base64url of 32-byte Ed25519 seed", + "seed_load": "startup only" + }, + "independent_public_admission": { + "kid": null, + "public_key": null, + "fingerprint": null, + "custody_receipt": null, + "consumer_trust_digest": null, + "rule": "Owner-authenticated public receipt independently installed with exact evaluator/mode/policy pins; no self-discovery or private KV read by consumer." + }, + "required_approvals": [ + { + "actor": "founder", + "scope": "New exact KV read/write custody policy scope and dedicated delivery role; exact proposed CCR/revision and owner reviews required; no approval inferred." + }, + { + "actor": "Access owner", + "scope": "Exact retained workload identity/source, signer interface, unchanged policy/caller binding, image provenance and producer rollout." + }, + { + "actor": "Platform owner", + "scope": "Custody path, protected CAS writer, delivery identity/role and recovery receipts; this source review only." + }, + { + "actor": "Secrets owner", + "scope": "Independent public key/trust pins, installed helper provenance and fail-closed native consumer acceptance." + }, + { + "actor": "cluster/GitOps owner", + "scope": "Namespace SecretStore/ESO TokenRequest restrictions, manifests, rollout/headroom, existing PVC and recovery." + } + ], + "missing_deployment_inputs": { + "schema_valid_reviewed_CCR": null, + "human_exact_scope_decision": null, + "protected_signer_writer_command_digest": null, + "approved_executor_and_abort_owner": null, + "access_identity_integrated_revision": "919ce25", + "managed_package_admission_or_explicit_debt_disposition": null, + "CI_source_to_image_receipt": null, + "candidate_image_digest": null, + "KV_and_Secret_safe_version_receipt": null, + "native_identity_and_negative_scope_receipt": null, + "consumer_native_allow_deny_receipts": null, + "PVC_and_capacity_retention_admission": null, + "durable_original_and_independent_audit_receipt": null, + "reviewed_diff_server_dryrun_and_headroom": null, + "rotation_revocation_and_recovery_receipts": null, + "activation_cost_bound_eur": null, + "activation_risk_bound_eur": null + }, + "unchanged_policy": { + "package": "secrets-engine.catalog-lane.lifecycle", + "version": "v2", + "digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4", + "caller_auth": "enforce", + "caller_audience": "flex-auth", + "execute_ccr": "DENY unknown_action", + "service_pilot": "runtime_admission false" + }, + "execution": { + "authorized_by_this_proposal": false, + "key_created": false, + "route_promoted": false, + "live_changes": false, + "preparation_incremental_spend_eur": 0 + }, + "source_writer": { + "path": "scripts/flex_auth_signer_custody.py", + "scope": "protected in-memory Ed25519 CAS/readback primitive, disposable-only fixed owner fixture adapter", + "production_entry": "refused pending exact CCR/founder scope/protected runtime/fencing/receipt admission", + "independent_public_admission": "required after custody verification; receipt shape supplies no trust authority", + "retry": "none after durable intent; unknown requires independent reconciliation, no remint", + "rollback": "forward recovery; no seed restore primitive" + } +} diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md new file mode 100644 index 00000000..1ff63a5c --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/preimages/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -0,0 +1,1342 @@ +--- +id: RPF-WP-0035 +type: workplan +title: "Implement reviewed credential lanes with separate owner gates" +domain: financials +repo: railiance-platform +status: blocked +flavor: implementation +owner: codex +created: "2026-09-05" +updated: "2026-10-13" +related: + - RPF-WP-0032 + - RPF-WP-0033 + - RPF-WP-0034 +state_hub_workstream_id: "975db491-5412-5e27-8e34-14a2417bb039" +--- + +# Credential lane implementation + +One S3 queue for three designed lanes; each task keeps its own approval, +execution and closure boundary. This replaces the implementation tasks in the +three completed design workplans, not the designs themselves. No approval is +inherited by consolidation. INTENT binding: secure custody, dependable delivery, +stable consumer interfaces. Incident custody remains in RPF-WP-0027/0029. + +## Consolidate completed designs and owner dependencies + +```task +id: RPF-WP-0035-T01 +status: done +priority: medium +state_hub_task_id: "0f3606bb-e95b-5484-8a57-bcdd6e3916fd" +``` + +Completed 2026-09-05. Preserved the three designs under +`docs/credential-lane-designs/`, identified native owner responsibilities and +linked each superseded task below. Owners have not been sent new requests and +no new external acceptance is claimed. STATE-WP-0085-T09 is already done; +the signing dependency belongs to the proposed FLEX-WP-0020-T05 cutover. + +## Accept and provision secrets-engine service JWT login + +```task +id: RPF-WP-0035-T02 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +depends_on: [KEY-WP-0039-T02, MASON-WP-0009-T05] +blocking_reason: "Agent work, not a human gate: claim refusals (KEY-WP-0039-T02 probe) and capabilities-self deny, then ops-mason MASON-WP-0009-T05." +priority: high +state_hub_task_id: "e0c82ea9-05a5-537e-8fbf-67534263572e" +``` + +2026-10-11: requalified — the remaining waits are other owners' tasks, not a human gate. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0032-T02. Design: +`docs/credential-lane-designs/secrets-engine-service-jwt.md`. + +Platform owns the exact JWT mount/role/policy, effective-policy negative tests +and a metadata-only custody receipt. KeyCape owns issuer/JWKS and service +registration (KEY-WP-0009); secrets-engine owns service authentication and +authority consumption (SECRETS-WP-0008-T06, SECRETS-WP-0007-T04). + +**Unblock:** live registration and protected client custody, reviewed exact source +and attended apply authority. Issuer/JWKS and consumer source claims now agree; +see the 2026-09-27 return below. A service login does +not grant lane mutation authority. Do not build another identity provider or +lifecycle engine here. + +**Done when:** approved exact role succeeds for the intended service, wrong +issuer/audience/subject/claims and unrelated secret access fail, bounded TTL +and revocation are proven, the consumer explicitly opts into the verified +contract, and rollback/cleanup receipts contain no secret material. + +2026-10-09 (T03 source): founder ruled the tenant segment stays `coulomb` +(ops-mason `b72ff77d`). New CCR request type `workload-kv-operator-matrix` +(`scripts/operator_matrix_lane.py`): exact per-entry capabilities, OIDC role on +the existing `netkingdom` mount only, and exact agent denies on all four data +and metadata paths appended to the live `agent-high-risk-boundary` (live content +preserved; partial presence refused). `scripts/fluid_telegram_custody_move.py` +copies the four undocumented `infotech` entries with CAS 0, verifies all, then +metadata-deletes the sources. `scripts/kv_duplicate_retire.py` retires +`activity-core/default/llm-connect-provider-secrets` only if no live non-admin +policy grants it. Founder session (each helper prints nothing; read the receipts): + +```bash +cd ~/railiance-platform +export BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 +W='warden access openbao-platform-admin-login --exec --' +# 1. dry-runs (no value reads, no writes) +$W python3 scripts/fluid_telegram_custody_move.py --dry-run --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move-dry.json +$W python3 scripts/kv_duplicate_retire.py --dry-run --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire-dry.json +# 2. lane: approve, confirm binding, apply +python3 scripts/credential-change.py approve CCR-2026-0039 --reviewer "platform-owner, fluid-telegram-owner, key-cape-owner (founder Bernd Worsch)" --comment "Approve ops-mason plan fluid-telegram-operator-credential-lane (spec 41a0ca27): four-entry matrix at coulomb/fluid-telegram/hall-of-helix, OIDC role on netkingdom, agent denies." \ + && python3 scripts/credential-change.py confirm-binding CCR-2026-0039 --reviewer founder --comment "groups=[fluid-telegram-operators] (LLDAP, member tegwick) and /assurance/level=aal2 match key-cape b2ed890f." \ + && $W python3 scripts/credential-change.py applier-apply CCR-2026-0039 --confirm "DELEGATED APPLY CCR-2026-0039" --actor founder --record-state-hub --quiet +# 3. custody move, then duplicate retirement +$W python3 scripts/fluid_telegram_custody_move.py --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move.json +$W python3 scripts/kv_duplicate_retire.py --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire.json +``` + +2026-10-09 (T03 founder session): CCR-2026-0039 applied at 10:30Z; readback +matched for the 8 boundary denies, policy and role. Custody move `moved`: all +four entries copied at coulomb v1 (operator-session from infotech v4) and the +infotech entries metadata-deleted. Duplicate +`activity-core/default/llm-connect-provider-secrets` retired; its first dry-run +refused on mount-wide `platform/metadata/*` survey grants, after which the check +was narrowed to data-path grants (`64ae594`). Receipts: +`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +2026-10-03 (CUST-WP-0075): gate check. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named in the design is open. It is not the last one: the design says to confirm the exact live client registration and protected client-side custody before writing, and positive-login proof needs a real KeyCape service JWT. KeyCape's contract (`openbao-service-auth-contract.md`) and KEY-WP-0009 claim source registration only; the live registration of `secrets-engine-openbao` and its client-credential custody are "a separate approved custody action" that no workplan task owns yet (SECRETS-WP-0008-T06 waits on this task). Re-qualified with `blocked_on: message-from:key-cape`; key-cape was asked for the owning task id, which will replace it as `depends_on`. The design stays proposed and no child command was written. Not approvable in D1 yet. + +2026-10-04: Founder authorized the prepared coordination request. Sent +`b4fc62ea-f92c-4410-919a-9f3cce2d406b` to key-cape on preparation thread +`f84637fa-2355-4971-a2dc-7f1fd01710a8`, referencing platform source +`6b91d510395215d178d60ee8884e7fc00930a0cf`. Requested actual registration and +protected-custody owning tasks/status/revisions and non-secret receipts. Source +registration is not live custody; no value fetch or live registration was +requested. T02 remains waiting on the owner return and separate execution gates. + +2026-10-04 blocked-task review: KeyCape returns 58826056/eb20a78c now identify +KEY-WP-0037-T02/T03/T04, replacing the unowned-registration wait with real +dependencies. Prepared proposed CCR-2026-0033 and exact-path issuer policy/auth, +sso-only ESO and evidence checklist from the returned candidate coordinates. +No issuer/consumer value, registration or native issuance is supplied by them. +secrets-engine must return independent source acceptance of consumer host/path, +protected delivery and rotation/revocation ownership; awaiting that source phase +does not depend on its full live service-login task. KeyCape's exact-primary sync +remains pending its scoped historical identity repair. Requirements and acceptance +boundaries: `docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`. +This workplan was already blocked and remains blocked on its open owner/live gates. + +2026-10-06: secrets-engine returned consumer custody source acceptance +(message 680136e2, SECRETS-WP-0012, commit a3897c2). CCR-2026-0033 finalized as +**proposed**: KV path corrected to `platform/workloads/keycape/secrets-engine-openbao` +(applier scope), consumer copy coordinates with D1-D4 pending founder choice, +rotation/revocation ownership, live order and rollback. Attended custody child +`scripts/keycape_secrets_engine_openbao_custody.py` with fake-only tests +(`tests/test_keycape_secrets_engine_openbao_custody.py`) refuses without an exact +founder decision id recorded in the approved CCR. Nothing executed, generated or +applied; nothing added to active GitOps. The founder approval it needs is T09. + +2026-10-09: KEY-WP-0037 finished 2026-10-07 (registration live, issuance +verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Source for this +lane is now complete as **CCR-2026-0038** (proposed, +`credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml`). +The delegated applier gained a narrow `service-jwt-login` request type +(`scripts/service_jwt_lane.py`): auth mount fixed to `keycape-services`, policy +must equal the generated login-self policy, role/config keys allow-listed, +TTLs at most 15m, uses 1..16, `token_no_default_policy`, refusal if the mount +exists with another type, and a value-free readback compare after the writes. +Policy `secrets-engine-login-self` now also carries explicit `deny` on +`platform/{data,metadata}/workloads/keycape/secrets-engine-openbao` so +ops-mason invariant (ii) (no capability on the client-secret path) holds even +if identity groups were ever attached. Tests: `tests/test_service_jwt_lane.py` +(8) plus the updated contract test; full suite unchanged apart from 5 +pre-existing failures unrelated to this lane. + +Founder apply (one line; approval, binding confirmation and silent apply): + +```bash +cd /home/worsch/railiance-platform && python3 scripts/credential-change.py approve CCR-2026-0038 --reviewer "platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd Worsch)" --comment "Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self (self endpoints + deny on the client-secret path)." && python3 scripts/credential-change.py confirm-binding CCR-2026-0038 --reviewer founder --comment "Bound claims match KeyCape registration: aud secrets-engine-openbao, sub service:secrets-engine, principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social RS256." && warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/credential-change.py applier-apply CCR-2026-0038 --confirm "DELEGATED APPLY CCR-2026-0038" --actor founder --record-state-hub --quiet +``` + +Done after that: login proof with a real KeyCape service JWT +(SECRETS-WP-0012-T03 probe-openbao; policies exactly +[secrets-engine-login-self], capabilities-self deny on the guarded paths, +revoke-self), negative claim checks, then publish the consumer contract file +and ops-mason MASON-WP-0009-T05 rechecks invariant (ii). + +## Implement the platform operator-write CCR contract and Fluid lane + +```task +id: RPF-WP-0035-T03 +status: wait +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +blocking_reason: "Founder session done 2026-10-09; waits on ops-mason verification (MASON-WP-0005-T05) and the FT-WP-0002 owner salt CAS probe." +priority: high +depends_on: [MASON-WP-0005-T05, FT-WP-0002] +state_hub_task_id: "f47e5bc5-6f3c-54bb-aa35-260ad03892ba" +``` + +2026-10-11: requalified — founder part done; remaining waits are owner tasks. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Supersedes RPF-WP-0033-T02. Design: +`docs/credential-lane-designs/fluid-telegram-operator-kv.md`. + +Platform owns the per-path capability schema/validator, exact OpenBao policy +and accepted custody coordinates. MASON-WP-0005 owns construction coordination +and engine integration; KeyCape/NetKingdom own OIDC/MFA and group membership; +FT-WP-0002 owns client CAS, prefix correction, output containment and Telegram +application acceptance. Retain the existing read-only CCR semantics. + +**Unblock:** accept tenant/path and per-entry field/capability matrix; confirm +actual group/assurance and callbacks, reviewed construction contract and writer +authority. Contract review can proceed without a live credential; the final +schema cannot be treated as accepted solely because a draft exists. + +**Done when:** validation rejects broad/unsupported grants, the consumer proves +CAS=0 first-write behavior and no value output, approved identities can perform +only the exact matrix, negative/expiry/revocation checks pass, custody is seeded +through the separate writer, and the verified route has a safe handoff receipt. +The unattended adapter remains a separate demand and gets no operator session. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Accept the needed signing lane and deliver it to the owning runtime + +```task +id: RPF-WP-0035-T04 +status: done +priority: medium +state_hub_task_id: "35a85846-61d5-54ce-8b18-ede45733d53c" +``` + +Supersedes RPF-WP-0034-T02. Design: +`docs/credential-lane-designs/state-hub-preflight-signing.md`. + +Platform owns signing-key custody, exact read policy/role and scoped delivery +acceptance. State Hub owns API chart/env wiring, all-replica rotation fencing +and health. FLEX-WP-0020-T05 owns the rename preflight/cutover dependency; +STATE-WP-0085-T09's adoption-plan delivery is already complete. + +**Unblock:** State Hub/repo-manager and the consuming migration owner confirm +that this transitional State Hub lane is still needed during retirement; +record the target runtime, namespace/SA/auth audience and an executable +rotation fence, plus approved writer and deployment window. Do not broaden the +lane into a general repository-rename authority or provision for a stale demand. + +**Done when:** protected one-time generation, API-only ESO delivery, negative +access checks and a non-mutating signed preflight pass; every API replica uses +the accepted version; rotation/invalidation and recovery are evidenced. No +repository rename is part of S3 lane acceptance. If demand is withdrawn, record +the owning decision and cancel this task explicitly rather than provision it. + +2026-09-05 continuation: verified the live primary cluster identity and healthy +single API replica; the signing ExternalSecret is still absent. Added a writer +guard against wrong-cluster kubeconfigs before any OpenBao access. The default +workstation kubeconfig's local port-forward listener was unavailable. Activation +still needs the contained attended OIDC/MFA login and the acceptance evidence +above; source preparation is not live completion. See +`history/2026-09-05-preflight-signing-activation-readiness.md`. + + +Completed 2026-09-05: user-led attended activation generated version 1 and +rotated to version 2 with every API replica stopped. Exact access and negative +identity checks passed; ESO delivery and API-only exposure passed; the recovered +single API replica accepts new signed preflight and rejects its predecessor by +signature, with healthy primary identity and no preflight blockers. State Hub +chart commit `49e3182`, Helm revision 59. No repository rename executed. +Evidence: `docs/evidence/RPF-WP-0035-T04-signing-activation-2026-09-05.json`; +closure: `history/2026-09-05-preflight-signing-activation-complete.md`. + +## Admit KeyCape approval-engine client custody and delivery + +```task +id: RPF-WP-0035-T05 +status: done +needs_human: false +intervention_note: "" +priority: high +state_hub_task_id: "e15d62c9-e5da-5721-a135-87c050f7851c" +``` + +Answers KEY-WP-0013-T02 (State Hub message +`278a3ebe-b529-49f6-bd1a-e3ebcf318260`). Admission: +`docs/credential-lane-designs/keycape-approval-clients.md`; requests +`CCR-2026-0017` (secrets-engine-approval) and `CCR-2026-0018` +(approval-engine-operator). + +Platform owns the two custody paths, exact-path read policies, Kubernetes auth +roles and the KeyCape-side ESO delivery. KeyCape owns the client registrations, +issuance, claim set and disablement; approval-engine owns approval semantics and +audit of emitted actions. + +2026-09-08 admission response: both proposed KV paths confirmed unchanged; field +`client_secret` corrected to `CLIENT_SECRET` for the uppercase KV convention and +CCR validator. Kubernetes delivery references confirmed against the live `sso` +namespace, which already resolves `KEYCAPE_RAPP_QONTO_CLIENT_SECRET` through the +same `secretKeyRef{key: client-secret}` shape on image `main-153258b`. Attended +authority named as the governed `openbao-platform-admin-login` lane +(`founder_required`); KeyCape's refusal to treat its generic `warden plan` +database match as authorization was correct. Rollout agreed as one attended +session with the KeyCape reading build pinned but undeployed, ordered after the +Authelia issuer precondition in message `c8b1ad10-dae8-48fb-a0ea-7e2a101c54bf`. +Policies, ClusterSecretStores and ExternalSecrets are written and validated, +none applied. + +**Unblock:** owner approval of both CCRs, a KeyCape image that reads both +environment names, the settled Authelia `iss` pin, and a founder-attended window +date. Verifier-side custody only — no client-side read lane is admitted, and no +scope beyond the two declared sets. + +**Done when:** both CCRs are approved, the attended window seeds both KV paths +with CAS=0, policies/roles/stores/ExternalSecrets apply and sync, the KeyCape +build resolves both environment names, KeyCape evidences live JWKS signature and +exact claim bindings with excess scopes denied (operator `consume`, human +`consume`), platform evidences cross-path/wrong-identity/out-of-namespace denial, +and every receipt is metadata-only. If either registration is abandoned, KeyCape +disables it before the KV version is destroyed. + +### 2026-09-08 actual upstream issuer returned + +The admitted KeyCape one-shot probe verified the actual signed upstream issuer +as **`https://auth.coulomb.social`** at 21:44:44 UTC. Signature, audience, +validity window and nonce checks passed and the pinned Job exited 0. All +five temporary resources and the Pod were removed; normal KeyCape Deployment +and config Secret metadata are unchanged. See +`docs/evidence/2026-09-08-keycape-upstream-issuer-proof.json`. + +T05's unknown-issuer input is resolved. The configuration owner still ensures +`authelia.issuer` equals that exact HTTPS value before the custody window. +Both CCRs remain proposed and await the named reviews; this probe grants no +custody mutation or client-side read. Keep the current authority preflight and +this signed-token proof as separate receipts. Live ESO/client/approval and +separate audit/client-side custody acceptance remain open. + + +2026-09-09 configuration and review-queue return: NetKingdom pinned the verified +HTTPS issuer, using an atomic UID/resourceVersion test and independent readback. +Secret revision `58713343`; unrelated configuration and signing key unchanged; +no Deployment rollout. Receipt: `docs/evidence/2026-09-09-keycape-upstream-issuer-pin.json`. + +The two existing CCRs remain proposed. They now link to concrete pending review +decisions, with platform-operator and key-cape-owner named explicitly. See +`docs/credential-lane-designs/keycape-approval-clients-review.md`. T05 owns this +human dependency; HFACT consumes it without a duplicate approval request. +Custody/ESO activation, client verification and the separate client-side/audit +lanes remain open. Current CLI apply plans refuse the proposed requests. + + +2026-09-09 admission: the user explicitly approved both CCRs in the named +platform-operator and key-cape-owner roles. Both source requests are approved +and both linked Hub decisions are resolved. Receipt: +`docs/evidence/2026-09-09-keycape-approval-admission.json`. The completed review +intervention is cleared; T05 is progress while the contained first-provision +procedure is exercised and the admitted attended rollout is carried through. +Verifier-side scope, separate client-side/audit lanes and live acceptance remain +as defined in the reviewed requests. + +2026-09-09 verifier-side return: both CCRs are verified after recorded user approval, +CAS=0 version-1 custody, native read/auth denials and revocation, Valid stores, +SecretSynced delivery, compatible KeyCape rollout and live positive/negative +service checks. Existing human OpenBao login passed again on the new image. +Receipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. Failed attempts restored the compatible +configuration/image and detached delivery; final resume reused version 1. + +T05 is done against its verifier-only acceptance criteria. Its former +"remains progress for client-side reads" statement expanded the task past its +reviewed scope; that residual now has the live owner task RPF-WP-0035-T06 below. +Neither Warden fetch selector is resolvable through these verifier-only CCRs. +Do not re-request the completed two named reviews or reseed these paths. +Rotation is a distinct, version-guarded operation. + +## Dispose of the ungoverned whynot-design npm duplicate + +```task +id: RPF-WP-0035-T07 +status: wait +decision_id: 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa +blocking_reason: "Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish." +priority: high +depends_on: [SECRETS-WP-0006-T06] +state_hub_task_id: "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b" +``` + +2026-10-11: requalified after founder decision D3 (trust root, build-mode default) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +Found by the attended session on 2026-09-10 while settling the npm field +question. `secret/coulomb/whynot-design/npm/publish` exists at version 1, +created 2026-07-03T15:00:44Z and never updated — five days after the governed +lane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified +(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and +outside any CCR here. Receipt: +`docs/evidence/2026-09-10-npm-lane-field-resolution.json`. + +Only metadata was read. Its field names were not enumerated, its value was not +read, and nothing was deleted — a location holding real credential material is +disposed of deliberately, not tidied away in the session that found it. + +The likely explanation, unconfirmed: secrets-engine reports the lane's field +under a lowercase name that is absent from the governed path, and their catalog +declares this legacy location. If their proven pilot publish read from here, +then a working production lane has been running off an ungoverned duplicate, +and the governed lane's acceptance evidence describes a path the consumer does +not use. That is worth establishing before anything is removed. + +**Operator decision, 2026-09-15:** destroy the legacy path after confirming the +governed lane is the live consumer. Do not wrap `secret/coulomb/whynot-design/npm/publish` +in a CCR. Value remains unread. Platform will ask secrets-engine which path +publish actually reads before any attended destroy. + +**Unblock:** admit the governed exact-path AppRole policy and coordinated catalog +path/field migration under SECRETS-WP-0006-T06; prove native delivery from the +governed lane before the attended legacy destroy. secrets-engine confirmed the +legacy source path on 2026-09-21 (message `355424d4-17ab-435e-9e1d-6921775cb4a2`). +No comparison of values, fingerprints, lengths or shapes is needed or authorized. + +**Done when:** the legacy path's provenance and consumer are established, the +governed lane is confirmed as the one in use or the consumer is moved to it as a +reviewed lane change, the duplicate is destroyed under the September 15 operator decision and the +disposition is recorded. Do not bring the legacy duplicate under a CCR. If the value proves to be live and +ungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027: +never record the value, fingerprint, length or shape. + +2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here. + +## Admit the separate approval client-side readers + +```task +id: RPF-WP-0035-T06 +status: done +decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 +priority: high +intervention_note: "" +state_hub_task_id: "68bff751-e48b-548b-8fb4-dfb3b16210c2" +``` + +2026-10-11: requalified after founder decision D1 (attended window standing rule) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +**Current return, 2026-09-10:** CCR-2026-0020 is cancelled on the requesting +Approval Engine owner's explicit withdrawal, source +`849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md`. +No presenter exists and no reader is wanted. The validator now accepts terminal +cancellation of an incomplete request only with owner/source/reason evidence, +retained declared omissions and a disabled, non-resolvable front door. Apply +remains refused. No live identity, policy, role, custody or verifier was changed. +Human approval follows existing INFD-WP-0001-T07/T08; future service requesters +need a separate narrow registration, not this withdrawn bundle. + +**Operator binding confirmed, 2026-09-14:** The user explicitly selected +`net-kingdom-admins` and authorized applying CCR-2026-0019. Its OIDC role is +`secrets-engine-approval-client-workload-kv-read`, aligned with the platform +applier naming rule; policy and exact KV scope are unchanged. The metadata dry +run passes with no warnings. Attended apply and exact role/policy readback passed; the enclosing Warden +command exited successfully after its self-revocation/cleanup. Receipt: +`docs/evidence/2026-09-14-ccr0019-operator-binding.json`. Scoped delivery proof +remains pending; the front door stays non-resolvable. Completed CCR-2026-0017/0018 +remain closed and T06 stays `wait`. + +Consumer procedure returned in source, 2026-09-10: +`secrets-engine@98d72ceb1dbcff2d2a80fb8c3058d76777a0ac93:docs/approval-service-auth.md` +specifies the requested private 0700 runtime directory, 0600 file outside Git, +path-only use, claim/consume lifetime and attended cleanup including hard-stop +residual inspection. CCR-2026-0019 retains this source-review comment without +changing admission status. Exact group, required-owner review, attended apply and +native positive/negative/cleanup evidence remain. No role or credential changed. + +Separate retained owner decision: KeyCape's 2026-09-10 return +`21427688-725f-4dea-aab4-7c78fd4328d2` identifies the already-live, unpresented +CCR-2026-0018 registration. Approval Engine, KeyCape and Platform must explicitly +decide retention/expiry or coordinated disablement. Reader cancellation neither +disables that live registration nor accepts indefinite retention. Keep this +disposition in T06; it is separate from the wanted CCR-2026-0019 factory reader. +No unilateral issuer/config/Secret change is authorized by this closeout. + +**Operator decision, 2026-09-15:** coordinated disablement with KeyCape and +Approval Engine. Platform will not disable the live registration or verifier +delivery unilaterally. T06 stays `wait` until both owners confirm the joint +disablement sequence. + +Residual handoff from RPF-WP-0035-T05; consumes the completed verifier custody +without extending CCR-2026-0017/0018. Owner: railiance-platform with the named +secrets-engine and approval-engine operator consumers. + +Prepare separate exact-reader admissions for existing version-1 paths: +`platform/workloads/secrets-engine/approval-client` and +`platform/workloads/approval-engine/operator-client`, field `CLIENT_SECRET`. +Name each actual actor/placement, bounded authentication/reader policy, protected +consumer delivery, cleanup/revocation and rollback, then obtain the required +owner reviews for those concrete requests. No reseeding, rotation, shared reader, +reuse of the sso verifier Secret, or implicit operator consume grant. + +2026-09-09 preparation return: both exact-reader admissions are prepared as +`CCR-2026-0019` (secrets-engine) and `CCR-2026-0020` (approval-engine-operator), +with their exact-path read policies written and committed. Design: +`docs/credential-lane-designs/keycape-approval-client-side-readers.md`. Both +reuse existing version-1 custody; no reseed, rotation, shared reader or verifier +Secret reuse. Both are `in_flight` and unapproved; nothing is applied. + +Read-only survey findings that decided the two shapes. Namespace +`secrets-engine` holds only ServiceAccount `secrets-engine` with no workload, +and `flex-auth/flex-auth-secrets-engine` is that consumer's PDP, not the +service; secrets-engine consumes the client secret through an operator-run CLI +reading `SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE` (SECRETS-WP-0009-T03, +revision `9eb07fd`). So reader 1 is an attended operator-workstation OIDC lane, +not an ESO lane. approval-engine has no namespace, workload or Service; its +manifest is unapplied, and no owner source names who presents the operator +client — approval-engine verifies these tokens and never holds them. + +**Unblock:** reader 1 needs the exact NetKingdom/KeyCape group claim for the +authorized operator, plus secrets-engine confirming the file mode and removal +step; `openbao.auth` is declared missing rather than filled with a placeholder +that would later read as a confirmed binding. Reader 2 needs its owner to name +the presenting actor and placement, or to record that no client-side reader is +wanted so the request is cancelled. Naming a reader for the widest approval +scope without that decision is the failure this task exists to avoid. + +**Done when:** each reader has a named actor and placement, a completed and +reviewed auth binding, admitted delivery, and its owner approvals; positive and +negative checks pass, including cross-path, wrong-identity and parent-list +denial and operator `consume` denial; or the request is explicitly cancelled by +its owner. Rotation stays a distinct version-guarded operation shared with +CCR-2026-0017/0018. + + +Consumer input supplied 2026-09-09: secrets-engine now implements per-request +`secrets-engine-approval` exchange from a protected temporary client-secret file, +with exact approval-engine / tenant:platform / read-or-consume scope, no token +file and no fallback. The pinned KeyCape image and actual Approval Engine source +passed its disposable component exercise; only the PDP was a sequencing double. +See `secrets-engine/docs/approval-service-auth.md` and the metadata receipt +`secrets-engine/docs/evidence/2026-09-09-approval-identity-exercise.json`. + +Routing check: `warden route show keycape-secrets-engine-approval-client` is +unknown; generic `openbao-api-key` routes ownership only and is not a delegable +lane. Do not advertise a working fetch command before this task supplies its +own accepted native delivery return. Client-side admission is not ready for a +new human decision until exact requests and contained execution/rollback checks +are reviewable; the completed verifier reviews must not recur in that queue. + +**Done when:** each retained consumer admission is approved and implemented, or +its requesting owner explicitly cancels it (CCR-2026-0020 now satisfies that branch); +actual consumer authentication/delivery succeeds; sibling/listing/wrong-reader +and scope refusals plus reader expiry/revocation/cleanup are evidenced; version-1 +custody and verifier availability remain intact. Return the source and metadata +receipts to HFACT-WP-0001-T03, SECRETS-WP-0009-T03 and APPROVAL-WP-0002-T01/T05. +Audit receiver/sender custody remains AUDIT-WP-0009-T09 and must not be folded +into this client-identity grant. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Admit the two factory audit-sender custody lanes + +```task +id: RPF-WP-0035-T08 +status: wait +decision_id: "ab85ae8a-12a0-4945-ae64-1d3d86d5b26f" +blocking_reason: "Approved conditionally (ab85ae8a, standing change rule): executes once independent archive readback and the interim bearer revocation receipt exist; owner work with audit-core." +priority: high +assignee: railiance-platform +intervention_note: null +blocked_on: message-from:audit-core +state_hub_task_id: "0ef52c26-2669-5cd1-8149-b1f6fcdda6cb" +``` + +2026-10-11: requalified — ab85ae8a resolved under the standing build-mode change rule. See the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md. + +2026-10-03 correction (CUST-WP-0075, informed-decision sitting draft `55fb078`): the D1 routing was wrong. First provision and delivery already ran on 2026-09-11, with seed and delivery receipts, and the review packet says not to repeat them. The task is not a provisioning-window act. It was taken off decision D1, and its blocking_reason now names what actually remains. railiance-platform should re-qualify it further if the receiver rollout has since happened. + +2026-10-03 (CUST-WP-0075): re-qualified. The receiver rollout already happened: Audit Core c82e0442de0f carries evidence_kind and native producer accepted/duplicate and scope/read-refusal checks passed 2026-09-11 10:42 UTC (`docs/credential-lane-designs/factory-audit-senders-review.md`, `factory-native-acceptance.md`). Remaining: independent archive readback and audit bearer-revocation acceptance. Still not a provisioning-window act. + +Consume AUDIT-WP-0009-T09/T11's exact declarations for approval-engine and +informed-decision: tenant:platform, write-only, load-bearing, redact. Source +preparation supplies two approved CCRs, independent exact-path policies/ESO +projections, and the attended `factory_audit_custody.py` first-provision helper. +Its CAS and request-provenance checks preserve unrelated senders and recover +interrupted writes without generating replacements. The user approved all named review roles on 2026-09-11. Native +provision/delivery/receiver-ingestion acceptance remains open. + +The 2026-09-11 native read-only check found an additional deployment dependency: +receiver image c2fe39a is 1/1 Ready but does not support evidence_kind. The +synthetic native probe now refuses before any credential read. Current receiver +source passes. AUDIT T09/T11 retain compatible release/source-manifest rollout; +Approval Engine's missing namespace remains its owner prerequisite. + +[Review packet](../docs/credential-lane-designs/factory-audit-senders-review.md). +[Preparation evidence](../docs/evidence/2026-09-11-factory-audit-custody.json). +Do not fold these senders into CCR-2026-0019 or the cancelled CCR-2026-0020. + +2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion. + +## Dependency review — 2026-09-06 + +### 2026-09-09 tenant question resolved — no change needed + +The `tenant:coulomb` / `tenant:platform` discrepancy raised against T02 is not a +discrepancy. KeyCape confirms decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6` +binds the *approval chain* to the landlord zone and was applied to exactly two +registrations, `secrets-engine-approval` and `approval-engine-operator`. +`codex-railiance-platform` is not in that chain and correctly stays +`tenant:coulomb`, as do `secrets-engine-openbao` and the human directory default. +KEY-WP-0013-T04 records this and their +`TestServiceRegistrationTenantsAreExactPerDecision` pins every reviewed client's +tenant against the real fixture, so a reintroduced alias fails their build. + +`docs/credential-lane-designs/secrets-engine-service-jwt.md` already says +`tenant:coulomb` and is therefore correct as written. Bind the exact role to +`tenant:coulomb`. Do not "correct" it to `tenant:platform` later; that would +break the issued claim. + +SECRETS-WP-0008-T02 now records the local PIP claim/validation join implemented +and tested. Its remaining gate is the unreachable approval-engine claim endpoint +and access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old local +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 ` 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. + +### Sender approval recorded — 2026-09-11 + +The user replied "good, go on" to the explicit CCR-2026-0021/0022 question naming +platform-operator, audit-core-owner and both producer owners. Both exact requests +are approved; their existing State Hub decisions are resolved. This clears the +review request only. Receiver rollout, namespace readiness, attended custody and +positive/negative native evidence remain the execution gates. + +### Native receiver and attended execution return — 2026-09-11 + +Audit Core c82e0442de0f is deployed and passes the native synthetic contract. +Its existing 32-event chain/head is unchanged. The owner Approval Engine +namespace now exists and all four ESO objects pass strict server dry-run. +The two exact ingress rules are applied; sender custody/ESO application is not. + +Warden selected founder_required/oidc_login and attempted the reviewed silent +seed command through the contained wrapper. Login failed before command +handoff; no custody receipt was created. Warden could not confirm remote +session revocation. Await operator browser/MFA feedback and login/session +resolution. Approvals remain valid; T08 waits for the identity act, not review. + +The receiver check now selects component=receiver, so retained attestation-job +pods cannot falsely block a stable receiver. Eighteen custody tests pass. +[Native return](../docs/evidence/2026-09-11-factory-receiver-live.json). + +### Attended custody retry succeeded — 2026-09-11 + +The user requested a retry and completed the attended identity act. Both CCRs +are applied: independent version-1 custody and registry CAS 7→8 succeeded, +preserving other senders/fields. Warden exited 0 with self-revocation confirmed +for this session. This does not retrospectively attest the earlier failed +login's remote session state. The old login wait is cleared; T08 is progress +for ESO delivery, exact native reader/namespace refusals, receiver reload and +producer acceptance. No token is reseeded or rotated on continuation. +[Seed receipt](../docs/evidence/2026-09-11-factory-audit-sender-seed.json). + +### Delivery prepared; fresh login did not hand off — 2026-09-11 + +The delivery helper and custody receipt are committed at `44314ca` and exactly +projected on primary/railiance01. Seven delivery tests and 18 custody tests +(including 11 actual disposable OpenBao cases) pass. The fresh attended +delivery invocation exited 5 before command handoff; no native delivery +receipt exists, no ESO application or receiver restart ran. The receiver +remains 1/1 Ready on c82e0442de0f. Warden could not confirm revocation for this +failed login; that is separate from the successful seed session. T08 now waits +for this delivery identity act. Neither CCR review nor first provision reopens. + +[Delivery return](../docs/evidence/2026-09-11-factory-audit-delivery-login.json). +Use the reviewed delivery command with a new receipt after login feedback. +Actual producer ingestion/duplicate/refusal and bearer revocation acceptance +remain open under AUDIT-WP-0009-T09/T11. + +### Native delivery accepted — 2026-09-11 08:27 UTC + +The user returned and requested another login attempt. It succeeded and the +reviewed delivery command completed in 28 seconds. Both native ESO readers +passed exact-path access and explicit sibling/registry/metadata/listing denials, +wrong-SA/namespace refusal and the coding-agent deny check. Each 900-second +reader session was revoked and lookup refusal verified. Both intended +ExternalSecrets are Ready; exact producer value and ESO ownership match. The +disallowed namespace produced an explicit store restriction and no Secret; +the uniquely owned namespace is now absent. + +Registry version 8 matches the delivered receiver JSON. Audit Core reloaded +and remains 1/1 Ready on c82e0442de0f; /readyz reports operational/durable with +tamper_evidence=false, as bounded by AUDIT-WP-0009-T12. Warden exited 0 and +confirmed self-revocation for this successful session. Earlier failed login +receipts remain historical and are not retroactively attested. + +The login wait is cleared. T08 remains progress and CCR21/22 remain applied +for native producer ingestion/duplicate/scope/read-refusal and bearer +revocation acceptance under AUDIT T09/T11. No credentials were reseeded or +rotated. No producer was deployed and no factory attempt or paid call ran. +[Native delivery receipt](../docs/evidence/2026-09-11-factory-audit-delivery-live.json). + +### Native producer return — 2026-09-11 10:42 UTC + +Both actual source adapters used their own ESO-delivered credential inside a +bounded native Job. Each synthetic event received 202, retained its durable +outbox after an injected lost receipt, and received duplicate 200 after a fresh +process reopened the outbox. Each source's reconciliation reported exactly one +record for its unique probe class. Wrong source/tenant, seven archive read +routes, sibling reconciliation and invalid-bearer requests were refused. + +The first Informed Decision probe exposed a private-store startup defect: +fsGroup volumes add inherited setgid to a newly created 0700 directory. +Informed Decision `1a12223` corrects creation without repairing unsafe existing +data. The regression failed before the fix; the available suite now passes +335 tests with 39 optional checks skipped. Native retry verifies the exact +corrected helper. Six probe tests and eleven rebuilt-container checks pass, +including actual setgid-volume startup, restart/restore and cleanup. + +All temporary probe Jobs, Pods, ConfigMaps and NetworkPolicies are verified +absent. Receiver c82e0442 remains operational/durable; tamper_evidence=false. +Producer verification requires no operator registry read or new OpenBao login. +Independent readback is a separate attended command consuming the successful +receipt; it must not rerun the producer jobs. Both attended verification-login +attempts this session ended before handoff (exit 5; remote revocation +unconfirmed), so independent archive readback remains pending. + +This proves synthetic outbox delivery/recovery with native sender credentials, +not domain-transaction atomicity, deployed producer services or human binding. +An invalid bearer is not a revoked formerly valid bearer. AUDIT T09/T11 and +RPF T08 remain progress for independent readback and audit bearer-revocation +acceptance; CCR21/22 remain applied. Service/policy/human admission and native +runtime/spend gates remain separate. Factory attempts and paid calls remain 0. + +[Native producer receipt](../docs/evidence/2026-09-11-factory-native-producers.json). + + +## Independent audit readback — 2026-09-11 13:11 UTC + +The existing attended readback command completed with exit 0 while the user +was present. Independent read-only identity `operator` found both retained +`factory-audit-20260911104152-94aced` producer events with exact source and +`tenant:platform`; receiver integrity is intact across 36 events. The wrapper +confirmed this session's self-revocation and private-helper cleanup. Prior +failed sessions' unconfirmed revocation remains historical unresolved evidence. + +This supersedes the earlier readback-login wait. No producer jobs were rerun, +no credentials were reseeded and no event was written by the reader. The +inherited zero registry-read count belongs to the producer phase; the attended +reader did consume registry version 8. CCR21/22 stay applied and owner tasks +stay progress pending formerly-valid audit-bearer revocation acceptance. +Service/domain-transaction/human and factory runtime/spend admission remain +separate; factory attempts and paid model calls remain zero. + +Receipt: [native readback](../docs/evidence/2026-09-11-factory-native-readback.json). + + +### T06 native reader acceptance — 2026-09-14 + +The scoped Warden login lane `secrets-engine-approval-client-login` now routes +to the applied OIDC reader and the platform's silent preflight. The installed +Warden package still carries an older catalog; use the explicit source catalog +`WARDEN_ROUTING_CATALOG=/home/worsch/ops-warden/registry/routing/catalog.yaml` +until its next normal installation refresh. This lane authenticates the reader; +it is not a raw secret fetch or retained-file delivery interface. + +Live effective-policy and capability checks passed: only exact data/metadata +read, no sibling secret, parent listing, write or control-plane authority. +A second contained session read existing version 1 into an operator-owned 0600 +file in a private 0700 runtime tmpfs directory. The native consumer exchanged +separate read and consume scopes; Approval Engine verified the read token before +returning 404 for a fresh nonexistent approval, and refused the consume-only +token's read request with 403. No approval was created, bound or consumed. +Both Warden sessions exited 0 after self-revocation/helper cleanup; temporary +credential file and directory were removed. Four refusal/path/redirect tests +pass. Receipts are in platform `docs/evidence/2026-09-14-ccr0019-{reader-preflight,delivery-check}.json`. + +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. + +### 2026-09-27 T02/T07 source follow-up + +T02 now has the exact proposed RS256 configuration, bounded JWT role and +self-only policy in `openbao/`. Operator correction: platform infrastructure +belongs to `tenant:platform`; KeyCape registration and consumer preflight are +corrected together. Existing live registrations must be migrated and verified. +Public discovery confirms issuer/JWKS/token endpoint. Registration/custody, +attended provisioning and live rejection/cleanup evidence remain required; +T02 stays wait. No service credential or backend entitlement was issued. + +T07 consumed the confirmed legacy consumer return. The stale value-comparison +ask is removed. WARDEN-WP-0037-T03's no-rotation hold stays in force until the +governed native migration is evidenced. Legacy destruction follows migration; +neither source reconciliation nor the historical pilot is that evidence. + +## Loose-end review — 2026-09-27 + +T08 now explicitly waits for formerly-valid audit-bearer revocation acceptance from AUDIT-WP-0009-T09/T11. Native delivery, producer checks and independent readback already passed; do not reopen login, seed or review gates. T02/T03/T06/T07 retain their latest exact service registration, signed-in human acceptance, owner delivery/disposition and governed-consumer migration dependencies. No credential value was read or changed. + +## Founder approval of the CCR-2026-0033 custody child + +```task +id: RPF-WP-0035-T09 +status: done +needs_human: false +priority: high +decision_id: 2ab717e1-7881-491e-aed4-28946550c289 +depends_on: [] +state_hub_task_id: "7c753be6-42f1-58a6-a4a4-a7ed686f461f" +``` + +Packets: `credential-change-requests/CCR-2026-0033.yaml` (custody child, KV +metadata, issuer ESO reader, live_order, rollback) and `CCR-2026-0034.yaml` +(attended operator OIDC reader, in-memory, 5m/4 uses). Revised 2026-10-06 per +founder direction; the consumer file is removed. Exact founder commands: +`docs/provisioning-windows/2026-10-04-1000/keycape/founder-runbook.md`. Live +order: custody child → platform applies policies/roles/ESO (Secret +sso/keycape-secrets-engine-openbao-client exists) → NetKingdom env patch +(NK-WP-0046) → KeyCape registration merge (KEY-WP-0037-T03) → KeyCape restart +immediately → live issuance check (KEY-WP-0037-T04) → OpenBao JWT role/login +proof (RPF-WP-0035-T02). Each live step after the custody run needs its own go. + + +2026-10-11 evidence reconciliation: T09's approval obligation is complete. +Authoritative founder decision 2ab717e1-7881-491e-aed4-28946550c289 is resolved, +decided by Bernd Worsch at2026-10-06T13:07:18.627943Z, and explicitly covers +A1 design, A2 CCR33/CCR34 plus owner reviews/bound claims, and A3 one custody run. +The approval comments in both CCRs record those exact grants; both source records +are applied. MASON-WP-0009-T02/T03 additionally record the October8 approval/owner-delivery +reconciliation and reference KeyCape +`docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`. Closing this approval task clears +its obsolete human gate. It grants no new run, credential access, rotation or +service execution: RPF35T02/T12, MASON9T05 and SECRETS8T06 retain their actual +native/adoption obligations. Historical per-step exclusions remain above. + +## Retire the approval-engine-operator client delivery and custody (CCR-2026-0018) + +```task +id: RPF-WP-0035-T10 +status: wait +priority: medium +blocked_on: message-from:approval-engine +blocking_reason: "Blue lane under the standing change rule (removing access, with reviewed order, rollback and receipts): executes once approval-engine confirms there is no presenter. No founder window needed." +state_hub_task_id: "af2d4dba-f83a-5819-9a8b-671bae799364" +``` + +2026-10-11: access removal is blue lane (canon build-mode-change-authorization_v0.1); no founder window. + +key-cape proposed a joint disablement on 2026-10-10 (message `7f2128fb`). +Precondition: approval-engine reconfirms there is no presenter. The order is the +reverse of provisioning, so KeyCape never starts with a client whose secret is +missing. key-cape removes the registration and restarts (1), checks that +`invalid_client` is returned (2), and net-kingdom removes +`KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET` from Deployment `sso/keycape` +(3). Platform steps, amended from the proposal: + +4. **Delivery.** In one commit, remove ExternalSecret + `sso/keycape-approval-engine-operator-client` from + `argocd/platform-addons/openbao-secretstore/keycape-approval-clients.externalsecrets.yaml` + and ClusterSecretStore `openbao-keycape-approval-engine-operator` from + `openbao-keycape-approval-clients.clustersecretstore.yaml`. Keep the + secrets-engine-approval objects. Then bump `targetRevision` of + `argocd/railiance01/applications/openbao-secretstore.application.yaml`. + The app is pinned and has no automated sync, so nothing changes live until + an attended `argocd app sync openbao-secretstore --prune` runs after step 3. + Verify, value-free, that the ExternalSecret, the store and Secret + `sso/keycape-approval-engine-operator-client` are gone. The target is + `creationPolicy: Owner` and `deletionPolicy: Retain`, so the Secret should + follow its owner; delete it explicitly if it does not. Then delete OpenBao + role `auth/kubernetes/role/external-secrets-keycape-approval-engine-operator` + and policy `workload-kv-read-keycape-approval-engine-operator`, and remove + their source files. Also remove policy + `workload-kv-read-approval-engine-operator-client` (CCR-2026-0020, cancelled) + if it exists live. +5. **Custody.** Run the metadata delete of + `platform/workloads/approval-engine/operator-client`, the destruction + foreseen in `docs/credential-lane-designs/keycape-approval-clients.md`. A + disabled client's secret has no recovery value; a narrowed successor gets a + fresh secret through the mint-secret lane at `platform/workloads/keycape/`. + Only after step 2's `invalid_client` receipt. Keep the agent boundary denies + for that path until the delete is verified, then drop them. + +2026-10-10: key-cape agreed the amended steps 4 and 5 (message `59304e33`, +KEY-WP-0013 c528daa). Waits on approval-engine confirming there is no presenter, +and on the founder's window. + +The manifest edits wait for the scheduled window, so a stray `targetRevision` +bump cannot remove KeyCape's secret before step 3. + + +## Complete independent service-JWT source preparation and execution design + +```task +id: RPF-WP-0035-T11 +status: done +priority: high +state_hub_task_id: "7952c8cd-c066-5b72-a025-78d24341c1ab" +``` + +2026-10-11: Platform-scoped agent loaded this checkout's AGENTS.md and INTENT, +RPF35-T02, actual CCR38/login contract/typed applier and Secrets Engine's native +claim/PDP/CAS/provider/apply flow. Frozen Secrets v2 manifest and all named staged +bytes/proof were hash-verified. Independent tests reproduced three source +counterexamples while retaining the frozen files: close exception can coexist +with native_verified=true; successful result needs no source/session fingerprints; +HTTP200 mixed errors+data envelope is accepted. Original 37 tests plus the three +counterexample tests pass (40 cases, synthetic/local only). Proposed owner design +`docs/credential-lane-designs/secrets-engine-task-execution-entitlement.md` binds +an explicit metadata-only execute-ccr action, immutable typed owner bodies, +CAS/journal replay control, 120s/12-use owner-held task token, independent payload +validation, native ACL endpoint bounds, revoke/readback and recovery. This completed +preparation record is established before the formal source review. It grants no +live authority and does not close T02 or represent acceptance by another owner. +Formal review artifact follows under this work item; all implementation/live +obligations are retained in T12 and existing T02 rather than a finished residual. + +## Implement and prove the separately approved task execution entitlement + +```task +id: RPF-WP-0035-T12 +status: progress +priority: high +depends_on: [RPF-WP-0035-T11] +state_hub_task_id: "914bf383-c13f-5247-9af0-91d7e3a4784a" +``` + +Review the proposed task-execution-grant schema and exact metadata-only execute-ccr +backend with Secrets Engine/access-engine/approval-engine; implement trusted service +subject and served consume verification, durable one-shot reservation, bounded +owner-held token issuer/middleware and exact source/payload enforcement. Obtain +separate exact founder approval/attendance before provisioning or live actions. +Prove disposable intended result and identity/action/target/body/time/replay/crash/ +cleanup negatives, and return owner-native acceptance. Existing service login policy +and defaults stay unchanged. T02 still owns login/claim/TTL/use/MASON acceptance; +Secrets T06 separately owns dispatcher adoption and steady-state default migration. + + +2026-10-16 T12 wave 5 source preparation: disposable adapter now binds owner +canonical before/after metadata snapshots to existing descriptor hashes, rejects +per-target baseline/readback mismatch, and records readback/verified evidence. +Mediator reports cleanup-confirmed only after independent fixed cleanup receipts. +Complete role metadata and policy name/HCL/version/cas are compared; validated +modification timestamp alone is excluded. This is sequential fixture acceptance, +not aggregate CAS, concurrent-writer exclusion or native production completion. +Role conflict may follow a policy write. Restart refuses dispatch and cannot +recover memory-only token/accessor cleanup handles. T12 remains progress; actual +fresh CCR/catalog/grant, source/trust/caller/policy admission, isolated owner custody, +scoped recovery and attended native acceptance remain explicit prerequisites. + + +2026-10-11 T11 refinement (same source-review trial): the exact Secrets Engine +v3 manifest `6bb05bac74e4939c3e42db2ae95c5f9fb4616bb20cc285811a315c26669ebce1` +and all named bytes/proof were verified and independently re-reviewed. The three +v2 counterexamples are corrected: close exceptions cannot pass through stale true +flags, complete typed source/session/attempted/revoke evidence is required, and +mixed HTTP200 errors/data fails closed. 49 maker/current-provider tests plus three +independent regressions passed (52, synthetic/local only). Platform source review +`docs/reviews/2026-10-11-secrets-service-jwt-v3-platform-review.json` approves only +the corrected boundary verifier and truthful packet. Prior changes-requested v2 +review is retained; this is not a second native success or changed authority. +No native or founder go is granted. T02, T12 and Secrets T06 remain open; the +metadata-only execute-ccr pilot is explicitly insufficient for generic lifecycle +adoption. All consume-verification/journal/action/body/backend implementation and +native acceptance gates remain real prerequisites, not architecture promises. + + +2026-10-11 T11 readiness refinement: independently reviewed frozen consumer +manifest `709b9dddd1c8f00a995b1ff14264323fbe080ed95df244270ce9607528878fa7`. +Platform source review `docs/reviews/2026-10-11-secrets-execution-readiness-v2-platform-review.json` +approves the local fail-closed guard and proposed consumer contract direction only. +All ten current protected backend handlers pass provider args through readiness +before authorization/consume; session revoke checks before handle reads. Configured +auto/explicit service-jwt therefore cannot burn a protected-action approval or +open the insufficient login-self backend. Explicit env/bootstrap and self-only +probes retain their existing contracts; local compromise/reactivate and disabled +destroy remain separate. Existing ambient-token route readiness reads are unchanged, +not claimed governed by this guard. 58 isolated tests passed: original36 plus20 +provider/action cases, handler enumeration and actual session-revoke ordering. +Prior v2 changes-requested and v3 boundary source reviews remain unchanged, same +T11 trial. No runtime grant, native acceptance, new Access/Approval semantics, +backend entitlement or full Lifecycle adoption is approved. T02/T12/SecretsT06 and +WP13 implementation/native gates remain open; the metadata pilot substitutes for +none of the ordinary generic lifecycle outcomes. + + +## Complete independent KEY39 v4 lifecycle source review preparation + +```task +id: RPF-WP-0035-T13 +status: done +priority: high +state_hub_task_id: "8f6966fa-6e9a-58b2-8b40-c47340ec19d1" +``` + +2026-10-11: Platform agent loaded its owner instructions/INTENT and RPF35-T02, +actual applied CCR38, exact native role/policy source and frozen KEY39 lifecycle +v4 manifest `d079f85c47d5c2635e1ee633ea4d1346b1737ce2be9ca273f22a38e620f418d8`. +All staged entry hashes were verified without changing the reviewed inputs. +Source role omits expiration_leeway: its observed actual default must be confirmed +natively, with -1→0 and 0→150 normalization preserved as a bounded model. Source +claims and login-only policy are unchanged. The supplied 41 lifecycle tests pass; +five independent cases also pass, including a new exceptional-response-close +elapsed-bound counterexample and four current-leeway normalization checks. +A 10ms HTTP request can take over70ms because exceptional finally response.close +runs outside the hard elapsed timer. Unknown native login is correctly recorded, +but source total elapsed enforcement is incomplete. This completed owner +preparation record exists before the formal exact source review entry. No +credential was requested/read, native action run, owner checkout edited or native +session grant inherited. T02 retains native role/policy/leeway, negative claims, +cleanup acceptance and MASON gates; KEY39 producer handoff and founder attendance +remain prerequisites. Source correction/re-review is required, not a native success. + + +2026-10-11 T13 correction preparation (same trial): exact KEY39 v5 manifest +`d1f997624db46693a7126a6eb6435f6b3a353d5bd67dcc8a539683e4b7147285` +and all entry hashes verified. The v4 exceptional-close finding is addressed: +one 20ms abort is clipped to original remaining time and the nonresettable +aggregate cleanup budget; zero calls after aggregate expiry; failed abort stays +unconfirmed/unknown with signal state restored. 46 supplied lifecycle checks and +five independent regressions pass; the unchanged runner's earlier17 tests remain +valid against identical source SHA. Existing T13 preparation record is retained +before the formal v5 exact source review. V4 changes-requested review and earlier +failed history remain retained, with no native success, inherited grant or scope +promotion. Actual private producer admission, fresh installed role/leeway/policy +observation, authenticated founder window and native refusal/cleanup remain gates. + + +2026-10-11 T11 journal preparation refinement (source-only): independently +inspected frozen root-maker v2 manifest +`341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7`, +verified all input hashes, and ran14 supplied tests plus5 independent checks. +The actual four-process race admits once; a separately forked process exiting +immediately after pending intent leaves durable unknown/nonresumable state. +Private SQLite modes, lock admission and binding/replay protections remain guarded. +Three independent counterexamples show after_call accepts False,0.0 or text'0' +as persisted integer ordinal0, contrary to before_call's exact integer validation. +Completed preparation under this existing done ownerT11 record precedes formal +review; require identical ordinal/call-digest validation before confirmation so +malformed calls cannot clear pending outcome. RPF35-T12 retains caller/PDP/consume +validation, exact body compiler/adapter and owner-private cleanup/recovery after +unknown; this unintegrated primitive proves none of those or full contract/native +acceptance. Inputs/prior reviews are preserved; no privileged/native action occurred. + + +2026-10-11 T11 journal v3 correction preparation (same trial): frozen manifest +`905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d` +verified against every file. Strict after_call integer0..63 and64hex string digest +validation now precedes SQLite confirmation; False,0.0 or text'0' cannot clear +pending external outcome.15 supplied tests plus5 independent regressions pass, +including realfork abrupt exit after durable intent and privatefile checks. +This existing completed ownerT11 refinement precedes the formal corrected-source +review. Prior v2 refusal is retained; no extra success/authority trial is counted. +Acceptance is only unintegrated journal source. Actual caller/PDP/consume validation, +independently compiled body/ordinal plan, restricted adapter, owner-private unknown +cleanup recovery and native/whole-contract adoption remain live RPF35-T12 gates. + + +2026-10-11 T13 node-route source preparation refinement (same trial): exact +successor manifest `23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035` +verified against all entries. Platform Service openbao-ui-gateway8080 and its +nginx /v1 proxy agree with the proposed bounded founder-held node port-forward; +workstation tunnel/DNS assumptions are not reused as node evidence.54 supplied +lifecycle/route checks plus6 independent public-health/abort checks pass, offline. +Initial execute/recovery health pin and repeated pre-create check fail before +native/Secret effects; public-preflight reads neither stdin nor Kubernetes. +Completed ownT13 preparation precedes this fresh exact source review, not reuse +of v5 acknowledgment. Main execute currently reads private stdin before execute's +health gate; the packet's pre-token-input phrase is not accepted. Private producer +handoff must preserve actual ordering or move the health gate before credential +input when implemented. Public cluster digest detects drift, not authenticated +estate identity. No route was opened or observed; no source packet authenticates +a founder approval. Native role/plugin version and raw/effective expiration, +clock-skew and not-before leeways require actual owner observation/semantic proof. +Issuer readiness_state/Argo ownership is not established by the inspected source; +unmapped means production-tier. If adopted/production-approved, temporary direct +CAS requires an explicit reviewed one-use maintenance exception and close-down +entry, plus reconciliation, before native go. No helper/source acknowledgment +waives that gate. Private token producer/callback/client/custody admission and +actual native negative/revoke/restoration/cleanup remain prerequisites. + + +2026-10-11 T13 v7 node-route preparation refinement (same trial): exact frozen +manifest `90aabec336008d7d51e37c04b5ff96ba8ed6630821cca1a4c333d803367247f7` +and all entries verified.58 supplied lifecycle/route checks plus9 independent +checks pass offline. Actual main now verifies source/public health before private +stdin; execute preserves the original wall/monotonic window rather than renewing +it. Actual child-process partial-pipe counterexample shows unbounded stdin.read +remains blocked beyond a synthetic20ms original window (still alive after100ms +without EOF). No credential/native/provider access is involved. Before private +producer admission, require byte-capped, deadline-bounded JSON input and EOF within +the original window, with fail-closed fixed receipt and no protected effects. +This completed ownT13 preparation precedes formal v7 source changes-requested +review. Retain v6 qualified health-gate agreement and all prior reviews; neither +v7 health ordering nor any source acknowledgment establishes custody completion, +actual route/plugin/leeway/readiness/Argo identity or founder/runtime authority. +Native and private-producer gates remain open; no owner checkout write occurred. + + +2026-10-11 T13 v8 bounded-input correction preparation (same trial): exact +frozen manifest `316fd6005cc4cb7fe14ea69a5fd408aed13e6122afef60afd13d97952b27cf4a` +and all entry hashes verified.65 supplied tests plus12 fresh independent checks +pass offline, including a standard buffered stdin pipe with complete JSON/noEOF +interrupted within original20ms window and restored SIGALRM state; exact64KiB +JSON/EOF accepted and extra byte refused, UTF8 token bytecap enforced, original +wall deadline clips longer monotonic budget. Original preinput window is retained. +Completed ownT13 preparation precedes fresh exact source review; v7 refusal and +v6 qualified agreement/prior reviews retained. This accepts child bounded-input +source only. No parent-ready handshake exists: producer must not eagerly pipe +private inputs, and producer/session/window readiness protocol remains an +unimplemented admission gate. No custody/native completion, sourcepacket approval +authentication, route/plugin/leeway/readiness/Argo observation or inherited grant. +Native prerequisites and producer handoff remain open; no owner checkout changed. + + +2026-10-11 T11 journal v4 canonical-format preparation refinement (same trial): +exact frozen manifest `22c6d225d393b994ab7b44a43904ced1b6d7f74e0e2bebf71ffe99f87191ef4c` +and entry hashes verified. Actual access-engine pkg/api/canonical.go RequestDigest/ +CanonicalDigest, Approval binding.py and Secrets authorization/approval_consume +all use sha256:<64 lowercase hex> request digests. V4 now preserves this exact +request value without prefix stripping; plan/call/evidence content hashes remain +explicit bare64hex.15 supplied checks plus15 fresh independent checks pass, +including malformed prefix/bare/uppercase/trailing whitespace refusal before +reservation, exact persistent value/reopen/mismatch replay, private-file mode, +real child crash after pending intent, ill-typed confirmations and pending-unknown +refusal. Completed ownT11 preparation precedes formal v4 source review; prior v2 +refusal/v3 approval and T13 v7 refusal/v8 source acknowledgment retained. +Acceptance is unintegrated primitive source only; no data migration/native use +of v3 journal has occurred. RPF35-T12 caller/PDP/consume validation, independent +owner plan compiler/restricted adapter, private runtime custody, bounded execution +and owner-private unknown cleanup recovery remain open. No checkout/native writes. + + +2026-10-11 T13 paired ready-child/launcher preparation refinement (same trial): +exact NetV9 manifest `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +and KeyproducerV2 `55a8e794af983ca2202e7a0054d0415a120d2c95018fb03fdb5f28313a109d58` +verified against all entries.74 Net checks plus31 Key checks and10 independent +checks pass offline including a truthful-unknown counterexample: adapter uncertain +private delivery with confirmed=false is copied into launcher receipt, but +consumer_outcome_unknown incorrectly remains false after local SSH teardown. +Complete bytes may have reached remote child before adapter timeout/EOF; local +terminate does not establish remote no-effects. Require sticky propagation of +uncertain delivery into consumer outcome before early return, retain unknown +unless independently established native outcome/recovery. Bad markers/source +pins/injection reject before private reads; extra marker authority/lines reject; +prohibited child output never forwards. Child-ready synchronization is not +authentication/approval. Proposed founder directSSH profile is incompatible with +warden quiet-output lane and not admitted here. Completed ownT13 preparation +precedes formal paired source review; preserve v7 refusal/v8 acknowledgment and +journal histories. No transport grant, coding-agent/private custody admission, +live SSH, credential/native action or owner checkout write. All native role/plugin/ +leeway/route/issuer readiness/Argo/maintenanceexception gates remain prerequisites. + + +2026-10-11 T13 paired producerV4 correction preparation (same trial): exact +producer manifest `d6f641dc1e4aae7d36658d4199d89af14d2fd7a4bd4e526856eb340234f2d33e` +and unchanged NetV9 `84542ddcff00932fc7ce22dcb2626be8942a3c006c5098a62fdd6b2478d0cd14` +entry hashes verified.74 Net tests,40 producer checks,9 actual local fakeSSH/ +realwrapper/child synthetic roundtrip regressions and12 fresh Platform checks +pass (135 total). V2 deliveryunknown now remains sticky consumerunknown with +completion=false after earlyreturn/localteardown. V3 Net FIFO acquisition finding +and originalbudgetreset are corrected: actualCLI starts original5s timer before +regular/nofollow/bytebounded contract acquisition, each later preparation phase +clips remaining time. ActualCLI FIFO refuses promptly; expired original budget +never validates/spawns/reads private files. Completed ownT13 preparation precedes +formal corrected pair source agreement. Preserve V2 Platform refusal, Key old +exactV2 acknowledgment and NetV3 refusal; no old acknowledgment repinned. +Agreement is only reviewed source synchronization/launcher behavior, not admission. +Founder authenticated SSH host/profile/channel/runtime pins, exclusive sameUID +file custody and explicit tmpfs file allowance/cleanup, verified human and +coding-agent producer/client/source, native role/plugin/leeway/route/issuer +readiness/Argo/maintenanceexception, refusal/revoke/restoration/readback and +unknown owner recovery remain prerequisites. Warden quietlane cannot carry ready +controlstdout; no transport/custody/native grant. No owner checkout/liveSSH/native. + + +2026-10-11 RPF35-T12 source implementation progress: durable journal source v4 +was independently accepted/committed; owner-derived typed plan compiler component +v2 is prepared at immutable manifest +`41cda74ab32384c789ea8a760475671aadad4e5121335c8f60567ff53d66665b` +with40 offline tests. Completed own bounded source-preparation ADHOCT02 anchor +was persisted at7adbcb4 before the qualified Platform contract/readiness receipt. +T12 progresses for actual source implementation underway, not native acceptance +or full descriptor/authority readiness. The compiler derives local CCR/HCL/role +bodies, matches actual independently pinned Secrets catalogue and revalidates +source/body before fixed calls; no body/target chosen by service is dispatched. +Independent technical integration review and exact full ExecutionContract/owner +grant/baseline/estate/deadline matching, initiating human/User/Tenant PIP/transport +representation/service identity, served PDP/claim/consume correspondence, journal +call dispatch/restricted adapter, native token TTL/uses/custody/revoke/cleanup and +owner-private unknown recovery remain unimplemented integration/native gates. +Actual CCR42 has no eligible approved pilot/catalogue; no source metadata is +invented. T02 and original negative/capability/native evidence remain unchanged; +T11/T13 history retained, no defaultflip/nativego or SecretsT06 closure follows. + + +2026-10-13 T12 source correction: the compiler hashed the catalogue sources but +used cached Python modules with matching paths, which did not establish executing +those exact bytes. A failing regression reproduced the substitution. Catalogue, +package and dependencies now execute from the verified snapshot in temporary +private modules; ambient modules remain untouched and cleanup runs on refusal. +45 compiler plus 15 journal tests pass. The v2 source review remains historical; +this change needs its own integration review. T12 retains all existing full +contract, identity/consume, dispatch, custody and native acceptance requirements. +RPF-IN-0012 remains open for the independent contract/wrapped-delivery return; +this code correction does not authorize either operation. + +2026-10-16 T12 source preparation (isolated owner checkout; not owner delivery): +added durable precommitted cleanup obligations and separate outcome evidence to +the existing Journal, plus a fixed three-method owner cleanup driver. Same live +postconsume admission can clean after a business timeout/failed/unknown outcome; +cleanup closes business dispatch and cannot replay or restore admission after a +crash. Empty obligations no longer produce cleanup-confirmed. Real SQLite +multiprocess races and abrupt process death before/after a separately durable +synthetic effect verify refusal on reopen. Current compiler/journal/cleanup suite: +73 passed, local source/fixture only. Details: docs/task-execution-cleanup.md. +No native adapter or production mediator exists; full grant/request/cleanup binding, +authenticated consume/identity, ephemeral token issuance, deadline/use checks, +native effect/revoke/absence, audit and protected recovery remain prerequisites. +T12 remains progress. No CCR38 default/entitlement or live grant was changed. + +2026-10-16 T12 second source package: Compiler Plans now bind deterministic cleanup +commitments and can bind the complete independently installed engine execution +descriptor. A fixed disposable-loopback native adapter actually materializes exact +per-operation metadata ACL/task token, executes six source-derived metadata calls, +and verifies self-revocation/accessor invalidation and policy retirement. Each +cleanup request has its own durable intent. Native fault tests cover lost response +after real write and policy deletion while task revoke fails. All initiating +identity/approval/consume/grant/state/source admission in this fixture is synthetic; +no production authority or complete native owner acceptance is claimed. Exact +remaining owner schema/admission and mediator work: docs/task-execution-native-fixture.md. +T12 stays progress; no live grant, credential/default change or owner sync performed. + +2026-10-16 T12 third source package: implemented proposed task-execution-grant +immutable projection and exact compiler/native-fixture integration through the +existing descriptor grant ID/SHA fields. Only typed review.comments/evidence.events +are excluded; separate append-only checks reject removal/rewrite/reordering and +unknown guessed evidence exclusions refuse. Owner-pinned grant bytes and validator +source must match independently reconstructed descriptor/source/cleanup/ACL/token +bodies before a native fixture can materialize. Proposed source records gain no +execution authority; no real grant, policy or legacy applier registration added. +Details and remaining production gates: docs/task-execution-grant-projection.md. +T12 remains progress; no owner sync or production effect performed by this package. + +2026-10-16 T12 fourth source package: connected the Secrets-owned strict task +handoff to actual Approval ExecutionConfirmationClient independent GET before +consume-confirmed/native fixture work. Platform accepts no supplied authorization +boolean/object/callback and preserves its exact owner descriptor/grant/Plan join. +Durable CAS/GET intents precede native ordinals through the repaired journal +prefix API. Actual source-server fixture uses signed Access/enforced synthetic +TokenReview, real Approval WSGI/SQLite with distinct synthetic human/service +identities, actual strict Secrets signature/CAS validation and disposable native +OpenBao. Untouched actual task policy remains signed DENY; separately named +synthetic fixture policy is never production admission. Read-scope denial after +CAS records consumed/unknown with zero native effects. Exact dependency/source +hashes, tests and remaining gates are retained with the source package and in +docs/task-execution-mediator-seam.md. No real grant/custody, policy default, owner +sync or native production acceptance is performed; T12 stays progress. + +2026-10-16 T12 recovery successor source preparation: optional independently +installed fixture custody durably retains operation-bound private accessors and +issuance checkpoints. Fresh cleanup-only owner permits can reconcile after actual +executor process death using fixed revoke/readback and policy delete/readback, +without restoring business/consume admission. Separate durable attempt evidence +retains original unknown outcomes. Lost token-create response remains unresolved +when no accessor was committed. Source-only process-loss fixtures are not native +production custody or recovery-role admission; T12 remains progress. + +2026-10-16 T12 recovery R2 source refinement retains R1's overbroad 404 failure: +policy cleanup now requires exact native empty-errors absence before/after delete; +HCL uses only documented single optional terminal LF normalization. Private +capsules are owner-key HMAC authenticated, strict nested schemas/ordered cleanup +commitments reject damage, and journal history prevents stale prepared capsules +from hiding issuance. Fixture process-loss source proof remains separate from +unadmitted production custody, integrity-key storage and recovery-role scope. + +2026-10-16 T12 independently reviewable budget/source slice: bound native HTTP +header/body/close, compiler work and cleanup through fixed owner main-thread +absolute budgets, with actual task expiry narrowing global authority. Actual v2 +mediator now verifies each independently installed source_bundle byte hash before +authorization/effects. No deadline/TTL extension, remint or generic service added. +Retained registry actual-provider proof still refuses Approval correspondence +before CAS/native; normalized pre-approval + precise immediate CAS whole-stack +positive remains live owner follow-up under CUST-WP-0080. T12 stays progress. + +2026-10-16 T12 actual v2 successor source proof: retained registry signed DENY +normalization from the real Secrets prepare_task_approval builder precedes actual +Approval issue/human approval. Actual Access v2 then signs ALLOW; strict Secrets +CAS and independent confirmation GET precede six disposable native calls, exact +readback and confirmed token/policy cleanup. Approval precision source permits +immediate CAS without sleeps/backdating. The 60-second immutable deadline, +30-second backend TTL, 120-second synthetic observation and existing cleanup +reserve remain bound; issued credential expiry narrows business time. Source, +caller, revoke, source-reader, registry drift and expiry refusals cause no native +effects; revoke between ALLOW/CAS retains unknown without business dispatch. +This owner fixture uses separately installed synthetic identity/key/trust and +loopback OpenBao, grants no production authority and keeps T12 progress. Prior +failed temporal/normalization proofs remain retained. + +2026-10-16 T12 signer custody R2 source preparation rebases the proposal to +integrated Access919ce25 and preserves current workplan state. Added protected +in-memory Ed25519 CAS/readback primitive with durable closed metadata receipts +and fixed disposable-only owner adapter. Actual synthetic OpenBao bootstrap, +rotation, conflict/unknown/readback/receipt/private-output and admission failures +are tested. Production direct entry refuses: exact CCR/founder scope, protected +executor/fencing/receipt custody, independent consumer public admission, migration +debt and native deployment prerequisites remain open. No live key/grant or CCR +admission; RPF-WP-0035-T12 remains progress. diff --git a/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/r2-to-r3.patch b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/r2-to-r3.patch new file mode 100644 index 00000000..d7a9d50d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/platform-signer-custody/writer-r3/r2-to-r3.patch @@ -0,0 +1,73 @@ +--- a/docs/credential-lane-designs/flex-auth-envelope-signing.md ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.md +@@ -1,6 +1,6 @@ + # Retained lifecycle PDP signer custody proposal + +-Proposal ID: RPF35-PDP-SIGNER-CUSTODY-20261016-R2. Preparation under ++Proposal ID: RPF35-PDP-SIGNER-CUSTODY-20261016-R3. Preparation under + RPF-WP-0035-T12, beneficiary FLEX-WP-0024-T06, coordinated by CUST-WP-0080. + Status: source proposal only; no key generated, credential read, CCR admission, + policy scope granted, package published or deployment changed. +@@ -159,3 +159,13 @@ + correspondence, rotation CAS1, stale CAS conflict, response-loss uncertainty, + read denial/mismatch, pre-effect durable-intent failure, receipt secrecy, retry + refusal and invalid admission/fencing rejection. No fixture key is promotable. ++ ++R3 metadata correction: every current proposal identifier is ++`RPF35-PDP-SIGNER-CUSTODY-20261016-R3`, including the Secret annotation. Frozen ++R1/R2 evidence remains historical. The writer public_fingerprint convention is ++`sha256:` plus lowercase SHA-256 hex of the canonical unpadded base64url public ++key ASCII string (43 bytes for a 32-byte Ed25519 key). It does not hash the raw ++decoded bytes. This names the existing writer convention without changing code ++or admitting any consumer. Public admission must explicitly agree this encoding ++with the independent consumer; a raw-byte fingerprint must use a separately ++named field/version and never be silently substituted. +--- a/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing.proposal.json +@@ -1,6 +1,6 @@ + { + "schema": "railiance-platform.signer-custody-proposal.v1", +- "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R2", ++ "proposal_id": "RPF35-PDP-SIGNER-CUSTODY-20261016-R3", + "status": "source-proposal-unadmitted", + "owner": "railiance-platform", + "work_item": "RPF-WP-0035-T12", +@@ -113,6 +113,7 @@ + "production_entry": "refused pending exact CCR/founder scope/protected runtime/fencing/receipt admission", + "independent_public_admission": "required after custody verification; receipt shape supplies no trust authority", + "retry": "none after durable intent; unknown requires independent reconciliation, no remint", +- "rollback": "forward recovery; no seed restore primitive" ++ "rollback": "forward recovery; no seed restore primitive", ++ "public_fingerprint_convention": "sha256: plus lowercase SHA-256 hex of canonical unpadded base64url public-key ASCII (43 bytes for Ed25519); not raw decoded key bytes" + } + } +--- a/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed ++++ b/docs/credential-lane-designs/flex-auth-envelope-signing-projection.yaml.proposed +@@ -42,7 +42,7 @@ + template: + metadata: + annotations: +- railiance.io/custody-proposal: RPF35-PDP-SIGNER-CUSTODY-20261016-R1 ++ railiance.io/custody-proposal: RPF35-PDP-SIGNER-CUSTODY-20261016-R3 + data: + - secretKey: seed + remoteRef: +--- a/workplans/RPF-WP-0035-credential-lane-implementation.md ++++ b/workplans/RPF-WP-0035-credential-lane-implementation.md +@@ -1331,7 +1331,7 @@ + loopback OpenBao, grants no production authority and keeps T12 progress. Prior + failed temporal/normalization proofs remain retained. + +-2026-10-16 T12 signer custody R2 source preparation rebases the proposal to ++2026-10-16 T12 signer custody R3 source preparation rebases the proposal to + integrated Access919ce25 and preserves current workplan state. Added protected + in-memory Ed25519 CAS/readback primitive with durable closed metadata receipts + and fixed disposable-only owner adapter. Actual synthetic OpenBao bootstrap, +@@ -1340,3 +1340,7 @@ + executor/fencing/receipt custody, independent consumer public admission, migration + debt and native deployment prerequisites remain open. No live key/grant or CCR + admission; RPF-WP-0035-T12 remains progress. ++ ++R3 source metadata correction aligns proposal IDs across JSON/docs/Secret ++annotation and documents existing base64url-ASCII public fingerprint hashing. ++Frozen R2 source/evidence is preserved; no writer behavior or admission changes. diff --git a/docs/changes/netkingdom-target-2026-10-16/progress-browser-source.json b/docs/changes/netkingdom-target-2026-10-16/progress-browser-source.json new file mode 100644 index 00000000..3f5fe81a --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/progress-browser-source.json @@ -0,0 +1,14 @@ +{ + "workplan_id": "dfadb19b-445e-59c6-bcd6-48e87b912c52", + "id": "d03a5c54-a410-405d-acb0-05f1f94a3db6", + "topic_id": null, + "task_id": "6aca534c-5c7a-556f-b6b6-406433670c29", + "decision_id": null, + "event_type": "note", + "summary": "CUST-WP-0080 implementation checkpoint 86a5b0dd published and normal sync89/89 passed: 0fail/automation_error,7warnings/4info; exact original staged brief/worktree preserved. Independently verified NetKingdom registration source0775c2bf and record0394484 against reviewed hashes, all16owner tasks projected; Warden d97652a canonical87checks pass, registration36checks pass. Recovery R3 independently52synthetic checks and14dependency hashes verified; retained R2 plaintext/daemon findings and R3 deadline cleanup race, successor in progress before canonical/native use. Real checker artifact local build preparation underway. All16TSA gates remain open; no new live credentials, deployment or native admission. Durable receipts under docs/changes/netkingdom-target-2026-10-16/.", + "detail": null, + "author": "codex", + "session_id": null, + "created_at": "2026-10-16T19:58:48.962667Z", + "workstream_id": "dfadb19b-445e-59c6-bcd6-48e87b912c52" +} diff --git a/docs/changes/netkingdom-target-2026-10-16/progress-preparation-successors.json b/docs/changes/netkingdom-target-2026-10-16/progress-preparation-successors.json new file mode 100644 index 00000000..d4953c16 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-16/progress-preparation-successors.json @@ -0,0 +1,14 @@ +{ + "workplan_id": "dfadb19b-445e-59c6-bcd6-48e87b912c52", + "id": "ce617715-77fe-4300-995c-2ade1e2e6ce2", + "topic_id": null, + "task_id": "6aca534c-5c7a-556f-b6b6-406433670c29", + "decision_id": null, + "event_type": "note", + "summary": "CUST-WP-0080-T06 source review checkpoint: exact Access rolloutR2 (manifest5be7a7f4) and Platform custodyP4 (manifest9eec8618) frozen and committed in Custodian3291a660ae5170d368bdc325b87d9bd5c551e7ff. Root reproduced both real Helm states and source projection; eight assembler tests pass, P4 executor/scope unchanged from independently testedP3. Source role, Helm maintenance and P4 join formally reviewed under cluster own RCLUSTER-WP-0017-T01; final source review+three canonical prefix examples committed2c98c637950164779d89a0b4eda194cbfd82b283, published/synced22/22, T01done only, nativeT02/T03todo. WFFC stop uses wait=false/no atomic; ready atomic requires actual stopped rollback revision. P1/P2/P3 and scanner failures retained. Root50de8be checkpoint published/synced89/89zero failures;3291 final sync running. No deployment, custody, trust, PVC or protected effect; actual founder/entity/expiry/CCR/fence/window/dispositions unresolved. All16 TSA gates open; full target goal remains active.", + "detail": null, + "author": "codex", + "session_id": null, + "created_at": "2026-10-16T18:40:21.384433Z", + "workstream_id": "dfadb19b-445e-59c6-bcd6-48e87b912c52" +}