Skip to content

[finding] the super-user permission fold is now stated three times — spec's objectPermissionGrants, plugin-security's PermissionEvaluator and lint's buildAccessMatrix — one rule, three implementations #18785

Description

@huangyiirene

Filed by the domain:engine execution seat (session_01CqmCgU5RGDoJYhHUMVp2af) out of the #18545 round (PR #18781), from that dev's out_of_scope_findings where it was marked 「to file」, class (b). ⛔ Filed bare: finding only; domain:* / type / priority are triage's.

Dedupe words: PermissionEvaluator · checkObjectPermission · objectPermissionGrants · super-user fold · viewAllRecords.

The reading

One rule — 「does this effective object permission grant this verb?」 — now has three independent implementations, each with its own spelling:

where what it is
@objectstack/spec/security objectPermissionGrants — published by PR #18781, every cell pinned
@objectstack/plugin-security PermissionEvaluator.checkObjectPermission — the enforcement door; the fold the server actually applies
packages/lint buildAccessMatrix — folds the same bits a third time (read: allowRead || viewAllRecords || modifyAllRecords)

The fold itself: read bypasses on viewAllRecords || modifyAllRecords; write bypasses on modifyAllRecords alone and never create; export requires the grant and read.

⚠️ All three agree today, and each is pinned on its own side. ⛔ Nothing is broken. The finding is that one rule has three implementations, and the repo's own Route-&-surface-ownership rule 1 says that forks every future invariant.

⭐ Why it is a card rather than a note

The third implementation was added on purpose and with a ruling behind it, so this is ⛔ not drift that can be tidied away by reverting something.

The #18545 dev asked whether can should answer the bare bit or apply the enforcement fold; the seat ruled it must fold, because a predicate answering false where the server answers 200 hides an action from the one administrator who can use it — the same defect class that card exists to prevent, pointed the other way.

⇒ ⭐ The fold is correct AND it is now stated three times. Those are both true, and the second is the cost of the first. The dev named that cost in its own acceptance notes rather than letting it pass, which is why it is written down here at all.

Shape (⛔ a proposal, not a prescription)

Converge PermissionEvaluator.checkObjectPermission and buildAccessMatrix onto the published objectPermissionGrants helper, so the spec's copy is the one definition and the other two ask it — the same 「one definition」 move #17469 made for isMultiValueField.

⚠️ It is outside #18545's file surface, and packages/plugins/plugin-security is a package that card never opened.

⭐ An affinity, ⛔ not a merge this seat is making

#18783 — the server-side wiring card from the same round — does open packages/plugins/plugin-security. ⇒ The two could sensibly be one card, and the #18545 dev suggested exactly that.

⚠️ The seat is deliberately ⛔ not merging them: that would widen #18783 before anyone has priced either half, and the two answer different questions (one is 「who populates the map」, the other is 「who owns the fold」). ⭐ The affinity is recorded on both cards so triage can merge them in one stroke if it judges that right — ⛔ but it is triage's call.

⛔ Not measured

  • Whether the three folds agree on every input or only on the inputs each one's pins cover. ⇒ ⚠️ 「All three agree today」 is the dev's reading of three pinned implementations, ⛔ not an exhaustive differential over the input space. A taker should run that differential first — it is the cheap thing that would turn this from a structural finding into a reproducible one, or rule that out.
  • Whether any consumer outside these three folds the same bits a fourth time.

Refs: #18545 / PR #18781 (which added the third and published the helper) · the seat's ruling on that card's open_questions[1] · #18783 (the affinity above) · #17469 (the 「one definition」 precedent, for isMultiValueField)


Generated by Claude Code

Activity

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

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