Found while implementing #6964 (PR #7149), by sweeping the same two expired premises across their whole consumption radius rather than only the packages that card named. Filed unassigned and unlabeled — deliberately not pre-graded, for the same reason #6964's filer declined to pre-grade: one of these two is ordinary prose drift and the other is published customer-facing security guidance, and that difference is triage's call, not the filer's.
The two premises (identical to #6964)
Both re-measured on origin/main @ 3e8e669c0 against the real imported defaultPermissionSets: member_default.objects['*'] is undefined, and its rowLevelSecurity carries no tenant_isolation entry — only owner_only_writes / owner_only_deletes (update/delete) and the *_self per-object carve-outs.
#6964 named platform-objects, qa/dogfood and content/docs/permissions/index.mdx, and its dispatch drew that file face explicitly. These two sites are outside it and were not fixed by PR #7149.
1. skills/objectstack-data/SKILL.md — a PUBLISHED customer skill, both premises
This is the sharper of the two: not an internal comment but shipped guidance, and it does not merely mention the wildcard — it builds a recommendation on it.
:764 asserts premise (b) as current:
- The default
member_default ships a wildcard tenant_isolation RLS (organization_id == current_user.organization_id). Any row whose organization_id is null or absent (common for adapter-written rows that never get the tenant stamp) is denied — the list renders empty.
:781 asserts premise (a), inside a warning callout:
⚠️ Don't use either flag alone. tenancy.enabled:false by itself drops the wildcard RLS, and member_default's '*': allowRead then leaks every row to all authenticated users.
The recommended recipe itself (tenancy: { enabled: false } + requiredPermissions) is still correct, so this is not a wrong instruction — but every reason given for it has expired, and one of them names a leak that cannot happen. A reader who checks the stated hazard finds it absent and may drop half the recipe. The viewAllRecords sentence at :768 is also now imprecise in the same region: under ADR-0095 W2 the superuser bit alone no longer crosses the tenant wall at all — that takes a true PLATFORM_ADMIN (superuser bit and a platform-exclusive capability), which is a stricter rule than "posture-gated".
Note this file is a skills/ artifact, so it is in scope for the skill-frame gates; any fix should re-run check:skill-frame-sync / check:doc-authoring.
2. packages/plugins/plugin-security/README.md:51 — premise (b)
- Service present → keeps the wildcard
tenant_isolation RLS policy (organization_id = current_user.organization_id) shipped with the default member_default / viewer_readonly permission sets.
- Service absent → strips those wildcard policies so single-tenant deployments aren't filtered to zero rows.
The described mechanism is the pre-ADR-0095 one. Tenant scope is now Layer 0, and it is inert under the single posture by construction (computeTenantLayer0Filter returns null when postureEnforcesWall is false) rather than by the org-scoping probe stripping policies. This is the plugin's own README describing its own retired behaviour.
Worth checking in the same pass whether viewer_readonly still ships such a policy — the sentence names it alongside member_default, and #6964 only ever measured member_default.
Verified correct — explicitly NOT part of this finding
These matched the same grep and were checked individually:
Why it stayed silent
Same reason #6842 and #6964 give, and the reason this keeps recurring: nothing mechanically relates "prose names set X as having shape Y" to what defaultPermissionSets actually ships. The #6958 pin closes that loop for two named surfaces only. If triage ever does want the pin to grow a repo-wide surface, these two files are the concrete argument for it — this is now the third filing in the same family.
Related: #6964 / PR #7149 (this issue's origin), #6842 / PR #6958, #6696 / PR #6846, #5491 / PR #6684 (cause (a)), ADR-0095 D1 (cause (b)), #6628 (the pin idiom).
Found while implementing #6964 (PR #7149), by sweeping the same two expired premises across their whole consumption radius rather than only the packages that card named. Filed unassigned and unlabeled — deliberately not pre-graded, for the same reason #6964's filer declined to pre-grade: one of these two is ordinary prose drift and the other is published customer-facing security guidance, and that difference is triage's call, not the filer's.
The two premises (identical to #6964)
member_defaulthas a'*'object grant — removed bymember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 (PR fix(plugin-security): enforce both declared write-wideners; the platform baseline becomes explicit-allow (#5492, #5491) #6684).member_defaultships a wildcardtenant_isolationRLS policy — retired by ADR-0095 D1 in favour of the Layer 0 tenant wall (plugin-security/tenant-layer.ts).Both re-measured on
origin/main@3e8e669c0against the real importeddefaultPermissionSets:member_default.objects['*']isundefined, and itsrowLevelSecuritycarries notenant_isolationentry — onlyowner_only_writes/owner_only_deletes(update/delete) and the*_selfper-object carve-outs.#6964 named
platform-objects,qa/dogfoodandcontent/docs/permissions/index.mdx, and its dispatch drew that file face explicitly. These two sites are outside it and were not fixed by PR #7149.1.
skills/objectstack-data/SKILL.md— a PUBLISHED customer skill, both premisesThis is the sharper of the two: not an internal comment but shipped guidance, and it does not merely mention the wildcard — it builds a recommendation on it.
:764asserts premise (b) as current::781asserts premise (a), inside a warning callout:The recommended recipe itself (
tenancy: { enabled: false }+requiredPermissions) is still correct, so this is not a wrong instruction — but every reason given for it has expired, and one of them names a leak that cannot happen. A reader who checks the stated hazard finds it absent and may drop half the recipe. TheviewAllRecordssentence at:768is also now imprecise in the same region: under ADR-0095 W2 the superuser bit alone no longer crosses the tenant wall at all — that takes a truePLATFORM_ADMIN(superuser bit and a platform-exclusive capability), which is a stricter rule than "posture-gated".Note this file is a
skills/artifact, so it is in scope for the skill-frame gates; any fix should re-runcheck:skill-frame-sync/check:doc-authoring.2.
packages/plugins/plugin-security/README.md:51— premise (b)The described mechanism is the pre-ADR-0095 one. Tenant scope is now Layer 0, and it is inert under the
singleposture by construction (computeTenantLayer0FilterreturnsnullwhenpostureEnforcesWallis false) rather than by the org-scoping probe stripping policies. This is the plugin's own README describing its own retired behaviour.Worth checking in the same pass whether
viewer_readonlystill ships such a policy — the sentence names it alongsidemember_default, and #6964 only ever measuredmember_default.Verified correct — explicitly NOT part of this finding
These matched the same grep and were checked individually:
content/docs/permissions/access-recipes.mdx:65— already says "tenant isolation is now the Layer 0 tenant wall intenant-layer.ts, ADR-0095 D1". Correct.packages/cli/src/commands/serve-verify-security-parity.contract.test.ts:18— "It stayed invisible untilmember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 removedmember_default's'*'wildcard". Correctly historical.packages/plugins/plugin-approvals/src/lifecycle-hooks.ts:423— "member_default's wildcardcreated_by == current_user.idRLS" is a grep false positive: "wildcard" there means the policy'sobject: '*', andowner_only_writes/owner_only_deletesstill ship exactly that. Do not "fix" it.CHANGELOG.mdfiles,content/docs/releases/, and the two pending.changeset/*.mdentries — correctly frozen or correctly descriptive.packages/plugins/plugin-security/audience-anchor-set-claims.pin.test.ts— the test(plugin-security): stop namingmember_defaultas the plain-wildcard shape, and pin the relation (#6842) #6958 pin, correct; itswatchedSurfaces()deliberately watches only two surfaces. Whether it should grow more is the open scoping questionmember_default's removed wildcard is still named as live fact inplatform-objects,qa/dogfoodand the permissions doc — the #6842 family, four packages further out #6964 already raised and triage has not ruled on.Why it stayed silent
Same reason #6842 and #6964 give, and the reason this keeps recurring: nothing mechanically relates "prose names set X as having shape Y" to what
defaultPermissionSetsactually ships. The #6958 pin closes that loop for two named surfaces only. If triage ever does want the pin to grow a repo-wide surface, these two files are the concrete argument for it — this is now the third filing in the same family.Related: #6964 / PR #7149 (this issue's origin), #6842 / PR #6958, #6696 / PR #6846, #5491 / PR #6684 (cause (a)), ADR-0095 D1 (cause (b)), #6628 (the pin idiom).