@rakomi/node 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +57 -1
- package/SECURITY.md +206 -0
- package/dist/agents.d.ts +90 -0
- package/dist/agents.js +203 -0
- package/dist/anonymous.d.ts +50 -0
- package/dist/anonymous.js +105 -0
- package/dist/ciba.d.ts +97 -0
- package/dist/ciba.js +282 -0
- package/dist/client.d.ts +93 -0
- package/dist/client.js +202 -0
- package/dist/credentials.d.ts +87 -0
- package/dist/credentials.js +104 -0
- package/dist/device.d.ts +76 -0
- package/dist/device.js +244 -0
- package/dist/doctor.d.ts +11 -0
- package/dist/doctor.js +135 -0
- package/dist/dpop-session.d.ts +90 -0
- package/dist/dpop-session.js +127 -0
- package/dist/dpop.d.ts +24 -0
- package/dist/dpop.js +51 -0
- package/dist/env-detect.d.ts +11 -0
- package/dist/env-detect.js +26 -0
- package/dist/errors.d.ts +307 -0
- package/dist/errors.js +385 -0
- package/dist/eudi.d.ts +23 -0
- package/dist/eudi.js +27 -0
- package/dist/flags.d.ts +50 -0
- package/dist/flags.js +173 -0
- package/dist/guards.d.ts +16 -0
- package/dist/guards.js +104 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +18 -0
- package/dist/internal/canonical-url.d.ts +13 -0
- package/dist/internal/canonical-url.js +52 -0
- package/dist/internal/shared-constants.d.ts +3 -0
- package/dist/internal/shared-constants.js +3 -0
- package/dist/jwks-cache.d.ts +31 -0
- package/dist/jwks-cache.js +135 -0
- package/dist/link.d.ts +73 -0
- package/dist/link.js +262 -0
- package/dist/middleware.d.ts +21 -0
- package/dist/middleware.js +84 -0
- package/dist/oauth.d.ts +46 -0
- package/dist/oauth.js +457 -0
- package/dist/rbac.d.ts +12 -0
- package/dist/rbac.js +20 -0
- package/dist/token-exchange.d.ts +65 -0
- package/dist/token-exchange.js +163 -0
- package/dist/types.d.ts +436 -0
- package/dist/types.js +1 -0
- package/dist/verify-publisher-webhook.d.ts +25 -0
- package/dist/verify-publisher-webhook.js +47 -0
- package/dist/verify-token.d.ts +3 -0
- package/dist/verify-token.js +148 -0
- package/dist/verify-webhook.d.ts +7 -0
- package/dist/verify-webhook.js +101 -0
- package/package.json +61 -5
- package/sbom.cdx.json +52 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request environment detection based on hostname.
|
|
3
|
+
* Safe default: production (never accidentally expose verbose errors).
|
|
4
|
+
*/
|
|
5
|
+
import type { SdkEnvironment } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Detect environment from request hostname.
|
|
8
|
+
* Returns 'development' for localhost, 127.0.0.1, ::1, *.local.
|
|
9
|
+
* Returns 'production' for everything else (safe default).
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectEnvironment(hostname: string): SdkEnvironment;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request environment detection based on hostname.
|
|
3
|
+
* Safe default: production (never accidentally expose verbose errors).
|
|
4
|
+
*/
|
|
5
|
+
const DEV_HOSTNAMES = new Set(['localhost', '127.0.0.1', '::1', '[::1]']);
|
|
6
|
+
/**
|
|
7
|
+
* Detect environment from request hostname.
|
|
8
|
+
* Returns 'development' for localhost, 127.0.0.1, ::1, *.local.
|
|
9
|
+
* Returns 'production' for everything else (safe default).
|
|
10
|
+
*/
|
|
11
|
+
export function detectEnvironment(hostname) {
|
|
12
|
+
if (!hostname)
|
|
13
|
+
return 'production';
|
|
14
|
+
if (DEV_HOSTNAMES.has(hostname))
|
|
15
|
+
return 'development';
|
|
16
|
+
const host = hostname.includes(']:')
|
|
17
|
+
? hostname.slice(1, hostname.indexOf(']'))
|
|
18
|
+
: hostname.lastIndexOf(':') > hostname.indexOf(':')
|
|
19
|
+
? hostname
|
|
20
|
+
: hostname.split(':')[0];
|
|
21
|
+
if (DEV_HOSTNAMES.has(host))
|
|
22
|
+
return 'development';
|
|
23
|
+
if (host.endsWith('.local'))
|
|
24
|
+
return 'development';
|
|
25
|
+
return 'production';
|
|
26
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import type { SdkError } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Error class thrown by Rakomi constructor for configuration errors.
|
|
4
|
+
* Extends Error so `instanceof Error` works and stack traces are available.
|
|
5
|
+
*/
|
|
6
|
+
export declare class RakomiError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly suggestion: string;
|
|
9
|
+
readonly docs_url: string;
|
|
10
|
+
readonly fix_command?: string;
|
|
11
|
+
constructor(sdkError: SdkError);
|
|
12
|
+
}
|
|
13
|
+
export declare const ERROR_CODES: {
|
|
14
|
+
readonly TOKEN_REVOKED: "token/revoked";
|
|
15
|
+
readonly TOKEN_EXPIRED: "token/expired";
|
|
16
|
+
readonly TOKEN_INVALID_SIGNATURE: "token/invalid_signature";
|
|
17
|
+
readonly TOKEN_MALFORMED: "token/malformed";
|
|
18
|
+
readonly TOKEN_INVALID_ALGORITHM: "token/invalid_algorithm";
|
|
19
|
+
readonly TOKEN_MISSING_CLAIMS: "token/missing_claims";
|
|
20
|
+
readonly TOKEN_INVALID_ISSUER: "token/invalid_issuer";
|
|
21
|
+
readonly TOKEN_INVALID_AUDIENCE: "token/invalid_audience";
|
|
22
|
+
readonly TOKEN_NOT_YET_VALID: "token/not_yet_valid";
|
|
23
|
+
readonly AUTH_ENVIRONMENT_MISMATCH: "auth/environment_mismatch";
|
|
24
|
+
readonly AUTH_DPOP_PROVER_UNAVAILABLE: "auth/dpop_prover_unavailable";
|
|
25
|
+
readonly AUTH_INVALID_DPOP_PROOF: "auth/invalid_dpop_proof";
|
|
26
|
+
readonly AUTH_INVALID_REFRESH_TOKEN: "auth/invalid_refresh_token";
|
|
27
|
+
readonly AUTH_DPOP_ROTATION_NOOP: "auth/dpop_rotation_noop";
|
|
28
|
+
readonly AUTH_DPOP_ROTATION_DID_NOT_TAKE: "auth/dpop_rotation_did_not_take";
|
|
29
|
+
readonly AUTH_REFRESH_SUPERSEDED_BY_ROTATION: "auth/refresh_superseded_by_rotation";
|
|
30
|
+
readonly JWKS_FETCH_FAILED: "jwks/fetch_failed";
|
|
31
|
+
readonly JWKS_NO_MATCHING_KEY: "jwks/no_matching_key";
|
|
32
|
+
readonly JWKS_INVALID_RESPONSE: "jwks/invalid_response";
|
|
33
|
+
readonly WEBHOOK_TIMESTAMP_TOO_OLD: "webhook/timestamp_too_old";
|
|
34
|
+
readonly WEBHOOK_TIMESTAMP_TOO_NEW: "webhook/timestamp_too_new";
|
|
35
|
+
readonly WEBHOOK_INVALID_SIGNATURE: "webhook/invalid_signature";
|
|
36
|
+
readonly WEBHOOK_INVALID_SECRET: "webhook/invalid_secret";
|
|
37
|
+
readonly WEBHOOK_MISSING_HEADER: "webhook/missing_header";
|
|
38
|
+
readonly WEBHOOK_INVALID_BODY: "webhook/invalid_body";
|
|
39
|
+
};
|
|
40
|
+
export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
41
|
+
export declare const TOKEN_REVOKED: () => SdkError;
|
|
42
|
+
export declare const TOKEN_EXPIRED: () => SdkError;
|
|
43
|
+
export declare const TOKEN_INVALID_SIGNATURE: () => SdkError;
|
|
44
|
+
export declare const TOKEN_MALFORMED: () => SdkError;
|
|
45
|
+
export declare const TOKEN_INVALID_ALGORITHM: () => SdkError;
|
|
46
|
+
export declare const TOKEN_MISSING_CLAIMS: () => SdkError;
|
|
47
|
+
export declare const TOKEN_INVALID_ISSUER: () => SdkError;
|
|
48
|
+
export declare const TOKEN_INVALID_AUDIENCE: () => SdkError;
|
|
49
|
+
export declare const TOKEN_NOT_YET_VALID: () => SdkError;
|
|
50
|
+
export declare const AUTH_ENVIRONMENT_MISMATCH: () => SdkError;
|
|
51
|
+
/**
|
|
52
|
+
* Client-side: this SDK/platform could not produce a DPoP proof here (no native
|
|
53
|
+
* prover, or the signer threw / returned falsy). NOT a security event — the SDK
|
|
54
|
+
* deliberately refused to send an empty/malformed `DPoP` header rather than
|
|
55
|
+
* silently downgrade to Bearer. App action: report a bug / re-login.
|
|
56
|
+
*/
|
|
57
|
+
export declare const AUTH_DPOP_PROVER_UNAVAILABLE: (detail?: string) => SdkError;
|
|
58
|
+
/**
|
|
59
|
+
* Server rejected the DPoP proof on the refresh request (signature / `htu` /
|
|
60
|
+
* `htm` / replayed `jti` / cold-start key mismatch). App action: re-attach a
|
|
61
|
+
* fresh proof, check device clock skew, or re-authenticate to re-bind the key.
|
|
62
|
+
*/
|
|
63
|
+
export declare const AUTH_INVALID_DPOP_PROOF: (detail?: string) => SdkError;
|
|
64
|
+
/**
|
|
65
|
+
* The refresh token itself is invalid, expired, or has been revoked (the
|
|
66
|
+
* genuine end-of-session class — RFC 6749 `invalid_grant` on the refresh
|
|
67
|
+
* operation). App action: start a full re-authentication (login) flow.
|
|
68
|
+
*/
|
|
69
|
+
export declare const AUTH_INVALID_REFRESH_TOKEN: (detail?: string) => SdkError;
|
|
70
|
+
/**
|
|
71
|
+
* Client-side rotation bug: the SDK attempted to rotate to a key the server
|
|
72
|
+
* already has bound (server `400 invalid_request` reason `rotation_noop`). NOT a
|
|
73
|
+
* security event and NO re-login — the session is unchanged. A fresh keypair
|
|
74
|
+
* makes this practically unreachable from the SDK; it surfaces only if a caller
|
|
75
|
+
* forces the new key to equal the old. App action: drop the rotation, keep using
|
|
76
|
+
* the current session.
|
|
77
|
+
*/
|
|
78
|
+
export declare const AUTH_DPOP_ROTATION_NOOP: (detail?: string) => SdkError;
|
|
79
|
+
/**
|
|
80
|
+
* The rotation did not take AND no usable refreshed token was obtained. This is the
|
|
81
|
+
* FAILURE arm — distinct from the common rotation-unaware-server case where the
|
|
82
|
+
* refresh itself succeeds (that returns `{ ok: true, data: { ...tokens, rotated: false } }` — a
|
|
83
|
+
* {@link RotationTokenResponse} the caller MUST persist). This error fires
|
|
84
|
+
* only when there is nothing to persist:
|
|
85
|
+
* - a rotation that lost the token-keyed gate to a concurrent ordinary refresh of
|
|
86
|
+
* the same one-time-use token (fail-SAFE, NO network call, OLD key still bound);
|
|
87
|
+
* - the unreachable-by-construction local pre-swap invariant refusing a swap the
|
|
88
|
+
* server DID confirm (a new-key-bound token the SDK has no prover for).
|
|
89
|
+
* The OLD key is STILL bound (never a half-swap). App action: retry the rotation, or
|
|
90
|
+
* re-authenticate if it keeps not taking.
|
|
91
|
+
*/
|
|
92
|
+
export declare const AUTH_DPOP_ROTATION_DID_NOT_TAKE: (detail?: string) => SdkError;
|
|
93
|
+
/**
|
|
94
|
+
* A refresh and a key-rotation were attempted concurrently on the SAME
|
|
95
|
+
* refresh_token. The server one-time-uses + rotates the refresh token on
|
|
96
|
+
* every success, so the two operations can never both spend the same token value
|
|
97
|
+
* without tripping server refresh-reuse detection (which revokes ALL session
|
|
98
|
+
* tokens). The SDK serializes every refresh_token-consuming operation through one
|
|
99
|
+
* token-keyed choke point: a key rotation already owns this token, so THIS
|
|
100
|
+
* ordinary refresh was NOT sent (fail-SAFE — no network call, no double-spend).
|
|
101
|
+
* The session/binding are unchanged. App action: use the rotation's result (it
|
|
102
|
+
* also delivers fresh tokens), or retry the refresh with the rotated
|
|
103
|
+
* refresh_token once the rotation settles.
|
|
104
|
+
*/
|
|
105
|
+
export declare const AUTH_REFRESH_SUPERSEDED_BY_ROTATION: (detail?: string) => SdkError;
|
|
106
|
+
export declare const JWKS_FETCH_FAILED: (detail?: string) => SdkError;
|
|
107
|
+
export declare const JWKS_NO_MATCHING_KEY: () => SdkError;
|
|
108
|
+
export declare const JWKS_INVALID_RESPONSE: () => SdkError;
|
|
109
|
+
export declare const WEBHOOK_TIMESTAMP_TOO_OLD: (tolerance: number) => SdkError;
|
|
110
|
+
export declare const WEBHOOK_TIMESTAMP_TOO_NEW: (tolerance: number) => SdkError;
|
|
111
|
+
/** @deprecated Use WEBHOOK_TIMESTAMP_TOO_OLD or WEBHOOK_TIMESTAMP_TOO_NEW */
|
|
112
|
+
export declare const WEBHOOK_TIMESTAMP_EXPIRED: () => SdkError;
|
|
113
|
+
export declare const WEBHOOK_INVALID_SIGNATURE: () => SdkError;
|
|
114
|
+
export declare const WEBHOOK_INVALID_SECRET: () => SdkError;
|
|
115
|
+
export declare const WEBHOOK_MISSING_HEADER: () => SdkError;
|
|
116
|
+
export declare const WEBHOOK_INVALID_BODY: () => SdkError;
|
|
117
|
+
export declare const CONFIG_MISSING_API_KEY: () => SdkError;
|
|
118
|
+
export declare const CONFIG_INVALID_BASE_URL: () => SdkError;
|
|
119
|
+
export declare const CONFIG_MISSING_WEBHOOK_SECRET: () => SdkError;
|
|
120
|
+
export declare const OAUTH_INVALID_GRANT: (detail?: string) => SdkError;
|
|
121
|
+
export declare const OAUTH_INVALID_CLIENT: (detail?: string) => SdkError;
|
|
122
|
+
export declare const OAUTH_INVALID_REQUEST: (detail?: string) => SdkError;
|
|
123
|
+
export declare const OAUTH_UNSUPPORTED_GRANT_TYPE: (detail?: string) => SdkError;
|
|
124
|
+
export declare const OAUTH_NETWORK_ERROR: (detail?: string) => SdkError;
|
|
125
|
+
export declare const OAUTH_MISSING_CLIENT_ID: () => SdkError;
|
|
126
|
+
export declare const OAUTH_MISSING_CLIENT_SECRET: () => SdkError;
|
|
127
|
+
export declare const DEVICE_AUTHORIZATION_PENDING: (detail?: string) => SdkError;
|
|
128
|
+
export declare const DEVICE_AUTHORIZATION_SLOW_DOWN: (detail?: string) => SdkError;
|
|
129
|
+
export declare const DEVICE_AUTHORIZATION_DENIED: (detail?: string) => SdkError;
|
|
130
|
+
export declare const DEVICE_AUTHORIZATION_EXPIRED: (detail?: string) => SdkError;
|
|
131
|
+
export declare const DEVICE_AUTHORIZATION_TIMEOUT: (detail?: string) => SdkError;
|
|
132
|
+
export declare const DEVICE_AUTHORIZATION_RATE_LIMITED: (detail?: string) => SdkError;
|
|
133
|
+
export declare const ANONYMOUS_DISABLED: () => SdkError;
|
|
134
|
+
export declare const ANONYMOUS_RATE_LIMITED: (retryAfterSeconds?: number) => SdkError;
|
|
135
|
+
export declare const ANONYMOUS_MAU_EXHAUSTED: () => SdkError;
|
|
136
|
+
export declare const ANONYMOUS_NETWORK_ERROR: (detail?: string) => SdkError;
|
|
137
|
+
/**
|
|
138
|
+
* Thrown by the auto-refresh path when a refresh returns 401 AND the prior
|
|
139
|
+
* access token was marked `is_anonymous: true`. Distinguishes "the tenant
|
|
140
|
+
* purged your anon user" from generic auth failures so apps can prompt a
|
|
141
|
+
* fresh `client.anonymous` rather than sending the user to a login screen.
|
|
142
|
+
*
|
|
143
|
+
* Carries `suggestedAction: 'call_anonymous'` as a stable hint for DX-level
|
|
144
|
+
* UX routing (DX thread).
|
|
145
|
+
*/
|
|
146
|
+
export declare class AnonymousSessionExpiredError extends Error {
|
|
147
|
+
readonly code = "anonymous/session_expired";
|
|
148
|
+
readonly suggestedAction: "call_anonymous()";
|
|
149
|
+
readonly suggestion: string;
|
|
150
|
+
readonly docs_url: string;
|
|
151
|
+
constructor(message?: string);
|
|
152
|
+
}
|
|
153
|
+
export declare const ACCOUNT_LINKING_NETWORK_ERROR: (detail?: string) => SdkError;
|
|
154
|
+
export declare const ACCOUNT_LINKING_RATE_LIMITED: (retryAfterSeconds?: number) => SdkError;
|
|
155
|
+
export declare const ACCOUNT_LINKING_IDENTITY_NOT_FOUND: () => SdkError;
|
|
156
|
+
/**
|
|
157
|
+
* Thrown when POST /v1/users/me/link/{provider} returns 403 —
|
|
158
|
+
* tenant has disabled explicit self-service linking.
|
|
159
|
+
*/
|
|
160
|
+
export declare class AccountLinkingDisabledError extends Error {
|
|
161
|
+
readonly code = "account_linking/disabled_for_tenant";
|
|
162
|
+
readonly suggestion: string;
|
|
163
|
+
readonly docs_url: string;
|
|
164
|
+
readonly retryAfterSeconds?: number;
|
|
165
|
+
constructor(message?: string);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Thrown when a link attempt finds the identity already owned by a different user.
|
|
169
|
+
* Never include details about the other user — anti-enumeration invariant.
|
|
170
|
+
*/
|
|
171
|
+
export declare class IdentityOwnedByOtherUserError extends Error {
|
|
172
|
+
readonly code = "account_linking/identity_owned_by_other_user";
|
|
173
|
+
readonly suggestion: string;
|
|
174
|
+
readonly docs_url: string;
|
|
175
|
+
constructor(message?: string);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Thrown when DELETE /v1/users/me/link/{provider} would remove the user's last
|
|
179
|
+
* sign-in method. Includes the remaining method kinds to inform UX.
|
|
180
|
+
*/
|
|
181
|
+
export declare class CannotUnlinkLastMethodError extends Error {
|
|
182
|
+
readonly code = "account_linking/cannot_unlink_last_method";
|
|
183
|
+
readonly suggestion: string;
|
|
184
|
+
readonly docs_url: string;
|
|
185
|
+
readonly remaining_methods: readonly string[];
|
|
186
|
+
constructor(remainingMethods?: readonly string[], message?: string);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Thrown when a high-risk operation is attempted within the 1-hour post-link
|
|
190
|
+
* cooldown window. Semantically distinct from rate-limit
|
|
191
|
+
* 429s: clients should surface a localized "try again at {time}" hint rather
|
|
192
|
+
* than "too many requests".
|
|
193
|
+
*
|
|
194
|
+
* Exposes both `unlockAt: Date` and `unlockAtIso: string` so consumers can
|
|
195
|
+
* format the timestamp without re-parsing.
|
|
196
|
+
*/
|
|
197
|
+
export declare class CooldownActiveError extends Error {
|
|
198
|
+
readonly code = "account_linking/cooldown_active";
|
|
199
|
+
readonly suggestion: string;
|
|
200
|
+
readonly docs_url: string;
|
|
201
|
+
readonly unlockAt: Date;
|
|
202
|
+
readonly unlockAtIso: string;
|
|
203
|
+
/**
|
|
204
|
+
* User-facing discriminator so consumer UX can render a distinct copy path
|
|
205
|
+
* ("you recently linked an account") vs. the generic rate-limit message.
|
|
206
|
+
* Populated from the server-side `details.reason` when present.
|
|
207
|
+
*/
|
|
208
|
+
readonly reason: 'account_recently_linked' | 'unknown';
|
|
209
|
+
constructor(unlockAtIso: string, reason?: 'account_recently_linked' | 'unknown', message?: string);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Thrown when POST /v1/users/me/link/{provider} returns 401 with
|
|
213
|
+
* `code: 'account_linking/mfa_required'`.
|
|
214
|
+
*
|
|
215
|
+
* @see https://datatracker.ietf.org/doc/html/rfc9470 (Step-Up Authentication
|
|
216
|
+
* Challenge Protocol — conceptual reference; the JSON-body discriminator here
|
|
217
|
+
* mirrors RFC 9470's Bearer `WWW-Authenticate` step-up signal for cookie-session
|
|
218
|
+
* APIs.)
|
|
219
|
+
*
|
|
220
|
+
* In SDK 0.11.0 the canonical post-401 discriminator is `next_action: 'verify_mfa'`
|
|
221
|
+
* (mirrors Stripe `payment_intent.next_action` / AWS Cognito `ChallengeName`).
|
|
222
|
+
* The `mfa_challenge_token` getter is RETAINED for backward compatibility with
|
|
223
|
+
* 0.10.x consumers but will be removed in 0.12.0 — switch to `next_action`.
|
|
224
|
+
*
|
|
225
|
+
* Calling code: guide the user through `POST /v1/auth/step-up/password`, then
|
|
226
|
+
* retry the link initiate with the resulting `X-Step-Up-Token` header.
|
|
227
|
+
*
|
|
228
|
+
* Note: this error is ONLY thrown for users who CAN satisfy step-up (i.e. have
|
|
229
|
+
* a password set). Passwordless users (magic-link / OTP / passkey-only) get the
|
|
230
|
+
* complementary {@link MfaStepUpUnavailableError} instead.
|
|
231
|
+
*/
|
|
232
|
+
export declare class MfaStepUpRequiredError extends Error {
|
|
233
|
+
readonly code = "account_linking/mfa_required";
|
|
234
|
+
readonly suggestion: string;
|
|
235
|
+
readonly docs_url: string;
|
|
236
|
+
/**
|
|
237
|
+
* Canonical post-401 discriminator. Always equals the literal `'verify_mfa'`
|
|
238
|
+
* in SDK 0.11.x. Reserved future literals: `'verify_passkey'`,
|
|
239
|
+
* `'verify_magic_link'`, `'verify_otp'`, `'verify_eudi_wallet'`.
|
|
240
|
+
*/
|
|
241
|
+
readonly next_action: "verify_mfa";
|
|
242
|
+
/**
|
|
243
|
+
* The set of step-up issuance routes the current user can satisfy. The
|
|
244
|
+
* client SHOULD pick one and call the corresponding `/v1/auth/step-up/*`
|
|
245
|
+
* route. Order is a HINT, not a guarantee — the server may personalize
|
|
246
|
+
* ordering by recent success rate or admin policy.
|
|
247
|
+
*
|
|
248
|
+
* Open union: backend-additive values (e.g. `ciba_push`, `eudi_wallet`)
|
|
249
|
+
* MUST NOT trigger a SemVer-major bump for SDK consumers — the
|
|
250
|
+
* `(string & {})` escape hatch keeps the literal-aware autocomplete
|
|
251
|
+
* experience while accepting unknown strings at runtime.
|
|
252
|
+
*
|
|
253
|
+
* Optional: older API responses (servers older than 2026-04-26)
|
|
254
|
+
* lack this field; consumers MUST handle `undefined` by falling through to
|
|
255
|
+
* the legacy `next_action === 'verify_mfa'` flow.
|
|
256
|
+
*/
|
|
257
|
+
readonly availableMethods?: ReadonlyArray<'password' | 'passkey' | 'magic_link' | 'email_otp' | (string & {})>;
|
|
258
|
+
private readonly _mfaChallengeToken;
|
|
259
|
+
/**
|
|
260
|
+
* @deprecated Will be removed in 0.12.0+ once the dual-emit window expires
|
|
261
|
+
* (2026-07-24). Switch to `next_action === 'verify_mfa'`. In 0.10.x this field carried the
|
|
262
|
+
* literal string `'mfa_step_up_required'` (a routing marker, never a nonce);
|
|
263
|
+
* the value is preserved here so existing consumers continue working through
|
|
264
|
+
* the dual-emit window.
|
|
265
|
+
*/
|
|
266
|
+
get mfa_challenge_token(): string;
|
|
267
|
+
constructor(mfaChallengeToken?: string, message?: string, availableMethods?: ReadonlyArray<'password' | 'passkey' | 'magic_link' | 'email_otp' | (string & {})>);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Thrown when POST /v1/users/me/link/{provider} returns 401 with
|
|
271
|
+
* `code: 'account_linking/mfa_step_up_unavailable'` — a passwordless user
|
|
272
|
+
* (magic-link / email-OTP / passkey-only) has MFA enabled but no step-up
|
|
273
|
+
* issuance route exists for their authenticator class today (only
|
|
274
|
+
* `POST /v1/auth/step-up/password` ships in 0.11.x).
|
|
275
|
+
*
|
|
276
|
+
* @see https://datatracker.ietf.org/doc/html/rfc9470
|
|
277
|
+
*
|
|
278
|
+
* The complement of {@link MfaStepUpRequiredError}: together the two classes
|
|
279
|
+
* partition the 401-with-MFA-enabled space. UX should surface a "complete
|
|
280
|
+
* account setup (set a password)" affordance — NOT a promise of a passwordless
|
|
281
|
+
* step-up flow (none exists in 0.11.x).
|
|
282
|
+
*/
|
|
283
|
+
export declare class MfaStepUpUnavailableError extends Error {
|
|
284
|
+
readonly code = "account_linking/mfa_step_up_unavailable";
|
|
285
|
+
readonly suggestion: string;
|
|
286
|
+
readonly docs_url: string;
|
|
287
|
+
/**
|
|
288
|
+
* Extensible enum — additional reasons reserved for future passwordless
|
|
289
|
+
* step-up flows. The recognised reasons include
|
|
290
|
+
* `'no_step_up_authenticator_available'`, emitted when the server finds
|
|
291
|
+
* zero satisfiable methods (defensive tripwire).
|
|
292
|
+
*/
|
|
293
|
+
readonly reason: string;
|
|
294
|
+
constructor(reason?: string, message?: string);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Thrown when an OAuth callback rejects a state row that expired or was
|
|
298
|
+
* already used. The SDK typically surfaces this via the
|
|
299
|
+
* link-list read (consumers infer the failure from a `?error=link_state_expired`
|
|
300
|
+
* query string). Direct API consumers get the typed class.
|
|
301
|
+
*/
|
|
302
|
+
export declare class LinkStateExpiredError extends Error {
|
|
303
|
+
readonly code = "account_linking/link_state_expired_or_missing";
|
|
304
|
+
readonly suggestion: string;
|
|
305
|
+
readonly docs_url: string;
|
|
306
|
+
constructor(message?: string);
|
|
307
|
+
}
|