@aithos/sdk 0.1.0-alpha.53 → 0.1.0-alpha.55
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/README.md +5 -3
- package/dist/src/assets.d.ts +19 -3
- package/dist/src/auth.js +50 -72
- package/dist/src/compute.d.ts +98 -0
- package/dist/src/compute.js +47 -0
- package/dist/src/data.d.ts +28 -7
- package/dist/src/data.js +85 -12
- package/dist/src/index.d.ts +5 -3
- package/dist/src/index.js +15 -2
- package/dist/src/internal/cmk-wrap.d.ts +41 -0
- package/dist/src/internal/cmk-wrap.js +132 -0
- package/dist/src/key-store.d.ts +7 -3
- package/dist/src/migrate.d.ts +105 -0
- package/dist/src/migrate.js +367 -0
- package/dist/src/rotate.d.ts +94 -0
- package/dist/src/rotate.js +298 -0
- package/dist/src/sdk.d.ts +26 -2
- package/dist/src/sdk.js +45 -1
- package/dist/test/converse.test.d.ts +2 -0
- package/dist/test/converse.test.js +162 -0
- package/dist/test/migrate.test.d.ts +2 -0
- package/dist/test/migrate.test.js +340 -0
- package/dist/test/rotate-ethos.test.d.ts +2 -0
- package/dist/test/rotate-ethos.test.js +151 -0
- package/dist/test/rotate.test.d.ts +2 -0
- package/dist/test/rotate.test.js +63 -0
- package/dist/test/schema-autoresolve.test.d.ts +2 -0
- package/dist/test/schema-autoresolve.test.js +136 -0
- package/package.json +1 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
// A reader that did NOT bundle a vendor schema can still read a collection that
|
|
4
|
+
// uses it, by auto-resolving the PUBLISHED JSON Schema from the PDS and
|
|
5
|
+
// deriving the field split from its aithos:indexable / aithos:auto annotations.
|
|
6
|
+
// This is what lets the strangler reference app (and any latest-SDK client)
|
|
7
|
+
// read any collection without hardcoding VENDOR_SCHEMAS.
|
|
8
|
+
import { test } from "node:test";
|
|
9
|
+
import { strict as assert } from "node:assert";
|
|
10
|
+
import { randomBytes } from "node:crypto";
|
|
11
|
+
import { createDataClient, liteFromPublishedSchema } from "../src/data.js";
|
|
12
|
+
import * as ed from "@noble/ed25519";
|
|
13
|
+
import { sha512 } from "@noble/hashes/sha2.js";
|
|
14
|
+
ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));
|
|
15
|
+
const MEMO_ID = "aithos.x.demo.memo.v1";
|
|
16
|
+
const memoLite = {
|
|
17
|
+
schema: MEMO_ID,
|
|
18
|
+
indexable: new Set(["title"]),
|
|
19
|
+
encrypted: new Set(["body"]),
|
|
20
|
+
auto: new Set(),
|
|
21
|
+
defaults: {},
|
|
22
|
+
};
|
|
23
|
+
const memoJson = {
|
|
24
|
+
"aithos:schema": MEMO_ID,
|
|
25
|
+
"aithos:version": "1.0.0",
|
|
26
|
+
type: "object",
|
|
27
|
+
additionalProperties: false,
|
|
28
|
+
required: ["title"],
|
|
29
|
+
properties: {
|
|
30
|
+
title: { type: "string", "aithos:indexable": true },
|
|
31
|
+
body: { type: "string" },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
test("liteFromPublishedSchema derives the field split from annotations", () => {
|
|
35
|
+
const lite = liteFromPublishedSchema(memoJson);
|
|
36
|
+
assert.equal(lite.schema, MEMO_ID);
|
|
37
|
+
assert.deepEqual([...lite.indexable].sort(), ["title"]);
|
|
38
|
+
assert.deepEqual([...lite.encrypted].sort(), ["body"]);
|
|
39
|
+
assert.equal(lite.auto.size, 0);
|
|
40
|
+
});
|
|
41
|
+
function makePds() {
|
|
42
|
+
const collections = new Map();
|
|
43
|
+
const records = new Map();
|
|
44
|
+
const schemas = new Map();
|
|
45
|
+
const fetchImpl = (async (_url, init) => {
|
|
46
|
+
const body = JSON.parse(init.body);
|
|
47
|
+
const p = body.params ?? {};
|
|
48
|
+
const ok = (result) => new Response(JSON.stringify({ jsonrpc: "2.0", id: body.id, result }), { status: 200 });
|
|
49
|
+
const er = (code, m) => new Response(JSON.stringify({ jsonrpc: "2.0", id: body.id, error: { code, message: m } }), { status: 200 });
|
|
50
|
+
const urn = (did, n) => `urn:aithos:collection:${did}:${n}`;
|
|
51
|
+
switch (body.method) {
|
|
52
|
+
case "aithos.data.register_schema":
|
|
53
|
+
schemas.set(p.schema_doc["aithos:schema"], p.schema_doc);
|
|
54
|
+
return ok({ schema_id: p.schema_doc["aithos:schema"], doc_hash: "h", created: true });
|
|
55
|
+
case "aithos.data.get_schema": {
|
|
56
|
+
const d = schemas.get(p.schema);
|
|
57
|
+
return d ? ok({ schema: d }) : er(-32070, "unknown schema");
|
|
58
|
+
}
|
|
59
|
+
case "aithos.data.create_collection": {
|
|
60
|
+
const u = urn(p.subject_did, p.collection_name);
|
|
61
|
+
collections.set(u, { urn: u, name: p.collection_name, schema: p.schema, subject_did: p.subject_did, cmk_envelope: p.cmk_envelope, record_count: 0 });
|
|
62
|
+
records.set(u, new Map());
|
|
63
|
+
return ok({ urn: u, name: p.collection_name, schema: p.schema, cmk_envelope: p.cmk_envelope });
|
|
64
|
+
}
|
|
65
|
+
case "aithos.data.get_collection": {
|
|
66
|
+
const c = collections.get(urn(p.subject_did, p.collection_name));
|
|
67
|
+
return c ? ok({ urn: c.urn, name: c.name, schema: c.schema, cmk_envelope: c.cmk_envelope, record_count: c.record_count }) : er(-32020, "nf");
|
|
68
|
+
}
|
|
69
|
+
case "aithos.data.insert_record": {
|
|
70
|
+
records.get(p.collection_urn).set(p.record_id, { record_id: p.record_id, metadata: p.metadata, payload: p.payload });
|
|
71
|
+
return ok({ record_id: p.record_id });
|
|
72
|
+
}
|
|
73
|
+
case "aithos.data.get_record": {
|
|
74
|
+
const r = records.get(p.collection_urn)?.get(p.record_id);
|
|
75
|
+
return r ? ok(r) : er(-32020, "nf");
|
|
76
|
+
}
|
|
77
|
+
default:
|
|
78
|
+
return er(-32601, body.method);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return { fetchImpl, schemas };
|
|
82
|
+
}
|
|
83
|
+
test("a reader without the bundled vendor lite decodes via the published schema", async () => {
|
|
84
|
+
const seed = new Uint8Array(randomBytes(32));
|
|
85
|
+
const pub = ed.getPublicKey(seed);
|
|
86
|
+
// did:key style (single-key) — fine for the data PDS owner path in this mock.
|
|
87
|
+
let n = 0n;
|
|
88
|
+
const mc = new Uint8Array([0xed, 0x01, ...pub]);
|
|
89
|
+
for (const b of mc)
|
|
90
|
+
n = (n << 8n) | BigInt(b);
|
|
91
|
+
const alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
92
|
+
let mb = "";
|
|
93
|
+
let x = n;
|
|
94
|
+
while (x > 0n) {
|
|
95
|
+
mb = alpha[Number(x % 58n)] + mb;
|
|
96
|
+
x /= 58n;
|
|
97
|
+
}
|
|
98
|
+
const did = `did:key:z${mb}`;
|
|
99
|
+
const vm = `${did}#z${mb}`;
|
|
100
|
+
const pds = makePds();
|
|
101
|
+
// Writer: bundles the lite, registers the JSON schema, writes a record.
|
|
102
|
+
const writer = createDataClient({ pdsUrl: "https://pds.test", did, sphereSeed: seed, verificationMethod: vm, schemas: [memoLite], fetch: pds.fetchImpl });
|
|
103
|
+
await writer.registerSchema(memoJson);
|
|
104
|
+
await writer.createCollection({ name: "memos", schema: MEMO_ID });
|
|
105
|
+
const recId = await writer.collection("memos").insert({ title: "Hello", body: "top secret body" });
|
|
106
|
+
// Reader: NO bundled schema. Must auto-resolve from the PDS-published schema.
|
|
107
|
+
const reader = createDataClient({ pdsUrl: "https://pds.test", did, sphereSeed: seed, verificationMethod: vm, fetch: pds.fetchImpl });
|
|
108
|
+
const got = await reader.collection("memos").get(recId);
|
|
109
|
+
assert.equal(got.title, "Hello", "indexable field present");
|
|
110
|
+
assert.equal(got.body, "top secret body", "encrypted field decoded via auto-resolved schema");
|
|
111
|
+
});
|
|
112
|
+
test("a reader still fails cleanly when the schema is neither bundled nor published", async () => {
|
|
113
|
+
const seed = new Uint8Array(randomBytes(32));
|
|
114
|
+
const pub = ed.getPublicKey(seed);
|
|
115
|
+
let n = 0n;
|
|
116
|
+
const mc = new Uint8Array([0xed, 0x01, ...pub]);
|
|
117
|
+
for (const b of mc)
|
|
118
|
+
n = (n << 8n) | BigInt(b);
|
|
119
|
+
const alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
120
|
+
let mb = "";
|
|
121
|
+
let x = n;
|
|
122
|
+
while (x > 0n) {
|
|
123
|
+
mb = alpha[Number(x % 58n)] + mb;
|
|
124
|
+
x /= 58n;
|
|
125
|
+
}
|
|
126
|
+
const did = `did:key:z${mb}`;
|
|
127
|
+
const vm = `${did}#z${mb}`;
|
|
128
|
+
const pds = makePds();
|
|
129
|
+
// Writer creates the collection WITHOUT registering the schema on the PDS.
|
|
130
|
+
const writer = createDataClient({ pdsUrl: "https://pds.test", did, sphereSeed: seed, verificationMethod: vm, schemas: [memoLite], fetch: pds.fetchImpl });
|
|
131
|
+
await writer.createCollection({ name: "memos", schema: MEMO_ID });
|
|
132
|
+
await writer.collection("memos").insert({ title: "x", body: "y" });
|
|
133
|
+
const reader = createDataClient({ pdsUrl: "https://pds.test", did, sphereSeed: seed, verificationMethod: vm, fetch: pds.fetchImpl });
|
|
134
|
+
await assert.rejects(() => reader.collection("memos").get("anything"), /not known to the SDK and not published/);
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=schema-autoresolve.test.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aithos/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.55",
|
|
4
4
|
"description": "Aithos SDK — high-level TypeScript developer kit for building agentic apps on the Aithos protocol. Wraps @aithos/protocol-client and exposes the Aithos compute proxy and wallet (Stripe top-up) endpoints.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aithos",
|