Repository navigation
Description
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)
- (a)
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). - (b)
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 @ 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_defaultships a wildcardtenant_isolationRLS (organization_id == current_user.organization_id). Any row whoseorganization_idis 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:falseby itself drops the wildcard RLS, andmember_default's'*': allowReadthen 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_isolationRLS policy (organization_id = current_user.organization_id) shipped with the defaultmember_default/viewer_readonlypermission 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:
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 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).
Activity
os-zhuang commentedon Aug 10, 2026
Triage:
pm:queue+domain:identity+target:v17.defaultPermissionSets. Both premises re-verified onorigin/main@3e8e669:skills/objectstack-data/SKILL.mdstill asserts the wildcardtenant_isolationRLS as current fact and warns about amember_default'*': allowReadleak that cannot happen (the callout block is live), andpackages/plugins/plugin-security/README.md:51still describes the pre-ADR-0095 probe-and-strip mechanism as the plugin's own behaviour.skills/**⇒ devx territory,plugin-security/README.md⇒ identity), split cost exceeds benefit for two prose edits sharing one premise set — routeddomain:identityper the family precedent (member_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, same premises, mixed file face, identity lane) so the family stays in one lane; treat as the rule-4 cross-domain exception: claim comment should declare the full two-file face, and the SKILL.md edit must re-runcheck:skill-frame-sync/check:doc-authoringas the body notes.target:v17: siblingmember_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 carries it, and the four-class check lands the same way here — this is the sharper surface of the same defect (a PUBLISHED customer skill whose security guidance builds a recommendation on a hazard that no longer exists; class ②/④: shipped guidance mis-describes the security model). Obligation follows the work per the split rule.member_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 / PR fix(qa,platform-objects,docs): re-premise member_default's removed wildcard and replace two vacuous D7 denial cases (#6964) #7149 is in flight but its dispatched file face (platform-objects, qa/dogfood, permissions doc) is disjoint from these two files by construction — noBlocked-by:needed; the implementer should still base on the post-fix(qa,platform-objects,docs): re-premise member_default's removed wildcard and replace two vacuous D7 denial cases (#6964) #7149 ref to pick up any shared-prose conventions it lands.member_default wildcard) — exactlymember_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 + this card; the filer's own checked-and-excluded list (approvals false positive, historical test comments, changesets) is thorough and stands.viewer_readonlystill ships atenant_isolationpolicy (README names it alongsidemember_default;member_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 only measuredmember_default) — the implementer should measure it in the same pass and file separately if it opens a third surface.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 10, 2026
Claim — identity-lane PM seat (#6022), session
session_01BM1tNf5U3nEbHKR4fo5qVQ. Dispatching to anos-devsubagent now.claude/issue-7151-published-prose-expired-premises../objectstack-issue-7151(dedicated per-task worktree; never the shared checkout)domain:identity+target:v17— labels untouched (single-producer rule; graded and routed by triage 01:22Z, which recorded the cross-domain split rationale)pm:queue→pm:dispatched. Thread re-read before claiming: one comment, the triage grading; no dev claim, no competing session ID.target:v17and in this lane, so it goes first under the maintainer's standing instruction.Serial constraints cleared: the sibling #6964 → PR #7149 is already enqueued (
added_to_merge_queue01:27:34Z) and its file face is disjoint from this one — #7149 coversplatform-objects,qa/dogfoodandcontent/docs/permissions/index.mdx; this card coversskills/objectstack-data/SKILL.mdandpackages/plugins/plugin-security/README.md, which #7149 explicitly did not touch. No overlap, no wait needed.Carried to the claimant:
member_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's and must stay separated: (a)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; (b)member_defaultships a wildcardtenant_isolationRLS — retired by ADR-0095 D1 in favour of the Layer 0 tenant wall. Both were re-measured by the filer against the real importeddefaultPermissionSets; re-measure again at your own branch point.skills/objectstack-data/SKILL.mdis the sharper site and needs the most care: it is published customer guidance, and it does not merely mention the wildcard — it builds apackages/plugins/plugin-security/README.md:51describes the pre-ADR-0095 probe-and-strip mechanism as the plugin's own current behaviour.viewer_readonlymay be worth checking in the same pass for whether it still carries that policy. Measure it; report the reading either way.⛔ Boundaries: nothing under
content/docs/releases/; do not "correct"CHANGELOG.mdfiles orreleases/history rows — they are correctly frozen historical records. Do not redo #6964/PR #7149's file face.If a claim comment with a different session ID appears above this one, that claim wins by timestamp and this seat stands down.
Generated by Claude Code
docs(plugin-security,skills): re-premise member_default's removed wil…