@aithos/sdk 0.1.0-alpha.4 → 0.1.0-alpha.40
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 +211 -7
- package/dist/src/assets.d.ts +207 -0
- package/dist/src/assets.js +533 -0
- package/dist/src/auth-api.d.ts +138 -0
- package/dist/src/auth-api.js +168 -0
- package/dist/src/auth.d.ts +536 -119
- package/dist/src/auth.js +1207 -152
- package/dist/src/compute.d.ts +221 -9
- package/dist/src/compute.js +293 -16
- package/dist/src/data-schema-contacts-v1.d.ts +14 -0
- package/dist/src/data-schema-contacts-v1.js +28 -0
- package/dist/src/data.d.ts +153 -0
- package/dist/src/data.js +670 -0
- package/dist/src/endpoints.d.ts +9 -0
- package/dist/src/endpoints.js +5 -0
- package/dist/src/ethos.d.ts +202 -1
- package/dist/src/ethos.js +821 -16
- package/dist/src/index.d.ts +16 -6
- package/dist/src/index.js +33 -6
- package/dist/src/internal/delegate-bundle.d.ts +18 -0
- package/dist/src/internal/delegate-bundle.js +94 -0
- package/dist/src/internal/delegate-state.d.ts +45 -0
- package/dist/src/internal/delegate-state.js +120 -0
- package/dist/src/internal/envelope.d.ts +77 -0
- package/dist/src/internal/envelope.js +154 -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 +163 -1
- package/dist/src/mandates.js +286 -8
- package/dist/src/react/AithosAsset.d.ts +66 -0
- package/dist/src/react/AithosAsset.js +67 -0
- package/dist/src/react/context.d.ts +29 -0
- package/dist/src/react/context.js +31 -0
- package/dist/src/react/index.d.ts +28 -0
- package/dist/src/react/index.js +30 -0
- package/dist/src/react/use-aithos-asset.d.ts +39 -0
- package/dist/src/react/use-aithos-asset.js +118 -0
- package/dist/src/sdk.d.ts +39 -3
- package/dist/src/sdk.js +36 -23
- package/dist/src/wallet.d.ts +4 -6
- package/dist/src/wallet.js +18 -8
- package/dist/src/web.d.ts +279 -0
- package/dist/src/web.js +186 -0
- package/package.json +18 -3
- package/dist/test/auth.test.d.ts +0 -2
- package/dist/test/auth.test.js +0 -175
- package/dist/test/compute.test.d.ts +0 -2
- package/dist/test/compute.test.js +0 -179
- package/dist/test/endpoints.test.d.ts +0 -2
- package/dist/test/endpoints.test.js +0 -43
- package/dist/test/sdk.test.d.ts +0 -2
- package/dist/test/sdk.test.js +0 -86
- package/dist/test/wallet.test.d.ts +0 -2
- package/dist/test/wallet.test.js +0 -110
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stored owner identity material. Treat as opaque from the consumer's
|
|
3
|
+
* point of view — its internal shape may evolve between SDK versions
|
|
4
|
+
* (e.g. when we migrate to `CryptoKey` references). Custom KeyStore
|
|
5
|
+
* implementations should round-trip the value as-is rather than
|
|
6
|
+
* peeking inside.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export interface StoredOwnerKeys {
|
|
11
|
+
/** Schema version. Today: `"0.1.0-hex"`. */
|
|
12
|
+
readonly version: "0.1.0-hex";
|
|
13
|
+
readonly did: string;
|
|
14
|
+
readonly handle: string;
|
|
15
|
+
readonly displayName: string;
|
|
16
|
+
/** Hex-encoded 32-byte Ed25519 seeds — one per sphere. */
|
|
17
|
+
readonly seedsHex: {
|
|
18
|
+
readonly root: string;
|
|
19
|
+
readonly public: string;
|
|
20
|
+
readonly circle: string;
|
|
21
|
+
readonly self: string;
|
|
22
|
+
};
|
|
23
|
+
/** ISO-8601 timestamp of the original save. Informational. */
|
|
24
|
+
readonly savedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Stored delegate session material. Opaque from the consumer's
|
|
28
|
+
* point of view; see {@link StoredOwnerKeys}.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export interface StoredDelegateKeys {
|
|
33
|
+
readonly version: "0.1.0-hex";
|
|
34
|
+
/** DID of the subject whose ethos this mandate authorizes. */
|
|
35
|
+
readonly subjectDid: string;
|
|
36
|
+
/** Mandate id — used as the storage key. */
|
|
37
|
+
readonly mandateId: string;
|
|
38
|
+
/** Full §4.2 SignedMandate, stored as opaque JSON. */
|
|
39
|
+
readonly mandate: Record<string, unknown>;
|
|
40
|
+
/** Grantee URN, e.g. `urn:aithos:agent:bob1`. */
|
|
41
|
+
readonly granteeId: string;
|
|
42
|
+
/** Multibase-encoded Ed25519 grantee pubkey, matches `mandate.grantee.pubkey`. */
|
|
43
|
+
readonly granteePubkeyMultibase: string;
|
|
44
|
+
/** Hex-encoded 32-byte delegate Ed25519 seed. */
|
|
45
|
+
readonly delegateSeedHex: string;
|
|
46
|
+
readonly importedAt: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Persistence backend for owner identity material and delegate
|
|
50
|
+
* bundles. Methods are async because an IndexedDB-backed
|
|
51
|
+
* implementation is the default and IDB's API is async — sync stores
|
|
52
|
+
* are still trivial to write (`memoryKeyStore`) by returning
|
|
53
|
+
* pre-resolved promises.
|
|
54
|
+
*
|
|
55
|
+
* Implementations should never throw on missing records: a fresh
|
|
56
|
+
* device returns `null` from `loadOwner` and `[]` from
|
|
57
|
+
* `listDelegates`. They should only throw on hard I/O failures
|
|
58
|
+
* (quota exceeded, schema corruption). The SDK treats throws as
|
|
59
|
+
* "store unavailable, fall through to re-auth".
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export interface AithosKeyStore {
|
|
64
|
+
loadOwner(): Promise<StoredOwnerKeys | null>;
|
|
65
|
+
saveOwner(owner: StoredOwnerKeys): Promise<void>;
|
|
66
|
+
clearOwner(): Promise<void>;
|
|
67
|
+
listDelegates(): Promise<readonly StoredDelegateKeys[]>;
|
|
68
|
+
loadDelegate(mandateId: string): Promise<StoredDelegateKeys | null>;
|
|
69
|
+
saveDelegate(d: StoredDelegateKeys): Promise<void>;
|
|
70
|
+
removeDelegate(mandateId: string): Promise<void>;
|
|
71
|
+
clearAllDelegates(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* In-memory key store. Loses everything on page reload — useful for
|
|
75
|
+
* tests, SSR, ephemeral CLI tools, and any workflow where you want a
|
|
76
|
+
* deliberately short-lived session.
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
export declare function memoryKeyStore(): AithosKeyStore;
|
|
81
|
+
/**
|
|
82
|
+
* Default IndexedDB database name used by {@link indexedDbKeyStore}.
|
|
83
|
+
* Apps that want to coexist with other Aithos-aware libs (or scope
|
|
84
|
+
* sessions per-tenant) can pass a custom `dbName`.
|
|
85
|
+
*/
|
|
86
|
+
export declare const DEFAULT_KEYSTORE_DB_NAME = "aithos-sdk-keys";
|
|
87
|
+
interface IndexedDbKeyStoreOptions {
|
|
88
|
+
/** Database name. Defaults to {@link DEFAULT_KEYSTORE_DB_NAME}. */
|
|
89
|
+
readonly dbName?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Inject a non-default IDBFactory — used by tests. Apps should not
|
|
92
|
+
* pass this; the global `indexedDB` is the right choice everywhere
|
|
93
|
+
* else.
|
|
94
|
+
*
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
readonly factory?: IDBFactory;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* IndexedDB-backed key store. Default in browser environments —
|
|
101
|
+
* persists across reloads and browser restarts, scoped to the
|
|
102
|
+
* page's origin.
|
|
103
|
+
*
|
|
104
|
+
* Storage shape today:
|
|
105
|
+
*
|
|
106
|
+
* - object store `owner` — single record at key `"self"`,
|
|
107
|
+
* shape {@link StoredOwnerKeys}
|
|
108
|
+
* - object store `delegates` — keyPath `mandateId`, shape
|
|
109
|
+
* {@link StoredDelegateKeys}
|
|
110
|
+
*
|
|
111
|
+
* Both stores live in DB `aithos-sdk-keys` (configurable via
|
|
112
|
+
* `dbName`) at version 1. Future versions will trigger an upgrade
|
|
113
|
+
* transaction that migrates records into the new shape.
|
|
114
|
+
*
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
export declare function indexedDbKeyStore(opts?: IndexedDbKeyStoreOptions): AithosKeyStore;
|
|
118
|
+
/**
|
|
119
|
+
* Pick a sensible default: {@link indexedDbKeyStore} when an IDBFactory
|
|
120
|
+
* is reachable (browser environments), {@link memoryKeyStore} otherwise
|
|
121
|
+
* (Node, edge runtimes — apps running there should pass their own
|
|
122
|
+
* keystore explicitly).
|
|
123
|
+
*
|
|
124
|
+
* @public
|
|
125
|
+
*/
|
|
126
|
+
export declare function defaultKeyStore(): AithosKeyStore;
|
|
127
|
+
export {};
|
|
128
|
+
//# sourceMappingURL=key-store.d.ts.map
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
/* -------------------------------------------------------------------------- */
|
|
4
|
+
/* In-memory implementation */
|
|
5
|
+
/* -------------------------------------------------------------------------- */
|
|
6
|
+
/**
|
|
7
|
+
* In-memory key store. Loses everything on page reload — useful for
|
|
8
|
+
* tests, SSR, ephemeral CLI tools, and any workflow where you want a
|
|
9
|
+
* deliberately short-lived session.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export function memoryKeyStore() {
|
|
14
|
+
let owner = null;
|
|
15
|
+
const delegates = new Map();
|
|
16
|
+
return {
|
|
17
|
+
async loadOwner() {
|
|
18
|
+
return owner;
|
|
19
|
+
},
|
|
20
|
+
async saveOwner(o) {
|
|
21
|
+
owner = o;
|
|
22
|
+
},
|
|
23
|
+
async clearOwner() {
|
|
24
|
+
owner = null;
|
|
25
|
+
},
|
|
26
|
+
async listDelegates() {
|
|
27
|
+
return [...delegates.values()];
|
|
28
|
+
},
|
|
29
|
+
async loadDelegate(mandateId) {
|
|
30
|
+
return delegates.get(mandateId) ?? null;
|
|
31
|
+
},
|
|
32
|
+
async saveDelegate(d) {
|
|
33
|
+
delegates.set(d.mandateId, d);
|
|
34
|
+
},
|
|
35
|
+
async removeDelegate(mandateId) {
|
|
36
|
+
delegates.delete(mandateId);
|
|
37
|
+
},
|
|
38
|
+
async clearAllDelegates() {
|
|
39
|
+
delegates.clear();
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/* -------------------------------------------------------------------------- */
|
|
44
|
+
/* IndexedDB implementation */
|
|
45
|
+
/* -------------------------------------------------------------------------- */
|
|
46
|
+
/**
|
|
47
|
+
* Default IndexedDB database name used by {@link indexedDbKeyStore}.
|
|
48
|
+
* Apps that want to coexist with other Aithos-aware libs (or scope
|
|
49
|
+
* sessions per-tenant) can pass a custom `dbName`.
|
|
50
|
+
*/
|
|
51
|
+
export const DEFAULT_KEYSTORE_DB_NAME = "aithos-sdk-keys";
|
|
52
|
+
const STORE_OWNER = "owner";
|
|
53
|
+
const STORE_DELEGATES = "delegates";
|
|
54
|
+
/** The single owner record always lives at this key — the store has no keyPath. */
|
|
55
|
+
const OWNER_KEY = "self";
|
|
56
|
+
/**
|
|
57
|
+
* IndexedDB-backed key store. Default in browser environments —
|
|
58
|
+
* persists across reloads and browser restarts, scoped to the
|
|
59
|
+
* page's origin.
|
|
60
|
+
*
|
|
61
|
+
* Storage shape today:
|
|
62
|
+
*
|
|
63
|
+
* - object store `owner` — single record at key `"self"`,
|
|
64
|
+
* shape {@link StoredOwnerKeys}
|
|
65
|
+
* - object store `delegates` — keyPath `mandateId`, shape
|
|
66
|
+
* {@link StoredDelegateKeys}
|
|
67
|
+
*
|
|
68
|
+
* Both stores live in DB `aithos-sdk-keys` (configurable via
|
|
69
|
+
* `dbName`) at version 1. Future versions will trigger an upgrade
|
|
70
|
+
* transaction that migrates records into the new shape.
|
|
71
|
+
*
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
export function indexedDbKeyStore(opts = {}) {
|
|
75
|
+
const dbName = opts.dbName ?? DEFAULT_KEYSTORE_DB_NAME;
|
|
76
|
+
const factory = opts.factory ??
|
|
77
|
+
(typeof indexedDB !== "undefined" ? indexedDB : undefined);
|
|
78
|
+
if (!factory) {
|
|
79
|
+
throw new Error("indexedDbKeyStore: no IDBFactory available — pass `factory` for non-browser environments or use memoryKeyStore() instead.");
|
|
80
|
+
}
|
|
81
|
+
const open = () => new Promise((resolve, reject) => {
|
|
82
|
+
const req = factory.open(dbName, 1);
|
|
83
|
+
req.onupgradeneeded = () => {
|
|
84
|
+
const db = req.result;
|
|
85
|
+
if (!db.objectStoreNames.contains(STORE_OWNER)) {
|
|
86
|
+
db.createObjectStore(STORE_OWNER);
|
|
87
|
+
}
|
|
88
|
+
if (!db.objectStoreNames.contains(STORE_DELEGATES)) {
|
|
89
|
+
db.createObjectStore(STORE_DELEGATES, { keyPath: "mandateId" });
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
req.onsuccess = () => resolve(req.result);
|
|
93
|
+
req.onerror = () => reject(req.error ?? new Error("indexedDB.open failed"));
|
|
94
|
+
});
|
|
95
|
+
const tx = async (stores, mode, run) => {
|
|
96
|
+
const db = await open();
|
|
97
|
+
try {
|
|
98
|
+
const t = db.transaction([...stores], mode);
|
|
99
|
+
const result = await Promise.resolve(run(t));
|
|
100
|
+
await new Promise((resolve, reject) => {
|
|
101
|
+
t.oncomplete = () => resolve();
|
|
102
|
+
t.onerror = () => reject(t.error ?? new Error("transaction failed"));
|
|
103
|
+
t.onabort = () => reject(t.error ?? new Error("transaction aborted"));
|
|
104
|
+
});
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
db.close();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const reqAsPromise = (req) => new Promise((resolve, reject) => {
|
|
112
|
+
req.onsuccess = () => resolve(req.result);
|
|
113
|
+
req.onerror = () => reject(req.error ?? new Error("IDBRequest failed"));
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
async loadOwner() {
|
|
117
|
+
return tx([STORE_OWNER], "readonly", async (t) => {
|
|
118
|
+
const v = await reqAsPromise(t.objectStore(STORE_OWNER).get(OWNER_KEY));
|
|
119
|
+
return validOwnerOrNull(v);
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
async saveOwner(owner) {
|
|
123
|
+
await tx([STORE_OWNER], "readwrite", (t) => {
|
|
124
|
+
t.objectStore(STORE_OWNER).put(owner, OWNER_KEY);
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
async clearOwner() {
|
|
128
|
+
await tx([STORE_OWNER], "readwrite", (t) => {
|
|
129
|
+
t.objectStore(STORE_OWNER).delete(OWNER_KEY);
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
async listDelegates() {
|
|
133
|
+
return tx([STORE_DELEGATES], "readonly", async (t) => {
|
|
134
|
+
const all = await reqAsPromise(t.objectStore(STORE_DELEGATES).getAll());
|
|
135
|
+
return all
|
|
136
|
+
.map(validDelegateOrNull)
|
|
137
|
+
.filter((d) => d !== null);
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
async loadDelegate(mandateId) {
|
|
141
|
+
return tx([STORE_DELEGATES], "readonly", async (t) => {
|
|
142
|
+
const v = await reqAsPromise(t.objectStore(STORE_DELEGATES).get(mandateId));
|
|
143
|
+
return validDelegateOrNull(v);
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
async saveDelegate(d) {
|
|
147
|
+
await tx([STORE_DELEGATES], "readwrite", (t) => {
|
|
148
|
+
t.objectStore(STORE_DELEGATES).put(d);
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
async removeDelegate(mandateId) {
|
|
152
|
+
await tx([STORE_DELEGATES], "readwrite", (t) => {
|
|
153
|
+
t.objectStore(STORE_DELEGATES).delete(mandateId);
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
async clearAllDelegates() {
|
|
157
|
+
await tx([STORE_DELEGATES], "readwrite", (t) => {
|
|
158
|
+
t.objectStore(STORE_DELEGATES).clear();
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/* -------------------------------------------------------------------------- */
|
|
164
|
+
/* Default picker */
|
|
165
|
+
/* -------------------------------------------------------------------------- */
|
|
166
|
+
/**
|
|
167
|
+
* Pick a sensible default: {@link indexedDbKeyStore} when an IDBFactory
|
|
168
|
+
* is reachable (browser environments), {@link memoryKeyStore} otherwise
|
|
169
|
+
* (Node, edge runtimes — apps running there should pass their own
|
|
170
|
+
* keystore explicitly).
|
|
171
|
+
*
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
export function defaultKeyStore() {
|
|
175
|
+
if (typeof indexedDB !== "undefined") {
|
|
176
|
+
try {
|
|
177
|
+
return indexedDbKeyStore();
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return memoryKeyStore();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return memoryKeyStore();
|
|
184
|
+
}
|
|
185
|
+
/* -------------------------------------------------------------------------- */
|
|
186
|
+
/* Runtime validators */
|
|
187
|
+
/* */
|
|
188
|
+
/* Storage values come from JSON-shaped records that may have been written */
|
|
189
|
+
/* by an older SDK version, by a corrupted process, or by an attacker with */
|
|
190
|
+
/* IDB write access. The SDK trusts only records that round-trip through */
|
|
191
|
+
/* these validators; anything else is treated as "no record" so the resume */
|
|
192
|
+
/* path falls through to re-auth. */
|
|
193
|
+
/* -------------------------------------------------------------------------- */
|
|
194
|
+
function validOwnerOrNull(v) {
|
|
195
|
+
if (typeof v !== "object" || v === null)
|
|
196
|
+
return null;
|
|
197
|
+
const o = v;
|
|
198
|
+
if (o["version"] !== "0.1.0-hex")
|
|
199
|
+
return null;
|
|
200
|
+
if (typeof o["did"] !== "string")
|
|
201
|
+
return null;
|
|
202
|
+
if (typeof o["handle"] !== "string")
|
|
203
|
+
return null;
|
|
204
|
+
if (typeof o["displayName"] !== "string")
|
|
205
|
+
return null;
|
|
206
|
+
const seeds = o["seedsHex"];
|
|
207
|
+
if (typeof seeds !== "object" || seeds === null)
|
|
208
|
+
return null;
|
|
209
|
+
const s = seeds;
|
|
210
|
+
for (const k of ["root", "public", "circle", "self"]) {
|
|
211
|
+
if (typeof s[k] !== "string")
|
|
212
|
+
return null;
|
|
213
|
+
if (s[k].length !== 64)
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
if (typeof o["savedAt"] !== "string")
|
|
217
|
+
return null;
|
|
218
|
+
return o;
|
|
219
|
+
}
|
|
220
|
+
function validDelegateOrNull(v) {
|
|
221
|
+
if (typeof v !== "object" || v === null)
|
|
222
|
+
return null;
|
|
223
|
+
const o = v;
|
|
224
|
+
if (o["version"] !== "0.1.0-hex")
|
|
225
|
+
return null;
|
|
226
|
+
if (typeof o["subjectDid"] !== "string")
|
|
227
|
+
return null;
|
|
228
|
+
if (typeof o["mandateId"] !== "string")
|
|
229
|
+
return null;
|
|
230
|
+
if (typeof o["granteeId"] !== "string")
|
|
231
|
+
return null;
|
|
232
|
+
if (typeof o["granteePubkeyMultibase"] !== "string")
|
|
233
|
+
return null;
|
|
234
|
+
if (typeof o["delegateSeedHex"] !== "string")
|
|
235
|
+
return null;
|
|
236
|
+
if (o["delegateSeedHex"].length !== 64)
|
|
237
|
+
return null;
|
|
238
|
+
if (typeof o["mandate"] !== "object" || o["mandate"] === null)
|
|
239
|
+
return null;
|
|
240
|
+
if (typeof o["importedAt"] !== "string")
|
|
241
|
+
return null;
|
|
242
|
+
return o;
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=key-store.js.map
|
package/dist/src/mandates.d.ts
CHANGED
|
@@ -1,2 +1,164 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AithosAuth } from "./auth.js";
|
|
2
|
+
import type { AithosSdkEndpoints } from "./endpoints.js";
|
|
3
|
+
/** Capability scope the SDK accepts. Server-side ultimately decides.
|
|
4
|
+
*
|
|
5
|
+
* Note: `compute.invoke` is intentionally NOT in this union. The token-
|
|
6
|
+
* spending capability is opt-in via the dedicated {@link CreateMandateInput.compute}
|
|
7
|
+
* namespace — see {@link MandatesNamespace.create}. Passing `compute.invoke`
|
|
8
|
+
* directly in `scopes` is rejected at runtime; the compiler can't enforce
|
|
9
|
+
* it (callers who up-cast to string[] would slip through), so the runtime
|
|
10
|
+
* check is the real gate. */
|
|
11
|
+
export type Scope = "ethos.read.public" | "ethos.read.circle" | "ethos.read.self" | "ethos.write.public" | "ethos.write.circle" | "ethos.write.self";
|
|
12
|
+
/**
|
|
13
|
+
* The opt-in scope that authorizes a delegate to spend the subject's
|
|
14
|
+
* compute credits via the Aithos compute proxy. Mirror of
|
|
15
|
+
* `COMPUTE_INVOKE_SCOPE` in `@aithos/protocol-core` v0.4.0.
|
|
16
|
+
*
|
|
17
|
+
* The SDK's `mandates.create()` injects this scope automatically when
|
|
18
|
+
* the caller passes a `compute` namespace, and refuses to mint a
|
|
19
|
+
* mandate where the caller put it directly into `scopes` — this is
|
|
20
|
+
* what makes "compute is a separate, conscious decision" hold at the
|
|
21
|
+
* API surface.
|
|
22
|
+
*/
|
|
23
|
+
export declare const COMPUTE_INVOKE_SCOPE: "compute.invoke";
|
|
24
|
+
/**
|
|
25
|
+
* Which sphere of the owner signs the mandate. Bounds the upper-most
|
|
26
|
+
* scope set the mandate can carry.
|
|
27
|
+
*/
|
|
28
|
+
export type ActorSphere = "public" | "circle" | "self";
|
|
29
|
+
/**
|
|
30
|
+
* Compute-spending capability — opt-in only, never implied by ethos
|
|
31
|
+
* scopes.
|
|
32
|
+
*
|
|
33
|
+
* When `compute` is set on {@link CreateMandateInput}, the SDK:
|
|
34
|
+
* 1. Adds the `compute.invoke` scope to the minted mandate.
|
|
35
|
+
* 2. Maps the caller's caps onto `constraints.compute` in the
|
|
36
|
+
* protocol's snake_case shape (= what the verifier reads).
|
|
37
|
+
* 3. Forbids the caller from passing `compute.invoke` in `scopes`
|
|
38
|
+
* directly — that would let an app slip the scope past a
|
|
39
|
+
* consent UI that only reviews `compute`.
|
|
40
|
+
*
|
|
41
|
+
* At least one of `dailyCapMicrocredits` or `totalCapMicrocredits` MUST
|
|
42
|
+
* be set: an unbounded compute mandate is the kind of bearer-token
|
|
43
|
+
* footgun this whole namespace exists to prevent. Validation happens
|
|
44
|
+
* at the SDK boundary (here) AND at the protocol layer (the
|
|
45
|
+
* server-side verifier rejects capless 0.4.0 mandates), so a bug in
|
|
46
|
+
* either tier still fails closed.
|
|
47
|
+
*
|
|
48
|
+
* `maxCreditsPerCall` is a per-invocation safety net for runaway
|
|
49
|
+
* single requests. `allowedModels`, when set, restricts which Bedrock
|
|
50
|
+
* model ids the delegate may target (the proxy's own allowlist still
|
|
51
|
+
* applies on top).
|
|
52
|
+
*/
|
|
53
|
+
export interface CreateMandateComputeInput {
|
|
54
|
+
/** Hard cap on credits debited per UTC day under this mandate. */
|
|
55
|
+
readonly dailyCapMicrocredits?: number;
|
|
56
|
+
/** Hard cap on credits debited over the whole mandate lifetime. */
|
|
57
|
+
readonly totalCapMicrocredits?: number;
|
|
58
|
+
/** Hard cap on credits debited by any single invocation. */
|
|
59
|
+
readonly maxCreditsPerCall?: number;
|
|
60
|
+
/** Allowlist of Bedrock model ids the delegate may invoke. */
|
|
61
|
+
readonly allowedModels?: readonly string[];
|
|
62
|
+
}
|
|
63
|
+
export interface CreateMandateInput {
|
|
64
|
+
/** Grantee URN — usually `urn:aithos:agent:<extension-id>` or similar. */
|
|
65
|
+
readonly granteeId: string;
|
|
66
|
+
/** Optional human-readable label for the grantee. */
|
|
67
|
+
readonly granteeLabel?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Sphere of the owner that issues the mandate. Defaults to the
|
|
70
|
+
* highest-numbered sphere covered by `scopes` (most permissive
|
|
71
|
+
* common ancestor): `"self"` if any scope ends in `.self`, else
|
|
72
|
+
* `"circle"` if any ends in `.circle`, else `"public"`.
|
|
73
|
+
*/
|
|
74
|
+
readonly actorSphere?: ActorSphere;
|
|
75
|
+
/** Capability set granted by the mandate. */
|
|
76
|
+
readonly scopes: readonly Scope[];
|
|
77
|
+
/** Lifetime in seconds. */
|
|
78
|
+
readonly ttlSeconds: number;
|
|
79
|
+
/**
|
|
80
|
+
* Opt-in compute (token-spending) capability — adds the
|
|
81
|
+
* `compute.invoke` scope and a bounded `constraints.compute` budget
|
|
82
|
+
* to the mandate. See {@link CreateMandateComputeInput}.
|
|
83
|
+
*
|
|
84
|
+
* NEVER add `compute.invoke` to `scopes` directly — the SDK rejects
|
|
85
|
+
* that path so the caller has to pass through this typed namespace,
|
|
86
|
+
* which is what a consent UI can review.
|
|
87
|
+
*/
|
|
88
|
+
readonly compute?: CreateMandateComputeInput;
|
|
89
|
+
/**
|
|
90
|
+
* When the mandate becomes valid. Optional — when omitted, the
|
|
91
|
+
* underlying mint helper signs with `not_before = now - 30s` (see
|
|
92
|
+
* `MANDATE_NOTBEFORE_OFFSET_SECONDS_DEFAULT` in
|
|
93
|
+
* `@aithos/protocol-client`) so a server whose clock runs slightly
|
|
94
|
+
* behind the client doesn't reject the freshly-minted mandate as
|
|
95
|
+
* `not yet valid`.
|
|
96
|
+
*
|
|
97
|
+
* Pass an explicit `Date` only for advanced flows (delayed-activation
|
|
98
|
+
* mandates, deterministic tests).
|
|
99
|
+
*/
|
|
100
|
+
readonly notBefore?: Date;
|
|
101
|
+
}
|
|
102
|
+
export interface MintedMandate {
|
|
103
|
+
/** Unique mandate id (matches `mandate.id` inside the bundle). */
|
|
104
|
+
readonly mandateId: string;
|
|
105
|
+
/** Subject DID — the owner who issued it. */
|
|
106
|
+
readonly subjectDid: string;
|
|
107
|
+
/** Grantee URN. */
|
|
108
|
+
readonly granteeId: string;
|
|
109
|
+
readonly scopes: readonly Scope[];
|
|
110
|
+
/** ISO-8601 (UTC) — `null` if the mandate has no `not_after`. */
|
|
111
|
+
readonly expiresAt: string | null;
|
|
112
|
+
/** Shareable `.aithos-delegate.json` Blob. Hand this to the grantee. */
|
|
113
|
+
readonly bundle: Blob;
|
|
114
|
+
/** Suggested filename for the bundle. */
|
|
115
|
+
readonly filename: string;
|
|
116
|
+
}
|
|
117
|
+
export interface OwnedMandate {
|
|
118
|
+
readonly mandateId: string;
|
|
119
|
+
readonly issuerDid: string;
|
|
120
|
+
readonly actorDid: string;
|
|
121
|
+
readonly scopes: readonly Scope[];
|
|
122
|
+
readonly notBefore: number | null;
|
|
123
|
+
readonly notAfter: number | null;
|
|
124
|
+
readonly createdAt: number;
|
|
125
|
+
}
|
|
126
|
+
export interface MandatesNamespaceDeps {
|
|
127
|
+
readonly auth: AithosAuth;
|
|
128
|
+
readonly endpoints: AithosSdkEndpoints;
|
|
129
|
+
readonly fetch: typeof fetch;
|
|
130
|
+
}
|
|
131
|
+
export declare class MandatesNamespace {
|
|
132
|
+
#private;
|
|
133
|
+
constructor(deps: MandatesNamespaceDeps);
|
|
134
|
+
/**
|
|
135
|
+
* Mint, sign, publish, and package a fresh delegate bundle. The
|
|
136
|
+
* grantee's keypair is generated inside this call and never
|
|
137
|
+
* persisted on the owner's machine — the seed flows out via the
|
|
138
|
+
* returned Blob and only via that Blob.
|
|
139
|
+
*/
|
|
140
|
+
create(input: CreateMandateInput): Promise<MintedMandate>;
|
|
141
|
+
/**
|
|
142
|
+
* List mandates issued by the signed-in owner. Pages through
|
|
143
|
+
* `aithos.list_mandates` until exhausted (or until 5 pages have
|
|
144
|
+
* been crawled — an owner with more than 1000 active mandates is
|
|
145
|
+
* out of scope today).
|
|
146
|
+
*/
|
|
147
|
+
list(): Promise<readonly OwnedMandate[]>;
|
|
148
|
+
/**
|
|
149
|
+
* Publish a §4.2 revocation for `mandateId`. The mandate stops
|
|
150
|
+
* authorizing future actions (artifacts dated before `revoked_at`
|
|
151
|
+
* remain valid — revocation is not retroactive).
|
|
152
|
+
*
|
|
153
|
+
* Server-side: handled by `aithos.publish_revocation`. The envelope
|
|
154
|
+
* is signed by the owner's `#public` sphere — the spec also accepts
|
|
155
|
+
* `#root`, but `#public` is what the existing app does.
|
|
156
|
+
*
|
|
157
|
+
* Throws {@link AithosSDKError} on backend errors. Note that
|
|
158
|
+
* server-side support is in-flight; this method may surface a
|
|
159
|
+
* `mandates_-32601` (method not found) until the auth platform
|
|
160
|
+
* lands the corresponding write handler.
|
|
161
|
+
*/
|
|
162
|
+
revoke(mandateId: string): Promise<void>;
|
|
163
|
+
}
|
|
2
164
|
//# sourceMappingURL=mandates.d.ts.map
|