@aithos/sdk 0.1.0-alpha.2 → 0.1.0-alpha.20
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 +45 -0
- package/dist/src/auth-api.d.ts +50 -0
- package/dist/src/auth-api.js +102 -0
- package/dist/src/auth.d.ts +253 -0
- package/dist/src/auth.js +940 -0
- package/dist/src/compute.d.ts +370 -9
- package/dist/src/compute.js +369 -16
- package/dist/src/ethos.d.ts +117 -1
- package/dist/src/ethos.js +646 -16
- package/dist/src/index.d.ts +11 -4
- package/dist/src/index.js +31 -5
- package/dist/src/internal/delegate-bundle.d.ts +18 -0
- package/dist/src/internal/delegate-bundle.js +94 -0
- package/dist/src/internal/delegate-state.d.ts +45 -0
- package/dist/src/internal/delegate-state.js +120 -0
- package/dist/src/internal/owner-signers.d.ts +78 -0
- package/dist/src/internal/owner-signers.js +179 -0
- package/dist/src/internal/protocol-client-bridge.d.ts +8 -0
- package/dist/src/internal/protocol-client-bridge.js +20 -0
- package/dist/src/internal/recovery-file.d.ts +29 -0
- package/dist/src/internal/recovery-file.js +98 -0
- package/dist/src/internal/signer.d.ts +59 -0
- package/dist/src/internal/signer.js +86 -0
- package/dist/src/key-store.d.ts +128 -0
- package/dist/src/key-store.js +244 -0
- package/dist/src/mandates.d.ts +163 -1
- package/dist/src/mandates.js +286 -8
- package/dist/src/sdk.d.ts +36 -3
- package/dist/src/sdk.js +27 -23
- package/dist/src/session-store.d.ts +58 -0
- package/dist/src/session-store.js +158 -0
- package/dist/src/wallet.d.ts +4 -6
- package/dist/src/wallet.js +18 -8
- package/dist/test/auth-j3.test.d.ts +2 -0
- package/dist/test/auth-j3.test.js +391 -0
- package/dist/test/auth.test.d.ts +2 -0
- package/dist/test/auth.test.js +175 -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 +184 -11
- package/dist/test/ethos-first-edition.test.d.ts +2 -0
- package/dist/test/ethos-first-edition.test.js +248 -0
- package/dist/test/ethos.test.d.ts +2 -0
- package/dist/test/ethos.test.js +219 -0
- package/dist/test/key-store.test.d.ts +2 -0
- package/dist/test/key-store.test.js +161 -0
- package/dist/test/mandates-compute.test.d.ts +2 -0
- package/dist/test/mandates-compute.test.js +256 -0
- package/dist/test/mandates.test.d.ts +2 -0
- package/dist/test/mandates.test.js +93 -0
- package/dist/test/sdk.test.js +70 -30
- package/dist/test/signer.test.d.ts +2 -0
- package/dist/test/signer.test.js +117 -0
- package/dist/test/signup-bootstrap.test.d.ts +2 -0
- package/dist/test/signup-bootstrap.test.js +222 -0
- package/dist/test/wallet.test.js +20 -9
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -55,6 +55,51 @@ const reply = await sdk.compute.invokeBedrock({
|
|
|
55
55
|
console.log(reply.content);
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
## Delegating compute to an agent — opt-in token spending
|
|
59
|
+
|
|
60
|
+
To let an agent (or another user, or a third-party app) invoke Bedrock
|
|
61
|
+
**in your name**, with **your credits**, you mint a mandate. Token
|
|
62
|
+
spending is its own opt-in capability — passing it is a separate,
|
|
63
|
+
named, validated input that a consent UI can review. It is NEVER an
|
|
64
|
+
implicit side-effect of an ethos read/write scope.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// Mint a mandate that lets agent Bob read your public ethos AND
|
|
68
|
+
// spend up to 5 000 microcredits/day on Haiku, capped at 100 000
|
|
69
|
+
// microcredits over the whole mandate lifetime.
|
|
70
|
+
const mandate = await sdk.mandates.create({
|
|
71
|
+
granteeId: "urn:agent:bob",
|
|
72
|
+
scopes: ["ethos.read.public"],
|
|
73
|
+
ttlSeconds: 86_400,
|
|
74
|
+
compute: {
|
|
75
|
+
dailyCapMicrocredits: 5_000,
|
|
76
|
+
totalCapMicrocredits: 100_000,
|
|
77
|
+
maxCreditsPerCall: 500,
|
|
78
|
+
allowedModels: ["claude-haiku-4-5"],
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Hand `mandate.bundle` (a `.aithos-delegate.json` Blob) to Bob.
|
|
83
|
+
// He imports it, then signs his own envelopes and calls
|
|
84
|
+
// sdk.compute.invokeBedrock({ mandateId: mandate.mandateId, … })
|
|
85
|
+
// — every invocation debits *your* wallet, capped per the budget
|
|
86
|
+
// you set.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Three invariants the SDK enforces synchronously, before reaching the
|
|
90
|
+
network — they fail fast with a precise `AithosSDKError`:
|
|
91
|
+
|
|
92
|
+
- **No smuggling.** Adding `"compute.invoke"` directly to `scopes[]`
|
|
93
|
+
throws `mandates_invalid_scopes`. The `compute` namespace is the
|
|
94
|
+
only path, so a UI reviewing `compute` can never be bypassed.
|
|
95
|
+
- **No bearer compute.** A `compute` namespace without at least one
|
|
96
|
+
of `dailyCapMicrocredits` or `totalCapMicrocredits` throws
|
|
97
|
+
`mandates_invalid_compute`. Unbounded compute mandates are forbidden
|
|
98
|
+
by construction.
|
|
99
|
+
- **Compute-only is fine.** `scopes: []` is allowed when `compute` is
|
|
100
|
+
set — useful for agents that only consume tokens (e.g. creative
|
|
101
|
+
assistants) without seeing any of your data.
|
|
102
|
+
|
|
58
103
|
## What lives where
|
|
59
104
|
|
|
60
105
|
| Namespace | Purpose |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type KdfParams } from "@aithos/protocol-client";
|
|
2
|
+
interface HttpClient {
|
|
3
|
+
readonly fetchImpl: typeof fetch;
|
|
4
|
+
readonly authBaseUrl: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RegisterApiInput {
|
|
7
|
+
readonly email: string;
|
|
8
|
+
readonly handle: string;
|
|
9
|
+
readonly displayName: string;
|
|
10
|
+
readonly did: string;
|
|
11
|
+
readonly authKey: Uint8Array;
|
|
12
|
+
readonly authSalt: Uint8Array;
|
|
13
|
+
readonly encSalt: Uint8Array;
|
|
14
|
+
readonly kdf: KdfParams;
|
|
15
|
+
readonly blob: Uint8Array;
|
|
16
|
+
readonly blobNonce: Uint8Array;
|
|
17
|
+
readonly blobVersion: number;
|
|
18
|
+
}
|
|
19
|
+
export interface RegisterApiResponse {
|
|
20
|
+
readonly session: string;
|
|
21
|
+
readonly exp: number;
|
|
22
|
+
}
|
|
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
|
+
}>;
|
|
33
|
+
export interface LoginChallengeResponse {
|
|
34
|
+
readonly authSalt: Uint8Array;
|
|
35
|
+
readonly encSalt: Uint8Array;
|
|
36
|
+
readonly kdf: KdfParams;
|
|
37
|
+
}
|
|
38
|
+
export declare function loginChallenge(http: HttpClient, email: string): Promise<LoginChallengeResponse>;
|
|
39
|
+
export interface LoginVerifyResponse {
|
|
40
|
+
readonly session: string;
|
|
41
|
+
readonly exp: number;
|
|
42
|
+
readonly did: string;
|
|
43
|
+
readonly handle: string;
|
|
44
|
+
readonly blob: Uint8Array;
|
|
45
|
+
readonly blobNonce: Uint8Array;
|
|
46
|
+
readonly blobVersion: number;
|
|
47
|
+
}
|
|
48
|
+
export declare function loginVerify(http: HttpClient, email: string, authKey: Uint8Array): Promise<LoginVerifyResponse>;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=auth-api.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
// Thin HTTP client over the Aithos auth Lambda.
|
|
4
|
+
//
|
|
5
|
+
// Internal — not exported from the package's public surface. The
|
|
6
|
+
// {@link AithosAuth} class composes these calls with the crypto
|
|
7
|
+
// primitives in `@aithos/protocol-client` and the session store in
|
|
8
|
+
// {@link ./session-store.ts} to expose a high-level
|
|
9
|
+
// signIn / signUp / signInWithGoogle API.
|
|
10
|
+
//
|
|
11
|
+
// Wire format mirrors `aithos/auth/API.md` exactly. All `*_b64` fields
|
|
12
|
+
// are standard-base64 (not URL-safe), padding stripped — see
|
|
13
|
+
// `bytesToB64` / `b64ToBytes` in `@aithos/protocol-client`.
|
|
14
|
+
import { bytesToB64, b64ToBytes, } from "@aithos/protocol-client";
|
|
15
|
+
import { AithosSDKError } from "./types.js";
|
|
16
|
+
async function readError(res, defaultCode) {
|
|
17
|
+
let body = null;
|
|
18
|
+
try {
|
|
19
|
+
body = (await res.json());
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
/* body not JSON */
|
|
23
|
+
}
|
|
24
|
+
const code = typeof body?.code === "string" ? `auth_${body.code}` : `auth_${defaultCode}`;
|
|
25
|
+
const message = body?.error ?? `${res.status} ${res.statusText || "request failed"}`;
|
|
26
|
+
return new AithosSDKError(code, message, {
|
|
27
|
+
status: res.status,
|
|
28
|
+
...(body !== null ? { data: body } : {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function postJson(http, path, body, jwt) {
|
|
32
|
+
const res = await http.fetchImpl(`${http.authBaseUrl}${path}`, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: {
|
|
35
|
+
"content-type": "application/json",
|
|
36
|
+
...(jwt ? { authorization: `Bearer ${jwt}` } : {}),
|
|
37
|
+
},
|
|
38
|
+
body: JSON.stringify(body),
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok)
|
|
41
|
+
throw await readError(res, "request_failed");
|
|
42
|
+
return (await res.json());
|
|
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
|
+
}
|
|
57
|
+
export async function registerAccount(http, input) {
|
|
58
|
+
return postJson(http, "/auth/register", {
|
|
59
|
+
email: input.email,
|
|
60
|
+
handle: input.handle,
|
|
61
|
+
display_name: input.displayName,
|
|
62
|
+
did: input.did,
|
|
63
|
+
auth_key_b64: bytesToB64(input.authKey),
|
|
64
|
+
auth_salt_b64: bytesToB64(input.authSalt),
|
|
65
|
+
enc_salt_b64: bytesToB64(input.encSalt),
|
|
66
|
+
kdf: input.kdf,
|
|
67
|
+
blob_b64: bytesToB64(input.blob),
|
|
68
|
+
blob_nonce_b64: bytesToB64(input.blobNonce),
|
|
69
|
+
blob_version: input.blobVersion,
|
|
70
|
+
});
|
|
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
|
+
}
|
|
79
|
+
export async function loginChallenge(http, email) {
|
|
80
|
+
const wire = await postJson(http, "/auth/login/challenge", { email });
|
|
81
|
+
return {
|
|
82
|
+
authSalt: b64ToBytes(wire.auth_salt_b64),
|
|
83
|
+
encSalt: b64ToBytes(wire.enc_salt_b64),
|
|
84
|
+
kdf: wire.kdf,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export async function loginVerify(http, email, authKey) {
|
|
88
|
+
const wire = await postJson(http, "/auth/login/verify", {
|
|
89
|
+
email,
|
|
90
|
+
auth_key_b64: bytesToB64(authKey),
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
session: wire.session,
|
|
94
|
+
exp: wire.exp,
|
|
95
|
+
did: wire.did,
|
|
96
|
+
handle: wire.handle,
|
|
97
|
+
blob: b64ToBytes(wire.blob_b64),
|
|
98
|
+
blobNonce: b64ToBytes(wire.blob_nonce_b64),
|
|
99
|
+
blobVersion: wire.blob_version,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=auth-api.js.map
|
|
@@ -0,0 +1,253 @@
|
|
|
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";
|
|
5
|
+
/** Default URL of the Aithos auth backend. */
|
|
6
|
+
export declare const DEFAULT_AUTH_BASE_URL = "https://auth.aithos.be";
|
|
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";
|
|
9
|
+
export interface AithosAuthConfig {
|
|
10
|
+
readonly authBaseUrl?: string;
|
|
11
|
+
/**
|
|
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}.
|
|
17
|
+
*/
|
|
18
|
+
readonly apiBaseUrl?: string;
|
|
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;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Active Aithos session. Returned by JWT-backed entry points
|
|
28
|
+
* (`signIn`, `signUp`, `handleCallback`). Recovery-file and mandate
|
|
29
|
+
* sign-ins do NOT return an `AithosSession` — they yield the lighter
|
|
30
|
+
* {@link OwnerInfo} / {@link DelegateInfo}.
|
|
31
|
+
*/
|
|
32
|
+
export interface AithosSession {
|
|
33
|
+
readonly session: string;
|
|
34
|
+
readonly exp: number;
|
|
35
|
+
readonly did: string;
|
|
36
|
+
readonly handle: string;
|
|
37
|
+
readonly blob_b64: string;
|
|
38
|
+
readonly blob_nonce_b64: string;
|
|
39
|
+
readonly blob_version: number;
|
|
40
|
+
readonly enc_key_b64: string;
|
|
41
|
+
readonly is_first_login: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Public information about the loaded owner identity. Available after
|
|
45
|
+
* any owner-side sign-in (password, Google, recovery), regardless of
|
|
46
|
+
* whether a JWT is also present.
|
|
47
|
+
*/
|
|
48
|
+
export interface OwnerInfo {
|
|
49
|
+
readonly did: string;
|
|
50
|
+
readonly handle: string;
|
|
51
|
+
readonly displayName: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Public information about a delegate session held by the SDK. Returned
|
|
55
|
+
* by `importMandate` and `getDelegates`.
|
|
56
|
+
*/
|
|
57
|
+
export interface DelegateInfo {
|
|
58
|
+
readonly mandateId: string;
|
|
59
|
+
readonly subjectDid: string;
|
|
60
|
+
readonly granteeId: string;
|
|
61
|
+
readonly scopes: readonly string[];
|
|
62
|
+
/** ISO-8601, or null when the mandate has no `not_after`. */
|
|
63
|
+
readonly expiresAt: string | null;
|
|
64
|
+
readonly label?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface SignInWithGoogleOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Opaque state the consumer app wants to recover after the OAuth
|
|
69
|
+
* round-trip (e.g. a deep-link to resume on). Echoed back as
|
|
70
|
+
* `?app_state=` on the final redirect.
|
|
71
|
+
*/
|
|
72
|
+
readonly appState?: string;
|
|
73
|
+
/**
|
|
74
|
+
* App id registered in the Aithos `aithos-auth-apps` table. When set
|
|
75
|
+
* together with {@link returnTo}, the auth backend redirects the
|
|
76
|
+
* browser to {@link returnTo} (post Google + Aithos sign-in) instead
|
|
77
|
+
* of the legacy hard-coded `app.aithos.be/auth/callback`.
|
|
78
|
+
*
|
|
79
|
+
* The pair is required together: the backend rejects half-presence
|
|
80
|
+
* with `sso_app_redirect_pair_required`. Use it for any consumer app
|
|
81
|
+
* other than the canonical `app.aithos.be` (typically your own
|
|
82
|
+
* domain in prod, `http://localhost:<port>/auth/callback` in dev).
|
|
83
|
+
*/
|
|
84
|
+
readonly appId?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Where the auth backend should 302 the browser back to after a
|
|
87
|
+
* successful Google sign-in. MUST be on the app's
|
|
88
|
+
* `allowed_redirect_uris` allowlist (registered with Aithos out of
|
|
89
|
+
* band; see {@link appId}). Exact-match — wildcards rejected.
|
|
90
|
+
*/
|
|
91
|
+
readonly returnTo?: string;
|
|
92
|
+
}
|
|
93
|
+
export interface SignInInput {
|
|
94
|
+
readonly email: string;
|
|
95
|
+
readonly password: string;
|
|
96
|
+
}
|
|
97
|
+
export interface SignUpInput {
|
|
98
|
+
readonly email: string;
|
|
99
|
+
readonly password: string;
|
|
100
|
+
readonly handle: string;
|
|
101
|
+
readonly displayName?: string;
|
|
102
|
+
}
|
|
103
|
+
export interface SignUpResult {
|
|
104
|
+
readonly session: AithosSession;
|
|
105
|
+
readonly recoveryFile: Blob;
|
|
106
|
+
readonly recoveryFilename: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Input to {@link AithosAuth.completeSsoFirstLogin}. The handle is
|
|
110
|
+
* required (the auth backend pre-generated one from the user's email
|
|
111
|
+
* local-part, available on the session payload — we re-confirm it
|
|
112
|
+
* here so the user can edit before commit).
|
|
113
|
+
*/
|
|
114
|
+
export interface CompleteSsoFirstLoginInput {
|
|
115
|
+
readonly handle: string;
|
|
116
|
+
readonly displayName?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Result of {@link AithosAuth.completeSsoFirstLogin}. Returns a recovery
|
|
120
|
+
* file just like signUp — even though the user authenticated via Google,
|
|
121
|
+
* the freshly-generated Ed25519 seeds are the only material that can
|
|
122
|
+
* sign Aithos artifacts; without the recovery file, losing access to
|
|
123
|
+
* the Google account means losing the ethos forever.
|
|
124
|
+
*/
|
|
125
|
+
export interface CompleteSsoFirstLoginResult {
|
|
126
|
+
readonly session: AithosSession;
|
|
127
|
+
readonly recoveryFile: Blob;
|
|
128
|
+
readonly recoveryFilename: string;
|
|
129
|
+
}
|
|
130
|
+
export interface SignInWithRecoveryInput {
|
|
131
|
+
/** Recovery file as a Blob (browser File input) or already-decoded JSON string. */
|
|
132
|
+
readonly file: Blob | string;
|
|
133
|
+
}
|
|
134
|
+
export interface ImportMandateInput {
|
|
135
|
+
/** Delegate bundle as a Blob or already-decoded JSON string. */
|
|
136
|
+
readonly bundle: Blob | string;
|
|
137
|
+
}
|
|
138
|
+
export declare class AithosAuth {
|
|
139
|
+
#private;
|
|
140
|
+
readonly authBaseUrl: string;
|
|
141
|
+
readonly apiBaseUrl: string;
|
|
142
|
+
constructor(config?: AithosAuthConfig);
|
|
143
|
+
/**
|
|
144
|
+
* Reload signing material and JWT session from the configured stores.
|
|
145
|
+
* Must be called once at app boot before relying on
|
|
146
|
+
* {@link getCurrentSession} / {@link getOwnerInfo} / {@link canSignAsOwner}
|
|
147
|
+
* — until then they reflect only what's been done in-memory in the
|
|
148
|
+
* current tab.
|
|
149
|
+
*
|
|
150
|
+
* Strict consistency: if the JWT and the stored owner disagree about
|
|
151
|
+
* who's signed in, both are wiped and the user re-auths. JWT-less
|
|
152
|
+
* owner state (loaded from keyStore but no JWT) is a valid resumed
|
|
153
|
+
* state — the user signed in via recovery or imported a mandate at
|
|
154
|
+
* some earlier moment and never went through the JWT flow.
|
|
155
|
+
*/
|
|
156
|
+
resume(): Promise<void>;
|
|
157
|
+
/** JWT-backed session. Null when signed in via recovery / mandate / not at all. */
|
|
158
|
+
getCurrentSession(): AithosSession | null;
|
|
159
|
+
/** Loaded owner identity. Independent of JWT presence. */
|
|
160
|
+
getOwnerInfo(): OwnerInfo | null;
|
|
161
|
+
getDelegates(): readonly DelegateInfo[];
|
|
162
|
+
canSignAsOwner(): boolean;
|
|
163
|
+
canSignAsDelegateFor(did: string): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Internal accessor used by sibling SDK namespaces (compute, wallet,
|
|
166
|
+
* ethos) when they need to sign on behalf of the owner. Returns null
|
|
167
|
+
* if no owner is loaded.
|
|
168
|
+
*
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
_getOwnerSigners(): OwnerSigners | null;
|
|
172
|
+
/**
|
|
173
|
+
* Internal accessor — looks up an active delegate by mandate id.
|
|
174
|
+
* @internal
|
|
175
|
+
*/
|
|
176
|
+
_getDelegateActor(mandateId: string): DelegateActor | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Internal accessor — finds the first active delegate whose subject
|
|
179
|
+
* matches `did`. Used by `sdk.ethos.of(did)` when the user holds a
|
|
180
|
+
* mandate for that subject.
|
|
181
|
+
* @internal
|
|
182
|
+
*/
|
|
183
|
+
_findDelegateForSubject(did: string): DelegateActor | undefined;
|
|
184
|
+
signIn(input: SignInInput): Promise<AithosSession>;
|
|
185
|
+
signUp(input: SignUpInput): Promise<SignUpResult>;
|
|
186
|
+
/**
|
|
187
|
+
* Sign in by uploading a recovery file. Hydrates the owner signers
|
|
188
|
+
* locally — no JWT is obtained on this path because the recovery
|
|
189
|
+
* file alone doesn't authenticate against the auth backend (no
|
|
190
|
+
* password, no Google session). Apps that need compute/wallet
|
|
191
|
+
* access should follow up with an email+password sign-in or with
|
|
192
|
+
* Google SSO.
|
|
193
|
+
*
|
|
194
|
+
* The recovery file is ALWAYS the file produced by `signUp` (or the
|
|
195
|
+
* equivalent one emitted by `protocol-client`'s `runOnboarding`).
|
|
196
|
+
* Both shapes are accepted.
|
|
197
|
+
*/
|
|
198
|
+
signInWithRecovery(input: SignInWithRecoveryInput): Promise<OwnerInfo>;
|
|
199
|
+
/**
|
|
200
|
+
* Import a delegate bundle (`.aithos-delegate.json`). Works in any
|
|
201
|
+
* state: with no owner loaded (delegate-only session), or alongside
|
|
202
|
+
* an existing owner (the user holds mandates for other people's
|
|
203
|
+
* ethoses while also being an owner themselves).
|
|
204
|
+
*/
|
|
205
|
+
importMandate(input: ImportMandateInput): Promise<DelegateInfo>;
|
|
206
|
+
removeMandate(mandateId: string): Promise<void>;
|
|
207
|
+
signInWithGoogle(opts?: SignInWithGoogleOptions): never;
|
|
208
|
+
/**
|
|
209
|
+
* Public entrypoint — dedupes concurrent calls (React StrictMode).
|
|
210
|
+
* The first call kicks off the actual exchange; subsequent calls
|
|
211
|
+
* before that promise resolves return the SAME promise so they all
|
|
212
|
+
* receive the same `AithosSession | null`. Otherwise StrictMode's
|
|
213
|
+
* second invocation would race against the URL clean done by the
|
|
214
|
+
* first call and resolve to `null`, robbing the AuthCallback page
|
|
215
|
+
* of the session it actually obtained.
|
|
216
|
+
*/
|
|
217
|
+
handleCallback(): Promise<AithosSession | null>;
|
|
218
|
+
exchange(aithosCode: string): Promise<AithosSession>;
|
|
219
|
+
/**
|
|
220
|
+
* Finish the first-time Google SSO bootstrap. After
|
|
221
|
+
* `signInWithGoogle()` + `handleCallback()`, a brand-new SSO user has
|
|
222
|
+
* a session JWT and an `enc_key` released by the auth backend, but
|
|
223
|
+
* NO Aithos identity yet (no Ed25519 seeds, no published did.json,
|
|
224
|
+
* no blob in the auth vault). This method closes that gap:
|
|
225
|
+
*
|
|
226
|
+
* 1. Generates a fresh {@link BrowserIdentity} client-side (4
|
|
227
|
+
* Ed25519 keypairs, derived DID).
|
|
228
|
+
* 2. Calls `aithos.publish_identity` on api.aithos.be so reads
|
|
229
|
+
* and writes against the Aithos primitives have an ethos to
|
|
230
|
+
* anchor to.
|
|
231
|
+
* 3. AES-GCM-encrypts the seeds with the session's `enc_key`,
|
|
232
|
+
* PUTs the result to `/auth/blob`. From now on, every Google
|
|
233
|
+
* sign-in for this user will receive the encrypted blob and
|
|
234
|
+
* hydrate locally.
|
|
235
|
+
* 4. Hydrates `ownerSigners` + `keyStore` so `canSignAsOwner()`
|
|
236
|
+
* flips to true.
|
|
237
|
+
* 5. Returns a recovery-file Blob — the only material that can
|
|
238
|
+
* restore this ethos if Google access is lost.
|
|
239
|
+
*
|
|
240
|
+
* Preconditions:
|
|
241
|
+
* - `getCurrentSession()` returns a non-null session (caller went
|
|
242
|
+
* through `handleCallback()` already).
|
|
243
|
+
* - The session's `blob_version` is 0 (i.e. no blob yet).
|
|
244
|
+
* - The session's `enc_key_b64` is non-empty.
|
|
245
|
+
*
|
|
246
|
+
* Throws `AithosSDKError("auth_sso_no_pending_first_login", …)` if
|
|
247
|
+
* preconditions don't hold (e.g. blob_version > 0 means the user has
|
|
248
|
+
* already completed setup; nothing to do).
|
|
249
|
+
*/
|
|
250
|
+
completeSsoFirstLogin(input: CompleteSsoFirstLoginInput): Promise<CompleteSsoFirstLoginResult>;
|
|
251
|
+
signOut(): Promise<void>;
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=auth.d.ts.map
|