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
216 lines
11 KiB
YAML
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
|