@brainervirus/workit-cursor 2.1.3 → 2.1.5
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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +1126 -889
- package/dist/mcp-server.js +10129 -13299
- package/dist/workit-hook.js +1132 -881
- package/package.json +3 -3
package/dist/workit-hook.js
CHANGED
|
@@ -23,18 +23,23 @@ function jsonStringifyReplacer(_, value) {
|
|
|
23
23
|
return value.toString();
|
|
24
24
|
return value;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
|
|
27
|
+
class Cached {
|
|
28
|
+
constructor(getter) {
|
|
29
|
+
this._getter = getter;
|
|
30
|
+
this._value = undefined;
|
|
31
|
+
}
|
|
32
|
+
get value() {
|
|
33
|
+
const getter = this._getter;
|
|
34
|
+
if (getter !== undefined) {
|
|
35
|
+
this._value = getter();
|
|
36
|
+
this._getter = undefined;
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
return this._value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function cached(getter) {
|
|
42
|
+
return new Cached(getter);
|
|
38
43
|
}
|
|
39
44
|
function nullish(input) {
|
|
40
45
|
return input === null || input === undefined;
|
|
@@ -60,6 +65,56 @@ function assignProp(target, prop, value) {
|
|
|
60
65
|
configurable: true
|
|
61
66
|
});
|
|
62
67
|
}
|
|
68
|
+
function rawShape(def) {
|
|
69
|
+
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
70
|
+
return desc?.get ? desc.get.raw : desc?.value;
|
|
71
|
+
}
|
|
72
|
+
function sourceShape(schema) {
|
|
73
|
+
return rawShape(schema._zod.def) ?? schema._zod.def.shape;
|
|
74
|
+
}
|
|
75
|
+
function deferProp(target, key, getter) {
|
|
76
|
+
Object.defineProperty(target, key, {
|
|
77
|
+
get() {
|
|
78
|
+
const value = getter();
|
|
79
|
+
assignProp(this, key, value);
|
|
80
|
+
return value;
|
|
81
|
+
},
|
|
82
|
+
enumerable: true,
|
|
83
|
+
configurable: true
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function putProp(target, key, value) {
|
|
87
|
+
if (key in target)
|
|
88
|
+
assignProp(target, key, value);
|
|
89
|
+
else
|
|
90
|
+
target[key] = value;
|
|
91
|
+
}
|
|
92
|
+
function mirrorShape(target, source, keys, wrap) {
|
|
93
|
+
const raw = sourceShape(source);
|
|
94
|
+
for (const key of keys) {
|
|
95
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
96
|
+
if (!desc.enumerable)
|
|
97
|
+
continue;
|
|
98
|
+
if (desc.get) {
|
|
99
|
+
deferProp(target, key, () => {
|
|
100
|
+
const value = source._zod.def.shape[key];
|
|
101
|
+
return wrap ? wrap(value, key) : value;
|
|
102
|
+
});
|
|
103
|
+
} else
|
|
104
|
+
putProp(target, key, wrap ? wrap(desc.value, key) : desc.value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function mirrorProps(target, source) {
|
|
108
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
109
|
+
const desc = Object.getOwnPropertyDescriptor(source, key);
|
|
110
|
+
if (!desc.enumerable)
|
|
111
|
+
continue;
|
|
112
|
+
if (desc.get)
|
|
113
|
+
deferProp(target, key, () => source[key]);
|
|
114
|
+
else
|
|
115
|
+
putProp(target, key, desc.value);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
63
118
|
function mergeDefs(...defs) {
|
|
64
119
|
const mergedDescriptors = {};
|
|
65
120
|
for (const def of defs) {
|
|
@@ -165,6 +220,10 @@ var NUMBER_FORMAT_RANGES = /* @__PURE__ */ (() => ({
|
|
|
165
220
|
float32: [-340282346638528860000000000000000000000, 340282346638528860000000000000000000000],
|
|
166
221
|
float64: [-Number.MAX_VALUE, Number.MAX_VALUE]
|
|
167
222
|
}))();
|
|
223
|
+
var BIGINT_FORMAT_RANGES = {
|
|
224
|
+
int64: [/* @__PURE__ */ BigInt("-9223372036854775808"), /* @__PURE__ */ BigInt("9223372036854775807")],
|
|
225
|
+
uint64: [/* @__PURE__ */ BigInt(0), /* @__PURE__ */ BigInt("18446744073709551615")]
|
|
226
|
+
};
|
|
168
227
|
function pick(schema, mask) {
|
|
169
228
|
const currDef = schema._zod.def;
|
|
170
229
|
const checks = currDef.checks;
|
|
@@ -172,23 +231,21 @@ function pick(schema, mask) {
|
|
|
172
231
|
if (hasChecks) {
|
|
173
232
|
throw new Error(".pick() cannot be used on object schemas containing refinements");
|
|
174
233
|
}
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
return clone(schema, def);
|
|
234
|
+
const newShape = {};
|
|
235
|
+
mirrorShape(newShape, schema, maskedKeys(schema, mask));
|
|
236
|
+
return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
|
|
237
|
+
}
|
|
238
|
+
function maskedKeys(schema, mask) {
|
|
239
|
+
const raw = sourceShape(schema);
|
|
240
|
+
const keys = [];
|
|
241
|
+
for (const key of Reflect.ownKeys(mask)) {
|
|
242
|
+
if (!Object.getOwnPropertyDescriptor(raw, key)?.enumerable) {
|
|
243
|
+
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
244
|
+
}
|
|
245
|
+
if (mask[key])
|
|
246
|
+
keys.push(key);
|
|
247
|
+
}
|
|
248
|
+
return keys;
|
|
192
249
|
}
|
|
193
250
|
function omit(schema, mask) {
|
|
194
251
|
const currDef = schema._zod.def;
|
|
@@ -197,23 +254,10 @@ function omit(schema, mask) {
|
|
|
197
254
|
if (hasChecks) {
|
|
198
255
|
throw new Error(".omit() cannot be used on object schemas containing refinements");
|
|
199
256
|
}
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (!Object.prototype.hasOwnProperty.call(currDef.shape, key)) {
|
|
205
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
206
|
-
}
|
|
207
|
-
if (!mask[key])
|
|
208
|
-
continue;
|
|
209
|
-
delete newShape[key];
|
|
210
|
-
}
|
|
211
|
-
assignProp(this, "shape", newShape);
|
|
212
|
-
return newShape;
|
|
213
|
-
},
|
|
214
|
-
checks: []
|
|
215
|
-
});
|
|
216
|
-
return clone(schema, def);
|
|
257
|
+
const omitted = new Set(maskedKeys(schema, mask));
|
|
258
|
+
const newShape = {};
|
|
259
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)).filter((key) => !omitted.has(key)));
|
|
260
|
+
return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
|
|
217
261
|
}
|
|
218
262
|
function extend(schema, shape) {
|
|
219
263
|
if (!isPlainObject(shape)) {
|
|
@@ -222,34 +266,26 @@ function extend(schema, shape) {
|
|
|
222
266
|
const checks = schema._zod.def.checks;
|
|
223
267
|
const hasChecks = checks && checks.length > 0;
|
|
224
268
|
if (hasChecks) {
|
|
225
|
-
const existingShape = schema
|
|
269
|
+
const existingShape = sourceShape(schema);
|
|
226
270
|
for (const key of Reflect.ownKeys(shape)) {
|
|
227
271
|
if (Object.getOwnPropertyDescriptor(existingShape, key) !== undefined) {
|
|
228
272
|
throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
|
|
229
273
|
}
|
|
230
274
|
}
|
|
231
275
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return clone(schema, def);
|
|
276
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
277
|
+
}
|
|
278
|
+
function extended(schema, shape) {
|
|
279
|
+
const newShape = {};
|
|
280
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)));
|
|
281
|
+
mirrorProps(newShape, shape);
|
|
282
|
+
return newShape;
|
|
240
283
|
}
|
|
241
284
|
function safeExtend(schema, shape) {
|
|
242
285
|
if (!isPlainObject(shape)) {
|
|
243
286
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
244
287
|
}
|
|
245
|
-
|
|
246
|
-
get shape() {
|
|
247
|
-
const _shape = { ...schema._zod.def.shape, ...shape };
|
|
248
|
-
assignProp(this, "shape", _shape);
|
|
249
|
-
return _shape;
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
return clone(schema, def);
|
|
288
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
253
289
|
}
|
|
254
290
|
function merge(a, b) {
|
|
255
291
|
if (!b?._zod?.def) {
|
|
@@ -258,12 +294,11 @@ function merge(a, b) {
|
|
|
258
294
|
if (a._zod.def.checks?.length) {
|
|
259
295
|
throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
|
|
260
296
|
}
|
|
297
|
+
const newShape = {};
|
|
298
|
+
mirrorShape(newShape, a, Reflect.ownKeys(sourceShape(a)));
|
|
299
|
+
mirrorShape(newShape, b, Reflect.ownKeys(sourceShape(b)));
|
|
261
300
|
const def = mergeDefs(a._zod.def, {
|
|
262
|
-
|
|
263
|
-
const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };
|
|
264
|
-
assignProp(this, "shape", _shape);
|
|
265
|
-
return _shape;
|
|
266
|
-
},
|
|
301
|
+
shape: newShape,
|
|
267
302
|
get catchall() {
|
|
268
303
|
return b._zod.def.catchall;
|
|
269
304
|
},
|
|
@@ -278,67 +313,16 @@ function partial(Class, schema, mask, name = "partial") {
|
|
|
278
313
|
if (hasChecks) {
|
|
279
314
|
throw new Error(`.${name}() cannot be used on object schemas containing refinements`);
|
|
280
315
|
}
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (mask) {
|
|
286
|
-
for (const key of Reflect.ownKeys(mask)) {
|
|
287
|
-
if (!Object.prototype.hasOwnProperty.call(oldShape, key)) {
|
|
288
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
289
|
-
}
|
|
290
|
-
if (!mask[key])
|
|
291
|
-
continue;
|
|
292
|
-
shape[key] = Class ? new Class({
|
|
293
|
-
type: "optional",
|
|
294
|
-
innerType: oldShape[key]
|
|
295
|
-
}) : oldShape[key];
|
|
296
|
-
}
|
|
297
|
-
} else {
|
|
298
|
-
for (const key of Reflect.ownKeys(oldShape)) {
|
|
299
|
-
shape[key] = Class ? new Class({
|
|
300
|
-
type: "optional",
|
|
301
|
-
innerType: oldShape[key]
|
|
302
|
-
}) : oldShape[key];
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
assignProp(this, "shape", shape);
|
|
306
|
-
return shape;
|
|
307
|
-
},
|
|
308
|
-
checks: []
|
|
309
|
-
});
|
|
310
|
-
return clone(schema, def);
|
|
316
|
+
const selected = mask ? new Set(maskedKeys(schema, mask)) : undefined;
|
|
317
|
+
const newShape = {};
|
|
318
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), Class && ((value, key) => selected && !selected.has(key) ? value : new Class({ type: "optional", innerType: value })));
|
|
319
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: newShape, checks: [] }));
|
|
311
320
|
}
|
|
312
321
|
function required(Class, schema, mask) {
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (mask) {
|
|
318
|
-
for (const key of Reflect.ownKeys(mask)) {
|
|
319
|
-
if (!Object.prototype.hasOwnProperty.call(shape, key)) {
|
|
320
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
321
|
-
}
|
|
322
|
-
if (!mask[key])
|
|
323
|
-
continue;
|
|
324
|
-
shape[key] = new Class({
|
|
325
|
-
type: "nonoptional",
|
|
326
|
-
innerType: oldShape[key]
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
} else {
|
|
330
|
-
for (const key of Reflect.ownKeys(oldShape)) {
|
|
331
|
-
shape[key] = new Class({
|
|
332
|
-
type: "nonoptional",
|
|
333
|
-
innerType: oldShape[key]
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
assignProp(this, "shape", shape);
|
|
338
|
-
return shape;
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
return clone(schema, def);
|
|
322
|
+
const selected = mask ? new Set(maskedKeys(schema, mask)) : undefined;
|
|
323
|
+
const newShape = {};
|
|
324
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), (value, key) => selected && !selected.has(key) ? value : new Class({ type: "nonoptional", innerType: value }));
|
|
325
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: newShape }));
|
|
342
326
|
}
|
|
343
327
|
function aborted(x, startIndex = 0) {
|
|
344
328
|
if (x.aborted === true)
|
|
@@ -388,13 +372,18 @@ function finalizeIssue(iss, ctx, config) {
|
|
|
388
372
|
}
|
|
389
373
|
const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : undefined;
|
|
390
374
|
const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config.customError?.(iss)) ?? unwrapMessage(config.localeError?.(iss)) ?? "Invalid input";
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
375
|
+
const full = {};
|
|
376
|
+
for (const k of Object.keys(iss)) {
|
|
377
|
+
if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
|
|
378
|
+
continue;
|
|
379
|
+
full[k] = iss[k];
|
|
380
|
+
}
|
|
381
|
+
full.path ?? (full.path = []);
|
|
382
|
+
full.message = message;
|
|
394
383
|
if (ctx?.reportInput) {
|
|
395
|
-
|
|
384
|
+
full.input = iss.input;
|
|
396
385
|
}
|
|
397
|
-
return
|
|
386
|
+
return full;
|
|
398
387
|
}
|
|
399
388
|
var highSurrogate = /[\uD800-\uDBFF]/;
|
|
400
389
|
function codePointLength(str) {
|
|
@@ -466,6 +455,22 @@ function own(inst, key, value, enumerable = true) {
|
|
|
466
455
|
function hide(inst, key, value) {
|
|
467
456
|
return own(inst, key, value, false);
|
|
468
457
|
}
|
|
458
|
+
function derived(computes, table) {
|
|
459
|
+
for (const key in computes) {
|
|
460
|
+
const compute = computes[key];
|
|
461
|
+
Object.defineProperty(table, key, {
|
|
462
|
+
configurable: true,
|
|
463
|
+
enumerable: true,
|
|
464
|
+
get() {
|
|
465
|
+
return own(this, key, compute(this));
|
|
466
|
+
},
|
|
467
|
+
set(value) {
|
|
468
|
+
own(this, key, value);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
return table;
|
|
473
|
+
}
|
|
469
474
|
function defineBound(proto, key, fn) {
|
|
470
475
|
Object.defineProperty(proto, key, {
|
|
471
476
|
configurable: true,
|
|
@@ -589,8 +594,7 @@ function $constructor(name, initializer, proto, params) {
|
|
|
589
594
|
} finally {
|
|
590
595
|
_zodDesc.value = undefined;
|
|
591
596
|
}
|
|
592
|
-
}
|
|
593
|
-
if (inst._zod.traits.has(name)) {
|
|
597
|
+
} else if (inst._zod.traits.has(name)) {
|
|
594
598
|
return;
|
|
595
599
|
}
|
|
596
600
|
inst._zod.traits.add(name);
|
|
@@ -681,16 +685,12 @@ var _messageDesc = {
|
|
|
681
685
|
enumerable: true,
|
|
682
686
|
configurable: true
|
|
683
687
|
};
|
|
684
|
-
var _zodDesc2 = { value: undefined, enumerable: false };
|
|
685
688
|
var _issuesDesc = { value: undefined, enumerable: false };
|
|
686
689
|
var _installedToString = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
|
|
687
690
|
var initializer = (inst, def) => {
|
|
688
691
|
inst.name = "$ZodError";
|
|
689
|
-
_zodDesc2.value = inst._zod;
|
|
690
|
-
Object.defineProperty(inst, "_zod", _zodDesc2);
|
|
691
692
|
_issuesDesc.value = def;
|
|
692
693
|
Object.defineProperty(inst, "issues", _issuesDesc);
|
|
693
|
-
_zodDesc2.value = undefined;
|
|
694
694
|
_issuesDesc.value = undefined;
|
|
695
695
|
Object.defineProperty(inst, "message", _messageDesc);
|
|
696
696
|
const proto = Object.getPrototypeOf(inst);
|
|
@@ -826,23 +826,68 @@ var _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
|
826
826
|
if (result instanceof Promise) {
|
|
827
827
|
throw new $ZodAsyncError;
|
|
828
828
|
}
|
|
829
|
-
return result.issues.length ? {
|
|
830
|
-
success: false,
|
|
831
|
-
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
832
|
-
} : { success: true, data: result.value };
|
|
829
|
+
return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
|
|
833
830
|
};
|
|
834
|
-
|
|
831
|
+
function failure(Err, issues, ctx) {
|
|
832
|
+
let error;
|
|
833
|
+
return {
|
|
834
|
+
success: false,
|
|
835
|
+
get error() {
|
|
836
|
+
if (!error) {
|
|
837
|
+
error = new Err(issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
838
|
+
issues = undefined;
|
|
839
|
+
ctx = undefined;
|
|
840
|
+
}
|
|
841
|
+
return error;
|
|
842
|
+
},
|
|
843
|
+
set error(e) {
|
|
844
|
+
error = e;
|
|
845
|
+
issues = undefined;
|
|
846
|
+
ctx = undefined;
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
}
|
|
835
850
|
var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
836
851
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
837
852
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
838
853
|
if (result instanceof Promise)
|
|
839
854
|
result = await result;
|
|
840
|
-
return result.issues.length ? {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
855
|
+
return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
|
|
856
|
+
};
|
|
857
|
+
var COMPILE_INVALID = /* @__PURE__ */ Symbol.for("zod.compile.invalid");
|
|
858
|
+
var COMPILE_FALLBACK = /* @__PURE__ */ Symbol.for("zod.compile.fallback");
|
|
859
|
+
var validate = (schema, value, _ctx) => {
|
|
860
|
+
const validator = schema._zod.bag.validator;
|
|
861
|
+
if (validator !== undefined) {
|
|
862
|
+
if (validator(value) !== COMPILE_INVALID)
|
|
863
|
+
return true;
|
|
864
|
+
if (validator.definite === true && _ctx === undefined)
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
return validateFallback(schema, value, _ctx);
|
|
868
|
+
};
|
|
869
|
+
function validateFallback(schema, value, _ctx) {
|
|
870
|
+
const ctx = _ctx ? { ..._ctx, async: false, abortEarly: true } : { async: false, abortEarly: true };
|
|
871
|
+
const fallbackRun = schema._zod.bag.fallbackRun;
|
|
872
|
+
let result;
|
|
873
|
+
if (fallbackRun) {
|
|
874
|
+
ctx[COMPILE_FALLBACK] = true;
|
|
875
|
+
result = fallbackRun({ value, issues: [] }, ctx);
|
|
876
|
+
} else {
|
|
877
|
+
result = schema._zod.run({ value, issues: [] }, ctx);
|
|
878
|
+
}
|
|
879
|
+
if (result instanceof Promise) {
|
|
880
|
+
throw new $ZodAsyncError;
|
|
881
|
+
}
|
|
882
|
+
return result.issues.length === 0;
|
|
883
|
+
}
|
|
884
|
+
var validateAsync = async (schema, value, _ctx) => {
|
|
885
|
+
const ctx = _ctx ? { ..._ctx, async: true, abortEarly: true } : { async: true, abortEarly: true };
|
|
886
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
887
|
+
if (result instanceof Promise)
|
|
888
|
+
result = await result;
|
|
889
|
+
return result.issues.length === 0;
|
|
844
890
|
};
|
|
845
|
-
var safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
846
891
|
var _encode = (_Err) => {
|
|
847
892
|
const parse = _parse(_Err);
|
|
848
893
|
const fn = (schema, value, _ctx, _params) => {
|
|
@@ -904,8 +949,8 @@ var uuid = (version) => {
|
|
|
904
949
|
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
|
905
950
|
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
|
|
906
951
|
};
|
|
907
|
-
var email = /^(
|
|
908
|
-
var _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`;
|
|
952
|
+
var email = /^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
953
|
+
var _emoji = `^(?=[\\s\\S]*[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u20E3])[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`;
|
|
909
954
|
function emoji() {
|
|
910
955
|
return new RegExp(_emoji, "u");
|
|
911
956
|
}
|
|
@@ -914,10 +959,11 @@ var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|(
|
|
|
914
959
|
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
|
915
960
|
var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
|
916
961
|
var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
917
|
-
var base64url = /^[A-Za-z0-9_-]
|
|
962
|
+
var base64url = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/;
|
|
918
963
|
var httpProtocol = /^https?$/;
|
|
919
964
|
var e164 = /^\+[1-9]\d{6,14}$/;
|
|
920
965
|
var creditCard = /^\d(?:[ -]?\d){11,18}$/;
|
|
966
|
+
var iban = /^[A-Z]{2}(?!00|01|99)\d{2}[A-Z0-9]{11,30}$/;
|
|
921
967
|
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
|
922
968
|
function anchor(source) {
|
|
923
969
|
return new RegExp(`^${source}$`);
|
|
@@ -939,10 +985,7 @@ function datetime(args) {
|
|
|
939
985
|
const timeRegex = args.local ? `${qualified}|${timeSource({ precision: args.precision })}` : qualified;
|
|
940
986
|
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
|
|
941
987
|
}
|
|
942
|
-
var
|
|
943
|
-
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
944
|
-
return new RegExp(`^${regex}$`);
|
|
945
|
-
};
|
|
988
|
+
var anyString = /^[\s\S]{0,}$/;
|
|
946
989
|
var integer = /^-?\d+$/;
|
|
947
990
|
var number = /^-?\d+(?:\.\d+)?$/;
|
|
948
991
|
var boolean = /^(?:true|false)$/i;
|
|
@@ -968,16 +1011,6 @@ var numericOriginMap = {
|
|
|
968
1011
|
var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst, def) => {
|
|
969
1012
|
$ZodCheck.init(inst, def);
|
|
970
1013
|
const origin = numericOriginMap[typeof def.value];
|
|
971
|
-
inst._zod.onattach.push((inst) => {
|
|
972
|
-
const bag = inst._zod.bag;
|
|
973
|
-
const curr = (def.inclusive ? bag.maximum : bag.exclusiveMaximum) ?? Number.POSITIVE_INFINITY;
|
|
974
|
-
if (def.value < curr) {
|
|
975
|
-
if (def.inclusive)
|
|
976
|
-
bag.maximum = def.value;
|
|
977
|
-
else
|
|
978
|
-
bag.exclusiveMaximum = def.value;
|
|
979
|
-
}
|
|
980
|
-
});
|
|
981
1014
|
inst._zod.check = (payload) => {
|
|
982
1015
|
if (def.inclusive ? payload.value <= def.value : payload.value < def.value) {
|
|
983
1016
|
return;
|
|
@@ -996,16 +1029,6 @@ var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst,
|
|
|
996
1029
|
var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
|
|
997
1030
|
$ZodCheck.init(inst, def);
|
|
998
1031
|
const origin = numericOriginMap[typeof def.value];
|
|
999
|
-
inst._zod.onattach.push((inst) => {
|
|
1000
|
-
const bag = inst._zod.bag;
|
|
1001
|
-
const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
|
|
1002
|
-
if (def.value > curr) {
|
|
1003
|
-
if (def.inclusive)
|
|
1004
|
-
bag.minimum = def.value;
|
|
1005
|
-
else
|
|
1006
|
-
bag.exclusiveMinimum = def.value;
|
|
1007
|
-
}
|
|
1008
|
-
});
|
|
1009
1032
|
inst._zod.check = (payload) => {
|
|
1010
1033
|
if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
|
|
1011
1034
|
return;
|
|
@@ -1023,10 +1046,6 @@ var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan",
|
|
|
1023
1046
|
});
|
|
1024
1047
|
var $ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (inst, def) => {
|
|
1025
1048
|
$ZodCheck.init(inst, def);
|
|
1026
|
-
inst._zod.onattach.push((inst) => {
|
|
1027
|
-
var _a;
|
|
1028
|
-
(_a = inst._zod.bag).multipleOf ?? (_a.multipleOf = def.value);
|
|
1029
|
-
});
|
|
1030
1049
|
inst._zod.check = (payload) => {
|
|
1031
1050
|
if (typeof payload.value !== typeof def.value)
|
|
1032
1051
|
throw new Error("Cannot mix number and bigint in multiple_of check.");
|
|
@@ -1049,14 +1068,6 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
1049
1068
|
const isInt = def.format?.includes("int");
|
|
1050
1069
|
const origin = isInt ? "int" : "number";
|
|
1051
1070
|
const [minimum, maximum] = NUMBER_FORMAT_RANGES[def.format];
|
|
1052
|
-
inst._zod.onattach.push((inst) => {
|
|
1053
|
-
const bag = inst._zod.bag;
|
|
1054
|
-
bag.format = def.format;
|
|
1055
|
-
bag.minimum = minimum;
|
|
1056
|
-
bag.maximum = maximum;
|
|
1057
|
-
if (isInt)
|
|
1058
|
-
bag.pattern = integer;
|
|
1059
|
-
});
|
|
1060
1071
|
inst._zod.check = (payload) => {
|
|
1061
1072
|
const input = payload.value;
|
|
1062
1073
|
if (isInt) {
|
|
@@ -1126,11 +1137,6 @@ var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (ins
|
|
|
1126
1137
|
var _a;
|
|
1127
1138
|
$ZodCheck.init(inst, def);
|
|
1128
1139
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1129
|
-
inst._zod.onattach.push((inst) => {
|
|
1130
|
-
const curr = inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY;
|
|
1131
|
-
if (def.maximum < curr)
|
|
1132
|
-
inst._zod.bag.maximum = def.maximum;
|
|
1133
|
-
});
|
|
1134
1140
|
inst._zod.check = (payload) => {
|
|
1135
1141
|
const input = payload.value;
|
|
1136
1142
|
const units = input.length;
|
|
@@ -1153,11 +1159,6 @@ var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (ins
|
|
|
1153
1159
|
var _a;
|
|
1154
1160
|
$ZodCheck.init(inst, def);
|
|
1155
1161
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1156
|
-
inst._zod.onattach.push((inst) => {
|
|
1157
|
-
const curr = inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY;
|
|
1158
|
-
if (def.minimum > curr)
|
|
1159
|
-
inst._zod.bag.minimum = def.minimum;
|
|
1160
|
-
});
|
|
1161
1162
|
inst._zod.check = (payload) => {
|
|
1162
1163
|
const input = payload.value;
|
|
1163
1164
|
const units = input.length;
|
|
@@ -1180,12 +1181,6 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
|
|
|
1180
1181
|
var _a;
|
|
1181
1182
|
$ZodCheck.init(inst, def);
|
|
1182
1183
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1183
|
-
inst._zod.onattach.push((inst) => {
|
|
1184
|
-
const bag = inst._zod.bag;
|
|
1185
|
-
bag.minimum = def.length;
|
|
1186
|
-
bag.maximum = def.length;
|
|
1187
|
-
bag.length = def.length;
|
|
1188
|
-
});
|
|
1189
1184
|
inst._zod.check = (payload) => {
|
|
1190
1185
|
const input = payload.value;
|
|
1191
1186
|
const units = input.length;
|
|
@@ -1208,14 +1203,6 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
|
|
|
1208
1203
|
var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat", (inst, def) => {
|
|
1209
1204
|
var _a, _b;
|
|
1210
1205
|
$ZodCheck.init(inst, def);
|
|
1211
|
-
inst._zod.onattach.push((inst) => {
|
|
1212
|
-
const bag = inst._zod.bag;
|
|
1213
|
-
bag.format = def.format;
|
|
1214
|
-
if (def.pattern) {
|
|
1215
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1216
|
-
bag.patterns.add(def.pattern);
|
|
1217
|
-
}
|
|
1218
|
-
});
|
|
1219
1206
|
if (def.pattern)
|
|
1220
1207
|
(_a = inst._zod).check ?? (_a.check = (payload) => {
|
|
1221
1208
|
def.pattern.lastIndex = 0;
|
|
@@ -1264,11 +1251,6 @@ var $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst,
|
|
|
1264
1251
|
const escapedRegex = escapeRegex(def.includes);
|
|
1265
1252
|
const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position},}${escapedRegex}` : escapedRegex);
|
|
1266
1253
|
def.pattern = pattern;
|
|
1267
|
-
inst._zod.onattach.push((inst) => {
|
|
1268
|
-
const bag = inst._zod.bag;
|
|
1269
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1270
|
-
bag.patterns.add(pattern);
|
|
1271
|
-
});
|
|
1272
1254
|
inst._zod.check = (payload) => {
|
|
1273
1255
|
if (payload.value.includes(def.includes, def.position))
|
|
1274
1256
|
return;
|
|
@@ -1287,11 +1269,6 @@ var $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (i
|
|
|
1287
1269
|
$ZodCheck.init(inst, def);
|
|
1288
1270
|
const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
|
|
1289
1271
|
def.pattern ?? (def.pattern = pattern);
|
|
1290
|
-
inst._zod.onattach.push((inst) => {
|
|
1291
|
-
const bag = inst._zod.bag;
|
|
1292
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1293
|
-
bag.patterns.add(pattern);
|
|
1294
|
-
});
|
|
1295
1272
|
inst._zod.check = (payload) => {
|
|
1296
1273
|
if (payload.value.startsWith(def.prefix))
|
|
1297
1274
|
return;
|
|
@@ -1310,11 +1287,6 @@ var $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst,
|
|
|
1310
1287
|
$ZodCheck.init(inst, def);
|
|
1311
1288
|
const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
|
|
1312
1289
|
def.pattern ?? (def.pattern = pattern);
|
|
1313
|
-
inst._zod.onattach.push((inst) => {
|
|
1314
|
-
const bag = inst._zod.bag;
|
|
1315
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1316
|
-
bag.patterns.add(pattern);
|
|
1317
|
-
});
|
|
1318
1290
|
inst._zod.check = (payload) => {
|
|
1319
1291
|
if (payload.value.endsWith(def.suffix))
|
|
1320
1292
|
return;
|
|
@@ -1346,8 +1318,11 @@ class Doc {
|
|
|
1346
1318
|
}
|
|
1347
1319
|
indented(fn) {
|
|
1348
1320
|
this.indent += 1;
|
|
1349
|
-
|
|
1350
|
-
|
|
1321
|
+
try {
|
|
1322
|
+
fn(this);
|
|
1323
|
+
} finally {
|
|
1324
|
+
this.indent -= 1;
|
|
1325
|
+
}
|
|
1351
1326
|
}
|
|
1352
1327
|
write(arg) {
|
|
1353
1328
|
if (typeof arg === "function") {
|
|
@@ -1378,8 +1353,8 @@ ${content.join(`
|
|
|
1378
1353
|
// node_modules/zod/v4/core/versions.js
|
|
1379
1354
|
var version = {
|
|
1380
1355
|
major: 4,
|
|
1381
|
-
minor:
|
|
1382
|
-
patch:
|
|
1356
|
+
minor: 6,
|
|
1357
|
+
patch: 5
|
|
1383
1358
|
};
|
|
1384
1359
|
|
|
1385
1360
|
// node_modules/zod/v4/core/schemas.js
|
|
@@ -1491,15 +1466,21 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
1491
1466
|
own(this, "~standard", value);
|
|
1492
1467
|
}
|
|
1493
1468
|
});
|
|
1494
|
-
var toStandardResult = (r) => r.
|
|
1469
|
+
var toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value };
|
|
1470
|
+
async function validateAsync2(inst, value) {
|
|
1471
|
+
const ctx = { async: true };
|
|
1472
|
+
return toStandardResult(await inst._zod.run({ value, issues: [] }, ctx), ctx);
|
|
1473
|
+
}
|
|
1495
1474
|
function standardProps(inst) {
|
|
1496
1475
|
return {
|
|
1497
1476
|
validate: (value) => {
|
|
1477
|
+
const ctx = { async: false };
|
|
1498
1478
|
try {
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
}
|
|
1479
|
+
const r = inst._zod.run({ value, issues: [] }, ctx);
|
|
1480
|
+
if (!(r instanceof Promise))
|
|
1481
|
+
return toStandardResult(r, ctx);
|
|
1482
|
+
} catch (_) {}
|
|
1483
|
+
return validateAsync2(inst, value);
|
|
1503
1484
|
},
|
|
1504
1485
|
vendor: "zod",
|
|
1505
1486
|
version: 1
|
|
@@ -1507,7 +1488,7 @@ function standardProps(inst) {
|
|
|
1507
1488
|
}
|
|
1508
1489
|
var $ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
|
|
1509
1490
|
$ZodType.init(inst, def);
|
|
1510
|
-
inst._zod.pattern =
|
|
1491
|
+
inst._zod.pattern = def.pattern ?? anyString;
|
|
1511
1492
|
inst._zod.parse = (payload, _) => {
|
|
1512
1493
|
if (def.coerce)
|
|
1513
1494
|
try {
|
|
@@ -1558,11 +1539,32 @@ var $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
|
|
|
1558
1539
|
});
|
|
1559
1540
|
var URL_BAD_FORMAT = 1;
|
|
1560
1541
|
var URL_UNPARSEABLE = 2;
|
|
1542
|
+
function canParseURL(input) {
|
|
1543
|
+
try {
|
|
1544
|
+
if (typeof URL !== "undefined" && typeof URL.canParse === "function")
|
|
1545
|
+
return URL.canParse(input);
|
|
1546
|
+
new URL(input);
|
|
1547
|
+
return true;
|
|
1548
|
+
} catch {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
function validateURL(trimmed, def) {
|
|
1553
|
+
if (!("normalize" in def) && !("hostname" in def) && !("protocol" in def)) {
|
|
1554
|
+
return canParseURL(trimmed) || URL_UNPARSEABLE;
|
|
1555
|
+
}
|
|
1556
|
+
return parseURLObject(trimmed, def);
|
|
1557
|
+
}
|
|
1561
1558
|
function parseURLObject(trimmed, def) {
|
|
1562
1559
|
if (!def.normalize && def.protocol?.source === httpProtocol.source && !/^https?:\/\//i.test(trimmed)) {
|
|
1563
1560
|
return URL_BAD_FORMAT;
|
|
1564
1561
|
}
|
|
1565
1562
|
try {
|
|
1563
|
+
if (typeof URL !== "undefined") {
|
|
1564
|
+
const URLStatic = URL;
|
|
1565
|
+
if (typeof URLStatic.parse === "function")
|
|
1566
|
+
return URLStatic.parse(trimmed) ?? URL_UNPARSEABLE;
|
|
1567
|
+
}
|
|
1566
1568
|
return new URL(trimmed);
|
|
1567
1569
|
} catch {
|
|
1568
1570
|
return URL_UNPARSEABLE;
|
|
@@ -1585,7 +1587,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
1585
1587
|
inst._zod.check = (payload) => {
|
|
1586
1588
|
try {
|
|
1587
1589
|
const trimmed = payload.value.trim();
|
|
1588
|
-
const url =
|
|
1590
|
+
const url = validateURL(trimmed, def);
|
|
1589
1591
|
if (url === URL_BAD_FORMAT) {
|
|
1590
1592
|
payload.issues.push({
|
|
1591
1593
|
code: "invalid_format",
|
|
@@ -1607,6 +1609,10 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
1607
1609
|
});
|
|
1608
1610
|
return;
|
|
1609
1611
|
}
|
|
1612
|
+
if (url === true) {
|
|
1613
|
+
payload.value = stripTabAndNewline(trimmed);
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1610
1616
|
if (def.hostname && !urlHostnameOk(url, def.hostname)) {
|
|
1611
1617
|
payload.issues.push({
|
|
1612
1618
|
code: "invalid_format",
|
|
@@ -1675,12 +1681,6 @@ var $ZodKSUID = /* @__PURE__ */ $constructor("$ZodKSUID", (inst, def) => {
|
|
|
1675
1681
|
var $ZodISODateTime = /* @__PURE__ */ $constructor("$ZodISODateTime", (inst, def) => {
|
|
1676
1682
|
def.pattern ?? (def.pattern = datetime(def));
|
|
1677
1683
|
$ZodStringFormat.init(inst, def);
|
|
1678
|
-
if (def.local || def.precision === -1) {
|
|
1679
|
-
inst._zod.bag.laxFormat = true;
|
|
1680
|
-
inst._zod.onattach.push((s) => {
|
|
1681
|
-
s._zod.bag.laxFormat = true;
|
|
1682
|
-
});
|
|
1683
|
-
}
|
|
1684
1684
|
});
|
|
1685
1685
|
var $ZodISODate = /* @__PURE__ */ $constructor("$ZodISODate", (inst, def) => {
|
|
1686
1686
|
def.pattern ?? (def.pattern = date);
|
|
@@ -1697,23 +1697,16 @@ var $ZodISODuration = /* @__PURE__ */ $constructor("$ZodISODuration", (inst, def
|
|
|
1697
1697
|
var $ZodIPv4 = /* @__PURE__ */ $constructor("$ZodIPv4", (inst, def) => {
|
|
1698
1698
|
def.pattern ?? (def.pattern = ipv4);
|
|
1699
1699
|
$ZodStringFormat.init(inst, def);
|
|
1700
|
-
inst._zod.bag.format = `ipv4`;
|
|
1701
1700
|
});
|
|
1702
1701
|
var ipv6Alphabet = /^[0-9a-fA-F:.]+$/;
|
|
1703
1702
|
function isValidIPv6(value) {
|
|
1704
1703
|
if (!ipv6Alphabet.test(value))
|
|
1705
1704
|
return false;
|
|
1706
|
-
|
|
1707
|
-
new URL(`http://[${value}]`);
|
|
1708
|
-
return true;
|
|
1709
|
-
} catch {
|
|
1710
|
-
return false;
|
|
1711
|
-
}
|
|
1705
|
+
return canParseURL(`http://[${value}]`);
|
|
1712
1706
|
}
|
|
1713
1707
|
var $ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
|
|
1714
1708
|
def.pattern ?? (def.pattern = ipv6);
|
|
1715
1709
|
$ZodStringFormat.init(inst, def);
|
|
1716
|
-
inst._zod.bag.format = `ipv6`;
|
|
1717
1710
|
inst._zod.check = (payload) => {
|
|
1718
1711
|
if (!isValidIPv6(payload.value)) {
|
|
1719
1712
|
payload.issues.push({
|
|
@@ -1773,10 +1766,10 @@ function isValidBase64(data) {
|
|
|
1773
1766
|
return false;
|
|
1774
1767
|
}
|
|
1775
1768
|
}
|
|
1769
|
+
var base64Charset = /^[0-9a-zA-Z+/]*={0,2}$/;
|
|
1776
1770
|
var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
1777
|
-
def.pattern ?? (def.pattern =
|
|
1771
|
+
def.pattern ?? (def.pattern = base64Charset);
|
|
1778
1772
|
$ZodStringFormat.init(inst, def);
|
|
1779
|
-
inst._zod.bag.contentEncoding = "base64";
|
|
1780
1773
|
inst._zod.check = (payload) => {
|
|
1781
1774
|
if (isValidBase64(payload.value))
|
|
1782
1775
|
return;
|
|
@@ -1789,17 +1782,17 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
|
1789
1782
|
});
|
|
1790
1783
|
};
|
|
1791
1784
|
});
|
|
1785
|
+
var base64urlCharset = /^[A-Za-z0-9_-]*$/;
|
|
1792
1786
|
function isValidBase64URL(data) {
|
|
1793
|
-
if (!
|
|
1787
|
+
if (!base64urlCharset.test(data))
|
|
1794
1788
|
return false;
|
|
1795
1789
|
const base64 = data.replace(/[-_]/g, (c) => c === "-" ? "+" : "/");
|
|
1796
1790
|
const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
|
|
1797
1791
|
return isValidBase64(padded);
|
|
1798
1792
|
}
|
|
1799
1793
|
var $ZodBase64URL = /* @__PURE__ */ $constructor("$ZodBase64URL", (inst, def) => {
|
|
1800
|
-
def.pattern ?? (def.pattern =
|
|
1794
|
+
def.pattern ?? (def.pattern = base64urlCharset);
|
|
1801
1795
|
$ZodStringFormat.init(inst, def);
|
|
1802
|
-
inst._zod.bag.contentEncoding = "base64url";
|
|
1803
1796
|
inst._zod.check = (payload) => {
|
|
1804
1797
|
if (isValidBase64URL(payload.value))
|
|
1805
1798
|
return;
|
|
@@ -1822,7 +1815,7 @@ function isLuhnAlgo(digits) {
|
|
|
1822
1815
|
let bit = 1;
|
|
1823
1816
|
let sum = 0;
|
|
1824
1817
|
while (length) {
|
|
1825
|
-
const value =
|
|
1818
|
+
const value = digits.charCodeAt(--length) - 48;
|
|
1826
1819
|
bit ^= 1;
|
|
1827
1820
|
sum += bit ? [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][value] : value;
|
|
1828
1821
|
}
|
|
@@ -1833,6 +1826,24 @@ function isValidCreditCard(input) {
|
|
|
1833
1826
|
return false;
|
|
1834
1827
|
return isLuhnAlgo(input.replace(CC_SANITIZE, ""));
|
|
1835
1828
|
}
|
|
1829
|
+
function isIso7064Mod97(iban2) {
|
|
1830
|
+
let remainder = 0;
|
|
1831
|
+
const len = iban2.length;
|
|
1832
|
+
for (let i = 4;i < len; i++) {
|
|
1833
|
+
const code = iban2.charCodeAt(i);
|
|
1834
|
+
remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
|
|
1835
|
+
}
|
|
1836
|
+
for (let i = 0;i < 4; i++) {
|
|
1837
|
+
const code = iban2.charCodeAt(i);
|
|
1838
|
+
remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
|
|
1839
|
+
}
|
|
1840
|
+
return remainder === 1;
|
|
1841
|
+
}
|
|
1842
|
+
function isValidIBAN(input) {
|
|
1843
|
+
if (!iban.test(input))
|
|
1844
|
+
return false;
|
|
1845
|
+
return isIso7064Mod97(input);
|
|
1846
|
+
}
|
|
1836
1847
|
function isValidJWT(token, algorithm = null) {
|
|
1837
1848
|
try {
|
|
1838
1849
|
const tokensParts = token.split(".");
|
|
@@ -1869,7 +1880,7 @@ var $ZodJWT = /* @__PURE__ */ $constructor("$ZodJWT", (inst, def) => {
|
|
|
1869
1880
|
});
|
|
1870
1881
|
var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
1871
1882
|
$ZodType.init(inst, def);
|
|
1872
|
-
inst._zod.pattern =
|
|
1883
|
+
inst._zod.pattern = number;
|
|
1873
1884
|
inst._zod.parse = (payload, _ctx) => {
|
|
1874
1885
|
if (def.coerce)
|
|
1875
1886
|
try {
|
|
@@ -1953,6 +1964,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
1953
1964
|
}
|
|
1954
1965
|
payload.value = memo ? memo.alloc(inst, payload, Array(input.length), ctx) : Array(input.length);
|
|
1955
1966
|
const proms = [];
|
|
1967
|
+
const abortEarly = ctx?.abortEarly;
|
|
1956
1968
|
for (let i = 0;i < input.length; i++) {
|
|
1957
1969
|
const item = input[i];
|
|
1958
1970
|
const result = def.element._zod.run({
|
|
@@ -1963,6 +1975,8 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
1963
1975
|
proms.push(result.then((result) => handleArrayResult(result, payload, i)));
|
|
1964
1976
|
} else {
|
|
1965
1977
|
handleArrayResult(result, payload, i);
|
|
1978
|
+
if (abortEarly && result.issues.length !== 0 && aborted(result))
|
|
1979
|
+
break;
|
|
1966
1980
|
}
|
|
1967
1981
|
}
|
|
1968
1982
|
if (proms.length) {
|
|
@@ -1995,7 +2009,7 @@ function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
|
1995
2009
|
return;
|
|
1996
2010
|
}
|
|
1997
2011
|
if (result.value === undefined) {
|
|
1998
|
-
if (isPresent) {
|
|
2012
|
+
if (isPresent || optin === "defaulted" && !isOptionalOut) {
|
|
1999
2013
|
final.value[key] = undefined;
|
|
2000
2014
|
}
|
|
2001
2015
|
} else {
|
|
@@ -2023,14 +2037,20 @@ function normalizeDef(def) {
|
|
|
2023
2037
|
optionalKeys: new Set(okeys)
|
|
2024
2038
|
};
|
|
2025
2039
|
}
|
|
2026
|
-
function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
2040
|
+
function handleCatchall(proms, input, payload, ctx, def, inst, abortEarly) {
|
|
2027
2041
|
const unrecognized = [];
|
|
2028
2042
|
const keySet = def.keySet;
|
|
2029
2043
|
const _catchall = def.catchall._zod;
|
|
2030
2044
|
const t = _catchall.def.type;
|
|
2031
2045
|
const optin = _catchall.optin;
|
|
2032
2046
|
const optout = _catchall.optout;
|
|
2047
|
+
let seen = 0;
|
|
2033
2048
|
for (const key in input) {
|
|
2049
|
+
if (abortEarly && payload.issues.length !== seen) {
|
|
2050
|
+
if (aborted(payload, seen))
|
|
2051
|
+
break;
|
|
2052
|
+
seen = payload.issues.length;
|
|
2053
|
+
}
|
|
2034
2054
|
if (keySet.has(key))
|
|
2035
2055
|
continue;
|
|
2036
2056
|
if (key === "__proto__") {
|
|
@@ -2064,23 +2084,19 @@ function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
|
2064
2084
|
return payload;
|
|
2065
2085
|
});
|
|
2066
2086
|
}
|
|
2067
|
-
var propShapes = new WeakMap;
|
|
2068
2087
|
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
2069
2088
|
$ZodType.init(inst, def);
|
|
2070
2089
|
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
return newSh;
|
|
2082
|
-
}
|
|
2083
|
-
});
|
|
2090
|
+
const sh = desc?.get ? desc.get.raw : def.shape ?? {};
|
|
2091
|
+
if (sh) {
|
|
2092
|
+
const get = () => {
|
|
2093
|
+
const newSh = { ...sh };
|
|
2094
|
+
Object.defineProperty(def, "shape", { value: newSh });
|
|
2095
|
+
get.raw = newSh;
|
|
2096
|
+
return newSh;
|
|
2097
|
+
};
|
|
2098
|
+
get.raw = sh;
|
|
2099
|
+
Object.defineProperty(def, "shape", { get });
|
|
2084
2100
|
}
|
|
2085
2101
|
const _normalized = cached(() => normalizeDef(def));
|
|
2086
2102
|
defineLazyInternal(inst, "propValues", (zod) => {
|
|
@@ -2120,7 +2136,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
2120
2136
|
payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};
|
|
2121
2137
|
const proms = [];
|
|
2122
2138
|
const shape = value.shape;
|
|
2139
|
+
const abortEarly = ctx?.abortEarly;
|
|
2140
|
+
let seen = payload.issues.length;
|
|
2123
2141
|
for (const key of value.allKeys) {
|
|
2142
|
+
if (abortEarly && payload.issues.length !== seen) {
|
|
2143
|
+
if (aborted(payload, seen))
|
|
2144
|
+
break;
|
|
2145
|
+
seen = payload.issues.length;
|
|
2146
|
+
}
|
|
2124
2147
|
if (key === "__proto__")
|
|
2125
2148
|
continue;
|
|
2126
2149
|
const el = shape[key];
|
|
@@ -2136,7 +2159,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
2136
2159
|
if (!catchall) {
|
|
2137
2160
|
return proms.length ? Promise.all(proms).then(() => payload) : payload;
|
|
2138
2161
|
}
|
|
2139
|
-
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst);
|
|
2162
|
+
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst, abortEarly === true);
|
|
2140
2163
|
};
|
|
2141
2164
|
});
|
|
2142
2165
|
var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => {
|
|
@@ -2150,10 +2173,16 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
2150
2173
|
const doc = new Doc(["payload", "ctx"], { shape, inst, memo, syms });
|
|
2151
2174
|
const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
2152
2175
|
const prefixStr = (id, k) => `
|
|
2176
|
+
let ${id}_ab = false;
|
|
2153
2177
|
for (let i = 0; i < ${id}.issues.length; i++) {
|
|
2154
2178
|
const iss = ${id}.issues[i];
|
|
2155
2179
|
iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
|
|
2156
2180
|
payload.issues.push(iss);
|
|
2181
|
+
if (iss.continue !== true) ${id}_ab = true;
|
|
2182
|
+
}
|
|
2183
|
+
if (${id}_ab && ctx && ctx.abortEarly) {
|
|
2184
|
+
payload.value = newResult;
|
|
2185
|
+
return payload;
|
|
2157
2186
|
}`;
|
|
2158
2187
|
doc.write(`const input = payload.value;`);
|
|
2159
2188
|
const ids = Object.create(null);
|
|
@@ -2199,6 +2228,10 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
2199
2228
|
input: undefined,
|
|
2200
2229
|
path: [${k}]
|
|
2201
2230
|
});
|
|
2231
|
+
if (ctx && ctx.abortEarly) {
|
|
2232
|
+
payload.value = newResult;
|
|
2233
|
+
return payload;
|
|
2234
|
+
}
|
|
2202
2235
|
}
|
|
2203
2236
|
|
|
2204
2237
|
if (${id}_present) {
|
|
@@ -2210,16 +2243,16 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
2210
2243
|
doc.write(`
|
|
2211
2244
|
if (${id}.issues.length) {${prefixStr(id, k)}
|
|
2212
2245
|
}
|
|
2213
|
-
|
|
2214
|
-
if (
|
|
2215
|
-
|
|
2216
|
-
newResult[${k}] = undefined;
|
|
2217
|
-
}
|
|
2246
|
+
`);
|
|
2247
|
+
if (optin === "defaulted") {
|
|
2248
|
+
doc.write(`newResult[${k}] = ${id}.value;`);
|
|
2218
2249
|
} else {
|
|
2250
|
+
doc.write(`
|
|
2251
|
+
if (${id}.value !== undefined || ${isPresent}) {
|
|
2219
2252
|
newResult[${k}] = ${id}.value;
|
|
2220
2253
|
}
|
|
2221
|
-
|
|
2222
2254
|
`);
|
|
2255
|
+
}
|
|
2223
2256
|
}
|
|
2224
2257
|
}
|
|
2225
2258
|
doc.write(`payload.value = newResult;`);
|
|
@@ -2251,7 +2284,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
2251
2284
|
payload = fastpass(payload, ctx);
|
|
2252
2285
|
if (!catchall)
|
|
2253
2286
|
return payload;
|
|
2254
|
-
return handleCatchall([], input, payload, ctx, value, inst);
|
|
2287
|
+
return handleCatchall([], input, payload, ctx, value, inst, ctx?.abortEarly === true);
|
|
2255
2288
|
}
|
|
2256
2289
|
return superParse(payload, ctx);
|
|
2257
2290
|
};
|
|
@@ -2321,16 +2354,37 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
2321
2354
|
});
|
|
2322
2355
|
};
|
|
2323
2356
|
});
|
|
2357
|
+
function discriminatorMap(def) {
|
|
2358
|
+
const map = new Map;
|
|
2359
|
+
for (const option of def.options) {
|
|
2360
|
+
const values = option._zod.propValues?.[def.discriminator];
|
|
2361
|
+
if (!values || values.size === 0)
|
|
2362
|
+
throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(option)}"`);
|
|
2363
|
+
for (const value of values) {
|
|
2364
|
+
if (map.has(value)) {
|
|
2365
|
+
if (value !== undefined)
|
|
2366
|
+
throw new Error(`Duplicate discriminator value "${String(value)}"`);
|
|
2367
|
+
map.set(value, null);
|
|
2368
|
+
} else {
|
|
2369
|
+
map.set(value, option);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
return map;
|
|
2374
|
+
}
|
|
2324
2375
|
var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnion", (inst, def) => {
|
|
2325
2376
|
def.inclusive = false;
|
|
2326
2377
|
$ZodUnion.init(inst, def);
|
|
2327
2378
|
const _super = inst._zod.parse;
|
|
2328
2379
|
defineLazyInternal(inst, "propValues", (zod) => {
|
|
2329
2380
|
const propValues = {};
|
|
2381
|
+
let undefinedCount = 0;
|
|
2330
2382
|
for (const option of zod.def.options) {
|
|
2331
2383
|
const pv = option._zod.propValues;
|
|
2332
2384
|
if (!pv || Object.keys(pv).length === 0)
|
|
2333
2385
|
throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
|
|
2386
|
+
if (pv[zod.def.discriminator]?.has(undefined))
|
|
2387
|
+
undefinedCount++;
|
|
2334
2388
|
for (const [k, v] of Object.entries(pv)) {
|
|
2335
2389
|
if (!Object.prototype.hasOwnProperty.call(propValues, k)) {
|
|
2336
2390
|
assignProp(propValues, k, new Set);
|
|
@@ -2340,30 +2394,17 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
2340
2394
|
}
|
|
2341
2395
|
}
|
|
2342
2396
|
}
|
|
2397
|
+
if (!zod.def.unionFallback && undefinedCount > 1)
|
|
2398
|
+
propValues[zod.def.discriminator]?.delete(undefined);
|
|
2343
2399
|
return propValues;
|
|
2344
2400
|
});
|
|
2345
2401
|
def.options.forEach((option, i) => {
|
|
2346
|
-
const propShape =
|
|
2402
|
+
const propShape = rawShape(option._zod.def);
|
|
2347
2403
|
if (propShape && !Object.prototype.hasOwnProperty.call(propShape, def.discriminator)) {
|
|
2348
2404
|
throw new Error(`Invalid discriminated union option at index "${i}"`);
|
|
2349
2405
|
}
|
|
2350
2406
|
});
|
|
2351
|
-
const disc = cached(() =>
|
|
2352
|
-
const opts = def.options;
|
|
2353
|
-
const map = new Map;
|
|
2354
|
-
for (const o of opts) {
|
|
2355
|
-
const values = o._zod.propValues?.[def.discriminator];
|
|
2356
|
-
if (!values || values.size === 0)
|
|
2357
|
-
throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(o)}"`);
|
|
2358
|
-
for (const v of values) {
|
|
2359
|
-
if (map.has(v)) {
|
|
2360
|
-
throw new Error(`Duplicate discriminator value "${String(v)}"`);
|
|
2361
|
-
}
|
|
2362
|
-
map.set(v, o);
|
|
2363
|
-
}
|
|
2364
|
-
}
|
|
2365
|
-
return map;
|
|
2366
|
-
});
|
|
2407
|
+
const disc = cached(() => discriminatorMap(def));
|
|
2367
2408
|
inst._zod.parse = (payload, ctx) => {
|
|
2368
2409
|
const input = payload.value;
|
|
2369
2410
|
if (!isObject(input)) {
|
|
@@ -2375,8 +2416,9 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
2375
2416
|
});
|
|
2376
2417
|
return payload;
|
|
2377
2418
|
}
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2419
|
+
const value = input?.[def.discriminator];
|
|
2420
|
+
const opt = disc.value.get(value);
|
|
2421
|
+
if (opt && (value !== undefined || ctx.direction !== "backward")) {
|
|
2380
2422
|
return opt._zod.run(payload, ctx);
|
|
2381
2423
|
}
|
|
2382
2424
|
if (def.unionFallback || ctx.direction === "backward") {
|
|
@@ -2387,7 +2429,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
2387
2429
|
errors: [],
|
|
2388
2430
|
note: "No matching discriminator",
|
|
2389
2431
|
discriminator: def.discriminator,
|
|
2390
|
-
options: Array.from(disc.value.keys()),
|
|
2432
|
+
options: Array.from(disc.value.keys()).filter((value) => disc.value.get(value) !== null),
|
|
2391
2433
|
input,
|
|
2392
2434
|
path: [def.discriminator],
|
|
2393
2435
|
inst
|
|
@@ -2669,8 +2711,10 @@ var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
|
2669
2711
|
const values = getEnumValues(def.entries);
|
|
2670
2712
|
const valuesSet = new Set(values);
|
|
2671
2713
|
inst._zod.values = valuesSet;
|
|
2672
|
-
|
|
2673
|
-
|
|
2714
|
+
defineLazyInternal(inst, "pattern", (zod) => {
|
|
2715
|
+
const patternValues = getEnumValues(zod.def.entries).filter((k) => propertyKeyTypes.has(typeof k));
|
|
2716
|
+
return new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join("|")})$` : "^[^\\s\\S]$");
|
|
2717
|
+
});
|
|
2674
2718
|
inst._zod.parse = (payload, _ctx) => {
|
|
2675
2719
|
const input = payload.value;
|
|
2676
2720
|
if (valuesSet.has(input)) {
|
|
@@ -2689,7 +2733,10 @@ var $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
|
2689
2733
|
$ZodType.init(inst, def);
|
|
2690
2734
|
const values = new Set(def.values);
|
|
2691
2735
|
inst._zod.values = values;
|
|
2692
|
-
inst
|
|
2736
|
+
defineLazyInternal(inst, "pattern", (zod) => {
|
|
2737
|
+
const vals = zod.def.values;
|
|
2738
|
+
return new RegExp(vals.length ? `^(${vals.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$` : "^[^\\s\\S]$");
|
|
2739
|
+
});
|
|
2693
2740
|
inst._zod.parse = (payload, _ctx) => {
|
|
2694
2741
|
const input = payload.value;
|
|
2695
2742
|
if (values.has(input)) {
|
|
@@ -2966,28 +3013,53 @@ class $ZodCyclicError extends Error {
|
|
|
2966
3013
|
}
|
|
2967
3014
|
var STATE = "~memo";
|
|
2968
3015
|
var NO_ISSUES = [];
|
|
3016
|
+
function isRef(value) {
|
|
3017
|
+
return value !== null && typeof value === "object";
|
|
3018
|
+
}
|
|
2969
3019
|
function cloneIssues(issues) {
|
|
2970
3020
|
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
|
|
2971
3021
|
}
|
|
2972
3022
|
var recursive = /* @__PURE__ */ new WeakMap;
|
|
2973
|
-
|
|
3023
|
+
var NONE = 0;
|
|
3024
|
+
var ASSUMED = 1;
|
|
3025
|
+
var PROVEN = 2;
|
|
3026
|
+
function isRecursive(inst, stack, resolve) {
|
|
2974
3027
|
const cached = recursive.get(inst);
|
|
2975
3028
|
if (cached !== undefined)
|
|
2976
|
-
return cached;
|
|
3029
|
+
return cached ? PROVEN : NONE;
|
|
2977
3030
|
if (stack.has(inst))
|
|
2978
|
-
return
|
|
3031
|
+
return PROVEN;
|
|
2979
3032
|
stack.add(inst);
|
|
2980
|
-
let result =
|
|
3033
|
+
let result = NONE;
|
|
2981
3034
|
const check = (child) => {
|
|
2982
|
-
if (
|
|
2983
|
-
|
|
3035
|
+
if (result !== PROVEN && child?._zod) {
|
|
3036
|
+
const answer = isRecursive(child, stack, resolve);
|
|
3037
|
+
if (answer > result)
|
|
3038
|
+
result = answer;
|
|
3039
|
+
}
|
|
3040
|
+
};
|
|
3041
|
+
const shape = (sh, spread) => {
|
|
3042
|
+
let answer = NONE;
|
|
3043
|
+
for (const key of Reflect.ownKeys(sh)) {
|
|
3044
|
+
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
3045
|
+
if (spread && !desc.enumerable)
|
|
3046
|
+
continue;
|
|
3047
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
|
|
3048
|
+
if (child > answer)
|
|
3049
|
+
answer = child;
|
|
3050
|
+
}
|
|
3051
|
+
return answer;
|
|
3052
|
+
};
|
|
3053
|
+
const merge = (answer) => {
|
|
3054
|
+
if (answer > result)
|
|
3055
|
+
result = answer;
|
|
2984
3056
|
};
|
|
2985
3057
|
const def = inst._zod.def;
|
|
2986
3058
|
const kind = def.type;
|
|
2987
3059
|
switch (kind) {
|
|
2988
3060
|
case "object": {
|
|
2989
|
-
|
|
2990
|
-
|
|
3061
|
+
const raw = rawShape(def);
|
|
3062
|
+
merge(raw ? shape(raw, true) : ASSUMED);
|
|
2991
3063
|
check(def.catchall);
|
|
2992
3064
|
break;
|
|
2993
3065
|
}
|
|
@@ -3034,9 +3106,11 @@ function isRecursive(inst, stack) {
|
|
|
3034
3106
|
check(def.input);
|
|
3035
3107
|
check(def.output);
|
|
3036
3108
|
break;
|
|
3037
|
-
case "lazy":
|
|
3038
|
-
|
|
3109
|
+
case "lazy": {
|
|
3110
|
+
const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : undefined);
|
|
3111
|
+
merge(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
3039
3112
|
break;
|
|
3113
|
+
}
|
|
3040
3114
|
case "template_literal":
|
|
3041
3115
|
case "string":
|
|
3042
3116
|
case "number":
|
|
@@ -3075,16 +3149,20 @@ function isRecursive(inst, stack) {
|
|
|
3075
3149
|
}
|
|
3076
3150
|
}
|
|
3077
3151
|
stack.delete(inst);
|
|
3078
|
-
|
|
3079
|
-
|
|
3152
|
+
return settle(inst, result);
|
|
3153
|
+
}
|
|
3154
|
+
function settle(inst, answer) {
|
|
3155
|
+
if (answer !== ASSUMED)
|
|
3156
|
+
recursive.set(inst, answer === PROVEN);
|
|
3157
|
+
return answer;
|
|
3080
3158
|
}
|
|
3081
3159
|
function isRecursiveSchema(inst) {
|
|
3082
|
-
return isRecursive(inst, new Set);
|
|
3160
|
+
return isRecursive(inst, new Set, true) !== NONE;
|
|
3083
3161
|
}
|
|
3084
3162
|
function bucketFor(state, inst) {
|
|
3085
3163
|
let bucket = state.buckets.get(inst);
|
|
3086
3164
|
if (!bucket) {
|
|
3087
|
-
bucket = new
|
|
3165
|
+
bucket = new WeakMap;
|
|
3088
3166
|
state.buckets.set(inst, bucket);
|
|
3089
3167
|
}
|
|
3090
3168
|
return bucket;
|
|
@@ -3120,6 +3198,7 @@ var memo = {
|
|
|
3120
3198
|
attach(inst) {
|
|
3121
3199
|
var _a;
|
|
3122
3200
|
let isRecursiveInst;
|
|
3201
|
+
let rechecked = false;
|
|
3123
3202
|
let lastCtx;
|
|
3124
3203
|
let lastBucket;
|
|
3125
3204
|
(_a = inst._zod).deferred ?? (_a.deferred = []);
|
|
@@ -3127,20 +3206,24 @@ var memo = {
|
|
|
3127
3206
|
const base = inst._zod.parse;
|
|
3128
3207
|
const wrapped = (payload, ctx) => {
|
|
3129
3208
|
if (isRecursiveInst === undefined) {
|
|
3130
|
-
|
|
3131
|
-
if (
|
|
3209
|
+
const walked = isRecursive(inst, new Set, false);
|
|
3210
|
+
if (walked === NONE) {
|
|
3132
3211
|
inst._zod.parse = base;
|
|
3133
3212
|
if (inst._zod.run === wrapped)
|
|
3134
3213
|
inst._zod.run = base;
|
|
3135
3214
|
return base(payload, ctx);
|
|
3136
3215
|
}
|
|
3216
|
+
if (walked === PROVEN || rechecked)
|
|
3217
|
+
isRecursiveInst = true;
|
|
3218
|
+
else
|
|
3219
|
+
rechecked = true;
|
|
3137
3220
|
}
|
|
3138
3221
|
const input = payload.value;
|
|
3139
|
-
if (input
|
|
3222
|
+
if (!isRef(input))
|
|
3140
3223
|
return base(payload, ctx);
|
|
3141
3224
|
let state = ctx[STATE];
|
|
3142
3225
|
if (!state) {
|
|
3143
|
-
state = { buckets: new
|
|
3226
|
+
state = { buckets: new WeakMap, backEdges: undefined };
|
|
3144
3227
|
ctx[STATE] = state;
|
|
3145
3228
|
}
|
|
3146
3229
|
let bucket;
|
|
@@ -3159,7 +3242,7 @@ var memo = {
|
|
|
3159
3242
|
payload.issues.push(...cloneIssues(hit.issues));
|
|
3160
3243
|
} else {
|
|
3161
3244
|
payload.memo = true;
|
|
3162
|
-
state.backEdges ?? (state.backEdges = new
|
|
3245
|
+
state.backEdges ?? (state.backEdges = new WeakSet);
|
|
3163
3246
|
state.backEdges.add(hit.value);
|
|
3164
3247
|
}
|
|
3165
3248
|
return payload;
|
|
@@ -3191,7 +3274,7 @@ function memoizer() {
|
|
|
3191
3274
|
}
|
|
3192
3275
|
function isBackEdge(ctx, value) {
|
|
3193
3276
|
const backEdges = ctx[STATE]?.backEdges;
|
|
3194
|
-
return backEdges !== undefined && value
|
|
3277
|
+
return backEdges !== undefined && isRef(value) && backEdges.has(value);
|
|
3195
3278
|
}
|
|
3196
3279
|
// node_modules/zod/v4/locales/en.js
|
|
3197
3280
|
var error = () => {
|
|
@@ -3233,7 +3316,9 @@ var error = () => {
|
|
|
3233
3316
|
base64url: "base64url-encoded string",
|
|
3234
3317
|
json_string: "JSON string",
|
|
3235
3318
|
e164: "E.164 number",
|
|
3319
|
+
currency_code: "currency code",
|
|
3236
3320
|
credit_card: "credit card number",
|
|
3321
|
+
iban: "IBAN",
|
|
3237
3322
|
jwt: "JWT",
|
|
3238
3323
|
template_literal: "input"
|
|
3239
3324
|
};
|
|
@@ -3388,38 +3473,46 @@ function compileValidator(schema, parser) {
|
|
|
3388
3473
|
function compile(schema, options) {
|
|
3389
3474
|
try {
|
|
3390
3475
|
const parser = compileFn(schema);
|
|
3391
|
-
const
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
const wrapped = (payload, ctx) => {
|
|
3395
|
-
if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
|
|
3396
|
-
return originalRun(payload, ctx);
|
|
3397
|
-
}
|
|
3398
|
-
if (ctx && isBackEdge(ctx, payload.value)) {
|
|
3399
|
-
return originalRun(payload, ctx);
|
|
3400
|
-
}
|
|
3401
|
-
const out = parser(payload.value);
|
|
3402
|
-
if (out !== INVALID) {
|
|
3403
|
-
payload.value = out;
|
|
3404
|
-
return payload;
|
|
3405
|
-
}
|
|
3406
|
-
if (ctx)
|
|
3407
|
-
ctx[FALLBACK_FLAG] = true;
|
|
3408
|
-
return originalRun(payload, ctx);
|
|
3409
|
-
};
|
|
3410
|
-
wrapped.__originalRun = originalRun;
|
|
3411
|
-
clone2._zod.bag.fallbackRun = originalRun;
|
|
3412
|
-
clone2._zod.bag.validator = compileValidator(schema, parser);
|
|
3413
|
-
clone2._zod.run = wrapped;
|
|
3414
|
-
if (!liveRun.__originalRun)
|
|
3415
|
-
installCompiledUserMethods(clone2, schema, parser);
|
|
3416
|
-
return clone2;
|
|
3476
|
+
const clone = withParser(schema, parser);
|
|
3477
|
+
clone._zod.bag.validator = compileValidator(schema, parser);
|
|
3478
|
+
return clone;
|
|
3417
3479
|
} catch (err) {
|
|
3418
3480
|
if (options?.strict)
|
|
3419
3481
|
throw err;
|
|
3420
3482
|
return schema;
|
|
3421
3483
|
}
|
|
3422
3484
|
}
|
|
3485
|
+
function withParser(schema, parser) {
|
|
3486
|
+
if (isRecursiveSchema(schema)) {
|
|
3487
|
+
throw new ZodCompileUnsupportedError("a schema whose subtree contains a reference cycle");
|
|
3488
|
+
}
|
|
3489
|
+
const clone2 = clone(schema);
|
|
3490
|
+
const liveRun = schema._zod.run;
|
|
3491
|
+
const originalRun = liveRun.__originalRun ?? liveRun;
|
|
3492
|
+
const wrapped = (payload, ctx) => {
|
|
3493
|
+
if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
|
|
3494
|
+
return originalRun(payload, ctx);
|
|
3495
|
+
}
|
|
3496
|
+
if (ctx && isBackEdge(ctx, payload.value)) {
|
|
3497
|
+
return originalRun(payload, ctx);
|
|
3498
|
+
}
|
|
3499
|
+
const out = parser(payload.value);
|
|
3500
|
+
if (out !== INVALID) {
|
|
3501
|
+
payload.value = out;
|
|
3502
|
+
return payload;
|
|
3503
|
+
}
|
|
3504
|
+
if (ctx)
|
|
3505
|
+
ctx[FALLBACK_FLAG] = true;
|
|
3506
|
+
return originalRun(payload, ctx);
|
|
3507
|
+
};
|
|
3508
|
+
wrapped.__originalRun = originalRun;
|
|
3509
|
+
clone2._zod.bag.fallbackRun = originalRun;
|
|
3510
|
+
clone2._zod.bag.validator = parser;
|
|
3511
|
+
clone2._zod.run = wrapped;
|
|
3512
|
+
if (!liveRun.__originalRun)
|
|
3513
|
+
installCompiledUserMethods(clone2, schema, parser);
|
|
3514
|
+
return clone2;
|
|
3515
|
+
}
|
|
3423
3516
|
function installCompiledUserMethods(target, source, parser) {
|
|
3424
3517
|
const targetAny = target;
|
|
3425
3518
|
const sourceAny = source;
|
|
@@ -3455,7 +3548,8 @@ function compileFn(schema, options) {
|
|
|
3455
3548
|
const ctx = {
|
|
3456
3549
|
constants: new Map,
|
|
3457
3550
|
constantCounter: 0,
|
|
3458
|
-
varCounter: 0
|
|
3551
|
+
varCounter: 0,
|
|
3552
|
+
definite: true
|
|
3459
3553
|
};
|
|
3460
3554
|
const doc = new Doc(["input"]);
|
|
3461
3555
|
const outputAccessor = generateCheck(doc, ctx, schema, "input", !options?.assertOnly);
|
|
@@ -3480,6 +3574,7 @@ ${code}
|
|
|
3480
3574
|
if (options?.debug) {
|
|
3481
3575
|
fn.code = fullCode;
|
|
3482
3576
|
}
|
|
3577
|
+
fn.definite = ctx.definite;
|
|
3483
3578
|
return fn;
|
|
3484
3579
|
}
|
|
3485
3580
|
function addConstant(ctx, value) {
|
|
@@ -3491,6 +3586,10 @@ function addConstant(ctx, value) {
|
|
|
3491
3586
|
ctx.constants.set(name, value);
|
|
3492
3587
|
return name;
|
|
3493
3588
|
}
|
|
3589
|
+
function addUserConstant(ctx, fn) {
|
|
3590
|
+
ctx.definite = false;
|
|
3591
|
+
return addConstant(ctx, fn);
|
|
3592
|
+
}
|
|
3494
3593
|
function newVar(ctx) {
|
|
3495
3594
|
return `v${ctx.varCounter++}`;
|
|
3496
3595
|
}
|
|
@@ -3523,6 +3622,7 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
3523
3622
|
}
|
|
3524
3623
|
}
|
|
3525
3624
|
function emitRuntimeIsland(doc, ctx, schema, accessor) {
|
|
3625
|
+
ctx.definite = false;
|
|
3526
3626
|
const schemaConst = addConstant(ctx, schema);
|
|
3527
3627
|
const runConst = addConstant(ctx, runtimeRun);
|
|
3528
3628
|
const outVar = newVar(ctx);
|
|
@@ -3603,6 +3703,9 @@ function generateChecks(doc, ctx, schema, accessor) {
|
|
|
3603
3703
|
case "property":
|
|
3604
3704
|
generatePropertyCheck(doc, ctx, def, currentAccessor);
|
|
3605
3705
|
break;
|
|
3706
|
+
case "properties":
|
|
3707
|
+
generatePropertiesChecks(doc, ctx, def, currentAccessor);
|
|
3708
|
+
break;
|
|
3606
3709
|
case "overwrite": {
|
|
3607
3710
|
const newAccessor = newVar(ctx);
|
|
3608
3711
|
generateOverwriteCheck(doc, ctx, check, currentAccessor, newAccessor);
|
|
@@ -3708,6 +3811,19 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
|
|
|
3708
3811
|
doc.write(`if (!${mimeSet}.has(${accessor}.type)) return INVALID;`);
|
|
3709
3812
|
}
|
|
3710
3813
|
}
|
|
3814
|
+
function generatePropertiesChecks(doc, ctx, def, accessor) {
|
|
3815
|
+
if (def.when) {
|
|
3816
|
+
throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
|
|
3817
|
+
}
|
|
3818
|
+
doc.write(`if (${accessor} == null) return INVALID;`);
|
|
3819
|
+
const shape = def.shape;
|
|
3820
|
+
for (const key of Reflect.ownKeys(shape)) {
|
|
3821
|
+
const keyExpr = typeof key === "symbol" ? addConstant(ctx, key) : esc(key);
|
|
3822
|
+
const inputVar = newVar(ctx);
|
|
3823
|
+
doc.write(`const ${inputVar} = ${accessor}[${keyExpr}];`);
|
|
3824
|
+
compileChild(doc, ctx, shape[key], inputVar, false);
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3711
3827
|
function generatePropertyCheck(doc, ctx, def, accessor) {
|
|
3712
3828
|
const propAccessor = `${accessor}[${JSON.stringify(def.property)}]`;
|
|
3713
3829
|
generateCheck(doc, ctx, def.schema, propAccessor);
|
|
@@ -3735,7 +3851,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
|
|
|
3735
3851
|
if (isAsyncFunction(def.fn)) {
|
|
3736
3852
|
throw new ZodCompileAsyncError("z.compile: async .refine() predicates are not supported");
|
|
3737
3853
|
}
|
|
3738
|
-
const fnConst =
|
|
3854
|
+
const fnConst = addUserConstant(ctx, def.fn);
|
|
3739
3855
|
const throwAsyncConst = addConstant(ctx, throwAsync);
|
|
3740
3856
|
const resVar = newVar(ctx);
|
|
3741
3857
|
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
|
|
@@ -3755,7 +3871,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
|
|
|
3755
3871
|
throwAsync();
|
|
3756
3872
|
return fakePayload.issues.length === 0 ? fakePayload.value : INVALID;
|
|
3757
3873
|
};
|
|
3758
|
-
const helperConst =
|
|
3874
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
3759
3875
|
const outVar = newVar(ctx);
|
|
3760
3876
|
doc.write(`const ${outVar} = ${helperConst}(${accessor});`);
|
|
3761
3877
|
doc.write(`if (${outVar} === INVALID) return INVALID;`);
|
|
@@ -3789,7 +3905,7 @@ var PATTERN_IS_COMPLETE = new Set([
|
|
|
3789
3905
|
"uuid",
|
|
3790
3906
|
"xid"
|
|
3791
3907
|
]);
|
|
3792
|
-
function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
3908
|
+
function generateStringFormatCheck(doc, ctx, def, accessor, needsValue = true) {
|
|
3793
3909
|
const fmt = def.format;
|
|
3794
3910
|
if (fmt === "base64") {
|
|
3795
3911
|
const validator = addConstant(ctx, isValidBase64);
|
|
@@ -3822,9 +3938,14 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
|
3822
3938
|
doc.write(`if (!${validator}(${accessor})) return INVALID;`);
|
|
3823
3939
|
return accessor;
|
|
3824
3940
|
}
|
|
3941
|
+
if (fmt === "iban") {
|
|
3942
|
+
const validator = addConstant(ctx, isValidIBAN);
|
|
3943
|
+
doc.write(`if (!${validator}(${accessor})) return INVALID;`);
|
|
3944
|
+
return accessor;
|
|
3945
|
+
}
|
|
3825
3946
|
const formatDef = def;
|
|
3826
3947
|
if (fmt === "url" || fmt === "httpurl" || formatDef.normalize || formatDef.hostname !== undefined || formatDef.protocol !== undefined) {
|
|
3827
|
-
const parseConst = addConstant(ctx,
|
|
3948
|
+
const parseConst = addConstant(ctx, validateURL);
|
|
3828
3949
|
const defConst = addConstant(ctx, def);
|
|
3829
3950
|
const trimVar = newVar(ctx);
|
|
3830
3951
|
const urlVar = newVar(ctx);
|
|
@@ -3839,6 +3960,8 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
|
3839
3960
|
const protocolConst = addConstant(ctx, urlProtocolOk);
|
|
3840
3961
|
doc.write(`if (!${protocolConst}(${urlVar}, ${defConst}.protocol)) return INVALID;`);
|
|
3841
3962
|
}
|
|
3963
|
+
if (!needsValue)
|
|
3964
|
+
return null;
|
|
3842
3965
|
const outputVar = newVar(ctx);
|
|
3843
3966
|
const outputExpr = formatDef.normalize ? `${urlVar}.href` : `${addConstant(ctx, stripTabAndNewline)}(${trimVar})`;
|
|
3844
3967
|
doc.write(`const ${outputVar} = ${outputExpr};`);
|
|
@@ -3897,7 +4020,7 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
3897
4020
|
let typeAccessor;
|
|
3898
4021
|
switch (type) {
|
|
3899
4022
|
case "string":
|
|
3900
|
-
typeAccessor = generateStringCheck(doc, ctx, schema, accessor);
|
|
4023
|
+
typeAccessor = generateStringCheck(doc, ctx, schema, accessor, buildsValue);
|
|
3901
4024
|
break;
|
|
3902
4025
|
case "number":
|
|
3903
4026
|
typeAccessor = generateNumberCheck(doc, schema, accessor);
|
|
@@ -4017,12 +4140,12 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
4017
4140
|
return null;
|
|
4018
4141
|
return generateChecks(doc, ctx, schema, typeAccessor);
|
|
4019
4142
|
}
|
|
4020
|
-
function generateStringCheck(doc, ctx, schema, accessor) {
|
|
4143
|
+
function generateStringCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
4021
4144
|
doc.write(`if (typeof ${accessor} !== "string") return INVALID;`);
|
|
4022
4145
|
const def = schema._zod.def;
|
|
4023
4146
|
if (def.format === undefined)
|
|
4024
4147
|
return accessor;
|
|
4025
|
-
return generateStringFormatCheck(doc, ctx, def, accessor);
|
|
4148
|
+
return generateStringFormatCheck(doc, ctx, def, accessor, needsValue);
|
|
4026
4149
|
}
|
|
4027
4150
|
function generateNumberCheck(doc, schema, accessor) {
|
|
4028
4151
|
doc.write(`if (typeof ${accessor} !== "number" || !Number.isFinite(${accessor})) return INVALID;`);
|
|
@@ -4140,7 +4263,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
4140
4263
|
}
|
|
4141
4264
|
}
|
|
4142
4265
|
const outputVar = newVar(ctx);
|
|
4143
|
-
const hasConditionalKeys = allKeys.some((k) =>
|
|
4266
|
+
const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
|
|
4144
4267
|
if (!buildsValue) {
|
|
4145
4268
|
if (unknownKeysMode === "schema") {
|
|
4146
4269
|
const knownSet = keys.length > 0 ? addConstant(ctx, new Set(keys)) : null;
|
|
@@ -4167,7 +4290,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
4167
4290
|
const out = propOutputs.get(k);
|
|
4168
4291
|
if (dropsWhenAbsent(propShape[k])) {
|
|
4169
4292
|
doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
|
|
4170
|
-
} else if (
|
|
4293
|
+
} else if (mayOmitUndefined(propShape[k])) {
|
|
4171
4294
|
doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
|
|
4172
4295
|
} else {
|
|
4173
4296
|
doc.write(`${outputVar}[${kx}] = ${out};`);
|
|
@@ -4300,6 +4423,9 @@ function fastPathAcceptsAbsence(schema) {
|
|
|
4300
4423
|
function dropsWhenAbsent(schema) {
|
|
4301
4424
|
return schema._zod.optin === "optional" && schema._zod.optout === "optional";
|
|
4302
4425
|
}
|
|
4426
|
+
function mayOmitUndefined(schema) {
|
|
4427
|
+
return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
|
|
4428
|
+
}
|
|
4303
4429
|
function mayOutputUndefined(schema) {
|
|
4304
4430
|
const def = schema._zod.def;
|
|
4305
4431
|
switch (def.type) {
|
|
@@ -4642,6 +4768,7 @@ function literalEquality(ctx, accessor, value) {
|
|
|
4642
4768
|
}
|
|
4643
4769
|
function generateIntersectionCheck(doc, ctx, schema, accessor) {
|
|
4644
4770
|
const def = schema._zod.def;
|
|
4771
|
+
ctx.definite = false;
|
|
4645
4772
|
const leftOutput = compileChild(doc, ctx, def.left, accessor);
|
|
4646
4773
|
const rightOutput = compileChild(doc, ctx, def.right, accessor);
|
|
4647
4774
|
const mergeConst = addConstant(ctx, mergeValues);
|
|
@@ -4695,14 +4822,13 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
|
|
|
4695
4822
|
const keyIsBareString = keyDef.type === "string" && keyDef.format === undefined && !keyDef.coerce && (keyDef.checks?.length ?? 0) === 0;
|
|
4696
4823
|
if (!keyIsBareString) {
|
|
4697
4824
|
const isLoose = def.mode === "loose";
|
|
4698
|
-
const
|
|
4825
|
+
const keyFn = compileFn(def.keyType);
|
|
4826
|
+
if (keyFn.definite === false)
|
|
4827
|
+
ctx.definite = false;
|
|
4828
|
+
const keyFast = addConstant(ctx, keyFn);
|
|
4699
4829
|
const numericConst = addConstant(ctx, number);
|
|
4700
|
-
const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
|
|
4701
4830
|
const outKeyVar = newVar(ctx);
|
|
4702
|
-
doc
|
|
4703
|
-
doc.indented((d) => {
|
|
4704
|
-
d.write(`if (${kVar} === "__proto__") continue;`);
|
|
4705
|
-
d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4831
|
+
emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
|
|
4706
4832
|
d.write(`let ${outKeyVar} = ${keyFast}(${kVar});`);
|
|
4707
4833
|
d.write(`if (${outKeyVar} === INVALID && typeof ${kVar} === "string" && ${numericConst}.test(${kVar})) ${outKeyVar} = ${keyFast}(Number(${kVar}));`);
|
|
4708
4834
|
if (isLoose) {
|
|
@@ -4716,21 +4842,39 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
|
|
|
4716
4842
|
const valOutput = compileChild(d, ctx, def.valueType, valueVar);
|
|
4717
4843
|
d.write(`${outputVar}[${outKeyVar}] = ${valOutput};`);
|
|
4718
4844
|
});
|
|
4719
|
-
doc.write(`}`);
|
|
4720
4845
|
return outputVar;
|
|
4721
4846
|
}
|
|
4722
|
-
|
|
4723
|
-
doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
|
|
4724
|
-
doc.indented((d) => {
|
|
4725
|
-
d.write(`if (${kVar} === "__proto__") continue;`);
|
|
4726
|
-
d.write(`if (!${propIsEnumerable}.call(${accessor}, ${kVar})) continue;`);
|
|
4727
|
-
d.write(`if (typeof ${kVar} !== "string") return INVALID;`);
|
|
4847
|
+
emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
|
|
4728
4848
|
d.write(`const ${valVar} = ${accessor}[${kVar}];`);
|
|
4729
4849
|
const valOutput = compileChild(d, ctx, def.valueType, valVar);
|
|
4730
4850
|
d.write(`${outputVar}[${kVar}] = ${valOutput};`);
|
|
4851
|
+
}, `return INVALID;`);
|
|
4852
|
+
return outputVar;
|
|
4853
|
+
}
|
|
4854
|
+
function emitOwnKeys(doc, ctx, accessor, kVar, body, onSymbol) {
|
|
4855
|
+
const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
|
|
4856
|
+
const symsVar = newVar(ctx);
|
|
4857
|
+
const keysVar = newVar(ctx);
|
|
4858
|
+
const iVar = newVar(ctx);
|
|
4859
|
+
doc.write(`const ${symsVar} = Object.getOwnPropertySymbols(${accessor});`);
|
|
4860
|
+
doc.write(`const ${keysVar} = Object.getOwnPropertyNames(${accessor});`);
|
|
4861
|
+
doc.write(`for (let ${iVar} = 0; ${iVar} < ${keysVar}.length; ${iVar}++) {`);
|
|
4862
|
+
doc.indented((d) => {
|
|
4863
|
+
d.write(`const ${kVar} = ${keysVar}[${iVar}];`);
|
|
4864
|
+
d.write(`if (${kVar} === "__proto__" || !${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4865
|
+
body(d);
|
|
4866
|
+
});
|
|
4867
|
+
doc.write(`}`);
|
|
4868
|
+
doc.write(`for (let ${iVar} = 0; ${iVar} < ${symsVar}.length; ${iVar}++) {`);
|
|
4869
|
+
doc.indented((d) => {
|
|
4870
|
+
d.write(`const ${kVar} = ${symsVar}[${iVar}];`);
|
|
4871
|
+
d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4872
|
+
if (onSymbol)
|
|
4873
|
+
d.write(onSymbol);
|
|
4874
|
+
else
|
|
4875
|
+
body(d);
|
|
4731
4876
|
});
|
|
4732
4877
|
doc.write(`}`);
|
|
4733
|
-
return outputVar;
|
|
4734
4878
|
}
|
|
4735
4879
|
function literalPropertyKey(ctx, key) {
|
|
4736
4880
|
if (typeof key === "string")
|
|
@@ -4783,7 +4927,7 @@ function generateTemplateLiteralCheck(doc, ctx, schema, accessor) {
|
|
|
4783
4927
|
}
|
|
4784
4928
|
function generateLazyCheck(doc, ctx, schema, accessor) {
|
|
4785
4929
|
const def = schema._zod.def;
|
|
4786
|
-
const getterConst =
|
|
4930
|
+
const getterConst = addUserConstant(ctx, def.getter);
|
|
4787
4931
|
const cacheConst = addConstant(ctx, { parser: null });
|
|
4788
4932
|
doc.write(`if (!${cacheConst}.parser) {`);
|
|
4789
4933
|
doc.indented((d) => {
|
|
@@ -4816,7 +4960,7 @@ function generatePipeCheck(doc, ctx, schema, accessor) {
|
|
|
4816
4960
|
return INVALID;
|
|
4817
4961
|
return fakePayload.issues.length === 0 ? result : INVALID;
|
|
4818
4962
|
};
|
|
4819
|
-
const helperConst =
|
|
4963
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
4820
4964
|
const transformedVar = newVar(ctx);
|
|
4821
4965
|
doc.write(`const ${transformedVar} = ${helperConst}(${inputOutput});`);
|
|
4822
4966
|
doc.write(`if (${transformedVar} === INVALID) return INVALID;`);
|
|
@@ -4834,7 +4978,7 @@ function generateCustomCheck(doc, ctx, schema, accessor) {
|
|
|
4834
4978
|
if (isAsyncFunction(def.fn)) {
|
|
4835
4979
|
throw new ZodCompileAsyncError("z.compile: async custom predicates are not supported");
|
|
4836
4980
|
}
|
|
4837
|
-
const fnConst =
|
|
4981
|
+
const fnConst = addUserConstant(ctx, def.fn);
|
|
4838
4982
|
const throwAsyncConst = addConstant(ctx, throwAsync);
|
|
4839
4983
|
const resVar = newVar(ctx);
|
|
4840
4984
|
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
|
|
@@ -4867,7 +5011,7 @@ function generateCatchCheck(doc, ctx, schema, accessor) {
|
|
|
4867
5011
|
});
|
|
4868
5012
|
doc.write(`})();`);
|
|
4869
5013
|
const innerConst = addConstant(ctx, def.innerType);
|
|
4870
|
-
const catchConst =
|
|
5014
|
+
const catchConst = addUserConstant(ctx, def.catchValue);
|
|
4871
5015
|
const catchHelperConst = addConstant(ctx, runtimeCatch);
|
|
4872
5016
|
doc.write(`if (${outputVar} === INVALID) {`);
|
|
4873
5017
|
doc.indented((d) => {
|
|
@@ -4891,7 +5035,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
|
|
|
4891
5035
|
return INVALID;
|
|
4892
5036
|
return fakePayload.issues.length === 0 ? result : INVALID;
|
|
4893
5037
|
};
|
|
4894
|
-
const helperConst =
|
|
5038
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
4895
5039
|
const outputVar = newVar(ctx);
|
|
4896
5040
|
doc.write(`const ${outputVar} = ${helperConst}(${accessor});`);
|
|
4897
5041
|
doc.write(`if (${outputVar} === INVALID) return INVALID;`);
|
|
@@ -4900,11 +5044,13 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
|
|
|
4900
5044
|
return accessor;
|
|
4901
5045
|
}
|
|
4902
5046
|
// node_modules/zod/v4/core/api.js
|
|
5047
|
+
function snapshotChecks(def) {
|
|
5048
|
+
if (def.checks)
|
|
5049
|
+
def.checks = [...def.checks];
|
|
5050
|
+
return def;
|
|
5051
|
+
}
|
|
4903
5052
|
function _string(Class, params) {
|
|
4904
|
-
return new Class({
|
|
4905
|
-
type: "string",
|
|
4906
|
-
...normalizeParams(params)
|
|
4907
|
-
});
|
|
5053
|
+
return new Class(snapshotChecks({ type: "string", ...normalizeParams(params) }));
|
|
4908
5054
|
}
|
|
4909
5055
|
function _email(Class, params) {
|
|
4910
5056
|
return new Class({
|
|
@@ -5144,11 +5290,7 @@ function _isoDuration(Class, params) {
|
|
|
5144
5290
|
});
|
|
5145
5291
|
}
|
|
5146
5292
|
function _number(Class, params) {
|
|
5147
|
-
return new Class({
|
|
5148
|
-
type: "number",
|
|
5149
|
-
checks: [],
|
|
5150
|
-
...normalizeParams(params)
|
|
5151
|
-
});
|
|
5293
|
+
return new Class(snapshotChecks({ type: "number", checks: [], ...normalizeParams(params) }));
|
|
5152
5294
|
}
|
|
5153
5295
|
function _int(Class, params) {
|
|
5154
5296
|
return new Class({
|
|
@@ -5404,7 +5546,7 @@ function handleUnrepresentable(schema, ctx, json, params, message) {
|
|
|
5404
5546
|
Object.assign(json, result);
|
|
5405
5547
|
return true;
|
|
5406
5548
|
}
|
|
5407
|
-
function
|
|
5549
|
+
function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
5408
5550
|
var _a;
|
|
5409
5551
|
const def = schema._zod.def;
|
|
5410
5552
|
const seen = ctx.seen.get(schema);
|
|
@@ -5443,7 +5585,7 @@ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
|
5443
5585
|
if (parent) {
|
|
5444
5586
|
if (!result.ref)
|
|
5445
5587
|
result.ref = parent;
|
|
5446
|
-
|
|
5588
|
+
processSchema(parent, ctx, params);
|
|
5447
5589
|
ctx.seen.get(parent).isParent = true;
|
|
5448
5590
|
}
|
|
5449
5591
|
}
|
|
@@ -5548,7 +5690,6 @@ function extractDefs(ctx, schema) {
|
|
|
5548
5690
|
if (seen.count > 1) {
|
|
5549
5691
|
if (ctx.reused === "ref") {
|
|
5550
5692
|
extractToDef(entry);
|
|
5551
|
-
continue;
|
|
5552
5693
|
}
|
|
5553
5694
|
}
|
|
5554
5695
|
}
|
|
@@ -5873,18 +6014,106 @@ function isTransforming(_schema, _ctx) {
|
|
|
5873
6014
|
}
|
|
5874
6015
|
var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
5875
6016
|
const ctx = initializeContext({ ...params, processors });
|
|
5876
|
-
|
|
6017
|
+
processSchema(schema, ctx);
|
|
5877
6018
|
extractDefs(ctx, schema);
|
|
5878
6019
|
return finalize(ctx, schema);
|
|
5879
6020
|
};
|
|
5880
6021
|
var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
|
|
5881
6022
|
const { libraryOptions, target } = params ?? {};
|
|
5882
6023
|
const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
|
|
5883
|
-
|
|
6024
|
+
processSchema(schema, ctx);
|
|
5884
6025
|
extractDefs(ctx, schema);
|
|
5885
6026
|
return finalize(ctx, schema);
|
|
5886
6027
|
};
|
|
5887
6028
|
// node_modules/zod/v4/core/json-schema-processors.js
|
|
6029
|
+
var narrowMin = (agg, key, value) => {
|
|
6030
|
+
if (agg[key] === undefined || value > agg[key])
|
|
6031
|
+
agg[key] = value;
|
|
6032
|
+
};
|
|
6033
|
+
var narrowMax = (agg, key, value) => {
|
|
6034
|
+
if (agg[key] === undefined || value < agg[key])
|
|
6035
|
+
agg[key] = value;
|
|
6036
|
+
};
|
|
6037
|
+
var narrowBoth = (agg, value) => {
|
|
6038
|
+
narrowMin(agg, "minimum", value);
|
|
6039
|
+
narrowMax(agg, "maximum", value);
|
|
6040
|
+
};
|
|
6041
|
+
var addDivisor = (agg, value) => {
|
|
6042
|
+
agg.multipleOf ?? (agg.multipleOf = []);
|
|
6043
|
+
if (!agg.multipleOf.includes(value))
|
|
6044
|
+
agg.multipleOf.push(value);
|
|
6045
|
+
};
|
|
6046
|
+
var addPattern = (agg, pattern) => {
|
|
6047
|
+
agg.patterns ?? (agg.patterns = new Set);
|
|
6048
|
+
agg.patterns.add(pattern);
|
|
6049
|
+
};
|
|
6050
|
+
var intersectMime = (agg, mime) => {
|
|
6051
|
+
agg.mime = agg.mime ? agg.mime.filter((m) => mime.includes(m)) : [...mime];
|
|
6052
|
+
};
|
|
6053
|
+
var setFormat = (agg, format) => {
|
|
6054
|
+
agg.format = format;
|
|
6055
|
+
if (format.includes("int"))
|
|
6056
|
+
agg.isInt = true;
|
|
6057
|
+
};
|
|
6058
|
+
var minContributor = (agg, def) => narrowMin(agg, "minimum", def.minimum);
|
|
6059
|
+
var maxContributor = (agg, def) => narrowMax(agg, "maximum", def.maximum);
|
|
6060
|
+
var formatContributor = (ranges) => (agg, def) => {
|
|
6061
|
+
setFormat(agg, def.format);
|
|
6062
|
+
const [minimum, maximum] = ranges[def.format];
|
|
6063
|
+
narrowMin(agg, "minimum", minimum);
|
|
6064
|
+
narrowMax(agg, "maximum", maximum);
|
|
6065
|
+
};
|
|
6066
|
+
var contributors = {
|
|
6067
|
+
greater_than: (agg, def) => narrowMin(agg, def.inclusive ? "minimum" : "exclusiveMinimum", def.value),
|
|
6068
|
+
less_than: (agg, def) => narrowMax(agg, def.inclusive ? "maximum" : "exclusiveMaximum", def.value),
|
|
6069
|
+
multiple_of: (agg, def) => addDivisor(agg, def.value),
|
|
6070
|
+
number_format: formatContributor(NUMBER_FORMAT_RANGES),
|
|
6071
|
+
bigint_format: formatContributor(BIGINT_FORMAT_RANGES),
|
|
6072
|
+
min_length: minContributor,
|
|
6073
|
+
max_length: maxContributor,
|
|
6074
|
+
length_equals: (agg, def) => narrowBoth(agg, def.length),
|
|
6075
|
+
min_size: minContributor,
|
|
6076
|
+
max_size: maxContributor,
|
|
6077
|
+
size_equals: (agg, def) => narrowBoth(agg, def.size),
|
|
6078
|
+
string_format: (agg, def) => {
|
|
6079
|
+
setFormat(agg, def.format);
|
|
6080
|
+
if (def.pattern)
|
|
6081
|
+
addPattern(agg, def.pattern);
|
|
6082
|
+
if (def.format === "base64" || def.format === "base64url")
|
|
6083
|
+
agg.contentEncoding = def.format;
|
|
6084
|
+
if (def.local || def.precision === -1)
|
|
6085
|
+
agg.laxFormat = true;
|
|
6086
|
+
},
|
|
6087
|
+
mime_type: (agg, def) => intersectMime(agg, def.mime)
|
|
6088
|
+
};
|
|
6089
|
+
function aggregateChecks(schema) {
|
|
6090
|
+
const agg = {};
|
|
6091
|
+
const def = schema._zod.def;
|
|
6092
|
+
const list = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
|
|
6093
|
+
for (const ch of list)
|
|
6094
|
+
contributors[ch._zod.def.check]?.(agg, ch._zod.def);
|
|
6095
|
+
const bag = schema._zod.bag;
|
|
6096
|
+
if (bag.minimum !== undefined)
|
|
6097
|
+
narrowMin(agg, "minimum", bag.minimum);
|
|
6098
|
+
if (bag.exclusiveMinimum !== undefined)
|
|
6099
|
+
narrowMin(agg, "exclusiveMinimum", bag.exclusiveMinimum);
|
|
6100
|
+
if (bag.maximum !== undefined)
|
|
6101
|
+
narrowMax(agg, "maximum", bag.maximum);
|
|
6102
|
+
if (bag.exclusiveMaximum !== undefined)
|
|
6103
|
+
narrowMax(agg, "exclusiveMaximum", bag.exclusiveMaximum);
|
|
6104
|
+
if (bag.multipleOf !== undefined)
|
|
6105
|
+
addDivisor(agg, bag.multipleOf);
|
|
6106
|
+
if (bag.format !== undefined) {
|
|
6107
|
+
agg.format ?? (agg.format = bag.format);
|
|
6108
|
+
if (bag.format.includes("int"))
|
|
6109
|
+
agg.isInt = true;
|
|
6110
|
+
}
|
|
6111
|
+
if (bag.mime)
|
|
6112
|
+
intersectMime(agg, bag.mime);
|
|
6113
|
+
for (const pattern of bag.patterns ?? [])
|
|
6114
|
+
addPattern(agg, pattern);
|
|
6115
|
+
return agg;
|
|
6116
|
+
}
|
|
5888
6117
|
var formatMap = {
|
|
5889
6118
|
guid: "uuid",
|
|
5890
6119
|
url: "uri",
|
|
@@ -5892,10 +6121,15 @@ var formatMap = {
|
|
|
5892
6121
|
json_string: "json-string",
|
|
5893
6122
|
regex: ""
|
|
5894
6123
|
};
|
|
6124
|
+
var exactPatterns = new Map([
|
|
6125
|
+
[base64Charset, base64],
|
|
6126
|
+
[base64urlCharset, base64url]
|
|
6127
|
+
]);
|
|
6128
|
+
var exactPattern = (p) => exactPatterns.get(p) ?? p;
|
|
5895
6129
|
var stringProcessor = (schema, ctx, _json, _params) => {
|
|
5896
6130
|
const json = _json;
|
|
5897
6131
|
json.type = "string";
|
|
5898
|
-
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = schema
|
|
6132
|
+
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
5899
6133
|
if (typeof minimum === "number")
|
|
5900
6134
|
json.minLength = minimum;
|
|
5901
6135
|
if (typeof maximum === "number")
|
|
@@ -5911,7 +6145,7 @@ var stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
5911
6145
|
if (contentEncoding)
|
|
5912
6146
|
json.contentEncoding = contentEncoding;
|
|
5913
6147
|
if (patterns && patterns.size > 0) {
|
|
5914
|
-
const patternList = [...patterns];
|
|
6148
|
+
const patternList = [...patterns].map(exactPattern);
|
|
5915
6149
|
if (patternList.length === 1)
|
|
5916
6150
|
json.pattern = patternList[0].source;
|
|
5917
6151
|
else if (patternList.length > 1) {
|
|
@@ -5926,11 +6160,8 @@ var stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
5926
6160
|
};
|
|
5927
6161
|
var numberProcessor = (schema, ctx, _json, params) => {
|
|
5928
6162
|
const json = _json;
|
|
5929
|
-
const { minimum, maximum,
|
|
5930
|
-
|
|
5931
|
-
json.type = "integer";
|
|
5932
|
-
else
|
|
5933
|
-
json.type = "number";
|
|
6163
|
+
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
|
|
6164
|
+
json.type = isInt ? "integer" : "number";
|
|
5934
6165
|
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
5935
6166
|
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
|
|
5936
6167
|
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
|
|
@@ -5954,11 +6185,19 @@ var numberProcessor = (schema, ctx, _json, params) => {
|
|
|
5954
6185
|
} else if (typeof maximum === "number") {
|
|
5955
6186
|
json.maximum = maximum;
|
|
5956
6187
|
}
|
|
5957
|
-
if (
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
6188
|
+
if (multipleOf) {
|
|
6189
|
+
const divisors = new Set;
|
|
6190
|
+
for (const divisor of multipleOf) {
|
|
6191
|
+
if (Number.isFinite(divisor) && divisor !== 0)
|
|
6192
|
+
divisors.add(Math.abs(divisor));
|
|
6193
|
+
else
|
|
6194
|
+
handleUnrepresentable(schema, ctx, json, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
|
|
6195
|
+
}
|
|
6196
|
+
const [first, ...rest] = divisors;
|
|
6197
|
+
if (first !== undefined)
|
|
6198
|
+
json.multipleOf = first;
|
|
6199
|
+
if (rest.length)
|
|
6200
|
+
json.allOf = [...json.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
|
|
5962
6201
|
}
|
|
5963
6202
|
};
|
|
5964
6203
|
var booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
@@ -6029,13 +6268,13 @@ var transformProcessor = (schema, ctx, json, params) => {
|
|
|
6029
6268
|
var arrayProcessor = (schema, ctx, _json, params) => {
|
|
6030
6269
|
const json = _json;
|
|
6031
6270
|
const def = schema._zod.def;
|
|
6032
|
-
const { minimum, maximum } = schema
|
|
6271
|
+
const { minimum, maximum } = aggregateChecks(schema);
|
|
6033
6272
|
if (typeof minimum === "number")
|
|
6034
6273
|
json.minItems = minimum;
|
|
6035
6274
|
if (typeof maximum === "number")
|
|
6036
6275
|
json.maxItems = maximum;
|
|
6037
6276
|
json.type = "array";
|
|
6038
|
-
json.items =
|
|
6277
|
+
json.items = processSchema(def.element, ctx, {
|
|
6039
6278
|
...params,
|
|
6040
6279
|
path: [...params.path, "items"]
|
|
6041
6280
|
});
|
|
@@ -6061,22 +6300,20 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
6061
6300
|
json.type = "object";
|
|
6062
6301
|
json.properties = {};
|
|
6063
6302
|
for (const key in shape) {
|
|
6064
|
-
assignProp(json.properties, key,
|
|
6303
|
+
assignProp(json.properties, key, processSchema(shape[key], ctx, {
|
|
6065
6304
|
...params,
|
|
6066
6305
|
path: [...params.path, "properties", key]
|
|
6067
6306
|
}));
|
|
6068
6307
|
}
|
|
6069
|
-
const
|
|
6070
|
-
const
|
|
6308
|
+
const requiredKeys = [];
|
|
6309
|
+
for (const key of Object.keys(shape)) {
|
|
6071
6310
|
const field = def.shape[key];
|
|
6072
|
-
if (ctx.io === "input") {
|
|
6073
|
-
|
|
6074
|
-
} else {
|
|
6075
|
-
return field._zod.optout === undefined;
|
|
6311
|
+
if (ctx.io === "input" ? inputOptin(field) === undefined : field._zod.optout === undefined) {
|
|
6312
|
+
requiredKeys.push(key);
|
|
6076
6313
|
}
|
|
6077
|
-
}
|
|
6078
|
-
if (requiredKeys.
|
|
6079
|
-
json.required =
|
|
6314
|
+
}
|
|
6315
|
+
if (requiredKeys.length > 0) {
|
|
6316
|
+
json.required = requiredKeys;
|
|
6080
6317
|
}
|
|
6081
6318
|
if (def.catchall?._zod.def.type === "never") {
|
|
6082
6319
|
json.additionalProperties = false;
|
|
@@ -6084,7 +6321,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
6084
6321
|
if (ctx.io === "output")
|
|
6085
6322
|
json.additionalProperties = false;
|
|
6086
6323
|
} else if (def.catchall) {
|
|
6087
|
-
json.additionalProperties =
|
|
6324
|
+
json.additionalProperties = processSchema(def.catchall, ctx, {
|
|
6088
6325
|
...params,
|
|
6089
6326
|
path: [...params.path, "additionalProperties"]
|
|
6090
6327
|
});
|
|
@@ -6093,7 +6330,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
6093
6330
|
var unionProcessor = (schema, ctx, json, params) => {
|
|
6094
6331
|
const def = schema._zod.def;
|
|
6095
6332
|
const isExclusive = def.inclusive === false;
|
|
6096
|
-
const options = def.options.map((x, i) =>
|
|
6333
|
+
const options = def.options.map((x, i) => processSchema(x, ctx, {
|
|
6097
6334
|
...params,
|
|
6098
6335
|
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
|
|
6099
6336
|
}));
|
|
@@ -6105,11 +6342,11 @@ var unionProcessor = (schema, ctx, json, params) => {
|
|
|
6105
6342
|
};
|
|
6106
6343
|
var intersectionProcessor = (schema, ctx, json, params) => {
|
|
6107
6344
|
const def = schema._zod.def;
|
|
6108
|
-
const a =
|
|
6345
|
+
const a = processSchema(def.left, ctx, {
|
|
6109
6346
|
...params,
|
|
6110
6347
|
path: [...params.path, "allOf", 0]
|
|
6111
6348
|
});
|
|
6112
|
-
const b =
|
|
6349
|
+
const b = processSchema(def.right, ctx, {
|
|
6113
6350
|
...params,
|
|
6114
6351
|
path: [...params.path, "allOf", 1]
|
|
6115
6352
|
});
|
|
@@ -6189,20 +6426,19 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
6189
6426
|
const def = schema._zod.def;
|
|
6190
6427
|
json.type = "object";
|
|
6191
6428
|
const keyType = def.keyType;
|
|
6192
|
-
const
|
|
6193
|
-
const patterns = keyBag?.patterns;
|
|
6429
|
+
const patterns = aggregateChecks(keyType).patterns;
|
|
6194
6430
|
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
6195
|
-
const valueSchema =
|
|
6431
|
+
const valueSchema = processSchema(def.valueType, ctx, {
|
|
6196
6432
|
...params,
|
|
6197
6433
|
path: [...params.path, "patternProperties", "*"]
|
|
6198
6434
|
});
|
|
6199
6435
|
json.patternProperties = {};
|
|
6200
6436
|
for (const pattern of patterns) {
|
|
6201
|
-
assignProp(json.patternProperties, pattern.source, valueSchema);
|
|
6437
|
+
assignProp(json.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
6202
6438
|
}
|
|
6203
6439
|
} else {
|
|
6204
6440
|
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
6205
|
-
json.propertyNames =
|
|
6441
|
+
json.propertyNames = processSchema(def.keyType, ctx, {
|
|
6206
6442
|
...params,
|
|
6207
6443
|
path: [...params.path, "propertyNames"]
|
|
6208
6444
|
});
|
|
@@ -6214,7 +6450,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
6214
6450
|
}
|
|
6215
6451
|
pending.push(schema);
|
|
6216
6452
|
}
|
|
6217
|
-
json.additionalProperties =
|
|
6453
|
+
json.additionalProperties = processSchema(def.valueType, ctx, {
|
|
6218
6454
|
...params,
|
|
6219
6455
|
path: [...params.path, "additionalProperties"]
|
|
6220
6456
|
});
|
|
@@ -6230,7 +6466,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
6230
6466
|
};
|
|
6231
6467
|
var nullableProcessor = (schema, ctx, json, params) => {
|
|
6232
6468
|
const def = schema._zod.def;
|
|
6233
|
-
const inner =
|
|
6469
|
+
const inner = processSchema(def.innerType, ctx, params);
|
|
6234
6470
|
const seen = ctx.seen.get(schema);
|
|
6235
6471
|
if (ctx.target === "openapi-3.0") {
|
|
6236
6472
|
seen.ref = def.innerType;
|
|
@@ -6241,7 +6477,7 @@ var nullableProcessor = (schema, ctx, json, params) => {
|
|
|
6241
6477
|
};
|
|
6242
6478
|
var nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
6243
6479
|
const def = schema._zod.def;
|
|
6244
|
-
|
|
6480
|
+
processSchema(def.innerType, ctx, params);
|
|
6245
6481
|
const seen = ctx.seen.get(schema);
|
|
6246
6482
|
seen.ref = def.innerType;
|
|
6247
6483
|
};
|
|
@@ -6261,7 +6497,7 @@ function serializeDefaultValue(value, schema, ctx, json, params) {
|
|
|
6261
6497
|
}
|
|
6262
6498
|
var defaultProcessor = (schema, ctx, json, params) => {
|
|
6263
6499
|
const def = schema._zod.def;
|
|
6264
|
-
|
|
6500
|
+
processSchema(def.innerType, ctx, params);
|
|
6265
6501
|
const seen = ctx.seen.get(schema);
|
|
6266
6502
|
seen.ref = def.innerType;
|
|
6267
6503
|
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);
|
|
@@ -6270,7 +6506,7 @@ var defaultProcessor = (schema, ctx, json, params) => {
|
|
|
6270
6506
|
};
|
|
6271
6507
|
var prefaultProcessor = (schema, ctx, json, params) => {
|
|
6272
6508
|
const def = schema._zod.def;
|
|
6273
|
-
|
|
6509
|
+
processSchema(def.innerType, ctx, params);
|
|
6274
6510
|
const seen = ctx.seen.get(schema);
|
|
6275
6511
|
seen.ref = def.innerType;
|
|
6276
6512
|
if (ctx.io !== "input")
|
|
@@ -6281,7 +6517,7 @@ var prefaultProcessor = (schema, ctx, json, params) => {
|
|
|
6281
6517
|
};
|
|
6282
6518
|
var catchProcessor = (schema, ctx, json, params) => {
|
|
6283
6519
|
const def = schema._zod.def;
|
|
6284
|
-
|
|
6520
|
+
processSchema(def.innerType, ctx, params);
|
|
6285
6521
|
const seen = ctx.seen.get(schema);
|
|
6286
6522
|
seen.ref = def.innerType;
|
|
6287
6523
|
let catchValue;
|
|
@@ -6297,20 +6533,20 @@ var pipeProcessor = (schema, ctx, _json, params) => {
|
|
|
6297
6533
|
const def = schema._zod.def;
|
|
6298
6534
|
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
|
|
6299
6535
|
const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
|
|
6300
|
-
|
|
6536
|
+
processSchema(innerType, ctx, params);
|
|
6301
6537
|
const seen = ctx.seen.get(schema);
|
|
6302
6538
|
seen.ref = innerType;
|
|
6303
6539
|
};
|
|
6304
6540
|
var readonlyProcessor = (schema, ctx, json, params) => {
|
|
6305
6541
|
const def = schema._zod.def;
|
|
6306
|
-
|
|
6542
|
+
processSchema(def.innerType, ctx, params);
|
|
6307
6543
|
const seen = ctx.seen.get(schema);
|
|
6308
6544
|
seen.ref = def.innerType;
|
|
6309
6545
|
json.readOnly = true;
|
|
6310
6546
|
};
|
|
6311
6547
|
var optionalProcessor = (schema, ctx, _json, params) => {
|
|
6312
6548
|
const def = schema._zod.def;
|
|
6313
|
-
|
|
6549
|
+
processSchema(def.innerType, ctx, params);
|
|
6314
6550
|
const seen = ctx.seen.get(schema);
|
|
6315
6551
|
seen.ref = def.innerType;
|
|
6316
6552
|
};
|
|
@@ -6360,10 +6596,10 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, undefi
|
|
|
6360
6596
|
});
|
|
6361
6597
|
|
|
6362
6598
|
// node_modules/zod/v4/classic/parse.js
|
|
6363
|
-
var
|
|
6364
|
-
var
|
|
6365
|
-
var
|
|
6366
|
-
var
|
|
6599
|
+
var parse2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
6600
|
+
var parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
6601
|
+
var safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
6602
|
+
var safeParseAsync = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
6367
6603
|
var encode = /* @__PURE__ */ _encode(ZodRealError);
|
|
6368
6604
|
var decode = /* @__PURE__ */ _decode(ZodRealError);
|
|
6369
6605
|
var encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
@@ -6496,16 +6732,16 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
6496
6732
|
own(this, "~standard", value);
|
|
6497
6733
|
},
|
|
6498
6734
|
parse: function _parse(data, params) {
|
|
6499
|
-
return
|
|
6735
|
+
return parse2(this, data, params, { callee: _parse });
|
|
6500
6736
|
},
|
|
6501
6737
|
parseAsync: async function _parseAsync(data, params) {
|
|
6502
|
-
return await
|
|
6738
|
+
return await parseAsync(this, data, params, { callee: _parseAsync });
|
|
6503
6739
|
},
|
|
6504
6740
|
safeParse(data, params) {
|
|
6505
|
-
return
|
|
6741
|
+
return safeParse(this, data, params);
|
|
6506
6742
|
},
|
|
6507
6743
|
async safeParseAsync(data, params) {
|
|
6508
|
-
return
|
|
6744
|
+
return safeParseAsync(this, data, params);
|
|
6509
6745
|
},
|
|
6510
6746
|
get spa() {
|
|
6511
6747
|
return this?.safeParseAsync;
|
|
@@ -6513,6 +6749,12 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
6513
6749
|
set spa(value) {
|
|
6514
6750
|
own(this, "spa", value);
|
|
6515
6751
|
},
|
|
6752
|
+
validate(data, params) {
|
|
6753
|
+
return validate(this, data, params);
|
|
6754
|
+
},
|
|
6755
|
+
validateAsync(data, params) {
|
|
6756
|
+
return validateAsync(this, data, params);
|
|
6757
|
+
},
|
|
6516
6758
|
encode: function _encode(data, params) {
|
|
6517
6759
|
return encode(this, data, params, { callee: _encode });
|
|
6518
6760
|
},
|
|
@@ -6551,10 +6793,10 @@ var _ZodString = /* @__PURE__ */ $constructor("_ZodString", (inst, def) => {
|
|
|
6551
6793
|
$ZodString.init(inst, def);
|
|
6552
6794
|
ZodType.init(inst, def);
|
|
6553
6795
|
inst._zod.processJSONSchema = (ctx, json, params) => stringProcessor(inst, ctx, json, params);
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6796
|
+
}, /* @__PURE__ */ derived({
|
|
6797
|
+
format: (inst) => aggregateChecks(inst).format ?? null,
|
|
6798
|
+
minLength: (inst) => aggregateChecks(inst).minimum ?? null,
|
|
6799
|
+
maxLength: (inst) => aggregateChecks(inst).maximum ?? null
|
|
6558
6800
|
}, {
|
|
6559
6801
|
regex(...args) {
|
|
6560
6802
|
return this.check(_regex(...args));
|
|
@@ -6601,7 +6843,7 @@ var _ZodString = /* @__PURE__ */ $constructor("_ZodString", (inst, def) => {
|
|
|
6601
6843
|
slugify() {
|
|
6602
6844
|
return this.check(_slugify());
|
|
6603
6845
|
}
|
|
6604
|
-
});
|
|
6846
|
+
}));
|
|
6605
6847
|
var ZodString = /* @__PURE__ */ $constructor("ZodString", (inst, def) => {
|
|
6606
6848
|
$ZodString.init(inst, def);
|
|
6607
6849
|
_ZodString.init(inst, def);
|
|
@@ -6788,12 +7030,21 @@ var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
|
|
|
6788
7030
|
$ZodNumber.init(inst, def);
|
|
6789
7031
|
ZodType.init(inst, def);
|
|
6790
7032
|
inst._zod.processJSONSchema = (ctx, json, params) => numberProcessor(inst, ctx, json, params);
|
|
6791
|
-
const bag = inst._zod.bag;
|
|
6792
|
-
inst.minValue = Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null;
|
|
6793
|
-
inst.maxValue = Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null;
|
|
6794
|
-
inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5);
|
|
6795
7033
|
inst.isFinite = true;
|
|
6796
|
-
|
|
7034
|
+
}, /* @__PURE__ */ derived({
|
|
7035
|
+
minValue: (inst) => {
|
|
7036
|
+
const { minimum, exclusiveMinimum } = aggregateChecks(inst);
|
|
7037
|
+
return Math.max(minimum ?? Number.NEGATIVE_INFINITY, exclusiveMinimum ?? Number.NEGATIVE_INFINITY);
|
|
7038
|
+
},
|
|
7039
|
+
maxValue: (inst) => {
|
|
7040
|
+
const { maximum, exclusiveMaximum } = aggregateChecks(inst);
|
|
7041
|
+
return Math.min(maximum ?? Number.POSITIVE_INFINITY, exclusiveMaximum ?? Number.POSITIVE_INFINITY);
|
|
7042
|
+
},
|
|
7043
|
+
isInt: (inst) => {
|
|
7044
|
+
const { isInt, multipleOf } = aggregateChecks(inst);
|
|
7045
|
+
return !!isInt || !!multipleOf?.some(Number.isSafeInteger);
|
|
7046
|
+
},
|
|
7047
|
+
format: (inst) => aggregateChecks(inst).format ?? null
|
|
6797
7048
|
}, {
|
|
6798
7049
|
gt(value, params) {
|
|
6799
7050
|
return this.check(_gt(value, params));
|
|
@@ -6840,7 +7091,7 @@ var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
|
|
|
6840
7091
|
finite() {
|
|
6841
7092
|
return this;
|
|
6842
7093
|
}
|
|
6843
|
-
});
|
|
7094
|
+
}));
|
|
6844
7095
|
function number2(params) {
|
|
6845
7096
|
return _number(ZodNumber, params);
|
|
6846
7097
|
}
|
|
@@ -6912,19 +7163,19 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
|
|
|
6912
7163
|
return _enum(Object.keys(this._zod.def.shape));
|
|
6913
7164
|
},
|
|
6914
7165
|
catchall(catchall) {
|
|
6915
|
-
return this.clone(
|
|
7166
|
+
return this.clone(mergeDefs(this._zod.def, { catchall }));
|
|
6916
7167
|
},
|
|
6917
7168
|
passthrough() {
|
|
6918
|
-
return this.clone(
|
|
7169
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));
|
|
6919
7170
|
},
|
|
6920
7171
|
loose() {
|
|
6921
|
-
return this.clone(
|
|
7172
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));
|
|
6922
7173
|
},
|
|
6923
7174
|
strict() {
|
|
6924
|
-
return this.clone(
|
|
7175
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: never() }));
|
|
6925
7176
|
},
|
|
6926
7177
|
strip() {
|
|
6927
|
-
return this.clone(
|
|
7178
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: undefined }));
|
|
6928
7179
|
},
|
|
6929
7180
|
extend(incoming) {
|
|
6930
7181
|
return extend(this, incoming);
|
|
@@ -7025,7 +7276,7 @@ var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
|
7025
7276
|
ZodType.init(inst, def);
|
|
7026
7277
|
inst._zod.processJSONSchema = (ctx, json, params) => enumProcessor(inst, ctx, json, params);
|
|
7027
7278
|
inst.enum = def.entries;
|
|
7028
|
-
inst.options =
|
|
7279
|
+
inst.options = [...inst._zod.values];
|
|
7029
7280
|
const keys = new Set(Object.keys(def.entries));
|
|
7030
7281
|
inst.extract = (values, params) => {
|
|
7031
7282
|
const newEntries = {};
|
|
@@ -8040,10 +8291,10 @@ var success = (revisionValue, workspaceRevisionValue, data) => ({
|
|
|
8040
8291
|
workspaceRevision: workspaceRevisionValue,
|
|
8041
8292
|
data
|
|
8042
8293
|
});
|
|
8043
|
-
var
|
|
8294
|
+
var failure2 = (code, error, details = {}) => ({ ok: false, schemaVersion: 1, code, error, details });
|
|
8044
8295
|
function parseOperation(family, input) {
|
|
8045
8296
|
if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
|
|
8046
|
-
return
|
|
8297
|
+
return failure2("unsupported_version", "unsupported schema version", { operation: family });
|
|
8047
8298
|
const compiled = compiledOperationSchemas[family].safeParse(input);
|
|
8048
8299
|
const parsed = compiled.success ? operationSchemas[family].safeParse(input) : compiled;
|
|
8049
8300
|
if (parsed.success)
|
|
@@ -8052,7 +8303,7 @@ function parseOperation(family, input) {
|
|
|
8052
8303
|
path: issue.code === "unrecognized_keys" ? issue.keys.join(".") : issue.path.join("."),
|
|
8053
8304
|
reason: issue.message
|
|
8054
8305
|
}));
|
|
8055
|
-
return
|
|
8306
|
+
return failure2("invalid_input", "operation input is invalid", { fields });
|
|
8056
8307
|
}
|
|
8057
8308
|
function canonical(value, seen) {
|
|
8058
8309
|
if (value === null || typeof value === "boolean" || typeof value === "string") {
|
|
@@ -8084,7 +8335,7 @@ function canonical(value, seen) {
|
|
|
8084
8335
|
throw new TypeError("symbol key is not JSON");
|
|
8085
8336
|
if (Object.keys(value).some((key) => invalidUnicode(key)))
|
|
8086
8337
|
throw new TypeError("invalid Unicode");
|
|
8087
|
-
result = Object.fromEntries(Object.keys(value).
|
|
8338
|
+
result = Object.fromEntries(Object.keys(value).toSorted().map((key) => [key, canonical(value[key], seen)]));
|
|
8088
8339
|
}
|
|
8089
8340
|
seen.delete(value);
|
|
8090
8341
|
return result;
|
|
@@ -8126,14 +8377,14 @@ function decisionDigest(input) {
|
|
|
8126
8377
|
function candidateDigest(input) {
|
|
8127
8378
|
const normalizedScope = {
|
|
8128
8379
|
description: input.scope.description,
|
|
8129
|
-
paths: [...input.scope.paths].
|
|
8130
|
-
exclusions: [...input.scope.exclusions].
|
|
8380
|
+
paths: [...input.scope.paths].toSorted(compareCodeUnits),
|
|
8381
|
+
exclusions: [...input.scope.exclusions].toSorted(compareCodeUnits)
|
|
8131
8382
|
};
|
|
8132
8383
|
return sha256({
|
|
8133
8384
|
scope: normalizedScope,
|
|
8134
8385
|
completeness: input.completeness,
|
|
8135
|
-
files: [...input.files].
|
|
8136
|
-
environment: input.environment.map(({ name, value }) => ({ name, value })).
|
|
8386
|
+
files: [...input.files].toSorted((left, right) => compareCodeUnits(left.path, right.path) || compareCodeUnits(left.kind, right.kind) || compareNullableText(left.digest, right.digest) || compareBooleanNullable(left.executable, right.executable)),
|
|
8387
|
+
environment: input.environment.map(({ name, value }) => ({ name, value })).toSorted((left, right) => compareCodeUnits(left.name, right.name) || compareNullableText(left.value, right.value)),
|
|
8137
8388
|
head: input.head
|
|
8138
8389
|
});
|
|
8139
8390
|
}
|
|
@@ -8142,8 +8393,8 @@ function requirementId(input) {
|
|
|
8142
8393
|
...input,
|
|
8143
8394
|
scope: {
|
|
8144
8395
|
description: input.scope.description,
|
|
8145
|
-
paths: [...input.scope.paths].
|
|
8146
|
-
exclusions: [...input.scope.exclusions].
|
|
8396
|
+
paths: [...input.scope.paths].toSorted(compareCodeUnits),
|
|
8397
|
+
exclusions: [...input.scope.exclusions].toSorted(compareCodeUnits)
|
|
8147
8398
|
}
|
|
8148
8399
|
});
|
|
8149
8400
|
}
|
|
@@ -8841,10 +9092,10 @@ var stampNew = (record) => ({
|
|
|
8841
9092
|
});
|
|
8842
9093
|
var isNewerVersion = (candidate, current) => {
|
|
8843
9094
|
const parts = (value) => value.split("-")[0].split(".").map((item) => Number.parseInt(item, 10) || 0);
|
|
8844
|
-
const [
|
|
9095
|
+
const [candidateParts, currentParts] = [parts(candidate), parts(current)];
|
|
8845
9096
|
for (let index = 0;index < 3; index += 1) {
|
|
8846
|
-
const left =
|
|
8847
|
-
const right =
|
|
9097
|
+
const left = candidateParts[index] ?? 0;
|
|
9098
|
+
const right = currentParts[index] ?? 0;
|
|
8848
9099
|
if (left !== right)
|
|
8849
9100
|
return left > right;
|
|
8850
9101
|
}
|
|
@@ -8902,18 +9153,18 @@ class TaskStore {
|
|
|
8902
9153
|
}
|
|
8903
9154
|
readTask(taskId) {
|
|
8904
9155
|
if (!validId(taskId))
|
|
8905
|
-
return
|
|
9156
|
+
return failure2("invalid_input", "task ID is invalid", { taskId });
|
|
8906
9157
|
const result = this.readRecord(path4.join(this.tasksDir, `${taskId}.json`), taskRecordSchema);
|
|
8907
9158
|
if (!result.exists)
|
|
8908
|
-
return
|
|
9159
|
+
return failure2("not_found", "task not found", { taskId });
|
|
8909
9160
|
if (result.result.ok && result.result.data.id !== taskId)
|
|
8910
|
-
return
|
|
9161
|
+
return failure2("recovery_required", "task filename and record ID differ", { taskId });
|
|
8911
9162
|
if (result.result.ok) {
|
|
8912
9163
|
const workspace = this.readWorkspace();
|
|
8913
9164
|
if (!workspace.ok)
|
|
8914
9165
|
return workspace;
|
|
8915
9166
|
if (!workspace.data || result.result.data.workspaceId !== workspace.data.id)
|
|
8916
|
-
return
|
|
9167
|
+
return failure2("recovery_required", "task workspace binding is invalid", { taskId });
|
|
8917
9168
|
}
|
|
8918
9169
|
return result.result;
|
|
8919
9170
|
}
|
|
@@ -8924,7 +9175,7 @@ class TaskStore {
|
|
|
8924
9175
|
try {
|
|
8925
9176
|
names = fs4.readdirSync(this.tasksDir).filter((name) => name.endsWith(".json"));
|
|
8926
9177
|
} catch (error) {
|
|
8927
|
-
return
|
|
9178
|
+
return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
|
|
8928
9179
|
path: this.tasksDir
|
|
8929
9180
|
});
|
|
8930
9181
|
}
|
|
@@ -8932,20 +9183,20 @@ class TaskStore {
|
|
|
8932
9183
|
if (!workspace.ok)
|
|
8933
9184
|
return workspace;
|
|
8934
9185
|
if (!workspace.data)
|
|
8935
|
-
return
|
|
9186
|
+
return failure2("recovery_required", "task workspace binding is invalid", {
|
|
8936
9187
|
path: this.workspacePath
|
|
8937
9188
|
});
|
|
8938
9189
|
const tasks = [];
|
|
8939
|
-
for (const name of names.
|
|
9190
|
+
for (const name of names.toSorted()) {
|
|
8940
9191
|
const item = this.readRecord(path4.join(this.tasksDir, name), taskRecordSchema);
|
|
8941
9192
|
if (!item.exists)
|
|
8942
9193
|
continue;
|
|
8943
9194
|
if (!item.result.ok)
|
|
8944
9195
|
return item.result;
|
|
8945
9196
|
if (!validId(name.slice(0, -5)) || item.result.data.id !== name.slice(0, -5))
|
|
8946
|
-
return
|
|
9197
|
+
return failure2("recovery_required", "task filename and record ID differ", { path: name });
|
|
8947
9198
|
if (item.result.data.workspaceId !== workspace.data.id)
|
|
8948
|
-
return
|
|
9199
|
+
return failure2("recovery_required", "task workspace binding is invalid", { path: name });
|
|
8949
9200
|
tasks.push(item.result.data);
|
|
8950
9201
|
}
|
|
8951
9202
|
return success(null, null, tasks);
|
|
@@ -8957,7 +9208,7 @@ class TaskStore {
|
|
|
8957
9208
|
try {
|
|
8958
9209
|
names = fs4.readdirSync(this.tasksDir).filter((name) => name.endsWith(".json"));
|
|
8959
9210
|
} catch (error) {
|
|
8960
|
-
return
|
|
9211
|
+
return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
|
|
8961
9212
|
path: this.tasksDir
|
|
8962
9213
|
});
|
|
8963
9214
|
}
|
|
@@ -8965,13 +9216,13 @@ class TaskStore {
|
|
|
8965
9216
|
if (!workspace.ok)
|
|
8966
9217
|
return workspace;
|
|
8967
9218
|
if (!workspace.data)
|
|
8968
|
-
return
|
|
9219
|
+
return failure2("recovery_required", "task workspace binding is invalid", {
|
|
8969
9220
|
path: this.workspacePath
|
|
8970
9221
|
});
|
|
8971
9222
|
const stored = this.readIndex(workspace.data.id);
|
|
8972
9223
|
const entries = [];
|
|
8973
9224
|
let changed = Object.keys(stored).length !== names.length;
|
|
8974
|
-
for (const name of names.
|
|
9225
|
+
for (const name of names.toSorted()) {
|
|
8975
9226
|
const file = path4.join(this.tasksDir, name);
|
|
8976
9227
|
const signature = fileSignature(file);
|
|
8977
9228
|
if (signature === null) {
|
|
@@ -8989,9 +9240,9 @@ class TaskStore {
|
|
|
8989
9240
|
if (!item.result.ok)
|
|
8990
9241
|
return item.result;
|
|
8991
9242
|
if (!validId(name.slice(0, -5)) || item.result.data.id !== name.slice(0, -5))
|
|
8992
|
-
return
|
|
9243
|
+
return failure2("recovery_required", "task filename and record ID differ", { path: name });
|
|
8993
9244
|
if (item.result.data.workspaceId !== workspace.data.id)
|
|
8994
|
-
return
|
|
9245
|
+
return failure2("recovery_required", "task workspace binding is invalid", { path: name });
|
|
8995
9246
|
const entry = indexEntry(item.result.data, signature);
|
|
8996
9247
|
if (!cached || canonicalJson(cached) !== canonicalJson(entry))
|
|
8997
9248
|
changed = true;
|
|
@@ -9006,7 +9257,7 @@ class TaskStore {
|
|
|
9006
9257
|
if (!item.exists)
|
|
9007
9258
|
return success(null, null, null);
|
|
9008
9259
|
if (item.result.ok && item.result.data.root !== this.root && !sameDirectoryIdentity(item.result.data.root, this.root))
|
|
9009
|
-
return
|
|
9260
|
+
return failure2("recovery_required", "workspace root binding is invalid", {
|
|
9010
9261
|
path: this.workspacePath
|
|
9011
9262
|
});
|
|
9012
9263
|
return item.result;
|
|
@@ -9022,18 +9273,18 @@ class TaskStore {
|
|
|
9022
9273
|
if (!current.ok)
|
|
9023
9274
|
return current;
|
|
9024
9275
|
if (current.data ? value.expectedWorkspaceRevision !== current.data.revision : value.expectedWorkspaceRevision !== null) {
|
|
9025
|
-
return
|
|
9276
|
+
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", {
|
|
9026
9277
|
expectedWorkspaceRevision: value.expectedWorkspaceRevision,
|
|
9027
9278
|
actualWorkspaceRevision: current.data?.revision ?? null
|
|
9028
9279
|
});
|
|
9029
9280
|
}
|
|
9030
9281
|
if (!value.provenance)
|
|
9031
|
-
return
|
|
9282
|
+
return failure2("invalid_input", "provenance is required");
|
|
9032
9283
|
if (!intentSchema.safeParse(value.intent).success || !provenanceSchema.safeParse(value.provenance).success)
|
|
9033
|
-
return
|
|
9284
|
+
return failure2("invalid_input", "task intent or provenance is invalid");
|
|
9034
9285
|
const previousWorkspaceBytes = current.data ? this.snapshotBytes(this.workspacePath) : null;
|
|
9035
9286
|
if (current.data && !previousWorkspaceBytes)
|
|
9036
|
-
return
|
|
9287
|
+
return failure2("storage_error", "workspace snapshot disappeared during creation");
|
|
9037
9288
|
const workspace = current.data ? {
|
|
9038
9289
|
...current.data,
|
|
9039
9290
|
revision: newRevision(),
|
|
@@ -9084,9 +9335,9 @@ class TaskStore {
|
|
|
9084
9335
|
if (current.data && previousWorkspaceBytes) {
|
|
9085
9336
|
const restored = this.replaceSnapshot(this.workspacePath, current.data, this.snapshotBytes(this.workspacePath));
|
|
9086
9337
|
if (!restored.ok)
|
|
9087
|
-
return
|
|
9338
|
+
return failure2("external_outcome_unknown", "task creation failed and workspace restoration is uncertain", { operation: "create", outcome: "unknown" });
|
|
9088
9339
|
}
|
|
9089
|
-
return
|
|
9340
|
+
return failure2("external_outcome_unknown", "workspace created but task write is uncertain", { operation: "create", outcome: "unknown" });
|
|
9090
9341
|
}
|
|
9091
9342
|
return success(task.revision, workspace.revision, task);
|
|
9092
9343
|
});
|
|
@@ -9104,29 +9355,29 @@ class TaskStore {
|
|
|
9104
9355
|
return success(source.data.revision, current.data.revision, source.data);
|
|
9105
9356
|
if (source.code !== "not_found")
|
|
9106
9357
|
return source;
|
|
9107
|
-
return
|
|
9358
|
+
return failure2("not_found", "source task is not present in this shared workspace");
|
|
9108
9359
|
}
|
|
9109
9360
|
const tasks = this.listTasks();
|
|
9110
9361
|
if (!tasks.ok)
|
|
9111
9362
|
return tasks;
|
|
9112
9363
|
const prior = tasks.data.filter((task) => task.origin?.workspaceId === origin.workspaceId && task.origin?.taskId === origin.taskId);
|
|
9113
9364
|
if (prior.length > 1)
|
|
9114
|
-
return
|
|
9365
|
+
return failure2("recovery_required", `source task has multiple imported mappings: ${prior.map((task) => task.id).join(", ")}`);
|
|
9115
9366
|
if (prior.length === 1) {
|
|
9116
9367
|
const existing = prior[0];
|
|
9117
9368
|
if (existing.origin.exportDigest !== origin.exportDigest)
|
|
9118
|
-
return
|
|
9369
|
+
return failure2("revision_conflict", "source task export changed; reconcile the mapped destination task before importing", { taskId: existing.id });
|
|
9119
9370
|
return success(existing.revision, current.data.revision, existing);
|
|
9120
9371
|
}
|
|
9121
9372
|
}
|
|
9122
9373
|
if (current.data ? input.expectedWorkspaceRevision !== current.data.revision : input.expectedWorkspaceRevision !== null)
|
|
9123
|
-
return
|
|
9374
|
+
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", {
|
|
9124
9375
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
9125
9376
|
actualWorkspaceRevision: current.data?.revision ?? null
|
|
9126
9377
|
});
|
|
9127
9378
|
const previousWorkspaceBytes = current.data ? this.snapshotBytes(this.workspacePath) : null;
|
|
9128
9379
|
if (current.data && !previousWorkspaceBytes)
|
|
9129
|
-
return
|
|
9380
|
+
return failure2("storage_error", "workspace snapshot disappeared during import");
|
|
9130
9381
|
const timestamp = input.now ?? now();
|
|
9131
9382
|
const workspace = current.data ? {
|
|
9132
9383
|
...current.data,
|
|
@@ -9154,7 +9405,7 @@ class TaskStore {
|
|
|
9154
9405
|
};
|
|
9155
9406
|
const validTask = taskRecordSchema.safeParse(task);
|
|
9156
9407
|
if (!validTask.success)
|
|
9157
|
-
return
|
|
9408
|
+
return failure2("invalid_input", "imported task does not satisfy its schema");
|
|
9158
9409
|
const writtenWorkspace = this.replaceSnapshot(this.workspacePath, workspace, previousWorkspaceBytes);
|
|
9159
9410
|
if (!writtenWorkspace.ok)
|
|
9160
9411
|
return writtenWorkspace;
|
|
@@ -9163,9 +9414,9 @@ class TaskStore {
|
|
|
9163
9414
|
if (current.data && previousWorkspaceBytes) {
|
|
9164
9415
|
const restored = this.replaceSnapshot(this.workspacePath, current.data, this.snapshotBytes(this.workspacePath));
|
|
9165
9416
|
if (!restored.ok)
|
|
9166
|
-
return
|
|
9417
|
+
return failure2("external_outcome_unknown", "import failed and workspace restoration is uncertain", { operation: "import", outcome: "unknown" });
|
|
9167
9418
|
}
|
|
9168
|
-
return
|
|
9419
|
+
return failure2("external_outcome_unknown", `workspace created but task import is uncertain: ${writtenTask.error}`, {
|
|
9169
9420
|
operation: "import",
|
|
9170
9421
|
outcome: "unknown",
|
|
9171
9422
|
path: writtenTask.details.path
|
|
@@ -9183,13 +9434,13 @@ class TaskStore {
|
|
|
9183
9434
|
return this.conflict(expected, current.data.revision);
|
|
9184
9435
|
const previousBytes = this.snapshotBytes(this.taskPath(taskId));
|
|
9185
9436
|
if (!previousBytes)
|
|
9186
|
-
return
|
|
9437
|
+
return failure2("storage_error", "task snapshot disappeared during mutation");
|
|
9187
9438
|
const context = { now: timestamp ?? now(), revision: newRevision() };
|
|
9188
9439
|
let changed;
|
|
9189
9440
|
try {
|
|
9190
9441
|
changed = update(current.data, Object.freeze({ ...context }));
|
|
9191
9442
|
} catch (error) {
|
|
9192
|
-
return
|
|
9443
|
+
return failure2("storage_error", `task mutation failed: ${String(error)}`);
|
|
9193
9444
|
}
|
|
9194
9445
|
if (!changed.ok)
|
|
9195
9446
|
return changed;
|
|
@@ -9204,7 +9455,7 @@ class TaskStore {
|
|
|
9204
9455
|
};
|
|
9205
9456
|
const valid = taskRecordSchema.safeParse(record);
|
|
9206
9457
|
if (!valid.success)
|
|
9207
|
-
return
|
|
9458
|
+
return failure2("invalid_input", "task mutation produced an invalid record");
|
|
9208
9459
|
const written = this.replaceSnapshot(this.taskPath(taskId), valid.data, previousBytes);
|
|
9209
9460
|
return written.ok ? success(valid.data.revision, null, valid.data) : written;
|
|
9210
9461
|
});
|
|
@@ -9215,18 +9466,18 @@ class TaskStore {
|
|
|
9215
9466
|
if (!current.ok)
|
|
9216
9467
|
return current;
|
|
9217
9468
|
if (!current.data)
|
|
9218
|
-
return
|
|
9469
|
+
return failure2("not_found", "workspace not found");
|
|
9219
9470
|
if (current.data.revision !== expected)
|
|
9220
9471
|
return this.conflict(expected, current.data.revision);
|
|
9221
9472
|
const previousBytes = this.snapshotBytes(this.workspacePath);
|
|
9222
9473
|
if (!previousBytes)
|
|
9223
|
-
return
|
|
9474
|
+
return failure2("storage_error", "workspace snapshot disappeared during mutation");
|
|
9224
9475
|
const context = { now: now(), revision: newRevision() };
|
|
9225
9476
|
let changed;
|
|
9226
9477
|
try {
|
|
9227
9478
|
changed = update(current.data, Object.freeze({ ...context }));
|
|
9228
9479
|
} catch (error) {
|
|
9229
|
-
return
|
|
9480
|
+
return failure2("storage_error", `workspace mutation failed: ${String(error)}`);
|
|
9230
9481
|
}
|
|
9231
9482
|
if (!changed.ok)
|
|
9232
9483
|
return changed;
|
|
@@ -9239,7 +9490,7 @@ class TaskStore {
|
|
|
9239
9490
|
};
|
|
9240
9491
|
const valid = workspaceRecordSchema.safeParse(record);
|
|
9241
9492
|
if (!valid.success)
|
|
9242
|
-
return
|
|
9493
|
+
return failure2("invalid_input", "workspace mutation produced an invalid record");
|
|
9243
9494
|
const written = this.replaceSnapshot(this.workspacePath, valid.data, previousBytes);
|
|
9244
9495
|
return written.ok ? success(valid.data.revision, valid.data.revision, valid.data) : written;
|
|
9245
9496
|
});
|
|
@@ -9253,10 +9504,10 @@ class TaskStore {
|
|
|
9253
9504
|
if (!workspace.ok)
|
|
9254
9505
|
return workspace;
|
|
9255
9506
|
if (!workspace.data)
|
|
9256
|
-
return
|
|
9507
|
+
return failure2("not_found", "workspace not found");
|
|
9257
9508
|
const expected = input.expectedRevision;
|
|
9258
9509
|
if (!expected)
|
|
9259
|
-
return
|
|
9510
|
+
return failure2("invalid_input", "task revision is required");
|
|
9260
9511
|
if (task.data.revision !== expected)
|
|
9261
9512
|
return this.conflict(expected, task.data.revision);
|
|
9262
9513
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
@@ -9264,13 +9515,13 @@ class TaskStore {
|
|
|
9264
9515
|
const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
|
|
9265
9516
|
const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
|
|
9266
9517
|
if (!previousWorkspaceBytes || !previousTaskBytes)
|
|
9267
|
-
return
|
|
9518
|
+
return failure2("storage_error", "snapshot disappeared during coupled mutation");
|
|
9268
9519
|
const workspaceContext = { now: input.now ?? now(), revision: newRevision() };
|
|
9269
9520
|
let changedWorkspace;
|
|
9270
9521
|
try {
|
|
9271
9522
|
changedWorkspace = input.workspace(workspace.data, Object.freeze({ ...workspaceContext }));
|
|
9272
9523
|
} catch (error) {
|
|
9273
|
-
return
|
|
9524
|
+
return failure2("storage_error", `workspace mutation failed: ${String(error)}`);
|
|
9274
9525
|
}
|
|
9275
9526
|
if (!changedWorkspace.ok)
|
|
9276
9527
|
return changedWorkspace;
|
|
@@ -9282,7 +9533,7 @@ class TaskStore {
|
|
|
9282
9533
|
runtime: stampNew(workspace.data)
|
|
9283
9534
|
});
|
|
9284
9535
|
if (!nextWorkspace.success)
|
|
9285
|
-
return
|
|
9536
|
+
return failure2("invalid_input", "workspace mutation produced an invalid record");
|
|
9286
9537
|
const reserved = this.replaceSnapshot(this.workspacePath, nextWorkspace.data, previousWorkspaceBytes);
|
|
9287
9538
|
if (!reserved.ok)
|
|
9288
9539
|
return reserved;
|
|
@@ -9292,11 +9543,11 @@ class TaskStore {
|
|
|
9292
9543
|
changedTask = input.task(task.data, Object.freeze({ ...taskContext }));
|
|
9293
9544
|
} catch (error) {
|
|
9294
9545
|
this.markUncertain(nextWorkspace.data);
|
|
9295
|
-
return
|
|
9546
|
+
return failure2("external_outcome_unknown", `workspace reserved but task mutation threw: ${String(error)}`, { operation: "coupled_mutation", outcome: "unknown" });
|
|
9296
9547
|
}
|
|
9297
9548
|
if (!changedTask.ok) {
|
|
9298
9549
|
this.markUncertain(nextWorkspace.data);
|
|
9299
|
-
return
|
|
9550
|
+
return failure2("external_outcome_unknown", "workspace reserved but task update is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9300
9551
|
}
|
|
9301
9552
|
const nextTask = taskRecordSchema.safeParse({
|
|
9302
9553
|
...changedTask.data,
|
|
@@ -9309,12 +9560,12 @@ class TaskStore {
|
|
|
9309
9560
|
});
|
|
9310
9561
|
if (!nextTask.success) {
|
|
9311
9562
|
this.markUncertain(nextWorkspace.data);
|
|
9312
|
-
return
|
|
9563
|
+
return failure2("external_outcome_unknown", "workspace reserved but task update is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9313
9564
|
}
|
|
9314
9565
|
const written = this.replaceSnapshot(this.taskPath(input.taskId), nextTask.data, previousTaskBytes);
|
|
9315
9566
|
if (!written.ok) {
|
|
9316
9567
|
this.markUncertain(nextWorkspace.data);
|
|
9317
|
-
return
|
|
9568
|
+
return failure2("external_outcome_unknown", "workspace reserved but task replacement is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9318
9569
|
}
|
|
9319
9570
|
return success(nextTask.data.revision, nextWorkspace.data.revision, {
|
|
9320
9571
|
task: nextTask.data,
|
|
@@ -9338,7 +9589,7 @@ class TaskStore {
|
|
|
9338
9589
|
}
|
|
9339
9590
|
return success(null, null, candidates);
|
|
9340
9591
|
} catch (error) {
|
|
9341
|
-
return
|
|
9592
|
+
return failure2("storage_error", `unable to list recovery: ${String(error)}`, {
|
|
9342
9593
|
path: this.recoveryDir
|
|
9343
9594
|
});
|
|
9344
9595
|
}
|
|
@@ -9351,11 +9602,11 @@ class TaskStore {
|
|
|
9351
9602
|
}
|
|
9352
9603
|
recover(target, taskId, input) {
|
|
9353
9604
|
if (taskId !== null && !validId(taskId))
|
|
9354
|
-
return
|
|
9605
|
+
return failure2("invalid_input", "task ID is invalid", { taskId });
|
|
9355
9606
|
if (!input.reason || !Array.isArray(input.authorityRefs) || typeof input.processEvidence !== "function" || !validDigest(input.expectedBytes) || !validDigest(input.snapshotDigest))
|
|
9356
|
-
return
|
|
9607
|
+
return failure2("invalid_input", "recovery authority is invalid");
|
|
9357
9608
|
if (input.authorityRefs.some((ref) => !refSchema.safeParse(ref).success))
|
|
9358
|
-
return
|
|
9609
|
+
return failure2("invalid_input", "recovery references are invalid");
|
|
9359
9610
|
try {
|
|
9360
9611
|
const workspace = this.readWorkspace();
|
|
9361
9612
|
if (!workspace.ok && target === "task")
|
|
@@ -9366,14 +9617,14 @@ class TaskStore {
|
|
|
9366
9617
|
const file = target === "workspace" ? this.workspacePath : this.taskPath(taskId);
|
|
9367
9618
|
const currentBytes = this.snapshotBytes(file);
|
|
9368
9619
|
if (!currentBytes)
|
|
9369
|
-
return
|
|
9620
|
+
return failure2("not_found", "snapshot not found");
|
|
9370
9621
|
if (digestBytes(currentBytes) !== input.expectedBytes)
|
|
9371
|
-
return
|
|
9622
|
+
return failure2("revision_conflict", "snapshot bytes do not match expected bytes");
|
|
9372
9623
|
let selectedBytes = currentBytes;
|
|
9373
9624
|
if (digestBytes(currentBytes) !== input.snapshotDigest) {
|
|
9374
9625
|
const candidate = this.findRecovery(target, taskId, input.snapshotDigest, workspaceValue);
|
|
9375
9626
|
if (!candidate)
|
|
9376
|
-
return
|
|
9627
|
+
return failure2("recovery_required", "validated recovery snapshot not found");
|
|
9377
9628
|
selectedBytes = candidate;
|
|
9378
9629
|
}
|
|
9379
9630
|
const selectedRecord = target === "workspace" ? this.parseBytes(selectedBytes, workspaceRecordSchema) : this.parseBytes(selectedBytes, taskRecordSchema);
|
|
@@ -9382,11 +9633,11 @@ class TaskStore {
|
|
|
9382
9633
|
if (target === "workspace") {
|
|
9383
9634
|
const parsed = selectedRecord;
|
|
9384
9635
|
if (!parsed.ok || parsed.data.root !== this.root)
|
|
9385
|
-
return
|
|
9636
|
+
return failure2("recovery_required", "workspace recovery binding is invalid");
|
|
9386
9637
|
} else {
|
|
9387
9638
|
const parsed = selectedRecord;
|
|
9388
9639
|
if (!parsed.ok || parsed.data.id !== taskId || !workspaceValue || parsed.data.workspaceId !== workspaceValue.id)
|
|
9389
|
-
return
|
|
9640
|
+
return failure2("recovery_required", "task recovery binding is invalid");
|
|
9390
9641
|
}
|
|
9391
9642
|
const lock = this.readLockSnapshot();
|
|
9392
9643
|
if (!lock.ok)
|
|
@@ -9396,28 +9647,28 @@ class TaskStore {
|
|
|
9396
9647
|
if (!evidence.ok)
|
|
9397
9648
|
return evidence;
|
|
9398
9649
|
if (lock.data && (evidence.data.pid !== lock.data.data.pid || evidence.data.processStart !== lock.data.data.processStart))
|
|
9399
|
-
return
|
|
9650
|
+
return failure2("recovery_required", "process evidence does not match metadata lock");
|
|
9400
9651
|
if (writer && (evidence.data.state !== "accounted_for" || evidence.data.ownerDigest !== sha256(canonicalJson(writer))))
|
|
9401
|
-
return
|
|
9652
|
+
return failure2("recovery_required", "workspace writer is not accounted for");
|
|
9402
9653
|
const recoveryGate = { reclaimed: false };
|
|
9403
9654
|
const result = this.withLock((handle) => {
|
|
9404
9655
|
if (lock.data && !recoveryGate.reclaimed)
|
|
9405
|
-
return
|
|
9656
|
+
return failure2("recovery_required", "metadata lock changed during recovery", {
|
|
9406
9657
|
path: this.lockPath
|
|
9407
9658
|
});
|
|
9408
9659
|
if (!handle.verifyStillHeld())
|
|
9409
|
-
return
|
|
9660
|
+
return failure2("recovery_required", "metadata lock was compromised", {
|
|
9410
9661
|
path: this.lockPath
|
|
9411
9662
|
});
|
|
9412
9663
|
const reacquiredBytes = this.snapshotBytes(file);
|
|
9413
9664
|
if (!reacquiredBytes)
|
|
9414
|
-
return
|
|
9665
|
+
return failure2("recovery_required", "snapshot disappeared during recovery");
|
|
9415
9666
|
if (digestBytes(reacquiredBytes) !== input.expectedBytes)
|
|
9416
|
-
return
|
|
9667
|
+
return failure2("revision_conflict", "snapshot changed during recovery");
|
|
9417
9668
|
if (target === "task") {
|
|
9418
9669
|
const currentWorkspace = this.readWorkspace();
|
|
9419
9670
|
if (!currentWorkspace.ok || !currentWorkspace.data)
|
|
9420
|
-
return
|
|
9671
|
+
return failure2("recovery_required", "workspace changed during recovery");
|
|
9421
9672
|
if (currentWorkspace.data.revision !== input.expectedWorkspaceRevision)
|
|
9422
9673
|
return this.conflict(input.expectedWorkspaceRevision, currentWorkspace.data.revision);
|
|
9423
9674
|
}
|
|
@@ -9443,7 +9694,7 @@ class TaskStore {
|
|
|
9443
9694
|
}, this.recoveryLockOptions(lock.data, evidence.data, recoveryGate));
|
|
9444
9695
|
return result;
|
|
9445
9696
|
} catch (error) {
|
|
9446
|
-
return
|
|
9697
|
+
return failure2("recovery_required", `recovery protocol failed: ${String(error)}`);
|
|
9447
9698
|
}
|
|
9448
9699
|
}
|
|
9449
9700
|
processEvidence(input, lock, writer) {
|
|
@@ -9454,15 +9705,15 @@ class TaskStore {
|
|
|
9454
9705
|
try {
|
|
9455
9706
|
const result = input.processEvidence(lockCopy, writerCopy);
|
|
9456
9707
|
if (lockCopy && sha256(canonicalJson(lockCopy)) !== lockDigest)
|
|
9457
|
-
return
|
|
9708
|
+
return failure2("recovery_required", "process evidence mutated lock identity");
|
|
9458
9709
|
if (writerCopy && sha256(canonicalJson(writerCopy)) !== writerDigest)
|
|
9459
|
-
return
|
|
9710
|
+
return failure2("recovery_required", "process evidence mutated writer identity");
|
|
9460
9711
|
if (!result.ok)
|
|
9461
9712
|
return result;
|
|
9462
9713
|
const parsed = processEvidenceSchema.safeParse(result.data);
|
|
9463
|
-
return parsed.success ? success(null, null, parsed.data) :
|
|
9714
|
+
return parsed.success ? success(null, null, parsed.data) : failure2("recovery_required", "process evidence is invalid");
|
|
9464
9715
|
} catch (error) {
|
|
9465
|
-
return
|
|
9716
|
+
return failure2("recovery_required", `process evidence failed: ${String(error)}`);
|
|
9466
9717
|
}
|
|
9467
9718
|
}
|
|
9468
9719
|
deepFreeze(value) {
|
|
@@ -9477,7 +9728,7 @@ class TaskStore {
|
|
|
9477
9728
|
try {
|
|
9478
9729
|
const stat = fs4.lstatSync(this.lockPath);
|
|
9479
9730
|
if (!stat.isFile() || stat.isSymbolicLink())
|
|
9480
|
-
return
|
|
9731
|
+
return failure2("recovery_required", "metadata lock is not a regular file", {
|
|
9481
9732
|
path: this.lockPath
|
|
9482
9733
|
});
|
|
9483
9734
|
const raw = fs4.readFileSync(this.lockPath, "utf8");
|
|
@@ -9485,7 +9736,7 @@ class TaskStore {
|
|
|
9485
9736
|
} catch (error) {
|
|
9486
9737
|
if (error?.code === "ENOENT")
|
|
9487
9738
|
return success(null, null, null);
|
|
9488
|
-
return
|
|
9739
|
+
return failure2("recovery_required", `metadata lock is invalid: ${String(error)}`, {
|
|
9489
9740
|
path: this.lockPath
|
|
9490
9741
|
});
|
|
9491
9742
|
}
|
|
@@ -9518,7 +9769,7 @@ class TaskStore {
|
|
|
9518
9769
|
try {
|
|
9519
9770
|
this.initializeMutationStorage();
|
|
9520
9771
|
} catch (error) {
|
|
9521
|
-
return
|
|
9772
|
+
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
9522
9773
|
path: this.workitDir
|
|
9523
9774
|
});
|
|
9524
9775
|
}
|
|
@@ -9531,7 +9782,7 @@ class TaskStore {
|
|
|
9531
9782
|
let result;
|
|
9532
9783
|
try {
|
|
9533
9784
|
if (!handle.verifyStillHeld())
|
|
9534
|
-
result =
|
|
9785
|
+
result = failure2("recovery_required", "metadata lock was compromised", {
|
|
9535
9786
|
path: this.lockPath
|
|
9536
9787
|
});
|
|
9537
9788
|
else {
|
|
@@ -9539,25 +9790,25 @@ class TaskStore {
|
|
|
9539
9790
|
const run = () => operation();
|
|
9540
9791
|
result = await (reentrant ? externalActionLockRoots.run(new Set([...activeRoots ?? [], this.root]), run) : run());
|
|
9541
9792
|
} catch {
|
|
9542
|
-
result =
|
|
9793
|
+
result = failure2("external_outcome_unknown", "external action outcome is unknown", {
|
|
9543
9794
|
outcome: "unknown"
|
|
9544
9795
|
});
|
|
9545
9796
|
}
|
|
9546
9797
|
try {
|
|
9547
9798
|
if (!handle.verifyStillHeld())
|
|
9548
|
-
result =
|
|
9799
|
+
result = failure2("external_outcome_unknown", "metadata lock was compromised", {
|
|
9549
9800
|
outcome: "unknown",
|
|
9550
9801
|
path: this.lockPath
|
|
9551
9802
|
});
|
|
9552
9803
|
} catch {
|
|
9553
|
-
result =
|
|
9804
|
+
result = failure2("external_outcome_unknown", "metadata lock could not be verified", {
|
|
9554
9805
|
outcome: "unknown",
|
|
9555
9806
|
path: this.lockPath
|
|
9556
9807
|
});
|
|
9557
9808
|
}
|
|
9558
9809
|
}
|
|
9559
9810
|
} catch {
|
|
9560
|
-
result =
|
|
9811
|
+
result = failure2("external_outcome_unknown", "external action lock operation failed", {
|
|
9561
9812
|
outcome: "unknown",
|
|
9562
9813
|
path: this.lockPath
|
|
9563
9814
|
});
|
|
@@ -9567,10 +9818,10 @@ class TaskStore {
|
|
|
9567
9818
|
} catch (error) {
|
|
9568
9819
|
const released = this.lockFailure(error);
|
|
9569
9820
|
const releaseError = released.ok ? "metadata lock release failed" : released.error;
|
|
9570
|
-
return result.ok ?
|
|
9821
|
+
return result.ok ? failure2("external_outcome_unknown", "external action metadata lock release is uncertain", {
|
|
9571
9822
|
outcome: "unknown",
|
|
9572
9823
|
path: this.lockPath
|
|
9573
|
-
}) :
|
|
9824
|
+
}) : failure2("recovery_required", `${result.error}; ${releaseError}`, result.details);
|
|
9574
9825
|
}
|
|
9575
9826
|
return result;
|
|
9576
9827
|
}
|
|
@@ -9601,12 +9852,12 @@ class TaskStore {
|
|
|
9601
9852
|
try {
|
|
9602
9853
|
this.initializeMutationStorage();
|
|
9603
9854
|
} catch (error) {
|
|
9604
|
-
return
|
|
9855
|
+
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
9605
9856
|
path: this.workitDir
|
|
9606
9857
|
});
|
|
9607
9858
|
}
|
|
9608
9859
|
let handle;
|
|
9609
|
-
let result =
|
|
9860
|
+
let result = failure2("storage_error", "metadata lock operation did not produce a result");
|
|
9610
9861
|
try {
|
|
9611
9862
|
handle = acquireFileLockSync(this.workspacePath, options);
|
|
9612
9863
|
} catch (error) {
|
|
@@ -9615,14 +9866,14 @@ class TaskStore {
|
|
|
9615
9866
|
if (handle) {
|
|
9616
9867
|
try {
|
|
9617
9868
|
if (!handle.verifyStillHeld())
|
|
9618
|
-
result =
|
|
9869
|
+
result = failure2("recovery_required", "metadata lock was compromised", {
|
|
9619
9870
|
path: this.lockPath
|
|
9620
9871
|
});
|
|
9621
9872
|
else {
|
|
9622
9873
|
try {
|
|
9623
9874
|
result = operation(handle);
|
|
9624
9875
|
} catch (error) {
|
|
9625
|
-
result =
|
|
9876
|
+
result = failure2("storage_error", `mutation failed: ${String(error)}`);
|
|
9626
9877
|
}
|
|
9627
9878
|
}
|
|
9628
9879
|
} catch (error) {
|
|
@@ -9635,7 +9886,7 @@ class TaskStore {
|
|
|
9635
9886
|
} catch (error) {
|
|
9636
9887
|
const releaseFailure = this.lockFailure(error);
|
|
9637
9888
|
const releaseError = releaseFailure.ok ? "metadata lock release failed" : releaseFailure.error;
|
|
9638
|
-
result = result.ok ? releaseFailure :
|
|
9889
|
+
result = result.ok ? releaseFailure : failure2("recovery_required", `${result.error}; ${releaseError}`, result.details);
|
|
9639
9890
|
}
|
|
9640
9891
|
}
|
|
9641
9892
|
return result;
|
|
@@ -9646,13 +9897,13 @@ class TaskStore {
|
|
|
9646
9897
|
if (code === "EEXIST" || code === "file_lock_timeout") {
|
|
9647
9898
|
const lock = this.readLockSnapshot();
|
|
9648
9899
|
if (lock.ok && lock.data?.data.externalAction)
|
|
9649
|
-
return
|
|
9900
|
+
return failure2("writer_conflict", "workspace is reserved by a managed external action", {
|
|
9650
9901
|
outcome: "not_started",
|
|
9651
9902
|
path: this.lockPath
|
|
9652
9903
|
});
|
|
9653
9904
|
}
|
|
9654
9905
|
const recovery = code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || code === "metadata_lock_invalid" || code === "not-file" || /metadata lock|file lock|reclaim/i.test(String(value?.message ?? error));
|
|
9655
|
-
return
|
|
9906
|
+
return failure2(recovery ? "recovery_required" : "storage_error", `metadata lock operation failed: ${String(error)}`, { path: this.lockPath });
|
|
9656
9907
|
}
|
|
9657
9908
|
initializeMutationStorage() {
|
|
9658
9909
|
fs4.mkdirSync(this.tasksDir, { recursive: true });
|
|
@@ -9684,7 +9935,7 @@ class TaskStore {
|
|
|
9684
9935
|
this.indexTaskWrite(file, value);
|
|
9685
9936
|
return success(null, null, value);
|
|
9686
9937
|
} catch (error) {
|
|
9687
|
-
return
|
|
9938
|
+
return failure2("storage_error", `snapshot replacement failed: ${String(error)}`, {
|
|
9688
9939
|
path: file
|
|
9689
9940
|
});
|
|
9690
9941
|
} finally {
|
|
@@ -9840,7 +10091,7 @@ class TaskStore {
|
|
|
9840
10091
|
return { exists: false, result: success(null, null, null) };
|
|
9841
10092
|
return {
|
|
9842
10093
|
exists: true,
|
|
9843
|
-
result:
|
|
10094
|
+
result: failure2("recovery_required", `snapshot cannot be read: ${String(error)}`, {
|
|
9844
10095
|
path: file
|
|
9845
10096
|
})
|
|
9846
10097
|
};
|
|
@@ -9851,17 +10102,17 @@ class TaskStore {
|
|
|
9851
10102
|
try {
|
|
9852
10103
|
value = JSON.parse(typeof bytes === "string" ? bytes : bytes.toString("utf8"));
|
|
9853
10104
|
} catch {
|
|
9854
|
-
return
|
|
10105
|
+
return failure2("recovery_required", "snapshot JSON is corrupt");
|
|
9855
10106
|
}
|
|
9856
10107
|
if (isObject2(value) && "schemaVersion" in value && value.schemaVersion !== SCHEMA_VERSION)
|
|
9857
|
-
return
|
|
10108
|
+
return failure2("unsupported_version", "unsupported snapshot schema version");
|
|
9858
10109
|
const parsed = schema.safeParse(value);
|
|
9859
10110
|
if (parsed.success)
|
|
9860
10111
|
return success(null, null, parsed.data);
|
|
9861
10112
|
const writerVersion = isObject2(value) && isObject2(value.runtime) ? value.runtime.updatedWith : null;
|
|
9862
10113
|
if (typeof writerVersion === "string" && isNewerVersion(writerVersion, runtimeVersion()))
|
|
9863
|
-
return
|
|
9864
|
-
return
|
|
10114
|
+
return failure2("recovery_required", `snapshot was written by workit ${writerVersion}; upgrade Workit before mutating this checkout`);
|
|
10115
|
+
return failure2("recovery_required", "snapshot does not satisfy its schema");
|
|
9865
10116
|
}
|
|
9866
10117
|
processStart(pid) {
|
|
9867
10118
|
try {
|
|
@@ -9871,7 +10122,7 @@ class TaskStore {
|
|
|
9871
10122
|
}
|
|
9872
10123
|
}
|
|
9873
10124
|
conflict(expected, actual) {
|
|
9874
|
-
return
|
|
10125
|
+
return failure2("revision_conflict", "snapshot revision does not match; omit expectedRevision to use the current record", {
|
|
9875
10126
|
expectedRevision: expected,
|
|
9876
10127
|
actualRevision: actual
|
|
9877
10128
|
});
|
|
@@ -10437,7 +10688,7 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
10437
10688
|
} catch (error) {
|
|
10438
10689
|
if (error.code === "ENOENT")
|
|
10439
10690
|
return null;
|
|
10440
|
-
throw new Error(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}
|
|
10691
|
+
throw new Error(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
10441
10692
|
}
|
|
10442
10693
|
let parsed;
|
|
10443
10694
|
try {
|
|
@@ -10678,7 +10929,7 @@ var UNCERTAIN_WORKER_STATES = ["dispatching", "running", "cancelling", "unknown"
|
|
|
10678
10929
|
var isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state);
|
|
10679
10930
|
var workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
|
|
10680
10931
|
var callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor };
|
|
10681
|
-
var validPath = (value) => typeof value === "string" && value.length > 0 && !
|
|
10932
|
+
var validPath = (value) => typeof value === "string" && value.length > 0 && !Array.from(value).some((char) => {
|
|
10682
10933
|
const code = char.charCodeAt(0);
|
|
10683
10934
|
return code < 32 || code === 127;
|
|
10684
10935
|
}) && !value.split(/[\\/]/).includes("..");
|
|
@@ -10690,9 +10941,9 @@ var currentWriterOwnsTask = (task, workspace, caller) => {
|
|
|
10690
10941
|
};
|
|
10691
10942
|
function assertProductWriteAllowed(input) {
|
|
10692
10943
|
if (!Array.isArray(input.paths) || input.paths.some((path) => !validPath(path)))
|
|
10693
|
-
return
|
|
10944
|
+
return failure2("invalid_input", "invalid product write path");
|
|
10694
10945
|
if (!input.store)
|
|
10695
|
-
return
|
|
10946
|
+
return failure2("permission_denied", "write authorization requires core state");
|
|
10696
10947
|
const task = input.store.readTask(input.task.id);
|
|
10697
10948
|
if (!task.ok)
|
|
10698
10949
|
return task;
|
|
@@ -10700,29 +10951,29 @@ function assertProductWriteAllowed(input) {
|
|
|
10700
10951
|
if (!workspace.ok)
|
|
10701
10952
|
return workspace;
|
|
10702
10953
|
if (!workspace.data)
|
|
10703
|
-
return
|
|
10954
|
+
return failure2("not_found", "workspace not found");
|
|
10704
10955
|
const workspaceRecord = workspace.data;
|
|
10705
10956
|
if (task.data.status !== "active")
|
|
10706
|
-
return
|
|
10957
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
10707
10958
|
if (workspaceRecord.id !== task.data.workspaceId || workspaceRecord.root.length === 0)
|
|
10708
|
-
return
|
|
10959
|
+
return failure2("recovery_required", "task and workspace bindings are invalid");
|
|
10709
10960
|
const writer = workspaceRecord.writer;
|
|
10710
10961
|
if (!writer)
|
|
10711
|
-
return
|
|
10962
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
10712
10963
|
if (writer.state === "uncertain")
|
|
10713
|
-
return
|
|
10964
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
10714
10965
|
owner: writer.owner
|
|
10715
10966
|
});
|
|
10716
10967
|
const caller = callerValue(input.caller);
|
|
10717
10968
|
const workerId = workerIdOf(input.caller);
|
|
10718
10969
|
const owner = writer.owner;
|
|
10719
10970
|
if (owner.taskId !== task.data.id || owner.workerId !== workerId || owner.session.host !== caller.host || owner.session.handle !== caller.actor)
|
|
10720
|
-
return
|
|
10971
|
+
return failure2("writer_conflict", "checkout is owned by another validated actor", { owner });
|
|
10721
10972
|
const worker = workerId === null ? null : task.data.workers.find((entry) => entry.id === workerId);
|
|
10722
10973
|
if (workerId !== null && (!worker || worker.data.assignment.role !== "implementer"))
|
|
10723
|
-
return
|
|
10974
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
10724
10975
|
if (workerId !== null && (!worker?.data.session || worker.data.state === "cancelling" || worker.data.state === "unknown" || worker.data.state === "stopped" || !same(worker.data.session, callerSession(input.caller))))
|
|
10725
|
-
return
|
|
10976
|
+
return failure2("recovery_required", "worker session is not an active writer");
|
|
10726
10977
|
return success(null, workspaceRecord.revision, owner);
|
|
10727
10978
|
}
|
|
10728
10979
|
|
|
@@ -10818,15 +11069,15 @@ var standingReceiptFor = (root, workspace, cls, dir) => {
|
|
|
10818
11069
|
};
|
|
10819
11070
|
var verifyStandingApproval = (root, task, caller, binding) => {
|
|
10820
11071
|
if (task.status !== "active")
|
|
10821
|
-
return
|
|
11072
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
10822
11073
|
const workspace = new TaskStore(root).readWorkspace();
|
|
10823
11074
|
if (!workspace.ok)
|
|
10824
11075
|
return workspace;
|
|
10825
11076
|
if (!workspace.data || !currentWriterOwnsTask(task, workspace.data, caller))
|
|
10826
|
-
return
|
|
11077
|
+
return failure2("permission_denied", "standing approval requires the current writer session");
|
|
10827
11078
|
const standing = binding.standing;
|
|
10828
11079
|
if (!standing || typeof standing.workspace !== "string" || typeof standing.class !== "string")
|
|
10829
|
-
return
|
|
11080
|
+
return failure2("invalid_input", "standing approval needs a workspace and class");
|
|
10830
11081
|
let operation;
|
|
10831
11082
|
try {
|
|
10832
11083
|
operation = typeof binding.approvedContent === "string" ? JSON.parse(binding.approvedContent).operation : null;
|
|
@@ -10835,22 +11086,22 @@ var verifyStandingApproval = (root, task, caller, binding) => {
|
|
|
10835
11086
|
}
|
|
10836
11087
|
const cls = operationAutoClass(operation);
|
|
10837
11088
|
if (!cls || cls !== standing.class)
|
|
10838
|
-
return
|
|
11089
|
+
return failure2("permission_denied", "standing approval does not cover this operation");
|
|
10839
11090
|
const target = targetOf(root, binding.approvedContent);
|
|
10840
11091
|
if (!target)
|
|
10841
|
-
return
|
|
11092
|
+
return failure2("permission_denied", "standing action target is invalid");
|
|
10842
11093
|
const resolved = resolveAutoApproval(target);
|
|
10843
11094
|
if (resolved.status !== "on" || resolved.workspace !== standing.workspace || !resolved.classes.includes(cls))
|
|
10844
|
-
return
|
|
11095
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
10845
11096
|
if (cls === "push") {
|
|
10846
|
-
const
|
|
10847
|
-
const provider =
|
|
11097
|
+
const targetWorkspace = resolveWorkspaceFrom(target, configDir());
|
|
11098
|
+
const provider = targetWorkspace?.vcs?.provider;
|
|
10848
11099
|
const account = resolved.account;
|
|
10849
11100
|
if (!provider || !account)
|
|
10850
|
-
return
|
|
11101
|
+
return failure2("permission_denied", "auto-push requires a workspace provider and area account");
|
|
10851
11102
|
const identity = verifyPushIdentity(target, provider, account);
|
|
10852
11103
|
if (!identity.ok)
|
|
10853
|
-
return
|
|
11104
|
+
return failure2("permission_denied", identity.error);
|
|
10854
11105
|
}
|
|
10855
11106
|
return success(null, null, {
|
|
10856
11107
|
kind: "host_observed",
|
|
@@ -10927,10 +11178,10 @@ var validProvenance = (value, caller) => {
|
|
|
10927
11178
|
};
|
|
10928
11179
|
var verifyNativeDecision = (verifier, input, binding) => {
|
|
10929
11180
|
if (!verifier)
|
|
10930
|
-
return
|
|
11181
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
10931
11182
|
const result = verifier.verifyDecision(input);
|
|
10932
11183
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
10933
|
-
return
|
|
11184
|
+
return failure2("permission_denied", "native decision observation was not attested");
|
|
10934
11185
|
return success(null, null, trustedAuthority("decision", result.data, {
|
|
10935
11186
|
taskId: input.expected.taskId,
|
|
10936
11187
|
workspaceId: input.expected.workspaceId,
|
|
@@ -10944,10 +11195,10 @@ var verifyNativeDecision = (verifier, input, binding) => {
|
|
|
10944
11195
|
};
|
|
10945
11196
|
var verifyNativeAction = (verifier, input, binding) => {
|
|
10946
11197
|
if (!verifier)
|
|
10947
|
-
return
|
|
11198
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
10948
11199
|
const result = verifier.verifyAction(input);
|
|
10949
11200
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
10950
|
-
return
|
|
11201
|
+
return failure2("permission_denied", "native action observation was not attested");
|
|
10951
11202
|
return success(null, null, trustedAuthority("action", result.data, {
|
|
10952
11203
|
taskId: input.expected.taskId,
|
|
10953
11204
|
workspaceId: input.expected.workspaceId,
|
|
@@ -10965,10 +11216,10 @@ var verifyNativeAction = (verifier, input, binding) => {
|
|
|
10965
11216
|
};
|
|
10966
11217
|
var verifyNativeReconciliation = (verifier, input, binding) => {
|
|
10967
11218
|
if (!verifier?.verifyReconciliation)
|
|
10968
|
-
return
|
|
11219
|
+
return failure2("permission_denied", "native reconciliation authority is unavailable");
|
|
10969
11220
|
const result = verifier.verifyReconciliation(input);
|
|
10970
11221
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
10971
|
-
return
|
|
11222
|
+
return failure2("permission_denied", "native reconciliation observation was not attested");
|
|
10972
11223
|
return success(null, null, trustedAuthority("reconciliation", result.data, {
|
|
10973
11224
|
taskId: input.expected.taskId,
|
|
10974
11225
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11014,16 +11265,16 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11014
11265
|
try {
|
|
11015
11266
|
root = fs6.realpathSync(checkoutRoot);
|
|
11016
11267
|
} catch {
|
|
11017
|
-
return
|
|
11268
|
+
return failure2("permission_denied", "checkout root is unavailable");
|
|
11018
11269
|
}
|
|
11019
11270
|
for (const reference of binding.contentRefs) {
|
|
11020
11271
|
if (reference.kind !== "file")
|
|
11021
11272
|
continue;
|
|
11022
11273
|
if (!reference.digest)
|
|
11023
|
-
return
|
|
11274
|
+
return failure2("invalid_input", "document references require a byte digest");
|
|
11024
11275
|
const target = path9.resolve(root, reference.path);
|
|
11025
11276
|
if (target !== root && !target.startsWith(`${root}${path9.sep}`))
|
|
11026
|
-
return
|
|
11277
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11027
11278
|
fields: [
|
|
11028
11279
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
11029
11280
|
]
|
|
@@ -11038,7 +11289,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11038
11289
|
const stat = fs6.lstatSync(current);
|
|
11039
11290
|
const real = fs6.realpathSync(current);
|
|
11040
11291
|
if (real !== root && !real.startsWith(`${root}${path9.sep}`))
|
|
11041
|
-
return
|
|
11292
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11042
11293
|
fields: [
|
|
11043
11294
|
{
|
|
11044
11295
|
path: "contentRefs.path",
|
|
@@ -11047,16 +11298,16 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11047
11298
|
]
|
|
11048
11299
|
});
|
|
11049
11300
|
if (stat.isSymbolicLink())
|
|
11050
|
-
return
|
|
11301
|
+
return failure2("invalid_input", "document reference uses a symlink");
|
|
11051
11302
|
if (current === target && !stat.isFile())
|
|
11052
|
-
return
|
|
11303
|
+
return failure2("invalid_input", "document reference is not a regular file");
|
|
11053
11304
|
if (current !== target && !stat.isDirectory())
|
|
11054
|
-
return
|
|
11305
|
+
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
11055
11306
|
}
|
|
11056
11307
|
if (digestBytes2(fs6.readFileSync(target)) !== reference.digest)
|
|
11057
|
-
return
|
|
11308
|
+
return failure2("permission_denied", "approved document bytes have changed");
|
|
11058
11309
|
} catch {
|
|
11059
|
-
return
|
|
11310
|
+
return failure2("invalid_input", "approved document is unavailable");
|
|
11060
11311
|
}
|
|
11061
11312
|
}
|
|
11062
11313
|
return success(null, null, null);
|
|
@@ -11079,15 +11330,15 @@ var approvalAuthorityMatches = (store, task, approval, current) => {
|
|
|
11079
11330
|
};
|
|
11080
11331
|
var validateAction = (store, task, workspaceId, input, authority) => {
|
|
11081
11332
|
if (task.status !== "active")
|
|
11082
|
-
return
|
|
11333
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
11083
11334
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11084
|
-
return
|
|
11335
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11085
11336
|
const entry = task.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11086
11337
|
if (!entry)
|
|
11087
|
-
return
|
|
11338
|
+
return failure2("not_found", "decision not found");
|
|
11088
11339
|
const decision = entry.data;
|
|
11089
11340
|
if (decision.purpose !== "action")
|
|
11090
|
-
return
|
|
11341
|
+
return failure2("permission_denied", "decision is not an action approval");
|
|
11091
11342
|
if (!authorityMatches(authority, {
|
|
11092
11343
|
taskId: task.id,
|
|
11093
11344
|
workspaceId,
|
|
@@ -11097,13 +11348,13 @@ var validateAction = (store, task, workspaceId, input, authority) => {
|
|
|
11097
11348
|
workspaceRevision: input.expectedWorkspaceRevision,
|
|
11098
11349
|
outcome: "reserve"
|
|
11099
11350
|
}))
|
|
11100
|
-
return
|
|
11351
|
+
return failure2("permission_denied", "native reservation authority is not bound");
|
|
11101
11352
|
if (!authorityDecisionMatches(authority, decision))
|
|
11102
|
-
return
|
|
11353
|
+
return failure2("permission_denied", "native reservation authority does not match decision");
|
|
11103
11354
|
if (decision.response !== "approved")
|
|
11104
|
-
return
|
|
11355
|
+
return failure2("permission_denied", "decision was rejected");
|
|
11105
11356
|
if (!approvalAuthorityMatches(store, task, entry.provenance, authority.provenance))
|
|
11106
|
-
return
|
|
11357
|
+
return failure2("permission_denied", "action approval lacks native receipt assurance");
|
|
11107
11358
|
const receipts = entry.provenance.receipts;
|
|
11108
11359
|
const standing = receipts.filter((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "standing");
|
|
11109
11360
|
const questionBacked = receipts.some((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "host");
|
|
@@ -11116,48 +11367,48 @@ var validateAction = (store, task, workspaceId, input, authority) => {
|
|
|
11116
11367
|
}
|
|
11117
11368
|
const cls = operationAutoClass(operation);
|
|
11118
11369
|
if (!cls || !standing.some((receipt) => standingApprovalLive(store.root, receipt, cls, undefined, decision.binding.approvedContent)))
|
|
11119
|
-
return
|
|
11370
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
11120
11371
|
}
|
|
11121
11372
|
if (decision.revoked)
|
|
11122
|
-
return
|
|
11373
|
+
return failure2("permission_denied", "decision is revoked");
|
|
11123
11374
|
if (decision.digest !== decisionDigest(decision))
|
|
11124
|
-
return
|
|
11375
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11125
11376
|
if (decision.binding.taskId !== task.id || decision.binding.workspaceId !== workspaceId)
|
|
11126
|
-
return
|
|
11377
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
11127
11378
|
if (input.binding && canonicalJson(input.binding) !== canonicalJson(decision.binding))
|
|
11128
|
-
return
|
|
11379
|
+
return failure2("permission_denied", "action binding does not match the approved decision");
|
|
11129
11380
|
const content = verifyContentRefs(store, decision.binding);
|
|
11130
11381
|
if (!content.ok)
|
|
11131
11382
|
return content;
|
|
11132
11383
|
const requestedSteps = parseSteps(decision.binding.approvedContent);
|
|
11133
11384
|
if (requestedSteps === null)
|
|
11134
|
-
return
|
|
11385
|
+
return failure2("invalid_input", "bounded action steps must be a unique non-empty array");
|
|
11135
11386
|
if (input.steps && canonicalJson(input.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11136
|
-
return
|
|
11387
|
+
return failure2("permission_denied", "bounded action steps do not match approved content");
|
|
11137
11388
|
const stored = task.actionProgress?.find((item) => item.decisionId === input.decisionId);
|
|
11138
11389
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: requestedSteps.map(chainStepKey), completed: [] };
|
|
11139
11390
|
if (workflow.steps.length && requestedSteps.length && canonicalJson(workflow.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11140
|
-
return
|
|
11391
|
+
return failure2("permission_denied", "bounded action scope changed");
|
|
11141
11392
|
return success(null, null, { entry, workflow });
|
|
11142
11393
|
};
|
|
11143
11394
|
function reserveAction(input) {
|
|
11144
11395
|
if (!input.store || !input.expectedRevision || !input.expectedWorkspaceRevision)
|
|
11145
|
-
return
|
|
11396
|
+
return failure2("invalid_input", "action reservation preconditions are required");
|
|
11146
11397
|
const authority = takeAuthority(input.authority, {
|
|
11147
11398
|
owner: input.authorityOwner,
|
|
11148
11399
|
store: input.store,
|
|
11149
11400
|
root: input.store.root
|
|
11150
11401
|
}, input.authorityCaller);
|
|
11151
11402
|
if (!authority)
|
|
11152
|
-
return
|
|
11403
|
+
return failure2("permission_denied", "native reservation authority is not verified");
|
|
11153
11404
|
const changed = input.store.mutateTask(input.taskId, input.expectedRevision, (current, mutation) => {
|
|
11154
11405
|
const workspace = input.store.readWorkspace();
|
|
11155
11406
|
if (!workspace.ok)
|
|
11156
11407
|
return workspace;
|
|
11157
11408
|
if (!workspace.data)
|
|
11158
|
-
return
|
|
11409
|
+
return failure2("not_found", "workspace not found");
|
|
11159
11410
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
11160
|
-
return
|
|
11411
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
11161
11412
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
11162
11413
|
actualWorkspaceRevision: workspace.data.revision
|
|
11163
11414
|
});
|
|
@@ -11167,19 +11418,19 @@ function reserveAction(input) {
|
|
|
11167
11418
|
const { entry, workflow } = valid.data;
|
|
11168
11419
|
const existing = entry.data.consumption;
|
|
11169
11420
|
if (existing?.state === "uncertain")
|
|
11170
|
-
return
|
|
11421
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
11171
11422
|
operation: "reserve_action",
|
|
11172
11423
|
outcome: "unknown"
|
|
11173
11424
|
});
|
|
11174
11425
|
if (existing?.state === "consumed")
|
|
11175
|
-
return
|
|
11426
|
+
return failure2("permission_denied", "action approval is consumed");
|
|
11176
11427
|
if (existing?.state === "reserved" && workflow.completed.length === 0)
|
|
11177
|
-
return
|
|
11428
|
+
return failure2("permission_denied", "action approval is already reserved");
|
|
11178
11429
|
const requestedStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11179
11430
|
if (workflow.steps.length && (!requestedStep || requestedStep !== workflow.steps[workflow.completed.length]))
|
|
11180
|
-
return
|
|
11431
|
+
return failure2("permission_denied", "action step is outside the approved remaining workflow");
|
|
11181
11432
|
if (requestedStep && workflow.completed.includes(requestedStep))
|
|
11182
|
-
return
|
|
11433
|
+
return failure2("permission_denied", "action step was already completed");
|
|
11183
11434
|
const nextDecision = {
|
|
11184
11435
|
...entry.data,
|
|
11185
11436
|
consumption: { state: "reserved", at: mutation.now, actionRef: input.actionRef }
|
|
@@ -11202,10 +11453,10 @@ function reserveAction(input) {
|
|
|
11202
11453
|
return changed;
|
|
11203
11454
|
const workspace = input.store.readWorkspace();
|
|
11204
11455
|
if (!workspace.ok || !workspace.data)
|
|
11205
|
-
return
|
|
11456
|
+
return failure2("recovery_required", "workspace disappeared after reservation");
|
|
11206
11457
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11207
11458
|
if (!entry)
|
|
11208
|
-
return
|
|
11459
|
+
return failure2("recovery_required", "reserved decision disappeared");
|
|
11209
11460
|
const workflow = changed.data.actionProgress?.find((progress) => progress.decisionId === input.decisionId) ?? {
|
|
11210
11461
|
steps: [],
|
|
11211
11462
|
completedSteps: []
|
|
@@ -11222,16 +11473,16 @@ function reserveAction(input) {
|
|
|
11222
11473
|
}
|
|
11223
11474
|
function settleAction(input) {
|
|
11224
11475
|
if (!input.store || !input.taskRevision || !input.workspaceRevision)
|
|
11225
|
-
return
|
|
11476
|
+
return failure2("invalid_input", "action settlement preconditions are required");
|
|
11226
11477
|
const authority = takeAuthority(input.authority, {
|
|
11227
11478
|
owner: input.authorityOwner,
|
|
11228
11479
|
store: input.store,
|
|
11229
11480
|
root: input.store.root
|
|
11230
11481
|
}, input.authorityCaller);
|
|
11231
11482
|
if (!authority)
|
|
11232
|
-
return
|
|
11483
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11233
11484
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11234
|
-
return
|
|
11485
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11235
11486
|
if (!authorityMatches(authority, {
|
|
11236
11487
|
taskId: input.taskId,
|
|
11237
11488
|
workspaceId: authority.workspaceId,
|
|
@@ -11241,14 +11492,14 @@ function settleAction(input) {
|
|
|
11241
11492
|
workspaceRevision: input.workspaceRevision,
|
|
11242
11493
|
outcome: input.outcome
|
|
11243
11494
|
}))
|
|
11244
|
-
return
|
|
11495
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11245
11496
|
let outcomeResult = null;
|
|
11246
11497
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11247
11498
|
const workspace = input.store.readWorkspace();
|
|
11248
11499
|
if (!workspace.ok)
|
|
11249
11500
|
return workspace;
|
|
11250
11501
|
if (!workspace.data)
|
|
11251
|
-
return
|
|
11502
|
+
return failure2("not_found", "workspace not found");
|
|
11252
11503
|
if (!authorityMatches(authority, {
|
|
11253
11504
|
taskId: input.taskId,
|
|
11254
11505
|
workspaceId: workspace.data.id,
|
|
@@ -11258,39 +11509,39 @@ function settleAction(input) {
|
|
|
11258
11509
|
workspaceRevision: input.workspaceRevision,
|
|
11259
11510
|
outcome: input.outcome
|
|
11260
11511
|
}))
|
|
11261
|
-
return
|
|
11512
|
+
return failure2("permission_denied", "native settlement authority does not match context");
|
|
11262
11513
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11263
|
-
return
|
|
11514
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
11264
11515
|
expectedWorkspaceRevision: input.workspaceRevision,
|
|
11265
11516
|
actualWorkspaceRevision: workspace.data.revision
|
|
11266
11517
|
});
|
|
11267
11518
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11268
11519
|
if (!entry)
|
|
11269
|
-
return
|
|
11520
|
+
return failure2("not_found", "decision not found");
|
|
11270
11521
|
if (!authorityDecisionMatches(authority, entry.data))
|
|
11271
|
-
return
|
|
11522
|
+
return failure2("permission_denied", "native settlement authority does not match decision");
|
|
11272
11523
|
if (!approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11273
|
-
return
|
|
11524
|
+
return failure2("permission_denied", "native settlement caller does not match approval");
|
|
11274
11525
|
if (entry.data.purpose !== "action" || entry.data.digest !== decisionDigest(entry.data))
|
|
11275
|
-
return
|
|
11526
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11276
11527
|
if (entry.data.consumption?.state === "uncertain")
|
|
11277
|
-
return
|
|
11528
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
11278
11529
|
operation: "settle_action",
|
|
11279
11530
|
outcome: "unknown"
|
|
11280
11531
|
});
|
|
11281
11532
|
if (entry.data.consumption?.state !== "reserved")
|
|
11282
|
-
return
|
|
11533
|
+
return failure2("permission_denied", "action is not reserved");
|
|
11283
11534
|
if (canonicalJson(entry.data.consumption.actionRef) !== canonicalJson(input.actionRef))
|
|
11284
|
-
return
|
|
11535
|
+
return failure2("permission_denied", "settlement reference does not match reservation");
|
|
11285
11536
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11286
11537
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: [], completed: [] };
|
|
11287
11538
|
if (entry.data.binding.approvedContent && !stored && (parseSteps(entry.data.binding.approvedContent) ?? []).length)
|
|
11288
|
-
return
|
|
11539
|
+
return failure2("recovery_required", "bounded action progress is missing");
|
|
11289
11540
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11290
11541
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11291
|
-
return
|
|
11542
|
+
return failure2("permission_denied", "settlement step is outside the approved workflow");
|
|
11292
11543
|
if (input.outcome === "unknown") {
|
|
11293
|
-
outcomeResult =
|
|
11544
|
+
outcomeResult = failure2("external_outcome_unknown", "external action outcome is unknown", {
|
|
11294
11545
|
operation: "settle_action",
|
|
11295
11546
|
outcome: "unknown"
|
|
11296
11547
|
});
|
|
@@ -11342,45 +11593,45 @@ function settleAction(input) {
|
|
|
11342
11593
|
return changed;
|
|
11343
11594
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11344
11595
|
if (!entry)
|
|
11345
|
-
return
|
|
11596
|
+
return failure2("recovery_required", "settled decision disappeared");
|
|
11346
11597
|
if (outcomeResult)
|
|
11347
11598
|
return outcomeResult;
|
|
11348
11599
|
return success(changed.data.revision, input.workspaceRevision, entry);
|
|
11349
11600
|
}
|
|
11350
11601
|
function reconcileAction(input) {
|
|
11351
11602
|
if (!input.store || !input.taskRevision || !input.workspaceRevision || !input.evidenceDigest)
|
|
11352
|
-
return
|
|
11603
|
+
return failure2("invalid_input", "action reconciliation preconditions are required");
|
|
11353
11604
|
const authority = takeAuthority(input.authority, { owner: input.authorityOwner, store: input.store, root: input.store.root }, input.authorityCaller);
|
|
11354
11605
|
if (!authority || authority.kind !== "reconciliation")
|
|
11355
|
-
return
|
|
11606
|
+
return failure2("permission_denied", "native reconciliation authority is not verified");
|
|
11356
11607
|
if (authority.taskId !== input.taskId || authority.decisionId !== input.decisionId || !sameRef(authority.actionRef, input.actionRef) || authority.taskRevision !== input.taskRevision || authority.workspaceRevision !== input.workspaceRevision || authority.outcome !== input.outcome || authority.evidenceDigest !== input.evidenceDigest || authority.step !== input.step)
|
|
11357
|
-
return
|
|
11608
|
+
return failure2("permission_denied", "native reconciliation authority is not bound");
|
|
11358
11609
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11359
11610
|
const workspace = input.store.readWorkspace();
|
|
11360
11611
|
if (!workspace.ok)
|
|
11361
11612
|
return workspace;
|
|
11362
11613
|
if (!workspace.data)
|
|
11363
|
-
return
|
|
11614
|
+
return failure2("not_found", "workspace not found");
|
|
11364
11615
|
if (authority.workspaceId !== workspace.data.id)
|
|
11365
|
-
return
|
|
11616
|
+
return failure2("permission_denied", "native reconciliation workspace does not match");
|
|
11366
11617
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11367
|
-
return
|
|
11618
|
+
return failure2("revision_conflict", "workspace revision does not match");
|
|
11368
11619
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11369
11620
|
if (!entry || entry.data.purpose !== "action")
|
|
11370
|
-
return
|
|
11621
|
+
return failure2("not_found", "decision not found");
|
|
11371
11622
|
if (!authorityDecisionMatches(authority, entry.data) || !approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11372
|
-
return
|
|
11623
|
+
return failure2("permission_denied", "native reconciliation caller does not match approval");
|
|
11373
11624
|
if (entry.data.response !== "approved" || entry.data.revoked !== null || entry.data.digest !== decisionDigest(entry.data) || entry.data.binding.taskId !== current.id || entry.data.binding.workspaceId !== current.workspaceId || entry.data.binding.workspaceId !== workspace.data.id)
|
|
11374
|
-
return
|
|
11625
|
+
return failure2("permission_denied", "reconciliation decision binding is invalid");
|
|
11375
11626
|
if (entry.data.consumption?.state !== "uncertain")
|
|
11376
|
-
return
|
|
11627
|
+
return failure2("external_outcome_unknown", "only an uncertain action can be reconciled");
|
|
11377
11628
|
if (!sameRef(entry.data.consumption.actionRef, input.actionRef))
|
|
11378
|
-
return
|
|
11629
|
+
return failure2("permission_denied", "reconciliation reference does not match reservation");
|
|
11379
11630
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11380
11631
|
const workflow = stored ? { steps: [...stored.steps], completed: [...stored.completedSteps] } : { steps: [], completed: [] };
|
|
11381
11632
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11382
11633
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11383
|
-
return
|
|
11634
|
+
return failure2("permission_denied", "reconciliation step is outside the approved workflow");
|
|
11384
11635
|
if (input.outcome === "not_started") {
|
|
11385
11636
|
return success(mutation.revision, null, {
|
|
11386
11637
|
...current,
|
|
@@ -11411,7 +11662,7 @@ function reconcileAction(input) {
|
|
|
11411
11662
|
if (!changed.ok)
|
|
11412
11663
|
return changed;
|
|
11413
11664
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11414
|
-
return entry ? success(changed.data.revision, input.workspaceRevision, entry) :
|
|
11665
|
+
return entry ? success(changed.data.revision, input.workspaceRevision, entry) : failure2("recovery_required", "reconciled decision disappeared");
|
|
11415
11666
|
}
|
|
11416
11667
|
var bindingCovers = scopeCovers;
|
|
11417
11668
|
var verifyDecisionContent = verifyContentRefs;
|
|
@@ -11437,8 +11688,8 @@ var compareCodeUnits2 = (left, right) => {
|
|
|
11437
11688
|
}
|
|
11438
11689
|
return left.length - right.length;
|
|
11439
11690
|
};
|
|
11440
|
-
var stableUnique = (values) => [...new Set(values)].
|
|
11441
|
-
var stableList = (values) => [...values].
|
|
11691
|
+
var stableUnique = (values) => [...new Set(values)].toSorted(compareCodeUnits2);
|
|
11692
|
+
var stableList = (values) => [...values].toSorted((left, right) => compareCodeUnits2(canonicalJson(left), canonicalJson(right)));
|
|
11442
11693
|
var normalizedScope = (scope) => ({
|
|
11443
11694
|
description: scope.description,
|
|
11444
11695
|
paths: stableUnique(scope.paths),
|
|
@@ -11511,11 +11762,11 @@ var invalidFields = (error) => ({
|
|
|
11511
11762
|
function normalizeResolverInput(input) {
|
|
11512
11763
|
const parsed = resolverInputSchema.safeParse(input);
|
|
11513
11764
|
if (!parsed.success)
|
|
11514
|
-
return
|
|
11765
|
+
return failure2("invalid_input", "resolver input is invalid", invalidFields(parsed.error));
|
|
11515
11766
|
const value = parsed.data;
|
|
11516
11767
|
const signals = value.assessment.signals;
|
|
11517
11768
|
if (signals.behaviorChange.value === true && signals.mechanicalLowRisk.value === true)
|
|
11518
|
-
return
|
|
11769
|
+
return failure2("invalid_input", "behavioral change cannot be wholly mechanical", {
|
|
11519
11770
|
fields: [
|
|
11520
11771
|
{
|
|
11521
11772
|
path: "assessment.signals",
|
|
@@ -11525,11 +11776,11 @@ function normalizeResolverInput(input) {
|
|
|
11525
11776
|
});
|
|
11526
11777
|
const ids = value.constraints.map((constraint) => constraint.id);
|
|
11527
11778
|
if (new Set(ids).size !== ids.length)
|
|
11528
|
-
return
|
|
11779
|
+
return failure2("invalid_input", "constraint IDs must be unique", {
|
|
11529
11780
|
fields: [{ path: "constraints", reason: "duplicate constraint id" }]
|
|
11530
11781
|
});
|
|
11531
11782
|
if (value.preferences?.fast && value.preferences.thorough)
|
|
11532
|
-
return
|
|
11783
|
+
return failure2("invalid_input", "fast and thorough preferences contradict", {
|
|
11533
11784
|
fields: [{ path: "preferences", reason: "fast and thorough cannot both be enabled" }]
|
|
11534
11785
|
});
|
|
11535
11786
|
const normalized = {
|
|
@@ -11713,7 +11964,7 @@ function resolvePolicy(input) {
|
|
|
11713
11964
|
};
|
|
11714
11965
|
const parsed = policySchema.safeParse(policy);
|
|
11715
11966
|
if (!parsed.success)
|
|
11716
|
-
return
|
|
11967
|
+
return failure2("invalid_input", "resolved policy is invalid", invalidFields(parsed.error));
|
|
11717
11968
|
return success(null, null, parsed.data);
|
|
11718
11969
|
}
|
|
11719
11970
|
function diffPolicy(previous, next, reason, now) {
|
|
@@ -11721,10 +11972,10 @@ function diffPolicy(previous, next, reason, now) {
|
|
|
11721
11972
|
throw new TypeError("previous policy is invalid");
|
|
11722
11973
|
if (!policySchema.safeParse(next).success)
|
|
11723
11974
|
throw new TypeError("next policy is invalid");
|
|
11724
|
-
const oldIds = new Set(previous?.requirements.map((
|
|
11725
|
-
const newIds = new Set(next.requirements.map((
|
|
11726
|
-
const added = [...newIds].filter((id) => !oldIds.has(id)).
|
|
11727
|
-
const retired = [...oldIds].filter((id) => !newIds.has(id)).
|
|
11975
|
+
const oldIds = new Set(previous?.requirements.map((item) => item.id) ?? []);
|
|
11976
|
+
const newIds = new Set(next.requirements.map((item) => item.id));
|
|
11977
|
+
const added = [...newIds].filter((id) => !oldIds.has(id)).toSorted(compareCodeUnits2);
|
|
11978
|
+
const retired = [...oldIds].filter((id) => !newIds.has(id)).toSorted(compareCodeUnits2);
|
|
11728
11979
|
if (added.length === 0 && retired.length === 0)
|
|
11729
11980
|
return null;
|
|
11730
11981
|
const normalizedReason = reason.trim();
|
|
@@ -11801,7 +12052,7 @@ var gitPaths = (root) => {
|
|
|
11801
12052
|
return {
|
|
11802
12053
|
paths: [],
|
|
11803
12054
|
uncertain: !/not a git repository/i.test(stderr),
|
|
11804
|
-
git:
|
|
12055
|
+
git: !/not a git repository/i.test(stderr)
|
|
11805
12056
|
};
|
|
11806
12057
|
}
|
|
11807
12058
|
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path10.sep).join("/")) : [];
|
|
@@ -11846,15 +12097,15 @@ var scopeRoots = (root, scope) => {
|
|
|
11846
12097
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
11847
12098
|
const target = path10.resolve(root, item);
|
|
11848
12099
|
if (!inside(root, target))
|
|
11849
|
-
return
|
|
12100
|
+
return failure2("invalid_input", `candidate scope escapes checkout: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} is outside the checkout` }] });
|
|
11850
12101
|
let ancestor = target;
|
|
11851
12102
|
while (!fs7.existsSync(ancestor) && ancestor !== root)
|
|
11852
12103
|
ancestor = path10.dirname(ancestor);
|
|
11853
12104
|
try {
|
|
11854
12105
|
if (!inside(root, fs7.realpathSync(ancestor)))
|
|
11855
|
-
return
|
|
12106
|
+
return failure2("invalid_input", `candidate scope escapes checkout through a symlink: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} resolves outside the checkout` }] });
|
|
11856
12107
|
} catch {
|
|
11857
|
-
return
|
|
12108
|
+
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
11858
12109
|
}
|
|
11859
12110
|
roots.push(target);
|
|
11860
12111
|
}
|
|
@@ -11865,11 +12116,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11865
12116
|
try {
|
|
11866
12117
|
checkout = fs7.realpathSync(root);
|
|
11867
12118
|
} catch {
|
|
11868
|
-
return
|
|
12119
|
+
return failure2("invalid_input", "candidate root does not exist");
|
|
11869
12120
|
}
|
|
11870
12121
|
const normalizedScope = canonicalScope(scope);
|
|
11871
12122
|
if (!normalizedScope)
|
|
11872
|
-
return
|
|
12123
|
+
return failure2("invalid_input", "candidate scope is invalid: paths must be checkout-relative — to work in another repository, keep this task here and coordinate a separate linked task in that checkout", { fields: [{ path: "scope.paths", reason: "must be checkout-relative" }] });
|
|
11873
12124
|
const roots = scopeRoots(checkout, normalizedScope);
|
|
11874
12125
|
if (!roots.ok)
|
|
11875
12126
|
return roots;
|
|
@@ -11898,7 +12149,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11898
12149
|
names.add(item);
|
|
11899
12150
|
const files = [];
|
|
11900
12151
|
let completeness = uncertain ? "uncertain" : "known";
|
|
11901
|
-
for (const item of [...names].
|
|
12152
|
+
for (const item of [...names].toSorted()) {
|
|
11902
12153
|
if (!scopeMatches(item, normalizedScope))
|
|
11903
12154
|
continue;
|
|
11904
12155
|
const target = path10.join(checkout, item);
|
|
@@ -11932,8 +12183,8 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11932
12183
|
}));
|
|
11933
12184
|
const namesByEnvironment = supplied.map(({ name }) => name);
|
|
11934
12185
|
if (new Set(namesByEnvironment).size !== namesByEnvironment.length || namesByEnvironment.some((name) => typeof name !== "string" || !name))
|
|
11935
|
-
return
|
|
11936
|
-
const values = supplied.
|
|
12186
|
+
return failure2("invalid_input", "candidate environment names must be unique and non-empty");
|
|
12187
|
+
const values = supplied.toSorted((left, right) => compareCodeUnits3(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
|
|
11937
12188
|
if (values.some(({ value }) => value === null))
|
|
11938
12189
|
completeness = "uncertain";
|
|
11939
12190
|
const headResult = spawnSync2("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
|
|
@@ -11950,7 +12201,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11950
12201
|
};
|
|
11951
12202
|
const candidate = { ...partial, id: candidateDigest(partial) };
|
|
11952
12203
|
const parsed = candidateSchema.safeParse(candidate);
|
|
11953
|
-
return parsed.success ? success(null, null, parsed.data) :
|
|
12204
|
+
return parsed.success ? success(null, null, parsed.data) : failure2("invalid_input", "captured candidate is invalid");
|
|
11954
12205
|
}
|
|
11955
12206
|
var fileMap = (candidate) => new Map(candidate.files.map((file) => [file.path, file]));
|
|
11956
12207
|
var changedPaths = (before, after) => {
|
|
@@ -12161,13 +12412,13 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
12161
12412
|
}
|
|
12162
12413
|
function evaluateClosure(requestedOutcome, view) {
|
|
12163
12414
|
if (requestedOutcome !== "stopped" && !view.task.policy)
|
|
12164
|
-
return
|
|
12415
|
+
return failure2("requirements_unsatisfied", "task has not been assessed");
|
|
12165
12416
|
if (view.task.policy && view.task.policy.policyVersion !== POLICY_VERSION)
|
|
12166
|
-
return
|
|
12417
|
+
return failure2("requirements_unsatisfied", "stored policy version is unsupported; reassessment is required");
|
|
12167
12418
|
const evaluations = view.requirements;
|
|
12168
12419
|
const openFindings = view.task.findings.filter((entry) => entry.data.disposition === "open");
|
|
12169
12420
|
if (requestedOutcome !== "stopped" && openFindings.length)
|
|
12170
|
-
return
|
|
12421
|
+
return failure2("requirements_unsatisfied", "open findings must be resolved before closure");
|
|
12171
12422
|
if (requestedOutcome !== "stopped") {
|
|
12172
12423
|
const evidenceById = new Map(view.evidence.map((entry) => [entry.evidenceId, entry.status]));
|
|
12173
12424
|
for (const entry of view.task.findings) {
|
|
@@ -12183,7 +12434,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12183
12434
|
});
|
|
12184
12435
|
});
|
|
12185
12436
|
if (!verified)
|
|
12186
|
-
return
|
|
12437
|
+
return failure2("requirements_unsatisfied", "fixed findings require current verification");
|
|
12187
12438
|
}
|
|
12188
12439
|
if (entry.data.disposition === "deferred") {
|
|
12189
12440
|
const valid = entry.data.resolution?.decisionIds.some((id) => {
|
|
@@ -12192,7 +12443,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12192
12443
|
return Boolean(decision && decisionEntry?.provenance.kind !== "imported" && decision.purpose === "limitation" && decision.response === "approved" && decision.revoked === null && decision.digest === decisionDigest(decision) && verifyDecisionContentAtRoot(view.workspace.root, decision.binding).ok && decision.binding.taskId === view.task.id && decision.binding.workspaceId === view.workspace.id && scopeCovers2(decision.binding.scope, entry.data.scope) && decision.requirementIds.some((requirementId) => view.task.policy?.requirements.some((requirement) => requirement.id === requirementId && requirement.acceptanceAllowed)));
|
|
12193
12444
|
});
|
|
12194
12445
|
if (!valid)
|
|
12195
|
-
return
|
|
12446
|
+
return failure2("requirements_unsatisfied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
12196
12447
|
}
|
|
12197
12448
|
}
|
|
12198
12449
|
}
|
|
@@ -12203,7 +12454,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12203
12454
|
return !requirement || requirement.before === "close";
|
|
12204
12455
|
});
|
|
12205
12456
|
if (requestedOutcome !== "stopped" && blocking.length)
|
|
12206
|
-
return
|
|
12457
|
+
return failure2("requirements_unsatisfied", "applicable requirements are unsatisfied", {
|
|
12207
12458
|
requirementIds: blocking.map((item) => item.requirementId),
|
|
12208
12459
|
requirements: blocking.map((item) => {
|
|
12209
12460
|
const requirement = view.task.policy?.requirements.find((candidate) => candidate.id === item.requirementId);
|
|
@@ -12218,7 +12469,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12218
12469
|
});
|
|
12219
12470
|
const accepted = evaluations.filter((item) => item.status === "accepted_limitation");
|
|
12220
12471
|
if (requestedOutcome === "verified" && accepted.length)
|
|
12221
|
-
return
|
|
12472
|
+
return failure2("requirements_unsatisfied", "accepted limitations cannot be reported as verified", {
|
|
12222
12473
|
requirementIds: accepted.map((item) => item.requirementId)
|
|
12223
12474
|
});
|
|
12224
12475
|
const evidenceIds = [
|
|
@@ -12369,7 +12620,7 @@ Load the skill; never act from memory of it.
|
|
|
12369
12620
|
// packages/workit-core/src/core/task-context.ts
|
|
12370
12621
|
function reconcileResume(view, observations = []) {
|
|
12371
12622
|
if (observations.length > 0)
|
|
12372
|
-
return
|
|
12623
|
+
return failure2("permission_denied", "worker observations require native host verification");
|
|
12373
12624
|
const candidate = captureCandidate(view.workspace.root, view.task.intent.data.scope, []);
|
|
12374
12625
|
if (!candidate.ok)
|
|
12375
12626
|
return candidate;
|
|
@@ -12425,7 +12676,7 @@ var compactReference = (ref) => {
|
|
|
12425
12676
|
return { kind: ref.kind };
|
|
12426
12677
|
};
|
|
12427
12678
|
function compactTaskContext(view) {
|
|
12428
|
-
const decisions = view.task.decisions.slice().
|
|
12679
|
+
const decisions = view.task.decisions.slice().toSorted((left, right) => {
|
|
12429
12680
|
const leftAt = compactTimestamp(left.recordedAt);
|
|
12430
12681
|
const rightAt = compactTimestamp(right.recordedAt);
|
|
12431
12682
|
if (leftAt !== rightAt)
|
|
@@ -12448,7 +12699,7 @@ function compactTaskContext(view) {
|
|
|
12448
12699
|
...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
|
|
12449
12700
|
...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
|
|
12450
12701
|
...view.task.progress.blockers.map((entry) => entry.reason)
|
|
12451
|
-
])).
|
|
12702
|
+
])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
|
|
12452
12703
|
const context = {
|
|
12453
12704
|
objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
|
|
12454
12705
|
status: view.task.status,
|
|
@@ -12511,14 +12762,14 @@ var sameValue = (left, right) => {
|
|
|
12511
12762
|
var validNativeProvenance = (value, caller, expected) => {
|
|
12512
12763
|
if (!provenanceSchema.safeParse(value).success)
|
|
12513
12764
|
return false;
|
|
12514
|
-
const
|
|
12515
|
-
return
|
|
12765
|
+
const observed = value;
|
|
12766
|
+
return observed.kind === "host_observed" && observed.host === caller.host && observed.workerId === expected.workerId && sameValue(observed.session, expected.session) && observed.receipts.some((receipt) => receipt.kind === "host" && receipt.host === caller.host);
|
|
12516
12767
|
};
|
|
12517
12768
|
var validDispatchProvenance = (value, caller, workerId) => {
|
|
12518
12769
|
if (!provenanceSchema.safeParse(value).success)
|
|
12519
12770
|
return false;
|
|
12520
|
-
const
|
|
12521
|
-
return
|
|
12771
|
+
const observed = value;
|
|
12772
|
+
return observed.kind === "host_observed" && observed.host === caller.host && observed.workerId === workerId && observed.session?.kind === "host" && observed.session.host === caller.host && observed.session.handle === caller.actor && observed.receipts.some((receipt) => receipt.kind === "host" && receipt.host === caller.host);
|
|
12522
12773
|
};
|
|
12523
12774
|
var validResumeApproval = (task, workspace, authorityRefs, context) => authorityRefs.some((ref) => {
|
|
12524
12775
|
if (ref.kind !== "record" || ref.collection !== "decisions")
|
|
@@ -12535,16 +12786,16 @@ var validResumeApproval = (task, workspace, authorityRefs, context) => authority
|
|
|
12535
12786
|
});
|
|
12536
12787
|
var verifyNativeWorker = (verifier, input, binding) => {
|
|
12537
12788
|
if (!verifier)
|
|
12538
|
-
return
|
|
12789
|
+
return failure2("permission_denied", "native worker verifier is unavailable");
|
|
12539
12790
|
let result;
|
|
12540
12791
|
try {
|
|
12541
12792
|
result = verifier.verifyWorker(input);
|
|
12542
12793
|
} catch (error) {
|
|
12543
|
-
return
|
|
12794
|
+
return failure2("permission_denied", `native worker observation failed: ${String(error)}`);
|
|
12544
12795
|
}
|
|
12545
12796
|
const expected = input.expected;
|
|
12546
12797
|
if (!result.ok || !validNativeProvenance(result.data, input.caller, expected))
|
|
12547
|
-
return
|
|
12798
|
+
return failure2("permission_denied", "native worker observation was not attested");
|
|
12548
12799
|
const token = {};
|
|
12549
12800
|
verifiedWorkers.set(token, {
|
|
12550
12801
|
taskId: expected.taskId,
|
|
@@ -12571,7 +12822,7 @@ var takeWorker = (token, binding, expected) => {
|
|
|
12571
12822
|
};
|
|
12572
12823
|
var applyWorkerLifecycle = (input) => {
|
|
12573
12824
|
if (!input.store || !input.authority || !input.authorityOwner)
|
|
12574
|
-
return
|
|
12825
|
+
return failure2("invalid_input", "native worker observation preconditions are required");
|
|
12575
12826
|
const authority = takeWorker(input.authority, {
|
|
12576
12827
|
owner: input.authorityOwner,
|
|
12577
12828
|
store: input.store,
|
|
@@ -12579,7 +12830,7 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12579
12830
|
caller: input.caller
|
|
12580
12831
|
}, input);
|
|
12581
12832
|
if (!authority)
|
|
12582
|
-
return
|
|
12833
|
+
return failure2("permission_denied", "native worker observation is not verified");
|
|
12583
12834
|
const task = input.store.readTask(input.taskId);
|
|
12584
12835
|
if (!task.ok)
|
|
12585
12836
|
return task;
|
|
@@ -12587,35 +12838,35 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12587
12838
|
if (!workspace.ok)
|
|
12588
12839
|
return workspace;
|
|
12589
12840
|
if (!workspace.data)
|
|
12590
|
-
return
|
|
12841
|
+
return failure2("not_found", "workspace not found");
|
|
12591
12842
|
if (task.data.workspaceId !== authority.workspaceId || workspace.data.id !== authority.workspaceId)
|
|
12592
|
-
return
|
|
12843
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
12593
12844
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
12594
12845
|
if (!entry)
|
|
12595
|
-
return
|
|
12846
|
+
return failure2("not_found", "worker not found");
|
|
12596
12847
|
if (task.data.status === "closed")
|
|
12597
|
-
return
|
|
12848
|
+
return failure2("invalid_transition", "closed task cannot observe workers");
|
|
12598
12849
|
if (task.data.status === "paused" && (input.state === "running" || input.state === "cancelling"))
|
|
12599
|
-
return
|
|
12850
|
+
return failure2("invalid_transition", "paused task cannot run a worker");
|
|
12600
12851
|
const notStarted = input.dispatch === true;
|
|
12601
12852
|
if (notStarted && entry.data.state === "stopped" && input.session === null)
|
|
12602
12853
|
return success(task.data.revision, workspace.data.revision, entry);
|
|
12603
12854
|
if (notStarted && (input.state !== "stopped" || input.session !== null))
|
|
12604
|
-
return
|
|
12855
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
12605
12856
|
if (notStarted && entry.data.session !== null)
|
|
12606
|
-
return
|
|
12857
|
+
return failure2("invalid_transition", "worker already has an observed session");
|
|
12607
12858
|
if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
|
|
12608
|
-
return
|
|
12859
|
+
return failure2("invalid_transition", "worker launch was not claimed");
|
|
12609
12860
|
if (input.report && input.state !== "stopped")
|
|
12610
|
-
return
|
|
12861
|
+
return failure2("invalid_input", "worker reports require a stopped worker");
|
|
12611
12862
|
if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
|
|
12612
|
-
return
|
|
12863
|
+
return failure2("invalid_input", "running worker observations require a session");
|
|
12613
12864
|
if (entry.data.session && !sameValue(entry.data.session, input.session))
|
|
12614
|
-
return
|
|
12865
|
+
return failure2("permission_denied", "worker session does not match its assignment");
|
|
12615
12866
|
if (input.state !== "running" && entry.data.state === "assigned" && input.state !== "stopped")
|
|
12616
|
-
return
|
|
12867
|
+
return failure2("invalid_transition", "worker has not started");
|
|
12617
12868
|
if (input.state === "running" && entry.data.state === "stopped")
|
|
12618
|
-
return
|
|
12869
|
+
return failure2("invalid_transition", "stopped worker cannot run again");
|
|
12619
12870
|
const terminalCancel = entry.data.state === "cancelling" && input.state === "running";
|
|
12620
12871
|
const nextEntry = {
|
|
12621
12872
|
...entry,
|
|
@@ -12649,7 +12900,7 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12649
12900
|
if (!changed.ok)
|
|
12650
12901
|
return changed;
|
|
12651
12902
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
12652
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
12903
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
|
|
12653
12904
|
};
|
|
12654
12905
|
var refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] }));
|
|
12655
12906
|
var trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now;
|
|
@@ -12733,13 +12984,13 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12733
12984
|
])
|
|
12734
12985
|
allocate(entry.id);
|
|
12735
12986
|
const fresh = (id) => allocate(id);
|
|
12736
|
-
const
|
|
12987
|
+
const imported = importedProvenance(context);
|
|
12737
12988
|
const remap = (ref) => mapRef(ref, ids);
|
|
12738
12989
|
const intent = {
|
|
12739
12990
|
...source.intent,
|
|
12740
12991
|
id: fresh(source.intent.id),
|
|
12741
12992
|
recordedAt: timestamp,
|
|
12742
|
-
provenance,
|
|
12993
|
+
provenance: imported,
|
|
12743
12994
|
data: rewriteRecordRefs(source.intent.data, intentSchema, remap)
|
|
12744
12995
|
};
|
|
12745
12996
|
const assessments = source.assessments.map((entry) => {
|
|
@@ -12748,7 +12999,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12748
12999
|
...entry,
|
|
12749
13000
|
id: fresh(entry.id),
|
|
12750
13001
|
recordedAt: timestamp,
|
|
12751
|
-
provenance,
|
|
13002
|
+
provenance: imported,
|
|
12752
13003
|
data: rewriteRecordRefs(data, assessmentSchema, remap)
|
|
12753
13004
|
};
|
|
12754
13005
|
});
|
|
@@ -12756,14 +13007,14 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12756
13007
|
...entry,
|
|
12757
13008
|
id: fresh(entry.id),
|
|
12758
13009
|
recordedAt: timestamp,
|
|
12759
|
-
provenance,
|
|
13010
|
+
provenance: imported,
|
|
12760
13011
|
data: rewriteRecordRefs(entry.data, evidenceSchema, remap)
|
|
12761
13012
|
}));
|
|
12762
13013
|
const decisions = source.decisions.map((entry) => ({
|
|
12763
13014
|
...entry,
|
|
12764
13015
|
id: fresh(entry.id),
|
|
12765
13016
|
recordedAt: timestamp,
|
|
12766
|
-
provenance
|
|
13017
|
+
provenance: imported
|
|
12767
13018
|
}));
|
|
12768
13019
|
const findings = source.findings.map((entry) => {
|
|
12769
13020
|
const data = rewriteRecordRefs(entry.data, findingSchema, remap);
|
|
@@ -12771,7 +13022,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12771
13022
|
...entry,
|
|
12772
13023
|
id: fresh(entry.id),
|
|
12773
13024
|
recordedAt: timestamp,
|
|
12774
|
-
provenance,
|
|
13025
|
+
provenance: imported,
|
|
12775
13026
|
data: {
|
|
12776
13027
|
...data,
|
|
12777
13028
|
resolution: data.resolution ? {
|
|
@@ -12786,7 +13037,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12786
13037
|
...entry,
|
|
12787
13038
|
id: fresh(entry.id),
|
|
12788
13039
|
recordedAt: timestamp,
|
|
12789
|
-
provenance,
|
|
13040
|
+
provenance: imported,
|
|
12790
13041
|
data: {
|
|
12791
13042
|
...entry.data,
|
|
12792
13043
|
state: "stopped",
|
|
@@ -12881,9 +13132,9 @@ class WorkitCore {
|
|
|
12881
13132
|
contextRootError() {
|
|
12882
13133
|
try {
|
|
12883
13134
|
if (realpathSync6(this.context.root) !== this.store.root)
|
|
12884
|
-
return
|
|
13135
|
+
return failure2("invalid_input", "operation context root does not match the task store root");
|
|
12885
13136
|
} catch {
|
|
12886
|
-
return
|
|
13137
|
+
return failure2("invalid_input", "operation context root cannot be resolved");
|
|
12887
13138
|
}
|
|
12888
13139
|
return success(null, null, null);
|
|
12889
13140
|
}
|
|
@@ -12902,16 +13153,16 @@ class WorkitCore {
|
|
|
12902
13153
|
helperEntry(task, requireSession = false, requireActive = false) {
|
|
12903
13154
|
const workerId = this.context.workerId ?? null;
|
|
12904
13155
|
if (workerId === null)
|
|
12905
|
-
return
|
|
13156
|
+
return failure2("permission_denied", "operation is lead-only");
|
|
12906
13157
|
const worker = task.workers.find((entry) => entry.id === workerId);
|
|
12907
13158
|
if (!worker)
|
|
12908
|
-
return
|
|
13159
|
+
return failure2("permission_denied", "worker is not assigned to this task");
|
|
12909
13160
|
if (worker.data.session && !sameSession2(worker.data.session, this.context))
|
|
12910
|
-
return
|
|
13161
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
12911
13162
|
if (requireSession && (!worker.data.session || !sameSession2(worker.data.session, this.context)))
|
|
12912
|
-
return
|
|
13163
|
+
return failure2("permission_denied", "worker session has not been observed");
|
|
12913
13164
|
if (requireActive && worker.data.state !== "running")
|
|
12914
|
-
return
|
|
13165
|
+
return failure2("permission_denied", "worker is not active");
|
|
12915
13166
|
return success(null, null, worker);
|
|
12916
13167
|
}
|
|
12917
13168
|
helperTaskGuard(task, allowRead = false) {
|
|
@@ -12920,13 +13171,13 @@ class WorkitCore {
|
|
|
12920
13171
|
const worker = this.helperEntry(task);
|
|
12921
13172
|
if (!worker.ok)
|
|
12922
13173
|
return worker;
|
|
12923
|
-
return allowRead ? success(null, null, null) :
|
|
13174
|
+
return allowRead ? success(null, null, null) : failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
12924
13175
|
}
|
|
12925
13176
|
activeWorkerBlocker(task, workspace) {
|
|
12926
13177
|
if (workspace.writer)
|
|
12927
|
-
return
|
|
13178
|
+
return failure2("recovery_required", "writer ownership must be released first");
|
|
12928
13179
|
if (task.workers.some((entry) => workerBlocksTransition("close", entry.data.state)))
|
|
12929
|
-
return
|
|
13180
|
+
return failure2("recovery_required", "worker state requires reconciliation");
|
|
12930
13181
|
return null;
|
|
12931
13182
|
}
|
|
12932
13183
|
state(request) {
|
|
@@ -12934,7 +13185,7 @@ class WorkitCore {
|
|
|
12934
13185
|
if (!root.ok)
|
|
12935
13186
|
return root;
|
|
12936
13187
|
if ((this.context.workerId ?? null) !== null)
|
|
12937
|
-
return
|
|
13188
|
+
return failure2("permission_denied", "helpers cannot control task state");
|
|
12938
13189
|
const parsed = parseOperation("state", request);
|
|
12939
13190
|
if (!parsed.ok)
|
|
12940
13191
|
return parsed;
|
|
@@ -12947,10 +13198,10 @@ class WorkitCore {
|
|
|
12947
13198
|
if (!workspace.ok)
|
|
12948
13199
|
return workspace;
|
|
12949
13200
|
if (!workspace.data)
|
|
12950
|
-
return
|
|
13201
|
+
return failure2("not_found", "workspace not found");
|
|
12951
13202
|
const portable = taskRecordSchema.safeParse(portableTask(task.data));
|
|
12952
13203
|
if (!portable.success)
|
|
12953
|
-
return
|
|
13204
|
+
return failure2("storage_error", "portable task is invalid after sanitization");
|
|
12954
13205
|
const bundle = {
|
|
12955
13206
|
schemaVersion: 1,
|
|
12956
13207
|
exportedAt: trustedNow(this.context),
|
|
@@ -12962,13 +13213,13 @@ class WorkitCore {
|
|
|
12962
13213
|
digest: exportDigest(bundle)
|
|
12963
13214
|
});
|
|
12964
13215
|
if (!checked.success)
|
|
12965
|
-
return
|
|
13216
|
+
return failure2("storage_error", "portable export bundle is invalid");
|
|
12966
13217
|
return success(task.data.revision, workspace.data.revision, checked.data);
|
|
12967
13218
|
}
|
|
12968
13219
|
if (input.action === "import") {
|
|
12969
13220
|
const checked = exportBundleSchema.safeParse(input.bundle);
|
|
12970
13221
|
if (!checked.success)
|
|
12971
|
-
return
|
|
13222
|
+
return failure2("invalid_input", "export bundle is invalid");
|
|
12972
13223
|
const bundle = checked.data;
|
|
12973
13224
|
if (bundle.sourceWorkspaceId !== bundle.task.workspaceId || exportDigest({
|
|
12974
13225
|
schemaVersion: bundle.schemaVersion,
|
|
@@ -12976,7 +13227,7 @@ class WorkitCore {
|
|
|
12976
13227
|
sourceWorkspaceId: bundle.sourceWorkspaceId,
|
|
12977
13228
|
task: bundle.task
|
|
12978
13229
|
}) !== bundle.digest)
|
|
12979
|
-
return
|
|
13230
|
+
return failure2("invalid_input", "export bundle digest is invalid");
|
|
12980
13231
|
const workspace = this.store.readWorkspace();
|
|
12981
13232
|
if (!workspace.ok)
|
|
12982
13233
|
return workspace;
|
|
@@ -12995,7 +13246,7 @@ class WorkitCore {
|
|
|
12995
13246
|
return this.summary(imported.data);
|
|
12996
13247
|
}
|
|
12997
13248
|
if (!this.context.nativeRecovery)
|
|
12998
|
-
return
|
|
13249
|
+
return failure2("permission_denied", "native recovery authority is unavailable");
|
|
12999
13250
|
const processEvidence = (lock, writer) => this.context.nativeRecovery({
|
|
13000
13251
|
lock,
|
|
13001
13252
|
writer,
|
|
@@ -13015,12 +13266,12 @@ class WorkitCore {
|
|
|
13015
13266
|
if (!workspace.ok)
|
|
13016
13267
|
return workspace;
|
|
13017
13268
|
if (!workspace.data)
|
|
13018
|
-
return
|
|
13269
|
+
return failure2("not_found", "workspace not found");
|
|
13019
13270
|
this.fillRevisions(input, undefined, workspace.data);
|
|
13020
13271
|
if (input.target === "workspace" && input.taskId !== undefined)
|
|
13021
|
-
return
|
|
13272
|
+
return failure2("invalid_input", "workspace recovery takes no task ID");
|
|
13022
13273
|
if (input.target === "task" && input.taskId === undefined)
|
|
13023
|
-
return
|
|
13274
|
+
return failure2("invalid_input", "task recovery requires a task ID");
|
|
13024
13275
|
return this.store.recoverTask(input.taskId, {
|
|
13025
13276
|
expectedBytes: input.expectedBytes,
|
|
13026
13277
|
snapshotDigest: input.snapshotDigest,
|
|
@@ -13040,7 +13291,7 @@ class WorkitCore {
|
|
|
13040
13291
|
const input = parsed.data;
|
|
13041
13292
|
if ((this.context.workerId ?? null) !== null) {
|
|
13042
13293
|
if (input.action !== "inspect" && input.action !== "list")
|
|
13043
|
-
return
|
|
13294
|
+
return failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
13044
13295
|
}
|
|
13045
13296
|
switch (input.action) {
|
|
13046
13297
|
case "start": {
|
|
@@ -13077,14 +13328,14 @@ class WorkitCore {
|
|
|
13077
13328
|
objective: task.intent.data.objective,
|
|
13078
13329
|
progress: task.progress,
|
|
13079
13330
|
decisions: task.decisions.map(({ data }) => data)
|
|
13080
|
-
}).toLowerCase().includes(term))).
|
|
13331
|
+
}).toLowerCase().includes(term))).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, limit);
|
|
13081
13332
|
if (selected.length === 0)
|
|
13082
13333
|
return success(null, null, []);
|
|
13083
13334
|
const workspace = this.store.readWorkspace();
|
|
13084
13335
|
if (!workspace.ok)
|
|
13085
13336
|
return workspace;
|
|
13086
13337
|
if (!workspace.data)
|
|
13087
|
-
return
|
|
13338
|
+
return failure2("not_found", "workspace not found");
|
|
13088
13339
|
const tasks = selected.map((task) => ({
|
|
13089
13340
|
id: task.id,
|
|
13090
13341
|
revision: task.revision,
|
|
@@ -13126,7 +13377,7 @@ class WorkitCore {
|
|
|
13126
13377
|
case "close":
|
|
13127
13378
|
return this.close(input);
|
|
13128
13379
|
default:
|
|
13129
|
-
return
|
|
13380
|
+
return failure2("invalid_transition", `task action ${input.action} is not implemented`);
|
|
13130
13381
|
}
|
|
13131
13382
|
}
|
|
13132
13383
|
policy(request) {
|
|
@@ -13143,7 +13394,7 @@ class WorkitCore {
|
|
|
13143
13394
|
if (input.action === "explain")
|
|
13144
13395
|
return success(task.data.revision, null, task.data.policy);
|
|
13145
13396
|
if ((this.context.workerId ?? null) !== null)
|
|
13146
|
-
return
|
|
13397
|
+
return failure2("permission_denied", "helpers cannot change task requirements");
|
|
13147
13398
|
this.fillRevisions(input, task.data);
|
|
13148
13399
|
const resolved = this.resolve(task.data, input.assessment);
|
|
13149
13400
|
if (!resolved.ok)
|
|
@@ -13151,10 +13402,10 @@ class WorkitCore {
|
|
|
13151
13402
|
if (input.action === "preview")
|
|
13152
13403
|
return success(null, null, resolved.data);
|
|
13153
13404
|
if (input.action !== "assess")
|
|
13154
|
-
return
|
|
13405
|
+
return failure2("invalid_transition", "unsupported policy action");
|
|
13155
13406
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13156
13407
|
if (current.status === "closed")
|
|
13157
|
-
return
|
|
13408
|
+
return failure2("invalid_transition", "closed task cannot be assessed");
|
|
13158
13409
|
const nextChange = diffPolicy(current.policy, resolved.data, "policy reassessed", mutation.now);
|
|
13159
13410
|
const assessment = {
|
|
13160
13411
|
id: newId(),
|
|
@@ -13187,17 +13438,17 @@ class WorkitCore {
|
|
|
13187
13438
|
if (!task.ok)
|
|
13188
13439
|
return task;
|
|
13189
13440
|
if (task.data.status === "closed")
|
|
13190
|
-
return
|
|
13441
|
+
return failure2("invalid_transition", "closed task cannot record evidence");
|
|
13191
13442
|
this.fillRevisions(input, task.data);
|
|
13192
13443
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
13193
13444
|
if (helper && !helper.ok)
|
|
13194
13445
|
return helper;
|
|
13195
13446
|
const evidence = input.evidence;
|
|
13196
13447
|
if ((evidence.result === "missing" || evidence.result === "skipped") && !evidence.summary.trim())
|
|
13197
|
-
return
|
|
13448
|
+
return failure2("invalid_input", "missing or skipped evidence requires a reason");
|
|
13198
13449
|
if (evidence.kind === "review") {
|
|
13199
13450
|
if (!sameSession2(evidence.reviewContext, this.context))
|
|
13200
|
-
return
|
|
13451
|
+
return failure2("invalid_input", "review context must match the trusted caller session");
|
|
13201
13452
|
}
|
|
13202
13453
|
const currentCandidate = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
13203
13454
|
if (!currentCandidate.ok)
|
|
@@ -13207,12 +13458,12 @@ class WorkitCore {
|
|
|
13207
13458
|
if (helper?.ok) {
|
|
13208
13459
|
const assignment = helper.data.data.assignment;
|
|
13209
13460
|
if (evidence.requirementIds.some((id) => !assignment.requirementIds.includes(id)) || !checkPin(assignment, bound.beforeCandidateId, bound.candidateId) || !refsWithinScope(evidence.refs, assignment.scope) || !refsWithinScope(evidence.refs, task.data.intent.data.scope))
|
|
13210
|
-
return
|
|
13461
|
+
return failure2("permission_denied", "evidence is outside the worker assignment");
|
|
13211
13462
|
}
|
|
13212
13463
|
const knownCandidates = new Set(task.data.candidates.map((candidate) => candidate.id));
|
|
13213
13464
|
for (const candidateId of [bound.beforeCandidateId, bound.candidateId]) {
|
|
13214
13465
|
if (candidateId && candidateId !== currentCandidate.data.id && !knownCandidates.has(candidateId))
|
|
13215
|
-
return
|
|
13466
|
+
return failure2("invalid_input", "evidence candidate is not a captured candidate");
|
|
13216
13467
|
}
|
|
13217
13468
|
const boundEvidence = { ...evidence, ...bound };
|
|
13218
13469
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
@@ -13269,38 +13520,38 @@ class WorkitCore {
|
|
|
13269
13520
|
return parsed;
|
|
13270
13521
|
const input = parsed.data;
|
|
13271
13522
|
if (nativeRequired && input.action !== "record")
|
|
13272
|
-
return
|
|
13523
|
+
return failure2("permission_denied", "native observation is only valid for recording decisions");
|
|
13273
13524
|
const stated = input.action === "record" && input.response === "stated";
|
|
13274
13525
|
if (stated && input.purpose === "action")
|
|
13275
|
-
return
|
|
13526
|
+
return failure2("permission_denied", "stated choices cannot authorize mutating actions");
|
|
13276
13527
|
if (stated && !input.binding?.statedChoice)
|
|
13277
|
-
return
|
|
13528
|
+
return failure2("invalid_input", "stated choices require binding.statedChoice");
|
|
13278
13529
|
if (nativeRequired && nativeObservation === undefined && !stated && !standing)
|
|
13279
|
-
return
|
|
13530
|
+
return failure2("permission_denied", "native decision observation is required");
|
|
13280
13531
|
if (standing && (!input.binding?.standing || input.purpose !== "action" || input.response !== "approved"))
|
|
13281
|
-
return
|
|
13532
|
+
return failure2("invalid_input", "standing approvals need an approved action binding with a standing rule");
|
|
13282
13533
|
const task = this.store.readTask(input.taskId);
|
|
13283
13534
|
if (!task.ok)
|
|
13284
13535
|
return task;
|
|
13285
13536
|
if ((this.context.workerId ?? null) !== null)
|
|
13286
|
-
return
|
|
13537
|
+
return failure2("permission_denied", "helpers cannot record or revoke decisions");
|
|
13287
13538
|
this.fillRevisions(input, task.data);
|
|
13288
13539
|
if (input.action === "record") {
|
|
13289
13540
|
if (task.data.status === "closed")
|
|
13290
|
-
return
|
|
13541
|
+
return failure2("invalid_transition", "closed task cannot record a decision");
|
|
13291
13542
|
const workspace = this.store.readWorkspace();
|
|
13292
13543
|
if (!workspace.ok)
|
|
13293
13544
|
return workspace;
|
|
13294
13545
|
if (!workspace.data)
|
|
13295
|
-
return
|
|
13546
|
+
return failure2("not_found", "workspace not found");
|
|
13296
13547
|
if (input.binding.taskId !== task.data.id || input.binding.workspaceId !== workspace.data.id)
|
|
13297
|
-
return
|
|
13548
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
13298
13549
|
const content = verifyDecisionContent(this.store, input.binding);
|
|
13299
13550
|
if (!content.ok)
|
|
13300
13551
|
return content;
|
|
13301
13552
|
const knownRequirements = new Set(task.data.policy?.requirements.map((item) => item.id) ?? []);
|
|
13302
13553
|
if (input.requirementIds.some((id) => !knownRequirements.has(id)))
|
|
13303
|
-
return
|
|
13554
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
13304
13555
|
const base = {
|
|
13305
13556
|
purpose: input.purpose,
|
|
13306
13557
|
binding: input.binding,
|
|
@@ -13331,16 +13582,16 @@ class WorkitCore {
|
|
|
13331
13582
|
return native;
|
|
13332
13583
|
const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
|
|
13333
13584
|
if (native?.ok && !nativeProvenance)
|
|
13334
|
-
return
|
|
13585
|
+
return failure2("permission_denied", "native decision authority was retired");
|
|
13335
13586
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13336
|
-
const
|
|
13337
|
-
if (!
|
|
13338
|
-
return
|
|
13587
|
+
const latestContent = verifyDecisionContent(this.store, input.binding);
|
|
13588
|
+
if (!latestContent.ok)
|
|
13589
|
+
return latestContent;
|
|
13339
13590
|
const known = new Set(current.policy?.requirements.map((item) => item.id) ?? []);
|
|
13340
13591
|
if (input.requirementIds.some((id) => !known.has(id)))
|
|
13341
|
-
return
|
|
13592
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
13342
13593
|
if (nativeProvenance && current.decisions.some((entry) => entry.provenance.receipts.some((existingReceipt) => nativeProvenance.receipts.some((receipt) => canonicalJson(receipt) === canonicalJson(existingReceipt)))))
|
|
13343
|
-
return
|
|
13594
|
+
return failure2("permission_denied", "native decision receipt was already consumed");
|
|
13344
13595
|
const entry = {
|
|
13345
13596
|
id: newId(),
|
|
13346
13597
|
recordedAt: mutation.now,
|
|
@@ -13358,21 +13609,21 @@ class WorkitCore {
|
|
|
13358
13609
|
}
|
|
13359
13610
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13360
13611
|
if (!decision)
|
|
13361
|
-
return
|
|
13612
|
+
return failure2("not_found", "decision not found");
|
|
13362
13613
|
if (!input.reason.trim())
|
|
13363
|
-
return
|
|
13614
|
+
return failure2("invalid_input", "decision revocation requires a reason");
|
|
13364
13615
|
if (decision.data.revoked)
|
|
13365
|
-
return
|
|
13616
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13366
13617
|
if (decision.data.consumption)
|
|
13367
|
-
return
|
|
13618
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13368
13619
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13369
13620
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13370
13621
|
if (!entry)
|
|
13371
|
-
return
|
|
13622
|
+
return failure2("not_found", "decision not found");
|
|
13372
13623
|
if (entry.data.revoked)
|
|
13373
|
-
return
|
|
13624
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13374
13625
|
if (entry.data.consumption)
|
|
13375
|
-
return
|
|
13626
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13376
13627
|
const data = {
|
|
13377
13628
|
...entry.data,
|
|
13378
13629
|
revoked: { at: mutation.now, reason: input.reason }
|
|
@@ -13386,7 +13637,7 @@ class WorkitCore {
|
|
|
13386
13637
|
if (!changed.ok)
|
|
13387
13638
|
return changed;
|
|
13388
13639
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13389
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13640
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
|
|
13390
13641
|
}
|
|
13391
13642
|
finding(request) {
|
|
13392
13643
|
const root = this.contextRootError();
|
|
@@ -13400,7 +13651,7 @@ class WorkitCore {
|
|
|
13400
13651
|
if (!task.ok)
|
|
13401
13652
|
return task;
|
|
13402
13653
|
if (task.data.status === "closed")
|
|
13403
|
-
return
|
|
13654
|
+
return failure2("invalid_transition", "closed task cannot mutate findings");
|
|
13404
13655
|
this.fillRevisions(input, task.data);
|
|
13405
13656
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
13406
13657
|
if (helper && !helper.ok)
|
|
@@ -13409,10 +13660,10 @@ class WorkitCore {
|
|
|
13409
13660
|
if (helper?.ok) {
|
|
13410
13661
|
const assignment = helper.data.data.assignment;
|
|
13411
13662
|
if (!bindingCovers(assignment.scope, input.scope) || !bindingCovers(task.data.intent.data.scope, input.scope) || !checkPin(assignment, null, input.candidateId ?? null) || !refsWithinScope(input.refs, assignment.scope) || !refsWithinScope(input.refs, task.data.intent.data.scope))
|
|
13412
|
-
return
|
|
13663
|
+
return failure2("permission_denied", "finding is outside the worker assignment");
|
|
13413
13664
|
}
|
|
13414
13665
|
if (input.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.candidateId))
|
|
13415
|
-
return
|
|
13666
|
+
return failure2("invalid_input", "finding candidate is not a captured candidate");
|
|
13416
13667
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13417
13668
|
const entry = {
|
|
13418
13669
|
id: newId(),
|
|
@@ -13438,16 +13689,16 @@ class WorkitCore {
|
|
|
13438
13689
|
return success(changed.data.revision, null, changed.data.findings.at(-1));
|
|
13439
13690
|
}
|
|
13440
13691
|
if (helper?.ok)
|
|
13441
|
-
return
|
|
13692
|
+
return failure2("permission_denied", "helpers cannot resolve findings");
|
|
13442
13693
|
const finding = task.data.findings.find((entry) => entry.id === input.findingId);
|
|
13443
13694
|
if (!finding)
|
|
13444
|
-
return
|
|
13695
|
+
return failure2("not_found", "finding not found");
|
|
13445
13696
|
if (!input.reason.trim())
|
|
13446
|
-
return
|
|
13697
|
+
return failure2("invalid_input", "finding resolution requires a reason");
|
|
13447
13698
|
const evidence = task.data.evidence.filter((entry) => input.evidenceIds.includes(entry.id));
|
|
13448
13699
|
const decisions = task.data.decisions.filter((entry) => input.decisionIds.includes(entry.id));
|
|
13449
13700
|
if (evidence.length !== input.evidenceIds.length || decisions.length !== input.decisionIds.length)
|
|
13450
|
-
return
|
|
13701
|
+
return failure2("invalid_input", "finding resolution references an unknown record");
|
|
13451
13702
|
if (input.disposition === "fixed") {
|
|
13452
13703
|
const current = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
13453
13704
|
if (!current.ok)
|
|
@@ -13462,10 +13713,10 @@ class WorkitCore {
|
|
|
13462
13713
|
});
|
|
13463
13714
|
});
|
|
13464
13715
|
if (!verified)
|
|
13465
|
-
return
|
|
13716
|
+
return failure2("permission_denied", "fixed findings require passing verification evidence");
|
|
13466
13717
|
}
|
|
13467
13718
|
if (input.disposition === "dismissed" && evidence.length === 0)
|
|
13468
|
-
return
|
|
13719
|
+
return failure2("permission_denied", "dismissal requires supporting evidence");
|
|
13469
13720
|
if (input.disposition === "dismissed") {
|
|
13470
13721
|
const relevant = evidence.every((entry) => {
|
|
13471
13722
|
if (entry.data.result === "missing" || entry.data.result === "skipped")
|
|
@@ -13475,22 +13726,22 @@ class WorkitCore {
|
|
|
13475
13726
|
return candidateMatches && (referenceMatches || entry.data.claim === finding.data.claim);
|
|
13476
13727
|
});
|
|
13477
13728
|
if (!relevant)
|
|
13478
|
-
return
|
|
13729
|
+
return failure2("permission_denied", "dismissal evidence is unrelated to the finding");
|
|
13479
13730
|
}
|
|
13480
13731
|
if (input.disposition === "deferred") {
|
|
13481
13732
|
const workspace = this.store.readWorkspace();
|
|
13482
13733
|
if (!workspace.ok)
|
|
13483
13734
|
return workspace;
|
|
13484
13735
|
if (!workspace.data)
|
|
13485
|
-
return
|
|
13736
|
+
return failure2("not_found", "workspace not found");
|
|
13486
13737
|
const allowed = decisions.some((entry) => entry.provenance.kind !== "imported" && entry.data.purpose === "limitation" && entry.data.response === "approved" && entry.data.revoked === null && entry.data.digest === decisionDigest(entry.data) && verifyDecisionContent(this.store, entry.data.binding).ok && entry.data.binding.taskId === task.data.id && entry.data.binding.workspaceId === workspace.data.id && bindingCovers(entry.data.binding.scope, finding.data.scope) && entry.data.requirementIds.some((id) => task.data.policy?.requirements.some((requirement) => requirement.id === id && requirement.acceptanceAllowed)));
|
|
13487
13738
|
if (!allowed)
|
|
13488
|
-
return
|
|
13739
|
+
return failure2("permission_denied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
13489
13740
|
}
|
|
13490
13741
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13491
13742
|
const existing = current.findings.find((entry) => entry.id === input.findingId);
|
|
13492
13743
|
if (!existing)
|
|
13493
|
-
return
|
|
13744
|
+
return failure2("not_found", "finding not found");
|
|
13494
13745
|
const data = input.disposition === "open" ? { ...existing.data, disposition: "open", resolution: null } : {
|
|
13495
13746
|
...existing.data,
|
|
13496
13747
|
disposition: input.disposition,
|
|
@@ -13509,7 +13760,7 @@ class WorkitCore {
|
|
|
13509
13760
|
if (!changed.ok)
|
|
13510
13761
|
return changed;
|
|
13511
13762
|
const entry = changed.data.findings.find((candidate) => candidate.id === input.findingId);
|
|
13512
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13763
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
|
|
13513
13764
|
}
|
|
13514
13765
|
worker(request) {
|
|
13515
13766
|
const root = this.contextRootError();
|
|
@@ -13526,16 +13777,16 @@ class WorkitCore {
|
|
|
13526
13777
|
if (!workspace.ok)
|
|
13527
13778
|
return workspace;
|
|
13528
13779
|
if (!workspace.data)
|
|
13529
|
-
return
|
|
13780
|
+
return failure2("not_found", "workspace not found");
|
|
13530
13781
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13531
13782
|
const helperId = this.context.workerId ?? null;
|
|
13532
13783
|
if (input.action === "assign") {
|
|
13533
13784
|
if (helperId !== null)
|
|
13534
|
-
return
|
|
13785
|
+
return failure2("permission_denied", "helpers cannot assign workers");
|
|
13535
13786
|
if (task.data.status !== "active")
|
|
13536
|
-
return
|
|
13787
|
+
return failure2("invalid_transition", "paused or closed tasks cannot assign workers");
|
|
13537
13788
|
if (!bindingCovers(task.data.intent.data.scope, input.assignment.scope))
|
|
13538
|
-
return
|
|
13789
|
+
return failure2("permission_denied", "worker assignment is outside task scope", {
|
|
13539
13790
|
fields: [
|
|
13540
13791
|
{
|
|
13541
13792
|
path: "assignment.scope",
|
|
@@ -13548,14 +13799,14 @@ class WorkitCore {
|
|
|
13548
13799
|
]
|
|
13549
13800
|
});
|
|
13550
13801
|
if (input.assignment.decisionIds.some((id) => !task.data.decisions.some((entry) => entry.id === id)))
|
|
13551
|
-
return
|
|
13802
|
+
return failure2("invalid_input", "worker assignment references an unknown decision");
|
|
13552
13803
|
if (input.assignment.requirementIds.some((id) => !task.data.policy?.requirements.some((requirement) => requirement.id === id)))
|
|
13553
|
-
return
|
|
13804
|
+
return failure2("invalid_input", "worker assignment references an unknown requirement");
|
|
13554
13805
|
const reviewRequirements = (task.data.policy?.requirements ?? []).filter((requirement) => requirement.dimension === "review");
|
|
13555
13806
|
if (input.assignment.role === "reviewer" && input.assignment.requirementIds.length === 0 && reviewRequirements.length)
|
|
13556
|
-
return
|
|
13807
|
+
return failure2("invalid_input", "reviewer assignment needs the review requirement ids it will evidence", { requirementIds: reviewRequirements.map((requirement) => requirement.id) });
|
|
13557
13808
|
if (input.assignment.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.assignment.candidateId))
|
|
13558
|
-
return
|
|
13809
|
+
return failure2("invalid_input", "worker assignment references an unknown candidate");
|
|
13559
13810
|
input.assignment.candidateId ??= null;
|
|
13560
13811
|
const workerId = newId();
|
|
13561
13812
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
@@ -13583,19 +13834,19 @@ class WorkitCore {
|
|
|
13583
13834
|
}
|
|
13584
13835
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13585
13836
|
if (!entry)
|
|
13586
|
-
return
|
|
13837
|
+
return failure2("not_found", "worker not found");
|
|
13587
13838
|
if (input.action === "report") {
|
|
13588
13839
|
if (helperId === null || helperId !== input.workerId)
|
|
13589
|
-
return
|
|
13840
|
+
return failure2("permission_denied", "workers can submit only their own report");
|
|
13590
13841
|
const helper = this.helperEntry(task.data, true, true);
|
|
13591
13842
|
if (!helper.ok)
|
|
13592
13843
|
return helper;
|
|
13593
13844
|
const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
|
|
13594
13845
|
const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
|
|
13595
13846
|
if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
|
|
13596
|
-
return
|
|
13847
|
+
return failure2("invalid_input", "worker report references an unknown record");
|
|
13597
13848
|
if (evidence.some((candidate) => candidate.provenance.workerId !== helperId) || findings.some((candidate) => candidate.provenance.workerId !== helperId) || evidence.some((candidate) => !refsWithinScope(candidate.data.refs, helper.data.data.assignment.scope) || !refsWithinScope(candidate.data.refs, task.data.intent.data.scope)) || findings.some((candidate) => !refsWithinScope(candidate.data.refs, helper.data.data.assignment.scope) || !refsWithinScope(candidate.data.refs, task.data.intent.data.scope)))
|
|
13598
|
-
return
|
|
13849
|
+
return failure2("permission_denied", "worker report is outside the worker assignment");
|
|
13599
13850
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
13600
13851
|
taskId: task.data.id,
|
|
13601
13852
|
expectedRevision: input.expectedRevision,
|
|
@@ -13614,14 +13865,14 @@ class WorkitCore {
|
|
|
13614
13865
|
if (!changed.ok)
|
|
13615
13866
|
return changed;
|
|
13616
13867
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
13617
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
13868
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
|
|
13618
13869
|
}
|
|
13619
13870
|
if (helperId !== null)
|
|
13620
|
-
return
|
|
13871
|
+
return failure2("permission_denied", "helpers cannot cancel or control workers");
|
|
13621
13872
|
if (task.data.status === "closed")
|
|
13622
|
-
return
|
|
13873
|
+
return failure2("invalid_transition", "closed task cannot cancel workers");
|
|
13623
13874
|
if (entry.data.state === "unknown")
|
|
13624
|
-
return
|
|
13875
|
+
return failure2("recovery_required", "worker state requires recovery");
|
|
13625
13876
|
if (entry.data.state === "stopped") {
|
|
13626
13877
|
const stopped = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13627
13878
|
return success(task.data.revision, workspace.data.revision, stopped);
|
|
@@ -13653,7 +13904,7 @@ class WorkitCore {
|
|
|
13653
13904
|
if (!root.ok)
|
|
13654
13905
|
return root;
|
|
13655
13906
|
if (this.context.workerId !== undefined && this.context.workerId !== null && this.context.workerId !== input.workerId)
|
|
13656
|
-
return
|
|
13907
|
+
return failure2("permission_denied", "worker observation does not match the caller");
|
|
13657
13908
|
const task = this.store.readTask(input.taskId);
|
|
13658
13909
|
if (!task.ok)
|
|
13659
13910
|
return task;
|
|
@@ -13661,7 +13912,7 @@ class WorkitCore {
|
|
|
13661
13912
|
if (!workspace.ok)
|
|
13662
13913
|
return workspace;
|
|
13663
13914
|
if (!workspace.data)
|
|
13664
|
-
return
|
|
13915
|
+
return failure2("not_found", "workspace not found");
|
|
13665
13916
|
const authority = verifyNativeWorker(this.context.nativeWorker, {
|
|
13666
13917
|
observation: input.observation,
|
|
13667
13918
|
expected: { ...input, workspaceId: workspace.data.id },
|
|
@@ -13687,7 +13938,7 @@ class WorkitCore {
|
|
|
13687
13938
|
verifyDispatch(stage, input, workspaceId) {
|
|
13688
13939
|
const verifier = this.context.nativeWorker?.verifyDispatch;
|
|
13689
13940
|
if (!verifier)
|
|
13690
|
-
return
|
|
13941
|
+
return failure2("permission_denied", "native worker dispatch attestation is unavailable");
|
|
13691
13942
|
let result;
|
|
13692
13943
|
try {
|
|
13693
13944
|
result = verifier({
|
|
@@ -13703,10 +13954,10 @@ class WorkitCore {
|
|
|
13703
13954
|
caller: this.context.caller
|
|
13704
13955
|
});
|
|
13705
13956
|
} catch (error) {
|
|
13706
|
-
return
|
|
13957
|
+
return failure2("permission_denied", `native worker dispatch failed: ${String(error)}`);
|
|
13707
13958
|
}
|
|
13708
13959
|
if (!result.ok || !validDispatchProvenance(result.data, this.context.caller, input.workerId))
|
|
13709
|
-
return
|
|
13960
|
+
return failure2("permission_denied", "worker dispatch was not attested by the host");
|
|
13710
13961
|
return result;
|
|
13711
13962
|
}
|
|
13712
13963
|
prepareWorkerDispatch(input) {
|
|
@@ -13714,7 +13965,7 @@ class WorkitCore {
|
|
|
13714
13965
|
if (!root.ok)
|
|
13715
13966
|
return root;
|
|
13716
13967
|
if ((this.context.workerId ?? null) !== null)
|
|
13717
|
-
return
|
|
13968
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13718
13969
|
const task = this.store.readTask(input.taskId);
|
|
13719
13970
|
if (!task.ok)
|
|
13720
13971
|
return task;
|
|
@@ -13722,16 +13973,16 @@ class WorkitCore {
|
|
|
13722
13973
|
if (!workspace.ok)
|
|
13723
13974
|
return workspace;
|
|
13724
13975
|
if (!workspace.data)
|
|
13725
|
-
return
|
|
13976
|
+
return failure2("not_found", "workspace not found");
|
|
13726
13977
|
if (task.data.workspaceId !== workspace.data.id)
|
|
13727
|
-
return
|
|
13978
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13728
13979
|
if (task.data.status !== "active")
|
|
13729
|
-
return
|
|
13980
|
+
return failure2("invalid_transition", "paused or closed tasks cannot dispatch workers");
|
|
13730
13981
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13731
13982
|
if (!entry)
|
|
13732
|
-
return
|
|
13983
|
+
return failure2("not_found", "worker not found");
|
|
13733
13984
|
if (entry.data.state !== "assigned" || entry.data.session !== null)
|
|
13734
|
-
return
|
|
13985
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13735
13986
|
const attested = this.verifyDispatch("prepare", input, workspace.data.id);
|
|
13736
13987
|
if (!attested.ok)
|
|
13737
13988
|
return attested;
|
|
@@ -13744,9 +13995,9 @@ class WorkitCore {
|
|
|
13744
13995
|
task: (current, mutation) => {
|
|
13745
13996
|
const candidate = current.workers.find((item) => item.id === input.workerId);
|
|
13746
13997
|
if (!candidate)
|
|
13747
|
-
return
|
|
13998
|
+
return failure2("not_found", "worker not found");
|
|
13748
13999
|
if (candidate.data.state !== "assigned" || candidate.data.session !== null)
|
|
13749
|
-
return
|
|
14000
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13750
14001
|
return success(mutation.revision, null, {
|
|
13751
14002
|
...current,
|
|
13752
14003
|
workers: current.workers.map((item) => item.id === input.workerId ? {
|
|
@@ -13785,17 +14036,17 @@ class WorkitCore {
|
|
|
13785
14036
|
if (!root.ok)
|
|
13786
14037
|
return root;
|
|
13787
14038
|
if ((this.context.workerId ?? null) !== null)
|
|
13788
|
-
return
|
|
14039
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13789
14040
|
const reservation = dispatchReservations.get(input.dispatch);
|
|
13790
14041
|
if (!reservation || reservation.owner !== this.authorityOwner || reservation.store !== this.store || reservation.root !== this.store.root || !sameValue(reservation.caller, this.context.caller) || reservation.taskId !== input.taskId || reservation.workerId !== input.workerId)
|
|
13791
|
-
return
|
|
14042
|
+
return failure2("permission_denied", "worker dispatch reservation is not live");
|
|
13792
14043
|
const workspace = this.store.readWorkspace();
|
|
13793
14044
|
if (!workspace.ok)
|
|
13794
14045
|
return workspace;
|
|
13795
14046
|
if (!workspace.data)
|
|
13796
|
-
return
|
|
14047
|
+
return failure2("not_found", "workspace not found");
|
|
13797
14048
|
if (workspace.data.id !== reservation.workspaceId)
|
|
13798
|
-
return
|
|
14049
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13799
14050
|
const observation = {
|
|
13800
14051
|
taskId: input.taskId,
|
|
13801
14052
|
workerId: input.workerId,
|
|
@@ -13808,7 +14059,7 @@ class WorkitCore {
|
|
|
13808
14059
|
let authority;
|
|
13809
14060
|
if (input.outcome === "started") {
|
|
13810
14061
|
if (!input.session)
|
|
13811
|
-
return
|
|
14062
|
+
return failure2("invalid_input", "a started worker requires a session");
|
|
13812
14063
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
13813
14064
|
observation: input.observation,
|
|
13814
14065
|
expected: { ...observation, workspaceId: workspace.data.id },
|
|
@@ -13824,7 +14075,7 @@ class WorkitCore {
|
|
|
13824
14075
|
authority = verified.data;
|
|
13825
14076
|
} else {
|
|
13826
14077
|
if (input.session !== null)
|
|
13827
|
-
return
|
|
14078
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
13828
14079
|
const attested = this.verifyDispatch("not_started", input, workspace.data.id);
|
|
13829
14080
|
if (!attested.ok)
|
|
13830
14081
|
return attested;
|
|
@@ -13873,31 +14124,31 @@ class WorkitCore {
|
|
|
13873
14124
|
if (!workspace.ok)
|
|
13874
14125
|
return workspace;
|
|
13875
14126
|
if (!workspace.data)
|
|
13876
|
-
return
|
|
14127
|
+
return failure2("not_found", "workspace not found");
|
|
13877
14128
|
if (task.data.status !== "active")
|
|
13878
|
-
return
|
|
14129
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
13879
14130
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13880
14131
|
const helperId = this.context.workerId ?? null;
|
|
13881
14132
|
if (input.action === "acquire") {
|
|
13882
14133
|
if (input.workerId === undefined)
|
|
13883
14134
|
input.workerId = helperId;
|
|
13884
14135
|
if (input.workerId !== helperId)
|
|
13885
|
-
return
|
|
14136
|
+
return failure2("permission_denied", "writer identity does not match the caller");
|
|
13886
14137
|
if (workspace.data.writer) {
|
|
13887
14138
|
if (workspace.data.writer.state === "uncertain")
|
|
13888
|
-
return
|
|
14139
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
13889
14140
|
owner: workspace.data.writer.owner
|
|
13890
14141
|
});
|
|
13891
14142
|
const currentOwner = workspace.data.writer.owner;
|
|
13892
14143
|
if (currentOwner.workerId) {
|
|
13893
14144
|
const ownerWorker = task.data.workers.find((candidate) => candidate.id === currentOwner.workerId);
|
|
13894
14145
|
if (ownerWorker?.data.state === "cancelling" || ownerWorker?.data.state === "unknown")
|
|
13895
|
-
return
|
|
14146
|
+
return failure2("recovery_required", "current worker has not stopped", {
|
|
13896
14147
|
owner: currentOwner
|
|
13897
14148
|
});
|
|
13898
14149
|
}
|
|
13899
14150
|
if (currentOwner.workerId !== null || helperId !== null)
|
|
13900
|
-
return
|
|
14151
|
+
return failure2("writer_conflict", "checkout already has a writer", {
|
|
13901
14152
|
owner: currentOwner
|
|
13902
14153
|
});
|
|
13903
14154
|
}
|
|
@@ -13906,17 +14157,17 @@ class WorkitCore {
|
|
|
13906
14157
|
if (!helper.ok)
|
|
13907
14158
|
return helper;
|
|
13908
14159
|
if (helper.data.data.assignment.role !== "implementer")
|
|
13909
|
-
return
|
|
14160
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
13910
14161
|
if (helper.data.data.state !== "running" || !helper.data.data.session)
|
|
13911
|
-
return
|
|
14162
|
+
return failure2("permission_denied", "writer ownership requires an observed running worker");
|
|
13912
14163
|
if (!sameSession2(helper.data.data.session, this.context))
|
|
13913
|
-
return
|
|
14164
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
13914
14165
|
}
|
|
13915
14166
|
const gate = this.view(task.data);
|
|
13916
14167
|
if (gate.ok) {
|
|
13917
14168
|
const writeGates = (task.data.policy?.requirements ?? []).filter((requirement) => requirement.before === "write" && gate.data.requirements.some((evaluation) => evaluation.requirementId === requirement.id && (evaluation.status === "unsatisfied" || evaluation.status === "unavailable")));
|
|
13918
14169
|
if (writeGates.length)
|
|
13919
|
-
return
|
|
14170
|
+
return failure2("requirements_unsatisfied", "writer ownership is gated by unsatisfied requirements; record their evidence or an approved limitation waiver first", { requirementIds: writeGates.map((requirement) => requirement.id) });
|
|
13920
14171
|
}
|
|
13921
14172
|
const owner = {
|
|
13922
14173
|
taskId: task.data.id,
|
|
@@ -13944,19 +14195,19 @@ class WorkitCore {
|
|
|
13944
14195
|
}
|
|
13945
14196
|
const current = workspace.data.writer;
|
|
13946
14197
|
if (!current)
|
|
13947
|
-
return
|
|
14198
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
13948
14199
|
if (current.state === "uncertain")
|
|
13949
|
-
return
|
|
14200
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
13950
14201
|
owner: current.owner
|
|
13951
14202
|
});
|
|
13952
14203
|
if (current.owner.taskId !== task.data.id || current.owner.workerId !== helperId || !sameSession2(current.owner.session, this.context))
|
|
13953
|
-
return
|
|
14204
|
+
return failure2("permission_denied", "only the current writer can release ownership");
|
|
13954
14205
|
if (helperId !== null) {
|
|
13955
14206
|
const helper = this.helperEntry(task.data);
|
|
13956
14207
|
if (!helper.ok)
|
|
13957
14208
|
return helper;
|
|
13958
14209
|
if (helper.data.data.state !== "running")
|
|
13959
|
-
return
|
|
14210
|
+
return failure2("recovery_required", "worker must be observed stopped before release");
|
|
13960
14211
|
}
|
|
13961
14212
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
13962
14213
|
taskId: task.data.id,
|
|
@@ -13988,9 +14239,9 @@ class WorkitCore {
|
|
|
13988
14239
|
if (!root.ok)
|
|
13989
14240
|
return root;
|
|
13990
14241
|
if ((this.context.workerId ?? null) !== null)
|
|
13991
|
-
return
|
|
14242
|
+
return failure2("permission_denied", "helpers cannot reserve external actions");
|
|
13992
14243
|
if (input.observation === undefined)
|
|
13993
|
-
return
|
|
14244
|
+
return failure2("invalid_input", "native action observation is required");
|
|
13994
14245
|
const task = this.store.readTask(input.taskId);
|
|
13995
14246
|
if (!task.ok)
|
|
13996
14247
|
return task;
|
|
@@ -13998,10 +14249,10 @@ class WorkitCore {
|
|
|
13998
14249
|
if (!workspace.ok)
|
|
13999
14250
|
return workspace;
|
|
14000
14251
|
if (!workspace.data)
|
|
14001
|
-
return
|
|
14252
|
+
return failure2("not_found", "workspace not found");
|
|
14002
14253
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14003
14254
|
if (!decision)
|
|
14004
|
-
return
|
|
14255
|
+
return failure2("not_found", "decision not found");
|
|
14005
14256
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
14006
14257
|
observation: input.observation,
|
|
14007
14258
|
expected: {
|
|
@@ -14026,7 +14277,7 @@ class WorkitCore {
|
|
|
14026
14277
|
const evaluations = new Map(view.data.requirements.map((entry) => [entry.requirementId, entry.status]));
|
|
14027
14278
|
const blocked = (view.data.task.policy?.requirements ?? []).filter((requirement) => requirement.dependentAction === operation && (evaluations.get(requirement.id) === "unsatisfied" || evaluations.get(requirement.id) === "unavailable"));
|
|
14028
14279
|
if (blocked.length)
|
|
14029
|
-
return
|
|
14280
|
+
return failure2("requirements_unsatisfied", `${operation} is gated by unsatisfied requirements; record their evidence or an approved limitation waiver first`, { operation, requirementIds: blocked.map((requirement) => requirement.id) });
|
|
14030
14281
|
}
|
|
14031
14282
|
return reserveAction({
|
|
14032
14283
|
...input,
|
|
@@ -14042,9 +14293,9 @@ class WorkitCore {
|
|
|
14042
14293
|
if (!root.ok)
|
|
14043
14294
|
return root;
|
|
14044
14295
|
if ((this.context.workerId ?? null) !== null)
|
|
14045
|
-
return
|
|
14296
|
+
return failure2("permission_denied", "helpers cannot settle external actions");
|
|
14046
14297
|
if (input.observation === undefined)
|
|
14047
|
-
return
|
|
14298
|
+
return failure2("invalid_input", "native action observation is required");
|
|
14048
14299
|
const task = this.store.readTask(input.taskId);
|
|
14049
14300
|
if (!task.ok)
|
|
14050
14301
|
return task;
|
|
@@ -14052,10 +14303,10 @@ class WorkitCore {
|
|
|
14052
14303
|
if (!workspace.ok)
|
|
14053
14304
|
return workspace;
|
|
14054
14305
|
if (!workspace.data)
|
|
14055
|
-
return
|
|
14306
|
+
return failure2("not_found", "workspace not found");
|
|
14056
14307
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14057
14308
|
if (!decision)
|
|
14058
|
-
return
|
|
14309
|
+
return failure2("not_found", "decision not found");
|
|
14059
14310
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
14060
14311
|
observation: input.observation,
|
|
14061
14312
|
expected: {
|
|
@@ -14086,7 +14337,7 @@ class WorkitCore {
|
|
|
14086
14337
|
if (!root.ok)
|
|
14087
14338
|
return root;
|
|
14088
14339
|
if ((this.context.workerId ?? null) !== null)
|
|
14089
|
-
return
|
|
14340
|
+
return failure2("permission_denied", "helpers cannot reconcile external actions");
|
|
14090
14341
|
const task = this.store.readTask(input.taskId);
|
|
14091
14342
|
if (!task.ok)
|
|
14092
14343
|
return task;
|
|
@@ -14094,10 +14345,10 @@ class WorkitCore {
|
|
|
14094
14345
|
if (!workspace.ok)
|
|
14095
14346
|
return workspace;
|
|
14096
14347
|
if (!workspace.data)
|
|
14097
|
-
return
|
|
14348
|
+
return failure2("not_found", "workspace not found");
|
|
14098
14349
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14099
14350
|
if (!decision)
|
|
14100
|
-
return
|
|
14351
|
+
return failure2("not_found", "decision not found");
|
|
14101
14352
|
const authority = verifyNativeReconciliation(this.context.nativeAuthority, {
|
|
14102
14353
|
observation: input.observation,
|
|
14103
14354
|
expected: {
|
|
@@ -14144,7 +14395,7 @@ class WorkitCore {
|
|
|
14144
14395
|
if (!workspace.ok)
|
|
14145
14396
|
return workspace;
|
|
14146
14397
|
if (!workspace.data)
|
|
14147
|
-
return
|
|
14398
|
+
return failure2("not_found", "workspace not found");
|
|
14148
14399
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
14149
14400
|
const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
|
|
14150
14401
|
if (!current.ok)
|
|
@@ -14187,7 +14438,7 @@ class WorkitCore {
|
|
|
14187
14438
|
if (!workspace.ok)
|
|
14188
14439
|
return workspace;
|
|
14189
14440
|
if (!workspace.data)
|
|
14190
|
-
return
|
|
14441
|
+
return failure2("not_found", "workspace not found");
|
|
14191
14442
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
14192
14443
|
const current = historical ? success(null, null, historical) : capture ? captureCandidate(this.store.root, task.intent.data.scope, environment()) : success(null, null, task.candidates.at(-1) ?? null);
|
|
14193
14444
|
if (!current.ok)
|
|
@@ -14207,14 +14458,14 @@ class WorkitCore {
|
|
|
14207
14458
|
if (!root.ok)
|
|
14208
14459
|
return root;
|
|
14209
14460
|
if ((this.context.workerId ?? null) !== null)
|
|
14210
|
-
return
|
|
14461
|
+
return failure2("permission_denied", "helpers cannot reconcile task workers");
|
|
14211
14462
|
if (view.task.workspaceId !== view.workspace.id)
|
|
14212
|
-
return
|
|
14463
|
+
return failure2("invalid_input", "task and workspace bindings are invalid");
|
|
14213
14464
|
try {
|
|
14214
14465
|
if (realpathSync6(view.workspace.root) !== this.store.root)
|
|
14215
|
-
return
|
|
14466
|
+
return failure2("invalid_input", "task view root does not match the task store");
|
|
14216
14467
|
} catch {
|
|
14217
|
-
return
|
|
14468
|
+
return failure2("invalid_input", "task view root cannot be resolved");
|
|
14218
14469
|
}
|
|
14219
14470
|
const updates = [];
|
|
14220
14471
|
const seen = new Set;
|
|
@@ -14226,7 +14477,7 @@ class WorkitCore {
|
|
|
14226
14477
|
};
|
|
14227
14478
|
for (const observation of observations) {
|
|
14228
14479
|
if (seen.has(observation.workerId))
|
|
14229
|
-
return
|
|
14480
|
+
return failure2("invalid_input", "worker observations must be unique");
|
|
14230
14481
|
seen.add(observation.workerId);
|
|
14231
14482
|
const freshTask = this.store.readTask(view.task.id);
|
|
14232
14483
|
const freshWorkspace = this.store.readWorkspace();
|
|
@@ -14235,11 +14486,11 @@ class WorkitCore {
|
|
|
14235
14486
|
if (!freshWorkspace.ok)
|
|
14236
14487
|
return freshWorkspace;
|
|
14237
14488
|
if (!freshWorkspace.data)
|
|
14238
|
-
return
|
|
14489
|
+
return failure2("not_found", "workspace not found");
|
|
14239
14490
|
if (observation.taskId !== view.task.id || observation.expectedRevision !== freshTask.data.revision || observation.expectedWorkspaceRevision !== freshWorkspace.data.revision)
|
|
14240
|
-
return
|
|
14491
|
+
return failure2("revision_conflict", "worker observation is stale");
|
|
14241
14492
|
if (!view.task.workers.some((entry) => entry.id === observation.workerId))
|
|
14242
|
-
return
|
|
14493
|
+
return failure2("permission_denied", "worker observation is not assigned");
|
|
14243
14494
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
14244
14495
|
observation: observation.observation,
|
|
14245
14496
|
expected: { ...observation, workspaceId: view.workspace.id },
|
|
@@ -14248,7 +14499,7 @@ class WorkitCore {
|
|
|
14248
14499
|
if (!verified.ok)
|
|
14249
14500
|
return verified;
|
|
14250
14501
|
if (!takeWorker(verified.data, binding, observation))
|
|
14251
|
-
return
|
|
14502
|
+
return failure2("permission_denied", "worker observation authority was not retained");
|
|
14252
14503
|
updates.push(observation);
|
|
14253
14504
|
}
|
|
14254
14505
|
const observedStates = new Map(updates.map((entry) => [entry.workerId, entry.state]));
|
|
@@ -14286,19 +14537,19 @@ class WorkitCore {
|
|
|
14286
14537
|
if (!helper.ok)
|
|
14287
14538
|
return helper;
|
|
14288
14539
|
if (status === "paused" && task.data.status !== "active" || status === "active" && task.data.status !== "paused")
|
|
14289
|
-
return
|
|
14540
|
+
return failure2("invalid_transition", `cannot transition ${task.data.status} to ${status}`);
|
|
14290
14541
|
const workspace = this.store.readWorkspace();
|
|
14291
14542
|
if (!workspace.ok)
|
|
14292
14543
|
return workspace;
|
|
14293
14544
|
if (!workspace.data)
|
|
14294
|
-
return
|
|
14545
|
+
return failure2("not_found", "workspace not found");
|
|
14295
14546
|
this.fillRevisions(input, task.data, workspace.data);
|
|
14296
14547
|
let resumeCandidate = null;
|
|
14297
14548
|
if (status === "active" && task.data.origin) {
|
|
14298
14549
|
if (!task.data.policy)
|
|
14299
|
-
return
|
|
14550
|
+
return failure2("needs_input", "imported task requires a current policy");
|
|
14300
14551
|
if (task.data.policy.policyVersion !== POLICY_VERSION)
|
|
14301
|
-
return
|
|
14552
|
+
return failure2("needs_input", "stored policy version is unsupported; reassessment is required");
|
|
14302
14553
|
const view = this.view(task.data);
|
|
14303
14554
|
if (!view.ok)
|
|
14304
14555
|
return view;
|
|
@@ -14307,20 +14558,20 @@ class WorkitCore {
|
|
|
14307
14558
|
return current;
|
|
14308
14559
|
const requirements = view.data.requirements;
|
|
14309
14560
|
if (requirements.some((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable"))
|
|
14310
|
-
return
|
|
14561
|
+
return failure2("requirements_unsatisfied", "imported task requires current requirements", {
|
|
14311
14562
|
requirementIds: requirements.filter((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable").map((requirement) => requirement.requirementId)
|
|
14312
14563
|
});
|
|
14313
14564
|
if (current.data.reassessmentRequired)
|
|
14314
|
-
return
|
|
14565
|
+
return failure2("needs_input", "imported task requires destination policy reassessment");
|
|
14315
14566
|
if (current.data.staleEvidenceIds.length)
|
|
14316
|
-
return
|
|
14567
|
+
return failure2("needs_input", "imported task requires fresh destination evidence");
|
|
14317
14568
|
if (current.data.blockers.some((blocker) => blocker.dependentAction === "resume" || blocker.reason === "worker state requires reconciliation"))
|
|
14318
|
-
return
|
|
14569
|
+
return failure2("recovery_required", "imported task requires resume reconciliation");
|
|
14319
14570
|
if (!validResumeApproval(task.data, workspace.data, input.authorityRefs ?? [], this.context))
|
|
14320
|
-
return
|
|
14571
|
+
return failure2("permission_denied", "imported resume requires native destination approval");
|
|
14321
14572
|
resumeCandidate = current.data.candidate;
|
|
14322
14573
|
}
|
|
14323
|
-
const blocker = status === "paused" ? workspace.data.writer ?
|
|
14574
|
+
const blocker = status === "paused" ? workspace.data.writer ? failure2("recovery_required", "writer ownership must be released first") : null : this.activeWorkerBlocker(task.data, workspace.data);
|
|
14324
14575
|
if (blocker)
|
|
14325
14576
|
return blocker;
|
|
14326
14577
|
let pauseCandidate = null;
|
|
@@ -14335,7 +14586,7 @@ class WorkitCore {
|
|
|
14335
14586
|
expectedRevision: input.expectedRevision,
|
|
14336
14587
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14337
14588
|
now: trustedNow(this.context),
|
|
14338
|
-
workspace: (
|
|
14589
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14339
14590
|
task: (current, context) => success(context.revision, null, {
|
|
14340
14591
|
...current,
|
|
14341
14592
|
status,
|
|
@@ -14356,7 +14607,7 @@ class WorkitCore {
|
|
|
14356
14607
|
if (!helper.ok)
|
|
14357
14608
|
return helper;
|
|
14358
14609
|
if (task.data.status === "closed")
|
|
14359
|
-
return
|
|
14610
|
+
return failure2("invalid_transition", "closed task cannot update progress");
|
|
14360
14611
|
this.fillRevisions(input, task.data);
|
|
14361
14612
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, context) => success(context.revision, null, { ...current, progress: input.progress }), trustedNow(this.context));
|
|
14362
14613
|
if (!changed.ok)
|
|
@@ -14371,12 +14622,12 @@ class WorkitCore {
|
|
|
14371
14622
|
if (!helper.ok)
|
|
14372
14623
|
return helper;
|
|
14373
14624
|
if (task.data.status === "closed")
|
|
14374
|
-
return
|
|
14625
|
+
return failure2("invalid_transition", "closed task cannot be revised");
|
|
14375
14626
|
const workspace = this.store.readWorkspace();
|
|
14376
14627
|
if (!workspace.ok)
|
|
14377
14628
|
return workspace;
|
|
14378
14629
|
if (!workspace.data)
|
|
14379
|
-
return
|
|
14630
|
+
return failure2("not_found", "workspace not found");
|
|
14380
14631
|
const revisionBlocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14381
14632
|
if (revisionBlocker)
|
|
14382
14633
|
return revisionBlocker;
|
|
@@ -14386,7 +14637,7 @@ class WorkitCore {
|
|
|
14386
14637
|
expectedRevision: input.expectedRevision,
|
|
14387
14638
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14388
14639
|
now: trustedNow(this.context),
|
|
14389
|
-
workspace: (
|
|
14640
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14390
14641
|
task: (current, context) => success(context.revision, null, {
|
|
14391
14642
|
...current,
|
|
14392
14643
|
intent: {
|
|
@@ -14411,12 +14662,12 @@ class WorkitCore {
|
|
|
14411
14662
|
if (!helper.ok)
|
|
14412
14663
|
return helper;
|
|
14413
14664
|
if (task.data.status !== "active" && task.data.status !== "paused")
|
|
14414
|
-
return
|
|
14665
|
+
return failure2("invalid_transition", "closed task cannot be reopened or closed again");
|
|
14415
14666
|
const workspace = this.store.readWorkspace();
|
|
14416
14667
|
if (!workspace.ok)
|
|
14417
14668
|
return workspace;
|
|
14418
14669
|
if (!workspace.data)
|
|
14419
|
-
return
|
|
14670
|
+
return failure2("not_found", "workspace not found");
|
|
14420
14671
|
const blocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14421
14672
|
if (blocker)
|
|
14422
14673
|
return blocker;
|
|
@@ -14724,7 +14975,7 @@ var unfinishedTaskOffer2 = (root, session, excludedTaskId) => {
|
|
|
14724
14975
|
const listed = new TaskStore(root).listTasks();
|
|
14725
14976
|
if (!listed.ok)
|
|
14726
14977
|
return null;
|
|
14727
|
-
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === "cursor" && task.intent.provenance.session.handle === session) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === "cursor" && worker.data.session.handle === session)).
|
|
14978
|
+
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === "cursor" && task.intent.provenance.session.handle === session) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === "cursor" && worker.data.session.handle === session)).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, 3);
|
|
14728
14979
|
if (tasks.length === 0)
|
|
14729
14980
|
return null;
|
|
14730
14981
|
const quote = (value) => JSON.stringify(value.replace(/[<>]/g, " ").slice(0, 120));
|
|
@@ -14747,9 +14998,9 @@ var workerVerifier = (input) => ({
|
|
|
14747
14998
|
const parentId = input.parent_conversation_id;
|
|
14748
14999
|
const observation = expected && input.subagent_id ? { subagent_id: subagentId, parent_conversation_id: parentId } : null;
|
|
14749
15000
|
if (!observation || !subagentId || !parentId || caller.host !== "cursor" || caller.actor !== parentId)
|
|
14750
|
-
return
|
|
15001
|
+
return failure2("permission_denied", "native subagent observation is unavailable");
|
|
14751
15002
|
if (expected.session?.kind !== "host" || expected.session.host !== "cursor" || expected.session.handle !== subagentId)
|
|
14752
|
-
return
|
|
15003
|
+
return failure2("permission_denied", "native subagent identity does not match");
|
|
14753
15004
|
return success(null, null, {
|
|
14754
15005
|
kind: "host_observed",
|
|
14755
15006
|
host: "cursor",
|