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

Closed

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

Activity

  1. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    Collaborator

    Triage (maintainer-authorized one-off pass, 2026-08-09 — registered on #6015): graded finding, routed domain:identity (the drift's subject is member_default/permission-set shape; the sibling fixes #6842/#6696 ran in the identity lane).


    Generated by Claude Code

  2. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    ContributorAuthor

    Finding-triage ruling: Promote — finding to pm:queue.

    member_default's removed wildcard is still asserted as live fact at six-plus named locations — including the published permissions doc (permissions/index.mdx tenant-isolation sentence), a security-semantics page contradicting shipped behavior today. Part 1 (named-location prose sweep) is mechanically dispatchable; Part 2 (verify the two dogfood tests aren't vacuous) rides it, per the 08-09 grading.

    Release-board four-class check: hits class ④ — published security docs that would need a release-notes apology. target:v17 added.

    Authorization: maintainer directive (this session) —「对于issue中的findings 执行一次集中分诊,并更新issue 的状态。」Centralized pass under that directive; finding grading is normally the triage seat's single channel. Round: objectstack#4949 finding-triage, 2026-08-10.
    Session: 01JaVVMrSxt7Tgi1uwEuDtH7


    Generated by Claude Code

  3. self-assigned this
    on Aug 10, 2026
  4. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    ContributorAuthor

    Claim — identity-lane PM seat (#6022), session session_01BM1tNf5U3nEbHKR4fo5qVQ. Dispatching to an os-dev subagent now.

    • Branch: claude/issue-6964-member-default-wildcard-prose
    • Worktree: ../objectstack-issue-6964 (dedicated per-task worktree; never the shared checkout)
    • Domain / board: domain:identity + target:v17 — labels untouched (single-producer rule; promoted and boarded by the finding-triage round 00:12Z)
    • Status: pm:queue → pm:dispatched. Thread re-read before claiming: two comments, both triage grading, no dev claim and no competing session ID.
    • Priority: this is the identity lane's only target:v17 card, and the maintainer's standing instruction is v17 first.

    Serial constraints cleared: the lane has nothing in flight. The sibling that covered the two plugin-security surfaces (#6842 → PR #6958) landed 07:01Z and this card is explicitly the non-overlapping remainder, four packages further out. plugin-security is not in this card's file face.

    Scope carried to the claimant, exactly as the triage grading split it:

    ⛔ Boundaries:

    Note for the claimant: the repo carries a dogfood-verification skill for booting a real example app and driving it — Part 2's answer needs a live stack, and "I could not run it, here is why" is an acceptable report only if you say what you tried. A green suite is not evidence here; that is precisely the failure mode this card is about.

    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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions