Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
173 lines
7.9 KiB
YAML
173 lines
7.9 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: cancelled
|
|
created: '2026-09-09'
|
|
updated: '2026-09-10'
|
|
cancellation:
|
|
owner: approval-engine
|
|
reason: >-
|
|
Requesting owner withdrew the combined lifecycle operator client: no
|
|
presenter exists and no client-side reader is wanted. Human approval belongs
|
|
to informed-decision; any future service presenter needs a narrow new request.
|
|
Completed verifier custody CCR-2026-0018 remains unchanged.
|
|
source_ref: >-
|
|
approval-engine@849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md#approval-engine-operator
|
|
recorded_at: '2026-09-10'
|
|
# Historical omissions retained so cancellation does not invent an auth binding.
|
|
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.
|
|
- at: '2026-09-09'
|
|
reviewer: key-cape (issuer view, not a decision)
|
|
decision: presenting_actor_shapes_offered
|
|
comment: >-
|
|
KeyCape notes the registration carries both approval:create and
|
|
approval:approve, so a single presenter can create an entry and then
|
|
approve it. That is a separation-of-duties property of whoever holds the
|
|
credential, not a defect in the token: KeyCape issues exactly the grants
|
|
approval-engine requested. Two shapes are supportable -- two registrations
|
|
with disjoint create and approve grants, enforced at issuance and
|
|
available today; or one registration with the holder constrained by
|
|
custody, which is where it sits now. Which is right is approval-engine's
|
|
call and the doctrine question is gate-house's. Recorded in key-cape
|
|
docs/approval-engine-provisioning-request.yaml under
|
|
presenting_actor_note. This does not name an actor and does not unblock
|
|
this request.
|
|
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: disabled
|
|
delivery:
|
|
surface: none
|
|
target: >-
|
|
Cancelled on owner withdrawal; the following alternatives were never admitted.
|
|
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
|