You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit bb5d739
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: content/docs/permissions/system-context.mdx
+8-7Lines changed: 8 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ the seed loader replaying package fixtures, a plugin's boot reconciler, a
10
10
service self-write, a migration.
11
11
12
12
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
14
14
distinct sites across 20 packages**, and knowing three of those behaviours gives
15
15
no hint that the other hundred-and-four exist. Every documented app-side bug
16
16
traced to `isSystem` had the same shape — the metadata was complete and correct,
@@ -138,11 +138,12 @@ that silently does not happen.
138
138
| 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`|
139
139
| 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`|
140
140
| 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`|
141
142
| 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`|
142
143
143
144
### 3. Sharing (`plugin-sharing`)
144
145
145
-
The largest single consumer — **17 of the 123 sites**.
146
+
The largest single consumer — **17 of the 124 sites**.
146
147
147
148
| # | Behaviour when `isSystem`| What you get / what you lose | Anchor |
148
149
|:--|:---|:---|:---|
@@ -285,7 +286,7 @@ Ownership injection, `readonly` bypass and sharing materialisation are
285
286
independent decisions, and a seed loader plausibly wants the first two but not
286
287
the third. The concept is nevertheless **staying as one boolean**:
287
288
288
-
-**Shipped semantics.**`isSystem` is a published contract with 123 read sites
289
+
-**Shipped semantics.**`isSystem` is a published contract with 124 read sites
289
290
in 20 packages. Splitting it is a breaking contract change across all of them.
290
291
(The ruling was taken when the census read 80 sites in 18 packages; the count
291
292
has grown, which strengthens rather than weakens the argument.)
@@ -359,16 +360,16 @@ still holds equal to the census on every pull request:
359
360
| Appearances of the bare identifier `isSystem` in non-test sources | 813 | — |
360
361
| — parsed as a declaration | 28 | ✅ |
361
362
| — 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| ✅ |
363
364
| — parsed in some other syntactic position (a local, a cast, a conditional) | 9 | ✅ |
364
365
| — the remainder: text inside comments and string literals | 358 | — |
365
366
| 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| ✅ |
368
369
| — carry the flag onward only (rows 62–64 above) | 3 | ✅ |
369
370
| Packages containing at least one elevation read |**20**| ✅ |
370
371
| 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| ✅ |
372
373
| — of those files, the ones holding more than one read in one symbol | 8 | ✅ |
373
374
374
375
The six rows marked — are a **dated decomposition, not a live claim**: they were
0 commit comments