Skip to content

member_default's removed wildcard is still named as live fact in platform-objects, qa/dogfood and the permissions doc — the #6842 family, four packages further out #6964

Description

@os-zhuang

Found while implementing #6842 (PR #6958). Filed unassigned for the triage round to grade — most of it is observation-class prose drift, but Part 2 may not be, so it is deliberately left unlabeled rather than pre-graded as finding.

Context

#6842 framed the drift as "three separate pieces of prose went stale when #5491 (PR #6684) removed member_default's plain '*' wildcard grant" — the packages/spec JSDoc (fixed by #6696 / PR #6846) and two it() titles in plugin-security (fixed by PR #6958). Grepping the whole repo for member_default co-occurring with wildcard language shows the count was not three. At least six more live sites survive in three other packages plus the published docs, and they carry two distinct expired premises:

Measured on origin/main @ 68feaadd6, probing the real imported defaultPermissionSets: member_default.objects['*'] is undefined, and its object keys are 23 explicitly named sys_* tables plus sys_user_preference — no wildcard.

CHANGELOG files and content/docs/releases/ also match the grep and are correctly frozen: they are historical records of what was true then. They are not part of this finding.

Part 1 — stale prose in live source (observation-class)

packages/platform-objects/src/identity/sys-scim-provider.object.ts:40 — premise (a):

without it, the member_default wildcard '*': allowRead would expose SCIM connections to every authenticated user

packages/platform-objects/src/identity/sys-sso-provider.object.ts:38 — premise (b) — and :43 — premise (a):

without it, the member_default wildcard tenant_isolation RLS denies every row
without it, tenancy-disabled + member_default's '*': allowRead would leak providers to every authenticated user

packages/qa/dogfood/test/rls-multitenant.dogfood.test.ts:7 — premise (b):

member_default scopes rows with a wildcard tenant_isolation policy

These are load-bearing rationale comments, not decoration: each one justifies why a requiredPermissions gate exists by naming the exposure it prevents. A reader who checks the named exposure finds it absent and may conclude the gate is redundant. The gates are almost certainly still right for other reasons (ADR-0066 D3 admin-only config), but the stated reason has expired — the validate-security-posture.ts hazard #6628 cites, one layer out.

content/docs/permissions/index.mdx:47 states as current fact:

The default member_default set ships the wildcard tenant-isolation RLS (organization_id == current_user.organization_id)

which contradicts content/docs/releases/implementation-status.mdx:294 and :435 in the same repo, both of which say that policy "was retired". A published doc asserting the opposite of the status page is worth more than a naming fix.

Part 2 — two dogfood tests whose stated proof may now be vacuous

This is the part that may not be observation-class, and the reason this issue is unlabeled.

packages/qa/dogfood/test/showcase-default-profile.dogfood.test.ts:50 and packages/qa/dogfood/test/showcase-d7-default-profile.dogfood.test.ts:55 are both titled and NOT by the built-in member_default wildcard (...), and both carry the same inline rationale:

member_default has a wildcard grant → would be 200. The declared default grants only announcement → this object is denied, proving D7 is in effect.

The assertion is expect(r.status).not.toBe(200). Its evidential value rests entirely on the named counterfactual: the object is denied despite a baseline that would otherwise have allowed it. Since #5491 that baseline grants nothing on app objects at all, so a non-200 is now the trivially expected outcome whether or not the app's declared default profile is in force — which is the exact thing these tests exist to prove. If that reading is right, both tests still pass while no longer demonstrating D7, and the fixture would need replacing rather than re-wording (the #5046 "replace wholesale" disposition: the assertion keeps passing because nothing is produced, not because the logic is right).

Not verified by running them — the dogfood suite needs a live stack and this was out of scope for #6842's PR. The reading above is from the source and the measured array only, and it should be confirmed before being acted on. If it is wrong, Part 2 collapses into Part 1 and this is all prose.

Why it stayed silent

The same reason #6842 gives: nothing mechanically relates "prose names set X as having shape Y" to what defaultPermissionSets ships. PR #6958 adds a pin for that relation in plugin-security, but it deliberately watches only two surfaces (audience-anchors.test.ts and the describeHighPrivilegeBits JSDoc), because those were the two #6842 named. Its watchedSurfaces() is a one-line-per-surface list and any of the files above could be added to it — but whether the pin should grow a repo-wide surface, and whether platform-objects / qa should depend on plugin-security to get one, is a scoping decision for triage rather than something to assume.

Related: #6842 and PR #6958 (this issue's origin), #6696 / PR #6846 (the spec half), #5491 / PR #6684 (cause (a)), ADR-0095 D1 (cause (b)), #6628 (the pin idiom).


🤖 Generated with Claude Code

https://claude.ai/code/session_01BM1tNf5U3nEbHKR4fo5qVQ

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions