@stapel/auth-react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/MODULE.md +147 -0
  4. package/README.md +116 -0
  5. package/dist/api/authApi.d.ts +68 -0
  6. package/dist/api/authApi.d.ts.map +1 -0
  7. package/dist/api/authApi.js +90 -0
  8. package/dist/api/authApi.js.map +1 -0
  9. package/dist/api/types.d.ts +238 -0
  10. package/dist/api/types.d.ts.map +1 -0
  11. package/dist/api/types.js +14 -0
  12. package/dist/api/types.js.map +1 -0
  13. package/dist/api/urls.d.ts +41 -0
  14. package/dist/api/urls.d.ts.map +1 -0
  15. package/dist/api/urls.js +86 -0
  16. package/dist/api/urls.js.map +1 -0
  17. package/dist/flows/anonymousFlow.d.ts +33 -0
  18. package/dist/flows/anonymousFlow.d.ts.map +1 -0
  19. package/dist/flows/anonymousFlow.js +26 -0
  20. package/dist/flows/anonymousFlow.js.map +1 -0
  21. package/dist/flows/authenticatorChangeFlow.d.ts +67 -0
  22. package/dist/flows/authenticatorChangeFlow.d.ts.map +1 -0
  23. package/dist/flows/authenticatorChangeFlow.js +79 -0
  24. package/dist/flows/authenticatorChangeFlow.js.map +1 -0
  25. package/dist/flows/createFlowMachine.d.ts +55 -0
  26. package/dist/flows/createFlowMachine.d.ts.map +1 -0
  27. package/dist/flows/createFlowMachine.js +56 -0
  28. package/dist/flows/createFlowMachine.js.map +1 -0
  29. package/dist/flows/errors.d.ts +15 -0
  30. package/dist/flows/errors.d.ts.map +1 -0
  31. package/dist/flows/errors.js +17 -0
  32. package/dist/flows/errors.js.map +1 -0
  33. package/dist/flows/magicLinkFlow.d.ts +41 -0
  34. package/dist/flows/magicLinkFlow.d.ts.map +1 -0
  35. package/dist/flows/magicLinkFlow.js +29 -0
  36. package/dist/flows/magicLinkFlow.js.map +1 -0
  37. package/dist/flows/oauthFlow.d.ts +58 -0
  38. package/dist/flows/oauthFlow.d.ts.map +1 -0
  39. package/dist/flows/oauthFlow.js +53 -0
  40. package/dist/flows/oauthFlow.js.map +1 -0
  41. package/dist/flows/otpFlow.d.ts +74 -0
  42. package/dist/flows/otpFlow.d.ts.map +1 -0
  43. package/dist/flows/otpFlow.js +68 -0
  44. package/dist/flows/otpFlow.js.map +1 -0
  45. package/dist/flows/passkeyFlow.d.ts +75 -0
  46. package/dist/flows/passkeyFlow.d.ts.map +1 -0
  47. package/dist/flows/passkeyFlow.js +100 -0
  48. package/dist/flows/passkeyFlow.js.map +1 -0
  49. package/dist/flows/passwordChangeFlow.d.ts +53 -0
  50. package/dist/flows/passwordChangeFlow.d.ts.map +1 -0
  51. package/dist/flows/passwordChangeFlow.js +51 -0
  52. package/dist/flows/passwordChangeFlow.js.map +1 -0
  53. package/dist/flows/passwordLoginFlow.d.ts +62 -0
  54. package/dist/flows/passwordLoginFlow.d.ts.map +1 -0
  55. package/dist/flows/passwordLoginFlow.js +55 -0
  56. package/dist/flows/passwordLoginFlow.js.map +1 -0
  57. package/dist/flows/passwordResetFlow.d.ts +56 -0
  58. package/dist/flows/passwordResetFlow.d.ts.map +1 -0
  59. package/dist/flows/passwordResetFlow.js +57 -0
  60. package/dist/flows/passwordResetFlow.js.map +1 -0
  61. package/dist/flows/qrLoginFlow.d.ts +55 -0
  62. package/dist/flows/qrLoginFlow.d.ts.map +1 -0
  63. package/dist/flows/qrLoginFlow.js +91 -0
  64. package/dist/flows/qrLoginFlow.js.map +1 -0
  65. package/dist/flows/ssoFlow.d.ts +46 -0
  66. package/dist/flows/ssoFlow.d.ts.map +1 -0
  67. package/dist/flows/ssoFlow.js +34 -0
  68. package/dist/flows/ssoFlow.js.map +1 -0
  69. package/dist/flows/totpSetupFlow.d.ts +49 -0
  70. package/dist/flows/totpSetupFlow.d.ts.map +1 -0
  71. package/dist/flows/totpSetupFlow.js +47 -0
  72. package/dist/flows/totpSetupFlow.js.map +1 -0
  73. package/dist/flows/useFlow.d.ts +9 -0
  74. package/dist/flows/useFlow.d.ts.map +1 -0
  75. package/dist/flows/useFlow.js +11 -0
  76. package/dist/flows/useFlow.js.map +1 -0
  77. package/dist/flows/verificationFlow.d.ts +108 -0
  78. package/dist/flows/verificationFlow.d.ts.map +1 -0
  79. package/dist/flows/verificationFlow.js +195 -0
  80. package/dist/flows/verificationFlow.js.map +1 -0
  81. package/dist/headless/AuthProvider.d.ts +18 -0
  82. package/dist/headless/AuthProvider.d.ts.map +1 -0
  83. package/dist/headless/AuthProvider.js +22 -0
  84. package/dist/headless/AuthProvider.js.map +1 -0
  85. package/dist/headless/Passkey.d.ts +31 -0
  86. package/dist/headless/Passkey.d.ts.map +1 -0
  87. package/dist/headless/Passkey.js +51 -0
  88. package/dist/headless/Passkey.js.map +1 -0
  89. package/dist/headless/PasswordChange.d.ts +20 -0
  90. package/dist/headless/PasswordChange.d.ts.map +1 -0
  91. package/dist/headless/PasswordChange.js +30 -0
  92. package/dist/headless/PasswordChange.js.map +1 -0
  93. package/dist/headless/PasswordLogin.d.ts +17 -0
  94. package/dist/headless/PasswordLogin.d.ts.map +1 -0
  95. package/dist/headless/PasswordLogin.js +31 -0
  96. package/dist/headless/PasswordLogin.js.map +1 -0
  97. package/dist/headless/PasswordReset.d.ts +19 -0
  98. package/dist/headless/PasswordReset.d.ts.map +1 -0
  99. package/dist/headless/PasswordReset.js +34 -0
  100. package/dist/headless/PasswordReset.js.map +1 -0
  101. package/dist/headless/PasswordlessLogin.d.ts +28 -0
  102. package/dist/headless/PasswordlessLogin.d.ts.map +1 -0
  103. package/dist/headless/PasswordlessLogin.js +42 -0
  104. package/dist/headless/PasswordlessLogin.js.map +1 -0
  105. package/dist/headless/QrLogin.d.ts +19 -0
  106. package/dist/headless/QrLogin.d.ts.map +1 -0
  107. package/dist/headless/QrLogin.js +32 -0
  108. package/dist/headless/QrLogin.js.map +1 -0
  109. package/dist/headless/TotpSetup.d.ts +17 -0
  110. package/dist/headless/TotpSetup.d.ts.map +1 -0
  111. package/dist/headless/TotpSetup.js +26 -0
  112. package/dist/headless/TotpSetup.js.map +1 -0
  113. package/dist/headless/VerificationChallenge.d.ts +37 -0
  114. package/dist/headless/VerificationChallenge.d.ts.map +1 -0
  115. package/dist/headless/VerificationChallenge.js +40 -0
  116. package/dist/headless/VerificationChallenge.js.map +1 -0
  117. package/dist/headless/misc.d.ts +47 -0
  118. package/dist/headless/misc.d.ts.map +1 -0
  119. package/dist/headless/misc.js +84 -0
  120. package/dist/headless/misc.js.map +1 -0
  121. package/dist/i18n/keys.d.ts +34 -0
  122. package/dist/i18n/keys.d.ts.map +1 -0
  123. package/dist/i18n/keys.js +83 -0
  124. package/dist/i18n/keys.js.map +1 -0
  125. package/dist/index.d.ts +73 -0
  126. package/dist/index.d.ts.map +1 -0
  127. package/dist/index.js +48 -0
  128. package/dist/index.js.map +1 -0
  129. package/dist/model/context.d.ts +22 -0
  130. package/dist/model/context.d.ts.map +1 -0
  131. package/dist/model/context.js +34 -0
  132. package/dist/model/context.js.map +1 -0
  133. package/dist/model/mutations.d.ts +28 -0
  134. package/dist/model/mutations.d.ts.map +1 -0
  135. package/dist/model/mutations.js +108 -0
  136. package/dist/model/mutations.js.map +1 -0
  137. package/dist/model/queries.d.ts +30 -0
  138. package/dist/model/queries.d.ts.map +1 -0
  139. package/dist/model/queries.js +87 -0
  140. package/dist/model/queries.js.map +1 -0
  141. package/dist/model/queryKeys.d.ts +13 -0
  142. package/dist/model/queryKeys.d.ts.map +1 -0
  143. package/dist/model/queryKeys.js +21 -0
  144. package/dist/model/queryKeys.js.map +1 -0
  145. package/dist/model/runtime.d.ts +39 -0
  146. package/dist/model/runtime.d.ts.map +1 -0
  147. package/dist/model/runtime.js +44 -0
  148. package/dist/model/runtime.js.map +1 -0
  149. package/dist/model/session.d.ts +50 -0
  150. package/dist/model/session.d.ts.map +1 -0
  151. package/dist/model/session.js +124 -0
  152. package/dist/model/session.js.map +1 -0
  153. package/package.json +68 -0
  154. package/src/api/authApi.ts +332 -0
  155. package/src/api/types.ts +291 -0
  156. package/src/api/urls.ts +99 -0
  157. package/src/flows/anonymousFlow.ts +57 -0
  158. package/src/flows/authenticatorChangeFlow.ts +160 -0
  159. package/src/flows/createFlowMachine.ts +126 -0
  160. package/src/flows/errors.ts +29 -0
  161. package/src/flows/magicLinkFlow.ts +68 -0
  162. package/src/flows/oauthFlow.ts +114 -0
  163. package/src/flows/otpFlow.ts +156 -0
  164. package/src/flows/passkeyFlow.ts +191 -0
  165. package/src/flows/passwordChangeFlow.ts +114 -0
  166. package/src/flows/passwordLoginFlow.ts +122 -0
  167. package/src/flows/passwordResetFlow.ts +123 -0
  168. package/src/flows/qrLoginFlow.ts +158 -0
  169. package/src/flows/ssoFlow.ts +84 -0
  170. package/src/flows/totpSetupFlow.ts +96 -0
  171. package/src/flows/useFlow.ts +16 -0
  172. package/src/flows/verificationFlow.ts +341 -0
  173. package/src/headless/AuthProvider.tsx +30 -0
  174. package/src/headless/Passkey.tsx +97 -0
  175. package/src/headless/PasswordChange.tsx +46 -0
  176. package/src/headless/PasswordLogin.tsx +49 -0
  177. package/src/headless/PasswordReset.tsx +51 -0
  178. package/src/headless/PasswordlessLogin.tsx +60 -0
  179. package/src/headless/QrLogin.tsx +52 -0
  180. package/src/headless/TotpSetup.tsx +40 -0
  181. package/src/headless/VerificationChallenge.tsx +54 -0
  182. package/src/headless/misc.tsx +151 -0
  183. package/src/i18n/keys.ts +94 -0
  184. package/src/index.ts +229 -0
  185. package/src/model/context.tsx +51 -0
  186. package/src/model/mutations.ts +152 -0
  187. package/src/model/queries.ts +130 -0
  188. package/src/model/queryKeys.ts +32 -0
  189. package/src/model/runtime.ts +93 -0
  190. package/src/model/session.ts +188 -0
  191. package/tsconfig.json +26 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,56 @@
1
+ # @stapel/auth-react
2
+
3
+ ## 1.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 809b706: New package: headless React auth flow pair for stapel-auth (frontend-standard
8
+ §2), built on `@stapel/core`. First instance of the framework's
9
+ `createFlowMachine` pattern (typed steps, human-wait vs async `run`,
10
+ auto-instrumented `flow.<id>.<step>` analytics).
11
+
12
+ Full journeys: Email/Phone OTP, password login (with TOTP challenge branch),
13
+ password change/reset, the step-up **verification factor flow** wired into
14
+ core's verification-403 interception (the flagship cross-module seam), TOTP
15
+ setup, OAuth token exchange, sessions, token refresh with rotation + teardown,
16
+ QR login polling, magic-link request, anonymous, instant authenticator change,
17
+ and SSO discovery. Passkeys + the passkey verification factor are flow-complete
18
+ with a thin injectable WebAuthn binding (see MODULE.md).
19
+
20
+ Ships typed API client (CSRF on mutations), open-redirect guards (§19.2),
21
+ namespaced TanStack Query hooks/mutations, `createAuthRuntime` (session token
22
+ seam + verification controller wired into the client), render-prop headless
23
+ components, and an i18n key bundle.
24
+
25
+ Not released — Opus-authored first instance, awaits independent adversarial
26
+ review.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [5dfa61e]
31
+ - @stapel/core@0.2.0
32
+
33
+ ## 0.1.0 (unreleased)
34
+
35
+ Initial headless auth flow pair for stapel-auth (frontend-standard §2), built on
36
+ `@stapel/core`. First instance of the framework's `createFlowMachine` pattern.
37
+
38
+ - **flows/** — `createFlowMachine` primitive (typed steps, human-wait vs async
39
+ `run`, auto-instrumented `flow.<id>.<step>` analytics) + machines for OTP,
40
+ password login (with TOTP branch), password change/reset, step-up
41
+ verification, TOTP setup, OAuth, QR login, magic link, anonymous,
42
+ authenticator change, SSO, and passkeys.
43
+ - **api/** — typed client over `StapelClient` for the auth-sa.md endpoints
44
+ (CSRF header on mutations), browser-redirect URL builders, and the §19.2
45
+ open-redirect guards.
46
+ - **model/** — `createAuthRuntime` (wires the session token seam and the
47
+ verification-403 controller into the client), `AuthSession` (refresh rotation
48
+ - teardown + persistence), namespaced TanStack Query hooks and mutations.
49
+ - **headless/** — render-prop components incl. the flagship
50
+ `<VerificationChallenge>` factor UI, plus `<AuthProvider>`.
51
+ - **i18n/** — auth-react key bundle registered into core's engine.
52
+
53
+ Passkeys and the passkey verification factor are flow-complete; the WebAuthn
54
+ browser binding is a thin injectable seam (see MODULE.md).
55
+
56
+ **NOT released** — awaits independent adversarial review.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stapel contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/MODULE.md ADDED
@@ -0,0 +1,147 @@
1
+ # @stapel/auth-react — MODULE.md
2
+
3
+ Headless auth flow pair for stapel-auth (frontend-standard §2/§5). First
4
+ instance of the framework's **flow-machine** pattern; later `-react` pairs copy
5
+ it. Layers: `api/` (typed client over `@stapel/core`) → `model/` (runtime,
6
+ session, query hooks) → `flows/` (state machines) → `headless/` (render props)
7
+ → `i18n/` (key bundle).
8
+
9
+ ## The `createFlowMachine` pattern (reusable primitive)
10
+
11
+ A flow is a tiny state container whose state is a discriminated union keyed by
12
+ `step`. `createFlowMachine({ id, initial, analytics })` gives every flow three
13
+ things for free:
14
+
15
+ - **Typed transitions** — `to(next)` swaps state (immutable snapshots) and
16
+ notifies React via `useFlow` (`useSyncExternalStore`).
17
+ - **Human-wait vs async steps** — a resting step waits for user input (`to`);
18
+ an async step goes through `run(pending, task, { resolve, reject })`, which
19
+ parks in `pending`, awaits, then transitions on the result. `run` **never
20
+ throws** — rejections fold into an error state, so hosts render errors
21
+ instead of catching them. `run` is **staleness-guarded** (an epoch counter
22
+ bumped on every `to`): if a newer transition happens while the task is in
23
+ flight — double-submit, cancel, navigate, challenge expiry — the late result
24
+ is dropped, never clobbering the newer state nor running its resolve/reject
25
+ side effects (analytics still fires). This guard lives in the primitive so
26
+ every future pair inherits it.
27
+ - **Auto-instrumentation** — each transition emits `flow.<id>.<step>` started;
28
+ each `run` emits `completed`/`failed` for its pending step
29
+ (analytics-standard §1.2). Funnels exist without hand-written tracking.
30
+
31
+ Each flow is a factory `createXxxFlow(deps) → { machine, ...actions }`. Deps are
32
+ `{ api, analytics?, onAuthenticated? }`. Copy this shape for new pairs.
33
+
34
+ ## Flows & headless components
35
+
36
+ | Journey (auth-sa.md) | Flow factory | Headless | Status |
37
+ |---|---|---|---|
38
+ | Email/Phone OTP §1–2 | `createOtpFlow` | `<PasswordlessLogin>` | **full** |
39
+ | Password login + TOTP branch §3/§11 | `createPasswordLoginFlow` | `<PasswordLogin>` | **full** |
40
+ | Password change §4 | `createPasswordChangeFlow` | `<PasswordChange>` | **full** |
41
+ | Password reset §5 | `createPasswordResetFlow` | `<PasswordReset>` | **full** |
42
+ | Step-up verification §11 | `createVerificationController` | `<VerificationChallenge>` | **full** (passkey factor thin) |
43
+ | TOTP setup §11 | `createTotpSetupFlow` | `<TotpSetup>` | **full** |
44
+ | OAuth token exchange §7 | `createOAuthFlow` | — (+ `authUrls().oauthAuthorize`) | **full** |
45
+ | Sessions §12 | model hooks/mutations | — | **full** |
46
+ | Token refresh §13 | `AuthSession.onAuthRefresh` | — | **full** |
47
+ | QR login/session-share §8 | `createQrLoginFlow` | `<QrLogin>` | **full** (polling) |
48
+ | Magic link §15 | `createMagicLinkFlow` | `<MagicLink>` | **full** (request side) |
49
+ | Anonymous §6 | `createAnonymousFlow` | `<AnonymousSession>` | **full** |
50
+ | Authenticator change (instant) §9 | `createAuthenticatorChangeFlow` | `<AuthenticatorChange>` | **full** (delayed = CRUD hooks) |
51
+ | SSO discovery §18 | `createSsoFlow` | `<SsoDiscovery>` | **full** (redirect handoff) |
52
+ | Passkeys §17 | `createPasskeyRegistrationFlow` / `createPasskeyLoginFlow` | `<PasskeyRegistration>` / `<PasskeyLogin>` | **flow complete, WebAuthn binding THIN** |
53
+
54
+ ### Thin-WebAuthn TODO (honest scope)
55
+
56
+ Passkeys and the `passkey` verification factor model the full
57
+ begin→ceremony→complete journey and surface the server `options` /
58
+ `session_key`. The **single browser step** — `navigator.credentials.create()` /
59
+ `.get()` — is **not** implemented here. Provide it one of two ways:
60
+
61
+ 1. **Inject a binding** — pass `webauthnCreate` / `webauthnGet` (to the flow,
62
+ the `<Passkey*>` components, or `createAuthRuntime({ webauthnGet })`); the
63
+ flow auto-drives the ceremony.
64
+ 2. **Drive it manually** — read the `awaitingCredential` / `awaitingAssertion`
65
+ state's `options`, run the ceremony yourself, call `submitCredential` /
66
+ `submitAssertion` / `submitPasskey`.
67
+
68
+ No "no credentials" heuristics — per auth-sa.md §19.6 that leak works against
69
+ the privacy property; show the single copy key `auth.passkey.no_credentials`.
70
+
71
+ ## Verification challenge lifecycle
72
+
73
+ Exactly one challenge is live at a time. The controller holds the core
74
+ request's awaited resolver, so it must always release it:
75
+
76
+ - **Success** → `settle({ retry: true, token })`; core replays with
77
+ `X-Verification-Token`.
78
+ - **Cancel** → `settle({ retry: false })`; the original 403 propagates.
79
+ - **Expiry** → the envelope's `expires_at` schedules an auto-release: an
80
+ abandoned modal (user walks away, never cancels) resolves `{ retry: false }`
81
+ instead of hanging the core `fetch` forever — and because the resolver is
82
+ cleared, subsequent challenges are handled rather than declined (no wedge).
83
+ - **Factor initiate failure** → a 404 (challenge gone) ends the whole challenge
84
+ (`unavailable` + settle `retry:false`); any other failure (a 423-locked or
85
+ invalid factor, network) returns to the **picker** carrying the error, so a
86
+ different, still-valid factor remains choosable.
87
+
88
+ ## Model hooks
89
+
90
+ Queries: `useCapabilities`, `useMe`, `useSecurityStatus`, `usePasswordMethods`,
91
+ `useSessions`, `usePasskeys`, `useAuditLog`, `useDelayedChangeStatus`,
92
+ `useSsoLookup`. Mutations (with invalidation): `useLogout`, `useRevokeSession`,
93
+ `useRevokeOtherSessions`, `useConfirmSession`, `useRemovePasskey`,
94
+ `useDisableTotp`, `useCancelDelayedChange`. Keys are namespaced under `["auth"]`
95
+ (`authQueryKeys`).
96
+
97
+ ## Session & persist policy
98
+
99
+ `AuthSession` (via `createAuthRuntime`) holds `{ user, tokens, status }`,
100
+ exposes `getAccessToken` / `onAuthRefresh` wired into the client, and rotates
101
+ the refresh token on 401. `error.401.refresh_revoked` → `onTeardown("revoked")`
102
+ (hard logout); any other refresh failure → `"expired"`; explicit
103
+ `logout()` → `"logout"`. A recursion guard ensures the refresh request's own
104
+ 401 does not re-enter refresh. Session persists `{ user, tokens }` to core's
105
+ `PersistStorage` (IndexedDB→localStorage) under `stapel-auth:session`; query
106
+ cache persistence is per-user via core's `setPersistUser` — call
107
+ `purgePersistedCache()` from `onTeardown` for GDPR-grade logout.
108
+
109
+ ## Extension points (fork-free, frontend-standard §7)
110
+
111
+ - **Client injection** — every flow/hook uses the client from
112
+ `createAuthRuntime` (host-built); a divergent backend injects its own
113
+ generated client into the same machines.
114
+ - **Steps/guards** — flows are plain factories; wrap or replace actions.
115
+ - **Headless layer** — render props are replaceable by definition; shadcn-copy
116
+ them into the app.
117
+ - **i18n** — override any key via core's `loadLocale`.
118
+
119
+ ## Ambiguities / conflicts surfaced from auth-sa.md
120
+
121
+ 1. **Legacy step-up vs verification envelope.** §11 keeps `POST /totp/step-up/`
122
+ + `X-Step-Up-Token`, while §19.4 says the interceptor currently handles
123
+ `403 error.403.step_up_required` (the legacy path). auth-sa.md itself says
124
+ "new integrations should implement the envelope flow." We implement **only**
125
+ the envelope flow (`error.403.verification_required` → `verification`
126
+ object), matching `@stapel/core`'s interception seam. The legacy
127
+ `X-Step-Up-Token` path is intentionally **not** implemented — flag for review
128
+ if any endpoint still emits it.
129
+ 2. **QR error codes diverge.** The §8 status polling uses a `{status}` body
130
+ (`rejected`/`expired`) while the Error reference lists `error.409.qr_*` /
131
+ `error.403.qr_*` HTTP errors. The flow treats the status body as
132
+ authoritative for polling and surfaces HTTP errors as `error` state.
133
+ 3. **OAuth redirect (option A) shapes.** §7 option A + §19.1 imply a
134
+ `/app/oauth/callback` frontend route and a `/totp-challenge` alias; those are
135
+ **host routing** concerns (the backend sets cookies), so auth-react provides
136
+ only `authUrls().oauthAuthorize` and the token-exchange flow (option B), not
137
+ the callback route.
138
+ 4. **Magic-link / SSO landings** (`/login?...` params, §15/§18.2) are backend
139
+ redirects to host routes; auth-react provides the `safeNextPath` /
140
+ `safeScanRedirect` guards (§19.2) but the route components are app-layer.
141
+ 5. **Capabilities `password` under registration** is documented but no
142
+ password-registration endpoint exists in §1–18; treated as display-only.
143
+
144
+ ## Status
145
+
146
+ **NOT released** — Opus-authored first instance; awaits independent adversarial
147
+ review before any npm publish (no-Fable protocol).
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # @stapel/auth-react
2
+
3
+ The **headless** React flow pair for [stapel-auth](../../../docs/auth-sa.md)
4
+ (frontend-standard §2). Business + state only — **zero visual opinion**. Every
5
+ flow is a typed state machine; every headless component is a render prop. You
6
+ bring the markup and design; auth-react brings the auth journeys, the token
7
+ seam, and the flagship step-up verification flow.
8
+
9
+ Built entirely on [`@stapel/core`](../core): typed client + error envelope,
10
+ verification-403 interception, token refresh seam, TanStack Query layer, i18n
11
+ engine, and the analytics facade.
12
+
13
+ ## Install
14
+
15
+ ```
16
+ pnpm add @stapel/auth-react @stapel/core @tanstack/react-query react
17
+ ```
18
+
19
+ ## Wire the app once
20
+
21
+ `createAuthRuntime` is the single place the flagship seams are connected: it
22
+ builds a `StapelClient` whose token refresh comes from the session and whose
23
+ `onVerificationChallenge` is the verification controller. Hand that client to
24
+ core's provider.
25
+
26
+ ```tsx
27
+ import {
28
+ createStapelQueryClient,
29
+ StapelConfigProvider,
30
+ I18nProvider,
31
+ createI18n,
32
+ } from "@stapel/core";
33
+ import { QueryClientProvider } from "@tanstack/react-query";
34
+ import {
35
+ createAuthRuntime,
36
+ AuthProvider,
37
+ VerificationChallenge,
38
+ registerAuthI18n,
39
+ } from "@stapel/auth-react";
40
+
41
+ const runtime = createAuthRuntime({
42
+ baseUrl: "/auth/api",
43
+ // cookieMode: true, // httponly JWT cookies instead of bearer
44
+ onTeardown: (reason) => { // auth-sa.md §19.3
45
+ void query.purgePersistedCache();
46
+ location.assign(reason === "revoked" ? "/sign-in?session_revoked=1" : "/sign-in");
47
+ },
48
+ });
49
+
50
+ const query = createStapelQueryClient({ cacheVersion: "0.1.0" });
51
+ const i18n = createI18n({ locale: "en" });
52
+ registerAuthI18n(i18n); // auth-react's key bundle → core's engine
53
+
54
+ export function Root({ children }: { children: React.ReactNode }) {
55
+ return (
56
+ <StapelConfigProvider config={{ client: runtime.client }} analytics={analytics}>
57
+ <QueryClientProvider client={query.queryClient}>
58
+ <I18nProvider i18n={i18n}>
59
+ <AuthProvider runtime={runtime}>
60
+ {children}
61
+ {/* Mount ONCE — renders your step-up modal on demand */}
62
+ <VerificationChallenge>
63
+ {({ state, chooseFactor, submitCode, cancel }) => (
64
+ <YourModal open={state.step !== "idle"} onClose={cancel}>
65
+ {/* render state.challenge.factors → chooseFactor(f) → submitCode({code}) */}
66
+ </YourModal>
67
+ )}
68
+ </VerificationChallenge>
69
+ </AuthProvider>
70
+ </I18nProvider>
71
+ </QueryClientProvider>
72
+ </StapelConfigProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ## Use a headless component
78
+
79
+ ```tsx
80
+ import { PasswordlessLogin } from "@stapel/auth-react";
81
+ import { useT } from "@stapel/core";
82
+
83
+ function SignIn() {
84
+ const t = useT();
85
+ return (
86
+ <PasswordlessLogin>
87
+ {({ state, requestCode, submitCode, resend }) => {
88
+ if (state.step === "codeSent" || state.step === "codeError")
89
+ return (
90
+ <CodeForm
91
+ hint={t("auth.otp.sent_to", { target: state.target })}
92
+ error={state.step === "codeError" ? t(state.error.code, state.error.params) : null}
93
+ onSubmit={submitCode}
94
+ onResend={() => resend()}
95
+ />
96
+ );
97
+ if (state.step === "authenticated") return <Redirect to="/app" />;
98
+ return <EmailForm onSubmit={(email) => requestCode("email", email)} />;
99
+ }}
100
+ </PasswordlessLogin>
101
+ );
102
+ }
103
+ ```
104
+
105
+ Error codes on every flow error state are backend `localizable_error` keys —
106
+ resolve them with core's `useT()`. auth-react ships an English fallback bundle
107
+ (`registerAuthI18n`) covering both its UI keys and the auth-sa.md error codes.
108
+
109
+ ## Shadcn mode (frontend-standard §7)
110
+
111
+ Every headless component is app-layer by definition — copy it into your repo
112
+ and own it while keeping `api/`/`model/`/`flows/` as a dependency. Visual
113
+ divergence never forks the package.
114
+
115
+ See **[MODULE.md](./MODULE.md)** for the full flow/hook catalogue, extension
116
+ points, and which journeys are full vs thin-WebAuthn.
@@ -0,0 +1,68 @@
1
+ import type { StapelClient } from "@stapel/core";
2
+ import type { AuthResponse, AuditPage, AuthSession, Capabilities, ChangeOldVerifiedResponse, DelayedChangeInitiatedResponse, DelayedChangeStatus, LoginResponse, OtpChannel, OtpRequestResponse, Passkey, PasskeyAuthenticateBeginResponse, PasskeyRegisterBeginResponse, PasswordMethods, QrGenerateResponse, QrStatusResponse, QrType, RefreshResponse, SecurityStatus, SsoLookupResponse, StapelUser, StatusResponse, TotpDisableRequest, TotpSetupConfirmResponse, TotpSetupResponse, VerificationCompleteResponse, VerificationEnvelope, VerificationFactorId, VerificationInitiateResponse } from "./types.js";
3
+ /**
4
+ * The typed auth surface. One method per auth-sa.md endpoint that a JS client
5
+ * may call. Browser-redirect endpoints (OAuth authorize, SSO login, QR scan,
6
+ * magic-link verify) are intentionally absent — see `authUrls`.
7
+ */
8
+ export interface AuthApi {
9
+ readonly client: StapelClient;
10
+ capabilities(): Promise<Capabilities>;
11
+ me(): Promise<StapelUser>;
12
+ logout(): Promise<StatusResponse>;
13
+ otpRequest(channel: OtpChannel, value: string, captchaToken?: string): Promise<OtpRequestResponse>;
14
+ otpVerify(channel: OtpChannel, value: string, code: string): Promise<AuthResponse>;
15
+ passwordLogin(login: string, password: string): Promise<LoginResponse>;
16
+ passwordMethods(): Promise<PasswordMethods>;
17
+ passwordChange(oldPassword: string, newPassword: string): Promise<StatusResponse>;
18
+ passwordChangeOtpRequest(method: OtpChannel): Promise<OtpRequestResponse>;
19
+ passwordChangeOtpVerify(method: OtpChannel, code: string, newPassword: string): Promise<StatusResponse>;
20
+ passwordResetRequest(channel: OtpChannel, value: string): Promise<OtpRequestResponse>;
21
+ passwordResetVerify(channel: OtpChannel, value: string, code: string, newPassword: string): Promise<AuthResponse>;
22
+ anonymous(deviceId?: string): Promise<AuthResponse>;
23
+ oauthLogin(provider: string, accessToken: string): Promise<LoginResponse>;
24
+ totpChallengeVerify(challengeToken: string, proof: {
25
+ code?: string;
26
+ backup_code?: string;
27
+ }): Promise<AuthResponse>;
28
+ totpSetup(): Promise<TotpSetupResponse>;
29
+ totpSetupConfirm(code: string): Promise<TotpSetupConfirmResponse>;
30
+ totpDisable(request: TotpDisableRequest): Promise<StatusResponse>;
31
+ totpDisableOtpRequest(): Promise<OtpRequestResponse>;
32
+ verificationGet(challengeId: string): Promise<VerificationEnvelope>;
33
+ verificationInitiate(challengeId: string, factor: VerificationFactorId): Promise<VerificationInitiateResponse>;
34
+ verificationComplete(challengeId: string, body: Record<string, unknown>): Promise<VerificationCompleteResponse>;
35
+ securityStatus(): Promise<SecurityStatus>;
36
+ sessions(): Promise<readonly AuthSession[]>;
37
+ confirmSession(id: string): Promise<StatusResponse>;
38
+ revokeSession(id: string): Promise<StatusResponse>;
39
+ revokeOtherSessions(): Promise<StatusResponse>;
40
+ tokenRefresh(refresh?: string): Promise<RefreshResponse>;
41
+ qrGenerate(type: QrType, redirectUrl: string, allowUnauthenticatedScanner?: boolean): Promise<QrGenerateResponse>;
42
+ qrStatus(key: string): Promise<QrStatusResponse>;
43
+ qrConfirm(key: string): Promise<StatusResponse>;
44
+ qrReject(key: string): Promise<StatusResponse>;
45
+ magicRequest(email: string, redirectUrl?: string): Promise<StatusResponse>;
46
+ passkeys(): Promise<readonly Passkey[]>;
47
+ passkeyRegisterBegin(): Promise<PasskeyRegisterBeginResponse>;
48
+ passkeyRegisterComplete(credential: unknown, deviceName?: string): Promise<Passkey>;
49
+ passkeyAuthenticateBegin(email?: string): Promise<PasskeyAuthenticateBeginResponse>;
50
+ passkeyAuthenticateComplete(sessionKey: string, credential: unknown): Promise<AuthResponse>;
51
+ passkeyRemove(id: string): Promise<void>;
52
+ changeInstantRequestOld(channel: OtpChannel): Promise<OtpRequestResponse>;
53
+ changeInstantVerifyOld(channel: OtpChannel, code: string): Promise<ChangeOldVerifiedResponse>;
54
+ changeInstantRequestNew(channel: OtpChannel, value: string, changeToken: string): Promise<OtpRequestResponse>;
55
+ changeInstantVerifyNew(channel: OtpChannel, value: string, code: string, changeToken: string): Promise<AuthResponse>;
56
+ changeDelayedInitiate(channel: OtpChannel, value: string): Promise<DelayedChangeInitiatedResponse>;
57
+ changeDelayedStatus(channel: OtpChannel): Promise<DelayedChangeStatus>;
58
+ changeDelayedCancel(channel: OtpChannel, changeRequestId: string): Promise<StatusResponse>;
59
+ ssoLookup(domain: string): Promise<SsoLookupResponse>;
60
+ auditLog(page?: number): Promise<AuditPage>;
61
+ }
62
+ /**
63
+ * Build the auth API bound to an injected {@link StapelClient} (per-module
64
+ * override from `StapelProvider`, the fork-resolution seam of §7.2). All
65
+ * mutations carry the CSRF header.
66
+ */
67
+ export declare function createAuthApi(client: StapelClient): AuthApi;
68
+ //# sourceMappingURL=authApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authApi.d.ts","sourceRoot":"","sources":["../../src/api/authApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * CSRF rule for cookie-authenticated browser clients (auth-sa.md §"CSRF"):
3
+ * the simplest SPA rule is to always send `X-Requested-With: XMLHttpRequest`
4
+ * on mutating requests. Header-token clients are exempt but it is harmless
5
+ * for them, so we send it on every mutation.
6
+ */
7
+ const CSRF_HEADERS = {
8
+ "X-Requested-With": "XMLHttpRequest",
9
+ };
10
+ function mutating(options) {
11
+ return {
12
+ ...options,
13
+ headers: { ...CSRF_HEADERS, ...options?.headers },
14
+ };
15
+ }
16
+ /**
17
+ * Build the auth API bound to an injected {@link StapelClient} (per-module
18
+ * override from `StapelProvider`, the fork-resolution seam of §7.2). All
19
+ * mutations carry the CSRF header.
20
+ */
21
+ export function createAuthApi(client) {
22
+ return {
23
+ client,
24
+ capabilities: () => client.get("/capabilities/"),
25
+ me: () => client.get("/me/"),
26
+ logout: () => client.post("/logout/", undefined, mutating()),
27
+ otpRequest: (channel, value, captchaToken) => client.post(`/${channel}/request/`, captchaToken === undefined
28
+ ? { [channel]: value }
29
+ : { [channel]: value, captcha_token: captchaToken }, mutating()),
30
+ otpVerify: (channel, value, code) => client.post(`/${channel}/verify/`, { [channel]: value, code }, mutating()),
31
+ passwordLogin: (login, password) => client.post("/password/login/", { login, password }, mutating()),
32
+ passwordMethods: () => client.get("/password/methods/"),
33
+ passwordChange: (oldPassword, newPassword) => client.post("/password/change/", { old_password: oldPassword, new_password: newPassword }, mutating()),
34
+ passwordChangeOtpRequest: (method) => client.post("/password/change/otp/request/", { method }, mutating()),
35
+ passwordChangeOtpVerify: (method, code, newPassword) => client.post("/password/change/otp/verify/", { method, code, new_password: newPassword }, mutating()),
36
+ passwordResetRequest: (channel, value) => client.post(`/password/reset/${channel}/request/`, { [channel]: value }, mutating()),
37
+ passwordResetVerify: (channel, value, code, newPassword) => client.post(`/password/reset/${channel}/verify/`, { [channel]: value, code, new_password: newPassword }, mutating()),
38
+ anonymous: (deviceId) => client.post("/anonymous/", deviceId === undefined ? {} : { device_id: deviceId }, mutating()),
39
+ oauthLogin: (provider, accessToken) => client.post("/oauth/login/", { provider, access_token: accessToken }, mutating()),
40
+ totpChallengeVerify: (challengeToken, proof) => client.post("/totp/challenge/verify/", { challenge_token: challengeToken, ...proof }, mutating()),
41
+ totpSetup: () => client.post("/totp/setup/", undefined, mutating()),
42
+ totpSetupConfirm: (code) => client.post("/totp/setup/confirm/", { code }, mutating()),
43
+ totpDisable: (request) => client.post("/totp/disable/", request, mutating()),
44
+ totpDisableOtpRequest: () => client.post("/totp/disable-otp/request/", undefined, mutating()),
45
+ verificationGet: (challengeId) => client.get(`/verification/${challengeId}/`),
46
+ verificationInitiate: (challengeId, factor) => client.post(`/verification/${challengeId}/initiate/`, { factor }, mutating()),
47
+ verificationComplete: (challengeId, body) => client.post(`/verification/${challengeId}/complete/`, body, mutating()),
48
+ securityStatus: () => client.get("/security/status/"),
49
+ sessions: () => client.get("/sessions/"),
50
+ confirmSession: (id) => client.post(`/sessions/${id}/confirm/`, undefined, mutating()),
51
+ revokeSession: (id) => client.delete(`/sessions/${id}/`, mutating()),
52
+ revokeOtherSessions: () => client.delete("/sessions/", mutating()),
53
+ tokenRefresh: (refresh) => refresh === undefined
54
+ ? client.get("/token/refresh/")
55
+ : client.post("/token/refresh/", { refresh }, mutating()),
56
+ qrGenerate: (type, redirectUrl, allowUnauthenticatedScanner) => client.post("/qr/generate/", allowUnauthenticatedScanner === undefined
57
+ ? { type, redirect_url: redirectUrl }
58
+ : {
59
+ type,
60
+ redirect_url: redirectUrl,
61
+ allow_unauthenticated_scanner: allowUnauthenticatedScanner,
62
+ }, mutating()),
63
+ qrStatus: (key) => client.get(`/qr/${key}/status/`),
64
+ qrConfirm: (key) => client.post(`/qr/${key}/confirm/`, undefined, mutating()),
65
+ qrReject: (key) => client.post(`/qr/${key}/reject/`, undefined, mutating()),
66
+ magicRequest: (email, redirectUrl) => client.post("/magic/request/", redirectUrl === undefined ? { email } : { email, redirect_url: redirectUrl }, mutating()),
67
+ passkeys: () => client
68
+ .get("/passkey/")
69
+ .then((r) => r.passkeys),
70
+ passkeyRegisterBegin: () => client.post("/passkey/register/begin/", undefined, mutating()),
71
+ passkeyRegisterComplete: (credential, deviceName) => client.post("/passkey/register/complete/", deviceName === undefined
72
+ ? { credential }
73
+ : { credential, device_name: deviceName }, mutating()),
74
+ passkeyAuthenticateBegin: (email) => client.post("/passkey/authenticate/begin/", email === undefined ? {} : { email }, mutating()),
75
+ passkeyAuthenticateComplete: (sessionKey, credential) => client.post("/passkey/authenticate/complete/", { session_key: sessionKey, credential }, mutating()),
76
+ passkeyRemove: (id) => client.delete(`/passkey/${id}/`, mutating()),
77
+ changeInstantRequestOld: (channel) => client.post(`/${channel}/change/instant/request-old/`, undefined, mutating()),
78
+ changeInstantVerifyOld: (channel, code) => client.post(`/${channel}/change/instant/verify-old/`, { code }, mutating()),
79
+ changeInstantRequestNew: (channel, value, changeToken) => client.post(`/${channel}/change/instant/request-new/`, { [channel]: value, change_token: changeToken }, mutating()),
80
+ changeInstantVerifyNew: (channel, value, code, changeToken) => client.post(`/${channel}/change/instant/verify-new/`, { [channel]: value, code, change_token: changeToken }, mutating()),
81
+ changeDelayedInitiate: (channel, value) => client.post(`/${channel}/change/delayed/initiate/`, { [channel]: value }, mutating()),
82
+ changeDelayedStatus: (channel) => client.get(`/${channel}/change/delayed/status/`),
83
+ changeDelayedCancel: (channel, changeRequestId) => client.post(`/${channel}/change/delayed/cancel/`, { change_request_id: changeRequestId }, mutating()),
84
+ ssoLookup: (domain) => client.get("/sso/lookup/", { query: { domain } }),
85
+ auditLog: (page) => client.get("/security/audit/", {
86
+ query: page === undefined ? {} : { page },
87
+ }),
88
+ };
89
+ }
90
+ //# sourceMappingURL=authApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authApi.js","sourceRoot":"","sources":["../../src/api/authApi.ts"],"names":[],"mappings":"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"}