---
id: w6/m8/t001
title: "Design the split: keep app.bex.co verbs cluster-wide, move secrets/pods/pods-log to a namespace-scoped Role"
worker: worker6
status: done
estimate: 45m
depends_on: []
---

## Objective

Decide the concrete RBAC shape: which verbs stay on a cluster-wide `ClusterRole` (only `app.bex.co` resources, since tenant namespaces are dynamic) and which move to a namespace-scoped `Role` bound only in the namespaces bex-api actually serves.

## Context

- `lego/operator/config/api/rbac.yaml` — current single `ClusterRole` grants cluster-wide read on `secrets`, `pods`, `pods/log` plus `app.bex.co` verbs.
- bex-api is configured to operate in `BEX_API_NAMESPACE`/`BEX_CP_APPS_NAMESPACE` (both `default` today, per `CLAUDE.md`'s env var table) but tenant namespaces are dynamic (one per deploy target potentially).
- Uses of `secrets`/`pods`/`pods/log`: bex-api reads CNPG-generated `<db>-app` Secrets, writes per-app `<app>-env` Secrets, tails pod logs for the logs API.

## Steps

1. Enumerate every place bex-api reads/writes `secrets`, `pods`, `pods/log` (grep `lego/backend/internal/` for client-go calls against these resources).
2. Determine whether all uses are scoped to `BEX_API_NAMESPACE`/`BEX_CP_APPS_NAMESPACE`/tenant-App namespaces, or whether any legitimately need broader reach.
3. Write the target shape: `ClusterRole` (app.bex.co only) + `Role`(s) (secrets/pods/pods-log) bound via `RoleBinding` in the served namespace(s) — or a label/resourceName-filtered approach if tenant namespaces are dynamic and a static namespace list won't work.

## Files

- `lego/operator/config/api/rbac.yaml`
- `lego/backend/internal/` (grep for client-go Secret/Pod/Pod-log usage)

## Acceptance criteria

- [ ] A written target RBAC shape covering every real bex-api use of secrets/pods/pods-log, with no use left unaccounted for.

## Out of scope

- Implementation — that's t002.
