@aithos/sdk 0.1.0-alpha.12 → 0.1.0-alpha.14
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/dist/src/auth-api.d.ts +9 -0
- package/dist/src/auth-api.js +20 -0
- package/dist/src/auth.d.ts +63 -0
- package/dist/src/auth.js +220 -29
- package/dist/src/index.d.ts +1 -1
- package/package.json +1 -1
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;
|
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 {
|
package/dist/src/auth.d.ts
CHANGED
|
@@ -105,6 +105,28 @@ export interface SignUpResult {
|
|
|
105
105
|
readonly recoveryFile: Blob;
|
|
106
106
|
readonly recoveryFilename: string;
|
|
107
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
|
+
}
|
|
108
130
|
export interface SignInWithRecoveryInput {
|
|
109
131
|
/** Recovery file as a Blob (browser File input) or already-decoded JSON string. */
|
|
110
132
|
readonly file: Blob | string;
|
|
@@ -183,8 +205,49 @@ export declare class AithosAuth {
|
|
|
183
205
|
importMandate(input: ImportMandateInput): Promise<DelegateInfo>;
|
|
184
206
|
removeMandate(mandateId: string): Promise<void>;
|
|
185
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
|
+
*/
|
|
186
217
|
handleCallback(): Promise<AithosSession | null>;
|
|
187
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>;
|
|
188
251
|
signOut(): Promise<void>;
|
|
189
252
|
}
|
|
190
253
|
//# sourceMappingURL=auth.d.ts.map
|
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 { loginChallenge, loginVerify, registerAccount, } from "./auth-api.js";
|
|
24
|
+
import { 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";
|
|
@@ -47,6 +47,16 @@ export class AithosAuth {
|
|
|
47
47
|
#ownerSigners = null;
|
|
48
48
|
/** Active delegate registry. */
|
|
49
49
|
#delegates = new DelegateRegistry();
|
|
50
|
+
/**
|
|
51
|
+
* In-flight (or just-resolved) `handleCallback()` result. React
|
|
52
|
+
* StrictMode (dev) double-invokes the mount effect — the URL clean
|
|
53
|
+
* inside the first call makes the second invocation see a clean URL
|
|
54
|
+
* and resolve to `null`, with the session it just consumed locked
|
|
55
|
+
* inside the first promise. Caching the result here lets both
|
|
56
|
+
* invocations resolve to the same value. Cleared on next mount via
|
|
57
|
+
* the wrapper's once-per-instance dedup.
|
|
58
|
+
*/
|
|
59
|
+
#handleCallbackPromise = null;
|
|
50
60
|
constructor(config = {}) {
|
|
51
61
|
this.authBaseUrl = trimSlash(config.authBaseUrl ?? DEFAULT_AUTH_BASE_URL);
|
|
52
62
|
this.apiBaseUrl = trimSlash(config.apiBaseUrl ?? DEFAULT_API_BASE_URL);
|
|
@@ -466,7 +476,41 @@ export class AithosAuth {
|
|
|
466
476
|
this.#win.location.assign(url.toString());
|
|
467
477
|
throw new AithosSDKError("auth_redirecting", "redirecting to google");
|
|
468
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* Public entrypoint — dedupes concurrent calls (React StrictMode).
|
|
481
|
+
* The first call kicks off the actual exchange; subsequent calls
|
|
482
|
+
* before that promise resolves return the SAME promise so they all
|
|
483
|
+
* receive the same `AithosSession | null`. Otherwise StrictMode's
|
|
484
|
+
* second invocation would race against the URL clean done by the
|
|
485
|
+
* first call and resolve to `null`, robbing the AuthCallback page
|
|
486
|
+
* of the session it actually obtained.
|
|
487
|
+
*/
|
|
469
488
|
async handleCallback() {
|
|
489
|
+
if (!this.#win)
|
|
490
|
+
return null;
|
|
491
|
+
if (this.#handleCallbackPromise)
|
|
492
|
+
return this.#handleCallbackPromise;
|
|
493
|
+
const p = this.#doHandleCallback();
|
|
494
|
+
this.#handleCallbackPromise = p;
|
|
495
|
+
// Clear the cache once the promise settles so a subsequent
|
|
496
|
+
// signInWithGoogle round-trip on the same AithosAuth instance can
|
|
497
|
+
// process its own callback. We use `then(cleanup, cleanup)`
|
|
498
|
+
// rather than `finally(...)` because `finally` re-throws — without
|
|
499
|
+
// a downstream `.catch` the resulting promise becomes an
|
|
500
|
+
// unhandledrejection when `p` itself rejects (the caller already
|
|
501
|
+
// surfaces that rejection via the returned `p`). `then(success,
|
|
502
|
+
// error)` converts a rejection into a clean resolution on this
|
|
503
|
+
// side-effect chain so node:test doesn't flag the orphan as a
|
|
504
|
+
// failure.
|
|
505
|
+
const clear = () => {
|
|
506
|
+
if (this.#handleCallbackPromise === p) {
|
|
507
|
+
this.#handleCallbackPromise = null;
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
p.then(clear, clear);
|
|
511
|
+
return p;
|
|
512
|
+
}
|
|
513
|
+
async #doHandleCallback() {
|
|
470
514
|
if (!this.#win)
|
|
471
515
|
return null;
|
|
472
516
|
const here = new URL(this.#win.location.href);
|
|
@@ -504,34 +548,44 @@ export class AithosAuth {
|
|
|
504
548
|
const blobBytes = decryptBlob(encKey, nonce, blob);
|
|
505
549
|
try {
|
|
506
550
|
const plaintext = parseBlob(blobBytes);
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
this.#
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
551
|
+
// Earlier versions of the SDK gated hydration on
|
|
552
|
+
// `plaintext.identity.did === session.did` as a defense
|
|
553
|
+
// against tampered sessionStores. The check breaks SSO
|
|
554
|
+
// flows: the auth backend assigns a placeholder random
|
|
555
|
+
// DID at user-record creation time (no client keypair on
|
|
556
|
+
// hand), but the BLOB is built around a real
|
|
557
|
+
// BrowserIdentity whose DID is derived from its root
|
|
558
|
+
// pubkey. The two intentionally differ — the blob is the
|
|
559
|
+
// truth source for everything downstream (signing, DID
|
|
560
|
+
// resolution against api.aithos.be), the session.did is
|
|
561
|
+
// just auth-side bookkeeping. Drop the check and trust
|
|
562
|
+
// the blob.
|
|
563
|
+
if (this.#ownerSigners)
|
|
564
|
+
this.#ownerSigners.destroy();
|
|
565
|
+
this.#ownerSigners = OwnerSigners.fromBlobPlaintext(plaintext);
|
|
566
|
+
await this.#keyStore.saveOwner({
|
|
567
|
+
version: "0.1.0-hex",
|
|
568
|
+
did: plaintext.identity.did,
|
|
569
|
+
handle: plaintext.identity.handle,
|
|
570
|
+
displayName: plaintext.identity.displayName,
|
|
571
|
+
seedsHex: plaintext.seeds,
|
|
572
|
+
savedAt: new Date().toISOString(),
|
|
573
|
+
});
|
|
574
|
+
await this.#keyStore.clearAllDelegates();
|
|
575
|
+
this.#delegates.destroy();
|
|
576
|
+
for (const d of plaintext.delegates) {
|
|
577
|
+
const stored = storedDelegateFromBlob(d);
|
|
578
|
+
try {
|
|
579
|
+
await this.#keyStore.saveDelegate(stored);
|
|
580
|
+
}
|
|
581
|
+
catch {
|
|
582
|
+
/* keep going */
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
this.#delegates.add(DelegateActor.fromStored(stored));
|
|
586
|
+
}
|
|
587
|
+
catch {
|
|
588
|
+
/* keep going */
|
|
535
589
|
}
|
|
536
590
|
}
|
|
537
591
|
}
|
|
@@ -580,6 +634,143 @@ export class AithosAuth {
|
|
|
580
634
|
return (await res.json());
|
|
581
635
|
}
|
|
582
636
|
/* ------------------------------------------------------------------------ */
|
|
637
|
+
/* Complete SSO first login */
|
|
638
|
+
/* ------------------------------------------------------------------------ */
|
|
639
|
+
/**
|
|
640
|
+
* Finish the first-time Google SSO bootstrap. After
|
|
641
|
+
* `signInWithGoogle()` + `handleCallback()`, a brand-new SSO user has
|
|
642
|
+
* a session JWT and an `enc_key` released by the auth backend, but
|
|
643
|
+
* NO Aithos identity yet (no Ed25519 seeds, no published did.json,
|
|
644
|
+
* no blob in the auth vault). This method closes that gap:
|
|
645
|
+
*
|
|
646
|
+
* 1. Generates a fresh {@link BrowserIdentity} client-side (4
|
|
647
|
+
* Ed25519 keypairs, derived DID).
|
|
648
|
+
* 2. Calls `aithos.publish_identity` on api.aithos.be so reads
|
|
649
|
+
* and writes against the Aithos primitives have an ethos to
|
|
650
|
+
* anchor to.
|
|
651
|
+
* 3. AES-GCM-encrypts the seeds with the session's `enc_key`,
|
|
652
|
+
* PUTs the result to `/auth/blob`. From now on, every Google
|
|
653
|
+
* sign-in for this user will receive the encrypted blob and
|
|
654
|
+
* hydrate locally.
|
|
655
|
+
* 4. Hydrates `ownerSigners` + `keyStore` so `canSignAsOwner()`
|
|
656
|
+
* flips to true.
|
|
657
|
+
* 5. Returns a recovery-file Blob — the only material that can
|
|
658
|
+
* restore this ethos if Google access is lost.
|
|
659
|
+
*
|
|
660
|
+
* Preconditions:
|
|
661
|
+
* - `getCurrentSession()` returns a non-null session (caller went
|
|
662
|
+
* through `handleCallback()` already).
|
|
663
|
+
* - The session's `blob_version` is 0 (i.e. no blob yet).
|
|
664
|
+
* - The session's `enc_key_b64` is non-empty.
|
|
665
|
+
*
|
|
666
|
+
* Throws `AithosSDKError("auth_sso_no_pending_first_login", …)` if
|
|
667
|
+
* preconditions don't hold (e.g. blob_version > 0 means the user has
|
|
668
|
+
* already completed setup; nothing to do).
|
|
669
|
+
*/
|
|
670
|
+
async completeSsoFirstLogin(input) {
|
|
671
|
+
if (!/^[a-z0-9][a-z0-9_-]{0,62}$/i.test(input.handle)) {
|
|
672
|
+
throw new AithosSDKError("auth_invalid_handle", "handle must be 1–63 alphanumeric chars + _ -");
|
|
673
|
+
}
|
|
674
|
+
const displayName = input.displayName ?? input.handle;
|
|
675
|
+
const session = this.#sessionStore.get();
|
|
676
|
+
if (!session) {
|
|
677
|
+
throw new AithosSDKError("auth_sso_no_pending_first_login", "no active session — sign in via Google first");
|
|
678
|
+
}
|
|
679
|
+
if (!session.enc_key_b64) {
|
|
680
|
+
throw new AithosSDKError("auth_sso_no_pending_first_login", "session does not carry an enc_key (not an SSO-flow session?)");
|
|
681
|
+
}
|
|
682
|
+
if (session.blob_version > 0) {
|
|
683
|
+
throw new AithosSDKError("auth_sso_no_pending_first_login", "this session already has a published blob — nothing to bootstrap");
|
|
684
|
+
}
|
|
685
|
+
// 1. Fresh identity client-side. The DID derived here is the
|
|
686
|
+
// truth source from now on — the placeholder DID stamped in
|
|
687
|
+
// the user record by the auth Lambda is left as-is (auth-side
|
|
688
|
+
// bookkeeping; never used for signing).
|
|
689
|
+
const identity = createBrowserIdentity(input.handle, displayName);
|
|
690
|
+
const recoverySerialized = serializeRecoveryFile(identity);
|
|
691
|
+
const recoveryFile = new Blob([recoverySerialized.text], {
|
|
692
|
+
type: "application/json",
|
|
693
|
+
});
|
|
694
|
+
// 2. publish_identity on api.aithos.be — reuses the alpha.6
|
|
695
|
+
// helper. Must succeed before we persist anything locally:
|
|
696
|
+
// a half-completed bootstrap (blob uploaded but identity not
|
|
697
|
+
// published) would leave the user with seeds they can't use.
|
|
698
|
+
await this.#publishIdentity(identity);
|
|
699
|
+
// 3. Encrypt the seeds with the SSO-released enc_key and PUT
|
|
700
|
+
// /auth/blob. The auth Lambda accepts the new blob_version=1
|
|
701
|
+
// and stores the bytes verbatim.
|
|
702
|
+
const encKey = b64ToBytes(session.enc_key_b64);
|
|
703
|
+
let blob;
|
|
704
|
+
let blobNonce;
|
|
705
|
+
let plaintext;
|
|
706
|
+
try {
|
|
707
|
+
plaintext = buildBlobPlaintext({
|
|
708
|
+
identity: {
|
|
709
|
+
did: identity.did,
|
|
710
|
+
handle: identity.handle,
|
|
711
|
+
displayName: identity.displayName,
|
|
712
|
+
},
|
|
713
|
+
seeds: {
|
|
714
|
+
root: identity.root.seed,
|
|
715
|
+
public: identity.public.seed,
|
|
716
|
+
circle: identity.circle.seed,
|
|
717
|
+
self: identity.self.seed,
|
|
718
|
+
},
|
|
719
|
+
delegates: [],
|
|
720
|
+
});
|
|
721
|
+
const blobBytes = serializeBlob(plaintext);
|
|
722
|
+
blobNonce = randomNonce();
|
|
723
|
+
blob = encryptBlob(encKey, blobNonce, blobBytes);
|
|
724
|
+
}
|
|
725
|
+
finally {
|
|
726
|
+
zeroize(encKey);
|
|
727
|
+
}
|
|
728
|
+
const newBlobVersion = 1;
|
|
729
|
+
try {
|
|
730
|
+
await putBlob({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, {
|
|
731
|
+
jwt: session.session,
|
|
732
|
+
blob,
|
|
733
|
+
blobNonce,
|
|
734
|
+
blobVersion: newBlobVersion,
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
catch (e) {
|
|
738
|
+
throw new AithosSDKError("auth_sso_blob_upload_failed", `couldn't store the encrypted vault on auth.aithos.be: ${e.message ?? "unknown"}`);
|
|
739
|
+
}
|
|
740
|
+
// 4. Hydrate in-memory state from the fresh identity.
|
|
741
|
+
if (this.#ownerSigners)
|
|
742
|
+
this.#ownerSigners.destroy();
|
|
743
|
+
this.#ownerSigners = OwnerSigners.fromBrowserIdentity(identity);
|
|
744
|
+
await this.#keyStore.saveOwner({
|
|
745
|
+
version: "0.1.0-hex",
|
|
746
|
+
did: identity.did,
|
|
747
|
+
handle: identity.handle,
|
|
748
|
+
displayName: identity.displayName,
|
|
749
|
+
seedsHex: {
|
|
750
|
+
root: bytesToHex(identity.root.seed),
|
|
751
|
+
public: bytesToHex(identity.public.seed),
|
|
752
|
+
circle: bytesToHex(identity.circle.seed),
|
|
753
|
+
self: bytesToHex(identity.self.seed),
|
|
754
|
+
},
|
|
755
|
+
savedAt: new Date().toISOString(),
|
|
756
|
+
});
|
|
757
|
+
// 5. Persist the updated session — same JWT, but now carrying
|
|
758
|
+
// the freshly-built blob bytes so a subsequent `resume()` can
|
|
759
|
+
// rehydrate without another /auth/blob round-trip.
|
|
760
|
+
const refreshed = {
|
|
761
|
+
...session,
|
|
762
|
+
blob_b64: bytesToB64Public(blob),
|
|
763
|
+
blob_nonce_b64: bytesToB64Public(blobNonce),
|
|
764
|
+
blob_version: newBlobVersion,
|
|
765
|
+
};
|
|
766
|
+
this.#sessionStore.set(refreshed);
|
|
767
|
+
return {
|
|
768
|
+
session: refreshed,
|
|
769
|
+
recoveryFile,
|
|
770
|
+
recoveryFilename: recoverySerialized.filename,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
/* ------------------------------------------------------------------------ */
|
|
583
774
|
/* Sign-out */
|
|
584
775
|
/* ------------------------------------------------------------------------ */
|
|
585
776
|
async signOut() {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { ComputeNamespace } from "./compute.js";
|
|
|
10
10
|
export type { CreditPackId, CreateTopupSessionArgs, CreateTopupSessionResult, GetBalanceArgs, GetBalanceResult, } from "./wallet.js";
|
|
11
11
|
export { WalletNamespace } from "./wallet.js";
|
|
12
12
|
export { AithosAuth, DEFAULT_API_BASE_URL, DEFAULT_AUTH_BASE_URL, } from "./auth.js";
|
|
13
|
-
export type { AithosAuthConfig, AithosSession, DelegateInfo, ImportMandateInput, OwnerInfo, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, } from "./auth.js";
|
|
13
|
+
export type { AithosAuthConfig, AithosSession, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, DelegateInfo, ImportMandateInput, OwnerInfo, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, } from "./auth.js";
|
|
14
14
|
export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, type AithosSessionStore, } from "./session-store.js";
|
|
15
15
|
export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, type AithosKeyStore, type StoredDelegateKeys, type StoredOwnerKeys, } from "./key-store.js";
|
|
16
16
|
export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aithos/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.14",
|
|
4
4
|
"description": "Aithos SDK — 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",
|