Repository navigation
Commit 45e6001
feat(spec): register the invitation role cap refusal codes under plugin-auth (#24092)
Fixes #24082
Clause-②: yes (widening)
## What
Registers three `@objectstack/plugin-auth` codes in
`packages/spec/src/api/error-code-ledger.zod.ts`, one per refusal the
invitation role cap
(`packages/plugins/plugin-auth/src/invitation-role-cap.ts`) can return.
Today `auth-manager.ts` throws all three as a bare
`APIError('FORBIDDEN', { message })` from `beforeCreateInvitation`
(`:3416`–`:3423`), so the Invite User dialog cannot branch on them.
| Code | Producer path at `8a83cebc15` | Status `plugin-auth` pairs it
with |
| :--- | :--- | :--- |
| `INVITE_ROLE_ABOVE_ISSUER` | `invitation-role-cap.ts:186`–`192`: the
requested role grades above the issuer's own | 403 |
| `INVITE_ISSUER_MEMBER_ONLY` | `invitation-role-cap.ts:194`–`199`: an
issuer below admin grade asks for anything but a single plain `member` |
403 |
| `INVITE_ISSUER_UNVERIFIED` | `invitation-role-cap.ts:175`–`181`: the
issuer's grade is unresolved (`resolveMembershipRole` answered `null`) |
403, fail-closed |
Registration only, ahead of the producer (the
`FLOW_INPUT_SCHEMA_INVALID` split shape the ledger test already
records). #23945 stamps these codes in `plugin-auth`; that card is not
closed by this PR.
## Measurements
- **The set is exactly three.** `invitationRoleCapFailure` has three
non-null returns (lines 175, 186, 194) and no other refusal; its one
caller (`auth-manager.ts:3416`) turns each into the same `FORBIDDEN`.
Path 2 is reached only by an issuer below admin grade: an admin or owner
passes `grantTableAdmits` for every role except one that outranks them,
which is path 1.
- **Names under the synonym gate.** `standardSynonymOf` on the built
`dist` returns `undefined` for all three (`INVITE` is a token no
standard member carries), and `ErrorCode.safeParse` accepts each. No
`STANDARD_SYNONYM_WAIVERS` entry. Named in the existing `INVITE_*`
family, for the condition rather than the status.
- **Condition 3 is fail-closed, and its comment says so.**
`resolveMembershipRole` (`auth-manager.ts:7612`) answers `null` for four
inputs: missing keys, no engine, no membership row, or a lookup that
threw. The cap cannot tell them apart, so the code's meaning is "could
not be established" and it pairs with 403, fail-closed. Whether #23945
should split the thrown-lookup case onto the standard
`SERVICE_UNAVAILABLE` (as the slug guard's read fault does,
`auth-manager.ts:1333`) is noted below for that card. It is not decided
here.
## Files
- `packages/spec/src/api/error-code-ledger.zod.ts`: three rows, each
with a meaning comment citing #24082.
- `packages/spec/src/api/error-code-ledger.test.ts`: one case pinning
the three by value (parse, owner, no synonym), mirroring the
registered-ahead-of-producer precedent.
- `content/docs/references/api/contract.mdx`,
`content/docs/references/api/error-code-ledger.mdx`: regenerated by
`pnpm --filter @objectstack/spec check:generated --fix` (the only stale
artifact it found was `check:docs`).
- `.changeset/24082-invite-role-cap-codes.md`: `minor` on
`@objectstack/spec`.
## Verification (head `44818e2e6d`)
- `pnpm --filter @objectstack/spec build`: exit 0. Then `exec vitest run
src/api/error-code-ledger.test.ts src/api/api-error-code-type.test.ts`:
2 files, 24 tests passed. `typecheck`: exit 0.
- `pnpm --filter @objectstack/spec check:generated`: exit 1 before
regeneration (`check:docs` stale), exit 0 after `--fix`.
- `node scripts/pm/dispatch-gates.mjs --commands`: 111 families derived,
all run and reconciled with `--ran` (`111 derived famil(ies) accounted
for — 109 run, 2 NOT-MEASURED`). Among them `check:error-code-casing`,
`check:dispatcher-error-vocabulary`, `check:error-code-provenance`,
`check:api-surface` and `check:docs` all exit 0.
- NOT MEASURED locally: `check:dual-build-cjs-loads` and
`check:lean-entry-closure` (exit 3, PREREQUISITE NOT MET: they need a
whole-workspace build). Both are left to CI's `Lint & Repo Gates`.
- ESLint (`--no-inline-config`) over both changed `.ts` files: exit 0.
## Acceptance notes
- For #23945 (not a finding filed): `resolveMembershipRole` answers
`null` both when the issuer has no membership row and when the lookup
threw. Under this registration both are `INVITE_ISSUER_UNVERIFIED` with
403. If #23945 separates the thrown lookup, the existing standard
`SERVICE_UNAVAILABLE` is the code that fits it, so no fourth code is
registered here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01GDoMKJFY45jdSGzFmyumij)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent d6bd98a commit 45e6001
5 files changed
Lines changed: 40 additions & 1 deletion
File tree
- .changeset
- content/docs/references/api
- packages/spec/src/api
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| |||
219 | 219 | | |
220 | 220 | | |
221 | 221 | | |
| 222 | + | |
| 223 | + | |
222 | 224 | | |
| 225 | + | |
223 | 226 | | |
224 | 227 | | |
225 | 228 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
386 | 386 | | |
387 | 387 | | |
388 | 388 | | |
| 389 | + | |
| 390 | + | |
389 | 391 | | |
| 392 | + | |
390 | 393 | | |
391 | 394 | | |
392 | 395 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
231 | 231 | | |
232 | 232 | | |
233 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
234 | 246 | | |
235 | 247 | | |
236 | 248 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
570 | 570 | | |
571 | 571 | | |
572 | 572 | | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
573 | 578 | | |
| 579 | + | |
574 | 580 | | |
575 | 581 | | |
576 | 582 | | |
| |||
0 commit comments