docs(adr): amend ADR-0092 D5 — self-service edits route through the generic data path - #15109
Conversation
…eneric data path Maintainer ruling 2026-09-03, decision batch #22 (verbatim 「同意」). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AUF1NoViznQK32gqpK8wS8
…r-0092-d5-amendment
|
Ready for the maintainer — undrafted, green, and deliberately not armed
State, read at job level rather than from an aggregator: 30 checks green, 0 failures, nothing still running on head
The Not armed, on purpose. What it gates. The code PR #15108 ( Review record for both halves is on the card: Generated by Claude Code |
Dequeued
|
| reading | value |
|---|---|
not-green checks on its own head 4807b058b1 |
0 — every check green, nothing running |
| what this PR changes | 1 file, docs/adr/0092-sys-user-profile-field-delegation.md, +70/-1 |
files under packages/ |
0 |
A documentation-only ADR amendment cannot fail Test Core, a typecheck lane or a build. The queue here is grouped, and GitHub's own dequeue notice says so explicitly: "In a grouped queue the failure can come from another PR in the same batch." The batch this PR sat in also carried #15008, which merged — main advanced to fcc42e6c1d in the same window.
⛔ The queue refs and their runs are already cleaned up, so the batch-mate cannot be named from here. That is a limit of the reading, stated rather than papered over: what is established is that this PR's own head is clean, not which sibling failed.
What happens next, and why it has not happened yet
The remedy is to re-queue, which on this repository means re-enabling auto-merge — there is no hand-merge path, as PUT /pulls/15109/merge answers 405 Repository rule violations found — Changes must be made through the merge queue.
API rate limit already exceeded at 03:0xZ. The repo-scoped REST channel this comment is posted through cannot set auto_merge. Per this seat's standing rule the response to an exhausted pool is to back off, not to retry-loop, so the re-arm is owed and scheduled rather than attempted repeatedly.
Anyone with the UI can clear this immediately by pressing Merge when ready — the PR is green, undrafted, mergeable_state: clean, and its skip-changeset label is applied. Otherwise this seat re-arms it as soon as the quota window recovers.
⛔ One re-arm is this seat's limit and it is being spent here, on the "failure that is not this PR's" case. If it dequeues a second time the failure will be treated as real and root-caused rather than re-queued again.
#15108 remains held behind this PR — green (29 checks, 0 failures), contract review PASSED at tier (14959#issuecomment-5534395446), carriers still applied, draft. It lands immediately once this one merges.
Generated by Claude Code
|
Maintainer ruling, 2026-09-04, given in chat to the director seat (session_01WXyGTWPbbreqXow7Z2pZCk) on the governed batch presented at 01:50Z, item 1 (this PR, option A). Verbatim: 「15109 同意 其他不处理」. Executing on that instruction from the maintainer's own account: merging directly (squash) at head Generated by Claude Code |
Part of #14959
Governed surface — the maintainer merges this by hand. This PR carries the ADR amendment alone; the code that implements it is a separate PR, cross-linked below, and that one must not be armed for merge before this one lands.
What this amends
ADR-0092 D5 ("Who can edit whom: unchanged permission topology") said, in its third bullet:
Maintainer ruling 2026-09-03, decision batch #22, verbatim and untranslated as adopted:
A rank-and-file member may edit their own
sys_userrow on the generic data path. The original text is kept verbatim and the amendment is added as a blockquote beneath it, in the house style ADR-0105 established — two of D5's three bullets still hold, and the third is only readable against what it used to say.Why the original text stopped being true
D5 rests on a premise a later ruling retired: that better-auth
/update-usercan carry everything Tier 1 holds. It could, while Tier 1 was{name, image}. The 2026-09-03 ruling on #14787 admittedlocale, andlocaleis deliberately not a better-authadditionalFieldsentry — #13881 measured that declaring it there makesgetSessionSELECT a column an environment that has not run schema-sync does not have.So
/update-usercannot post the column, and withmember_defaultdenyingallowEditonsys_user, the generic path could not either. The column shipped reachable by platform admins alone — a user-stated preference (#14788 ruled the stored value outranksAccept-Languageprecisely because it is the user's own statement) that the user could not state.What the amendment decides
Self-service edits of the D1 Tier-1 columns route through the generic data path, bounded on the two axes that already exist and in the shape
sys_api_keyhas shipped since #8053:member_defaultgains an explicitsys_userentry (allowRead/allowEdittrue, create/delete false), and itssys_user_selfpolicy widens fromselecttoallso it reaches the by-id write pre-image check.sys_user_org_membersstaysselect-only: RLS policies OR-combine, so widening the org-peer visibility scope would compose "my id OR every user id in my org" and hand every member their colleagues' profile rows. The org-admin follow-up the original D5 text names at its end is still open, and still a separate decision.name/imagetherefore become editable on the generic path too. That is the real cost, accepted deliberately: D6 already mirrors better-auth'srefreshUserSessionsfor exactly those columns, so the session-cache coherence the original bullet bought by routing through/update-useris bought here by the companion hook instead.localeis correctly excluded from that mirror — better-auth carries no such field on its user model, so there is no stale cached copy to repair.Rejected in the same ruling and recorded in the amendment so they are not re-proposed: a dedicated endpoint under system context (the "second stamping route" #14787's own ruling rejected one level up), leaving the column admin-only, and
localeas anadditionalFieldsentry.Not amended: D1's tier table still lists two Tier-1 members while the enforced whitelist constant holds three. That reconciliation is tracked separately in #14951 and is deliberately left alone here.
Gates
docs/adr/**is excluded fromdispatch-gates.mjs's derived family forcheck-adr-anchors, so it was checked explicitly. Every gate in the derived family for this diff was run at the pushed head4807b058b1:check:adr-anchors,check-adr-links(+ self-test),check-adr-symbol-anchors(+ self-test),check:doc-authoring,check:doc-formula-expressions,check:nul-bytes,check:pm-governed-merges,check:cross-package-test-inputs(+ the direct-node spelling),check-ci-filter-parity,check-closing-keyword-parity(+ self-test),check-comment-mask-corpus,check-shard-attestation,check:refd-timer-probe,check:watch-hint-literalcheck-test-completeness— it grades a savedturbo run testlog that only CI produces, and a markdown-only diff cannot move it.Cross-links
sys_user.locale? Ruling B opened the COLUMN; ADR-0092 D5 still answers no to the ROUTE, so today only admins can set it #14959 (the ruling of record is itsissuecomment-5528362189)sys_api_key), [Decision] May a user set their ownsys_user.locale? — the ADR-0092 D2 self-service whitelist stays{name, image}after #13881 (column landsreadonly, system-context writes only) #14787 / feat(platform-objects,plugin-auth): makesys_user.localeuser-writable, with a loud BCP-47 refusal (#14787) #14958 (the column half)🤖 Generated with Claude Code
https://claude.ai/code/session_01AUF1NoViznQK32gqpK8wS8
Generated by Claude Code