@aithos/sdk 0.1.0-alpha.4 → 0.1.0-alpha.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +211 -7
  2. package/dist/src/apps.d.ts +155 -0
  3. package/dist/src/apps.js +288 -0
  4. package/dist/src/assets.d.ts +207 -0
  5. package/dist/src/assets.js +533 -0
  6. package/dist/src/auth-api.d.ts +138 -0
  7. package/dist/src/auth-api.js +168 -0
  8. package/dist/src/auth.d.ts +536 -119
  9. package/dist/src/auth.js +1207 -152
  10. package/dist/src/compute.d.ts +251 -9
  11. package/dist/src/compute.js +293 -16
  12. package/dist/src/data-schema-contacts-v1.d.ts +14 -0
  13. package/dist/src/data-schema-contacts-v1.js +28 -0
  14. package/dist/src/data.d.ts +153 -0
  15. package/dist/src/data.js +670 -0
  16. package/dist/src/endpoints.d.ts +9 -0
  17. package/dist/src/endpoints.js +5 -0
  18. package/dist/src/ethos.d.ts +202 -1
  19. package/dist/src/ethos.js +821 -16
  20. package/dist/src/index.d.ts +18 -6
  21. package/dist/src/index.js +39 -6
  22. package/dist/src/internal/delegate-bundle.d.ts +18 -0
  23. package/dist/src/internal/delegate-bundle.js +94 -0
  24. package/dist/src/internal/delegate-state.d.ts +45 -0
  25. package/dist/src/internal/delegate-state.js +120 -0
  26. package/dist/src/internal/envelope.d.ts +77 -0
  27. package/dist/src/internal/envelope.js +154 -0
  28. package/dist/src/internal/owner-signers.d.ts +78 -0
  29. package/dist/src/internal/owner-signers.js +179 -0
  30. package/dist/src/internal/protocol-client-bridge.d.ts +8 -0
  31. package/dist/src/internal/protocol-client-bridge.js +20 -0
  32. package/dist/src/internal/recovery-file.d.ts +29 -0
  33. package/dist/src/internal/recovery-file.js +98 -0
  34. package/dist/src/internal/signer.d.ts +59 -0
  35. package/dist/src/internal/signer.js +86 -0
  36. package/dist/src/key-store.d.ts +128 -0
  37. package/dist/src/key-store.js +244 -0
  38. package/dist/src/mandates.d.ts +163 -1
  39. package/dist/src/mandates.js +286 -8
  40. package/dist/src/react/AithosAsset.d.ts +66 -0
  41. package/dist/src/react/AithosAsset.js +67 -0
  42. package/dist/src/react/context.d.ts +29 -0
  43. package/dist/src/react/context.js +31 -0
  44. package/dist/src/react/index.d.ts +28 -0
  45. package/dist/src/react/index.js +30 -0
  46. package/dist/src/react/use-aithos-asset.d.ts +39 -0
  47. package/dist/src/react/use-aithos-asset.js +118 -0
  48. package/dist/src/sdk.d.ts +46 -3
  49. package/dist/src/sdk.js +49 -23
  50. package/dist/src/wallet.d.ts +4 -6
  51. package/dist/src/wallet.js +18 -8
  52. package/dist/src/web.d.ts +279 -0
  53. package/dist/src/web.js +186 -0
  54. package/dist/test/auth-j3.test.d.ts +2 -0
  55. package/dist/test/auth-j3.test.js +391 -0
  56. package/dist/test/compute-delegate-path.test.d.ts +2 -0
  57. package/dist/test/compute-delegate-path.test.js +183 -0
  58. package/dist/test/compute.test.js +26 -11
  59. package/dist/test/endpoints.test.js +20 -1
  60. package/dist/test/envelope.test.d.ts +2 -0
  61. package/dist/test/envelope.test.js +318 -0
  62. package/dist/test/ethos-first-edition.test.d.ts +2 -0
  63. package/dist/test/ethos-first-edition.test.js +248 -0
  64. package/dist/test/ethos.test.d.ts +2 -0
  65. package/dist/test/ethos.test.js +219 -0
  66. package/dist/test/key-store.test.d.ts +2 -0
  67. package/dist/test/key-store.test.js +161 -0
  68. package/dist/test/mandates-compute.test.d.ts +2 -0
  69. package/dist/test/mandates-compute.test.js +256 -0
  70. package/dist/test/mandates.test.d.ts +2 -0
  71. package/dist/test/mandates.test.js +93 -0
  72. package/dist/test/sdk.test.js +70 -30
  73. package/dist/test/signer.test.d.ts +2 -0
  74. package/dist/test/signer.test.js +117 -0
  75. package/dist/test/signup-bootstrap.test.d.ts +2 -0
  76. package/dist/test/signup-bootstrap.test.js +311 -0
  77. package/dist/test/wallet.test.js +20 -9
  78. package/dist/test/web.test.d.ts +2 -0
  79. package/dist/test/web.test.js +270 -0
  80. package/package.json +18 -3
@@ -1,18 +1,30 @@
1
- export declare const VERSION = "0.1.0-alpha.4";
1
+ export declare const VERSION = "0.1.0-alpha.41";
2
2
  export { AithosSDK } from "./sdk.js";
3
3
  export type { AithosSDKConfig } from "./types.js";
4
4
  export { AithosSDKError } from "./types.js";
5
+ export { AithosRpcError } from "@aithos/protocol-client";
5
6
  export type { AithosSdkEndpoints } from "./endpoints.js";
6
7
  export { DEFAULT_SDK_ENDPOINTS } from "./endpoints.js";
7
- export type { ComputeMessage, InvokeBedrockArgs, InvokeBedrockResult, StopReason, } from "./compute.js";
8
+ export type { ComputeMessage, ImageAspectRatio, ImageModelId, InvokeBedrockArgs, InvokeBedrockResult, InvokeBedrockVisionArgs, InvokeBedrockVisionResult, InvokeImageArgs, InvokeImageImage, InvokeImageResult, InvokeSegmentationArgs, InvokeSegmentationResult, SegmentPolygon, StopReason, } from "./compute.js";
8
9
  export { ComputeNamespace } from "./compute.js";
9
10
  export type { CreditPackId, CreateTopupSessionArgs, CreateTopupSessionResult, GetBalanceArgs, GetBalanceResult, } from "./wallet.js";
10
11
  export { WalletNamespace } from "./wallet.js";
11
- export { AithosAuth, DEFAULT_AUTH_BASE_URL } from "./auth.js";
12
- export type { AithosAuthConfig, AithosSession, SignInInput, SignInWithGoogleOptions, SignUpInput, SignUpResult, } from "./auth.js";
12
+ export type { ComponentStyle, ExtractArgs, ExtractContent, ExtractData, ExtractForm, ExtractFormField, ExtractHeading, ExtractIconDeclaration, ExtractImage, ExtractLink, ExtractLogo, ExtractMeta, ExtractResult, ExtractSection, ExtractStructure, ExtractStyles, FetchAssetArgs, FetchAssetResult, PaletteEntry, VisualSignature, WebNamespaceDeps, } from "./web.js";
13
+ export { WebNamespace, WEB_EXTRACT_SCOPE } from "./web.js";
14
+ export { AithosAuth, DEFAULT_API_BASE_URL, DEFAULT_AUTH_BASE_URL, } from "./auth.js";
15
+ export type { AithosAuthConfig, AithosSession, ApplyPasswordResetInput, ApplyPasswordResetResult, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, CustodialSignInInput, CustodialSignInResult, CustodialSignUpInput, CustodialSignUpResult, DelegateInfo, ImportMandateInput, OwnerInfo, RequestPasswordResetInput, ResendVerificationInput, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, VerifyEmailInput, VerifyEmailResult, } from "./auth.js";
16
+ export type { SignedEnvelope } from "./internal/envelope.js";
13
17
  export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, type AithosSessionStore, } from "./session-store.js";
14
- export * as ethos from "./ethos.js";
18
+ export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, type AithosKeyStore, type StoredDelegateKeys, type StoredOwnerKeys, } from "./key-store.js";
19
+ export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
20
+ export type { AddSectionInput, PublishResult, StagedChange, UpdateSectionPatch, ZoneName, } from "./ethos.js";
21
+ export { COMPUTE_INVOKE_SCOPE, MandatesNamespace } from "./mandates.js";
22
+ export type { ActorSphere, CreateMandateComputeInput, CreateMandateInput, MintedMandate, OwnedMandate, Scope, } from "./mandates.js";
23
+ export { AppsNamespace } from "./apps.js";
24
+ export type { AudienceSet, AppCreditPackId, CreateAppTopupSessionArgs, CreateAppTopupSessionResult, CreateSponsorshipMandateArgs, SignedSponsorshipMandate, SignedSponsorshipRevocation, SponsorshipAccountingAuthorityInput, SponsorshipAudienceInput, SponsorshipBudgetInput, } from "./apps.js";
15
25
  export * as onboarding from "./onboarding.js";
16
- export * as mandates from "./mandates.js";
17
26
  export { createBrowserIdentity, browserIdentityFromStored, type BrowserIdentity, } from "@aithos/protocol-client";
27
+ export type { Section } from "@aithos/protocol-client";
28
+ export { createDataClient, type CreateDataClientArgs, type DataClient, type DataCollection, type ListOpts, type AithosSchemaLite, } from "./data.js";
29
+ export { createAssetsClient, AssetsClient, type CreateAssetsClientArgs, type AttachedContext, type AssetUploadInput, type AssetUploadResult, type AssetFetchResult, type AssetBrief, type ListAssetsOpts, type ThumbnailUploadInput, type ThumbnailUploadResult, type RecipientResolver, type RecipientSet, } from "./assets.js";
18
30
  //# sourceMappingURL=index.d.ts.map
package/dist/src/index.js CHANGED
@@ -17,28 +17,61 @@
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.4";
20
+ export const VERSION = "0.1.0-alpha.41";
21
21
  export { AithosSDK } from "./sdk.js";
22
22
  export { AithosSDKError } from "./types.js";
23
+ // Re-export protocol-client's JSON-RPC error type so consumers can
24
+ // `instanceof`-check server-side errors and inspect the JSON-RPC code
25
+ // without taking a direct dependency on @aithos/protocol-client.
26
+ export { AithosRpcError } from "@aithos/protocol-client";
23
27
  export { DEFAULT_SDK_ENDPOINTS } from "./endpoints.js";
24
28
  export { ComputeNamespace } from "./compute.js";
25
29
  export { WalletNamespace } from "./wallet.js";
30
+ export { WebNamespace, WEB_EXTRACT_SCOPE } from "./web.js";
26
31
  // Sign-up, sign-in, sign-in-with-Google. Lives outside the AithosSDK
27
32
  // class because the auth flow runs *before* the user has a
28
33
  // BrowserIdentity (sign-up creates one, sign-in restores it from the
29
34
  // server). The class also owns the session store — see
30
35
  // ./session-store.ts for pluggable persistence.
31
- export { AithosAuth, DEFAULT_AUTH_BASE_URL } from "./auth.js";
36
+ export { AithosAuth, DEFAULT_API_BASE_URL, DEFAULT_AUTH_BASE_URL, } from "./auth.js";
32
37
  // Session storage backends used by AithosAuth. `sessionStorageStore` is
33
38
  // the default in browser environments ; pass another store at construction
34
39
  // time if you need different persistence.
35
40
  export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, } from "./session-store.js";
36
- // Re-exports under stable namespace modules. Apps may also import these
37
- // directly via `@aithos/protocol-client`; the SDK simply curates them.
38
- export * as ethos from "./ethos.js";
41
+ // Key persistence (owner identity material + delegate bundles). Pluggable
42
+ // like {@link AithosSessionStore}: `indexedDbKeyStore` is the browser
43
+ // default, `memoryKeyStore` is a no-persist fallback used in tests / SSR.
44
+ // Stored shapes ({@link StoredOwnerKeys}, {@link StoredDelegateKeys}) are
45
+ // opaque from the consumer's point of view — round-trip them, don't peek
46
+ // inside.
47
+ export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, } from "./key-store.js";
48
+ // `sdk.ethos` namespace — high-level ethos editing (load, mutate
49
+ // staged, publish lazy). The class is constructed once by the
50
+ // AithosSDK constructor; `sdk.ethos.me()` / `sdk.ethos.of(did)` are
51
+ // the entry points.
52
+ export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
53
+ // `sdk.mandates` namespace — owner-side mandate lifecycle.
54
+ export { COMPUTE_INVOKE_SCOPE, MandatesNamespace } from "./mandates.js";
55
+ // `sdk.apps` namespace — sponsorship mandates + app-credit top-ups
56
+ // (draft §13, V0.1). Pre-pay a pool that funds your users' compute
57
+ // calls within explicit caps. Per-user caps + per-day caps + lifetime
58
+ // pool cap enforced server-side. Fallback to user wallet when caps
59
+ // are reached or pool is empty.
60
+ export { AppsNamespace } from "./apps.js";
61
+ // Onboarding re-exports kept for advanced callers — the curated API
62
+ // for first-run flows is `auth.signUp` (already shipped in J3).
39
63
  export * as onboarding from "./onboarding.js";
40
- export * as mandates from "./mandates.js";
41
64
  // Convenience direct re-exports of the most-used identity primitives so the
42
65
  // quick-start example doesn't need a namespace import.
43
66
  export { createBrowserIdentity, browserIdentityFromStored, } from "@aithos/protocol-client";
67
+ // `sdk.data` namespace — Aithos data sub-protocol PDS client. Manages
68
+ // the lifecycle of subject-owned, encrypted, schema-validated records.
69
+ // See spec/data/ in the aithos-protocol repo.
70
+ export { createDataClient, } from "./data.js";
71
+ // `sdk.assets` — Aithos assets sub-protocol PDS client. Upload,
72
+ // fetch, list, ref/unref binary content (images, PDFs, audio, video)
73
+ // owned by a subject. AEAD-encrypted per-asset under AMKs wrapped for
74
+ // the subject's X25519 sphere keys (and, in v0.2, mandate grantees).
75
+ // See spec/assets/ in the aithos-protocol repo.
76
+ export { createAssetsClient, AssetsClient, } from "./assets.js";
44
77
  //# sourceMappingURL=index.js.map
@@ -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,94 @@
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
+ // The mandate subject's DID is carried by `issuer` in the wire format
54
+ // emitted by `mintDelegateBundle()` (cf. SignedMandate.issuer in
55
+ // protocol-client). We accept the legacy `subject_did` / camelCase
56
+ // variants too so older test fixtures and any externally-minted
57
+ // bundles using the older shape keep working.
58
+ const subjectDid = m["issuer"] ?? m["subject_did"] ?? m["subjectDid"];
59
+ const grantee = m["grantee"];
60
+ if (typeof mandateId !== "string" || !mandateId) {
61
+ throw bad("mandate.id missing");
62
+ }
63
+ if (typeof subjectDid !== "string" || !subjectDid.startsWith("did:")) {
64
+ throw bad("mandate.issuer missing or malformed (expected a `did:` URL)");
65
+ }
66
+ if (typeof grantee !== "object" || grantee === null) {
67
+ throw bad("mandate.grantee missing");
68
+ }
69
+ const g = grantee;
70
+ const granteeId = g["id"];
71
+ const pubkey = g["pubkey"];
72
+ if (typeof granteeId !== "string" || !granteeId) {
73
+ throw bad("mandate.grantee.id missing");
74
+ }
75
+ if (typeof pubkey !== "string" || !pubkey.startsWith("z")) {
76
+ throw bad("mandate.grantee.pubkey missing or not multibase");
77
+ }
78
+ const seed = o["delegate_seed_hex"];
79
+ if (typeof seed !== "string" || !HEX_64.test(seed)) {
80
+ throw bad("delegate_seed_hex: expected 64-char lowercase hex");
81
+ }
82
+ return {
83
+ mandate: mandate,
84
+ mandateId,
85
+ subjectDid,
86
+ granteeId,
87
+ granteePubkeyMultibase: pubkey,
88
+ delegateSeedHex: seed,
89
+ };
90
+ }
91
+ function bad(detail) {
92
+ return new AithosSDKError("auth_invalid_delegate_bundle", `delegate bundle is invalid: ${detail}`);
93
+ }
94
+ //# 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,77 @@
1
+ /**
2
+ * Minimal signing surface required to produce an envelope's
3
+ * `proof.proofValue`. Intentionally narrower than {@link Signer} so
4
+ * callers that don't want to construct a full `RawSeedSigner` can pass
5
+ * a one-shot inline adapter. Every {@link Signer} satisfies this
6
+ * interface structurally.
7
+ */
8
+ export interface EnvelopeSigner {
9
+ sign(message: Uint8Array): Promise<Uint8Array>;
10
+ }
11
+ /**
12
+ * The wire-format envelope per spec §11.2. Apps that POST this to a
13
+ * backend serialize the whole object as JSON (alongside the rest of
14
+ * `params`) under `params._envelope`.
15
+ */
16
+ export interface SignedEnvelope {
17
+ readonly "aithos-envelope": "0.1.0";
18
+ readonly iss: string;
19
+ readonly aud: string;
20
+ readonly method: string;
21
+ readonly iat: number;
22
+ readonly exp: number;
23
+ readonly nonce: string;
24
+ readonly params_hash: string;
25
+ readonly proof: {
26
+ readonly type: "Ed25519Signature2020";
27
+ readonly verificationMethod: string;
28
+ readonly created: string;
29
+ readonly proofValue: string;
30
+ };
31
+ }
32
+ export interface SignOwnerEnvelopeArgs {
33
+ /** Subject DID — issuer of the envelope (`iss` field). */
34
+ readonly iss: string;
35
+ /**
36
+ * Absolute URL of the target endpoint (scheme + host + path, no query,
37
+ * no fragment). The server verifier rejects envelopes where `aud`
38
+ * does not match the actual endpoint being called.
39
+ */
40
+ readonly aud: string;
41
+ /** Fully-qualified JSON-RPC method name. */
42
+ readonly method: string;
43
+ /** Tool payload — what `params_hash` commits to. */
44
+ readonly params: unknown;
45
+ /**
46
+ * Anything that can produce an Ed25519 signature over a byte
47
+ * sequence. In practice: one of the four owner sphere signers
48
+ * loaded post sign-in, or an inline adapter wrapping a raw seed.
49
+ */
50
+ readonly signer: EnvelopeSigner;
51
+ /**
52
+ * Verification method URL — typically `${did}#${sphere}`. The server
53
+ * resolves this against the issuer's DID document to find the
54
+ * matching public key.
55
+ */
56
+ readonly verificationMethod: string;
57
+ /** Envelope lifetime in seconds. Default 60. Server caps at 300. */
58
+ readonly ttlSeconds?: number;
59
+ /** Clock override for deterministic tests. Defaults to `new Date()`. */
60
+ readonly now?: Date;
61
+ /** Nonce override for deterministic tests. Defaults to a fresh ULID. */
62
+ readonly nonce?: string;
63
+ }
64
+ /**
65
+ * Build, canonicalize and sign an owner-path envelope per spec §11.2.
66
+ *
67
+ * The unsigned envelope is JCS-canonicalized (RFC 8785 subset), the
68
+ * bytes signed with Ed25519, and the resulting signature attached as
69
+ * `proof.proofValue` (base64url).
70
+ *
71
+ * Async return type — even though `Signer.sign` may resolve
72
+ * synchronously today (via `RawSeedSigner`), the interface is shaped
73
+ * async so that future implementations backed by `crypto.subtle.sign`
74
+ * (non-extractable keys) drop in without breaking callers.
75
+ */
76
+ export declare function signOwnerEnvelope(args: SignOwnerEnvelopeArgs): Promise<SignedEnvelope>;
77
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1,154 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Mathieu Colla
3
+ /**
4
+ * Aithos signed-envelope helper — SDK-internal.
5
+ *
6
+ * Implements the `aithos-envelope` v0.1.0 wire format from spec §11.2.
7
+ * Used by SDK namespaces (sdk.data, sdk.ethos, sdk.mandates, ...) to
8
+ * sign their writes to api.aithos.be, AND by the public method
9
+ * {@link AithosAuth.signEnvelope} so apps can sign envelopes for
10
+ * arbitrary third-party Aithos-aware backends with the same primitive.
11
+ *
12
+ * NOT exported from the package barrel. The corresponding `SignedEnvelope`
13
+ * type IS re-exported from `src/index.ts` for consumer typing.
14
+ *
15
+ * Reference algorithm: `@aithos/protocol-core/envelope.ts:signEnvelope`.
16
+ * This file duplicates a self-contained subset of the helpers (JCS,
17
+ * SHA-256, base64url, ULID, CSPRNG) to keep the SDK's signing path
18
+ * decoupled from internal changes elsewhere in the SDK. The duplication
19
+ * with `src/data.ts` is intentional and tracked; consolidation into a
20
+ * shared `src/internal/canonical.ts` is planned for a follow-up release.
21
+ */
22
+ import { sha256 } from "@noble/hashes/sha2.js";
23
+ /**
24
+ * Build, canonicalize and sign an owner-path envelope per spec §11.2.
25
+ *
26
+ * The unsigned envelope is JCS-canonicalized (RFC 8785 subset), the
27
+ * bytes signed with Ed25519, and the resulting signature attached as
28
+ * `proof.proofValue` (base64url).
29
+ *
30
+ * Async return type — even though `Signer.sign` may resolve
31
+ * synchronously today (via `RawSeedSigner`), the interface is shaped
32
+ * async so that future implementations backed by `crypto.subtle.sign`
33
+ * (non-extractable keys) drop in without breaking callers.
34
+ */
35
+ export async function signOwnerEnvelope(args) {
36
+ const nowMs = (args.now ?? new Date()).getTime();
37
+ const iat = Math.floor(nowMs / 1000);
38
+ const exp = iat + (args.ttlSeconds ?? 60);
39
+ const nonce = args.nonce ?? makeUlid();
40
+ const paramsHash = "sha256-" + sha256Hex(jcsCanonicalize(args.params));
41
+ const unsigned = {
42
+ "aithos-envelope": "0.1.0",
43
+ iss: args.iss,
44
+ aud: args.aud,
45
+ method: args.method,
46
+ iat,
47
+ exp,
48
+ nonce,
49
+ params_hash: paramsHash,
50
+ proof: {
51
+ type: "Ed25519Signature2020",
52
+ verificationMethod: args.verificationMethod,
53
+ created: new Date(iat * 1000).toISOString(),
54
+ proofValue: "",
55
+ },
56
+ };
57
+ const bytes = new TextEncoder().encode(jcsCanonicalize(unsigned));
58
+ const sig = await args.signer.sign(bytes);
59
+ return {
60
+ ...unsigned,
61
+ proof: { ...unsigned.proof, proofValue: base64url(sig) },
62
+ };
63
+ }
64
+ /* -------------------------------------------------------------------------- */
65
+ /* Self-contained helpers (duplicated with src/data.ts for isolation) */
66
+ /* -------------------------------------------------------------------------- */
67
+ /** Cross-platform CSPRNG: Web Crypto in browser, Node WebCrypto in Node 19+. */
68
+ function cryptoRandom(n) {
69
+ const buf = new Uint8Array(n);
70
+ globalThis.crypto?.getRandomValues(buf);
71
+ return buf;
72
+ }
73
+ function makeUlid() {
74
+ // Lightweight ULID — millisecond timestamp + 80 bits of randomness.
75
+ // Crockford base32. For tests this is sufficient; production uses
76
+ // the canonical ulid package.
77
+ const tsBuf = new Uint8Array(6);
78
+ let ts = Date.now();
79
+ for (let i = 5; i >= 0; i--) {
80
+ tsBuf[i] = ts & 0xff;
81
+ ts = Math.floor(ts / 256);
82
+ }
83
+ const rndBuf = cryptoRandom(10);
84
+ const all = new Uint8Array(16);
85
+ all.set(tsBuf, 0);
86
+ all.set(rndBuf, 6);
87
+ const alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
88
+ let bits = 0;
89
+ let value = 0;
90
+ let out = "";
91
+ for (const b of all) {
92
+ value = (value << 8) | b;
93
+ bits += 8;
94
+ while (bits >= 5) {
95
+ out += alphabet[(value >> (bits - 5)) & 0x1f];
96
+ bits -= 5;
97
+ }
98
+ }
99
+ if (bits > 0)
100
+ out += alphabet[(value << (5 - bits)) & 0x1f];
101
+ return out.slice(0, 26);
102
+ }
103
+ /** Standard base64 (with `=` padding). Browser + Node compatible. */
104
+ function base64Std(bytes) {
105
+ let bin = "";
106
+ for (let i = 0; i < bytes.length; i++)
107
+ bin += String.fromCharCode(bytes[i]);
108
+ return btoa(bin);
109
+ }
110
+ /** base64url (URL-safe, no padding). */
111
+ function base64url(bytes) {
112
+ return base64Std(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
113
+ }
114
+ function sha256Hex(s) {
115
+ const d = sha256(new TextEncoder().encode(s));
116
+ let hex = "";
117
+ for (const b of d)
118
+ hex += b.toString(16).padStart(2, "0");
119
+ return hex;
120
+ }
121
+ /**
122
+ * JCS-style canonicalization (RFC 8785 subset).
123
+ *
124
+ * Sorted object keys, no whitespace, finite numbers via `toString()`,
125
+ * strings via `JSON.stringify` (escapes), arrays preserve order.
126
+ * `undefined` is rejected (RFC 8785 §3.2.2).
127
+ */
128
+ function jcsCanonicalize(value) {
129
+ if (value === null)
130
+ return "null";
131
+ if (value === undefined)
132
+ throw new Error("Cannot canonicalize undefined");
133
+ if (typeof value === "boolean")
134
+ return value ? "true" : "false";
135
+ if (typeof value === "number") {
136
+ if (!Number.isFinite(value))
137
+ throw new Error("non-finite number");
138
+ return value.toString();
139
+ }
140
+ if (typeof value === "string")
141
+ return JSON.stringify(value);
142
+ if (Array.isArray(value)) {
143
+ return "[" + value.map(jcsCanonicalize).join(",") + "]";
144
+ }
145
+ if (typeof value === "object") {
146
+ const obj = value;
147
+ const keys = Object.keys(obj).sort();
148
+ return ("{" +
149
+ keys.map((k) => JSON.stringify(k) + ":" + jcsCanonicalize(obj[k])).join(",") +
150
+ "}");
151
+ }
152
+ throw new Error(`Cannot canonicalize ${typeof value}`);
153
+ }
154
+ //# sourceMappingURL=envelope.js.map