@frockbot/kernel-contracts 0.1.2 → 0.1.4
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/package.json +1 -1
- package/src/isolate.test.ts +6 -11
- package/src/isolate.ts +11 -14
package/package.json
CHANGED
package/src/isolate.test.ts
CHANGED
|
@@ -368,38 +368,34 @@ describe("isolate capability failure v1", () => {
|
|
|
368
368
|
});
|
|
369
369
|
|
|
370
370
|
describe("isolate loader identity", () => {
|
|
371
|
-
test("is the
|
|
371
|
+
test("is the User and the content address — nothing else", () => {
|
|
372
372
|
expect(
|
|
373
373
|
isolateLoaderIdV1({
|
|
374
374
|
userId: "user-1",
|
|
375
|
-
botId: "bot-1",
|
|
376
375
|
artifactSetHash: "a".repeat(64),
|
|
377
376
|
}),
|
|
378
|
-
).toBe(`bot-package:user-1
|
|
377
|
+
).toBe(`bot-package:user-1:${"a".repeat(64)}`);
|
|
379
378
|
});
|
|
380
379
|
|
|
381
|
-
test("two
|
|
380
|
+
test("two Users never share an id", () => {
|
|
382
381
|
const hash = "b".repeat(64);
|
|
383
382
|
expect(
|
|
384
383
|
isolateLoaderIdV1({
|
|
385
384
|
userId: "user-1",
|
|
386
|
-
botId: "bot-1",
|
|
387
385
|
artifactSetHash: hash,
|
|
388
386
|
}),
|
|
389
387
|
).not.toBe(
|
|
390
388
|
isolateLoaderIdV1({
|
|
391
|
-
userId: "user-
|
|
392
|
-
botId: "bot-2",
|
|
389
|
+
userId: "user-2",
|
|
393
390
|
artifactSetHash: hash,
|
|
394
391
|
}),
|
|
395
392
|
);
|
|
396
393
|
});
|
|
397
394
|
|
|
398
|
-
test("rejects a component that could forge another
|
|
395
|
+
test("rejects a component that could forge another User's id", () => {
|
|
399
396
|
expect(() =>
|
|
400
397
|
isolateLoaderIdV1({
|
|
401
|
-
userId: "user-1:
|
|
402
|
-
botId: "bot-1",
|
|
398
|
+
userId: "user-1:other",
|
|
403
399
|
artifactSetHash: "c".repeat(64),
|
|
404
400
|
}),
|
|
405
401
|
).toThrow(/components are invalid/);
|
|
@@ -409,7 +405,6 @@ describe("isolate loader identity", () => {
|
|
|
409
405
|
expect(() =>
|
|
410
406
|
isolateLoaderIdV1({
|
|
411
407
|
userId: "user-1",
|
|
412
|
-
botId: "bot-1",
|
|
413
408
|
artifactSetHash: "not-a-hash",
|
|
414
409
|
}),
|
|
415
410
|
).toThrow(/components are invalid/);
|
package/src/isolate.ts
CHANGED
|
@@ -125,7 +125,7 @@ export type IsolateCapabilityListOutcomeV1 =
|
|
|
125
125
|
IsolateCapabilityDescriptorV1[] | IsolateCapabilityFailureV1;
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
* D6: model invocation as an
|
|
128
|
+
* D6: model invocation as an enabled-capability binding. Events cross the RPC
|
|
129
129
|
* boundary as an NDJSON byte stream — see `decodeIsolateModelEventV1`. A
|
|
130
130
|
* `ReadableStream` of JavaScript objects is not transferable over workerd RPC;
|
|
131
131
|
* a byte stream is, so the kernel encodes and the isolate decodes.
|
|
@@ -152,7 +152,7 @@ export interface BotIsolateEntrypoint {
|
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
154
|
* The loopback service binding the Bot's Durable Object mints for one isolate.
|
|
155
|
-
* Every method
|
|
155
|
+
* Every method derives from enabled capabilities: nothing here can hand out authority the
|
|
156
156
|
* Bot does not already hold.
|
|
157
157
|
*/
|
|
158
158
|
export interface BotCapabilitiesStub {
|
|
@@ -160,7 +160,7 @@ export interface BotCapabilitiesStub {
|
|
|
160
160
|
/**
|
|
161
161
|
* D6 addendum. The kernel records the normalized request and acquires the
|
|
162
162
|
* credential lease through the existing provider path *before* forwarding.
|
|
163
|
-
* Without a matching enabled model
|
|
163
|
+
* Without a matching enabled model capability the answer is a pending
|
|
164
164
|
* decision, never a grant.
|
|
165
165
|
*/
|
|
166
166
|
invokeModel(request: NormalizedModelRequest): Promise<IsolateModelOutcomeV1>;
|
|
@@ -198,30 +198,27 @@ export interface IsolateHost {
|
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
200
|
* D2. The loader identity, and nothing else — a reused id silently serves the
|
|
201
|
-
* first code
|
|
202
|
-
* covers the
|
|
203
|
-
*
|
|
201
|
+
* first code and `env`, so every component here is content- or owner-derived.
|
|
202
|
+
* The hash covers the mounted wrapper and Package artifact plus the digest of
|
|
203
|
+
* every baked-in binding: User, Bot, Composition generation, and enabled set.
|
|
204
|
+
* Identical artifacts reuse an isolate only under identical authority; the
|
|
205
|
+
* User prefix independently prevents cross-User reuse (AGENTS.md Package
|
|
206
|
+
* composition; ADR 0019).
|
|
204
207
|
*/
|
|
205
208
|
export function isolateLoaderIdV1(input: {
|
|
206
209
|
userId: string;
|
|
207
|
-
botId: string;
|
|
208
210
|
artifactSetHash: string;
|
|
209
211
|
}): string {
|
|
210
212
|
const userId = boundedString(input.userId, "isolate loader userId", 256);
|
|
211
|
-
const botId = boundedString(input.botId, "isolate loader botId", 256);
|
|
212
213
|
const hash = boundedString(
|
|
213
214
|
input.artifactSetHash,
|
|
214
215
|
"isolate loader artifactSetHash",
|
|
215
216
|
128,
|
|
216
217
|
);
|
|
217
|
-
if (
|
|
218
|
-
/[:\s]/.test(userId) ||
|
|
219
|
-
/[:\s]/.test(botId) ||
|
|
220
|
-
!/^[0-9a-f]+$/.test(hash)
|
|
221
|
-
) {
|
|
218
|
+
if (/[:\s]/.test(userId) || !/^[0-9a-f]+$/.test(hash)) {
|
|
222
219
|
throw new Error("isolate loader id components are invalid");
|
|
223
220
|
}
|
|
224
|
-
return `bot-package:${userId}:${
|
|
221
|
+
return `bot-package:${userId}:${hash}`;
|
|
225
222
|
}
|
|
226
223
|
|
|
227
224
|
function record(value: unknown, label: string): Record<string, unknown> {
|