RAILIANCE-WP is a family name, not a repository (ADR-007, and the prefix registry already lists it retired). Three repositories independently used one number space for unrelated work — RAILIANCE-WP-0012 was openbao extraction here, a cnpg backup in railiance-apps and a deploy-verify in railiance-cluster. This repository also carried two files both numbered 0016. Active workplans move to the successor prefix and are renumbered from 0001 in historical order. Archived workplans keep their historical identifiers. Projection UUIDs are re-derived from the new canonical ids. Records already registered under the old identifiers leave orphaned hub rows behind; that debt is recorded in CUST-WP-0068 and clears when ADR-012's reset-from-forge lands. Refs CUST-WP-0068-T03 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
319 lines
12 KiB
Markdown
319 lines
12 KiB
Markdown
---
|
|
id: RPF-WP-0003
|
|
type: workplan
|
|
title: "Issue-Core Runtime Ingestion Credential Lane"
|
|
domain: financials
|
|
repo: railiance-platform
|
|
status: finished
|
|
owner: codex
|
|
topic_slug: railiance
|
|
planning_priority: high
|
|
planning_order: 9
|
|
created: "2026-06-29"
|
|
updated: "2026-07-02"
|
|
depends_on_workplans:
|
|
- RAIL-PL-WP-0002
|
|
- RAILIANCE-WP-0004
|
|
- RAILIANCE-WP-0007
|
|
- RAILIANCE-WP-0008
|
|
related_state_hub_messages:
|
|
- "f76d3a9e-a98f-4081-885d-b79d94312699"
|
|
related_ccrs:
|
|
- CCR-2026-0002
|
|
state_hub_workstream_id: "5fb6b6a7-3a40-5658-9804-21c0928c6dd9"
|
|
---
|
|
|
|
# RPF-WP-0003 - Issue-Core Runtime Ingestion Credential Lane
|
|
|
|
## Goal
|
|
|
|
Promote the draft `issue-core-ingestion-api-key` access lane from a proposed
|
|
CCR to a reviewed, least-privilege, verified OpenBao workload KV lane that
|
|
`issue-core` can consume through External Secrets and that `ops-warden` can
|
|
reference without holding secret values.
|
|
|
|
This follows the same platform pattern proven by `RAILIANCE-WP-0006`, but keeps
|
|
the issue-core lane independent so the field set, service-account binding,
|
|
verification evidence, and activation decision can be reviewed on their own.
|
|
|
|
No task in this workplan may paste, commit, log, or send secret values through
|
|
Git, State Hub, chat, prompts, shell history, or workplan text.
|
|
|
|
## Suggestion Reviewed
|
|
|
|
Ops-warden confirmed the whynot-design lane in State Hub message
|
|
`f76d3a9e-a98f-4081-885d-b79d94312699` and noted that
|
|
`issue-core-ingestion-api-key` remains draft on its side. The repo already has
|
|
the proposed non-secret CCR:
|
|
|
|
- `credential-change-requests/CCR-2026-0002-issue-core-ingestion-api-key.yaml`
|
|
|
|
## INTENT Fit
|
|
|
|
This work belongs in railiance-platform because it provides shared, secure,
|
|
operable secret custody and delivery behind stable interfaces. It does not add
|
|
issue-core application behavior. The platform-owned output is the OpenBao path,
|
|
read policy, Kubernetes auth role, External Secrets contract, verification
|
|
evidence, and ops-warden handoff.
|
|
|
|
The plan supports these `INTENT.md` principles:
|
|
|
|
- secure custody: secret values stay in OpenBao/operator custody;
|
|
- stable interfaces: issue-core consumes a documented path, fields, role, and
|
|
External Secrets target rather than internal OpenBao topology;
|
|
- operable and observable: activation requires positive and negative checks
|
|
plus non-secret audit evidence;
|
|
- independently evolvable: the credential store, auth role, and front door can
|
|
change underneath the consumer contract.
|
|
|
|
## Proposed Contract
|
|
|
|
| Item | Proposed value |
|
|
| --- | --- |
|
|
| CCR | `CCR-2026-0002` |
|
|
| ops-warden catalog id | `issue-core-ingestion-api-key` |
|
|
| Tenant/org | `issue-core` |
|
|
| Workload/project | `issue-core` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/issue-core/issue-core/issue-core-runtime` |
|
|
| Secret fields | `ISSUE_CORE_API_KEY`, pending decision on `GITEA_BACKEND_TOKEN` |
|
|
| Read policy | `workload-kv-read-issue-core-runtime` |
|
|
| Policy file | `openbao/policies/workload-kv-read-issue-core-runtime.hcl` |
|
|
| Auth method | Kubernetes auth |
|
|
| Auth role | `external-secrets-issue-core` |
|
|
| OpenBao auth service account | `external-secrets` |
|
|
| OpenBao auth namespace | `external-secrets` |
|
|
| Delivery surface | `ExternalSecret issue-core/issue-core-runtime` to Secret `issue-core-runtime` |
|
|
| ops-warden command | `warden access issue-core-ingestion-api-key --fetch ISSUE_CORE_API_KEY` |
|
|
|
|
The `GITEA_BACKEND_TOKEN` field remains an explicit review point. Remove it
|
|
from the CCR before approval if issue-core no longer needs it in this lane.
|
|
|
|
## Tasks
|
|
|
|
## T01 - Review CCR scope and field set
|
|
|
|
```task
|
|
id: RPF-WP-0003-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "a4675954-898a-5b9c-b549-06c5a4bb2afe"
|
|
```
|
|
|
|
Review `CCR-2026-0002` with the platform operator and issue-core owner before
|
|
any live OpenBao apply.
|
|
|
|
Acceptance:
|
|
|
|
- The issue-core owner confirms whether `GITEA_BACKEND_TOKEN` belongs in this
|
|
lane or should be removed before approval.
|
|
- The approved field set is limited to runtime ingestion credentials needed by
|
|
issue-core.
|
|
- Review comments and approval state are recorded in the CCR without secret
|
|
values.
|
|
- The lane remains clearly platform-owned secret custody, not issue-core
|
|
application logic.
|
|
|
|
**2026-06-30:** Live cluster metadata confirms
|
|
`ExternalSecret issue-core/issue-core-runtime` is `Ready=True` with reason
|
|
`SecretSynced` and maps both `ISSUE_CORE_API_KEY` and `GITEA_BACKEND_TOKEN` from
|
|
`platform/workloads/issue-core/issue-core/issue-core-runtime`. Retain both
|
|
fields in `CCR-2026-0002` unless the issue-core owner later removes one through
|
|
review. The CCR remains `proposed`; this task records non-secret scope review,
|
|
not approval to apply.
|
|
|
|
## T02 - Confirm Kubernetes auth and External Secrets binding
|
|
|
|
```task
|
|
id: RPF-WP-0003-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "8c938e3e-3302-5f1f-a422-03dd7eca7ed1"
|
|
```
|
|
|
|
Confirm the exact Kubernetes service account, namespace, and External Secrets
|
|
target that should consume this lane.
|
|
|
|
Acceptance:
|
|
|
|
- The service account and namespace are confirmed as `issue-core`/`issue-core`
|
|
or the CCR is updated with the approved alternative.
|
|
- The auth role binds only the approved service account and namespace.
|
|
- The External Secrets target and expected field names are documented.
|
|
- No direct human or agent read path is activated unless separately approved.
|
|
|
|
**2026-06-30:** Confirmed the current delivery path uses the platform External
|
|
Secrets operator, not a workload pod service account. The `issue-core`
|
|
Deployment uses the `default` service account, and no `issue-core` service
|
|
account exists. `ClusterSecretStore/openbao` authenticates to OpenBao as
|
|
`external-secrets/external-secrets` with role `external-secrets-issue-core` and
|
|
is limited to the `issue-core` namespace. Updated `CCR-2026-0002` to this
|
|
confirmed auth subject while keeping the exact
|
|
`workload-kv-read-issue-core-runtime` policy. `credential-change.py
|
|
applier-dry-run CCR-2026-0002` now blocks only because the CCR is still
|
|
`proposed`.
|
|
|
|
## T03 - Apply or confirm least-privilege OpenBao metadata
|
|
|
|
```task
|
|
id: RPF-WP-0003-T03
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "b0fd87d6-9150-5607-8102-411d0a373e1b"
|
|
```
|
|
|
|
Apply the read policy and Kubernetes auth role only after review and binding
|
|
confirmation.
|
|
|
|
Acceptance:
|
|
|
|
- `openbao/policies/workload-kv-read-issue-core-runtime.hcl` grants only read
|
|
access to the exact KV-v2 data and metadata paths.
|
|
- The Kubernetes auth role attaches only
|
|
`workload-kv-read-issue-core-runtime`.
|
|
- Live apply uses an approved operator path or the delegated applier from
|
|
`RAILIANCE-WP-0008`; broad `platform-admin` handoffs are avoided where
|
|
possible.
|
|
- Apply evidence records only policy name, role name, actor, timestamp, and
|
|
non-secret OpenBao request ids.
|
|
|
|
## T04 - Provision values through approved custody
|
|
|
|
```task
|
|
id: RPF-WP-0003-T04
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "8b2d803d-7165-58c4-b9ce-95d45273b8fb"
|
|
```
|
|
|
|
Have an approved operator create or confirm the OpenBao KV entry and fields.
|
|
|
|
Acceptance:
|
|
|
|
- The path exists at
|
|
`platform/workloads/issue-core/issue-core/issue-core-runtime`.
|
|
- Approved fields are present with the exact reviewed names.
|
|
- Values are entered directly through OpenBao/operator custody, never through
|
|
Git, State Hub, chat, prompts, workplans, or shell history.
|
|
- Non-secret evidence records only path, field names, actor, timestamp, and
|
|
verification result.
|
|
|
|
## T05 - Verify positive and negative access
|
|
|
|
```task
|
|
id: RPF-WP-0003-T05
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "83c98191-b9eb-5189-9aa7-06cb58424f95"
|
|
```
|
|
|
|
Prove that the approved issue-core identity can consume the lane and that other
|
|
identities cannot.
|
|
|
|
Acceptance:
|
|
|
|
- Positive verification shows the approved issue-core service account can read
|
|
the configured fields through OpenBao or External Secrets without printing
|
|
values.
|
|
- Negative verification shows an unapproved service account cannot read the
|
|
path.
|
|
- OpenBao audit evidence exists for allowed and denied attempts, recorded only
|
|
as non-secret request ids or timestamps.
|
|
- Verification includes the External Secrets delivery path if that is the
|
|
production consumer interface.
|
|
|
|
## T06 - Activate ops-warden catalog front door
|
|
|
|
```task
|
|
id: RPF-WP-0003-T06
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "f8a321d1-e898-5a96-b4c5-b025739e5d9c"
|
|
```
|
|
|
|
Send ops-warden the non-secret pointers needed to promote
|
|
`issue-core-ingestion-api-key` from draft to active.
|
|
|
|
Acceptance:
|
|
|
|
- The handoff includes only catalog id, mount, path, field names, auth role,
|
|
policy name/path, External Secrets target, optional flex-auth ref, and
|
|
runbook/workplan links.
|
|
- ops-warden confirms the catalog entry has no unresolved placeholders.
|
|
- ops-warden confirms it proxies access as the caller and holds no secret
|
|
value.
|
|
- The CCR front-door readiness becomes active/resolvable only after positive
|
|
and negative verification.
|
|
|
|
**2026-07-02:** T06 done. ops-warden promoted catalog id
|
|
`issue-core-ingestion-api-key` from draft to active (ops-warden commit
|
|
`364eb7d`) following its own promotion checklist: concrete zero-placeholder
|
|
handoff (`warden route show issue-core-ingestion-api-key --json` reports
|
|
`status: active`, `resolvable: true`), playbook gate marked met, draft tables
|
|
updated, routing tests passing (45/45). The entry carries pointers only —
|
|
ops-warden proxies reads as the caller and holds no secret value.
|
|
`CCR-2026-0002` recorded the `frontdoor_activation` evidence and moved to
|
|
`status: active` with `readiness: ready`. Promotion happened only after the
|
|
2026-07-02 positive/negative verification.
|
|
|
|
## T07 - Record lifecycle operations
|
|
|
|
```task
|
|
id: RPF-WP-0003-T07
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "cac50ef4-7236-5218-8882-c9e5cc1f772f"
|
|
```
|
|
|
|
Document how to deactivate, rotate, and respond to compromise for this lane.
|
|
|
|
Acceptance:
|
|
|
|
- Deactivation disables the ops-warden front door and removes or detaches the
|
|
auth role policy without deleting required audit evidence.
|
|
- Rotation keeps values inside OpenBao/operator custody and records only
|
|
non-secret evidence.
|
|
- Compromise response names the immediate front-door disable, affected field
|
|
rotation, and follow-up incident workplan path.
|
|
|
|
## Exit Criteria
|
|
|
|
- `CCR-2026-0002` is reviewed, approved, applied, verified, and active.
|
|
- issue-core can consume the required runtime ingestion credential through the
|
|
approved platform interface.
|
|
- Unauthorized access is denied and recorded.
|
|
- ops-warden can resolve `issue-core-ingestion-api-key` without storing the
|
|
value.
|
|
- No secret values appear in Git, State Hub, chat, prompts, logs, or workplans.
|
|
|
|
|
|
## Progress 2026-07-02 — approval, apply, verification
|
|
|
|
`CCR-2026-0002` approved by bernd.worsch (both required approver roles) with
|
|
the field-set decision to keep `ISSUE_CORE_API_KEY` and `GITEA_BACKEND_TOKEN`.
|
|
|
|
- T03 done: policy `workload-kv-read-issue-core-runtime` and kubernetes auth
|
|
role applied via the constrained `credential-change-prod-applier` child
|
|
token (accessor revoked after use); State Hub apply evidence `4a66c84f`.
|
|
- T04 done: KV entry exists at the approved path (metadata `current_version
|
|
2`, created 2026-06-25); values were provisioned through operator custody.
|
|
- T05 done: positive = ExternalSecret `issue-core/issue-core-runtime`
|
|
Ready=True/SecretSynced (refresh 2026-07-02T09:42Z); negative =
|
|
default-policy token denied on the KV data path (2026-07-02T10:08Z, probe
|
|
accessor revoked); both recorded in the file audit device
|
|
`/openbao/audit/openbao-audit.log`.
|
|
- T06 progress: front-door handoff sent to ops-warden (State Hub message
|
|
`5d47caaa-dd3f-496f-94ba-a488722f8d82`); waiting on catalog confirmation.
|
|
|
|
|
|
## T07 completed 2026-07-02
|
|
|
|
Lifecycle operations documented in
|
|
`docs/credential-lane-lifecycle-runbook.md`: the canonical per-action
|
|
procedure is generated by `scripts/credential-change.py lifecycle-plan
|
|
<CCR> --action {deactivate|rotate|compromise}`, and the runbook adds the
|
|
lane-specific consumer facts (materialized-Secret persistence, second
|
|
consumers, restart requirements, provider-side revocation for the OpenRouter
|
|
key) plus the post-rotate verification contract. Front-door disable comes
|
|
first in every action; audit evidence is never deleted; values stay in
|
|
OpenBao/operator custody.
|