← Files InsForgeARCHIVED FILE
skills/insforge-debug/references/policies.md
4.51 KB · Oct 5, 2026 · 18:29 UTC
# Policies Active RLS (Row-Level Security) rules pulled from Postgres's `pg_policies` system view. The primary primitive for **what RLS is currently allowing or denying** — distinct from "what config we *meant* to deploy" (that lives in [metadata](metadata.md) / migration history). ## Command ```bash npx @insforge/cli db policies ``` Returns every policy: table, schema, policy name, command (`SELECT` / `INSERT` / `UPDATE` / `DELETE` / `ALL`), target role, `USING` expression, `WITH CHECK` expression. Only specific InsForge-managed tables allow developer RLS changes. Check the relevant module skill or CLI reference before writing policy SQL for a managed table. If that table is listed as allowing RLS changes, normal RLS operations are allowed and should go in migrations. ## Policy anatomy | Field | Meaning | |-------|---------| | `tablename` | Which table the policy applies to | | `cmd` | Which operation it gates (read/write/all) | | `roles` | Which DB roles the policy applies to (typically `authenticated`, `anon`, `public`) | | `qual` (USING) | Filter expression: **which existing rows the role can see/modify**. Applied to `SELECT`, `UPDATE`, `DELETE`. | | `with_check` | Validation expression: **which new/modified rows are allowed**. Applied to `INSERT`, `UPDATE`. | | `permissive` / `restrictive` | Permissive policies OR together; restrictive AND. Most InsForge projects use permissive. | ## How to read For "why was this request denied?": 1. Identify the table from the request URL (`/api/database/records/<table>`). 2. List policies for that table — note `cmd` and `roles`. 3. Walk the `USING` / `WITH CHECK` expressions against the actual request: - **No policy for that role+cmd combo** → denied by default. Need to add a policy. - **`USING` evaluates false for this row** → row is invisible / not modifiable. Confirm the helper (e.g., `auth.uid()` returns the expected user_id). - **`WITH CHECK` evaluates false on insert** → the new row's columns violate the policy. The insert payload is wrong, or the policy is too strict. ## Common RLS bug shapes | Symptom | Likely cause | |---------|-------------| | All authenticated users see all rows (no isolation) | Policy is `USING (true)` — too permissive; restrict by `user_id` column | | Authenticated user gets empty result on own data | Wrong helper function (`auth.uid()` returns UUID; if `user_id` column is TEXT from third-party auth, use `requesting_user_id()` instead) | | Insert fails for owner with "new row violates RLS policy" | Missing `WITH CHECK` matching the `USING`, or `WITH CHECK` references columns not in payload | | Third-party auth (Clerk/Auth0/etc.) users get blanket deny | Wrong helper (`auth.uid()` expects InsForge-issued JWT; third-party providers need `requesting_user_id()` with the right claim extraction) | | Anonymous user can read sensitive table | RLS not enabled on the table (forgot `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`), or a policy applies to `public` / `anon` role without filter, or the connection is using a role with `BYPASSRLS` | ## Boundaries - **Lists active policies, doesn't simulate.** Doesn't tell you "this specific request would be allowed" — combine with [logs](logs.md) (`postgREST.logs`) to see the actual denial event. - **Doesn't include the helper function bodies.** `auth.uid()` / `requesting_user_id()` are SQL functions; inspect via `db query` if you need to verify they return what you expect. - **Only listed managed tables allow RLS changes.** Check the relevant module skill or CLI reference before changing RLS on a managed table. If the table is listed, put normal RLS operations in [migrations](../../insforge-cli/references/database/migrations.md); keep normal schema changes in `public`. ## Example User reports: "logged-in user gets 403 trying to `GET /api/database/records/posts`". ```bash # 1. See the denial event npx @insforge/cli logs postgREST.logs --limit 50 # 2. List policies on the posts table npx @insforge/cli db policies # 3. If the project uses third-party auth, verify the helper npx @insforge/cli db query "SELECT requesting_user_id()" # 4. Confirm the user's JWT contains the expected claim (auth config in metadata) npx @insforge/cli metadata --json ``` ## Frequently paired with - [logs](logs.md) — `postgREST.logs` shows the actual RLS denial events; pair with policies to identify which rule fired - [metadata](metadata.md) — auth config determines which claim feeds `auth.uid()` / `requesting_user_id()` - [advisor](advisor.md) — security category often flags missing/overly-permissive RLS policies
SHA-256: fc69a3a31056dc5abc069784ba5155be9c2591b5792a8bcfe5314c72770b6794