@aithos/sdk 0.1.0-alpha.30 → 0.1.0-alpha.31

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.
@@ -46,27 +46,71 @@ export interface LoginVerifyResponse {
46
46
  readonly blobVersion: number;
47
47
  }
48
48
  export declare function loginVerify(http: HttpClient, email: string, authKey: Uint8Array): Promise<LoginVerifyResponse>;
49
+ /**
50
+ * Input for {@link custodialSignUp}. Caller authenticates the app via ONE
51
+ * of `apiKey` (server-only secret) or `publicKey` (browser-safe). The
52
+ * user's `password` is always required — sign-up no longer auto-generates
53
+ * one server-side. The created account starts in a *pending* state and
54
+ * the user must click the link sent to their inbox before they can
55
+ * sign in.
56
+ */
49
57
  export interface CustodialSignUpApiInput {
50
- readonly apiKey: string;
58
+ /** Server-only Bearer secret: `aithos_<env>_<…>`. Mutually exclusive
59
+ * with `publicKey`. Use this from your backend. */
60
+ readonly apiKey?: string;
61
+ /** Browser-safe public client key: `pk_<env>_<…>`. Mutually exclusive
62
+ * with `apiKey`. The browser sends its `Origin` header alongside; the
63
+ * Aithos backend matches it against the app's allowed_origins list. */
64
+ readonly publicKey?: string;
51
65
  readonly email: string;
66
+ /** Raw password the user chose. Must be ≥ 10 chars and mix letters
67
+ * with at least one digit or symbol (server-side rule). */
68
+ readonly password: string;
52
69
  readonly displayName?: string;
53
70
  readonly handleHint?: string;
54
71
  }
55
72
  export interface CustodialSignUpApiResponse {
56
- readonly userId: string;
57
- readonly did: string;
58
- readonly handle: string;
73
+ /** Always "pending_verification" — sign-in is blocked until the
74
+ * user clicks the confirmation link. */
75
+ readonly status: "pending_verification";
59
76
  readonly email: string;
60
77
  readonly mailSent: boolean;
61
78
  readonly mailMessageId?: string;
62
79
  }
63
80
  /**
64
81
  * Provision a custodial-mode account on behalf of a registered app.
65
- * Server-only — the API key MUST be kept off the browser (it grants the
66
- * ability to create accounts under your app's name). Typical use site is
67
- * the app's backend in response to a sign-up form submission.
82
+ *
83
+ * Two integration paths:
84
+ * - **Backend** caller passes `apiKey` (server-only secret).
85
+ * - **Browser** caller passes `publicKey` (safe to ship in the bundle).
86
+ * The browser also sends its `Origin` header automatically and the
87
+ * auth backend validates it against the app's allowed_origins list.
88
+ *
89
+ * On success the account exists in DDB with `email_verified: false` and
90
+ * the response carries `status: "pending_verification"` — call
91
+ * {@link custodialVerifyEmail} after the user clicks the confirmation
92
+ * link before attempting sign-in.
68
93
  */
69
94
  export declare function custodialSignUp(http: HttpClient, input: CustodialSignUpApiInput): Promise<CustodialSignUpApiResponse>;
95
+ export interface CustodialVerifyEmailApiInput {
96
+ readonly email: string;
97
+ readonly token: string;
98
+ }
99
+ /** Consume the verification token from the confirmation link. Idempotent
100
+ * on repeated clicks; throws `auth_token_invalid_or_expired` if the
101
+ * token is wrong, consumed, or past its 24h TTL. */
102
+ export declare function custodialVerifyEmail(http: HttpClient, input: CustodialVerifyEmailApiInput): Promise<{
103
+ ok: true;
104
+ }>;
105
+ /** Re-send the verification mail for a pending account. The backend
106
+ * is anti-enum (always 200) and rate-limited 1/h/account, so this is
107
+ * safe to call even when the user state is unknown. Accepts the same
108
+ * credential families as {@link custodialSignUp}. */
109
+ export declare function custodialResendVerify(http: HttpClient, args: {
110
+ readonly email: string;
111
+ readonly apiKey?: string;
112
+ readonly publicKey?: string;
113
+ }): Promise<void>;
70
114
  export interface CustodialSignInApiInput {
71
115
  readonly email: string;
72
116
  readonly password: string;
@@ -101,19 +101,35 @@ export async function loginVerify(http, email, authKey) {
101
101
  }
102
102
  /**
103
103
  * Provision a custodial-mode account on behalf of a registered app.
104
- * Server-only — the API key MUST be kept off the browser (it grants the
105
- * ability to create accounts under your app's name). Typical use site is
106
- * the app's backend in response to a sign-up form submission.
104
+ *
105
+ * Two integration paths:
106
+ * - **Backend** caller passes `apiKey` (server-only secret).
107
+ * - **Browser** caller passes `publicKey` (safe to ship in the bundle).
108
+ * The browser also sends its `Origin` header automatically and the
109
+ * auth backend validates it against the app's allowed_origins list.
110
+ *
111
+ * On success the account exists in DDB with `email_verified: false` and
112
+ * the response carries `status: "pending_verification"` — call
113
+ * {@link custodialVerifyEmail} after the user clicks the confirmation
114
+ * link before attempting sign-in.
107
115
  */
108
116
  export async function custodialSignUp(http, input) {
117
+ if (!input.apiKey && !input.publicKey) {
118
+ throw new AithosSDKError("auth_missing_api_key", "signUpCustodial requires either apiKey or publicKey");
119
+ }
120
+ if (input.apiKey && input.publicKey) {
121
+ throw new AithosSDKError("auth_invalid_input", "signUpCustodial: pass exactly one of apiKey or publicKey, not both");
122
+ }
123
+ const bearer = (input.apiKey ?? input.publicKey);
109
124
  const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/sign-up`, {
110
125
  method: "POST",
111
126
  headers: {
112
127
  "content-type": "application/json",
113
- authorization: `Bearer ${input.apiKey}`,
128
+ authorization: `Bearer ${bearer}`,
114
129
  },
115
130
  body: JSON.stringify({
116
131
  email: input.email,
132
+ password: input.password,
117
133
  ...(input.displayName ? { display_name: input.displayName } : {}),
118
134
  ...(input.handleHint ? { handle_hint: input.handleHint } : {}),
119
135
  }),
@@ -122,9 +138,7 @@ export async function custodialSignUp(http, input) {
122
138
  throw await readError(res, "custodial_signup_failed");
123
139
  const wire = (await res.json());
124
140
  return {
125
- userId: wire.user_id,
126
- did: wire.did,
127
- handle: wire.handle,
141
+ status: "pending_verification",
128
142
  email: wire.email,
129
143
  mailSent: wire.mail_sent,
130
144
  ...(wire.mail_message_id !== undefined
@@ -132,6 +146,40 @@ export async function custodialSignUp(http, input) {
132
146
  : {}),
133
147
  };
134
148
  }
149
+ /** Consume the verification token from the confirmation link. Idempotent
150
+ * on repeated clicks; throws `auth_token_invalid_or_expired` if the
151
+ * token is wrong, consumed, or past its 24h TTL. */
152
+ export async function custodialVerifyEmail(http, input) {
153
+ const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/verify`, {
154
+ method: "POST",
155
+ headers: { "content-type": "application/json" },
156
+ body: JSON.stringify({ email: input.email, token: input.token }),
157
+ });
158
+ if (!res.ok)
159
+ throw await readError(res, "custodial_verify_failed");
160
+ return (await res.json());
161
+ }
162
+ /* ---- POST /auth/custodial/verify/resend -------------------------------- */
163
+ /** Re-send the verification mail for a pending account. The backend
164
+ * is anti-enum (always 200) and rate-limited 1/h/account, so this is
165
+ * safe to call even when the user state is unknown. Accepts the same
166
+ * credential families as {@link custodialSignUp}. */
167
+ export async function custodialResendVerify(http, args) {
168
+ if (!args.apiKey && !args.publicKey) {
169
+ throw new AithosSDKError("auth_missing_api_key", "resendVerificationEmail requires either apiKey or publicKey");
170
+ }
171
+ const bearer = (args.apiKey ?? args.publicKey);
172
+ const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/verify/resend`, {
173
+ method: "POST",
174
+ headers: {
175
+ "content-type": "application/json",
176
+ authorization: `Bearer ${bearer}`,
177
+ },
178
+ body: JSON.stringify({ email: args.email }),
179
+ });
180
+ if (!res.ok)
181
+ throw await readError(res, "custodial_resend_failed");
182
+ }
135
183
  export async function custodialSignIn(http, input) {
136
184
  const wire = await postJson(http, "/auth/custodial/sign-in", { email: input.email, password: input.password });
137
185
  return {
@@ -22,6 +22,22 @@ export interface AithosAuthConfig {
22
22
  readonly sessionStore?: AithosSessionStore;
23
23
  /** Pluggable key persistence. Defaults to {@link defaultKeyStore}. */
24
24
  readonly keyStore?: AithosKeyStore;
25
+ /**
26
+ * Public client key issued by Aithos for browser callers
27
+ * (`pk_<env>_<…>`). When set, the custodial endpoints (`signUpCustodial`,
28
+ * `verifyEmail`, `resendVerificationEmail`) authenticate as this app
29
+ * by default — the caller no longer has to repeat the key on every
30
+ * call. The corresponding `allowed_origins` allowlist must include the
31
+ * current page's origin.
32
+ *
33
+ * Safe to ship in the browser bundle: it grants nothing beyond what
34
+ * a visitor of the app can already do, is gated by Origin on every
35
+ * call, and is rate-limited per IP by the backend.
36
+ *
37
+ * If your app authenticates with a SECRET Bearer API key from a
38
+ * backend instead, leave this unset and pass `apiKey` per call.
39
+ */
40
+ readonly publicKey?: string;
25
41
  }
26
42
  /**
27
43
  * Active Aithos session. Returned by JWT-backed entry points
@@ -136,36 +152,66 @@ export interface ImportMandateInput {
136
152
  readonly bundle: Blob | string;
137
153
  }
138
154
  /**
139
- * Input to {@link AithosAuth.signUpCustodial}. Server-side only — the
140
- * API key MUST stay off the browser (it grants account-creation
141
- * authority under your app's name). Typical use site: your app's
142
- * backend in response to a sign-up form submission.
155
+ * Input to {@link AithosAuth.signUpCustodial}.
156
+ *
157
+ * The caller authenticates as an app via ONE of:
158
+ * - `apiKey` : server-only secret Bearer. Pass from your backend
159
+ * only — never ship it in browser code.
160
+ * - `publicKey` : browser-safe public client key. Safe to embed in
161
+ * the bundle; the backend gates it by Origin and
162
+ * rate-limits by IP.
163
+ *
164
+ * If you set `publicKey` on the {@link AithosAuth} constructor, omit
165
+ * both fields here — the default credential is used.
166
+ *
167
+ * The `password` is always required and is chosen by the user (sign-up
168
+ * no longer auto-generates one). The created account starts as
169
+ * **pending** (`email_verified=false`); the user must click the
170
+ * confirmation link sent by SES before {@link signInCustodial} works.
143
171
  */
144
172
  export interface CustodialSignUpInput {
145
- /** Bearer API key issued to your app (`aithos_<env>_<32b58>`). */
146
- readonly apiKey: string;
147
- /** Email address of the new user. Will receive the welcome mail. */
173
+ /** Server-only Bearer secret. Mutually exclusive with `publicKey`. */
174
+ readonly apiKey?: string;
175
+ /** Browser-safe public client key. Mutually exclusive with `apiKey`.
176
+ * Overrides the constructor's default `publicKey` when provided. */
177
+ readonly publicKey?: string;
178
+ /** Email address of the new user. Will receive the verification mail. */
148
179
  readonly email: string;
180
+ /** Raw password the user chose. ≥ 10 chars, mix of letters with
181
+ * ≥ 1 digit or symbol. Enforced server-side. */
182
+ readonly password: string;
149
183
  /** Optional display name. Capped at 200 chars by the backend. */
150
184
  readonly displayName?: string;
151
185
  /** Optional handle hint. Backend may sanitise or replace. */
152
186
  readonly handleHint?: string;
153
187
  }
154
188
  /**
155
- * Result of {@link AithosAuth.signUpCustodial}. The raw password is
156
- * NEVER returned in this response it lives only in the welcome email
157
- * sent to the user via SES. `mailSent: false` means the account row
158
- * was created but the email handoff to SES failed; the operator can
159
- * trigger a manual resend.
189
+ * Result of {@link AithosAuth.signUpCustodial}. Always carries
190
+ * `status: "pending_verification"`the user must click the link in
191
+ * their inbox before sign-in works. If `mailSent` is false the row
192
+ * exists in DDB anyway; trigger {@link AithosAuth.resendVerificationEmail}
193
+ * to retry the SES send.
160
194
  */
161
195
  export interface CustodialSignUpResult {
162
- readonly userId: string;
163
- readonly did: string;
164
- readonly handle: string;
196
+ readonly status: "pending_verification";
165
197
  readonly email: string;
166
198
  readonly mailSent: boolean;
167
199
  readonly mailMessageId?: string;
168
200
  }
201
+ /** Input to {@link AithosAuth.verifyEmail}. Both fields come straight
202
+ * out of the `?email=&token=` query string of the confirmation URL. */
203
+ export interface VerifyEmailInput {
204
+ readonly email: string;
205
+ readonly token: string;
206
+ }
207
+ /** Input to {@link AithosAuth.resendVerificationEmail}. The `email` is
208
+ * required; credential overrides follow the same rules as
209
+ * {@link CustodialSignUpInput}. */
210
+ export interface ResendVerificationInput {
211
+ readonly email: string;
212
+ readonly apiKey?: string;
213
+ readonly publicKey?: string;
214
+ }
169
215
  export interface CustodialSignInInput {
170
216
  readonly email: string;
171
217
  readonly password: string;
@@ -330,25 +376,57 @@ export declare class AithosAuth {
330
376
  /**
331
377
  * Provision a custodial-mode account on behalf of a registered app.
332
378
  *
333
- * SERVER-ONLY the API key MUST stay off the browser. The raw user
334
- * password is generated server-side and sent to the user via the
335
- * Aithos welcome email; it is NEVER returned in this response.
379
+ * Two integration patterns:
380
+ * - **Frontend-only** apps : set `publicKey` on the constructor
381
+ * (or on this call). Safe to ship in browser bundles — the
382
+ * backend gates each request by Origin + IP rate limit.
383
+ * - **Backend-fronted** apps : the backend passes `apiKey` (secret
384
+ * Bearer); the browser never sees the credential.
336
385
  *
337
- * Typical use site: your app's backend in response to a sign-up form
338
- * submission. The frontend never sees the API key, only the resulting
339
- * `{ userId, did, handle, email, mailSent }` it can show to the user
340
- * ("we just sent you a mail with your credentials").
386
+ * The created account is in a *pending* state sign-in stays blocked
387
+ * until the user clicks the confirmation link sent to their inbox.
388
+ * Call {@link verifyEmail} from the page mounted on
389
+ * `app.verify_base_url` to consume the token; afterwards
390
+ * {@link signInCustodial} works.
341
391
  *
342
392
  * Errors map to `AithosSDKError` codes:
343
- * - `auth_missing_api_key` (your code passed empty apiKey)
393
+ * - `auth_missing_api_key` (no credential provided)
344
394
  * - `auth_invalid_api_key` (Bearer rejected by backend)
345
- * - `auth_api_key_revoked` (backend marked the key revoked)
395
+ * - `auth_invalid_public_key` (public key rejected by backend)
396
+ * - `auth_api_key_revoked` / `auth_public_key_revoked`
397
+ * - `auth_origin_not_allowed` (public key + Origin not in allowlist)
398
+ * - `auth_password_too_weak` (400 — server-side strength check)
346
399
  * - `auth_email_exists` (409 — email already registered)
347
400
  * - `auth_email_invalid` (400 — bad email format)
348
401
  * - `auth_mail_send_failed` (502 — DDB row exists but SES failed)
349
402
  * - `auth_custodial_signup_failed` (catch-all)
350
403
  */
351
404
  signUpCustodial(input: CustodialSignUpInput): Promise<CustodialSignUpResult>;
405
+ /**
406
+ * Confirm the user's email address by consuming the one-time token
407
+ * from the confirmation link. Idempotent on repeated clicks; throws
408
+ * `auth_token_invalid_or_expired` if the token is wrong, already
409
+ * consumed, or past its 24h TTL.
410
+ *
411
+ * Mount this on the page declared as `verify_base_url` in your app's
412
+ * registration. Read `email` + `token` from `window.location.search`,
413
+ * call this, then redirect to your sign-in page on success.
414
+ */
415
+ verifyEmail(input: VerifyEmailInput): Promise<{
416
+ ok: true;
417
+ }>;
418
+ /**
419
+ * Re-send the verification mail for a pending account. Use when the
420
+ * user reports never having received the welcome mail, or when their
421
+ * verification token expired (24h TTL).
422
+ *
423
+ * The backend is anti-enumeration (always 200) and rate-limited
424
+ * 1/h/account, so it's safe to call even when the state of `email`
425
+ * is unknown. Accepts the same credential families as
426
+ * {@link signUpCustodial}; falls back to the constructor's
427
+ * `publicKey` when neither override is set.
428
+ */
429
+ resendVerificationEmail(input: ResendVerificationInput): Promise<void>;
352
430
  /**
353
431
  * Authenticate a custodial-mode user with email + password. Single
354
432
  * round-trip: returns a fresh JWT session AND hydrates the local
package/dist/src/auth.js CHANGED
@@ -21,7 +21,7 @@
21
21
  // keyStore is the source of truth for "is the user signed in", the
22
22
  // JWT is auxiliary for compute/wallet.
23
23
  import { buildBlobPlaintext, buildSignedEnvelope, createBrowserIdentity, decryptBlob, DEFAULT_KDF, deriveAuthAndEncKeys, encryptBlob, parseBlob, randomNonce, randomSalt, serializeBlob, signedDidDocument, zeroize, } from "@aithos/protocol-client";
24
- import { custodialResetFinalize, custodialResetRequest, custodialSignIn, custodialSignUp, loginChallenge, loginVerify, putBlob, registerAccount, } from "./auth-api.js";
24
+ import { custodialResendVerify, custodialResetFinalize, custodialResetRequest, custodialSignIn, custodialSignUp, custodialVerifyEmail, loginChallenge, loginVerify, putBlob, registerAccount, } from "./auth-api.js";
25
25
  import { defaultSessionStore, } from "./session-store.js";
26
26
  import { defaultKeyStore, } from "./key-store.js";
27
27
  import { parseDelegateBundle, readDelegateBundleText, } from "./internal/delegate-bundle.js";
@@ -43,6 +43,7 @@ export class AithosAuth {
43
43
  #win;
44
44
  #sessionStore;
45
45
  #keyStore;
46
+ #publicKey;
46
47
  /** In-memory owner signers — populated after sign-in or `resume`. */
47
48
  #ownerSigners = null;
48
49
  /** Active delegate registry. */
@@ -66,6 +67,7 @@ export class AithosAuth {
66
67
  (typeof window !== "undefined" ? window : undefined);
67
68
  this.#sessionStore = config.sessionStore ?? defaultSessionStore();
68
69
  this.#keyStore = config.keyStore ?? defaultKeyStore();
70
+ this.#publicKey = config.publicKey;
69
71
  }
70
72
  /* ------------------------------------------------------------------------ */
71
73
  /* Boot-time hydration */
@@ -776,32 +778,93 @@ export class AithosAuth {
776
778
  /**
777
779
  * Provision a custodial-mode account on behalf of a registered app.
778
780
  *
779
- * SERVER-ONLY the API key MUST stay off the browser. The raw user
780
- * password is generated server-side and sent to the user via the
781
- * Aithos welcome email; it is NEVER returned in this response.
781
+ * Two integration patterns:
782
+ * - **Frontend-only** apps : set `publicKey` on the constructor
783
+ * (or on this call). Safe to ship in browser bundles — the
784
+ * backend gates each request by Origin + IP rate limit.
785
+ * - **Backend-fronted** apps : the backend passes `apiKey` (secret
786
+ * Bearer); the browser never sees the credential.
782
787
  *
783
- * Typical use site: your app's backend in response to a sign-up form
784
- * submission. The frontend never sees the API key, only the resulting
785
- * `{ userId, did, handle, email, mailSent }` it can show to the user
786
- * ("we just sent you a mail with your credentials").
788
+ * The created account is in a *pending* state sign-in stays blocked
789
+ * until the user clicks the confirmation link sent to their inbox.
790
+ * Call {@link verifyEmail} from the page mounted on
791
+ * `app.verify_base_url` to consume the token; afterwards
792
+ * {@link signInCustodial} works.
787
793
  *
788
794
  * Errors map to `AithosSDKError` codes:
789
- * - `auth_missing_api_key` (your code passed empty apiKey)
795
+ * - `auth_missing_api_key` (no credential provided)
790
796
  * - `auth_invalid_api_key` (Bearer rejected by backend)
791
- * - `auth_api_key_revoked` (backend marked the key revoked)
797
+ * - `auth_invalid_public_key` (public key rejected by backend)
798
+ * - `auth_api_key_revoked` / `auth_public_key_revoked`
799
+ * - `auth_origin_not_allowed` (public key + Origin not in allowlist)
800
+ * - `auth_password_too_weak` (400 — server-side strength check)
792
801
  * - `auth_email_exists` (409 — email already registered)
793
802
  * - `auth_email_invalid` (400 — bad email format)
794
803
  * - `auth_mail_send_failed` (502 — DDB row exists but SES failed)
795
804
  * - `auth_custodial_signup_failed` (catch-all)
796
805
  */
797
806
  async signUpCustodial(input) {
798
- if (!input.apiKey) {
799
- throw new AithosSDKError("auth_missing_api_key", "signUpCustodial: apiKey is required");
800
- }
801
807
  if (!input.email) {
802
808
  throw new AithosSDKError("auth_invalid_input", "signUpCustodial: email is required");
803
809
  }
804
- return custodialSignUp({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, input);
810
+ if (!input.password) {
811
+ throw new AithosSDKError("auth_invalid_input", "signUpCustodial: password is required");
812
+ }
813
+ const apiKey = input.apiKey;
814
+ const publicKey = input.publicKey ?? this.#publicKey;
815
+ if (!apiKey && !publicKey) {
816
+ throw new AithosSDKError("auth_missing_api_key", "signUpCustodial: pass apiKey, or publicKey, or set publicKey on the AithosAuth constructor");
817
+ }
818
+ return custodialSignUp({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, {
819
+ email: input.email,
820
+ password: input.password,
821
+ ...(apiKey ? { apiKey } : {}),
822
+ ...(apiKey ? {} : publicKey ? { publicKey } : {}),
823
+ ...(input.displayName ? { displayName: input.displayName } : {}),
824
+ ...(input.handleHint ? { handleHint: input.handleHint } : {}),
825
+ });
826
+ }
827
+ /**
828
+ * Confirm the user's email address by consuming the one-time token
829
+ * from the confirmation link. Idempotent on repeated clicks; throws
830
+ * `auth_token_invalid_or_expired` if the token is wrong, already
831
+ * consumed, or past its 24h TTL.
832
+ *
833
+ * Mount this on the page declared as `verify_base_url` in your app's
834
+ * registration. Read `email` + `token` from `window.location.search`,
835
+ * call this, then redirect to your sign-in page on success.
836
+ */
837
+ async verifyEmail(input) {
838
+ if (!input.email || !input.token) {
839
+ throw new AithosSDKError("auth_invalid_input", "verifyEmail: email and token are required");
840
+ }
841
+ return custodialVerifyEmail({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, input);
842
+ }
843
+ /**
844
+ * Re-send the verification mail for a pending account. Use when the
845
+ * user reports never having received the welcome mail, or when their
846
+ * verification token expired (24h TTL).
847
+ *
848
+ * The backend is anti-enumeration (always 200) and rate-limited
849
+ * 1/h/account, so it's safe to call even when the state of `email`
850
+ * is unknown. Accepts the same credential families as
851
+ * {@link signUpCustodial}; falls back to the constructor's
852
+ * `publicKey` when neither override is set.
853
+ */
854
+ async resendVerificationEmail(input) {
855
+ if (!input.email) {
856
+ throw new AithosSDKError("auth_invalid_input", "resendVerificationEmail: email is required");
857
+ }
858
+ const apiKey = input.apiKey;
859
+ const publicKey = input.publicKey ?? this.#publicKey;
860
+ if (!apiKey && !publicKey) {
861
+ throw new AithosSDKError("auth_missing_api_key", "resendVerificationEmail: pass apiKey, publicKey, or set publicKey on the AithosAuth constructor");
862
+ }
863
+ await custodialResendVerify({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, {
864
+ email: input.email,
865
+ ...(apiKey ? { apiKey } : {}),
866
+ ...(apiKey ? {} : publicKey ? { publicKey } : {}),
867
+ });
805
868
  }
806
869
  /**
807
870
  * Authenticate a custodial-mode user with email + password. Single
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.1.0-alpha.30";
1
+ export declare const VERSION = "0.1.0-alpha.31";
2
2
  export { AithosSDK } from "./sdk.js";
3
3
  export type { AithosSDKConfig } from "./types.js";
4
4
  export { AithosSDKError } from "./types.js";
@@ -12,7 +12,7 @@ export { WalletNamespace } from "./wallet.js";
12
12
  export type { ComponentStyle, ExtractArgs, ExtractContent, ExtractData, ExtractForm, ExtractFormField, ExtractHeading, ExtractIconDeclaration, ExtractImage, ExtractLink, ExtractLogo, ExtractMeta, ExtractResult, ExtractSection, ExtractStructure, ExtractStyles, FetchAssetArgs, FetchAssetResult, PaletteEntry, VisualSignature, WebNamespaceDeps, } from "./web.js";
13
13
  export { WebNamespace, WEB_EXTRACT_SCOPE } from "./web.js";
14
14
  export { AithosAuth, DEFAULT_API_BASE_URL, DEFAULT_AUTH_BASE_URL, } from "./auth.js";
15
- export type { AithosAuthConfig, AithosSession, ApplyPasswordResetInput, ApplyPasswordResetResult, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, CustodialSignInInput, CustodialSignInResult, CustodialSignUpInput, CustodialSignUpResult, DelegateInfo, ImportMandateInput, OwnerInfo, RequestPasswordResetInput, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, } from "./auth.js";
15
+ export type { AithosAuthConfig, AithosSession, ApplyPasswordResetInput, ApplyPasswordResetResult, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, CustodialSignInInput, CustodialSignInResult, CustodialSignUpInput, CustodialSignUpResult, DelegateInfo, ImportMandateInput, OwnerInfo, RequestPasswordResetInput, ResendVerificationInput, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, VerifyEmailInput, } from "./auth.js";
16
16
  export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, type AithosSessionStore, } from "./session-store.js";
17
17
  export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, type AithosKeyStore, type StoredDelegateKeys, type StoredOwnerKeys, } from "./key-store.js";
18
18
  export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
package/dist/src/index.js CHANGED
@@ -17,7 +17,7 @@
17
17
  // Public types specific to the SDK (`AithosSDKConfig`, `AithosSDKError`)
18
18
  // are exported from here. Endpoint config (`AithosSdkEndpoints`,
19
19
  // `DEFAULT_SDK_ENDPOINTS`) likewise.
20
- export const VERSION = "0.1.0-alpha.30";
20
+ export const VERSION = "0.1.0-alpha.31";
21
21
  export { AithosSDK } from "./sdk.js";
22
22
  export { AithosSDKError } from "./types.js";
23
23
  // Re-export protocol-client's JSON-RPC error type so consumers can
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aithos/sdk",
3
- "version": "0.1.0-alpha.30",
3
+ "version": "0.1.0-alpha.31",
4
4
  "description": "Aithos SDK \u2014 high-level TypeScript developer kit for building agentic apps on the Aithos protocol. Wraps @aithos/protocol-client and exposes the Aithos compute proxy and wallet (Stripe top-up) endpoints.",
5
5
  "keywords": [
6
6
  "aithos",