From e979418e10696b3b8e3e7a8be710cd2884db356a Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Fri, 17 Jul 2026 20:12:32 +0800 Subject: [PATCH] docs(approvals): drop reserved word "role" from lifecycle copy (ADR-0090 D3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #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 `:` slot that no user matches. The fourth documented `approverId` accepting `role:`. 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 `:` 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 --- content/docs/automation/approvals.mdx | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/content/docs/automation/approvals.mdx b/content/docs/automation/approvals.mdx index 592e26199..a3d48ba44 100644 --- a/content/docs/automation/approvals.mdx +++ b/content/docs/automation/approvals.mdx @@ -130,14 +130,10 @@ record is **locked** against edits while pending (`lockRecord`, default `true`), and the flow run parks until a decision arrives. Only `approvers` is required on the node; everything else has a default -(`behavior: 'first_response'`, `lockRecord: true`, `maxRevisions: 3`). - - -**`type: 'role'` is not a position.** In an approver entry, `role` means the -better-auth membership tier (`owner` / `admin` / `member`). Naming a business -role like `sales_manager` there matches nobody and the request silently has no -approvers — use `{ type: 'position', value: 'sales_manager' }`. - +(`behavior: 'first_response'`, `lockRecord: true`, `maxRevisions: 3`). An +approver entry that resolves to no users falls back to a literal `:` +slot that no one matches, so the request opens and then stalls — see the +approver-type warning under [The approval node](#3-the-approval-node). ### The approver finds it in their queue @@ -150,10 +146,10 @@ curl -b cookies.txt \ "https://your-app.example.com/api/v1/approvals/requests?status=pending&approverId=usr_123" ``` -`approverId` accepts a user id, an email, or `role:` — and takes several -values (comma-separated or repeated) to cover a person's identities in one call. -Other filters: `status`, `object`, `recordId`, `submitterId`, `q`, `limit`, -`offset`. +`approverId` accepts a user id, an email, or a `:` approver literal +(`position:finance_manager`) — and takes several values (comma-separated or +repeated) to cover a person's identities in one call. Other filters: `status`, +`object`, `recordId`, `submitterId`, `q`, `limit`, `offset`. **Opening a request notifies nobody.** There is no built-in "you have an