RBAC-7: DESIGN Forgejo-identity -> per-app postgres role/RLS (design only) #55

Merged
plat merged 1 commit from feat/rbac-7-postgres-rls-design into main 2026-07-01 17:06:35 +00:00
Owner

RBAC-7 (roadmap #33): DESIGN Forgejo-identity → per-app Postgres role / RLS

Design-only. Adds docs/design/forgejo-identity-to-postgres-rbac.md.

Question: does the Postgres layer need per-Forgejo-team roles / RLS, given forwardAuth (RBAC-2) already gates the whole app at the edge and each app already gets its own fenced CNPG cluster?

Key move: separate the two things "Postgres RBAC" can mean —

  • (A) platform-tenant isolation (app X out of app Y's DB) — already solved by per-app CNPG cluster + namespace + NetworkPolicies (mcp/src/server.ts:2312, :2345). No per-team role needed.
  • (B) intra-app sub-user authz (rows/tables within one app) — the real RBAC-7 question.

If (B) is warranted, the doc specifies the buildable mapping: Forgejo team → app_<team> role → RLS POLICY on current_setting(app.forgejo_team), bound per-transaction via SET LOCAL from the forwardAuth-verified identity; RLS policies live in the app's own migration (_app-template/src/migrate.ts), create_app stays out of it, better-auth tables are BYPASSRLS. Identity is already consistent end-to-end (better-auth id == Forgejo sub, _app-template/src/auth.ts:181).

Recommendation: DEFER for the single-client platform

Ship Option 1 (authorize in app code against the better-auth/forwardAuth identity). The edge already gates the app and the DB is already single-tenant; RLS would add a third gate for intra-app row authz the client has no requirement for, at real (stateful) build cost. Deferring is free — RLS is additive later with no schema debt.

Build RLS when: one app hosts mutually-distrusting tenants/teams over shared tables, OR a compliance rule demands DB-enforced row authz, OR the authz surface outgrows app code.

Closes #33.

🤖 Generated with Claude Code

## RBAC-7 (roadmap #33): DESIGN Forgejo-identity → per-app Postgres role / RLS Design-only. Adds `docs/design/forgejo-identity-to-postgres-rbac.md`. **Question:** does the Postgres layer need per-Forgejo-team roles / RLS, given forwardAuth (RBAC-2) already gates the whole app at the edge and each app already gets its own fenced CNPG cluster? **Key move:** separate the two things "Postgres RBAC" can mean — - **(A) platform-tenant isolation** (app X out of app Y's DB) — **already solved** by per-app CNPG cluster + namespace + NetworkPolicies (`mcp/src/server.ts:2312`, `:2345`). No per-team role needed. - **(B) intra-app sub-user authz** (rows/tables within one app) — the real RBAC-7 question. **If (B) is warranted**, the doc specifies the buildable mapping: Forgejo team → `app_<team>` role → RLS `POLICY` on `current_setting(app.forgejo_team)`, bound per-transaction via `SET LOCAL` from the forwardAuth-verified identity; RLS policies live in the **app's own migration** (`_app-template/src/migrate.ts`), `create_app` stays out of it, better-auth tables are `BYPASSRLS`. Identity is already consistent end-to-end (better-auth id == Forgejo `sub`, `_app-template/src/auth.ts:181`). ### Recommendation: **DEFER** for the single-client platform Ship Option 1 (authorize in app code against the better-auth/forwardAuth identity). The edge already gates the app and the DB is already single-tenant; RLS would add a third gate for intra-app row authz the client has no requirement for, at real (stateful) build cost. Deferring is free — RLS is additive later with no schema debt. **Build RLS when:** one app hosts mutually-distrusting tenants/teams over shared tables, OR a compliance rule demands DB-enforced row authz, OR the authz surface outgrows app code. Closes #33. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Decides whether the Postgres layer needs per-Forgejo-team roles / RLS given
forwardAuth (RBAC-2) already gates the whole app and each app has its own fenced
CNPG cluster. Separates platform-tenant isolation (already solved by
cluster+namespace+netpol) from intra-app sub-user authz (the real question).
Specifies the buildable Forgejo-team -> app_<team> role -> RLS-policy mapping,
who provisions each layer (per-app migration vs create_app vs a team reconciler),
and the better-auth user-table interaction (id == Forgejo sub; tables BYPASSRLS).

Recommendation: DEFER for the single-client platform; ship Option 1 (authorize
in app code against the better-auth/forwardAuth identity). Build RLS only when an
app hosts mutually-distrusting internal tenants over shared tables, a compliance
rule demands DB-enforced row authz, or the authz surface outgrows app code.

Anchored to mcp/src/server.ts CNPG bootstrap + netpol + create_app and
_app-template auth.ts/migrate.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
plat merged commit fb9dd1d615 into main 2026-07-01 17:06:35 +00:00
Sign in to join this conversation.
No description provided.