@aithos/sdk 0.1.0-alpha.6 → 0.1.0-alpha.60
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/README.md +202 -7
- package/dist/src/agent-dispatch.d.ts +18 -0
- package/dist/src/agent-dispatch.js +178 -0
- package/dist/src/agent-loop.d.ts +94 -0
- package/dist/src/agent-loop.js +95 -0
- package/dist/src/agent-tools.d.ts +24 -0
- package/dist/src/agent-tools.js +147 -0
- package/dist/src/apps.d.ts +224 -0
- package/dist/src/apps.js +432 -0
- package/dist/src/assets.d.ts +225 -0
- package/dist/src/assets.js +534 -0
- package/dist/src/auth-api.d.ts +219 -0
- package/dist/src/auth-api.js +248 -0
- package/dist/src/auth.d.ts +591 -0
- package/dist/src/auth.js +947 -31
- package/dist/src/compute.d.ts +674 -6
- package/dist/src/compute.js +968 -20
- package/dist/src/data-schema-contacts-v1.d.ts +14 -0
- package/dist/src/data-schema-contacts-v1.js +28 -0
- package/dist/src/data.d.ts +368 -0
- package/dist/src/data.js +1124 -0
- package/dist/src/endpoints.d.ts +43 -0
- package/dist/src/endpoints.js +23 -0
- package/dist/src/ethos.d.ts +85 -0
- package/dist/src/ethos.js +463 -7
- package/dist/src/index.d.ts +22 -4
- package/dist/src/index.js +47 -2
- package/dist/src/internal/cmk-wrap.d.ts +41 -0
- package/dist/src/internal/cmk-wrap.js +132 -0
- package/dist/src/internal/delegate-bundle.js +7 -2
- package/dist/src/internal/envelope.d.ts +93 -0
- package/dist/src/internal/envelope.js +59 -0
- package/dist/src/internal/owner-signers.d.ts +5 -2
- package/dist/src/internal/owner-signers.js +22 -1
- package/dist/src/internal/recovery-file.d.ts +2 -0
- package/dist/src/internal/recovery-file.js +7 -0
- package/dist/src/key-store.d.ts +10 -0
- package/dist/src/key-store.js +6 -0
- package/dist/src/mandates.d.ts +58 -1
- package/dist/src/mandates.js +46 -3
- package/dist/src/migrate.d.ts +105 -0
- package/dist/src/migrate.js +367 -0
- package/dist/src/react/AithosAsset.d.ts +66 -0
- package/dist/src/react/AithosAsset.js +67 -0
- package/dist/src/react/context.d.ts +29 -0
- package/dist/src/react/context.js +31 -0
- package/dist/src/react/index.d.ts +29 -0
- package/dist/src/react/index.js +31 -0
- package/dist/src/react/use-aithos-asset.d.ts +39 -0
- package/dist/src/react/use-aithos-asset.js +118 -0
- package/dist/src/react/use-transcribe-pending.d.ts +21 -0
- package/dist/src/react/use-transcribe-pending.js +47 -0
- package/dist/src/rotate.d.ts +94 -0
- package/dist/src/rotate.js +298 -0
- package/dist/src/sdk.d.ts +36 -2
- package/dist/src/sdk.js +72 -1
- package/dist/src/transcribe-resilience.d.ts +57 -0
- package/dist/src/transcribe-resilience.js +203 -0
- package/dist/src/web.d.ts +279 -0
- package/dist/src/web.js +186 -0
- package/dist/test/agent-dispatch.test.d.ts +2 -0
- package/dist/test/agent-dispatch.test.js +222 -0
- package/dist/test/agent-loop.test.d.ts +2 -0
- package/dist/test/agent-loop.test.js +117 -0
- package/dist/test/agent-tools.test.d.ts +2 -0
- package/dist/test/agent-tools.test.js +50 -0
- package/dist/test/auth-j3.test.js +32 -1
- package/dist/test/canonical-conformance.test.d.ts +2 -0
- package/dist/test/canonical-conformance.test.js +86 -0
- package/dist/test/compute-delegate-path.test.d.ts +2 -0
- package/dist/test/compute-delegate-path.test.js +183 -0
- package/dist/test/compute.test.js +4 -0
- package/dist/test/converse.test.d.ts +2 -0
- package/dist/test/converse.test.js +162 -0
- package/dist/test/data-sphere.test.d.ts +2 -0
- package/dist/test/data-sphere.test.js +57 -0
- package/dist/test/endpoints.test.js +40 -1
- package/dist/test/envelope-core-conformance.test.d.ts +2 -0
- package/dist/test/envelope-core-conformance.test.js +75 -0
- package/dist/test/envelope.test.d.ts +2 -0
- package/dist/test/envelope.test.js +318 -0
- package/dist/test/ethos-first-edition.test.d.ts +2 -0
- package/dist/test/ethos-first-edition.test.js +371 -0
- package/dist/test/invoke-turn-sdk.test.d.ts +2 -0
- package/dist/test/invoke-turn-sdk.test.js +177 -0
- package/dist/test/migrate.test.d.ts +2 -0
- package/dist/test/migrate.test.js +340 -0
- package/dist/test/owner-data-client.test.d.ts +2 -0
- package/dist/test/owner-data-client.test.js +88 -0
- package/dist/test/rotate-ethos.test.d.ts +2 -0
- package/dist/test/rotate-ethos.test.js +151 -0
- package/dist/test/rotate.test.d.ts +2 -0
- package/dist/test/rotate.test.js +63 -0
- package/dist/test/schema-autoresolve.test.d.ts +2 -0
- package/dist/test/schema-autoresolve.test.js +146 -0
- package/dist/test/sdk.test.js +11 -2
- package/dist/test/signup-bootstrap.test.d.ts +2 -0
- package/dist/test/signup-bootstrap.test.js +311 -0
- package/dist/test/transcribe-invoke.test.d.ts +2 -0
- package/dist/test/transcribe-invoke.test.js +204 -0
- package/dist/test/transcribe.test.d.ts +2 -0
- package/dist/test/transcribe.test.js +186 -0
- package/dist/test/web.test.d.ts +2 -0
- package/dist/test/web.test.js +270 -0
- package/package.json +20 -3
package/dist/src/auth-api.d.ts
CHANGED
|
@@ -21,6 +21,15 @@ export interface RegisterApiResponse {
|
|
|
21
21
|
readonly exp: number;
|
|
22
22
|
}
|
|
23
23
|
export declare function registerAccount(http: HttpClient, input: RegisterApiInput): Promise<RegisterApiResponse>;
|
|
24
|
+
export interface PutBlobApiInput {
|
|
25
|
+
readonly jwt: string;
|
|
26
|
+
readonly blob: Uint8Array;
|
|
27
|
+
readonly blobNonce: Uint8Array;
|
|
28
|
+
readonly blobVersion: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function putBlob(http: HttpClient, input: PutBlobApiInput): Promise<{
|
|
31
|
+
ok: true;
|
|
32
|
+
}>;
|
|
24
33
|
export interface LoginChallengeResponse {
|
|
25
34
|
readonly authSalt: Uint8Array;
|
|
26
35
|
readonly encSalt: Uint8Array;
|
|
@@ -37,5 +46,215 @@ export interface LoginVerifyResponse {
|
|
|
37
46
|
readonly blobVersion: number;
|
|
38
47
|
}
|
|
39
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
|
+
*/
|
|
57
|
+
export interface CustodialSignUpApiInput {
|
|
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;
|
|
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;
|
|
69
|
+
readonly displayName?: string;
|
|
70
|
+
readonly handleHint?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface CustodialSignUpApiResponse {
|
|
73
|
+
/** Always "pending_verification" — sign-in is blocked until the
|
|
74
|
+
* user clicks the confirmation link. */
|
|
75
|
+
readonly status: "pending_verification";
|
|
76
|
+
readonly email: string;
|
|
77
|
+
readonly mailSent: boolean;
|
|
78
|
+
readonly mailMessageId?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Provision a custodial-mode account on behalf of a registered app.
|
|
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.
|
|
93
|
+
*/
|
|
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
|
+
/**
|
|
100
|
+
* Result of consuming the verification link. Magic-link mode: a
|
|
101
|
+
* successful first-time consumption returns a full session payload
|
|
102
|
+
* (JWT + seeds) so the caller can sign the user in without prompting
|
|
103
|
+
* for the password. Replays of the same link (after first consumption)
|
|
104
|
+
* land on `status: "already_verified"` — the user is already verified
|
|
105
|
+
* and must use the regular sign-in flow from now on.
|
|
106
|
+
*
|
|
107
|
+
* The discriminator is the `status` field. Callers should pattern-match.
|
|
108
|
+
*/
|
|
109
|
+
export type CustodialVerifyEmailApiResponse = {
|
|
110
|
+
readonly status: "signed_in";
|
|
111
|
+
readonly session: string;
|
|
112
|
+
readonly exp: number;
|
|
113
|
+
readonly did: string;
|
|
114
|
+
readonly handle: string;
|
|
115
|
+
readonly displayName: string;
|
|
116
|
+
readonly seed: Uint8Array;
|
|
117
|
+
readonly encKey: Uint8Array;
|
|
118
|
+
readonly blob: Uint8Array;
|
|
119
|
+
readonly blobNonce: Uint8Array;
|
|
120
|
+
readonly blobVersion: number;
|
|
121
|
+
} | {
|
|
122
|
+
readonly status: "already_verified";
|
|
123
|
+
readonly email: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Consume the verification token from the confirmation link. On a fresh
|
|
127
|
+
* click: returns a full session payload (magic-link auto-signin). On a
|
|
128
|
+
* replayed click of an already-consumed link: returns
|
|
129
|
+
* `{ status: "already_verified" }`.
|
|
130
|
+
*
|
|
131
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong, consumed,
|
|
132
|
+
* or past its TTL.
|
|
133
|
+
*/
|
|
134
|
+
export declare function custodialVerifyEmail(http: HttpClient, input: CustodialVerifyEmailApiInput): Promise<CustodialVerifyEmailApiResponse>;
|
|
135
|
+
/**
|
|
136
|
+
* Input for {@link custodialInvite}. The app authenticates via `apiKey`
|
|
137
|
+
* (server-only secret) or `publicKey` (browser-safe, Origin-gated). The
|
|
138
|
+
* `invitePayload` is an OPAQUE app string delivered verbatim to the invitee
|
|
139
|
+
* on {@link custodialAccept}. For Aithos invitations it's a delegate bundle
|
|
140
|
+
* (mandate + seed) serialized as JSON — but the auth backend never parses it;
|
|
141
|
+
* it stores it bound to a single-use token and returns it at accept time.
|
|
142
|
+
*/
|
|
143
|
+
export interface CustodialInviteApiInput {
|
|
144
|
+
readonly apiKey?: string;
|
|
145
|
+
readonly publicKey?: string;
|
|
146
|
+
readonly email: string;
|
|
147
|
+
/** Opaque payload delivered to the invitee on accept (e.g. a mandate bundle JSON). */
|
|
148
|
+
readonly invitePayload: string;
|
|
149
|
+
/** Token TTL in seconds. Backend clamps to its own min/max. Default backend-side. */
|
|
150
|
+
readonly ttlSeconds?: number;
|
|
151
|
+
/** Optional display name pre-filled on the pending account. */
|
|
152
|
+
readonly displayName?: string;
|
|
153
|
+
}
|
|
154
|
+
export interface CustodialInviteApiResponse {
|
|
155
|
+
readonly status: "invited";
|
|
156
|
+
readonly email: string;
|
|
157
|
+
readonly mailSent: boolean;
|
|
158
|
+
readonly mailMessageId?: string;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Send an invitation magic link carrying an opaque payload. The backend
|
|
162
|
+
* mints a single-use token, stores `{ token, email, invite_payload, ttl }`,
|
|
163
|
+
* and emails the magic link (same SES path as the verification mail). The
|
|
164
|
+
* payload (e.g. a mandate bundle) stays server-side — it never rides the
|
|
165
|
+
* email URL. The invitee redeems it via {@link custodialAccept}.
|
|
166
|
+
*
|
|
167
|
+
* No password here: this is an invitation, not an account creation. The
|
|
168
|
+
* invitee chooses their password when they accept.
|
|
169
|
+
*/
|
|
170
|
+
export declare function custodialInvite(http: HttpClient, input: CustodialInviteApiInput): Promise<CustodialInviteApiResponse>;
|
|
171
|
+
export interface CustodialAcceptApiInput {
|
|
172
|
+
readonly email: string;
|
|
173
|
+
readonly token: string;
|
|
174
|
+
/**
|
|
175
|
+
* Password. For a brand-new account the invitee SETS it here; for an
|
|
176
|
+
* existing account they AUTHENTICATE with it. Required unless the backend
|
|
177
|
+
* accepts a session-bound redemption (not in v1).
|
|
178
|
+
*/
|
|
179
|
+
readonly password?: string;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Result of redeeming an invitation. Always `signed_in` on success — the
|
|
183
|
+
* token is consumed, the account is created (or the existing one is
|
|
184
|
+
* authenticated), and a full session payload is returned alongside the
|
|
185
|
+
* `invitePayload` the inviter attached. `accountCreated` distinguishes the
|
|
186
|
+
* two cases for UX.
|
|
187
|
+
*/
|
|
188
|
+
export interface CustodialAcceptApiResponse {
|
|
189
|
+
readonly status: "signed_in";
|
|
190
|
+
readonly session: string;
|
|
191
|
+
readonly exp: number;
|
|
192
|
+
readonly did: string;
|
|
193
|
+
readonly handle: string;
|
|
194
|
+
readonly displayName: string;
|
|
195
|
+
readonly seed: Uint8Array;
|
|
196
|
+
readonly encKey: Uint8Array;
|
|
197
|
+
readonly blob: Uint8Array;
|
|
198
|
+
readonly blobNonce: Uint8Array;
|
|
199
|
+
readonly blobVersion: number;
|
|
200
|
+
/** The opaque payload the inviter attached (e.g. a mandate bundle JSON). */
|
|
201
|
+
readonly invitePayload: string;
|
|
202
|
+
/** True when a new account was provisioned; false when an existing one signed in. */
|
|
203
|
+
readonly accountCreated: boolean;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Redeem an invitation token from the magic link. Consumes the token
|
|
207
|
+
* (single-use), creates the account with the supplied password (or
|
|
208
|
+
* authenticates an existing account), and returns a session + the inviter's
|
|
209
|
+
* `invitePayload`.
|
|
210
|
+
*
|
|
211
|
+
* Throws `auth_token_invalid_or_expired` (bad/consumed/expired token) or an
|
|
212
|
+
* auth error if an existing account's password is wrong / a new password is
|
|
213
|
+
* too weak.
|
|
214
|
+
*/
|
|
215
|
+
export declare function custodialAccept(http: HttpClient, input: CustodialAcceptApiInput): Promise<CustodialAcceptApiResponse>;
|
|
216
|
+
/** Re-send the verification mail for a pending account. The backend
|
|
217
|
+
* is anti-enum (always 200) and rate-limited 1/h/account, so this is
|
|
218
|
+
* safe to call even when the user state is unknown. Accepts the same
|
|
219
|
+
* credential families as {@link custodialSignUp}. */
|
|
220
|
+
export declare function custodialResendVerify(http: HttpClient, args: {
|
|
221
|
+
readonly email: string;
|
|
222
|
+
readonly apiKey?: string;
|
|
223
|
+
readonly publicKey?: string;
|
|
224
|
+
}): Promise<void>;
|
|
225
|
+
export interface CustodialSignInApiInput {
|
|
226
|
+
readonly email: string;
|
|
227
|
+
readonly password: string;
|
|
228
|
+
}
|
|
229
|
+
export interface CustodialSignInApiResponse {
|
|
230
|
+
readonly session: string;
|
|
231
|
+
readonly exp: number;
|
|
232
|
+
readonly did: string;
|
|
233
|
+
readonly handle: string;
|
|
234
|
+
readonly displayName: string;
|
|
235
|
+
/** Raw 32-byte Ed25519 seed — caller MUST hydrate its keystore and
|
|
236
|
+
* zeroize this buffer. */
|
|
237
|
+
readonly seed: Uint8Array;
|
|
238
|
+
/** Raw 32-byte vault encryption key — same lifecycle. */
|
|
239
|
+
readonly encKey: Uint8Array;
|
|
240
|
+
readonly blob: Uint8Array;
|
|
241
|
+
readonly blobNonce: Uint8Array;
|
|
242
|
+
readonly blobVersion: number;
|
|
243
|
+
readonly passwordMustChange: boolean;
|
|
244
|
+
}
|
|
245
|
+
export declare function custodialSignIn(http: HttpClient, input: CustodialSignInApiInput): Promise<CustodialSignInApiResponse>;
|
|
246
|
+
export declare function custodialResetRequest(http: HttpClient, email: string): Promise<void>;
|
|
247
|
+
export interface CustodialResetFinalizeApiInput {
|
|
248
|
+
readonly email: string;
|
|
249
|
+
readonly token: string;
|
|
250
|
+
readonly newPassword: string;
|
|
251
|
+
}
|
|
252
|
+
export interface CustodialResetFinalizeApiResponse {
|
|
253
|
+
readonly session: string;
|
|
254
|
+
readonly exp: number;
|
|
255
|
+
readonly did: string;
|
|
256
|
+
readonly handle: string;
|
|
257
|
+
}
|
|
258
|
+
export declare function custodialResetFinalize(http: HttpClient, input: CustodialResetFinalizeApiInput): Promise<CustodialResetFinalizeApiResponse>;
|
|
40
259
|
export {};
|
|
41
260
|
//# sourceMappingURL=auth-api.d.ts.map
|
package/dist/src/auth-api.js
CHANGED
|
@@ -41,6 +41,19 @@ async function postJson(http, path, body, jwt) {
|
|
|
41
41
|
throw await readError(res, "request_failed");
|
|
42
42
|
return (await res.json());
|
|
43
43
|
}
|
|
44
|
+
async function putJson(http, path, body, jwt) {
|
|
45
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}${path}`, {
|
|
46
|
+
method: "PUT",
|
|
47
|
+
headers: {
|
|
48
|
+
"content-type": "application/json",
|
|
49
|
+
authorization: `Bearer ${jwt}`,
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify(body),
|
|
52
|
+
});
|
|
53
|
+
if (!res.ok)
|
|
54
|
+
throw await readError(res, "request_failed");
|
|
55
|
+
return (await res.json());
|
|
56
|
+
}
|
|
44
57
|
export async function registerAccount(http, input) {
|
|
45
58
|
return postJson(http, "/auth/register", {
|
|
46
59
|
email: input.email,
|
|
@@ -56,6 +69,13 @@ export async function registerAccount(http, input) {
|
|
|
56
69
|
blob_version: input.blobVersion,
|
|
57
70
|
});
|
|
58
71
|
}
|
|
72
|
+
export async function putBlob(http, input) {
|
|
73
|
+
return putJson(http, "/auth/blob", {
|
|
74
|
+
blob_b64: bytesToB64(input.blob),
|
|
75
|
+
blob_nonce_b64: bytesToB64(input.blobNonce),
|
|
76
|
+
blob_version: input.blobVersion,
|
|
77
|
+
}, input.jwt);
|
|
78
|
+
}
|
|
59
79
|
export async function loginChallenge(http, email) {
|
|
60
80
|
const wire = await postJson(http, "/auth/login/challenge", { email });
|
|
61
81
|
return {
|
|
@@ -79,4 +99,232 @@ export async function loginVerify(http, email, authKey) {
|
|
|
79
99
|
blobVersion: wire.blob_version,
|
|
80
100
|
};
|
|
81
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Provision a custodial-mode account on behalf of a registered app.
|
|
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.
|
|
115
|
+
*/
|
|
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);
|
|
124
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/sign-up`, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: {
|
|
127
|
+
"content-type": "application/json",
|
|
128
|
+
authorization: `Bearer ${bearer}`,
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
email: input.email,
|
|
132
|
+
password: input.password,
|
|
133
|
+
...(input.displayName ? { display_name: input.displayName } : {}),
|
|
134
|
+
...(input.handleHint ? { handle_hint: input.handleHint } : {}),
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok)
|
|
138
|
+
throw await readError(res, "custodial_signup_failed");
|
|
139
|
+
const wire = (await res.json());
|
|
140
|
+
return {
|
|
141
|
+
status: "pending_verification",
|
|
142
|
+
email: wire.email,
|
|
143
|
+
mailSent: wire.mail_sent,
|
|
144
|
+
...(wire.mail_message_id !== undefined
|
|
145
|
+
? { mailMessageId: wire.mail_message_id }
|
|
146
|
+
: {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Consume the verification token from the confirmation link. On a fresh
|
|
151
|
+
* click: returns a full session payload (magic-link auto-signin). On a
|
|
152
|
+
* replayed click of an already-consumed link: returns
|
|
153
|
+
* `{ status: "already_verified" }`.
|
|
154
|
+
*
|
|
155
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong, consumed,
|
|
156
|
+
* or past its TTL.
|
|
157
|
+
*/
|
|
158
|
+
export async function custodialVerifyEmail(http, input) {
|
|
159
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/verify`, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: { "content-type": "application/json" },
|
|
162
|
+
body: JSON.stringify({ email: input.email, token: input.token }),
|
|
163
|
+
});
|
|
164
|
+
if (!res.ok)
|
|
165
|
+
throw await readError(res, "custodial_verify_failed");
|
|
166
|
+
const wire = (await res.json());
|
|
167
|
+
if (wire.status === "already_verified") {
|
|
168
|
+
return { status: "already_verified", email: wire.email };
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
status: "signed_in",
|
|
172
|
+
session: wire.session,
|
|
173
|
+
exp: wire.exp,
|
|
174
|
+
did: wire.did,
|
|
175
|
+
handle: wire.handle,
|
|
176
|
+
displayName: wire.display_name,
|
|
177
|
+
seed: b64ToBytes(wire.seed_b64),
|
|
178
|
+
encKey: b64ToBytes(wire.enc_key_b64),
|
|
179
|
+
blob: wire.blob_b64 ? b64ToBytes(wire.blob_b64) : new Uint8Array(0),
|
|
180
|
+
blobNonce: wire.blob_nonce_b64
|
|
181
|
+
? b64ToBytes(wire.blob_nonce_b64)
|
|
182
|
+
: new Uint8Array(0),
|
|
183
|
+
blobVersion: wire.blob_version,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Send an invitation magic link carrying an opaque payload. The backend
|
|
188
|
+
* mints a single-use token, stores `{ token, email, invite_payload, ttl }`,
|
|
189
|
+
* and emails the magic link (same SES path as the verification mail). The
|
|
190
|
+
* payload (e.g. a mandate bundle) stays server-side — it never rides the
|
|
191
|
+
* email URL. The invitee redeems it via {@link custodialAccept}.
|
|
192
|
+
*
|
|
193
|
+
* No password here: this is an invitation, not an account creation. The
|
|
194
|
+
* invitee chooses their password when they accept.
|
|
195
|
+
*/
|
|
196
|
+
export async function custodialInvite(http, input) {
|
|
197
|
+
if (!input.apiKey && !input.publicKey) {
|
|
198
|
+
throw new AithosSDKError("auth_missing_api_key", "inviteCustodial requires either apiKey or publicKey");
|
|
199
|
+
}
|
|
200
|
+
if (input.apiKey && input.publicKey) {
|
|
201
|
+
throw new AithosSDKError("auth_invalid_input", "inviteCustodial: pass exactly one of apiKey or publicKey, not both");
|
|
202
|
+
}
|
|
203
|
+
const bearer = (input.apiKey ?? input.publicKey);
|
|
204
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/invite`, {
|
|
205
|
+
method: "POST",
|
|
206
|
+
headers: {
|
|
207
|
+
"content-type": "application/json",
|
|
208
|
+
authorization: `Bearer ${bearer}`,
|
|
209
|
+
},
|
|
210
|
+
body: JSON.stringify({
|
|
211
|
+
email: input.email,
|
|
212
|
+
invite_payload: input.invitePayload,
|
|
213
|
+
...(input.ttlSeconds !== undefined ? { ttl_seconds: input.ttlSeconds } : {}),
|
|
214
|
+
...(input.displayName ? { display_name: input.displayName } : {}),
|
|
215
|
+
}),
|
|
216
|
+
});
|
|
217
|
+
if (!res.ok)
|
|
218
|
+
throw await readError(res, "custodial_invite_failed");
|
|
219
|
+
const wire = (await res.json());
|
|
220
|
+
return {
|
|
221
|
+
status: "invited",
|
|
222
|
+
email: wire.email,
|
|
223
|
+
mailSent: wire.mail_sent,
|
|
224
|
+
...(wire.mail_message_id !== undefined ? { mailMessageId: wire.mail_message_id } : {}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Redeem an invitation token from the magic link. Consumes the token
|
|
229
|
+
* (single-use), creates the account with the supplied password (or
|
|
230
|
+
* authenticates an existing account), and returns a session + the inviter's
|
|
231
|
+
* `invitePayload`.
|
|
232
|
+
*
|
|
233
|
+
* Throws `auth_token_invalid_or_expired` (bad/consumed/expired token) or an
|
|
234
|
+
* auth error if an existing account's password is wrong / a new password is
|
|
235
|
+
* too weak.
|
|
236
|
+
*/
|
|
237
|
+
export async function custodialAccept(http, input) {
|
|
238
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/accept`, {
|
|
239
|
+
method: "POST",
|
|
240
|
+
headers: { "content-type": "application/json" },
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
email: input.email,
|
|
243
|
+
token: input.token,
|
|
244
|
+
...(input.password ? { password: input.password } : {}),
|
|
245
|
+
}),
|
|
246
|
+
});
|
|
247
|
+
if (!res.ok)
|
|
248
|
+
throw await readError(res, "custodial_accept_failed");
|
|
249
|
+
const wire = (await res.json());
|
|
250
|
+
return {
|
|
251
|
+
status: "signed_in",
|
|
252
|
+
session: wire.session,
|
|
253
|
+
exp: wire.exp,
|
|
254
|
+
did: wire.did,
|
|
255
|
+
handle: wire.handle,
|
|
256
|
+
displayName: wire.display_name,
|
|
257
|
+
seed: b64ToBytes(wire.seed_b64),
|
|
258
|
+
encKey: b64ToBytes(wire.enc_key_b64),
|
|
259
|
+
blob: wire.blob_b64 ? b64ToBytes(wire.blob_b64) : new Uint8Array(0),
|
|
260
|
+
blobNonce: wire.blob_nonce_b64 ? b64ToBytes(wire.blob_nonce_b64) : new Uint8Array(0),
|
|
261
|
+
blobVersion: wire.blob_version,
|
|
262
|
+
invitePayload: wire.invite_payload,
|
|
263
|
+
accountCreated: wire.account_created,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/* ---- POST /auth/custodial/verify/resend -------------------------------- */
|
|
267
|
+
/** Re-send the verification mail for a pending account. The backend
|
|
268
|
+
* is anti-enum (always 200) and rate-limited 1/h/account, so this is
|
|
269
|
+
* safe to call even when the user state is unknown. Accepts the same
|
|
270
|
+
* credential families as {@link custodialSignUp}. */
|
|
271
|
+
export async function custodialResendVerify(http, args) {
|
|
272
|
+
if (!args.apiKey && !args.publicKey) {
|
|
273
|
+
throw new AithosSDKError("auth_missing_api_key", "resendVerificationEmail requires either apiKey or publicKey");
|
|
274
|
+
}
|
|
275
|
+
const bearer = (args.apiKey ?? args.publicKey);
|
|
276
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/verify/resend`, {
|
|
277
|
+
method: "POST",
|
|
278
|
+
headers: {
|
|
279
|
+
"content-type": "application/json",
|
|
280
|
+
authorization: `Bearer ${bearer}`,
|
|
281
|
+
},
|
|
282
|
+
body: JSON.stringify({ email: args.email }),
|
|
283
|
+
});
|
|
284
|
+
if (!res.ok)
|
|
285
|
+
throw await readError(res, "custodial_resend_failed");
|
|
286
|
+
}
|
|
287
|
+
export async function custodialSignIn(http, input) {
|
|
288
|
+
const wire = await postJson(http, "/auth/custodial/sign-in", { email: input.email, password: input.password });
|
|
289
|
+
return {
|
|
290
|
+
session: wire.session,
|
|
291
|
+
exp: wire.exp,
|
|
292
|
+
did: wire.did,
|
|
293
|
+
handle: wire.handle,
|
|
294
|
+
displayName: wire.display_name,
|
|
295
|
+
seed: b64ToBytes(wire.seed_b64),
|
|
296
|
+
encKey: b64ToBytes(wire.enc_key_b64),
|
|
297
|
+
blob: wire.blob_b64 ? b64ToBytes(wire.blob_b64) : new Uint8Array(0),
|
|
298
|
+
blobNonce: wire.blob_nonce_b64
|
|
299
|
+
? b64ToBytes(wire.blob_nonce_b64)
|
|
300
|
+
: new Uint8Array(0),
|
|
301
|
+
blobVersion: wire.blob_version,
|
|
302
|
+
passwordMustChange: wire.password_must_change,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/* ---- POST /auth/custodial/reset/request --------------------------------- */
|
|
306
|
+
export async function custodialResetRequest(http, email) {
|
|
307
|
+
// Backend always returns 200 { ok: true } regardless. We accept any
|
|
308
|
+
// 2xx body, even non-JSON, to be defensive.
|
|
309
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/reset/request`, {
|
|
310
|
+
method: "POST",
|
|
311
|
+
headers: { "content-type": "application/json" },
|
|
312
|
+
body: JSON.stringify({ email }),
|
|
313
|
+
});
|
|
314
|
+
if (!res.ok)
|
|
315
|
+
throw await readError(res, "custodial_reset_request_failed");
|
|
316
|
+
}
|
|
317
|
+
export async function custodialResetFinalize(http, input) {
|
|
318
|
+
const wire = await postJson(http, "/auth/custodial/reset/finalize", {
|
|
319
|
+
email: input.email,
|
|
320
|
+
token: input.token,
|
|
321
|
+
new_password: input.newPassword,
|
|
322
|
+
});
|
|
323
|
+
return {
|
|
324
|
+
session: wire.session,
|
|
325
|
+
exp: wire.exp,
|
|
326
|
+
did: wire.did,
|
|
327
|
+
handle: wire.handle,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
82
330
|
//# sourceMappingURL=auth-api.js.map
|