@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
@@ -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
@@ -0,0 +1,98 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Mathieu Colla
3
+ import { AithosSDKError } from "../types.js";
4
+ const HEX_64 = /^[0-9a-f]{64}$/;
5
+ /**
6
+ * Parse a recovery JSON string. Throws {@link AithosSDKError} with
7
+ * `code === "auth_invalid_recovery_file"` if the input is malformed.
8
+ */
9
+ export function parseRecoveryFile(text) {
10
+ let obj;
11
+ try {
12
+ obj = JSON.parse(text);
13
+ }
14
+ catch {
15
+ throw bad("not valid JSON");
16
+ }
17
+ if (typeof obj !== "object" || obj === null) {
18
+ throw bad("not a JSON object");
19
+ }
20
+ const o = obj;
21
+ const ver = o["aithos_recovery_version"];
22
+ if (typeof ver !== "string" || !ver.startsWith("0.1.0")) {
23
+ throw bad(`unsupported aithos_recovery_version: ${String(ver)}`);
24
+ }
25
+ // Both shapes use snake_case for `display_name` and `seeds_hex`.
26
+ const handle = o["handle"];
27
+ const displayName = o["display_name"];
28
+ const did = o["did"];
29
+ const seedsRaw = o["seeds_hex"];
30
+ if (typeof handle !== "string" || !handle)
31
+ throw bad("missing handle");
32
+ if (typeof displayName !== "string")
33
+ throw bad("missing display_name");
34
+ if (typeof did !== "string" || !did.startsWith("did:")) {
35
+ throw bad("missing or malformed did");
36
+ }
37
+ if (typeof seedsRaw !== "object" || seedsRaw === null) {
38
+ throw bad("missing seeds_hex");
39
+ }
40
+ const seeds = seedsRaw;
41
+ for (const k of ["root", "public", "circle", "self"]) {
42
+ const v = seeds[k];
43
+ if (typeof v !== "string" || !HEX_64.test(v)) {
44
+ throw bad(`seeds_hex.${k}: expected 64-char lowercase hex`);
45
+ }
46
+ }
47
+ return {
48
+ handle,
49
+ displayName,
50
+ did,
51
+ seedsHex: {
52
+ root: seeds["root"],
53
+ public: seeds["public"],
54
+ circle: seeds["circle"],
55
+ self: seeds["self"],
56
+ },
57
+ };
58
+ }
59
+ /** Read the file (Blob or already-decoded string) into UTF-8 text. */
60
+ export async function readRecoveryFileText(file) {
61
+ if (typeof file === "string")
62
+ return file;
63
+ return file.text();
64
+ }
65
+ /**
66
+ * Build the recovery-file JSON blob from a fresh BrowserIdentity. Used
67
+ * by `signUp` so the same writer/reader code handles both ends of the
68
+ * round-trip.
69
+ */
70
+ export function serializeRecoveryFile(identity) {
71
+ const payload = {
72
+ aithos_recovery_version: "0.1.0-plaintext",
73
+ handle: identity.handle,
74
+ display_name: identity.displayName,
75
+ did: identity.did,
76
+ seeds_hex: {
77
+ root: bytesToHex(identity.root.seed),
78
+ public: bytesToHex(identity.public.seed),
79
+ circle: bytesToHex(identity.circle.seed),
80
+ self: bytesToHex(identity.self.seed),
81
+ },
82
+ saved_at: new Date().toISOString(),
83
+ };
84
+ return {
85
+ text: JSON.stringify(payload, null, 2),
86
+ filename: `aithos-recovery-${identity.handle}.json`,
87
+ };
88
+ }
89
+ function bad(detail) {
90
+ return new AithosSDKError("auth_invalid_recovery_file", `recovery file is invalid: ${detail}`);
91
+ }
92
+ function bytesToHex(b) {
93
+ let out = "";
94
+ for (let i = 0; i < b.length; i++)
95
+ out += b[i].toString(16).padStart(2, "0");
96
+ return out;
97
+ }
98
+ //# sourceMappingURL=recovery-file.js.map
@@ -0,0 +1,59 @@
1
+ import { type KeyPair } from "@aithos/protocol-client";
2
+ /**
3
+ * Capability to produce Ed25519 signatures over a fixed key. The key
4
+ * material itself is not exposed — only the public key (which is, by
5
+ * definition, public) and the {@link sign} method.
6
+ *
7
+ * `sign` returns a Promise<Uint8Array> even when the underlying
8
+ * implementation is synchronous (e.g. {@link RawSeedSigner}) so future
9
+ * implementations backed by `crypto.subtle.sign` can drop in without
10
+ * breaking callers.
11
+ */
12
+ export interface Signer {
13
+ /** 32-byte Ed25519 public key. */
14
+ readonly publicKey: Uint8Array;
15
+ /** Sign `message` and return the 64-byte Ed25519 signature. */
16
+ sign(message: Uint8Array): Promise<Uint8Array>;
17
+ /** Zeroize any private material the signer holds. Idempotent. */
18
+ destroy(): void;
19
+ }
20
+ /**
21
+ * Today's implementation: wraps a raw 32-byte Ed25519 seed and signs
22
+ * via `@noble/ed25519`. Holds the seed in a defensively-copied
23
+ * Uint8Array bound to a private field, so mutating the constructor
24
+ * input afterwards does not affect the signer.
25
+ *
26
+ * Migration note: when we move to Web Crypto non-extractable keys,
27
+ * this class is replaced by a `SubtleSigner` that holds a `CryptoKey`
28
+ * reference and calls `crypto.subtle.sign("Ed25519", key, message)`.
29
+ * The {@link Signer} interface stays the same, so all callers (the
30
+ * SessionVault, the auth namespace, the ethos publish path) keep
31
+ * working unchanged.
32
+ */
33
+ export declare class RawSeedSigner implements Signer {
34
+ #private;
35
+ readonly publicKey: Uint8Array;
36
+ /**
37
+ * @param seed 32-byte Ed25519 seed (the private half).
38
+ * @param publicKey 32-byte Ed25519 public key matching `seed`.
39
+ * Both arrays are defensively copied — the caller may zeroize their
40
+ * originals immediately.
41
+ */
42
+ constructor(seed: Uint8Array, publicKey: Uint8Array);
43
+ sign(message: Uint8Array): Promise<Uint8Array>;
44
+ destroy(): void;
45
+ /**
46
+ * Internal escape hatch for protocol-client interop. Returns a KeyPair
47
+ * usable with `buildSignedEnvelope({ signer })` and friends, which
48
+ * today take a raw seed. Marked `_unsafe` because it surfaces the
49
+ * private seed bytes — only callers within `@aithos/sdk` should use
50
+ * it, and never propagate the result outside the SDK boundary.
51
+ *
52
+ * When protocol-client gains a Signer-shaped API (post-alpha), this
53
+ * method goes away and SubtleSigner becomes pluggable upstream.
54
+ *
55
+ * @internal
56
+ */
57
+ _unsafeKeyPair(): KeyPair;
58
+ }
59
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1,86 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Mathieu Colla
3
+ // Internal Signer abstraction.
4
+ //
5
+ // SDK-internal only — NOT exported from the package barrel. The whole
6
+ // point of this file is to draw the line between "what the SDK consumer
7
+ // sees" (no seeds, no key bytes, just verbs like `addSection` and
8
+ // `publish`) and "how the SDK signs internally" (today: raw Ed25519
9
+ // seeds via @noble; tomorrow: non-extractable CryptoKeys via
10
+ // crypto.subtle).
11
+ //
12
+ // The {@link Signer} interface is the contract. {@link RawSeedSigner}
13
+ // is today's implementation. When we migrate to Web Crypto
14
+ // non-extractable keys, a {@link SubtleSigner} drops in beside it
15
+ // implementing the same interface, and nothing visible to the SDK
16
+ // consumer changes.
17
+ //
18
+ // `sign` is async-shaped from the start so the migration to
19
+ // `crypto.subtle.sign` (which is async) doesn't ripple through the
20
+ // caller graph as a breaking interface change.
21
+ import { sign as ed25519Sign } from "@aithos/protocol-client";
22
+ /**
23
+ * Today's implementation: wraps a raw 32-byte Ed25519 seed and signs
24
+ * via `@noble/ed25519`. Holds the seed in a defensively-copied
25
+ * Uint8Array bound to a private field, so mutating the constructor
26
+ * input afterwards does not affect the signer.
27
+ *
28
+ * Migration note: when we move to Web Crypto non-extractable keys,
29
+ * this class is replaced by a `SubtleSigner` that holds a `CryptoKey`
30
+ * reference and calls `crypto.subtle.sign("Ed25519", key, message)`.
31
+ * The {@link Signer} interface stays the same, so all callers (the
32
+ * SessionVault, the auth namespace, the ethos publish path) keep
33
+ * working unchanged.
34
+ */
35
+ export class RawSeedSigner {
36
+ publicKey;
37
+ #seed;
38
+ #destroyed = false;
39
+ /**
40
+ * @param seed 32-byte Ed25519 seed (the private half).
41
+ * @param publicKey 32-byte Ed25519 public key matching `seed`.
42
+ * Both arrays are defensively copied — the caller may zeroize their
43
+ * originals immediately.
44
+ */
45
+ constructor(seed, publicKey) {
46
+ if (seed.length !== 32) {
47
+ throw new Error(`RawSeedSigner: seed must be 32 bytes, got ${seed.length}`);
48
+ }
49
+ if (publicKey.length !== 32) {
50
+ throw new Error(`RawSeedSigner: publicKey must be 32 bytes, got ${publicKey.length}`);
51
+ }
52
+ this.#seed = new Uint8Array(seed);
53
+ this.publicKey = new Uint8Array(publicKey);
54
+ }
55
+ async sign(message) {
56
+ if (this.#destroyed) {
57
+ throw new Error("RawSeedSigner: cannot sign with a destroyed signer");
58
+ }
59
+ return ed25519Sign(message, this.#seed);
60
+ }
61
+ destroy() {
62
+ if (this.#destroyed)
63
+ return;
64
+ this.#seed.fill(0);
65
+ this.#destroyed = true;
66
+ }
67
+ /**
68
+ * Internal escape hatch for protocol-client interop. Returns a KeyPair
69
+ * usable with `buildSignedEnvelope({ signer })` and friends, which
70
+ * today take a raw seed. Marked `_unsafe` because it surfaces the
71
+ * private seed bytes — only callers within `@aithos/sdk` should use
72
+ * it, and never propagate the result outside the SDK boundary.
73
+ *
74
+ * When protocol-client gains a Signer-shaped API (post-alpha), this
75
+ * method goes away and SubtleSigner becomes pluggable upstream.
76
+ *
77
+ * @internal
78
+ */
79
+ _unsafeKeyPair() {
80
+ if (this.#destroyed) {
81
+ throw new Error("RawSeedSigner: cannot use a destroyed signer");
82
+ }
83
+ return { seed: this.#seed, publicKey: this.publicKey };
84
+ }
85
+ }
86
+ //# sourceMappingURL=signer.js.map