railiance-platform/docs/credential-lane-designs/activity-core-repo-manager-forgejo-read.md
codex be514f6d74 RPF-WP-0015/0056: record round-5 approval and close coordination
Round-5 owner receipts match 044df6f. T02 stays wait for a new attended
window. Custodian accepted Playwright coordination on CUST-WP-0080-T05,
so T06 is done and T03 still waits on identity mapping. The activity-core
Forgejo read design no longer cites the consumed CCR-2026-0034 number.

Assistant: grok
Assistant-Session: 01a13b3e-0402-7a83-a827-6b29197b7132
2026-10-14 18:33:07 +02:00

5.7 KiB

Activity Core repo-manager Forgejo read lane (no CCR filed)

Status: proposed design only, drafted 2026-10-04 for STATE-WP-0094 memo 3 (freshness-runner-deploy-trial-e77f8b4, accepted by the founder 2026-10-04, approval 4ae04c8e) and RMGR-WP-0020-T04. Nothing here is approved, applied or provisioned. No Forgejo, OpenBao or cluster object was created.

An earlier draft of this page cited CCR-2026-0034. That number is the KeyCape secrets-engine operator reader (credential-change-requests/CCR-2026-0034.yaml, applied 2026-10-07). No Forgejo-read CCR exists for the Activity Core worker. CCR-2026-0029 and CCR-2026-0030 are ops_run worker tokens, and CCR-2026-0031 is the core-hub Forgejo source read bound to another namespace. Do not treat this design as a CCR id. Assign the next free id only when this lane is admitted.

Why

The bounded freshness runner (rmgr freshness run, repo-manager e77f8b4) runs inside the Activity Core worker (activity-core/actcore-worker). It reads each repository's default-branch HEAD through the Forgejo API at forgejo.coulomb.social/coulomb/<slug>. Anonymous reads fail on private repositories, which the runner records as a refusal and which stops the memo 3 trials. warden route find (2026-10-04) has no route for this workload:

  • state-hub-forge-derivation-read is bound to SA state-hub/state-hub only.
  • core-hub-forgejo-source-read (CCR-2026-0031) and policy-nexus-forgejo-source-read (CCR-2026-0014) are bound to other namespaces.

Reusing any of them would share one identity across workloads, which the CCR-2026-0014 and CCR-2026-0031 precedent avoids. This lane gives the runner its own read-only identity.

Shape

Item Value
Forgejo user activity-core-freshness (restricted, non-admin, private; random unrecorded password)
Forgejo team coulomb/activity-core-freshness-readers: permission read, all repositories, repo.code read, every other unit none, cannot create repos
PAT activity-core-freshness-read-<UTC timestamp>, scope exactly read:repository
OpenBao platform/workloads/activity-core/repo-manager-forgejo-read fields FORGEJO_READ_TOKEN, API_USER, API_BASE_URL, TOKEN_SCOPES, GENERATED_AT
Policy workload-kv-read-activity-core-repo-manager-forgejo (read on data + metadata of that one path)
Auth Kubernetes role external-secrets-activity-core-repo-manager-forgejo, bound to SA external-secrets/external-secrets, TTL 15m
Delivery ExternalSecret activity-core/actcore-repo-manager-forgejo-read → separate Secret, key FORGEJO_READ_TOKEN. Never merged into actcore-runtime-secret, so the token is not in the worker env
Consumer worker mounts the Secret read-only at /var/run/secrets/repo-manager (defaultMode: 0440) and sets REPO_MANAGER_FORGEJO_TOKEN_FILE=/var/run/secrets/repo-manager/FORGEJO_READ_TOKEN (activity-core docs/rollout-owner-return-and-freshness-worker.md §3b, lines marked "only once 3c is resolved")
Rotation every 180 days or owner change; Forgejo PATs have no server-side expiry
Front door ops-warden activity-core-repo-manager-forgejo-read, follow-up after approval

Open choice for the reviewer: either a dedicated ClusterSecretStore openbao-activity-core-repo-manager-forgejo (CCR-2026-0031 pattern, below) or granting the existing openbao-activity-core store role read on the new path. The dedicated store keeps this high-risk org-wide read separate from the worker's other secrets and is the default here.

Draft manifests (land only after metadata apply)

# No CCR id. Do not apply until this design is admitted, numbered and approved.
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: openbao-activity-core-repo-manager-forgejo
  labels:
    app.kubernetes.io/part-of: railiance-gitops
    railiance-platform/component: external-secrets
    app.kubernetes.io/name: activity-core
spec:
  provider:
    vault:
      server: http://openbao.openbao.svc:8200
      path: platform
      version: v2
      auth:
        kubernetes:
          mountPath: kubernetes
          role: external-secrets-activity-core-repo-manager-forgejo
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets
  conditions:
    - namespaces:
        - activity-core
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: actcore-repo-manager-forgejo-read
  namespace: activity-core
spec:
  refreshInterval: 5m
  secretStoreRef:
    kind: ClusterSecretStore
    name: openbao-activity-core-repo-manager-forgejo
  target:
    template:
      metadata: {}
    name: actcore-repo-manager-forgejo-read
    creationPolicy: Owner
    deletionPolicy: Retain
  data:
    - secretKey: FORGEJO_READ_TOKEN
      remoteRef:
        key: workloads/activity-core/repo-manager-forgejo-read
        property: FORGEJO_READ_TOKEN

Attended sequence (after approval)

  1. Reviewers approve and confirm the binding with the CCR tooling (credential-change.py approve …, confirm-binding …).
  2. Founder, in their own terminal: delegated metadata apply (policy + auth role), then mint the PAT through warden access forgejo-admin-api-token --exec, verify scope, private-repository read and denials, write the value to OpenBao from stdin and read it back for equality. A bootstrap script modelled on scripts/openbao-bootstrap-core-hub-source.sh and scripts/provision-core-hub-forgejo-source.py is still to be written; it is not part of this draft.
  3. Commit the two manifests and let Argo sync; check presence only.
  4. activity-core adds the token env and mount lines from its rollout package §3b, syncs, and runs the memo 3 apply trials.
  5. Add the ops-warden catalog entry and move the CCR to verified/active with evidence.