railiance-platform/credential-change-requests/CCR-2026-0031-core-hub-forgejo-source-read.yaml
codex 963a4f8234
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
CCR-2026-0031: positive verification via verify-publisher (errors 9 -> 2, private-source reads work)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 3775@bnt-lap001
Assistant-Session: cfacb6a5-ad5b-4f79-ac67-053e3b0d34a3
2026-10-03 10:21:20 +02:00

216 lines
11 KiB
YAML

id: CCR-2026-0031
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: Core Hub repo-manager publisher Forgejo private-source read token lane
status: applied
created: '2026-10-03'
updated: '2026-10-03'
requester:
agent: claude (rapp-core-hub repo agent, dispatched by the-custodian under CUST-WP-0075)
reason: RAPPCOREHUB-WP-0003-T04. The repo-manager publisher in namespace core-hub
reads the 123-entry repository registry from Forgejo anonymously; nine private
sources return HTTP 404, so admission cannot reach 123 accepted / 0 errors. The
Forgejo admin PAT, any personal SSH key or PAT, and the policy-nexus-source token
(CCR-2026-0014) are prohibited for this workload. A dedicated identity with read:repository
only is required.
review:
required: true
required_approvers:
- platform-operator
- core-hub-owner
comments:
- at: '2026-10-03T06:32:38+00:00'
reviewer: bernd
decision: binding_confirmed
comment: 'Founder confirmed 2026-10-03 in chat: ''APPROVE CCR-2026-0031 and confirm
binding''. Kubernetes role binds external-secrets/external-secrets, same as
confirmed CCR-2026-0013.'
- at: '2026-10-03T06:32:45+00:00'
reviewer: bernd
decision: approved
comment: 'Founder approved 2026-10-03 in chat: ''APPROVE CCR-2026-0031 and confirm
binding''. Approves the dedicated core-hub-source Forgejo user with a read:repository-only
PAT, OpenBao path platform/workloads/core-hub/forgejo-source-read, ESO delivery
only into namespace core-hub. Provisioning remains a separate attended run.'
target:
domain: infotech
tenant: core-hub
workload: core-hub-repo-manager-publisher
rapp: rapp-core-hub
environment: production
purpose: Hold a dedicated Forgejo PAT scoped exactly read:repository and project
it through External Secrets into namespace core-hub as the Secret that the rapp-core-hub
publisher mounts read-only at /var/run/secrets/repo-manager/forgejo/token.
openbao:
mount: platform
kv_path: platform/workloads/core-hub/forgejo-source-read
fields:
- FORGEJO_SOURCE_TOKEN
- API_USER
- API_BASE_URL
- TOKEN_SCOPES
- GENERATED_AT
policy_name: workload-kv-read-core-hub-forgejo-source
policy_file: openbao/policies/workload-kv-read-core-hub-forgejo-source.hcl
auth:
method: kubernetes
mount: kubernetes
role: external-secrets-core-hub-forgejo-source
bound_claims:
service_account_names:
- external-secrets
service_account_namespaces:
- external-secrets
bound_claims_confirmed: true
policies:
- workload-kv-read-core-hub-forgejo-source
ttl: 15m
access_frontdoor:
type: ops-warden
catalog_id: core-hub-forgejo-source-read
selector: core hub repo-manager publisher Forgejo private source repository read
token
readiness: pending-review
resolvable: false
delivery:
surface: external-secrets
bootstrap_command: warden access openbao-platform-admin-login --exec -- scripts/openbao-bootstrap-core-hub-source.sh
target: ClusterSecretStore openbao-core-hub-forgejo-source (conditions limited to
namespace core-hub) feeding ExternalSecret core-hub/repo-manager-forgejo-source,
which materializes Secret repo-manager-forgejo-source with the single key token
(remoteRef workloads/core-hub/forgejo-source-read property FORGEJO_SOURCE_TOKEN),
explicit empty target metadata template, creationPolicy Owner, deletionPolicy
Retain. rapp-core-hub then sets publisher.existingSecret to repo-manager-forgejo-source
with tokenKey token. Both manifests are drafted in this CCR only and land in argocd/platform-addons/openbao-secretstore
after approval and metadata apply.
forgejo_identity: core-hub-source
forgejo_team: core-hub-source-readers
forgejo_team_contract: Restricted, non-admin, private service user (random unrecorded
password) in org coulomb; team permission read, includes_all_repositories true,
can_create_org_repo false, repo.code read, every non-code unit none. PAT name
prefix core-hub-source-read-, scope exactly read:repository.
repositories: All repositories of Forgejo org coulomb (the registry's 123 entries
are all coulomb/*). Per-repository team membership was rejected because the registry
changes weekly and each addition would need a new attended session.
naming_basis: Follows the CCR-2026-0014 precedent (<workload>-source user, <workload>-source-readers
team). repo-manager publishes no service-user naming canon; its outstanding identity-canon
correction is a registry/Forgejo identity mismatch for one repository and does
not constrain this name.
provisioning_script: scripts/provision-core-hub-forgejo-source.py (silent, idempotent;
admin token reaches it only through warden access forgejo-admin-api-token --exec)
risk:
classification: high
notes:
- Read-only at Forgejo, but disclosure grants estate-wide private source read for
org coulomb. No package, repository-write, organization-admin, user-write, Actions,
cluster, or deployment authority.
- Distinct from CCR-2026-0014; the policy-nexus-source identity and its token are
never reused, so revoking either lane leaves the other intact.
- The publisher calls the in-cluster Forgejo service over plain HTTP; the token
stays on the cluster network, restricted by the core-hub NetworkPolicy egress
to the forgejo namespace. TLS to the in-cluster service is out of scope here.
- Any ExternalSecret in namespace core-hub can reference the store; the namespace
is single-tenant (rapp-core-hub) and the store is not shared with other namespaces.
- Forgejo PATs carry no server-side expiry; the expiry is enforced by the rotation
schedule below and by GENERATED_AT metadata.
verification:
positive:
- The minted token metadata reports exactly read:repository; it resolves a branch
and fetches one archive of a private coulomb repository, checked without printing
the value.
- ExternalSecret core-hub/repo-manager-forgejo-source reports Ready and the Secret
exists (checked only with the safe secret_annotation_maintenance helper, never
by reading values).
- make verify-publisher in rapp-core-hub reports 123 accepted / 0 errors once the
separate identity-canon registry correction has shipped.
negative:
- The PAT cannot create, update, or delete repository content, write packages, or
read Actions secrets; /admin/users is denied.
- The effective permission of core-hub-source on a probe repository is read.
- The external-secrets role cannot read platform/workloads/policy-nexus/forgejo-source-read
or any sibling path; a default OpenBao identity cannot read this path.
- Removing the Secret makes publisher private-source reads fail with 404 again (fail
closed), not fall back to another credential.
activation_conditions:
- Platform operator and Core Hub owner approve this CCR.
- Kubernetes auth role binding for the external-secrets service account is confirmed
(bound_claims_confirmed set true by confirm-binding).
- Delegated metadata apply writes the policy and the auth role.
- Attended provisioning mints the PAT and writes it to OpenBao from stdin, without
logs, chat, Git, State Hub, argv, or persistent temp files.
- The ClusterSecretStore and ExternalSecret are committed and synced; rapp-core-hub
mounts the Secret and passes the positive and negative checks above.
- ops-warden catalog entry core-hub-forgejo-source-read is added and reviewed.
evidence:
- at: '2026-10-03T06:40:16+00:00'
actor: attended operator via governed platform-admin lane
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as attended operator via governed platform-admin
lane using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-core-hub-forgejo-source'
- 'Auth role metadata write: auth/kubernetes/role/external-secrets-core-hub-forgejo-source'
- No secret values were read, written, printed, or accepted in argv.
- at: '2026-10-03T08:06:12+00:00'
actor: attended operator via governed platform-admin lane
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as attended operator via governed platform-admin
lane using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-core-hub-forgejo-source'
- 'Auth role metadata write: auth/kubernetes/role/external-secrets-core-hub-forgejo-source'
- No secret values were read, written, printed, or accepted in argv.
- at: '2026-10-03T08:06:37+00:00'
actor: attended operator via governed platform-admin lane
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as attended operator via governed platform-admin
lane using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-core-hub-forgejo-source'
- 'Auth role metadata write: auth/kubernetes/role/external-secrets-core-hub-forgejo-source'
- No secret values were read, written, printed, or accepted in argv.
- at: '2026-10-03T08:10:11+00:00'
actor: attended operator via governed platform-admin lane
kind: delegated_metadata_apply
result: passed
details:
- Delegated metadata applier ran as attended operator via governed platform-admin
lane using local bao CLI ambient authority.
- 'Policy metadata write: sys/policies/acl/workload-kv-read-core-hub-forgejo-source'
- 'Auth role metadata write: auth/kubernetes/role/external-secrets-core-hub-forgejo-source'
- No secret values were read, written, printed, or accepted in argv.
- at: '2026-10-03T08:10:16+00:00'
actor: attended operator via governed platform-admin lane
kind: forgejo_source_bootstrap
result: passed
details:
- Restricted user core-hub-source and all-repository repo.code-read team core-hub-source-readers
verified; PAT core-hub-source-read-20261003T081013Z reports exactly read:repository;
private probe coulomb/rapp-openbao branch and archive read passed; effective
permission read-only; Actions-secret and instance-admin probes denied; OpenBao
field written from stdin and read back without value output.
- at: '2026-10-03T08:21:20+00:00'
actor: the-custodian (founder-run deploy, core-hub revision 29)
kind: positive_verification
result: passed
details:
- 'make verify-publisher after core-hub rev 29 (2026-10-03): private-source 404s
gone; accepted 121/123 (was 114), errors 2 (was 9). Remaining 2 are repo-manager
registry identity mismatches (identity-canon, flex-auth rename to access-engine),
not credential faults. 123/0 acceptance tracked with repo-manager.'
lifecycle:
deactivate: Delete ExternalSecret and Secret in core-hub, unset publisher.existingSecret,
revoke the PAT, disable the auth role, and leave private sources failing closed.
rotate: Every 180 days or on owner change. Mint a replacement read:repository PAT
for core-hub-source, write it to OpenBao from stdin, let ESO refresh (5m), pass
make verify-publisher, then revoke the predecessor PAT and record evidence.
compromised: Revoke the PAT immediately, delete the Secret, inspect Forgejo access
logs for core-hub-source reads, rotate through this lane, record bounded incident
evidence.
state_hub:
workplan_id: RAPPCOREHUB-WP-0003
task_id: RAPPCOREHUB-WP-0003-T04