Skip to content

Commit bb5d739

Browse files
committed
docs(permissions): census row for the header read door's system stand-down; counts regenerated (#22519)
Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
1 parent e0775cb commit bb5d739

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

‎content/docs/permissions/system-context.mdx‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ the seed loader replaying package fixtures, a plugin's boot reconciler, a
1010
service self-write, a migration.
1111

1212
This page is **the authority** for what that flag actually does. It exists
13-
because the flag is not one concept: it is a single boolean read at **123
13+
because the flag is not one concept: it is a single boolean read at **124
1414
distinct sites across 20 packages**, and knowing three of those behaviours gives
1515
no hint that the other hundred-and-four exist. Every documented app-side bug
1616
traced to `isSystem` had the same shape — the metadata was complete and correct,
@@ -138,11 +138,12 @@ that silently does not happen.
138138
| 28 | Dependent-count disclosure on a blocked delete | objectql | Get: the count of blocking children. Nothing was elevated past the caller, so nothing is withheld | `packages/objectql/src/engine.ts#dependentCountIsDisclosable` |
139139
| 29 | Reference-cleanup log attributes the write to `'system'` | objectql | Get: an honest actor label instead of `anonymous` when the context carries neither `userId` nor `actor` | `packages/objectql/src/engine.ts#recordReferenceCheckElevation` |
140140
| 29b | A traversing validation rule's related read skips the **caller's bounds** | objectql | Get: no row bound from the caller's own read on a related object no organization wall scopes, and a related read even with no organization under a walled posture (a `tenantId` on the context still scopes it). Every caller that is not system is held to both | `packages/objectql/src/engine.ts#resolvePredicateRelated` |
141+
| 29c | A detail write's master-detail header read asks **no read door** | objectql | Get: the write binds the header a parent-scoped `requiredWhen` / `readonlyWhen` reads as `parent` from the header's stored row whoever can read it, as before. Every caller that is not system meets its own read door first: a header that read does not return answers as a header that exists nowhere — an unbound `parent`, and `reference_not_found` on the reference check (which a system caller's write skips altogether) | `packages/objectql/src/engine.ts#masterDetailHeadersCallerReads` |
141142
| 30 | **Bulk data event `organizationId` OMITTED** — the batch is published "not asserted" | plugin-security | Get: nothing — the `data.records.*` event still publishes. Lose: the per-organization attribution: this exit is taken before the security middleware composes any tenant wall, so it records no Layer 0 verdict on the operation (`OperationContext.tenantLayer0Verdict`, #15813), and the engine's bulk producer — which reads that recorded verdict and nothing else — omits the key rather than filling it from the caller's `tenantId`; a tenant-scoped consumer then does not deliver the event inside an organization wall (#15225) | `packages/plugins/plugin-security/src/security-plugin.ts#start` |
142143

143144
### 3. Sharing (`plugin-sharing`)
144145

145-
The largest single consumer — **17 of the 123 sites**.
146+
The largest single consumer — **17 of the 124 sites**.
146147

147148
| # | Behaviour when `isSystem` | What you get / what you lose | Anchor |
148149
|:--|:---|:---|:---|
@@ -285,7 +286,7 @@ Ownership injection, `readonly` bypass and sharing materialisation are
285286
independent decisions, and a seed loader plausibly wants the first two but not
286287
the third. The concept is nevertheless **staying as one boolean**:
287288

288-
- **Shipped semantics.** `isSystem` is a published contract with 123 read sites
289+
- **Shipped semantics.** `isSystem` is a published contract with 124 read sites
289290
in 20 packages. Splitting it is a breaking contract change across all of them.
290291
(The ruling was taken when the census read 80 sites in 18 packages; the count
291292
has grown, which strengthens rather than weakens the argument.)
@@ -359,16 +360,16 @@ still holds equal to the census on every pull request:
359360
| Appearances of the bare identifier `isSystem` in non-test sources | 813 | — |
360361
| — parsed as a declaration | 28 | ✅ |
361362
| — parsed as an object-literal / type key (producers and option objects) | 310 | — |
362-
| — parsed as a property **read** | 129 | ✅ |
363+
| — parsed as a property **read** | 130 | ✅ |
363364
| — parsed in some other syntactic position (a local, a cast, a conditional) | 9 | ✅ |
364365
| — the remainder: text inside comments and string literals | 358 | — |
365366
| Of those reads: reads of one of the unrelated metadata fields | 6 | ✅ |
366-
| Of those reads: reads of `ExecutionContext.isSystem` | **123** | ✅ |
367-
| — behaviour-bearing (rows 1–61 above) | 120 | ✅ |
367+
| Of those reads: reads of `ExecutionContext.isSystem` | **124** | ✅ |
368+
| — behaviour-bearing (rows 1–61 above) | 121 | ✅ |
368369
| — carry the flag onward only (rows 62–64 above) | 3 | ✅ |
369370
| Packages containing at least one elevation read | **20** | ✅ |
370371
| Files containing at least one elevation read | 57 | ✅ |
371-
| — the distinct symbols those reads live in — what this page anchors | 105 | ✅ |
372+
| — the distinct symbols those reads live in — what this page anchors | 106 | ✅ |
372373
| — of those files, the ones holding more than one read in one symbol | 8 | ✅ |
373374

374375
The six rows marked — are a **dated decomposition, not a live claim**: they were

0 commit comments

Comments
 (0)