File CCR-2026-0051 MAS TEM relay lane; propose RPF-WP-0061 self-service CCR intake
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 306568@bnt-lap001
Assistant-Session: 8bdf8150-ea56-41e7-9132-13f04f6b0b91
This commit is contained in:
codex 2026-10-18 12:22:01 +02:00
parent d35c0f9d4b
commit 4398f89e02
3 changed files with 230 additions and 0 deletions

View file

@ -0,0 +1,95 @@
id: CCR-2026-0051
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: Temporary MAS Scaleway TEM relay SMTP ESO read lane
status: proposed
created: '2026-10-18'
updated: '2026-10-18'
requester:
agent: ops-mason
reason: ops-mason plans/mas-tem-relay-smtp.md (MASON-WP-0014, reviewed 2026-10-18T10:13:55Z)
for consumer mail-address-semantics MAS-WP-0003. Hub messages daa119e6, a77e5879
(kv_path correction) and 049afa1f. No approval is implied by this filing.
review:
required: true
required_approvers:
- founder
- railiance-platform-owner
- mail-address-semantics-owner
comments: []
target:
domain: infotech
tenant: platform
workload: mas-tem-relay
environment: production
purpose: Deliver Scaleway TEM SMTP relay username/password to namespace mas only.
Temporary lane; torn down with namespace mas.
openbao:
mount: platform
kv_path: platform/suppliers/scaleway/mas-tem-relay
fields:
- username
- password
metadata_read: false
token_self_lifecycle: true
policy_name: workload-kv-read-mas-tem-relay
policy_file: openbao/policies/workload-kv-read-mas-tem-relay.hcl
auth:
method: kubernetes
mount: kubernetes
role: external-secrets-mas-tem-relay
bound_claims:
service_account_names:
- mas-tem-relay-eso
service_account_namespaces:
- mas
bound_claims_confirmed: false
policies:
- workload-kv-read-mas-tem-relay
ttl: 15m
audience: openbao
token_max_ttl: 15m
token_explicit_max_ttl: 15m
token_no_default_policy: true
access_frontdoor:
type: external-secrets
catalog_id: mas-tem-relay-smtp
selector: Namespace mas, SA mas-tem-relay-eso only
readiness: pending-review
resolvable: false
delivery:
surface: external-secrets
target: Namespace mas; dedicated SA mas-tem-relay-eso; ExternalSecret projecting
username and password only.
bootstrap_command: Not applicable. KV value already written by the founder (v2);
this CCR creates no value and authorizes no value read.
risk:
classification: medium
notes:
- Supplier SMTP credential can send mail as the TEM sending domain; exposure is
limited to namespace mas.
- New read scope on a supplier path; founder approval required. No other lane reads
this path (ops-mason live survey 2026-10-18T10:13:55Z).
- Apply may be run by ops-mason under ops-mason-construct (MASON-IN-0005) once
installed (MASON-WP-0015-T02) and this CCR is approved; that grant covers
workload-kv-read-* policies and external-secrets-* roles only.
verification:
positive:
- Exact SA/namespace/audience login succeeds; ESO Ready/SecretSynced; metadata
version matches admitted KV version 2 without printing values.
negative:
- Wrong SA, namespace or audience login refused; sibling paths under platform/suppliers/scaleway,
list, metadata, write and delete denied.
activation_conditions:
- Founder, platform owner and consumer owner approve the exact CCR.
- Native bound claims confirmed (confirm-binding) and native policy/role readback
matches source.
evidence: []
lifecycle:
deactivate: Delete ExternalSecret and role external-secrets-mas-tem-relay, then
policy workload-kv-read-mas-tem-relay, when namespace mas is torn down.
rotate: Founder writes a new KV version via UI; ESO refresh picks it up; verify
metadata version only.
compromised: Revoke the SMTP credential at Scaleway, disable the role, rotate the
KV value, then re-enable after review.

View file

@ -0,0 +1,11 @@
path "platform/data/suppliers/scaleway/mas-tem-relay" {
capabilities = ["read"]
}
path "auth/token/lookup-self" {
capabilities = ["read"]
}
path "auth/token/revoke-self" {
capabilities = ["update"]
}

View file

@ -0,0 +1,124 @@
---
id: RPF-WP-0061
type: workplan
title: "Self-service CCR intake: clients file and progress CCRs without a platform worker"
domain: financials
repo: railiance-platform
status: proposed
owner: codex
created: "2026-10-18"
updated: "2026-10-18"
flavor: implementation
origin: cross-repo
origin_ref: ops-mason daa119e6 / 049afa1f; MASON-IN-0005
---
Demand: every credential change request today waits on a railiance-platform
worker session to allocate the CCR number, copy the client's draft and policy
file into this repo, run `credential-change.py validate`, write the platform
owner review and relay the founder command. For routine lanes the worker adds
no judgement: ops-mason already produces drafts that pass `validate`
(MASON-WP-0010-T03, MASON-WP-0014), and from MASON-IN-0005 ops-mason can apply
`workload-kv-read-*` policies and `external-secrets-*` roles itself. The worker
has become a relay, and clients stall whenever no platform session runs.
Goal: a client can take a standard CCR from draft to approved and applied
using only repo tooling, CI and the State Hub decision flow. Platform judgement
is moved into a versioned, reviewed *standard lane profile*; only requests that
fall outside it are routed to a platform worker.
Invariants (unchanged by this plan):
- CCRs remain non-secret repo files in `credential-change-requests/`; the repo
stays authoritative and the hub stays a read model.
- Founder approval is never automated. Bound claims still need
`confirm-binding` against native state before apply.
- Nothing here widens ops-mason-construct or any applier grant; secret-id,
token creation and value reads stay with the founder and applier.
## Design
1. **Submit.** The client runs, in a railiance-platform checkout,
`scripts/credential-change.py submit --bundle <dir>` (or `make ccr-submit`).
It copies the CCR and policy file, allocates the next free `CCR-YYYY-NNNN`
from the files on the current `main`, sets `status: proposed`, validates,
commits on branch `ccr/<id>-<slug>` and pushes. A push or merge race simply
re-allocates; git is the allocator, so no central counter or agent is needed.
2. **Platform review as policy-as-code.** `credential-change.py
review-standard <ccr>` checks the standard lane profile
(`registry/ccr-standard-profile.yaml`): `workload-kv-read`; kubernetes auth;
exactly one KV path under `platform/workloads/<a>/<b>` or
`platform/suppliers/<supplier>/<account>`; policy file byte-equal to the
generated HCL (read on the data path plus lookup/revoke-self only); ttl and
max ttl ≤ 15m; `token_no_default_policy: true`; one SA in one namespace;
no other CCR in `proposed|approved|active` reading the same path. A pass
appends the `railiance-platform-owner` review comment with the profile
version and digest. A fail writes the reasons and marks the CCR
`needs_platform_review`, which sends one hub message to `railiance-platform`.
3. **CI gate.** A Forgejo Action on `ccr/*` branches runs `validate`,
`review-standard` and the secret scan; only a green branch fast-forwards to
`main`. The client merges its own green branch.
4. **Founder decision.** `submit` records a State Hub decision for the CCR
(templates exist in `decision-templates`). The founder resolves it;
anyone runs `sync-decision` to move the file to `approved`/`needs_changes`.
5. **Apply and evidence.** In-profile CCRs are applied by ops-mason under
ops-mason-construct, or by the applier, after `confirm-binding`;
`record-evidence` closes the CCR to `active`.
6. **Platform oversight.** Platform owns the profile and reviews changes to it
like code. A weekly `credential-change.py audit-standard` lists every
auto-reviewed CCR so a platform session can spot-check after the fact.
## T01 — Define the standard lane profile
```task
id: RPF-WP-0061-T01
status: todo
priority: high
```
Write `registry/ccr-standard-profile.yaml` from the existing approved ESO
lanes (CCR-2026-0033, -0035, -0041, -0050, -0051 shapes). Record which past
CCRs would and would not have passed it.
## T02 — `submit` and `review-standard` subcommands
```task
id: RPF-WP-0061-T02
status: todo
priority: high
```
Add both subcommands to `scripts/credential-change.py` with tests covering
id allocation, duplicate-path refusal, policy-file mismatch and every profile
rule. `review-standard` never touches OpenBao.
## T03 — CI gate on `ccr/*` branches
```task
id: RPF-WP-0061-T03
status: todo
priority: medium
```
Forgejo Action running validate, review-standard and the secret scan; confirm
which identities may push `ccr/*` (ops-mason first).
## T04 — Hub decision on submit and client-run `sync-decision`
```task
id: RPF-WP-0061-T04
status: todo
priority: medium
```
## T05 — Client documentation and first self-service CCR
```task
id: RPF-WP-0061-T05
status: todo
priority: medium
```
Document the flow in `docs/credential-change-approval.md` and notify
ops-mason and ops-warden. Acceptance: one CCR filed, reviewed, approved and
applied by a client with no railiance-platform worker session involved.