Layer declaration (gate-house). INTENT.md now carries the declaration in its own voice with layer.yaml as the machine-readable form, adapted from ops-warden's reference. railiance-platform is Staff: operating OpenBao is not a claim to the Tooling layer, because §4 is explicit that no operator-of-third-party-Tooling shape exists and that someone running it stays a declared gap. Six direct Tooling contacts are mapped by capability rather than by file — one §5.2 conduit, one §5.1 diagnostic, four §5.3 gaps with intended owners and review dates — and the uncatalogued contacts are listed so the check is total. We are PEP-shaped and the unreachable-engine stance map is NOT published; that is recorded as an open obligation to build against v0.8, not left silent. Placement admission. canned-prompts was added as a PostgresConsumer on platform-pg-2 in rapp-postgres 1b68b4c without a placement owner here, which is exactly the cross-repo drift the assurance check exists to catch; the check had been failing on it. Registered with its real boundary evidence, corrected the stale test expectation that pinned the overflow cell at one consumer, and updated the SCOPE occupancy line to 2/4. Also records owner input received today: key-cape's issuer view on CCR-2026-0020's presenting actor, and their confirmation that codex-railiance-platform correctly stays tenant:coulomb, so the flagged T02 discrepancy is closed as not-a-defect. The whynot-design npm field is NOT changed. Two dated live receipts here name NPM_AUTH_TOKEN as the field, including an attended founder fetch; that is recorded against the counterparty claim rather than either side being flipped before the session settles it. 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
161 lines
7.3 KiB
YAML
161 lines
7.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.
|
|
- 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: 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
|