NK-WP-0048-T16 r5: 1.3 step text states how each step runs; canon clarifies kernel-dispatched attended steps

Folds NK-1.3-C1/C2, RPF-1.3-C1/C2, RAPPS-1.3-C3, KC-1.3-C1 and the OW-1.3-C1 lane names.
Parameters untouched (fingerprint unchanged). The execution_descriptors map is
regenerated after the adapter changes land.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 903097@bnt-lap001
Assistant-Session: aa320c8f-c3fa-46e7-8541-0b58e1e45d23
This commit is contained in:
tegwick 2026-10-17 11:59:02 +02:00
parent 239a528d62
commit aba012eba2
2 changed files with 96 additions and 40 deletions

View file

@ -101,6 +101,19 @@ A type is a directory `security-case-types/<type-id>/` in net-kingdom containing
standing credential for the step; that would make it a broker (ops-warden
ADR-0002). *(Clarified 2026-10-09 from ops-warden's review,
WARDEN-WP-0044-T01 R1–R3.)*
A step listed in the type's `execution_descriptors` is admissible to
ops-warden's case kernel whatever its `warden_executes` value, and the kernel
enforces the step's mode. For an `attended` step, "kernel-dispatched" means
the reviewed adapter runs only inside the attended human session (descriptor
actor `human`, the step's own lane, parent-session revocation per attempt),
never under an agent or a standing credential. The human session is the
authority, and the kernel is only the dispatcher. For an owner-path step
(neither `warden_executes` nor `attended`), the lane must resolve to the
owner's own delegated path, and ops-warden holds no owner credential.
`warden_executes` keeps its caller-proxy meaning above for unattended steps.
*(Clarified 2026-10-17 from the 1.3 owner reviews, NK-1.3-C2 and ops-warden
KERNEL-3.)*
- `verification`: the checks that prove a case is live (positive and
negative), runnable without reading a secret value
- `rollback`: the exact inverse of each step

View file

@ -232,14 +232,15 @@ spec:
follow_through:
- id: ensure-groups
owner: net-kingdom
entry_point: identity-provisioner ensure_service_groups, run inside the provisioner
pod through the session's contained cluster access (groups {access_groups};
members exactly {initial_members} as recorded in the accepted case, nothing
else)
auth: operator cluster access in the attended register-client session; the in-pod
call uses the provisioner's own directory binding, and no provisioner or user-engine
token is read or sent
lane: key-cape-oidc-login
entry_point: reviewed adapter net-kingdom/keycape-ensure-groups, dispatched by Warden's
case kernel inside the attended session; it calls identity-provisioner
ensure_service_groups in the provisioner pod through the session's contained
cluster access (groups {access_groups}; members exactly {initial_members} as
recorded in the accepted case, nothing else)
auth: the attended human session on lane keycape-attended-case-change (actor human,
parent-session revoked per attempt); the in-pod call uses the provisioner's own
directory binding, and no provisioner or user-engine token is read or sent
lane: keycape-attended-case-change
warden_executes: false
attended: true
value_handling: none
@ -248,14 +249,17 @@ spec:
would act as user-engine (ops-warden review R8; canon section 3; ops-warden
ADR-0002). Running it in the session register-client already needs adds no attended
session. It can become unattended once the provisioner has an operator credential
of its own and an admitted path.
of its own and an admitted path. Warden's case kernel dispatches the reviewed adapter only inside the one attended human session (descriptor actor human, lane keycape-attended-case-change, parent-session revoked per attempt); the human session is the authority and the kernel is only the dispatcher.
- id: mint-secret
owner: railiance-platform
when: client_type == confidential
entry_point: 'railiance-platform credential broker: generate a client secret inside
custody at bao:platform/workloads/keycape/{client_id}'
auth: the caller's broker grant for the case's KV path, through its lane; the
value is generated in custody and never returned
custody at bao:platform/workloads/keycape/{client_id}, through reviewed adapter
railiance-platform/keycape-mint-secret'
auth: a human caller (net-kingdom-admins, aal2) starts it; Warden runs it unattended
through the broker lane under the caller's session, with the caller's broker grant
for the case's KV path; agents and root are refused, and the value is generated
in custody and never returned
lane: keycape-client-secret-generate
warden_executes: true
attended: false
@ -263,10 +267,14 @@ spec:
- id: deliver-secret
owner: railiance-platform
when: client_type == confidential
entry_point: ExternalSecret sso/keycape-{client_id}-client (key client-secret)
from bao:platform/workloads/keycape/{client_id}
auth: railiance-platform ESO delivery through role external-secrets-keycape-{client_id};
no value leaves custody
entry_point: reviewed adapter railiance-platform/keycape-deliver-secret, dispatched
by Warden's case kernel; Platform's deliver capability applies ExternalSecret
sso/keycape-{client_id}-client (key client-secret) through the ESO store for
role external-secrets-keycape-{client_id}, from bao:platform/workloads/keycape/{client_id}
auth: Platform's own delivery path on lane platform-secret-delivery, inside the human
aal2 session; ESO reads custody through role external-secrets-keycape-{client_id};
Warden holds no Platform credential, and no value leaves custody
lane: platform-secret-delivery
warden_executes: false
attended: false
value_handling: none
@ -275,23 +283,30 @@ spec:
- id: bind-env
owner: net-kingdom
when: client_type == confidential
entry_point: 'patch Deployment sso/keycape: env KEYCAPE_{client_id:env}_CLIENT_SECRET
from sso/keycape-{client_id}-client'
auth: operator kube credentials for namespace sso
lane: key-cape-oidc-login
entry_point: 'reviewed adapter net-kingdom/keycape-bind-env, dispatched by Warden''s
case kernel inside the attended session: patch Deployment sso/keycape env
KEYCAPE_{client_id:env}_CLIENT_SECRET from sso/keycape-{client_id}-client, by
reference only'
auth: the attended human session on lane keycape-attended-case-change, with operator
kube credentials for namespace sso (actor human, parent-session revoked per attempt)
lane: keycape-attended-case-change
warden_executes: false
attended: true
value_handling: none
attended_justification: A change to the live identity provider's Deployment. It
runs in the same attended operator session as register-client, before it, because
KeyCape resolves a confidential client's secret at start and fails closed if
the binding is missing.
the binding is missing. Warden's case kernel dispatches the reviewed adapter only inside the one attended human session (descriptor actor human, lane keycape-attended-case-change, parent-session revoked per attempt); the human session is the authority and the kernel is only the dispatcher.
- id: register-client
owner: net-kingdom
entry_point: sso-mfa/k8s/keycape/keycape-client.py apply --client-file <client-from-case>
--case-acceptance <record> --check-config <keycape binary> (net-kingdom.keycape-client-registration)
auth: operator write access to the live KeyCape client registry in namespace sso
lane: key-cape-oidc-login
entry_point: reviewed adapter net-kingdom/keycape-register-client, dispatched by Warden's
case kernel inside the attended session; it runs sso-mfa/k8s/keycape/keycape-client.py
apply --client-file <client-from-case> --case-acceptance <record> --check-config
<keycape binary> (net-kingdom.keycape-client-registration)
auth: the attended human session on lane keycape-attended-case-change, with operator
write access to the live KeyCape client registry in namespace sso (actor human,
parent-session revoked per attempt)
lane: keycape-attended-case-change
warden_executes: false
attended: true
value_handling: none
@ -303,37 +318,63 @@ spec:
authorization and handoff state in memory, so the restart drops in-flight logins
and sessions for every client; runs go in a quiet window (key-cape type review
R4). The rendered registry must pass KeyCape''s own startup checks (keycape
check-config, key-cape c528daa, which keycape-client.py runs before it patches)
check-config, the pinned checker artifact sha256:be37738fe1c08259fb4f9ca0daf0f9301bfffc237e5bb38435525dfbf11ccff5
built from key-cape 3c71226, which keycape-client.py runs before it patches)
before the restart: a refused entry stops the single replica and every client
loses sign-in (R1).'
loses sign-in (R1). Warden''s case kernel dispatches the reviewed adapter only inside the one attended human session (descriptor actor human, lane keycape-attended-case-change, parent-session revoked per attempt); the human session is the authority and the kernel is only the dispatcher.'
- id: deliver-consumer-secret
owner: '{consumer_owner_repo}'
when: client_type == confidential
entry_point: Owner applies dedicated ServiceAccount {consumer_namespace}/{consuming_service}-keycape-{client_id}-eso
entry_point: Reviewed adapter net-kingdom/keycape-deliver-consumer-secret, dispatched
by Warden's case kernel inside the attended consumer-owner session; the owner's
apply capability creates dedicated ServiceAccount {consumer_namespace}/{consuming_service}-keycape-{client_id}-eso
(automount=false, no legacy tokens), namespace SecretStore openbao-keycape-{client_id}-consumer
with serviceAccountRef and audiences [openbao], and ExternalSecret {consuming_service}-netkingdom-oidc-client
with Owner target, Retain remote deletion and only CLIENT_SECRET from workloads/keycape/{client_id}.
Admission validates actual installed ESO TokenRequest support and common controller
RBAC before any owner-approved apply.
auth: Consumer owner contained Kubernetes deployment authority; ESO authenticates
to OpenBao role external-secrets-keycape-{client_id}-{consuming_service} with
a TokenRequest for the dedicated namespaced serviceAccountRef; controller remains
trusted
auth: the attended consumer-owner session on lane consumer-owner-deployment (actor
human, the consumer owner's operator deployment authority, on the founder's go
for the change); ESO authenticates to OpenBao role external-secrets-keycape-{client_id}-{consuming_service}
with a TokenRequest for the dedicated namespaced serviceAccountRef; controller
remains trusted
lane: consumer-owner-deployment
warden_executes: false
attended: false
attended: true
value_handling: none
attended_justification: The consumer owner's only deployment authority in the consumer
namespace is its operator credential, and production applies need the founder's
go per change. No contained agent deployer identity exists, and the owner does
not want a standing credential an agent could trigger. It runs in one attended
consumer-owner session together with hand-over. Warden's case kernel dispatches
the reviewed adapter only inside that session (actor human, parent-session
revoked per attempt); the human session is the authority and the kernel is only
the dispatcher.
ready_check: Namespace SecretStore and ExternalSecret both report Ready=True;
dedicated SA has no legacy token refs; status and fixed metadata only, never
Secret values.
- id: hand-over
owner: '{consumer_owner_repo}'
entry_point: configure {consuming_service} with issuer {issuer}, client {client_id}
and custody bao:platform/workloads/keycape/{client_id}, and make it require
one of {access_groups} in the groups claim before sign-in completes
auth: the consumer owner's own deployment path
entry_point: The consumer owner first makes its own Helm change configuring {consuming_service}
with issuer {issuer}, client {client_id} and custody bao:platform/workloads/keycape/{client_id},
requiring one of {access_groups} in the groups claim before sign-in completes.
Then reviewed adapter net-kingdom/keycape-hand-over, dispatched by Warden's case
kernel inside the attended consumer-owner session, verifies the consumer with
four value-free probes (member-login, non-member-refused, membership-add-grants,
membership-remove-revokes) and records the hand-over receipt.
auth: the attended consumer-owner session on lane apps-consumer-handover (actor human,
parent-session revoked per attempt); the consumer configuration itself is the
owner's own deployment path
lane: apps-consumer-handover
warden_executes: false
attended: false
attended: true
value_handling: none
attended_justification: The verification needs a real member login and a refused
non-member login, which only an attended session can perform, and it follows
the owner's own Helm change in the same consumer-owner session as
deliver-consumer-secret. Warden's case kernel dispatches the reviewed adapter
only inside that session (actor human, parent-session revoked per attempt); the
human session is the authority and the kernel is only the dispatcher.
verification:
- id: authorize-accepts-redirects
check: GET {issuer}/authorize with client {client_id} and each of {redirect_uris}
@ -389,8 +430,10 @@ spec:
reads_secret_value: false
rollback:
- reverses: hand-over
action: remove the OIDC source for {client_id} from {consuming_service} (owner
{consumer_owner_repo})
action: the adapter removes only its hand-over receipt. Removing the OIDC source
for {client_id} from {consuming_service} is the owner's Helm rollback (owner
{consumer_owner_repo}), done inside deliver-consumer-secret's owner_remove
before any consumer object is removed
- reverses: deliver-consumer-secret
when: client_type == confidential
action: After reverting consumer secret reference, delete only authenticated created