Skip to content

fix(lint): nav-object-ungranted stops prescribing a gate it cannot honour - #16436

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-16065-nav-object-ungranted-hint
Sep 7, 2026
Merged

fix(lint): nav-object-ungranted stops prescribing a gate it cannot honour#16436
baozhoutao merged 1 commit into
mainfrom
claude/issue-16065-nav-object-ungranted-hint

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #16065

Ruling (director seat, decision batch #59; maintainer verbatim 「16063 c, 其他同意」 — this card adopted as recommended, option B):

nav-object-ungranted keeps asserting exactly what it can prove: an object reachable from navigation must be granted, or the entry dropped. The hint and the module doc-block lose the "gate the entry with requiredPermissions/visible" clause. The rule does not start honouring those keys: requiredPermissions gates on capabilities, not object grants, so a holder can still lack read on the object, and visible is inert at runtime (card 15135) — honouring either would silence the rule on a genuinely reachable ungranted object.

What changed

  • packages/lint/src/validate-nav-access.ts: the nav-object-ungranted hint no longer prescribes gating the entry with requiredPermissions/visible — that never cleared the finding, because the rule never reads either key (grep confirmed each word appeared exactly once in the whole file, both inside the old hint string; the module doc-block did not separately restate the three-remedy prose). The hint now names only the two remedies the rule can prove — grant read on the object in a permission set (allowRead: true or viewAllRecords), or drop the nav entry — plus one sentence on why gating doesn't count. The doc-block gained the same statement.
  • validateNavAccess itself is unchanged: identical findings on identical inputs before and after this PR (proven by re-running the full existing suite unmodified, and by a red-first check that reverted only the source file and confirmed the new pin test fails against it while every other test still passes).
  • packages/lint/src/validate-nav-access.test.ts: added a pin for the hint text (the retired "gate the entry" clause must not return, the two live remedies must be present) plus three regression controls — a requiredPermissions-gated ungranted object still fires, a visible: false ungranted object still fires, and a gated-AND-granted object stays silent (gating causes neither a false negative nor a false positive).
  • .changeset/nav-object-ungranted-hint-drops-gating.md@objectstack/lint patch.

Why

Card 16065: an author following the hint's third remedy (gate the entry) got no change in the rule's output — the warning kept firing — after spending an edit that also narrowed what the app actually serves to a real user. requiredPermissions/visible gate visibility, not the object grant, so a holder who clears the gate can still open the entry and hit permission-denied on the object itself.

Related, not touched here

  • card 14453 — where the defect was first measured against a real audit.
  • card 15135 — visible is inert at runtime; unrelated defect, not addressed by this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8


Generated by Claude Code

…t honour

The hint (and module doc-block) prescribed gating a nav entry with
requiredPermissions/visible as a way to clear the finding. Neither key is
read by the rule, so following that advice left the warning firing forever.
Corrected to the two remedies the rule can prove: grant read on the object,
or drop the entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8
@github-actions github-actions Bot added the size/s label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to listnot a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 5 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json ac76425f0bc9df18031201bb01fa917f19f62944packageMentionDocs.

Which tree this was computed on

This run read content/docs from 9e645514d80f298bbb55b6acb074ff532cb4cf14 — the merge of head 3bd1d1b91cdca7ec57aa9adb7fcda210fe742f76 into base ac76425f0bc9df18031201bb01fa917f19f62944, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 9e645514d80f298bbb55b6acb074ff532cb4cf14 && git checkout 9e645514d80f298bbb55b6acb074ff532cb4cf14
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ac76425f0bc9df18031201bb01fa917f19f62944 3bd1d1b91cdca7ec57aa9adb7fcda210fe742f76 && git checkout -B drift-repro ac76425f0bc9df18031201bb01fa917f19f62944 && git merge --no-ff 3bd1d1b91cdca7ec57aa9adb7fcda210fe742f76

node scripts/docs-audit/affected-docs.mjs --json ac76425f0bc9df18031201bb01fa917f19f62944

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Flip point read 2026-09-07T01:41Z (PM seat devx, session_01Vbw3RPgdtqesx4azk9SbW8) — every check-run row at head 3bd1d1b91 reads completed/success on its own line (six Test Core (k/6) shards, Lint & Repo Gates, four Type Check · rows, three Dogfood Regression Gate (k/3), Dogfood Verify CLI, Build Core, Temporal Conformance (live PG + MySQL), Check Changeset; Build Docs/Console Pin Gate/Packed-tarball smoke skipped by path filter). Non-green rows: 0. The CLI e2e file the dev flagged on the card ran green inside these shards.

The flip itself is held by the channel, not by the PR: the seat's write channel for draft→ready and auto-merge (update_pull_request / enable_pr_auto_merge) returned API rate limit already exceeded for user ID 6194462 twice at 01:42Z; REST PATCH /pulls does not carry the draft field, and the GraphQL mutation is outside the pinned operation set on this session. Flip retry armed for 02:00Z; nothing about this PR changes until then. If a maintainer marks it ready and enables auto-merge (squash) before that, the seat will read the timeline and take it from there.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 7, 2026 02:21
@baozhoutao
baozhoutao enabled auto-merge September 7, 2026 02:21
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 7, 2026
@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Queued 2026-09-07T02:22:36Z (PM seat devx, session_01Vbw3RPgdtqesx4azk9SbW8) — the channel hold recorded above cleared on the third attempt: ready_for_review 02:21:46Z, auto_merge_enabled 02:21:53Z (squash requested; the queue decides the method), added_to_merge_queue 02:22:36Z, head 3bd1d1b91 unchanged since the ACCEPT and every check-run row still green at the flip (re-read 02:21Z). Hold duration 40 min (01:42Z → 02:21Z, retries at 01:42Z, 02:01Z, 02:21Z). Merged-probe armed for 02:55Z; a regroup is not a removal.


Generated by Claude Code

@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Queue reading 2026-09-07T03:13Z (PM seat devx, session_01Vbw3RPgdtqesx4azk9SbW8) — still queued, regroup count now 2, no removed_from_merge_queue (updating the count recorded at 02:56Z).

Each regroup restarts the shard-5 clock, which is the lap that runs closest to the 30-minute wall (#16173). Seat action: none — a regroup is not a removal, and the seat's one re-queue stays unspent. Next probe 03:40Z.


Generated by Claude Code

Merged via the queue into main with commit ce21963 Sep 7, 2026
35 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-16065-nav-object-ungranted-hint branch September 7, 2026 03:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tests tooling

Projects

None yet

2 participants