railiance-platform/docs/credential-lane-designs/core-hub-forgejo-source-read.md

116 lines
5.3 KiB
Markdown
Raw Normal View History

# Core Hub Forgejo source-read lane (CCR-2026-0031)
Status: **proposed**, drafted 2026-10-03 under CUST-WP-0075 for
`RAPPCOREHUB-WP-0003-T04`. Nothing here is approved, applied or provisioned.
No Forgejo, OpenBao or cluster object was created and no owner message other
than the CUST-WP-0075 reply was sent.
## Why
The repo-manager publisher in namespace `core-hub` reads the 123-entry
repository registry (all `coulomb/*`) anonymously. Nine private sources return
HTTP 404. T04 forbids the Forgejo admin PAT, personal keys or PATs, and the
`policy-nexus-source` token from CCR-2026-0014. This lane gives the publisher
its own read-only identity.
## Shape
| Item | Value |
| --- | --- |
| Forgejo user | `core-hub-source` (restricted, non-admin, private; random unrecorded password) |
| Forgejo team | `coulomb/core-hub-source-readers`: permission read, all repositories, `repo.code` read, every other unit none, cannot create repos |
| PAT | `core-hub-source-read-<UTC timestamp>`, scope exactly `read:repository` |
| OpenBao | `platform/workloads/core-hub/forgejo-source-read` fields `FORGEJO_SOURCE_TOKEN`, `API_USER`, `API_BASE_URL`, `TOKEN_SCOPES`, `GENERATED_AT` |
| Policy | `workload-kv-read-core-hub-forgejo-source` (`openbao/policies/…hcl`, read on data + metadata of that one path) |
| Auth | Kubernetes role `external-secrets-core-hub-forgejo-source`, bound to SA `external-secrets/external-secrets`, TTL 15m |
| Delivery | ESO store + ExternalSecret below → Secret `core-hub/repo-manager-forgejo-source` key `token` |
| Consumer | rapp-core-hub `publisher.existingSecret: repo-manager-forgejo-source` (already supported by the chart; mounts read-only at `/var/run/secrets/repo-manager/forgejo/token`) |
| Rotation | every 180 days or owner change; Forgejo PATs have no server-side expiry |
| Front door | ops-warden `core-hub-forgejo-source-read`, follow-up after approval (see below) |
Naming follows the CCR-2026-0014 precedent (`<workload>-source`,
`<workload>-source-readers`). repo-manager has no service-user naming canon.
Its outstanding `identity-canon` correction is a registry/Forgejo identity
mismatch for one repository. It blocks the 123/0 acceptance, not this
credential or its name.
## Draft manifests (land in `argocd/platform-addons/openbao-secretstore/` only after metadata apply)
```yaml
# CCR-2026-0031. Do not apply until approval and confirm-binding.
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openbao-core-hub-forgejo-source
labels:
app.kubernetes.io/part-of: railiance-gitops
railiance-platform/component: external-secrets
app.kubernetes.io/name: core-hub
spec:
provider:
vault:
server: http://openbao.openbao.svc:8200
path: platform
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: external-secrets-core-hub-forgejo-source
serviceAccountRef:
name: external-secrets
namespace: external-secrets
conditions:
- namespaces:
- core-hub
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: repo-manager-forgejo-source
namespace: core-hub
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-core-hub-forgejo-source
target:
# Explicit target metadata prevents ESO copying source last-applied annotations.
template:
metadata: {}
name: repo-manager-forgejo-source
creationPolicy: Owner
deletionPolicy: Retain
data:
- secretKey: token
remoteRef:
key: workloads/core-hub/forgejo-source-read
property: FORGEJO_SOURCE_TOKEN
```
## Attended sequence (after approval)
1. Reviewers approve and confirm the binding (human acts, recorded by the
CCR tooling): `credential-change.py approve CCR-2026-0031 …` and
`credential-change.py confirm-binding CCR-2026-0031 …`.
2. Founder, in their own terminal (child is silent; read the diagnostic file
on failure, never the output):
`warden access openbao-platform-admin-login --exec -- scripts/openbao-bootstrap-core-hub-source.sh`.
This runs the delegated metadata apply (policy + auth role), then
`scripts/provision-core-hub-forgejo-source.py`, which gets the Forgejo admin
token only through `warden access forgejo-admin-api-token --exec`, mints the
PAT, verifies scope, private-repo read and denials, writes the value to
OpenBao from stdin, reads it back for equality, and records non-secret
evidence. Re-running when the PAT and the OpenBao value both exist is a no-op;
a half state fails closed and points to rotation. Failure diagnostics:
`/tmp/core-hub-source-bootstrap-diagnostic.json` (stage + bounded reason only).
3. Commit the two manifests above and let Argo sync; check presence only with
`scripts/secret_annotation_maintenance.py` through the authorized admin path.
4. rapp-core-hub sets `publisher.existingSecret`, deploys, runs
`make verify-publisher` (expects 123/0 once repo-manager ships the
identity-canon correction), then enables `connectCandidate`.
5. Add the ops-warden catalog entry `core-hub-forgejo-source-read`
(risk high, owner railiance-platform, path above, rotation steps from the
CCR) and move the CCR to `verified`/`active` with evidence.
Offline tests: `python3 -m unittest tests/test_core_hub_forgejo_source_provision.py`.