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
The driver-level tenant scope (DriverOptions.tenantId → applyTenantScope) does not honour the deployment's platformGlobalObjects carve-out (#12699): an exempted object stays walled at the driver while Layer 0 composes nothing #15831
⛔ Ungraded and unrouted — domain:*, priority and type are triage's. Filed unassigned by the domain:engine execution seat while delivering #15813, as a sub-issue of #15212 (ADR-0131 C8: one tenant scope threaded to Layer 0 AND every driver) — this is that divergence, measured today.
Seeded two rows under a system context, one per organization. Ground truth past every scope (raw knex): ['org_acme', 'org_globex'].
read
context
rows seen
engine.find on the exempted object
system, tenantId: 'org_acme'
['org_acme']
engine.find on the exempted object
member of org_acme
['org_acme']
engine.update(multi) on the exempted object
member of org_acme
matched 1
plugin-security Layer 0 verdict for the same operation
member of org_acme
{ kind: 'none' } — the wall composed nothing (the #12699 contract)
So the #12699 declaration is honoured by plugin-security's Layer 0 (getReadFilter → undefined, pinned in deployment-platform-global-exemption.test.ts) and NOT by the driver leg: the engine still threads the caller's tenantId as DriverOptions.tenantId for any object carrying the injected organization_id column, and the SQL driver scopes on it. The exempted object is walled end to end after all — by the leg the declaration never reaches.
Why it matters, and why it is not this seat's to fix
Failure direction today is the SAFE one (over-walling: the exempted object is narrower than declared), so nothing leaks; but a deployment that declared the carve-out to make a platform-global object readable across organizations does not get what it declared on the SQL driver.
Dedup: repo-scoped REST list of 590 open issues + local grep — platformGlobalObjects hits #15813 and #15207 (C6) only; applyTenantScope hits #15212 / #15195 / #14946, none of which names the carve-out. Related: #12699 (the declaration) · #15207 (C6, #12699 made total) · #15212 (C8, parent) · #15813 (where it was measured).
⛔ Ungraded and unrouted —
domain:*, priority and type are triage's. Filed unassigned by thedomain:engineexecution seat while delivering #15813, as a sub-issue of #15212 (ADR-0131 C8: one tenant scope threaded to Layer 0 AND every driver) — this is that divergence, measured today.Measured (real
ObjectQL+SqlDriversqlite + realSecurityPlugin, postureisolated,org-scopingdeclaringplatformGlobalObjects: ['qa_widget_registry'])Seeded two rows under a system context, one per organization. Ground truth past every scope (raw knex):
['org_acme', 'org_globex'].engine.findon the exempted objecttenantId: 'org_acme'['org_acme']engine.findon the exempted objectorg_acme['org_acme']engine.update(multi)on the exempted objectorg_acmeorg_acme{ kind: 'none' }— the wall composed nothing (the #12699 contract)So the #12699 declaration is honoured by plugin-security's Layer 0 (
getReadFilter→undefined, pinned indeployment-platform-global-exemption.test.ts) and NOT by the driver leg: the engine still threads the caller'stenantIdasDriverOptions.tenantIdfor any object carrying the injectedorganization_idcolumn, and the SQL driver scopes on it. The exempted object is walled end to end after all — by the leg the declaration never reaches.Why it matters, and why it is not this seat's to fix
security-plugin.ts,getObjectSecurityMeta) promises a deployment-exempted object "behaves exactly as if it had declaredtenancy: { enabled: false }itself" — true on every plugin-security path, false at the driver. Two walls, two answers, for one object on one deployment: exactly the mirror ADR-0131 D8 (「一道谓词,算一次」) retires, and the C8 card (feat(spec,drivers,objectql,plugin-security):organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212) is where the one computed scope reaches the driver.plugin-securityrecords its Layer 0 verdict on the operation, and the bulk-event publish site reads it instead of re-deriving the wall #15813 by the ruling's own boundary (the producer reads the recorded verdict; it composes nothing) — the seam's end-to-end pin (tenant-layer0-verdict-end-to-end.test.ts) records this measurement (matchedis 1, not 2) rather than asserting a driver behaviour that card does not own.Re-check
Dedup: repo-scoped REST list of 590 open issues + local grep —
platformGlobalObjectshits #15813 and #15207 (C6) only;applyTenantScopehits #15212 / #15195 / #14946, none of which names the carve-out. Related: #12699 (the declaration) · #15207 (C6,#12699 made total) · #15212 (C8, parent) · #15813 (where it was measured).Generated by Claude Code