@orangecheck/auth-client 2.2.0 → 2.4.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,111 @@
1
+ # Changelog
2
+
3
+ All notable changes to **`@orangecheck/auth-client`** will be documented in this file.
4
+
5
+ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
+ and [Semantic Versioning](https://semver.org/). Wire-format / canonical-message
7
+ changes are coordinated via the relevant `oc-*-protocol` spec repo's CHANGELOG;
8
+ this file tracks the package's TS / Node / runtime API surface.
9
+
10
+ ## [Unreleased]
11
+
12
+ - _(no pending changes)_
13
+
14
+ ## [2.3.0] — 2026-05-14 · `useWebAuthnList.{rename,remove}` discriminated unions
15
+
16
+ Breaking shape change to two hook methods · same pattern that landed for
17
+ `register` / `stepUp` in v2.1.1. The bare `boolean` / `null` return left
18
+ the failure reason in the hook's `error` state, unreadable by the caller
19
+ post-await because of React closure semantics.
20
+
21
+ New shapes:
22
+
23
+ ```ts
24
+ rename(id, label) → Promise<{ ok: true; credential } | { ok: false; reason }>;
25
+ remove(id) → Promise<{ ok: true } | { ok: false; reason }>;
26
+ ```
27
+
28
+ Consumers branch on `result.ok` and read `result.reason` directly. The
29
+ hook's `error` field stays for debug; the awaited return is now the
30
+ source of truth.
31
+
32
+ The package is days old and the only known consumer (me-web's
33
+ `HardwareKeysPanel`) is updated in the same window. No external pins
34
+ break.
35
+
36
+ ## [2.2.0] — 2026-05-14 · Inline sudo-mode redirect helper
37
+
38
+ Additive · two new exports for the consumer-side counterpart to the
39
+ ochk.io `/sudo` page:
40
+
41
+ - `redirectToSudo({ returnTo?, purpose?, config? })` · navigates the
42
+ browser to `https://ochk.io/sudo?return_to=…&purpose=…`. The auth
43
+ host runs an email-OTP or BIP-322 re-authentication ceremony,
44
+ re-issues the session JWT with a fresh `sudo_at` claim, redirects
45
+ back. Consumers retry the original sensitive action once they're
46
+ back; the gate sees the fresh claim and lets it through.
47
+ - `handleSudoRequired(body, args)` · one-liner that checks
48
+ `body.reason === 'sudo_required'` and redirects if so. Returns
49
+ `true` when it redirected (caller should short-circuit), `false`
50
+ otherwise.
51
+
52
+ No React state is involved — the flow is a single browser
53
+ navigation. A future inline-modal version (no redirect) will keep
54
+ the same function names so consumers don't have to change call-sites.
55
+
56
+ Peer dep raised to `@orangecheck/auth-core` `^2.2.0` (for
57
+ `verifySudoClaim` server-side and the `sudo_at` claim shape).
58
+
59
+ ## [2.1.1] — 2026-05-14 · WebAuthn hook error-surface fix
60
+
61
+ Bug fix · `useWebAuthnRegister` and `useStepUpAuth` previously returned
62
+ `null` on failure with the reason buried in the hook's `error` state. The
63
+ caller couldn't read the reason post-await because of React closure
64
+ semantics (the destructured `status` / `error` were captured at render
65
+ time, not after the awaited state update). Symptom: clicking "register
66
+ key" did nothing visible when the underlying request failed (e.g. on
67
+ `session_too_old`).
68
+
69
+ Both hooks now return a discriminated union:
70
+
71
+ ```ts
72
+ register(args) → Promise<{ ok: true; credential } | { ok: false; reason }>;
73
+ stepUp(args) → Promise<{ ok: true; step_up_at } | { ok: false; reason }>;
74
+ ```
75
+
76
+ Consumers branch on `result.ok` and read `result.reason` directly. The
77
+ hook's `error` / `status` fields stay for debug/UX, but the awaited
78
+ return value is now the source of truth for "did this ceremony
79
+ succeed."
80
+
81
+ Breaking only against the v2.1.0 register/stepUp signatures; types
82
+ adjusted in the same package, no semver-major needed because the API
83
+ is hours old and no published consumer pinned 2.1.0.
84
+
85
+ ## [2.1.0] — 2026-05-14 · WebAuthn step-up hooks
86
+
87
+ Additive · all v2.0.0 consumers keep working unchanged. Three new
88
+ React hooks wrap the ochk.io `/api/auth/webauthn/*` surface plus the
89
+ `@simplewebauthn/browser` ceremony:
90
+
91
+ - `useWebAuthnRegister()` — bind a hardware key to the account.
92
+ - `useWebAuthnList()` — list / rename / revoke registered keys.
93
+ - `useStepUpAuth()` — assert against a registered key before a
94
+ sensitive action; on success refreshes the session so
95
+ `verifyStepUpClaim(payload, …)` (from auth-core v2.1.0) flips to
96
+ true immediately.
97
+
98
+ `@simplewebauthn/browser` is now a hard runtime dependency. Bumps
99
+ the peer requirement for `@orangecheck/auth-core` to `^2.1.0` (the
100
+ new `step_up_at` claim + `verifyStepUpClaim` helper).
101
+
102
+ ## [0.1.0] — Initial published state
103
+
104
+ Initial public release. `<OcSessionProvider>`, `useOcSession()`, `<OcSignInButton>`, `<OcAccountPill>` for cross-subdomain ochk.io auth.
105
+
106
+ The package passes its conformance harness in CI on every change. See the
107
+ shared [conformance vectors](https://github.com/orangecheck/oc-packages#conformance)
108
+ section in the monorepo README for the cross-impl byte-equality discipline.
109
+
110
+ [Unreleased]: https://github.com/orangecheck/oc-packages/compare/orangecheck-auth-client-v0.1.0...HEAD
111
+ [0.1.0]: https://github.com/orangecheck/oc-packages/releases/tag/orangecheck-auth-client-v0.1.0
package/dist/index.d.mts CHANGED
@@ -9,6 +9,7 @@ interface OcAccount {
9
9
  nostrNpub?: string | null;
10
10
  homeFederation?: string | null;
11
11
  signingMethod?: 'fedimint_threshold' | 'fedimint_client' | 'bip322' | null;
12
+ isOwner?: boolean;
12
13
  }
13
14
  type OcSessionStatus = 'loading' | 'authenticated' | 'anonymous' | 'error';
14
15
  interface OcSessionState {
@@ -139,13 +140,26 @@ interface UseWebAuthnRegisterReturn {
139
140
  reset: () => void;
140
141
  }
141
142
  declare function useWebAuthnRegister(opts?: UseHostOptions): UseWebAuthnRegisterReturn;
143
+ type WebAuthnRenameResult = {
144
+ ok: true;
145
+ credential: WebAuthnCredentialPublic;
146
+ } | {
147
+ ok: false;
148
+ reason: string;
149
+ };
150
+ type WebAuthnRemoveResult = {
151
+ ok: true;
152
+ } | {
153
+ ok: false;
154
+ reason: string;
155
+ };
142
156
  interface UseWebAuthnListReturn {
143
157
  status: WebAuthnListStatus;
144
158
  credentials: WebAuthnCredentialPublic[];
145
159
  error: Error | null;
146
160
  refetch: () => Promise<void>;
147
- rename: (id: string, label: string) => Promise<WebAuthnCredentialPublic | null>;
148
- remove: (id: string) => Promise<boolean>;
161
+ rename: (id: string, label: string) => Promise<WebAuthnRenameResult>;
162
+ remove: (id: string) => Promise<WebAuthnRemoveResult>;
149
163
  }
150
164
  declare function useWebAuthnList(opts?: UseHostOptions): UseWebAuthnListReturn;
151
165
  type WebAuthnStepUpResult = {
@@ -177,4 +191,4 @@ declare function handleSudoRequired(body: {
177
191
  returnTo?: string;
178
192
  }): boolean;
179
193
 
180
- export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnStepUpResult, buildSignInUrl, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
194
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildSignInUrl, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ interface OcAccount {
9
9
  nostrNpub?: string | null;
10
10
  homeFederation?: string | null;
11
11
  signingMethod?: 'fedimint_threshold' | 'fedimint_client' | 'bip322' | null;
12
+ isOwner?: boolean;
12
13
  }
13
14
  type OcSessionStatus = 'loading' | 'authenticated' | 'anonymous' | 'error';
14
15
  interface OcSessionState {
@@ -139,13 +140,26 @@ interface UseWebAuthnRegisterReturn {
139
140
  reset: () => void;
140
141
  }
141
142
  declare function useWebAuthnRegister(opts?: UseHostOptions): UseWebAuthnRegisterReturn;
143
+ type WebAuthnRenameResult = {
144
+ ok: true;
145
+ credential: WebAuthnCredentialPublic;
146
+ } | {
147
+ ok: false;
148
+ reason: string;
149
+ };
150
+ type WebAuthnRemoveResult = {
151
+ ok: true;
152
+ } | {
153
+ ok: false;
154
+ reason: string;
155
+ };
142
156
  interface UseWebAuthnListReturn {
143
157
  status: WebAuthnListStatus;
144
158
  credentials: WebAuthnCredentialPublic[];
145
159
  error: Error | null;
146
160
  refetch: () => Promise<void>;
147
- rename: (id: string, label: string) => Promise<WebAuthnCredentialPublic | null>;
148
- remove: (id: string) => Promise<boolean>;
161
+ rename: (id: string, label: string) => Promise<WebAuthnRenameResult>;
162
+ remove: (id: string) => Promise<WebAuthnRemoveResult>;
149
163
  }
150
164
  declare function useWebAuthnList(opts?: UseHostOptions): UseWebAuthnListReturn;
151
165
  type WebAuthnStepUpResult = {
@@ -177,4 +191,4 @@ declare function handleSudoRequired(body: {
177
191
  returnTo?: string;
178
192
  }): boolean;
179
193
 
180
- export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnStepUpResult, buildSignInUrl, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
194
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildSignInUrl, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
package/dist/index.js CHANGED
@@ -57,7 +57,8 @@ function normalizeAccount(raw) {
57
57
  displayName: raw.display_name ?? raw.displayName ?? null,
58
58
  nostrNpub: raw.nostr_npub ?? raw.nostrNpub ?? null,
59
59
  homeFederation: raw.home_federation_slug ?? raw.homeFederation ?? null,
60
- signingMethod: raw.signing_method ?? raw.signingMethod ?? null
60
+ signingMethod: raw.signing_method ?? raw.signingMethod ?? null,
61
+ isOwner: Boolean(raw.is_owner ?? raw.isOwner ?? false)
61
62
  };
62
63
  }
63
64
  function OcSessionProvider({
@@ -1395,14 +1396,16 @@ function useWebAuthnList(opts) {
1395
1396
  });
1396
1397
  const j = await r.json();
1397
1398
  if (!j.ok || !j.credential) {
1398
- setError(new Error(j.reason ?? "rename_failed"));
1399
- return null;
1399
+ const reason = j.reason ?? `rename_failed_${r.status}`;
1400
+ setError(new Error(reason));
1401
+ return { ok: false, reason };
1400
1402
  }
1401
1403
  await refetch();
1402
- return j.credential;
1404
+ return { ok: true, credential: j.credential };
1403
1405
  } catch (e) {
1404
- setError(e instanceof Error ? e : new Error(String(e)));
1405
- return null;
1406
+ const reason = e instanceof Error ? e.message : String(e);
1407
+ setError(new Error(reason));
1408
+ return { ok: false, reason };
1406
1409
  }
1407
1410
  },
1408
1411
  [authOrigin, refetch]
@@ -1416,14 +1419,16 @@ function useWebAuthnList(opts) {
1416
1419
  });
1417
1420
  const j = await r.json();
1418
1421
  if (!j.ok) {
1419
- setError(new Error(j.reason ?? "delete_failed"));
1420
- return false;
1422
+ const reason = j.reason ?? `delete_failed_${r.status}`;
1423
+ setError(new Error(reason));
1424
+ return { ok: false, reason };
1421
1425
  }
1422
1426
  await refetch();
1423
- return true;
1427
+ return { ok: true };
1424
1428
  } catch (e) {
1425
- setError(e instanceof Error ? e : new Error(String(e)));
1426
- return false;
1429
+ const reason = e instanceof Error ? e.message : String(e);
1430
+ setError(new Error(reason));
1431
+ return { ok: false, reason };
1427
1432
  }
1428
1433
  },
1429
1434
  [authOrigin, refetch]