Commit f907c1a
committed
feat(auth)!: membership grade is not a capability channel — close the
`sys_member.role` answers "what is your standing in this organization". It
does not answer "what may you do" — that is what positions are for. One
column was answering both.
`resolve-authz-context` projects EVERY value stored in `sys_member.role` into
`current_user.positions`, alongside the rows read from `sys_user_position`. A
business role handed out through the membership role was therefore capability,
granted with none of the position system's controls: no `granted_by`, no
ADR-0091 validity window, no BU-subtree check, no `assignablePermissionSets`
allowlist. ADR-0057 D4 ruled that out ("never as the authority for RBAC"),
ADR-0090 D3's word ban restates it (distribution = `position`), and ADR-0095
D3 keeps the better-auth role out of the enforcement path. No ADR ever
authorized the widening — it arrived as a bug fix (#3747) and was then made
automatic in every host (#3779).
The vocabulary is closed to the four framework-owned names: owner / admin /
delegated_admin / member.
- `additionalOrgRoles` removed from AuthManagerOptions and AuthPluginOptions,
with `plugin-auth/src/org-roles.ts` in full and the `kernel:ready`
derivation hook. A TypeScript error is the intended failure; a silently
ignored option would be `declared != enforced` one more time.
- The two `role` selects carry `BUILTIN_MEMBERSHIP_ROLE_OPTIONS` and nothing
else; nothing widens them at boot.
- `MEMBERSHIP_ROLE_NAME_PATTERN` / `_MIN_LENGTH` dropped from spec — they
existed only to validate app-supplied names.
- lint's `MEMBERSHIP_TIERS` derives from `BUILTIN_MEMBERSHIP_ROLES`. The
hand-kept copy carried `guest`, which the select has never offered, so an
approver naming it resolved to nobody and the lint whose job is to catch
that stayed silent — fixed by construction, with a regression test.
- `app-org-role-invite.dogfood.test.ts` is replaced by
`membership-role-vocabulary.dogfood.test.ts`, which proves the vocabulary is
closed, that an app name is refused at better-auth's door leaving no row,
and that the same intent succeeds through ADR-0105 D8 placement.
Migration (also in the changeset):
- POST /organization/invite-member { email, role: 'sales_rep' }
+ POST /organization/invite-member { email, role: 'member',
+ businessUnitId, positions: ['sales_rep'] }
Placement reaches further than what it replaces: it is authorized against the
issuer's adminScope, so a delegated admin may use it within their subtree,
where the membership-role route was open to org admins only.
Both reversed changesets were unreleased, so no published version ever offered
the behaviour.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186LhwkUBupmLJUUAMda5hUsys_member.role vocabulary (ADR-0108, #3723)1 parent 32d3800 commit f907c1a
29 files changed
Lines changed: 789 additions & 1284 deletions
File tree
- .changeset
- content/docs/permissions
- docs/adr
- packages
- cli/src/commands
- lint/src
- platform-objects/src/identity
- plugins
- plugin-auth/src
- plugin-dev/src
- qa/dogfood/test
- runtime/src
- spec
- src
- identity
- verify/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | | - | |
| 17 | + | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
668 | 668 | | |
669 | 669 | | |
670 | 670 | | |
671 | | - | |
| 671 | + | |
672 | 672 | | |
673 | 673 | | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
679 | 688 | | |
680 | 689 | | |
681 | 690 | | |
682 | | - | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
683 | 697 | | |
684 | 698 | | |
685 | | - | |
686 | | - | |
687 | | - | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
702 | | - | |
703 | | - | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
704 | 717 | | |
705 | 718 | | |
706 | 719 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
173 | 173 | | |
174 | 174 | | |
175 | 175 | | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
180 | 182 | | |
181 | 183 | | |
182 | 184 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| |||
0 commit comments