Skip to content

Commit b67c008

Browse files
committed
docs(permissions): document the field-predicate 403 in the authorization layer table
Layer 6 (field-level security) now states the predicate guard: caller queries filtering/sorting/grouping/aggregating by a non-readable field are rejected (403 field_predicate_denied) rather than value-leaking through row presence; RLS-injected predicates are exempt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018m3GX7EMKNPDZuee152EKK
1 parent 999f2db commit b67c008

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

content/docs/permissions/authorization.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ site — the file you read when behavior surprises you.
4747
| 3 | **Object CRUD** | `allowRead/Create/Edit/Delete` (+ the destructive lifecycle class `allowTransfer/Restore/Purge`, gated ahead of the M2 operations — #1883) resolved across the caller's permission sets. | `packages/plugins/plugin-security/src/permission-evaluator.ts` `checkObjectPermission` | fail-closed 403 |
4848
| 4 | **OWD / sharing** | Org-wide default (`private` / `public_read` / `public_read_write` / `controlled_by_parent`), manual record shares, criteria sharing rules (owner-type rules are declared but seed-skipped — [not enforced](/docs/permissions/sharing-rules#owner-based-sharing-rules)), business-unit hierarchy widening (ADR-0057 D5: scope-depth hierarchy lives on `sys_business_unit`, not roles). | `packages/plugins/plugin-sharing/src/sharing-service.ts` + `sharing-rule-service.ts` | owner-only baseline |
4949
| 5 | **Row-level security** | CEL predicates (`using` read filter, `check` write post-image) compiled into the query. If **no** applicable policy compiles, the result is a deny-all sentinel (fail-closed); an uncompilable policy alongside compilable ones is excluded from the OR-union **with a logged warning** — exclusion can only narrow access, never widen it. Tenant isolation is a wildcard RLS rule AND-ed on top. | `packages/plugins/plugin-security/src/rls-compiler.ts` + `security-plugin.ts` | fail-closed |
50-
| 6 | **Field-level security** | Read mask (strip non-readable fields) + write deny per `fields` rules. | `packages/plugins/plugin-security/src/field-masker.ts` | see posture note below |
50+
| 6 | **Field-level security** | Read mask (strip non-readable fields) + write deny per `fields` rules. Caller queries that **filter, sort, group, or aggregate by** a non-readable field are rejected outright (HTTP 403, `field_predicate_denied`) — masking only the output would leave row presence as a value oracle. RLS-injected predicates are exempt (they run after the guard and may reference hidden fields like `owner_id`). | `packages/plugins/plugin-security/src/field-masker.ts` + `predicate-guard.ts` | fail-closed on predicates; see posture note below |
5151

5252
Two orthogonal identity-layer gates run before all of this: the ADR-0069
5353
**authentication-policy gate** (password expiry / enforced MFA blocks a gated

0 commit comments

Comments
 (0)