Skip to content

nav-object-ungranted prescribes gating the nav entry, but validateNavAccess never reads requiredPermissions / visible — one of its three remedies does not clear the finding #16065

Description

@os-warren

Observed by the domain:services seat while working #14453 (showcase permission gaps). Not touched there — different package, different defect class. Filed unassigned, no severity claimed.

What the rule tells the author

packages/lint/src/validate-nav-access.ts emits this hint with every finding:

Add "OBJECT" to a permission set's objects with allowRead: true (or viewAllRecords), gate the entry with requiredPermissions/visible if it is meant for admins only, or drop it.

Three remedies. The module doc-block says the same thing again in prose.

What the rule actually reads

collectNavExposures walks exactly four keys per nav item — type, objectName, id, children — and validateNavAccess then filters only on isPlatformProvidedObjectName, membership in stack.objects, and the read column of buildAccessMatrix. Neither requiredPermissions nor visible is read anywhere in the file.

So a nav entry gated exactly as prescribed keeps warning, forever.

Measured

Against the shipped rule (packages/lint/dist/index.js, tree at 53cbad9f7), on a synthetic stack with one ungranted object in nav, with both controls:

CONTROL ungated+ungranted (MUST be 1): 1 finding(s) -> nav-object-ungranted
CONTROL granted            (MUST be 0): 0 finding(s)
PROBE requiredPermissions             : 1 finding(s) -> nav-object-ungranted
PROBE visible:false                   : 1 finding(s) -> nav-object-ungranted

The negative control (granted ⇒ silent) and the positive control (ungranted ⇒ fires) both behave, so the two probe readings are about the gating keys and nothing else.

Why it is worth a card

The prescribed action is not merely ineffective at silencing the diagnostic — it is the one remedy an author reaches for when the entry is deliberately admin-only, which is exactly the case the hint invents it for. Following it costs an edit, changes what the app serves, and leaves the warning standing, with nothing saying why. The author's next move is to distrust the rule.

It also narrows the rule's real menu to two: grant, or drop the entry. On #14453 that was load-bearing — with gating unavailable, every one of the seven flagged objects had to be granted or removed from navigation, and there was no third disposition to weigh.

requiredPermissions on a navigation ITEM is a real, server-enforced gate (app.zod.ts: the item is stripped server-side for a caller lacking the capability), so the hint is not wrong about the platform — only about this rule. Note also that visible is separately reported as inert at runtime in #15135, which would make it a poor second half of the prescription even if the lint did honour it.

Shape of the work

Two readings, and they are not equivalent:

  • Honour the keys — skip an exposure whose item carries requiredPermissions (a capability gate this stack can see) and/or a statically-false visible. Note requiredPermissions gates on capabilities, not object grants, so "gated ⇒ genuinely reachable only by holders" needs deciding rather than assuming.
  • Correct the hint — drop the gating clause and say plainly that grant-or-drop are the two remedies that clear it.

Either is small; picking between them is a judgement about what the rule is asserting, which is why this is filed rather than patched.

Refs: #14453 (where it was measured) · #15135 (visible inert at runtime) · packages/lint/src/validate-nav-access.ts.

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