railiance-platform/credential-change-requests/CCR-2026-0020-approval-engine-operator-client-read.yaml
codex 32d5cf0211
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Prepare the two approval client-side reader admissions
RPF-WP-0035-T06. Adds CCR-2026-0019 (secrets-engine) and CCR-2026-0020
(approval-engine-operator) with their exact-path read policies, reusing the
existing version-1 custody from the verifier activation. No reseed, rotation,
shared reader or verifier Secret reuse; both requests are in_flight and nothing
is applied.

The two shapes were decided by read-only survey rather than assumed.
secrets-engine consumes its client secret through an operator-run CLI reading a
protected file, and its namespace holds no workload, so reader 1 is an attended
operator-workstation OIDC lane rather than an ESO lane; its one missing input is
the operator group claim, which NetKingdom and KeyCape own. approval-engine is
not deployed and no owner source names who presents the operator client, so
reader 2 records the undetermined actor instead of guessing one for the widest
approval scope in the pair. Both declare openbao.auth missing rather than
carrying a placeholder binding.

T06 moves to wait on those two owner inputs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLUjpv3ssxNRAEPPgLFnEB

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1275505@bnt-lap001
Assistant-Session: 97265baa-f08f-4032-b290-a1e2965a69c5
2026-09-09 14:41:01 +02:00

145 lines
6.3 KiB
YAML

id: CCR-2026-0020
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: Client-side read of the approval-engine-operator client secret
status: in_flight
created: '2026-09-09'
updated: '2026-09-09'
in_flight:
missing_fields:
- openbao.auth
blocking_reason: >-
The presenting actor is not identified by any owner source. approval-engine
verifies this client's tokens but never presents them, and no other repo
claims the approver surface that would. Live inspection on 2026-09-09 found
no approval-engine namespace, workload or Service in the cluster; the owner
deploy manifest targets namespace approval-engine and remains unapplied. An
auth method cannot be chosen before it is known whether the presenter is an
attended operator, an in-cluster component, or an agent surface, and the
three imply different roles, policies and delivery.
owner: railiance-platform
requester:
agent: claude
reason: >-
RPF-WP-0035-T06 residual from the completed verifier custody
(CCR-2026-0018). The verifier copy lets KeyCape authenticate the
approval-engine-operator client; something must also present it. This request
holds the client-side reader open with the determined parts recorded and the
undetermined parts named, rather than guessing a reader for the widest scope
set in the pair. It reuses existing version-1 custody; no reseed, no rotation.
review:
required: true
required_approvers:
- platform-operator
- approval-engine-owner
comments:
- at: '2026-09-09'
reviewer: railiance-platform (claude)
decision: actor_not_determined
comment: >-
Determined from owner source: the approval-engine-operator registration
holds approval:create, read, approve, revoke, supersede, observe and emit,
and explicitly not consume; approval-engine itself only verifies presented
tokens (approval_engine/api.py identity check) and does not hold this
client. approval-engine's own records note the engine does not restrict
/entries by principal type, so this client can supply approver evidence
today, and whether it should is approval doctrine owned by gate-house. The
reader therefore cannot be named here without an owner decision, and
naming one anyway would hand the widest approval scope to a guessed
identity. Held in_flight deliberately.
target:
domain: financials
tenant: platform
workload: approval-engine
environment: production
purpose: >-
Establish the separate exact read by which the eventual approval-engine
operator surface obtains its client secret, once that surface is named by its
owner.
openbao:
mount: platform
kv_path: platform/workloads/approval-engine/operator-client
fields:
- CLIENT_SECRET
policy_name: workload-kv-read-approval-engine-operator-client
policy_file: openbao/policies/workload-kv-read-approval-engine-operator-client.hcl
access_frontdoor:
type: ops-warden
catalog_id: approval-engine-operator-client
selector: approval-engine operator client secret
resolvable: false
readiness: pending-review
delivery:
surface: undetermined
target: >-
Not determined. The delivery surface follows the actor: an attended operator
implies a protected workstation file, an in-cluster component implies an
ExternalSecret into the eventual approval-engine namespace, and an agent
surface implies neither. No surface is admitted until the owner names one.
risk:
classification: high
notes:
- >-
This is the widest scope set in the pair: create, approve, revoke and
supersede. A holder can forge approval lifecycle actions, and because
approval-engine records principal_type rather than restricting it, a
non-human holder can supply approver evidence. That is why the actor is left
unnamed rather than defaulted.
- >-
approval:consume is absent by design and stays absent. Adding it is a new
lane decision, not an edit to this request.
- >-
The exact-path read policy is written and committed so the eventual reader
inherits a bounded grant rather than a broad one drafted under time pressure.
Writing the policy is not admitting a reader.
- >-
No reseed and no rotation; custody is the existing version 1 from the
verifier activation.
verification:
positive:
- >-
Once the actor is named, the bound identity reads CLIENT_SECRET from the
exact path into its admitted delivery surface with no value in chat, argv,
shell history or logs.
- >-
The named surface obtains a token with subject service:approval-engine-operator,
audience approval-engine and tenant tenant:platform, verified against live JWKS.
negative:
- >-
An identity outside the confirmed binding cannot authenticate through the
eventual role.
- >-
The role cannot read the secrets-engine approval-client path, cannot list any
parent, and cannot write or patch the custody path.
- The reader is denied approval:consume, and denial is observed rather than assumed.
- >-
The KeyCape verifier role cannot be substituted for this reader, and this
reader cannot read the verifier's delivery Secret.
activation_conditions:
- >-
The approval-engine owner names the presenting actor and its placement, or
records that no client-side reader is wanted and this request is cancelled.
- >-
Given that actor, the auth method, mount, role, bound claims and delivery
surface are completed and reviewed as a concrete request.
- >-
Policy and role applied under attended authority
(openbao-platform-admin-login, founder_required) with metadata-only receipts.
- Positive and negative results recorded with non-secret request ids.
evidence: []
lifecycle:
deactivate: >-
Detach the policy from the eventual role and disable the ops-warden catalog
entry. The KeyCape verifier lane and its delivery are unaffected.
rotate: >-
Shared with CCR-2026-0018: one client secret, minted by KeyCape and rewritten
once under attended authority. No independent rotation for this lane alone.
compromised: >-
KeyCape disables the approval-engine-operator registration first, then the
value is rotated; emitted approval actions are referred to approval-engine
for audit review, since rotation does not retract them.
state_hub:
workplan_id: RPF-WP-0035
task_id: RPF-WP-0035-T06
related_request: CCR-2026-0018