**RESOLVED 2026-07-12 (w6 follow-ups).** bex-api secrets/pods/pods-log/metrics moved from the cluster-wide ClusterRole to a -namespace-scoped Role+RoleBinding (deploy/gitops/base/bex-api-apps-rbac.yaml); the ClusterRole now holds only the app.bex.co verbs. Operator secrets-CRUD defense-in-depth left as-is (justified by dynamic namespaces).

# Scope down bex-api's cluster-wide RBAC — from w6/m6/t001 (RBAC audit)

`lego/operator/config/api/rbac.yaml` grants the **externally-reachable** bex-api
ServiceAccount a ClusterRole (bound ClusterRoleBinding) with cluster-wide read
on `secrets`, `pods`, and `pods/log` — the largest blast-radius grant on the
product surface. A compromised bex-api pod can read ANY secret cluster-wide
(Kratos/Hydra in `auth`, OpenBao in `secrets`, the GitHub App key in `bex-system`,
CNPG creds everywhere) and tail any pod's logs.

The grant is genuinely *used* (bex-api reads CNPG-generated `<db>-app` Secrets,
writes per-app `<app>-env` Secrets, tails pod logs for the logs API), and it
deliberately omits `delete`/`watch`. The problem is **scope**, not the verbs:
bex-api is configured to operate in `BEX_API_NAMESPACE`/`BEX_CP_APPS_NAMESPACE`
(both `default` today), but the binding reaches every namespace including
platform namespaces.

**Fix direction (needs careful analysis — why this is filed, not done mid-milestone):**
split the grant — keep the `app.bex.co` verbs cluster-wide (tenant namespaces are
dynamic), but move `secrets`/`pods`/`pods/log` to a namespace-scoped Role in the
served namespace(s), or gate them with a label/resourceName filter so they
cannot reach `auth`/`secrets`/`bex-system`/`argocd`. Verify the logs/env-vars/
managed-DB surfaces still work after the change against a live cluster.

**Adjacent (defense-in-depth, same note):** the operator's `manager-role` has
cluster-wide full-CRUD on core `secrets` (`lego/operator/config/rbac/role.yaml:7-19`).
Justified — the operator reconciles Apps across dynamic tenant namespaces and
needs owner-GC of build/env secrets — but consider an admission/NetworkPolicy
guard forbidding the operator SA from `secrets` in platform namespaces.

Source: w6/m6/t001 RBAC least-privilege audit, 2026-07-11.
