@aithos/sdk 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +41 -0
- package/dist/src/auth-api.js +82 -0
- package/dist/src/auth.d.ts +114 -75
- package/dist/src/auth.js +553 -73
- package/dist/src/compute.d.ts +8 -6
- package/dist/src/compute.js +19 -11
- package/dist/src/ethos.d.ts +117 -1
- package/dist/src/ethos.js +417 -16
- package/dist/src/index.d.ts +8 -4
- package/dist/src/index.js +26 -8
- package/dist/src/internal/delegate-bundle.d.ts +18 -0
- package/dist/src/internal/delegate-bundle.js +89 -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 +88 -1
- package/dist/src/mandates.js +185 -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 +360 -0
- package/dist/test/compute.test.js +22 -11
- 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.test.d.ts +2 -0
- package/dist/test/mandates.test.js +93 -0
- package/dist/test/sdk.test.js +64 -30
- package/dist/test/signer.test.d.ts +2 -0
- package/dist/test/signer.test.js +117 -0
- package/dist/test/wallet.test.js +20 -9
- package/package.json +4 -3
package/dist/src/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.0-alpha.
|
|
1
|
+
export declare const VERSION = "0.1.0-alpha.5";
|
|
2
2
|
export { AithosSDK } from "./sdk.js";
|
|
3
3
|
export type { AithosSDKConfig } from "./types.js";
|
|
4
4
|
export { AithosSDKError } from "./types.js";
|
|
@@ -9,9 +9,13 @@ export { ComputeNamespace } from "./compute.js";
|
|
|
9
9
|
export type { CreditPackId, CreateTopupSessionArgs, CreateTopupSessionResult, GetBalanceArgs, GetBalanceResult, } from "./wallet.js";
|
|
10
10
|
export { WalletNamespace } from "./wallet.js";
|
|
11
11
|
export { AithosAuth, DEFAULT_AUTH_BASE_URL } from "./auth.js";
|
|
12
|
-
export type { AithosAuthConfig, AithosSession, SignInWithGoogleOptions, } from "./auth.js";
|
|
13
|
-
export
|
|
12
|
+
export type { AithosAuthConfig, AithosSession, DelegateInfo, ImportMandateInput, OwnerInfo, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, } from "./auth.js";
|
|
13
|
+
export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, type AithosSessionStore, } from "./session-store.js";
|
|
14
|
+
export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, type AithosKeyStore, type StoredDelegateKeys, type StoredOwnerKeys, } from "./key-store.js";
|
|
15
|
+
export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
|
|
16
|
+
export type { AddSectionInput, PublishResult, StagedChange, UpdateSectionPatch, ZoneName, } from "./ethos.js";
|
|
17
|
+
export { MandatesNamespace } from "./mandates.js";
|
|
18
|
+
export type { ActorSphere, CreateMandateInput, MintedMandate, OwnedMandate, Scope, } from "./mandates.js";
|
|
14
19
|
export * as onboarding from "./onboarding.js";
|
|
15
|
-
export * as mandates from "./mandates.js";
|
|
16
20
|
export { createBrowserIdentity, browserIdentityFromStored, type BrowserIdentity, } from "@aithos/protocol-client";
|
|
17
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.js
CHANGED
|
@@ -17,21 +17,39 @@
|
|
|
17
17
|
// Public types specific to the SDK (`AithosSDKConfig`, `AithosSDKError`)
|
|
18
18
|
// are exported from here. Endpoint config (`AithosSdkEndpoints`,
|
|
19
19
|
// `DEFAULT_SDK_ENDPOINTS`) likewise.
|
|
20
|
-
export const VERSION = "0.1.0-alpha.
|
|
20
|
+
export const VERSION = "0.1.0-alpha.5";
|
|
21
21
|
export { AithosSDK } from "./sdk.js";
|
|
22
22
|
export { AithosSDKError } from "./types.js";
|
|
23
23
|
export { DEFAULT_SDK_ENDPOINTS } from "./endpoints.js";
|
|
24
24
|
export { ComputeNamespace } from "./compute.js";
|
|
25
25
|
export { WalletNamespace } from "./wallet.js";
|
|
26
|
-
// Sign in with
|
|
27
|
-
//
|
|
28
|
-
// BrowserIdentity
|
|
26
|
+
// Sign-up, sign-in, sign-in-with-Google. Lives outside the AithosSDK
|
|
27
|
+
// class because the auth flow runs *before* the user has a
|
|
28
|
+
// BrowserIdentity (sign-up creates one, sign-in restores it from the
|
|
29
|
+
// server). The class also owns the session store — see
|
|
30
|
+
// ./session-store.ts for pluggable persistence.
|
|
29
31
|
export { AithosAuth, DEFAULT_AUTH_BASE_URL } from "./auth.js";
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
32
|
+
// Session storage backends used by AithosAuth. `sessionStorageStore` is
|
|
33
|
+
// the default in browser environments ; pass another store at construction
|
|
34
|
+
// time if you need different persistence.
|
|
35
|
+
export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, } from "./session-store.js";
|
|
36
|
+
// Key persistence (owner identity material + delegate bundles). Pluggable
|
|
37
|
+
// like {@link AithosSessionStore}: `indexedDbKeyStore` is the browser
|
|
38
|
+
// default, `memoryKeyStore` is a no-persist fallback used in tests / SSR.
|
|
39
|
+
// Stored shapes ({@link StoredOwnerKeys}, {@link StoredDelegateKeys}) are
|
|
40
|
+
// opaque from the consumer's point of view — round-trip them, don't peek
|
|
41
|
+
// inside.
|
|
42
|
+
export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, } from "./key-store.js";
|
|
43
|
+
// `sdk.ethos` namespace — high-level ethos editing (load, mutate
|
|
44
|
+
// staged, publish lazy). The class is constructed once by the
|
|
45
|
+
// AithosSDK constructor; `sdk.ethos.me()` / `sdk.ethos.of(did)` are
|
|
46
|
+
// the entry points.
|
|
47
|
+
export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
|
|
48
|
+
// `sdk.mandates` namespace — owner-side mandate lifecycle.
|
|
49
|
+
export { MandatesNamespace } from "./mandates.js";
|
|
50
|
+
// Onboarding re-exports kept for advanced callers — the curated API
|
|
51
|
+
// for first-run flows is `auth.signUp` (already shipped in J3).
|
|
33
52
|
export * as onboarding from "./onboarding.js";
|
|
34
|
-
export * as mandates from "./mandates.js";
|
|
35
53
|
// Convenience direct re-exports of the most-used identity primitives so the
|
|
36
54
|
// quick-start example doesn't need a namespace import.
|
|
37
55
|
export { createBrowserIdentity, browserIdentityFromStored, } from "@aithos/protocol-client";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ParsedDelegateBundle {
|
|
2
|
+
readonly mandate: Record<string, unknown>;
|
|
3
|
+
readonly mandateId: string;
|
|
4
|
+
readonly subjectDid: string;
|
|
5
|
+
readonly granteeId: string;
|
|
6
|
+
readonly granteePubkeyMultibase: string;
|
|
7
|
+
readonly delegateSeedHex: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Read the bundle (Blob or already-decoded string) into UTF-8 text.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readDelegateBundleText(file: Blob | string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a delegate-bundle JSON string. Throws {@link AithosSDKError}
|
|
15
|
+
* with `code === "auth_invalid_delegate_bundle"` if malformed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseDelegateBundle(text: string): ParsedDelegateBundle;
|
|
18
|
+
//# sourceMappingURL=delegate-bundle.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
// Delegate-bundle format — parser for `.aithos-delegate.json` files
|
|
4
|
+
// shipped by `mandate-mint`. The file is the only material a delegate
|
|
5
|
+
// receives from an owner: the full SignedMandate + a fresh Ed25519
|
|
6
|
+
// seed bound to that mandate via `mandate.grantee.pubkey`.
|
|
7
|
+
//
|
|
8
|
+
// Wire shape:
|
|
9
|
+
//
|
|
10
|
+
// {
|
|
11
|
+
// aithos_delegate_version: "0.1.0",
|
|
12
|
+
// mandate: { id, scopes, grantee: { id, pubkey }, ... },
|
|
13
|
+
// delegate_seed_hex: "<64 lowercase hex chars>"
|
|
14
|
+
// }
|
|
15
|
+
//
|
|
16
|
+
// Anything else is rejected with `auth_invalid_delegate_bundle`.
|
|
17
|
+
import { AithosSDKError } from "../types.js";
|
|
18
|
+
const HEX_64 = /^[0-9a-f]{64}$/;
|
|
19
|
+
/**
|
|
20
|
+
* Read the bundle (Blob or already-decoded string) into UTF-8 text.
|
|
21
|
+
*/
|
|
22
|
+
export async function readDelegateBundleText(file) {
|
|
23
|
+
if (typeof file === "string")
|
|
24
|
+
return file;
|
|
25
|
+
return file.text();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse a delegate-bundle JSON string. Throws {@link AithosSDKError}
|
|
29
|
+
* with `code === "auth_invalid_delegate_bundle"` if malformed.
|
|
30
|
+
*/
|
|
31
|
+
export function parseDelegateBundle(text) {
|
|
32
|
+
let obj;
|
|
33
|
+
try {
|
|
34
|
+
obj = JSON.parse(text);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw bad("not valid JSON");
|
|
38
|
+
}
|
|
39
|
+
if (typeof obj !== "object" || obj === null) {
|
|
40
|
+
throw bad("not a JSON object");
|
|
41
|
+
}
|
|
42
|
+
const o = obj;
|
|
43
|
+
const ver = o["aithos_delegate_version"];
|
|
44
|
+
if (typeof ver !== "string" || !ver.startsWith("0.1.0")) {
|
|
45
|
+
throw bad(`unsupported aithos_delegate_version: ${String(ver)}`);
|
|
46
|
+
}
|
|
47
|
+
const mandate = o["mandate"];
|
|
48
|
+
if (typeof mandate !== "object" || mandate === null) {
|
|
49
|
+
throw bad("missing mandate");
|
|
50
|
+
}
|
|
51
|
+
const m = mandate;
|
|
52
|
+
const mandateId = m["id"];
|
|
53
|
+
const subjectDid = m["subject_did"] ?? m["subjectDid"];
|
|
54
|
+
const grantee = m["grantee"];
|
|
55
|
+
if (typeof mandateId !== "string" || !mandateId) {
|
|
56
|
+
throw bad("mandate.id missing");
|
|
57
|
+
}
|
|
58
|
+
if (typeof subjectDid !== "string" || !subjectDid.startsWith("did:")) {
|
|
59
|
+
throw bad("mandate.subject_did missing or malformed");
|
|
60
|
+
}
|
|
61
|
+
if (typeof grantee !== "object" || grantee === null) {
|
|
62
|
+
throw bad("mandate.grantee missing");
|
|
63
|
+
}
|
|
64
|
+
const g = grantee;
|
|
65
|
+
const granteeId = g["id"];
|
|
66
|
+
const pubkey = g["pubkey"];
|
|
67
|
+
if (typeof granteeId !== "string" || !granteeId) {
|
|
68
|
+
throw bad("mandate.grantee.id missing");
|
|
69
|
+
}
|
|
70
|
+
if (typeof pubkey !== "string" || !pubkey.startsWith("z")) {
|
|
71
|
+
throw bad("mandate.grantee.pubkey missing or not multibase");
|
|
72
|
+
}
|
|
73
|
+
const seed = o["delegate_seed_hex"];
|
|
74
|
+
if (typeof seed !== "string" || !HEX_64.test(seed)) {
|
|
75
|
+
throw bad("delegate_seed_hex: expected 64-char lowercase hex");
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
mandate: mandate,
|
|
79
|
+
mandateId,
|
|
80
|
+
subjectDid,
|
|
81
|
+
granteeId,
|
|
82
|
+
granteePubkeyMultibase: pubkey,
|
|
83
|
+
delegateSeedHex: seed,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function bad(detail) {
|
|
87
|
+
return new AithosSDKError("auth_invalid_delegate_bundle", `delegate bundle is invalid: ${detail}`);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=delegate-bundle.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StoredDelegateKeys } from "../key-store.js";
|
|
2
|
+
import { type Signer } from "./signer.js";
|
|
3
|
+
/**
|
|
4
|
+
* One active delegate session. Lives in {@link DelegateRegistry}'s
|
|
5
|
+
* map keyed by `mandateId`.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DelegateActor {
|
|
8
|
+
#private;
|
|
9
|
+
readonly subjectDid: string;
|
|
10
|
+
readonly mandateId: string;
|
|
11
|
+
readonly granteeId: string;
|
|
12
|
+
readonly granteePubkeyMultibase: string;
|
|
13
|
+
/** Full §4.2 SignedMandate, opaque JSON object. */
|
|
14
|
+
readonly mandate: Record<string, unknown>;
|
|
15
|
+
readonly signer: Signer;
|
|
16
|
+
constructor(args: {
|
|
17
|
+
subjectDid: string;
|
|
18
|
+
mandateId: string;
|
|
19
|
+
granteeId: string;
|
|
20
|
+
granteePubkeyMultibase: string;
|
|
21
|
+
mandate: Record<string, unknown>;
|
|
22
|
+
signer: Signer;
|
|
23
|
+
});
|
|
24
|
+
/** Build from the persisted KeyStore shape. */
|
|
25
|
+
static fromStored(stored: StoredDelegateKeys): DelegateActor;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
get destroyed(): boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Map of active delegate sessions, keyed by `mandateId`. Provides
|
|
31
|
+
* lookup helpers used by the auth namespace and (later) by `sdk.ethos`.
|
|
32
|
+
*/
|
|
33
|
+
export declare class DelegateRegistry {
|
|
34
|
+
#private;
|
|
35
|
+
add(actor: DelegateActor): void;
|
|
36
|
+
remove(mandateId: string): void;
|
|
37
|
+
get(mandateId: string): DelegateActor | undefined;
|
|
38
|
+
/** Find any active actor whose subject matches `did`. */
|
|
39
|
+
findForSubject(did: string): DelegateActor | undefined;
|
|
40
|
+
list(): readonly DelegateActor[];
|
|
41
|
+
size(): number;
|
|
42
|
+
/** Zeroize every actor's signer and clear the registry. */
|
|
43
|
+
destroy(): void;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=delegate-state.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
// In-memory delegate registry — the runtime sibling of
|
|
4
|
+
// {@link AithosKeyStore}'s delegate slot.
|
|
5
|
+
//
|
|
6
|
+
// A delegate session is a mandate + a single Ed25519 seed bound to
|
|
7
|
+
// that mandate via `mandate.grantee.pubkey`. The SDK keeps these
|
|
8
|
+
// active sessions hot in memory so signing operations don't need
|
|
9
|
+
// IndexedDB on every call.
|
|
10
|
+
//
|
|
11
|
+
// {@link DelegateActor} bundles the in-memory signer with the public
|
|
12
|
+
// metadata needed to drive an envelope (subject DID, grantee URN,
|
|
13
|
+
// grantee pubkey multibase, mandate id). The full mandate JSON is
|
|
14
|
+
// kept too because envelope signing for delegate writes must attach
|
|
15
|
+
// the §4.2 mandate.
|
|
16
|
+
import { getPublicKey } from "@noble/ed25519";
|
|
17
|
+
import { RawSeedSigner } from "./signer.js";
|
|
18
|
+
/**
|
|
19
|
+
* One active delegate session. Lives in {@link DelegateRegistry}'s
|
|
20
|
+
* map keyed by `mandateId`.
|
|
21
|
+
*/
|
|
22
|
+
export class DelegateActor {
|
|
23
|
+
subjectDid;
|
|
24
|
+
mandateId;
|
|
25
|
+
granteeId;
|
|
26
|
+
granteePubkeyMultibase;
|
|
27
|
+
/** Full §4.2 SignedMandate, opaque JSON object. */
|
|
28
|
+
mandate;
|
|
29
|
+
signer;
|
|
30
|
+
#destroyed = false;
|
|
31
|
+
constructor(args) {
|
|
32
|
+
this.subjectDid = args.subjectDid;
|
|
33
|
+
this.mandateId = args.mandateId;
|
|
34
|
+
this.granteeId = args.granteeId;
|
|
35
|
+
this.granteePubkeyMultibase = args.granteePubkeyMultibase;
|
|
36
|
+
this.mandate = args.mandate;
|
|
37
|
+
this.signer = args.signer;
|
|
38
|
+
}
|
|
39
|
+
/** Build from the persisted KeyStore shape. */
|
|
40
|
+
static fromStored(stored) {
|
|
41
|
+
const seed = hexToBytes(stored.delegateSeedHex);
|
|
42
|
+
try {
|
|
43
|
+
const pubkey = getPublicKey(seed);
|
|
44
|
+
const signer = new RawSeedSigner(seed, pubkey);
|
|
45
|
+
return new DelegateActor({
|
|
46
|
+
subjectDid: stored.subjectDid,
|
|
47
|
+
mandateId: stored.mandateId,
|
|
48
|
+
granteeId: stored.granteeId,
|
|
49
|
+
granteePubkeyMultibase: stored.granteePubkeyMultibase,
|
|
50
|
+
mandate: stored.mandate,
|
|
51
|
+
signer,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
seed.fill(0);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
destroy() {
|
|
59
|
+
if (this.#destroyed)
|
|
60
|
+
return;
|
|
61
|
+
this.signer.destroy();
|
|
62
|
+
this.#destroyed = true;
|
|
63
|
+
}
|
|
64
|
+
get destroyed() {
|
|
65
|
+
return this.#destroyed;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Map of active delegate sessions, keyed by `mandateId`. Provides
|
|
70
|
+
* lookup helpers used by the auth namespace and (later) by `sdk.ethos`.
|
|
71
|
+
*/
|
|
72
|
+
export class DelegateRegistry {
|
|
73
|
+
#actors = new Map();
|
|
74
|
+
add(actor) {
|
|
75
|
+
// Replace any existing entry for the same mandate (re-import).
|
|
76
|
+
const existing = this.#actors.get(actor.mandateId);
|
|
77
|
+
if (existing)
|
|
78
|
+
existing.destroy();
|
|
79
|
+
this.#actors.set(actor.mandateId, actor);
|
|
80
|
+
}
|
|
81
|
+
remove(mandateId) {
|
|
82
|
+
const a = this.#actors.get(mandateId);
|
|
83
|
+
if (a)
|
|
84
|
+
a.destroy();
|
|
85
|
+
this.#actors.delete(mandateId);
|
|
86
|
+
}
|
|
87
|
+
get(mandateId) {
|
|
88
|
+
return this.#actors.get(mandateId);
|
|
89
|
+
}
|
|
90
|
+
/** Find any active actor whose subject matches `did`. */
|
|
91
|
+
findForSubject(did) {
|
|
92
|
+
for (const a of this.#actors.values()) {
|
|
93
|
+
if (a.subjectDid === did)
|
|
94
|
+
return a;
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
list() {
|
|
99
|
+
return [...this.#actors.values()];
|
|
100
|
+
}
|
|
101
|
+
size() {
|
|
102
|
+
return this.#actors.size;
|
|
103
|
+
}
|
|
104
|
+
/** Zeroize every actor's signer and clear the registry. */
|
|
105
|
+
destroy() {
|
|
106
|
+
for (const a of this.#actors.values())
|
|
107
|
+
a.destroy();
|
|
108
|
+
this.#actors.clear();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function hexToBytes(hex) {
|
|
112
|
+
if (hex.length % 2 !== 0)
|
|
113
|
+
throw new Error("hex must be even-length");
|
|
114
|
+
const out = new Uint8Array(hex.length / 2);
|
|
115
|
+
for (let i = 0; i < out.length; i++) {
|
|
116
|
+
out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=delegate-state.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type BlobPlaintext, type BrowserIdentity, type StoredIdentity } from "@aithos/protocol-client";
|
|
2
|
+
import type { StoredOwnerKeys } from "../key-store.js";
|
|
3
|
+
import { type Signer } from "./signer.js";
|
|
4
|
+
/**
|
|
5
|
+
* The four signing capabilities of an authenticated owner.
|
|
6
|
+
*
|
|
7
|
+
* The `did`, `handle`, `displayName` fields are public metadata.
|
|
8
|
+
* The four signers expose only `publicKey` + `sign` — never the
|
|
9
|
+
* underlying seed bytes.
|
|
10
|
+
*/
|
|
11
|
+
export declare class OwnerSigners {
|
|
12
|
+
#private;
|
|
13
|
+
readonly did: string;
|
|
14
|
+
readonly handle: string;
|
|
15
|
+
readonly displayName: string;
|
|
16
|
+
readonly root: Signer;
|
|
17
|
+
readonly public: Signer;
|
|
18
|
+
readonly circle: Signer;
|
|
19
|
+
readonly self: Signer;
|
|
20
|
+
constructor(args: {
|
|
21
|
+
did: string;
|
|
22
|
+
handle: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
root: Signer;
|
|
25
|
+
public: Signer;
|
|
26
|
+
circle: Signer;
|
|
27
|
+
self: Signer;
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Build from a {@link BrowserIdentity}. The seeds inside `identity`
|
|
31
|
+
* are defensively copied into fresh signers — mutating the
|
|
32
|
+
* BrowserIdentity afterwards does not affect the signers, and the
|
|
33
|
+
* caller may zeroize the original identity immediately.
|
|
34
|
+
*/
|
|
35
|
+
static fromBrowserIdentity(identity: BrowserIdentity): OwnerSigners;
|
|
36
|
+
/**
|
|
37
|
+
* Build from a {@link StoredIdentity} — the persisted shape used by
|
|
38
|
+
* extension-kit's IndexedDbKeystore (hex-encoded seeds).
|
|
39
|
+
*
|
|
40
|
+
* Internally calls `browserIdentityFromStored` to derive
|
|
41
|
+
* `publicKey`s, then wraps. The caller may discard the StoredIdentity
|
|
42
|
+
* afterwards.
|
|
43
|
+
*/
|
|
44
|
+
static fromStoredIdentity(stored: StoredIdentity): OwnerSigners;
|
|
45
|
+
/**
|
|
46
|
+
* Build from the SDK's own {@link StoredOwnerKeys} shape — what the
|
|
47
|
+
* KeyStore round-trips for owner-side resume.
|
|
48
|
+
*/
|
|
49
|
+
static fromStoredOwnerKeys(stored: StoredOwnerKeys): OwnerSigners;
|
|
50
|
+
/**
|
|
51
|
+
* Build from a {@link BlobPlaintext} — the parsed payload of the
|
|
52
|
+
* password-decrypted vault blob returned by `loginVerify`. Hex
|
|
53
|
+
* seeds are turned into KeyPairs eagerly; the plaintext input is
|
|
54
|
+
* not retained.
|
|
55
|
+
*/
|
|
56
|
+
static fromBlobPlaintext(plaintext: BlobPlaintext): OwnerSigners;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a sphere name to its signer. Convenience for callers that
|
|
59
|
+
* have the sphere as a string ("public" | "circle" | "self") rather
|
|
60
|
+
* than a typed accessor.
|
|
61
|
+
*/
|
|
62
|
+
signerForSphere(sphere: "root" | "public" | "circle" | "self"): Signer;
|
|
63
|
+
/**
|
|
64
|
+
* Internal — project to a {@link StoredIdentity} for protocol-client
|
|
65
|
+
* interop. Reads seed bytes via {@link RawSeedSigner._unsafeKeyPair}
|
|
66
|
+
* on each signer and hex-encodes them. Throws if any signer is not
|
|
67
|
+
* a RawSeedSigner (which can happen post-migration to SubtleSigner;
|
|
68
|
+
* at that point protocol-client must accept Signer-shaped objects
|
|
69
|
+
* directly and this method goes away).
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
_unsafeStoredIdentity(): StoredIdentity;
|
|
74
|
+
/** Zeroize all four private seeds. Idempotent. */
|
|
75
|
+
destroy(): void;
|
|
76
|
+
get destroyed(): boolean;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=owner-signers.d.ts.map
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
// OwnerSigners — the four-keypair signing capability of an Aithos
|
|
4
|
+
// owner identity, behind the {@link Signer} interface.
|
|
5
|
+
//
|
|
6
|
+
// SDK-internal only — NOT exported from the package barrel.
|
|
7
|
+
//
|
|
8
|
+
// An owner identity has four key roles: `root` (controls the DID
|
|
9
|
+
// document), `public` (signs writes / envelopes for the public zone),
|
|
10
|
+
// `circle` (signs writes for the friends zone), `self` (signs writes
|
|
11
|
+
// for the private zone). All four are Ed25519. The X25519 keys used
|
|
12
|
+
// for HPKE zone encryption are deterministically derived from the
|
|
13
|
+
// Ed25519 seeds at use-site (see protocol-client/crypto/kex), so we
|
|
14
|
+
// only need to hold the Ed25519 signers here.
|
|
15
|
+
//
|
|
16
|
+
// This class is the in-memory home for those signers throughout an
|
|
17
|
+
// authenticated session. The auth namespace owns a single instance,
|
|
18
|
+
// hands references to the compute / wallet / ethos namespaces, and
|
|
19
|
+
// destroys it on `signOut`.
|
|
20
|
+
import { browserIdentityFromStored, } from "@aithos/protocol-client";
|
|
21
|
+
import { RawSeedSigner } from "./signer.js";
|
|
22
|
+
/**
|
|
23
|
+
* The four signing capabilities of an authenticated owner.
|
|
24
|
+
*
|
|
25
|
+
* The `did`, `handle`, `displayName` fields are public metadata.
|
|
26
|
+
* The four signers expose only `publicKey` + `sign` — never the
|
|
27
|
+
* underlying seed bytes.
|
|
28
|
+
*/
|
|
29
|
+
export class OwnerSigners {
|
|
30
|
+
did;
|
|
31
|
+
handle;
|
|
32
|
+
displayName;
|
|
33
|
+
root;
|
|
34
|
+
public;
|
|
35
|
+
circle;
|
|
36
|
+
self;
|
|
37
|
+
#destroyed = false;
|
|
38
|
+
constructor(args) {
|
|
39
|
+
this.did = args.did;
|
|
40
|
+
this.handle = args.handle;
|
|
41
|
+
this.displayName = args.displayName;
|
|
42
|
+
this.root = args.root;
|
|
43
|
+
this.public = args.public;
|
|
44
|
+
this.circle = args.circle;
|
|
45
|
+
this.self = args.self;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build from a {@link BrowserIdentity}. The seeds inside `identity`
|
|
49
|
+
* are defensively copied into fresh signers — mutating the
|
|
50
|
+
* BrowserIdentity afterwards does not affect the signers, and the
|
|
51
|
+
* caller may zeroize the original identity immediately.
|
|
52
|
+
*/
|
|
53
|
+
static fromBrowserIdentity(identity) {
|
|
54
|
+
return new OwnerSigners({
|
|
55
|
+
did: identity.did,
|
|
56
|
+
handle: identity.handle,
|
|
57
|
+
displayName: identity.displayName,
|
|
58
|
+
root: new RawSeedSigner(identity.root.seed, identity.root.publicKey),
|
|
59
|
+
public: new RawSeedSigner(identity.public.seed, identity.public.publicKey),
|
|
60
|
+
circle: new RawSeedSigner(identity.circle.seed, identity.circle.publicKey),
|
|
61
|
+
self: new RawSeedSigner(identity.self.seed, identity.self.publicKey),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build from a {@link StoredIdentity} — the persisted shape used by
|
|
66
|
+
* extension-kit's IndexedDbKeystore (hex-encoded seeds).
|
|
67
|
+
*
|
|
68
|
+
* Internally calls `browserIdentityFromStored` to derive
|
|
69
|
+
* `publicKey`s, then wraps. The caller may discard the StoredIdentity
|
|
70
|
+
* afterwards.
|
|
71
|
+
*/
|
|
72
|
+
static fromStoredIdentity(stored) {
|
|
73
|
+
return OwnerSigners.fromBrowserIdentity(browserIdentityFromStored(stored));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build from the SDK's own {@link StoredOwnerKeys} shape — what the
|
|
77
|
+
* KeyStore round-trips for owner-side resume.
|
|
78
|
+
*/
|
|
79
|
+
static fromStoredOwnerKeys(stored) {
|
|
80
|
+
return OwnerSigners.fromStoredIdentity({
|
|
81
|
+
version: "0.1.0",
|
|
82
|
+
handle: stored.handle,
|
|
83
|
+
displayName: stored.displayName,
|
|
84
|
+
did: stored.did,
|
|
85
|
+
seeds: stored.seedsHex,
|
|
86
|
+
savedAt: stored.savedAt,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build from a {@link BlobPlaintext} — the parsed payload of the
|
|
91
|
+
* password-decrypted vault blob returned by `loginVerify`. Hex
|
|
92
|
+
* seeds are turned into KeyPairs eagerly; the plaintext input is
|
|
93
|
+
* not retained.
|
|
94
|
+
*/
|
|
95
|
+
static fromBlobPlaintext(plaintext) {
|
|
96
|
+
return OwnerSigners.fromStoredIdentity({
|
|
97
|
+
version: "0.1.0",
|
|
98
|
+
handle: plaintext.identity.handle,
|
|
99
|
+
displayName: plaintext.identity.displayName,
|
|
100
|
+
did: plaintext.identity.did,
|
|
101
|
+
seeds: plaintext.seeds,
|
|
102
|
+
savedAt: new Date().toISOString(),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Resolve a sphere name to its signer. Convenience for callers that
|
|
107
|
+
* have the sphere as a string ("public" | "circle" | "self") rather
|
|
108
|
+
* than a typed accessor.
|
|
109
|
+
*/
|
|
110
|
+
signerForSphere(sphere) {
|
|
111
|
+
if (this.#destroyed) {
|
|
112
|
+
throw new Error("OwnerSigners: cannot use destroyed signers");
|
|
113
|
+
}
|
|
114
|
+
switch (sphere) {
|
|
115
|
+
case "root":
|
|
116
|
+
return this.root;
|
|
117
|
+
case "public":
|
|
118
|
+
return this.public;
|
|
119
|
+
case "circle":
|
|
120
|
+
return this.circle;
|
|
121
|
+
case "self":
|
|
122
|
+
return this.self;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Internal — project to a {@link StoredIdentity} for protocol-client
|
|
127
|
+
* interop. Reads seed bytes via {@link RawSeedSigner._unsafeKeyPair}
|
|
128
|
+
* on each signer and hex-encodes them. Throws if any signer is not
|
|
129
|
+
* a RawSeedSigner (which can happen post-migration to SubtleSigner;
|
|
130
|
+
* at that point protocol-client must accept Signer-shaped objects
|
|
131
|
+
* directly and this method goes away).
|
|
132
|
+
*
|
|
133
|
+
* @internal
|
|
134
|
+
*/
|
|
135
|
+
_unsafeStoredIdentity() {
|
|
136
|
+
if (this.#destroyed) {
|
|
137
|
+
throw new Error("OwnerSigners: cannot project destroyed signers");
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
version: "0.1.0",
|
|
141
|
+
handle: this.handle,
|
|
142
|
+
displayName: this.displayName,
|
|
143
|
+
did: this.did,
|
|
144
|
+
seeds: {
|
|
145
|
+
root: bytesToHexLocal(asRawSeed(this.root, "root")._unsafeKeyPair().seed),
|
|
146
|
+
public: bytesToHexLocal(asRawSeed(this.public, "public")._unsafeKeyPair().seed),
|
|
147
|
+
circle: bytesToHexLocal(asRawSeed(this.circle, "circle")._unsafeKeyPair().seed),
|
|
148
|
+
self: bytesToHexLocal(asRawSeed(this.self, "self")._unsafeKeyPair().seed),
|
|
149
|
+
},
|
|
150
|
+
savedAt: new Date().toISOString(),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Zeroize all four private seeds. Idempotent. */
|
|
154
|
+
destroy() {
|
|
155
|
+
if (this.#destroyed)
|
|
156
|
+
return;
|
|
157
|
+
this.root.destroy();
|
|
158
|
+
this.public.destroy();
|
|
159
|
+
this.circle.destroy();
|
|
160
|
+
this.self.destroy();
|
|
161
|
+
this.#destroyed = true;
|
|
162
|
+
}
|
|
163
|
+
get destroyed() {
|
|
164
|
+
return this.#destroyed;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function asRawSeed(s, role) {
|
|
168
|
+
if (!(s instanceof RawSeedSigner)) {
|
|
169
|
+
throw new Error(`OwnerSigners._unsafeStoredIdentity: signer for "${role}" is not a RawSeedSigner; this method is incompatible with non-extractable key implementations.`);
|
|
170
|
+
}
|
|
171
|
+
return s;
|
|
172
|
+
}
|
|
173
|
+
function bytesToHexLocal(b) {
|
|
174
|
+
let out = "";
|
|
175
|
+
for (let i = 0; i < b.length; i++)
|
|
176
|
+
out += b[i].toString(16).padStart(2, "0");
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=owner-signers.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { KeyPair } from "@aithos/protocol-client";
|
|
2
|
+
import type { DelegateActor } from "./delegate-state.js";
|
|
3
|
+
import type { OwnerSigners } from "./owner-signers.js";
|
|
4
|
+
/** Extract the raw KeyPair for one of the owner's spheres. */
|
|
5
|
+
export declare function ownerKeyPair(owner: OwnerSigners, sphere: "root" | "public" | "circle" | "self"): KeyPair;
|
|
6
|
+
/** Extract the raw KeyPair held by a delegate actor. */
|
|
7
|
+
export declare function delegateKeyPair(actor: DelegateActor): KeyPair;
|
|
8
|
+
//# sourceMappingURL=protocol-client-bridge.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
import { AithosSDKError } from "../types.js";
|
|
4
|
+
import { RawSeedSigner } from "./signer.js";
|
|
5
|
+
/** Extract the raw KeyPair for one of the owner's spheres. */
|
|
6
|
+
export function ownerKeyPair(owner, sphere) {
|
|
7
|
+
const signer = owner.signerForSphere(sphere);
|
|
8
|
+
return rawKeyPair(signer, `owner.${sphere}`);
|
|
9
|
+
}
|
|
10
|
+
/** Extract the raw KeyPair held by a delegate actor. */
|
|
11
|
+
export function delegateKeyPair(actor) {
|
|
12
|
+
return rawKeyPair(actor.signer, `delegate(${actor.mandateId})`);
|
|
13
|
+
}
|
|
14
|
+
function rawKeyPair(signer, role) {
|
|
15
|
+
if (!(signer instanceof RawSeedSigner)) {
|
|
16
|
+
throw new AithosSDKError("sdk_unsupported_signer", `${role}: signer is not RawSeedSigner — protocol-client interop requires raw seed access until upstream gains a Signer-shaped API`);
|
|
17
|
+
}
|
|
18
|
+
return signer._unsafeKeyPair();
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=protocol-client-bridge.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { BrowserIdentity } from "@aithos/protocol-client";
|
|
2
|
+
export interface ParsedRecoveryFile {
|
|
3
|
+
readonly handle: string;
|
|
4
|
+
readonly displayName: string;
|
|
5
|
+
readonly did: string;
|
|
6
|
+
readonly seedsHex: {
|
|
7
|
+
readonly root: string;
|
|
8
|
+
readonly public: string;
|
|
9
|
+
readonly circle: string;
|
|
10
|
+
readonly self: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a recovery JSON string. Throws {@link AithosSDKError} with
|
|
15
|
+
* `code === "auth_invalid_recovery_file"` if the input is malformed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseRecoveryFile(text: string): ParsedRecoveryFile;
|
|
18
|
+
/** Read the file (Blob or already-decoded string) into UTF-8 text. */
|
|
19
|
+
export declare function readRecoveryFileText(file: Blob | string): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Build the recovery-file JSON blob from a fresh BrowserIdentity. Used
|
|
22
|
+
* by `signUp` so the same writer/reader code handles both ends of the
|
|
23
|
+
* round-trip.
|
|
24
|
+
*/
|
|
25
|
+
export declare function serializeRecoveryFile(identity: BrowserIdentity): {
|
|
26
|
+
readonly text: string;
|
|
27
|
+
readonly filename: string;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=recovery-file.d.ts.map
|