@aithos/sdk 0.1.0-alpha.3 → 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.
Files changed (66) hide show
  1. package/README.md +159 -0
  2. package/dist/src/auth-api.d.ts +149 -0
  3. package/dist/src/auth-api.js +226 -0
  4. package/dist/src/auth.d.ts +436 -67
  5. package/dist/src/auth.js +1098 -69
  6. package/dist/src/compute.d.ts +221 -9
  7. package/dist/src/compute.js +293 -16
  8. package/dist/src/data-schema-contacts-v1.d.ts +14 -0
  9. package/dist/src/data-schema-contacts-v1.js +28 -0
  10. package/dist/src/data.d.ts +97 -0
  11. package/dist/src/data.js +634 -0
  12. package/dist/src/endpoints.d.ts +9 -0
  13. package/dist/src/endpoints.js +5 -0
  14. package/dist/src/ethos.d.ts +202 -1
  15. package/dist/src/ethos.js +821 -16
  16. package/dist/src/index.d.ts +15 -6
  17. package/dist/src/index.js +36 -9
  18. package/dist/src/internal/delegate-bundle.d.ts +18 -0
  19. package/dist/src/internal/delegate-bundle.js +94 -0
  20. package/dist/src/internal/delegate-state.d.ts +45 -0
  21. package/dist/src/internal/delegate-state.js +120 -0
  22. package/dist/src/internal/owner-signers.d.ts +78 -0
  23. package/dist/src/internal/owner-signers.js +179 -0
  24. package/dist/src/internal/protocol-client-bridge.d.ts +8 -0
  25. package/dist/src/internal/protocol-client-bridge.js +20 -0
  26. package/dist/src/internal/recovery-file.d.ts +29 -0
  27. package/dist/src/internal/recovery-file.js +98 -0
  28. package/dist/src/internal/signer.d.ts +59 -0
  29. package/dist/src/internal/signer.js +86 -0
  30. package/dist/src/key-store.d.ts +128 -0
  31. package/dist/src/key-store.js +244 -0
  32. package/dist/src/mandates.d.ts +163 -1
  33. package/dist/src/mandates.js +286 -8
  34. package/dist/src/sdk.d.ts +39 -3
  35. package/dist/src/sdk.js +36 -23
  36. package/dist/src/session-store.d.ts +58 -0
  37. package/dist/src/session-store.js +158 -0
  38. package/dist/src/wallet.d.ts +4 -6
  39. package/dist/src/wallet.js +18 -8
  40. package/dist/src/web.d.ts +279 -0
  41. package/dist/src/web.js +186 -0
  42. package/dist/test/auth-j3.test.d.ts +2 -0
  43. package/dist/test/auth-j3.test.js +391 -0
  44. package/dist/test/compute-delegate-path.test.d.ts +2 -0
  45. package/dist/test/compute-delegate-path.test.js +183 -0
  46. package/dist/test/compute.test.js +26 -11
  47. package/dist/test/endpoints.test.js +20 -1
  48. package/dist/test/ethos-first-edition.test.d.ts +2 -0
  49. package/dist/test/ethos-first-edition.test.js +248 -0
  50. package/dist/test/ethos.test.d.ts +2 -0
  51. package/dist/test/ethos.test.js +219 -0
  52. package/dist/test/key-store.test.d.ts +2 -0
  53. package/dist/test/key-store.test.js +161 -0
  54. package/dist/test/mandates-compute.test.d.ts +2 -0
  55. package/dist/test/mandates-compute.test.js +256 -0
  56. package/dist/test/mandates.test.d.ts +2 -0
  57. package/dist/test/mandates.test.js +93 -0
  58. package/dist/test/sdk.test.js +70 -30
  59. package/dist/test/signer.test.d.ts +2 -0
  60. package/dist/test/signer.test.js +117 -0
  61. package/dist/test/signup-bootstrap.test.d.ts +2 -0
  62. package/dist/test/signup-bootstrap.test.js +222 -0
  63. package/dist/test/wallet.test.js +20 -9
  64. package/dist/test/web.test.d.ts +2 -0
  65. package/dist/test/web.test.js +270 -0
  66. package/package.json +5 -4
@@ -1,116 +1,485 @@
1
+ import { type AithosSessionStore } from "./session-store.js";
2
+ import { type AithosKeyStore } from "./key-store.js";
3
+ import { DelegateActor } from "./internal/delegate-state.js";
4
+ import { OwnerSigners } from "./internal/owner-signers.js";
1
5
  /** Default URL of the Aithos auth backend. */
2
6
  export declare const DEFAULT_AUTH_BASE_URL = "https://auth.aithos.be";
3
- /**
4
- * Construction options for {@link AithosAuth}.
5
- */
7
+ /** Default URL of the Aithos primitives API (publish_identity, publish_ethos_edition, etc.). */
8
+ export declare const DEFAULT_API_BASE_URL = "https://api.aithos.be";
6
9
  export interface AithosAuthConfig {
7
- /**
8
- * Base URL of the Aithos auth backend. Defaults to
9
- * {@link DEFAULT_AUTH_BASE_URL}. Override for staging or self-hosted
10
- * deployments.
11
- */
12
10
  readonly authBaseUrl?: string;
13
11
  /**
14
- * Optional `fetch` implementation. Defaults to `globalThis.fetch`. Used
15
- * by tests to inject a mock without monkeypatching globals.
12
+ * Base URL of the Aithos primitives API (`api.aithos.be`). Used by
13
+ * {@link AithosAuth.signUp} to bootstrap the user's Ethos via
14
+ * `aithos.publish_identity` after the auth account is created. Override
15
+ * for staging or self-hosted deployments. Defaults to
16
+ * {@link DEFAULT_API_BASE_URL}.
16
17
  */
18
+ readonly apiBaseUrl?: string;
17
19
  readonly fetch?: typeof fetch;
20
+ readonly window?: Pick<Window, "location" | "history">;
21
+ /** Pluggable JWT-session storage. Defaults to {@link defaultSessionStore}. */
22
+ readonly sessionStore?: AithosSessionStore;
23
+ /** Pluggable key persistence. Defaults to {@link defaultKeyStore}. */
24
+ readonly keyStore?: AithosKeyStore;
18
25
  /**
19
- * Optional `window`-like object. Defaults to `globalThis.window` when
20
- * available. Provided so node-side tests can assert redirect URLs without
21
- * shimming jsdom.
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.
22
39
  */
23
- readonly window?: Pick<Window, "location" | "history">;
40
+ readonly publicKey?: string;
24
41
  }
25
42
  /**
26
- * Payload returned by a successful Google sign-in.
27
- *
28
- * Wire-compatible with the auth Lambda's `SsoExchangeResponse`. Field names
29
- * are kept snake_case to match the backend; rationale: avoids an extra
30
- * mapping layer and keeps the SDK transparent if the user opens the
31
- * Network panel.
43
+ * Active Aithos session. Returned by JWT-backed entry points
44
+ * (`signIn`, `signUp`, `handleCallback`). Recovery-file and mandate
45
+ * sign-ins do NOT return an `AithosSession` they yield the lighter
46
+ * {@link OwnerInfo} / {@link DelegateInfo}.
32
47
  */
33
48
  export interface AithosSession {
34
- /** HS256 JWT — send in `Authorization: Bearer <session>` to auth/* and
35
- * app endpoints that consume it. */
36
49
  readonly session: string;
37
- /** JWT expiry, Unix seconds. */
38
50
  readonly exp: number;
39
- /** Aithos DID — `did:aithos:z…`. Stable across all the user's devices. */
40
51
  readonly did: string;
41
- /** User-visible handle (rendered as `@handle`). */
42
52
  readonly handle: string;
43
- /** Encrypted vault, base64. Empty string + version 0 on first sign-in. */
44
53
  readonly blob_b64: string;
45
- /** AES-GCM nonce for the blob, base64 (12 bytes). Empty on first sign-in. */
46
54
  readonly blob_nonce_b64: string;
47
- /** Monotonic blob version. Bumped on every PUT /auth/blob. */
48
55
  readonly blob_version: number;
49
- /** 32-byte vault key, base64. Decrypts {@link blob_b64} via AES-GCM-256. */
50
56
  readonly enc_key_b64: string;
51
- /** True the first time this user signs in. The app should run its
52
- * onboarding flow rather than mounting an empty blob. */
53
57
  readonly is_first_login: boolean;
54
58
  }
55
59
  /**
56
- * Options for {@link AithosAuth.signInWithGoogle}.
60
+ * Public information about the loaded owner identity. Available after
61
+ * any owner-side sign-in (password, Google, recovery), regardless of
62
+ * whether a JWT is also present.
63
+ */
64
+ export interface OwnerInfo {
65
+ readonly did: string;
66
+ readonly handle: string;
67
+ readonly displayName: string;
68
+ }
69
+ /**
70
+ * Public information about a delegate session held by the SDK. Returned
71
+ * by `importMandate` and `getDelegates`.
57
72
  */
73
+ export interface DelegateInfo {
74
+ readonly mandateId: string;
75
+ readonly subjectDid: string;
76
+ readonly granteeId: string;
77
+ readonly scopes: readonly string[];
78
+ /** ISO-8601, or null when the mandate has no `not_after`. */
79
+ readonly expiresAt: string | null;
80
+ readonly label?: string;
81
+ }
58
82
  export interface SignInWithGoogleOptions {
59
83
  /**
60
- * Opaque deep-link state preserved across the OAuth round-trip and
61
- * surfaced back to the app via `?app_state=…` on the callback URL. Use
62
- * to remember "the user clicked sign-in from /settings/billing" so you
63
- * can restore that route after the redirect chain.
64
- *
65
- * Maximum 1024 characters.
84
+ * Opaque state the consumer app wants to recover after the OAuth
85
+ * round-trip (e.g. a deep-link to resume on). Echoed back as
86
+ * `?app_state=` on the final redirect.
66
87
  */
67
88
  readonly appState?: string;
89
+ /**
90
+ * App id registered in the Aithos `aithos-auth-apps` table. When set
91
+ * together with {@link returnTo}, the auth backend redirects the
92
+ * browser to {@link returnTo} (post Google + Aithos sign-in) instead
93
+ * of the legacy hard-coded `app.aithos.be/auth/callback`.
94
+ *
95
+ * The pair is required together: the backend rejects half-presence
96
+ * with `sso_app_redirect_pair_required`. Use it for any consumer app
97
+ * other than the canonical `app.aithos.be` (typically your own
98
+ * domain in prod, `http://localhost:<port>/auth/callback` in dev).
99
+ */
100
+ readonly appId?: string;
101
+ /**
102
+ * Where the auth backend should 302 the browser back to after a
103
+ * successful Google sign-in. MUST be on the app's
104
+ * `allowed_redirect_uris` allowlist (registered with Aithos out of
105
+ * band; see {@link appId}). Exact-match — wildcards rejected.
106
+ */
107
+ readonly returnTo?: string;
108
+ }
109
+ export interface SignInInput {
110
+ readonly email: string;
111
+ readonly password: string;
112
+ }
113
+ export interface SignUpInput {
114
+ readonly email: string;
115
+ readonly password: string;
116
+ readonly handle: string;
117
+ readonly displayName?: string;
118
+ }
119
+ export interface SignUpResult {
120
+ readonly session: AithosSession;
121
+ readonly recoveryFile: Blob;
122
+ readonly recoveryFilename: string;
123
+ }
124
+ /**
125
+ * Input to {@link AithosAuth.completeSsoFirstLogin}. The handle is
126
+ * required (the auth backend pre-generated one from the user's email
127
+ * local-part, available on the session payload — we re-confirm it
128
+ * here so the user can edit before commit).
129
+ */
130
+ export interface CompleteSsoFirstLoginInput {
131
+ readonly handle: string;
132
+ readonly displayName?: string;
133
+ }
134
+ /**
135
+ * Result of {@link AithosAuth.completeSsoFirstLogin}. Returns a recovery
136
+ * file just like signUp — even though the user authenticated via Google,
137
+ * the freshly-generated Ed25519 seeds are the only material that can
138
+ * sign Aithos artifacts; without the recovery file, losing access to
139
+ * the Google account means losing the ethos forever.
140
+ */
141
+ export interface CompleteSsoFirstLoginResult {
142
+ readonly session: AithosSession;
143
+ readonly recoveryFile: Blob;
144
+ readonly recoveryFilename: string;
145
+ }
146
+ export interface SignInWithRecoveryInput {
147
+ /** Recovery file as a Blob (browser File input) or already-decoded JSON string. */
148
+ readonly file: Blob | string;
149
+ }
150
+ export interface ImportMandateInput {
151
+ /** Delegate bundle as a Blob or already-decoded JSON string. */
152
+ readonly bundle: Blob | string;
153
+ }
154
+ /**
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.
171
+ */
172
+ export interface CustodialSignUpInput {
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. */
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;
183
+ /** Optional display name. Capped at 200 chars by the backend. */
184
+ readonly displayName?: string;
185
+ /** Optional handle hint. Backend may sanitise or replace. */
186
+ readonly handleHint?: string;
187
+ }
188
+ /**
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.
194
+ */
195
+ export interface CustodialSignUpResult {
196
+ readonly status: "pending_verification";
197
+ readonly email: string;
198
+ readonly mailSent: boolean;
199
+ readonly mailMessageId?: string;
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
+ }
215
+ export interface CustodialSignInInput {
216
+ readonly email: string;
217
+ readonly password: string;
218
+ }
219
+ /**
220
+ * Active custodial session. Same JWT-backed shape as {@link AithosSession}
221
+ * but adds a `passwordMustChange` flag the UI can honour to nudge the
222
+ * user toward a `requestPasswordReset` on first login.
223
+ */
224
+ export interface CustodialSignInResult {
225
+ readonly session: AithosSession;
226
+ readonly passwordMustChange: boolean;
227
+ }
228
+ export interface RequestPasswordResetInput {
229
+ readonly email: string;
230
+ }
231
+ /**
232
+ * Input to {@link AithosAuth.applyPasswordReset}. Finalises a password
233
+ * reset started by {@link AithosAuth.requestPasswordReset}. The `email`
234
+ * and `token` come straight from the magic-link URL that landed in the
235
+ * user's inbox (`?email=…&token=…`); the `newPassword` is what the user
236
+ * just typed in the reset page.
237
+ */
238
+ export interface ApplyPasswordResetInput {
239
+ /** Email address whose password is being reset. */
240
+ readonly email: string;
241
+ /** Raw reset token extracted from the magic-link URL query string. */
242
+ readonly token: string;
243
+ /** New password — must satisfy the backend's policy (≥ 10 chars). */
244
+ readonly newPassword: string;
68
245
  }
69
246
  /**
70
- * Authenticator for the Aithos identity service. One instance per app
71
- * is the recommended pattern (the constructor is cheap; it just trims the
72
- * URL). All methods are pure no module-global state.
247
+ * Result of {@link AithosAuth.applyPasswordReset}. Carries a fresh JWT
248
+ * session so the UI can either redirect to a "you're now signed in"
249
+ * landing or prompt the user to sign in explicitly with their new
250
+ * credentials — same {@link CustodialSignInResult} shape as a normal
251
+ * sign-in.
252
+ *
253
+ * Note: unlike {@link signInCustodial}, this DOES NOT hydrate the local
254
+ * keystore. The reset path on the auth Lambda re-wraps the seed bundle
255
+ * with KMS but doesn't return it (the user just typed a password — they
256
+ * still need to sign in once to materialise the seeds locally). The
257
+ * {@link AithosSession} returned here lets the app store the JWT and
258
+ * call {@link signInCustodial} to complete hydration.
73
259
  */
260
+ export interface ApplyPasswordResetResult {
261
+ readonly session: AithosSession;
262
+ }
74
263
  export declare class AithosAuth {
75
- /** Resolved auth base URL with a trailing slash trimmed. */
264
+ #private;
76
265
  readonly authBaseUrl: string;
77
- private readonly fetchImpl;
78
- private readonly win;
266
+ readonly apiBaseUrl: string;
79
267
  constructor(config?: AithosAuthConfig);
80
268
  /**
81
- * Redirect the browser to Google's OAuth consent screen. Must be called
82
- * synchronously in response to a user gesture (button click) — most
83
- * browsers block top-level navigation triggered from idle code.
269
+ * Reload signing material and JWT session from the configured stores.
270
+ * Must be called once at app boot before relying on
271
+ * {@link getCurrentSession} / {@link getOwnerInfo} / {@link canSignAsOwner}
272
+ * — until then they reflect only what's been done in-memory in the
273
+ * current tab.
84
274
  *
85
- * Does not return: navigation tears the JS context down. The `never`
86
- * return type tells callers any code after the call is unreachable.
275
+ * Strict consistency: if the JWT and the stored owner disagree about
276
+ * who's signed in, both are wiped and the user re-auths. JWT-less
277
+ * owner state (loaded from keyStore but no JWT) is a valid resumed
278
+ * state — the user signed in via recovery or imported a mandate at
279
+ * some earlier moment and never went through the JWT flow.
87
280
  */
88
- signInWithGoogle(opts?: SignInWithGoogleOptions): never;
281
+ resume(): Promise<void>;
282
+ /** JWT-backed session. Null when signed in via recovery / mandate / not at all. */
283
+ getCurrentSession(): AithosSession | null;
284
+ /** Loaded owner identity. Independent of JWT presence. */
285
+ getOwnerInfo(): OwnerInfo | null;
286
+ getDelegates(): readonly DelegateInfo[];
287
+ canSignAsOwner(): boolean;
288
+ canSignAsDelegateFor(did: string): boolean;
89
289
  /**
90
- * Inspect the current URL for an `aithos_code` query parameter. If it's
91
- * present, exchange it at the backend and return the resulting
92
- * {@link AithosSession}. The query params are stripped from the URL via
93
- * `history.replaceState` so a page refresh doesn't replay the redeem
94
- * (which would 410 anyway).
290
+ * Internal accessor used by sibling SDK namespaces (compute, wallet,
291
+ * ethos) when they need to sign on behalf of the owner. Returns null
292
+ * if no owner is loaded.
95
293
  *
96
- * Returns `null` when there's no code in the URL — safe to call on every
97
- * page load. Throws {@link AithosSDKError} on backend errors or when
98
- * the URL carries `aithos_error=…` (Google denial, token-exchange
99
- * failure, etc.).
294
+ * @internal
100
295
  */
101
- handleCallback(): Promise<AithosSession | null>;
296
+ _getOwnerSigners(): OwnerSigners | null;
297
+ /**
298
+ * Internal accessor — looks up an active delegate by mandate id.
299
+ * @internal
300
+ */
301
+ _getDelegateActor(mandateId: string): DelegateActor | undefined;
102
302
  /**
103
- * Programmatically redeem an `aithos_code` for a session. `handleCallback`
104
- * calls this for you; expose it directly for callers that already pulled
105
- * the code out of the URL via their own router.
303
+ * Internal accessor finds the first active delegate whose subject
304
+ * matches `did`. Used by `sdk.ethos.of(did)` when the user holds a
305
+ * mandate for that subject.
306
+ * @internal
106
307
  */
308
+ _findDelegateForSubject(did: string): DelegateActor | undefined;
309
+ signIn(input: SignInInput): Promise<AithosSession>;
310
+ signUp(input: SignUpInput): Promise<SignUpResult>;
311
+ /**
312
+ * Sign in by uploading a recovery file. Hydrates the owner signers
313
+ * locally — no JWT is obtained on this path because the recovery
314
+ * file alone doesn't authenticate against the auth backend (no
315
+ * password, no Google session). Apps that need compute/wallet
316
+ * access should follow up with an email+password sign-in or with
317
+ * Google SSO.
318
+ *
319
+ * The recovery file is ALWAYS the file produced by `signUp` (or the
320
+ * equivalent one emitted by `protocol-client`'s `runOnboarding`).
321
+ * Both shapes are accepted.
322
+ */
323
+ signInWithRecovery(input: SignInWithRecoveryInput): Promise<OwnerInfo>;
324
+ /**
325
+ * Import a delegate bundle (`.aithos-delegate.json`). Works in any
326
+ * state: with no owner loaded (delegate-only session), or alongside
327
+ * an existing owner (the user holds mandates for other people's
328
+ * ethoses while also being an owner themselves).
329
+ */
330
+ importMandate(input: ImportMandateInput): Promise<DelegateInfo>;
331
+ removeMandate(mandateId: string): Promise<void>;
332
+ signInWithGoogle(opts?: SignInWithGoogleOptions): never;
333
+ /**
334
+ * Public entrypoint — dedupes concurrent calls (React StrictMode).
335
+ * The first call kicks off the actual exchange; subsequent calls
336
+ * before that promise resolves return the SAME promise so they all
337
+ * receive the same `AithosSession | null`. Otherwise StrictMode's
338
+ * second invocation would race against the URL clean done by the
339
+ * first call and resolve to `null`, robbing the AuthCallback page
340
+ * of the session it actually obtained.
341
+ */
342
+ handleCallback(): Promise<AithosSession | null>;
107
343
  exchange(aithosCode: string): Promise<AithosSession>;
108
344
  /**
109
- * Stateless sign-out. The Aithos backend doesn't track sessions, so
110
- * there's nothing to revoke server-side; this method exists so the app
111
- * has a symmetric API surface and to remind callers to clear their
112
- * own storage. The Promise always resolves.
345
+ * Finish the first-time Google SSO bootstrap. After
346
+ * `signInWithGoogle()` + `handleCallback()`, a brand-new SSO user has
347
+ * a session JWT and an `enc_key` released by the auth backend, but
348
+ * NO Aithos identity yet (no Ed25519 seeds, no published did.json,
349
+ * no blob in the auth vault). This method closes that gap:
350
+ *
351
+ * 1. Generates a fresh {@link BrowserIdentity} client-side (4
352
+ * Ed25519 keypairs, derived DID).
353
+ * 2. Calls `aithos.publish_identity` on api.aithos.be so reads
354
+ * and writes against the Aithos primitives have an ethos to
355
+ * anchor to.
356
+ * 3. AES-GCM-encrypts the seeds with the session's `enc_key`,
357
+ * PUTs the result to `/auth/blob`. From now on, every Google
358
+ * sign-in for this user will receive the encrypted blob and
359
+ * hydrate locally.
360
+ * 4. Hydrates `ownerSigners` + `keyStore` so `canSignAsOwner()`
361
+ * flips to true.
362
+ * 5. Returns a recovery-file Blob — the only material that can
363
+ * restore this ethos if Google access is lost.
364
+ *
365
+ * Preconditions:
366
+ * - `getCurrentSession()` returns a non-null session (caller went
367
+ * through `handleCallback()` already).
368
+ * - The session's `blob_version` is 0 (i.e. no blob yet).
369
+ * - The session's `enc_key_b64` is non-empty.
370
+ *
371
+ * Throws `AithosSDKError("auth_sso_no_pending_first_login", …)` if
372
+ * preconditions don't hold (e.g. blob_version > 0 means the user has
373
+ * already completed setup; nothing to do).
374
+ */
375
+ completeSsoFirstLogin(input: CompleteSsoFirstLoginInput): Promise<CompleteSsoFirstLoginResult>;
376
+ /**
377
+ * Provision a custodial-mode account on behalf of a registered app.
378
+ *
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.
385
+ *
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.
391
+ *
392
+ * Errors map to `AithosSDKError` codes:
393
+ * - `auth_missing_api_key` (no credential provided)
394
+ * - `auth_invalid_api_key` (Bearer rejected by backend)
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)
399
+ * - `auth_email_exists` (409 — email already registered)
400
+ * - `auth_email_invalid` (400 — bad email format)
401
+ * - `auth_mail_send_failed` (502 — DDB row exists but SES failed)
402
+ * - `auth_custodial_signup_failed` (catch-all)
403
+ */
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>;
430
+ /**
431
+ * Authenticate a custodial-mode user with email + password. Single
432
+ * round-trip: returns a fresh JWT session AND hydrates the local
433
+ * KeyStore with the user's 4 Ed25519 seeds (KMS-unwrapped server-side
434
+ * after Argon2id verify).
435
+ *
436
+ * After this returns, the SDK is ready to publish ethos editions,
437
+ * invoke compute, mint mandates, etc. — exactly as if the user had
438
+ * signed in via {@link signIn} (zk) or {@link handleCallback} (SSO).
439
+ *
440
+ * Errors map to `AithosSDKError` codes:
441
+ * - `auth_invalid_input` (your code passed empty fields)
442
+ * - `auth_invalid_credentials` (401 — wrong email / wrong password)
443
+ * - `auth_wrong_auth_mode` (403 — user exists in another flow)
444
+ */
445
+ signInCustodial(input: CustodialSignInInput): Promise<CustodialSignInResult>;
446
+ /**
447
+ * Trigger a password-reset email to the given address. Backend ALWAYS
448
+ * resolves silently (no enumeration) — caller cannot tell whether the
449
+ * email is registered or not. The mail itself, if sent, contains a
450
+ * magic-link URL of shape `<resetBaseUrl>?token=<raw>&email=<email>`.
451
+ *
452
+ * Per-email rate limits apply server-side (5 mails/day, 5 min cooldown
453
+ * between consecutive requests). Calls during cooldown silently no-op
454
+ * the mail send while still returning success here.
455
+ */
456
+ requestPasswordReset(input: RequestPasswordResetInput): Promise<void>;
457
+ /**
458
+ * Finalise a password reset using the magic-link token sent to the
459
+ * user's inbox by {@link requestPasswordReset}.
460
+ *
461
+ * Typical use site: the page mounted on the reset URL declared in
462
+ * `aithos-auth-apps.reset_base_url`. The page reads `email` and
463
+ * `token` from `window.location.search`, prompts the user for a new
464
+ * password, then calls this method.
465
+ *
466
+ * On success, the returned {@link AithosSession} is persisted to the
467
+ * session store but the local keystore is NOT hydrated — the backend
468
+ * does not return the seed bundle on this endpoint. To get a fully
469
+ * usable session (one that can sign envelopes), follow up with
470
+ * {@link signInCustodial} using the email + new password. The two
471
+ * round-trips can be hidden inside a single UI action: reset → auto
472
+ * sign-in → redirect to dashboard.
473
+ *
474
+ * Errors map to `AithosSDKError` codes:
475
+ * - `auth_invalid_input` (your code passed empty fields)
476
+ * - `auth_reset_token_invalid` (400 — token forged / wrong email)
477
+ * - `auth_reset_token_expired` (410 — token TTL elapsed)
478
+ * - `auth_reset_token_consumed` (409 — already used)
479
+ * - `auth_password_too_short` (400 — < 10 chars)
480
+ * - `auth_custodial_reset_failed` (catch-all)
113
481
  */
482
+ applyPasswordReset(input: ApplyPasswordResetInput): Promise<ApplyPasswordResetResult>;
114
483
  signOut(): Promise<void>;
115
484
  }
116
485
  //# sourceMappingURL=auth.d.ts.map