@aithos/sdk 0.1.0-alpha.5 → 0.1.0-alpha.50

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 (67) hide show
  1. package/README.md +245 -7
  2. package/dist/src/apps.d.ts +224 -0
  3. package/dist/src/apps.js +432 -0
  4. package/dist/src/assets.d.ts +208 -0
  5. package/dist/src/assets.js +534 -0
  6. package/dist/src/auth-api.d.ts +219 -0
  7. package/dist/src/auth-api.js +248 -0
  8. package/dist/src/auth.d.ts +543 -0
  9. package/dist/src/auth.js +937 -31
  10. package/dist/src/compute.d.ts +464 -6
  11. package/dist/src/compute.js +746 -20
  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 +342 -0
  15. package/dist/src/data.js +1002 -0
  16. package/dist/src/endpoints.d.ts +18 -0
  17. package/dist/src/endpoints.js +6 -0
  18. package/dist/src/ethos.d.ts +85 -0
  19. package/dist/src/ethos.js +463 -7
  20. package/dist/src/index.d.ts +17 -6
  21. package/dist/src/index.js +25 -3
  22. package/dist/src/internal/delegate-bundle.js +7 -2
  23. package/dist/src/internal/envelope.d.ts +93 -0
  24. package/dist/src/internal/envelope.js +59 -0
  25. package/dist/src/mandates.d.ts +111 -2
  26. package/dist/src/mandates.js +150 -7
  27. package/dist/src/react/AithosAsset.d.ts +66 -0
  28. package/dist/src/react/AithosAsset.js +67 -0
  29. package/dist/src/react/context.d.ts +29 -0
  30. package/dist/src/react/context.js +31 -0
  31. package/dist/src/react/index.d.ts +29 -0
  32. package/dist/src/react/index.js +31 -0
  33. package/dist/src/react/use-aithos-asset.d.ts +39 -0
  34. package/dist/src/react/use-aithos-asset.js +118 -0
  35. package/dist/src/react/use-transcribe-pending.d.ts +21 -0
  36. package/dist/src/react/use-transcribe-pending.js +47 -0
  37. package/dist/src/sdk.d.ts +10 -0
  38. package/dist/src/sdk.js +22 -0
  39. package/dist/src/transcribe-resilience.d.ts +57 -0
  40. package/dist/src/transcribe-resilience.js +203 -0
  41. package/dist/src/web.d.ts +279 -0
  42. package/dist/src/web.js +186 -0
  43. package/dist/test/auth-j3.test.js +32 -1
  44. package/dist/test/canonical-conformance.test.d.ts +2 -0
  45. package/dist/test/canonical-conformance.test.js +86 -0
  46. package/dist/test/compute-delegate-path.test.d.ts +2 -0
  47. package/dist/test/compute-delegate-path.test.js +183 -0
  48. package/dist/test/compute.test.js +4 -0
  49. package/dist/test/endpoints.test.js +25 -1
  50. package/dist/test/envelope-core-conformance.test.d.ts +2 -0
  51. package/dist/test/envelope-core-conformance.test.js +75 -0
  52. package/dist/test/envelope.test.d.ts +2 -0
  53. package/dist/test/envelope.test.js +318 -0
  54. package/dist/test/ethos-first-edition.test.d.ts +2 -0
  55. package/dist/test/ethos-first-edition.test.js +371 -0
  56. package/dist/test/mandates-compute.test.d.ts +2 -0
  57. package/dist/test/mandates-compute.test.js +256 -0
  58. package/dist/test/sdk.test.js +10 -2
  59. package/dist/test/signup-bootstrap.test.d.ts +2 -0
  60. package/dist/test/signup-bootstrap.test.js +311 -0
  61. package/dist/test/transcribe-invoke.test.d.ts +2 -0
  62. package/dist/test/transcribe-invoke.test.js +204 -0
  63. package/dist/test/transcribe.test.d.ts +2 -0
  64. package/dist/test/transcribe.test.js +186 -0
  65. package/dist/test/web.test.d.ts +2 -0
  66. package/dist/test/web.test.js +270 -0
  67. package/package.json +20 -3
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Bundled copy of the `aithos.contacts.v1` schema.
3
+ *
4
+ * Mirrors `spec/data/schemas/aithos.contacts.v1.json` of the
5
+ * Aithos-protocol repo. The SDK uses this to split a record into its
6
+ * indexable (metadata) and encrypted (payload) parts on insert and to
7
+ * recombine them on read.
8
+ *
9
+ * In a later iteration the SDK will fetch / resolve schemas dynamically
10
+ * from a registry; for v0.1 we bundle the core schemas.
11
+ */
12
+ import type { AithosSchemaLite } from "./data.js";
13
+ export declare const contactsV1: AithosSchemaLite;
14
+ //# sourceMappingURL=data-schema-contacts-v1.d.ts.map
@@ -0,0 +1,28 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Mathieu Colla
3
+ export const contactsV1 = {
4
+ schema: "aithos.contacts.v1",
5
+ indexable: new Set([
6
+ "name",
7
+ "email",
8
+ "phone_hash",
9
+ "status",
10
+ "tags",
11
+ "source",
12
+ "created_at",
13
+ "modified_at",
14
+ "last_contacted_at",
15
+ ]),
16
+ encrypted: new Set([
17
+ "phone",
18
+ "notes",
19
+ "conversation_log",
20
+ "form_responses",
21
+ "custom_fields",
22
+ ]),
23
+ auto: new Set(["created_at", "modified_at"]),
24
+ defaults: {
25
+ status: "lead",
26
+ },
27
+ };
28
+ //# sourceMappingURL=data-schema-contacts-v1.js.map
@@ -0,0 +1,342 @@
1
+ import { type SignedMandate } from "@aithos/protocol-client";
2
+ export interface AithosSchemaLite {
3
+ readonly schema: string;
4
+ readonly indexable: ReadonlySet<string>;
5
+ readonly encrypted: ReadonlySet<string>;
6
+ readonly auto: ReadonlySet<string>;
7
+ readonly defaults: Readonly<Record<string, unknown>>;
8
+ }
9
+ export interface CreateDataClientArgs {
10
+ /**
11
+ * PDS base URL. Defaults to `https://pds.aithos.be` (the production vanity
12
+ * domain, CloudFront-fronted) when omitted. Override for self-hosting or
13
+ * staging (e.g. a raw `execute-api` URL).
14
+ */
15
+ readonly pdsUrl?: string;
16
+ /** Subject DID — typically did:key:… in dev, did:aithos:… in prod. */
17
+ readonly did: string;
18
+ /**
19
+ * Ed25519 sphere seed (32 bytes). For did:key this is the same as
20
+ * the key embedded in the DID itself. For did:aithos this is the
21
+ * subject's `#data` (or `#public`) sphere key.
22
+ */
23
+ readonly sphereSeed: Uint8Array;
24
+ /**
25
+ * The verification method URL within the DID document used to sign
26
+ * envelopes. For did:key this is `<did>#<multibase>`. For did:aithos
27
+ * this is `<did>#data` (or `#public`).
28
+ */
29
+ readonly verificationMethod: string;
30
+ /** Optional fetch implementation. Defaults to globalThis.fetch. */
31
+ readonly fetch?: typeof fetch;
32
+ /**
33
+ * Optional list of app-defined schema definitions, in addition to
34
+ * the SDK-bundled core schemas (currently `aithos.contacts.v1`).
35
+ *
36
+ * Apps in the vendor namespace (`aithos.x.<vendor>.<name>.v<N>`) or
37
+ * non-`aithos.*` namespaces MUST supply their schemas here so the
38
+ * SDK can split records into indexable metadata vs encrypted payload.
39
+ *
40
+ * When the same schema id appears in both the bundled core registry
41
+ * and this list, the app-supplied definition wins (intentional —
42
+ * allows local overrides for testing, though immutability per spec
43
+ * §3.5 means a published schema id should never change shape).
44
+ *
45
+ * Schemas are scoped to the {@link DataClient} instance — they don't
46
+ * leak to other clients in the same process.
47
+ */
48
+ readonly schemas?: readonly AithosSchemaLite[];
49
+ }
50
+ export interface DataClient {
51
+ /** Get / create a collection handle. */
52
+ collection(name: string): DataCollection;
53
+ /** Initialize a new collection with an explicit schema. Throws
54
+ * `-32073 AITHOS_DATA_COLLECTION_EXISTS` if it already exists. */
55
+ createCollection(args: {
56
+ name: string;
57
+ schema: string;
58
+ forwardSecrecy?: "best_effort" | "strict";
59
+ }): Promise<void>;
60
+ /**
61
+ * Get-or-create: create the collection if it doesn't exist, otherwise
62
+ * succeed silently. Idempotent — safe to call on every app boot before
63
+ * writing. Absorbs the `-32073 AITHOS_DATA_COLLECTION_EXISTS` conflict
64
+ * (and the concurrent-create race) so callers don't have to special-case
65
+ * "already there". Avoids the friction where `collection(name).insert(…)`
66
+ * on a never-created collection fails with `-32020`.
67
+ */
68
+ ensureCollection(args: {
69
+ name: string;
70
+ schema: string;
71
+ forwardSecrecy?: "best_effort" | "strict";
72
+ }): Promise<void>;
73
+ /** List collections owned by this subject. */
74
+ listCollections(): Promise<readonly {
75
+ name: string;
76
+ schema: string;
77
+ record_count: number;
78
+ }[]>;
79
+ /** List gamma audit entries. */
80
+ listGammaEntries(opts?: {
81
+ limit?: number;
82
+ opPrefix?: string;
83
+ verify?: boolean;
84
+ }): Promise<unknown>;
85
+ /**
86
+ * Idempotently publish a vendor (`aithos.x.<vendor>.<name>.v<N>`)
87
+ * JSON Schema document to this subject's PDS. Once published, the
88
+ * PDS validates record writes against the schema doc server-side,
89
+ * closing the gap A2a left open (cf. Aithos-protocol/PLAN-A2b-…).
90
+ *
91
+ * Safe to call on every app boot — re-registering the same document
92
+ * (same canonical hash) resolves to `{ created: false }`. A different
93
+ * document for the same `aithos:schema` id is REJECTED with code
94
+ * -32082 `AITHOS_DATA_SCHEMA_IMMUTABLE` ; the caller must bump the
95
+ * version segment in `aithos:schema` and retry.
96
+ *
97
+ * Core schemas (`aithos.<name>.v<N>` without `.x.`) cannot be
98
+ * registered via this RPC ; they're bundled by the platform per spec
99
+ * §3.7.2.
100
+ *
101
+ * @param schemaDoc Full JSON Schema 2020-12 document. MUST carry
102
+ * `aithos:schema` and `aithos:version` top-level fields.
103
+ */
104
+ registerSchema(schemaDoc: object): Promise<{
105
+ schemaId: string;
106
+ docHash: string;
107
+ created: boolean;
108
+ createdAt?: string;
109
+ }>;
110
+ /**
111
+ * Fetch a published schema document from the PDS.
112
+ *
113
+ * For core schemas (`aithos.<name>.v<N>`) the lookup is global ;
114
+ * `subjectDid` is ignored. For vendor schemas (`aithos.x.*`) the
115
+ * `subjectDid` arg selects whose published registry to query and
116
+ * defaults to this client's own DID.
117
+ *
118
+ * Returns null when the lookup misses (rather than throwing) so
119
+ * call sites can branch on the result.
120
+ */
121
+ getSchema(schemaId: string, opts?: {
122
+ subjectDid?: string;
123
+ }): Promise<object | null>;
124
+ /**
125
+ * Grant a mandate-holding delegate read access to one of this owner's
126
+ * collections, by re-wrapping the collection's CMK to the grantee's
127
+ * key and posting `aithos.data.authorize_app`.
128
+ *
129
+ * Owner-only. The CMK is unwrapped locally (the owner holds it), then
130
+ * re-wrapped X25519-HKDF-AEAD to the grantee's X25519 key (derived
131
+ * from `mandate.grantee.pubkey`). The platform never sees the CMK in
132
+ * clear — it only appends the wrap to the collection's envelope after
133
+ * verifying the mandate (data spec §4.5).
134
+ *
135
+ * Idempotent at the server: re-authorizing the same grantee on the
136
+ * same collection is a no-op. One wrap per grantee covers every record
137
+ * in the collection (O(1) authorization — the CMK is stable).
138
+ *
139
+ * The mandate must carry a `data.<collectionName>.{read|write|admin}`
140
+ * or `data.*.*` scope and a `grantee.pubkey`.
141
+ */
142
+ authorizeDelegate(args: {
143
+ collectionName: string;
144
+ mandate: SignedMandate;
145
+ }): Promise<void>;
146
+ /**
147
+ * Revoke a delegate's access to a collection (`aithos.data.revoke_app`).
148
+ * Owner-only, forward-only: after revocation the PDS refuses the
149
+ * delegate's reads (the mandate is marked revoked), and the delegate's
150
+ * wrap is dropped from the collection's authorization index. Already-read
151
+ * / cached plaintext on the delegate side is out of scope (a known limit
152
+ * of any key-sharing scheme — revocation blocks FUTURE access).
153
+ */
154
+ revokeDelegate(args: {
155
+ collectionName: string;
156
+ mandateId: string;
157
+ reason?: string;
158
+ }): Promise<void>;
159
+ /** Drop in-memory cache (CMK, collection metadata, …). */
160
+ reset(): void;
161
+ }
162
+ /**
163
+ * Read-only view over a subject's data collections, driven by a mandate
164
+ * the subject granted to a delegate (`data.<collection>.read`). Built by
165
+ * {@link createDelegateDataClient}.
166
+ *
167
+ * Mirror of {@link DataClient} minus every mutating verb: a delegate
168
+ * holding a read mandate can `get`/`list` and enumerate collections, but
169
+ * cannot insert, update, delete, create collections, register schemas, or
170
+ * re-delegate. Those throw `-32042` client-side (and the PDS rejects them
171
+ * server-side regardless).
172
+ */
173
+ export interface ReadonlyDataClient {
174
+ /** Get a read-only collection handle. */
175
+ collection(name: string): ReadonlyDataCollection;
176
+ /** List collections the delegate's mandate scopes can reach. */
177
+ listCollections(): Promise<readonly {
178
+ name: string;
179
+ schema: string;
180
+ record_count: number;
181
+ }[]>;
182
+ /** List gamma audit entries (read). */
183
+ listGammaEntries(opts?: {
184
+ limit?: number;
185
+ opPrefix?: string;
186
+ verify?: boolean;
187
+ }): Promise<unknown>;
188
+ /** Drop in-memory cache (CMK, collection metadata, …). */
189
+ reset(): void;
190
+ }
191
+ export interface ReadonlyDataCollection {
192
+ readonly name: string;
193
+ /** Fetch one record by id (decrypted client-side via the re-wrapped CMK). */
194
+ get(recordId: string): Promise<Record<string, unknown> | null>;
195
+ /** List records, decrypted. Pagination via opaque cursor. */
196
+ list(opts?: ListOpts): Promise<{
197
+ items: Record<string, unknown>[];
198
+ nextCursor?: string;
199
+ }>;
200
+ }
201
+ export interface DataCollection {
202
+ readonly name: string;
203
+ /**
204
+ * Insert a record. The object MAY contain both indexable and
205
+ * encrypted fields per the schema; the SDK splits them.
206
+ */
207
+ insert(record: Record<string, unknown>): Promise<string>;
208
+ /** Fetch one record by id (decrypted client-side). */
209
+ get(recordId: string): Promise<Record<string, unknown> | null>;
210
+ /** List records, decrypted. Pagination via opaque cursor. */
211
+ list(opts?: ListOpts): Promise<{
212
+ items: Record<string, unknown>[];
213
+ nextCursor?: string;
214
+ }>;
215
+ /**
216
+ * Replace a record. Same shape as insert; the SDK splits indexable
217
+ * vs encrypted again per the schema.
218
+ */
219
+ update(recordId: string, record: Record<string, unknown>): Promise<void>;
220
+ /** Soft-delete a record. */
221
+ delete(recordId: string): Promise<void>;
222
+ }
223
+ export interface ListOpts {
224
+ readonly filter?: {
225
+ readonly equals?: {
226
+ field: string;
227
+ value: unknown;
228
+ };
229
+ readonly contains?: {
230
+ field: string;
231
+ value: string;
232
+ };
233
+ readonly tagsAny?: readonly string[];
234
+ readonly tagsAll?: readonly string[];
235
+ readonly range?: {
236
+ field: string;
237
+ gte?: string;
238
+ lte?: string;
239
+ };
240
+ };
241
+ readonly order?: "newest" | "oldest";
242
+ readonly limit?: number;
243
+ readonly cursor?: string;
244
+ }
245
+ export declare function createDataClient(args: CreateDataClientArgs): DataClient;
246
+ export interface CreateDelegateDataClientArgs {
247
+ /** PDS base URL (same endpoint the owner writes to). Defaults to
248
+ * `https://pds.aithos.be` when omitted. */
249
+ readonly pdsUrl?: string;
250
+ /** DID of the SUBJECT whose data is being read (the mandate issuer). */
251
+ readonly subjectDid: string;
252
+ /**
253
+ * The full signed mandate the subject granted to this delegate. Must
254
+ * carry a `data.<collection>.read` (or wider) scope and a
255
+ * `grantee.pubkey` matching `delegateSeed`.
256
+ */
257
+ readonly mandate: SignedMandate;
258
+ /** The delegate's Ed25519 seed (32 bytes) — the grantee key the mandate
259
+ * is bound to. Used to sign envelopes AND to derive the X25519 key that
260
+ * unwraps the re-wrapped CMK. */
261
+ readonly delegateSeed: Uint8Array;
262
+ /**
263
+ * The delegate's Ed25519 public key, multibase-encoded. Defaults to
264
+ * `mandate.grantee.pubkey`. This is the bare verificationMethod the PDS
265
+ * binds the delegate envelope to.
266
+ */
267
+ readonly granteePubkeyMultibase?: string;
268
+ /** App-defined (vendor) schemas, as for {@link createDataClient}. */
269
+ readonly schemas?: readonly AithosSchemaLite[];
270
+ /** `fetch` override (tests). */
271
+ readonly fetch?: typeof fetch;
272
+ }
273
+ /**
274
+ * Build a read-only data client that reads a subject's collections under
275
+ * a mandate (delegate path). The returned {@link ReadonlyDataClient}
276
+ * signs every request as the delegate (bare-multibase verificationMethod
277
+ * + the mandate attached to the envelope), and decrypts records using the
278
+ * CMK the owner re-wrapped for this delegate via
279
+ * {@link DataClient.authorizeDelegate}.
280
+ *
281
+ * Writes are not available on the returned type and throw `-32042` if
282
+ * forced.
283
+ */
284
+ export declare function createDelegateDataClient(args: CreateDelegateDataClientArgs): ReadonlyDataClient;
285
+ /** An append-only handle on one collection: `insert` and nothing else. */
286
+ export interface AppendOnlyDataCollection {
287
+ readonly name: string;
288
+ /**
289
+ * Deposit a record. The DEK is sealed to the owner's public key, so the
290
+ * depositor cannot read this (or any) record back. Returns the record id.
291
+ */
292
+ insert(record: Record<string, unknown>): Promise<string>;
293
+ }
294
+ /** A client holding a `data.<collection>.append` mandate. Insert-only. */
295
+ export interface AppendOnlyDataClient {
296
+ /** Get an append-only handle on a collection (schema supplied at
297
+ * construction — append clients cannot read collection metadata). */
298
+ collection(name: string): AppendOnlyDataCollection;
299
+ /** Drop in-memory cache. */
300
+ reset(): void;
301
+ }
302
+ export interface CreateAppendDataClientArgs {
303
+ /** PDS base URL (same endpoint the owner writes to). Defaults to
304
+ * `https://pds.aithos.be` when omitted. */
305
+ readonly pdsUrl?: string;
306
+ /** DID of the SUBJECT who owns the target collection (the mandate issuer). */
307
+ readonly subjectDid: string;
308
+ /**
309
+ * The owner's `#data` Ed25519 public key (multibase z…). The depositor
310
+ * derives the owner's X25519 wrap target from it and seals each DEK to it.
311
+ * Source: the append mandate / invitation, or the owner's DID document.
312
+ */
313
+ readonly ownerDataPubkeyMultibase: string;
314
+ /** The signed mandate carrying `data.<collection>.append`. */
315
+ readonly mandate: SignedMandate;
316
+ /** The depositor's Ed25519 seed (32 bytes) — the grantee key the mandate is
317
+ * bound to. Signs each insert envelope. NEVER used to read. */
318
+ readonly delegateSeed: Uint8Array;
319
+ /** Defaults to `mandate.grantee.pubkey`. */
320
+ readonly granteePubkeyMultibase?: string;
321
+ /**
322
+ * Schema of the target collection(s). The append client builds records
323
+ * locally (it cannot fetch collection metadata), so the caller MUST supply
324
+ * the schema(s) used by the collection it deposits into. The first entry is
325
+ * used as the default; multiple may be passed for multi-collection clients.
326
+ */
327
+ readonly schema: AithosSchemaLite;
328
+ /** Additional schemas (looked up by id alongside `schema`). */
329
+ readonly schemas?: readonly AithosSchemaLite[];
330
+ /** `fetch` override (tests). */
331
+ readonly fetch?: typeof fetch;
332
+ }
333
+ /**
334
+ * Build an **append-only** data client from a `data.<collection>.append`
335
+ * mandate. The returned {@link AppendOnlyDataClient} can ONLY `insert`: it
336
+ * seals each record's DEK to the owner's public key (never the CMK), so it
337
+ * holds no read capability — it cannot decrypt anything in the collection,
338
+ * not even its own deposit. The PDS additionally enforces the append scope
339
+ * (insert allowed; get/list/update/delete refused).
340
+ */
341
+ export declare function createAppendDataClient(args: CreateAppendDataClientArgs): AppendOnlyDataClient;
342
+ //# sourceMappingURL=data.d.ts.map