Found while implementing #8468, sweeping every platform object with the real lint rule. Filed unassigned and deliberately separate from #8554 (the five clean inheritors), because the ruling of 2026-08-13 says an instance goes straight to the queue unless it carries a genuine semantic argument for an installation-wide namespace, which must then be stated explicitly. This one does, so it is stated below rather than queued.
The declaration
packages/platform-objects/src/system/sys-setting.object.ts:
indexes: [// Primary lookup path: (namespace, key, scope, user_id?) is what{fields: ['namespace','key','scope','user_id'],unique: true},
...
]Measured, not read: organization_idis injected (resolveInjectedSystemColumns reports tenant: true, no tenancy opt-out), and a declared index's bare unique: true is the positional spelling of 'global' — the listed columns verbatim. So the physical key is installation-wide on a tenant-scoped object, and organization_id is not part of it.
Why it is not simply a sixth inheritor
managedBy: 'engine-owned', and the object's header comment says the Setup grid is "a diagnostic surface only; all writes flow through SettingsService.set() so the resolver stays the single source of truth." So the rows are not admin-authored in the sense the ruling used, and the settings resolver may legitimately want one installation-wide row per (namespace, key, scope, user_id) — a platform default that every organization resolves against.
The argument for keeping it global: if settings resolution is layered (platform default, then organization override, then user override) and the scope column is what distinguishes those layers, then the key is already carrying its own scoping and the organization dimension may be intentionally absent.
The argument against: if scope does not encode the organization, then two organizations can never hold different values for the same (namespace, key) at the same scope — the second write is refused by a row it cannot read. That is both a cross-tenant oracle and a hard functional ceiling on per-organization configuration, which is a capability a multi-tenant platform is normally expected to have.
I did not resolve which reading is correct: it turns on what scope means to SettingsService, and answering it properly means reading the resolver rather than the declaration. That is the work this card is asking for, and it is why I am not asserting a defect.
What to do
Read SettingsService's resolution order and the scope vocabulary first. Then either:
Either way the end state should not be a positional default. Whoever takes it should run the live 409/201 probe first, per the ruling's discipline on #8468.
Also worth a look, same sweep, not asserted
These carry a bare declared unique: true on tenant-scoped objects but are plausibly intentional (identifiers/tokens that are meant to be globally unique, or composites of already-unique ids). Listing them so a future sweep does not have to re-derive the triage:
sys_job['name'] — engine-owned; job names are probably platform-defined.sys_notification['dedup_key'], sys_http_delivery['source', 'dedup_key'] — dedup keys likely already embed their scope.sys_audience_binding_suggestion['package_id', 'permission_set_name', 'anchor'] — package-scoped suggestion rows.sys_notification_subscription['topic', 'principal'] — the one I am least sure about in this group.sys_share_link['token'], sys_presence['session_id'] — tokens/ids, legitimately global.
Objects that already list organization_id in their index fields (sys_metadata, sys_metadata_history, sys_view_definition, sys_user_permission_set, sys_user_position, sys_business_unit) are the ADR-0120 S6 hand-written composite and are valid indefinitely — not findings.
Related
Found by session session_012WMpuAfA2KSdDjGF6tm1bH.
Generated by Claude Code
Found while implementing #8468, sweeping every platform object with the real lint rule. Filed unassigned and deliberately separate from #8554 (the five clean inheritors), because the ruling of 2026-08-13 says an instance goes straight to the queue unless it carries a genuine semantic argument for an installation-wide namespace, which must then be stated explicitly. This one does, so it is stated below rather than queued.
The declaration
packages/platform-objects/src/system/sys-setting.object.ts:Measured, not read:
organization_idis injected (resolveInjectedSystemColumnsreportstenant: true, notenancyopt-out), and a declared index's bareunique: trueis the positional spelling of'global'— the listed columns verbatim. So the physical key is installation-wide on a tenant-scoped object, andorganization_idis not part of it.Why it is not simply a sixth inheritor
managedBy: 'engine-owned', and the object's header comment says the Setup grid is "a diagnostic surface only; all writes flow throughSettingsService.set()so the resolver stays the single source of truth." So the rows are not admin-authored in the sense the ruling used, and the settings resolver may legitimately want one installation-wide row per(namespace, key, scope, user_id)— a platform default that every organization resolves against.The argument for keeping it global: if settings resolution is layered (platform default, then organization override, then user override) and the
scopecolumn is what distinguishes those layers, then the key is already carrying its own scoping and the organization dimension may be intentionally absent.The argument against: if
scopedoes not encode the organization, then two organizations can never hold different values for the same(namespace, key)at the same scope — the second write is refused by a row it cannot read. That is both a cross-tenant oracle and a hard functional ceiling on per-organization configuration, which is a capability a multi-tenant platform is normally expected to have.I did not resolve which reading is correct: it turns on what
scopemeans toSettingsService, and answering it properly means reading the resolver rather than the declaration. That is the work this card is asking for, and it is why I am not asserting a defect.What to do
Read
SettingsService's resolution order and thescopevocabulary first. Then either:scopealready encodes tenancy → spell the indexunique: 'global'explicitly and say why in a comment, so the next sweep stops re-raising it (this is what ADR-0120 wants in either direction — the current bare spelling states no scope at all); orscopedoes not encode tenancy → this is a sixth instance of the tenant-scoped objects get GLOBAL unique indexes: 409-vs-201 enumerates other tenants' values, and a user's preferences silently stop persisting in their second org #8323 class, and it inherits the 2026-08-13 ruling like the rest: respell to'organization', reusing thereplace_unique_indexarm.Either way the end state should not be a positional default. Whoever takes it should run the live 409/201 probe first, per the ruling's discipline on #8468.
Also worth a look, same sweep, not asserted
These carry a bare declared
unique: trueon tenant-scoped objects but are plausibly intentional (identifiers/tokens that are meant to be globally unique, or composites of already-unique ids). Listing them so a future sweep does not have to re-derive the triage:sys_job['name']— engine-owned; job names are probably platform-defined.sys_notification['dedup_key'],sys_http_delivery['source', 'dedup_key']— dedup keys likely already embed their scope.sys_audience_binding_suggestion['package_id', 'permission_set_name', 'anchor']— package-scoped suggestion rows.sys_notification_subscription['topic', 'principal']— the one I am least sure about in this group.sys_share_link['token'],sys_presence['session_id']— tokens/ids, legitimately global.Objects that already list
organization_idin their index fields (sys_metadata,sys_metadata_history,sys_view_definition,sys_user_permission_set,sys_user_position,sys_business_unit) are the ADR-0120 S6 hand-written composite and are valid indefinitely — not findings.Related
sys_position.nameis the third instance of the #8323 class: an admin-authored name on a tenant-scoped RBAC object carries an installation-wide unique index #8468 / fix(platform-objects,plugin-security,driver-sql): scope sys_user_preference and sys_capability uniqueness per organization (#8323) #8461 / tenant-scoped objects get GLOBAL unique indexes: 409-vs-201 enumerates other tenants' values, and a user's preferences silently stop persisting in their second org #8323 — the class and its ruling.Found by session
session_012WMpuAfA2KSdDjGF6tm1bH.Generated by Claude Code