# Three-lane ESO authentication recovery RPF-WP-0037 repairs Forgejo SMTP, reuse-surface and target-revenue delivery. All three consumers were active; their old static-token stores failed with 403. Before resync, attended comparison proved existing OpenBao values identical to deployed workload Secrets. This is an authentication migration, not an application credential rotation. | Store | Dedicated service account | OpenBao role | | --- | --- | --- | | openbao-forgejo | forgejo/forgejo-mailer-eso | forgejo-mailer-eso | | openbao-reuse | reuse/reuse-surface-eso | reuse-surface-runtime-eso | | openbao-target-revenue | target-revenue/target-revenue-eso | target-revenue-runtime-eso | Source: `openbao/eso-auth-recovery/lanes.json`, `serviceaccounts.yaml`, the three `*-eso.hcl` policies and existing ClusterSecretStore manifests under `argocd/platform-addons/openbao-secretstore/`. These stores remain outside the coulombcore kustomization. No broad RBAC is added; ESO's existing TokenRequest authority is used with exact namespace/SA/audience OpenBao bindings. Roles use audience `openbao`, 15-minute TTL/max/explicit max, no default policy, and exact data reads. ESO also needs token lookup-self and revoke-self. No KV metadata/list/write, token creation or sibling access is granted. Existing caller-facing policies and application credentials remain in place. Commit and push source before running the attended command: ```sh warden access openbao-platform-admin-login --exec -- \ /usr/bin/python3 /home/worsch/railiance-platform/scripts/repair_eso_kubernetes_auth.py \ apply --kubeconfig /home/worsch/.kube/config-railiance01 \ --receipt /tmp/eso-auth-apply.json --confirm 'APPLY RPF-WP-0037' ``` The helper pins cluster identity, compares custody before mutation, refuses scope drift, validates bounded positive and negative authentication, and patches only each store's auth using a JSON Patch test of the observed spec. `verify` forces another refresh and requires its timestamp to advance. `cleanup` performs the same verification, proves the old token is unreferenced, revokes it or proves invalidity, and deletes only its obsolete Secret with UID/resourceVersion preconditions. All receipts are exclusively created mode 0600; values and tokens stay in captured memory. Choose a fresh receipt path for each invocation. On failure, inspect only the receipt and safe metadata. Completed store repairs can be verified independently; retry apply only against matching reviewed source. Do not roll back to rejected static credentials. Correct forward to the accepted Kubernetes role; application Secrets are retained and no workload restart is part of this procedure. Custody disagreement needs its own owner-led resolution.