@danypops/vehicle-conformance 0.4.2 → 0.4.3
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.
|
@@ -48,6 +48,18 @@ const ConformanceKeyed = defineVehicleOperation({
|
|
|
48
48
|
output: outputSchema,
|
|
49
49
|
permissions: [],
|
|
50
50
|
effect: "external-write",
|
|
51
|
+
requiresApproval: false,
|
|
52
|
+
idempotency: { mode: "keyed", retentionMs: 60_000 },
|
|
53
|
+
limits: LIMITS,
|
|
54
|
+
});
|
|
55
|
+
const ConformanceUnconfiguredRisk = defineVehicleOperation({
|
|
56
|
+
name: "conformance.unconfigured-risk",
|
|
57
|
+
version: 1,
|
|
58
|
+
description: "Proves that risky operations require an explicit registry approval-policy decision.",
|
|
59
|
+
input: passthroughSchema,
|
|
60
|
+
output: outputSchema,
|
|
61
|
+
permissions: [],
|
|
62
|
+
effect: "external-write",
|
|
51
63
|
idempotency: { mode: "keyed", retentionMs: 60_000 },
|
|
52
64
|
limits: LIMITS,
|
|
53
65
|
});
|
|
@@ -94,6 +106,7 @@ export function registerConformanceOperations(registry) {
|
|
|
94
106
|
throw new VehicleError("conformance-boom", "conformance.boom always fails", { category: "internal" });
|
|
95
107
|
}));
|
|
96
108
|
registry.register("conformance", bindVehicleOperation(ConformanceKeyed, () => async (context) => ({ echoed: context.input.value })));
|
|
109
|
+
registry.register("conformance", bindVehicleOperation(ConformanceUnconfiguredRisk, () => async (context) => ({ echoed: context.input.value })));
|
|
97
110
|
registry.register("conformance", bindVehicleOperation(ConformanceProgress, () => async (context) => {
|
|
98
111
|
context.reportProgress({ step: 1 });
|
|
99
112
|
context.reportProgress({ step: 2 });
|
|
@@ -127,6 +140,7 @@ export function registerVehicleClientConformance(runner, fixture) {
|
|
|
127
140
|
"conformance.never@1",
|
|
128
141
|
"conformance.progress@1",
|
|
129
142
|
"conformance.slow-progress@1",
|
|
143
|
+
"conformance.unconfigured-risk@1",
|
|
130
144
|
]);
|
|
131
145
|
const echo = manifest.operations.find((op) => op.name === "conformance.echo");
|
|
132
146
|
expect(echo?.permissions).toEqual(["conformance:echo"]);
|
|
@@ -211,6 +225,20 @@ export function registerVehicleClientConformance(runner, fixture) {
|
|
|
211
225
|
await cleanup();
|
|
212
226
|
}
|
|
213
227
|
});
|
|
228
|
+
it("reports an unconfigured risky operation as a hard failure", async () => {
|
|
229
|
+
const { client, cleanup } = await fixture.create();
|
|
230
|
+
try {
|
|
231
|
+
const manifest = await client.manifest();
|
|
232
|
+
expect(manifest.approvalPolicy).toMatchObject({
|
|
233
|
+
status: "unconfigured",
|
|
234
|
+
unconfiguredRiskyOperations: ["conformance.unconfigured-risk@1"],
|
|
235
|
+
});
|
|
236
|
+
await expect(client.invoke("conformance.unconfigured-risk", 1, { value: "x" }, { idempotencyKey: "risk-1" })).rejects.toMatchObject({ code: "approval-policy-unconfigured", category: "authorization" });
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
await cleanup();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
214
242
|
it("invoke() rejects a request exceeding its declared byte bound", async () => {
|
|
215
243
|
const { client, cleanup } = await fixture.create();
|
|
216
244
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/vehicle-conformance",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Runner-neutral conformance suite for VehicleClient implementations, with Bun and Vitest adapters over one shared assertion matrix.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"typecheck": "tsc --noEmit"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@danypops/vehicle-core": "^0.19.
|
|
30
|
-
"@danypops/vehicle-server": "^0.27.
|
|
29
|
+
"@danypops/vehicle-core": "^0.19.2",
|
|
30
|
+
"@danypops/vehicle-server": "^0.27.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@danypops/vehicle-client": "^0.10.8",
|
|
@@ -100,6 +100,19 @@ const ConformanceKeyed = defineVehicleOperation({
|
|
|
100
100
|
output: outputSchema,
|
|
101
101
|
permissions: [],
|
|
102
102
|
effect: "external-write",
|
|
103
|
+
requiresApproval: false,
|
|
104
|
+
idempotency: { mode: "keyed", retentionMs: 60_000 },
|
|
105
|
+
limits: LIMITS,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const ConformanceUnconfiguredRisk = defineVehicleOperation({
|
|
109
|
+
name: "conformance.unconfigured-risk",
|
|
110
|
+
version: 1,
|
|
111
|
+
description: "Proves that risky operations require an explicit registry approval-policy decision.",
|
|
112
|
+
input: passthroughSchema,
|
|
113
|
+
output: outputSchema,
|
|
114
|
+
permissions: [],
|
|
115
|
+
effect: "external-write",
|
|
103
116
|
idempotency: { mode: "keyed", retentionMs: 60_000 },
|
|
104
117
|
limits: LIMITS,
|
|
105
118
|
});
|
|
@@ -160,6 +173,10 @@ export function registerConformanceOperations(registry: VehicleRegistry): void {
|
|
|
160
173
|
"conformance",
|
|
161
174
|
bindVehicleOperation(ConformanceKeyed, () => async (context) => ({ echoed: context.input.value })),
|
|
162
175
|
);
|
|
176
|
+
registry.register(
|
|
177
|
+
"conformance",
|
|
178
|
+
bindVehicleOperation(ConformanceUnconfiguredRisk, () => async (context) => ({ echoed: context.input.value })),
|
|
179
|
+
);
|
|
163
180
|
registry.register(
|
|
164
181
|
"conformance",
|
|
165
182
|
bindVehicleOperation(ConformanceProgress, () => async (context) => {
|
|
@@ -211,6 +228,7 @@ export function registerVehicleClientConformance(runner: VehicleConformanceRunne
|
|
|
211
228
|
"conformance.never@1",
|
|
212
229
|
"conformance.progress@1",
|
|
213
230
|
"conformance.slow-progress@1",
|
|
231
|
+
"conformance.unconfigured-risk@1",
|
|
214
232
|
]);
|
|
215
233
|
const echo = manifest.operations.find((op) => op.name === "conformance.echo");
|
|
216
234
|
expect(echo?.permissions).toEqual(["conformance:echo"]);
|
|
@@ -303,6 +321,22 @@ export function registerVehicleClientConformance(runner: VehicleConformanceRunne
|
|
|
303
321
|
}
|
|
304
322
|
});
|
|
305
323
|
|
|
324
|
+
it("reports an unconfigured risky operation as a hard failure", async () => {
|
|
325
|
+
const { client, cleanup } = await fixture.create();
|
|
326
|
+
try {
|
|
327
|
+
const manifest = await client.manifest();
|
|
328
|
+
expect(manifest.approvalPolicy).toMatchObject({
|
|
329
|
+
status: "unconfigured",
|
|
330
|
+
unconfiguredRiskyOperations: ["conformance.unconfigured-risk@1"],
|
|
331
|
+
});
|
|
332
|
+
await expect(client.invoke("conformance.unconfigured-risk", 1, { value: "x" }, { idempotencyKey: "risk-1" })).rejects.toMatchObject(
|
|
333
|
+
{ code: "approval-policy-unconfigured", category: "authorization" },
|
|
334
|
+
);
|
|
335
|
+
} finally {
|
|
336
|
+
await cleanup();
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
306
340
|
it("invoke() rejects a request exceeding its declared byte bound", async () => {
|
|
307
341
|
const { client, cleanup } = await fixture.create();
|
|
308
342
|
try {
|