Skip to content

docs(approvals): drop reserved word "role" from lifecycle copy (ADR-0090 D3)#3132

Closed
os-zhuang wants to merge 1 commit into
mainfrom
fix/role-word-approvals
Closed

docs(approvals): drop reserved word "role" from lifecycle copy (ADR-0090 D3)#3132
os-zhuang wants to merge 1 commit into
mainfrom
fix/role-word-approvals

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes the red Lint & Type Check on main. Docs-only — hence skip-changeset.

What broke

#3113 (25a19be72) added the approval-lifecycle walkthrough, including 4 new occurrences of the reserved word "role" in content/docs/automation/approvals.mdx (5 → 9), without updating scripts/role-word-baseline.json. pnpm check:role-word has failed on every push to main since — the last 4 runs of lint.yml are red — so every open PR inherits a failing ESLint check and real failures are masked.

Why not bump the baseline

Per ADR-0090 D3 the word is reserved-forbidden and new occurrences are banned; --update exists to ratchet the baseline down when a file improves. So the baseline stays at 5 and the copy is reworded.

The fix

Three of the four were a duplicate. The new callout under The request opens, the run pauses restated the already-baselined position vs role callout ~80 lines above it on the same page — which says the same thing in more detail (it names the os lint rule). Removed in favour of a cross-reference.

While rewording I also tightened the claim to match expandApprovers(): an unresolvable approver entry does not leave pending_approvers empty — it falls back to a literal <type>:<value> slot that no user matches, which is why the request stalls.

The fourth documented approverId accepting role:<r>. That literal is real, but it is one of several (team: / department: / position: / role: / manager:), so naming only the role: form was both off-vocabulary and needlessly narrow. Generalized to <type>:<value> with a position:finance_manager example, matching the page’s existing finance_manager sample.

The surviving 5 are the documented D3 exception — the better-auth boundary (sys_member.role), which the role approver type genuinely resolves against via expandRoleUsers(). Left untouched.

Verification

  • pnpm check:role-word → exit 0, approvals.mdx back to 5, role-word-baseline.json unmodified.
  • pnpm lint, check:doc-authoring, check:authz-resolver, check:release-notes → all pass.
    (Local eslint OOMs at the default heap on node 25 — an environment artifact, not this change; it is clean under --max-old-space-size=8192, and CI runs node 20.)
  • Rendered the page in the docs site: the <Steps> block keeps all 4 step headings after the callout removal, the reworded approverId sentence renders (<type>:<value> survives MDX as inline code), and the new #3-the-approval-node cross-reference resolves to the right heading — no console or server errors. Worth checking by hand since no CI job validates anchors.

🤖 Generated with Claude Code

…090 D3)

#3113 added the approval-lifecycle walkthrough with 4 new occurrences of the
reserved word "role", taking approvals.mdx from 5 → 9 and turning check:role-word
red. Lint & Type Check has failed on every push to main since, so every open PR
inherits a failing ESLint check.

ADR-0090 D3 bans NEW occurrences — the --update path is for ratcheting the
baseline DOWN — so the baseline stays at 5 and the copy is reworded instead.

Three of the four were a duplicate: the new callout under "The request opens"
restated the baselined `position` vs `role` callout ~80 lines above it, which
already says the same thing in more detail (it names the os lint rule). Replaced
with a cross-reference to it. The claim is also tightened to match
expandApprovers(): an unresolvable entry does not leave `pending_approvers`
empty, it falls back to a literal `<type>:<value>` slot that no user matches.

The fourth documented `approverId` accepting `role:<r>`. That literal is real,
but it is one of several (`team:` / `department:` / `position:` / `role:` /
`manager:` per approval-service.ts), so naming only the `role:` form was both
off-vocabulary and needlessly narrow. Generalized to `<type>:<value>` with a
`position:finance_manager` example, matching the page's existing finance_manager
sample.

The surviving 5 are the documented D3 exception — the better-auth boundary
(`sys_member.role`), which the `role` approver type genuinely resolves against
via expandRoleUsers().

Verified: check:role-word exits 0 at 5 occurrences with the baseline untouched;
eslint, check:doc-authoring, check:authz-resolver and check:release-notes pass;
page rendered in the docs site — Steps block intact and the #3-the-approval-node
cross-reference resolves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@os-zhuang os-zhuang added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Jul 17, 2026
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jul 17, 2026 12:13pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/s labels Jul 17, 2026
@os-zhuang

Copy link
Copy Markdown
Contributor Author

Closing as a duplicate of #3122, which fixes the same file for the same reason, was opened ~10 min earlier, and is already fully green.

I missed #3122 before opening this — my mistake. #3122 is also the better fix on the 4th occurrence:

  • Both PRs delete the duplicate type: 'role' is not a position callout (−3), which restates the callout ~75 lines above it.
  • For the 4th, I rewrote approverId accepting role:<r>position:finance_manager. That was wrong. Per contracts/approval-service.ts the identities are literally "their user id, email, and role:<r> entries"role:<r> is one of a person's own identities (their better-auth membership tier) and a genuine ADR-0090 D3 exception. A position: literal is not an identity at all; it only appears as a fallback when position expansion matches nobody. So my version contradicted the sentence's own "cover a person's identities in one call" clause.
  • docs(approvals): drop duplicate role-vs-position callout (unbreak role-word ratchet) #3122 instead trims the surviving callout's duplicated mention of the role approver type (−1) — removing real redundancy without laundering a real boundary literal.

No action needed here; #3122 covers it.

@os-zhuang os-zhuang closed this Jul 17, 2026
@os-zhuang
os-zhuang deleted the fix/role-word-approvals branch July 17, 2026 12:16
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 skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant