@brainervirus/workit-codex 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/.codex-plugin/plugin.json +1 -1
- package/dist/launch-mcp.js +1677 -4845
- 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 {
|
|
@@ -10684,8 +10935,8 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
|
|
|
10684
10935
|
const resolved = effectiveWorkspacePolicy(workspaceRoot, "branch");
|
|
10685
10936
|
const branchPolicy = resolved.branchPolicy;
|
|
10686
10937
|
const source = resolved.provenance.branchPolicy;
|
|
10687
|
-
const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).
|
|
10688
|
-
const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).
|
|
10938
|
+
const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).toSorted();
|
|
10939
|
+
const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).toSorted();
|
|
10689
10940
|
const fingerprint = createHash4("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
|
|
10690
10941
|
return {
|
|
10691
10942
|
branchPolicy,
|
|
@@ -10737,7 +10988,7 @@ var UNCERTAIN_WORKER_STATES = ["dispatching", "running", "cancelling", "unknown"
|
|
|
10737
10988
|
var isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state);
|
|
10738
10989
|
var workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
|
|
10739
10990
|
var callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor };
|
|
10740
|
-
var validPath = (value) => typeof value === "string" && value.length > 0 && !
|
|
10991
|
+
var validPath = (value) => typeof value === "string" && value.length > 0 && !Array.from(value).some((char) => {
|
|
10741
10992
|
const code = char.charCodeAt(0);
|
|
10742
10993
|
return code < 32 || code === 127;
|
|
10743
10994
|
}) && !value.split(/[\\/]/).includes("..");
|
|
@@ -10749,9 +11000,9 @@ var currentWriterOwnsTask = (task, workspace, caller) => {
|
|
|
10749
11000
|
};
|
|
10750
11001
|
function assertProductWriteAllowed(input) {
|
|
10751
11002
|
if (!Array.isArray(input.paths) || input.paths.some((path) => !validPath(path)))
|
|
10752
|
-
return
|
|
11003
|
+
return failure2("invalid_input", "invalid product write path");
|
|
10753
11004
|
if (!input.store)
|
|
10754
|
-
return
|
|
11005
|
+
return failure2("permission_denied", "write authorization requires core state");
|
|
10755
11006
|
const task = input.store.readTask(input.task.id);
|
|
10756
11007
|
if (!task.ok)
|
|
10757
11008
|
return task;
|
|
@@ -10759,29 +11010,29 @@ function assertProductWriteAllowed(input) {
|
|
|
10759
11010
|
if (!workspace.ok)
|
|
10760
11011
|
return workspace;
|
|
10761
11012
|
if (!workspace.data)
|
|
10762
|
-
return
|
|
11013
|
+
return failure2("not_found", "workspace not found");
|
|
10763
11014
|
const workspaceRecord = workspace.data;
|
|
10764
11015
|
if (task.data.status !== "active")
|
|
10765
|
-
return
|
|
11016
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
10766
11017
|
if (workspaceRecord.id !== task.data.workspaceId || workspaceRecord.root.length === 0)
|
|
10767
|
-
return
|
|
11018
|
+
return failure2("recovery_required", "task and workspace bindings are invalid");
|
|
10768
11019
|
const writer = workspaceRecord.writer;
|
|
10769
11020
|
if (!writer)
|
|
10770
|
-
return
|
|
11021
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
10771
11022
|
if (writer.state === "uncertain")
|
|
10772
|
-
return
|
|
11023
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
10773
11024
|
owner: writer.owner
|
|
10774
11025
|
});
|
|
10775
11026
|
const caller = callerValue(input.caller);
|
|
10776
11027
|
const workerId = workerIdOf(input.caller);
|
|
10777
11028
|
const owner = writer.owner;
|
|
10778
11029
|
if (owner.taskId !== task.data.id || owner.workerId !== workerId || owner.session.host !== caller.host || owner.session.handle !== caller.actor)
|
|
10779
|
-
return
|
|
11030
|
+
return failure2("writer_conflict", "checkout is owned by another validated actor", { owner });
|
|
10780
11031
|
const worker = workerId === null ? null : task.data.workers.find((entry) => entry.id === workerId);
|
|
10781
11032
|
if (workerId !== null && (!worker || worker.data.assignment.role !== "implementer"))
|
|
10782
|
-
return
|
|
11033
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
10783
11034
|
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))))
|
|
10784
|
-
return
|
|
11035
|
+
return failure2("recovery_required", "worker session is not an active writer");
|
|
10785
11036
|
return success(null, workspaceRecord.revision, owner);
|
|
10786
11037
|
}
|
|
10787
11038
|
|
|
@@ -10877,15 +11128,15 @@ var standingReceiptFor = (root, workspace, cls, dir) => {
|
|
|
10877
11128
|
};
|
|
10878
11129
|
var verifyStandingApproval = (root, task, caller, binding) => {
|
|
10879
11130
|
if (task.status !== "active")
|
|
10880
|
-
return
|
|
11131
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
10881
11132
|
const workspace = new TaskStore(root).readWorkspace();
|
|
10882
11133
|
if (!workspace.ok)
|
|
10883
11134
|
return workspace;
|
|
10884
11135
|
if (!workspace.data || !currentWriterOwnsTask(task, workspace.data, caller))
|
|
10885
|
-
return
|
|
11136
|
+
return failure2("permission_denied", "standing approval requires the current writer session");
|
|
10886
11137
|
const standing = binding.standing;
|
|
10887
11138
|
if (!standing || typeof standing.workspace !== "string" || typeof standing.class !== "string")
|
|
10888
|
-
return
|
|
11139
|
+
return failure2("invalid_input", "standing approval needs a workspace and class");
|
|
10889
11140
|
let operation;
|
|
10890
11141
|
try {
|
|
10891
11142
|
operation = typeof binding.approvedContent === "string" ? JSON.parse(binding.approvedContent).operation : null;
|
|
@@ -10894,22 +11145,22 @@ var verifyStandingApproval = (root, task, caller, binding) => {
|
|
|
10894
11145
|
}
|
|
10895
11146
|
const cls = operationAutoClass(operation);
|
|
10896
11147
|
if (!cls || cls !== standing.class)
|
|
10897
|
-
return
|
|
11148
|
+
return failure2("permission_denied", "standing approval does not cover this operation");
|
|
10898
11149
|
const target = targetOf(root, binding.approvedContent);
|
|
10899
11150
|
if (!target)
|
|
10900
|
-
return
|
|
11151
|
+
return failure2("permission_denied", "standing action target is invalid");
|
|
10901
11152
|
const resolved = resolveAutoApproval(target);
|
|
10902
11153
|
if (resolved.status !== "on" || resolved.workspace !== standing.workspace || !resolved.classes.includes(cls))
|
|
10903
|
-
return
|
|
11154
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
10904
11155
|
if (cls === "push") {
|
|
10905
|
-
const
|
|
10906
|
-
const provider =
|
|
11156
|
+
const targetWorkspace = resolveWorkspaceFrom(target, configDir());
|
|
11157
|
+
const provider = targetWorkspace?.vcs?.provider;
|
|
10907
11158
|
const account = resolved.account;
|
|
10908
11159
|
if (!provider || !account)
|
|
10909
|
-
return
|
|
11160
|
+
return failure2("permission_denied", "auto-push requires a workspace provider and area account");
|
|
10910
11161
|
const identity = verifyPushIdentity(target, provider, account);
|
|
10911
11162
|
if (!identity.ok)
|
|
10912
|
-
return
|
|
11163
|
+
return failure2("permission_denied", identity.error);
|
|
10913
11164
|
}
|
|
10914
11165
|
return success(null, null, {
|
|
10915
11166
|
kind: "host_observed",
|
|
@@ -10986,10 +11237,10 @@ var validProvenance = (value, caller) => {
|
|
|
10986
11237
|
};
|
|
10987
11238
|
var verifyNativeDecision = (verifier, input, binding) => {
|
|
10988
11239
|
if (!verifier)
|
|
10989
|
-
return
|
|
11240
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
10990
11241
|
const result = verifier.verifyDecision(input);
|
|
10991
11242
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
10992
|
-
return
|
|
11243
|
+
return failure2("permission_denied", "native decision observation was not attested");
|
|
10993
11244
|
return success(null, null, trustedAuthority("decision", result.data, {
|
|
10994
11245
|
taskId: input.expected.taskId,
|
|
10995
11246
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11003,10 +11254,10 @@ var verifyNativeDecision = (verifier, input, binding) => {
|
|
|
11003
11254
|
};
|
|
11004
11255
|
var verifyNativeAction = (verifier, input, binding) => {
|
|
11005
11256
|
if (!verifier)
|
|
11006
|
-
return
|
|
11257
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
11007
11258
|
const result = verifier.verifyAction(input);
|
|
11008
11259
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
11009
|
-
return
|
|
11260
|
+
return failure2("permission_denied", "native action observation was not attested");
|
|
11010
11261
|
return success(null, null, trustedAuthority("action", result.data, {
|
|
11011
11262
|
taskId: input.expected.taskId,
|
|
11012
11263
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11024,10 +11275,10 @@ var verifyNativeAction = (verifier, input, binding) => {
|
|
|
11024
11275
|
};
|
|
11025
11276
|
var verifyNativeReconciliation = (verifier, input, binding) => {
|
|
11026
11277
|
if (!verifier?.verifyReconciliation)
|
|
11027
|
-
return
|
|
11278
|
+
return failure2("permission_denied", "native reconciliation authority is unavailable");
|
|
11028
11279
|
const result = verifier.verifyReconciliation(input);
|
|
11029
11280
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
11030
|
-
return
|
|
11281
|
+
return failure2("permission_denied", "native reconciliation observation was not attested");
|
|
11031
11282
|
return success(null, null, trustedAuthority("reconciliation", result.data, {
|
|
11032
11283
|
taskId: input.expected.taskId,
|
|
11033
11284
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11073,16 +11324,16 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11073
11324
|
try {
|
|
11074
11325
|
root = fs6.realpathSync(checkoutRoot);
|
|
11075
11326
|
} catch {
|
|
11076
|
-
return
|
|
11327
|
+
return failure2("permission_denied", "checkout root is unavailable");
|
|
11077
11328
|
}
|
|
11078
11329
|
for (const reference of binding.contentRefs) {
|
|
11079
11330
|
if (reference.kind !== "file")
|
|
11080
11331
|
continue;
|
|
11081
11332
|
if (!reference.digest)
|
|
11082
|
-
return
|
|
11333
|
+
return failure2("invalid_input", "document references require a byte digest");
|
|
11083
11334
|
const target = path9.resolve(root, reference.path);
|
|
11084
11335
|
if (target !== root && !target.startsWith(`${root}${path9.sep}`))
|
|
11085
|
-
return
|
|
11336
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11086
11337
|
fields: [
|
|
11087
11338
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
11088
11339
|
]
|
|
@@ -11097,7 +11348,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11097
11348
|
const stat = fs6.lstatSync(current);
|
|
11098
11349
|
const real = fs6.realpathSync(current);
|
|
11099
11350
|
if (real !== root && !real.startsWith(`${root}${path9.sep}`))
|
|
11100
|
-
return
|
|
11351
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11101
11352
|
fields: [
|
|
11102
11353
|
{
|
|
11103
11354
|
path: "contentRefs.path",
|
|
@@ -11106,16 +11357,16 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
11106
11357
|
]
|
|
11107
11358
|
});
|
|
11108
11359
|
if (stat.isSymbolicLink())
|
|
11109
|
-
return
|
|
11360
|
+
return failure2("invalid_input", "document reference uses a symlink");
|
|
11110
11361
|
if (current === target && !stat.isFile())
|
|
11111
|
-
return
|
|
11362
|
+
return failure2("invalid_input", "document reference is not a regular file");
|
|
11112
11363
|
if (current !== target && !stat.isDirectory())
|
|
11113
|
-
return
|
|
11364
|
+
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
11114
11365
|
}
|
|
11115
11366
|
if (digestBytes2(fs6.readFileSync(target)) !== reference.digest)
|
|
11116
|
-
return
|
|
11367
|
+
return failure2("permission_denied", "approved document bytes have changed");
|
|
11117
11368
|
} catch {
|
|
11118
|
-
return
|
|
11369
|
+
return failure2("invalid_input", "approved document is unavailable");
|
|
11119
11370
|
}
|
|
11120
11371
|
}
|
|
11121
11372
|
return success(null, null, null);
|
|
@@ -11138,15 +11389,15 @@ var approvalAuthorityMatches = (store, task, approval, current) => {
|
|
|
11138
11389
|
};
|
|
11139
11390
|
var validateAction = (store, task, workspaceId, input, authority) => {
|
|
11140
11391
|
if (task.status !== "active")
|
|
11141
|
-
return
|
|
11392
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
11142
11393
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11143
|
-
return
|
|
11394
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11144
11395
|
const entry = task.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11145
11396
|
if (!entry)
|
|
11146
|
-
return
|
|
11397
|
+
return failure2("not_found", "decision not found");
|
|
11147
11398
|
const decision = entry.data;
|
|
11148
11399
|
if (decision.purpose !== "action")
|
|
11149
|
-
return
|
|
11400
|
+
return failure2("permission_denied", "decision is not an action approval");
|
|
11150
11401
|
if (!authorityMatches(authority, {
|
|
11151
11402
|
taskId: task.id,
|
|
11152
11403
|
workspaceId,
|
|
@@ -11156,13 +11407,13 @@ var validateAction = (store, task, workspaceId, input, authority) => {
|
|
|
11156
11407
|
workspaceRevision: input.expectedWorkspaceRevision,
|
|
11157
11408
|
outcome: "reserve"
|
|
11158
11409
|
}))
|
|
11159
|
-
return
|
|
11410
|
+
return failure2("permission_denied", "native reservation authority is not bound");
|
|
11160
11411
|
if (!authorityDecisionMatches(authority, decision))
|
|
11161
|
-
return
|
|
11412
|
+
return failure2("permission_denied", "native reservation authority does not match decision");
|
|
11162
11413
|
if (decision.response !== "approved")
|
|
11163
|
-
return
|
|
11414
|
+
return failure2("permission_denied", "decision was rejected");
|
|
11164
11415
|
if (!approvalAuthorityMatches(store, task, entry.provenance, authority.provenance))
|
|
11165
|
-
return
|
|
11416
|
+
return failure2("permission_denied", "action approval lacks native receipt assurance");
|
|
11166
11417
|
const receipts = entry.provenance.receipts;
|
|
11167
11418
|
const standing = receipts.filter((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "standing");
|
|
11168
11419
|
const questionBacked = receipts.some((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "host");
|
|
@@ -11175,48 +11426,48 @@ var validateAction = (store, task, workspaceId, input, authority) => {
|
|
|
11175
11426
|
}
|
|
11176
11427
|
const cls = operationAutoClass(operation);
|
|
11177
11428
|
if (!cls || !standing.some((receipt) => standingApprovalLive(store.root, receipt, cls, undefined, decision.binding.approvedContent)))
|
|
11178
|
-
return
|
|
11429
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
11179
11430
|
}
|
|
11180
11431
|
if (decision.revoked)
|
|
11181
|
-
return
|
|
11432
|
+
return failure2("permission_denied", "decision is revoked");
|
|
11182
11433
|
if (decision.digest !== decisionDigest(decision))
|
|
11183
|
-
return
|
|
11434
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11184
11435
|
if (decision.binding.taskId !== task.id || decision.binding.workspaceId !== workspaceId)
|
|
11185
|
-
return
|
|
11436
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
11186
11437
|
if (input.binding && canonicalJson(input.binding) !== canonicalJson(decision.binding))
|
|
11187
|
-
return
|
|
11438
|
+
return failure2("permission_denied", "action binding does not match the approved decision");
|
|
11188
11439
|
const content = verifyContentRefs(store, decision.binding);
|
|
11189
11440
|
if (!content.ok)
|
|
11190
11441
|
return content;
|
|
11191
11442
|
const requestedSteps = parseSteps(decision.binding.approvedContent);
|
|
11192
11443
|
if (requestedSteps === null)
|
|
11193
|
-
return
|
|
11444
|
+
return failure2("invalid_input", "bounded action steps must be a unique non-empty array");
|
|
11194
11445
|
if (input.steps && canonicalJson(input.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11195
|
-
return
|
|
11446
|
+
return failure2("permission_denied", "bounded action steps do not match approved content");
|
|
11196
11447
|
const stored = task.actionProgress?.find((item) => item.decisionId === input.decisionId);
|
|
11197
11448
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: requestedSteps.map(chainStepKey), completed: [] };
|
|
11198
11449
|
if (workflow.steps.length && requestedSteps.length && canonicalJson(workflow.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11199
|
-
return
|
|
11450
|
+
return failure2("permission_denied", "bounded action scope changed");
|
|
11200
11451
|
return success(null, null, { entry, workflow });
|
|
11201
11452
|
};
|
|
11202
11453
|
function reserveAction(input) {
|
|
11203
11454
|
if (!input.store || !input.expectedRevision || !input.expectedWorkspaceRevision)
|
|
11204
|
-
return
|
|
11455
|
+
return failure2("invalid_input", "action reservation preconditions are required");
|
|
11205
11456
|
const authority = takeAuthority(input.authority, {
|
|
11206
11457
|
owner: input.authorityOwner,
|
|
11207
11458
|
store: input.store,
|
|
11208
11459
|
root: input.store.root
|
|
11209
11460
|
}, input.authorityCaller);
|
|
11210
11461
|
if (!authority)
|
|
11211
|
-
return
|
|
11462
|
+
return failure2("permission_denied", "native reservation authority is not verified");
|
|
11212
11463
|
const changed = input.store.mutateTask(input.taskId, input.expectedRevision, (current, mutation) => {
|
|
11213
11464
|
const workspace = input.store.readWorkspace();
|
|
11214
11465
|
if (!workspace.ok)
|
|
11215
11466
|
return workspace;
|
|
11216
11467
|
if (!workspace.data)
|
|
11217
|
-
return
|
|
11468
|
+
return failure2("not_found", "workspace not found");
|
|
11218
11469
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
11219
|
-
return
|
|
11470
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
11220
11471
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
11221
11472
|
actualWorkspaceRevision: workspace.data.revision
|
|
11222
11473
|
});
|
|
@@ -11226,19 +11477,19 @@ function reserveAction(input) {
|
|
|
11226
11477
|
const { entry, workflow } = valid.data;
|
|
11227
11478
|
const existing = entry.data.consumption;
|
|
11228
11479
|
if (existing?.state === "uncertain")
|
|
11229
|
-
return
|
|
11480
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
11230
11481
|
operation: "reserve_action",
|
|
11231
11482
|
outcome: "unknown"
|
|
11232
11483
|
});
|
|
11233
11484
|
if (existing?.state === "consumed")
|
|
11234
|
-
return
|
|
11485
|
+
return failure2("permission_denied", "action approval is consumed");
|
|
11235
11486
|
if (existing?.state === "reserved" && workflow.completed.length === 0)
|
|
11236
|
-
return
|
|
11487
|
+
return failure2("permission_denied", "action approval is already reserved");
|
|
11237
11488
|
const requestedStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11238
11489
|
if (workflow.steps.length && (!requestedStep || requestedStep !== workflow.steps[workflow.completed.length]))
|
|
11239
|
-
return
|
|
11490
|
+
return failure2("permission_denied", "action step is outside the approved remaining workflow");
|
|
11240
11491
|
if (requestedStep && workflow.completed.includes(requestedStep))
|
|
11241
|
-
return
|
|
11492
|
+
return failure2("permission_denied", "action step was already completed");
|
|
11242
11493
|
const nextDecision = {
|
|
11243
11494
|
...entry.data,
|
|
11244
11495
|
consumption: { state: "reserved", at: mutation.now, actionRef: input.actionRef }
|
|
@@ -11261,10 +11512,10 @@ function reserveAction(input) {
|
|
|
11261
11512
|
return changed;
|
|
11262
11513
|
const workspace = input.store.readWorkspace();
|
|
11263
11514
|
if (!workspace.ok || !workspace.data)
|
|
11264
|
-
return
|
|
11515
|
+
return failure2("recovery_required", "workspace disappeared after reservation");
|
|
11265
11516
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11266
11517
|
if (!entry)
|
|
11267
|
-
return
|
|
11518
|
+
return failure2("recovery_required", "reserved decision disappeared");
|
|
11268
11519
|
const workflow = changed.data.actionProgress?.find((progress) => progress.decisionId === input.decisionId) ?? {
|
|
11269
11520
|
steps: [],
|
|
11270
11521
|
completedSteps: []
|
|
@@ -11281,16 +11532,16 @@ function reserveAction(input) {
|
|
|
11281
11532
|
}
|
|
11282
11533
|
function settleAction(input) {
|
|
11283
11534
|
if (!input.store || !input.taskRevision || !input.workspaceRevision)
|
|
11284
|
-
return
|
|
11535
|
+
return failure2("invalid_input", "action settlement preconditions are required");
|
|
11285
11536
|
const authority = takeAuthority(input.authority, {
|
|
11286
11537
|
owner: input.authorityOwner,
|
|
11287
11538
|
store: input.store,
|
|
11288
11539
|
root: input.store.root
|
|
11289
11540
|
}, input.authorityCaller);
|
|
11290
11541
|
if (!authority)
|
|
11291
|
-
return
|
|
11542
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11292
11543
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11293
|
-
return
|
|
11544
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11294
11545
|
if (!authorityMatches(authority, {
|
|
11295
11546
|
taskId: input.taskId,
|
|
11296
11547
|
workspaceId: authority.workspaceId,
|
|
@@ -11300,14 +11551,14 @@ function settleAction(input) {
|
|
|
11300
11551
|
workspaceRevision: input.workspaceRevision,
|
|
11301
11552
|
outcome: input.outcome
|
|
11302
11553
|
}))
|
|
11303
|
-
return
|
|
11554
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11304
11555
|
let outcomeResult = null;
|
|
11305
11556
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11306
11557
|
const workspace = input.store.readWorkspace();
|
|
11307
11558
|
if (!workspace.ok)
|
|
11308
11559
|
return workspace;
|
|
11309
11560
|
if (!workspace.data)
|
|
11310
|
-
return
|
|
11561
|
+
return failure2("not_found", "workspace not found");
|
|
11311
11562
|
if (!authorityMatches(authority, {
|
|
11312
11563
|
taskId: input.taskId,
|
|
11313
11564
|
workspaceId: workspace.data.id,
|
|
@@ -11317,39 +11568,39 @@ function settleAction(input) {
|
|
|
11317
11568
|
workspaceRevision: input.workspaceRevision,
|
|
11318
11569
|
outcome: input.outcome
|
|
11319
11570
|
}))
|
|
11320
|
-
return
|
|
11571
|
+
return failure2("permission_denied", "native settlement authority does not match context");
|
|
11321
11572
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11322
|
-
return
|
|
11573
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
11323
11574
|
expectedWorkspaceRevision: input.workspaceRevision,
|
|
11324
11575
|
actualWorkspaceRevision: workspace.data.revision
|
|
11325
11576
|
});
|
|
11326
11577
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11327
11578
|
if (!entry)
|
|
11328
|
-
return
|
|
11579
|
+
return failure2("not_found", "decision not found");
|
|
11329
11580
|
if (!authorityDecisionMatches(authority, entry.data))
|
|
11330
|
-
return
|
|
11581
|
+
return failure2("permission_denied", "native settlement authority does not match decision");
|
|
11331
11582
|
if (!approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11332
|
-
return
|
|
11583
|
+
return failure2("permission_denied", "native settlement caller does not match approval");
|
|
11333
11584
|
if (entry.data.purpose !== "action" || entry.data.digest !== decisionDigest(entry.data))
|
|
11334
|
-
return
|
|
11585
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11335
11586
|
if (entry.data.consumption?.state === "uncertain")
|
|
11336
|
-
return
|
|
11587
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
11337
11588
|
operation: "settle_action",
|
|
11338
11589
|
outcome: "unknown"
|
|
11339
11590
|
});
|
|
11340
11591
|
if (entry.data.consumption?.state !== "reserved")
|
|
11341
|
-
return
|
|
11592
|
+
return failure2("permission_denied", "action is not reserved");
|
|
11342
11593
|
if (canonicalJson(entry.data.consumption.actionRef) !== canonicalJson(input.actionRef))
|
|
11343
|
-
return
|
|
11594
|
+
return failure2("permission_denied", "settlement reference does not match reservation");
|
|
11344
11595
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11345
11596
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: [], completed: [] };
|
|
11346
11597
|
if (entry.data.binding.approvedContent && !stored && (parseSteps(entry.data.binding.approvedContent) ?? []).length)
|
|
11347
|
-
return
|
|
11598
|
+
return failure2("recovery_required", "bounded action progress is missing");
|
|
11348
11599
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11349
11600
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11350
|
-
return
|
|
11601
|
+
return failure2("permission_denied", "settlement step is outside the approved workflow");
|
|
11351
11602
|
if (input.outcome === "unknown") {
|
|
11352
|
-
outcomeResult =
|
|
11603
|
+
outcomeResult = failure2("external_outcome_unknown", "external action outcome is unknown", {
|
|
11353
11604
|
operation: "settle_action",
|
|
11354
11605
|
outcome: "unknown"
|
|
11355
11606
|
});
|
|
@@ -11401,45 +11652,45 @@ function settleAction(input) {
|
|
|
11401
11652
|
return changed;
|
|
11402
11653
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11403
11654
|
if (!entry)
|
|
11404
|
-
return
|
|
11655
|
+
return failure2("recovery_required", "settled decision disappeared");
|
|
11405
11656
|
if (outcomeResult)
|
|
11406
11657
|
return outcomeResult;
|
|
11407
11658
|
return success(changed.data.revision, input.workspaceRevision, entry);
|
|
11408
11659
|
}
|
|
11409
11660
|
function reconcileAction(input) {
|
|
11410
11661
|
if (!input.store || !input.taskRevision || !input.workspaceRevision || !input.evidenceDigest)
|
|
11411
|
-
return
|
|
11662
|
+
return failure2("invalid_input", "action reconciliation preconditions are required");
|
|
11412
11663
|
const authority = takeAuthority(input.authority, { owner: input.authorityOwner, store: input.store, root: input.store.root }, input.authorityCaller);
|
|
11413
11664
|
if (!authority || authority.kind !== "reconciliation")
|
|
11414
|
-
return
|
|
11665
|
+
return failure2("permission_denied", "native reconciliation authority is not verified");
|
|
11415
11666
|
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)
|
|
11416
|
-
return
|
|
11667
|
+
return failure2("permission_denied", "native reconciliation authority is not bound");
|
|
11417
11668
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11418
11669
|
const workspace = input.store.readWorkspace();
|
|
11419
11670
|
if (!workspace.ok)
|
|
11420
11671
|
return workspace;
|
|
11421
11672
|
if (!workspace.data)
|
|
11422
|
-
return
|
|
11673
|
+
return failure2("not_found", "workspace not found");
|
|
11423
11674
|
if (authority.workspaceId !== workspace.data.id)
|
|
11424
|
-
return
|
|
11675
|
+
return failure2("permission_denied", "native reconciliation workspace does not match");
|
|
11425
11676
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11426
|
-
return
|
|
11677
|
+
return failure2("revision_conflict", "workspace revision does not match");
|
|
11427
11678
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11428
11679
|
if (!entry || entry.data.purpose !== "action")
|
|
11429
|
-
return
|
|
11680
|
+
return failure2("not_found", "decision not found");
|
|
11430
11681
|
if (!authorityDecisionMatches(authority, entry.data) || !approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11431
|
-
return
|
|
11682
|
+
return failure2("permission_denied", "native reconciliation caller does not match approval");
|
|
11432
11683
|
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)
|
|
11433
|
-
return
|
|
11684
|
+
return failure2("permission_denied", "reconciliation decision binding is invalid");
|
|
11434
11685
|
if (entry.data.consumption?.state !== "uncertain")
|
|
11435
|
-
return
|
|
11686
|
+
return failure2("external_outcome_unknown", "only an uncertain action can be reconciled");
|
|
11436
11687
|
if (!sameRef(entry.data.consumption.actionRef, input.actionRef))
|
|
11437
|
-
return
|
|
11688
|
+
return failure2("permission_denied", "reconciliation reference does not match reservation");
|
|
11438
11689
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11439
11690
|
const workflow = stored ? { steps: [...stored.steps], completed: [...stored.completedSteps] } : { steps: [], completed: [] };
|
|
11440
11691
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11441
11692
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11442
|
-
return
|
|
11693
|
+
return failure2("permission_denied", "reconciliation step is outside the approved workflow");
|
|
11443
11694
|
if (input.outcome === "not_started") {
|
|
11444
11695
|
return success(mutation.revision, null, {
|
|
11445
11696
|
...current,
|
|
@@ -11470,7 +11721,7 @@ function reconcileAction(input) {
|
|
|
11470
11721
|
if (!changed.ok)
|
|
11471
11722
|
return changed;
|
|
11472
11723
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11473
|
-
return entry ? success(changed.data.revision, input.workspaceRevision, entry) :
|
|
11724
|
+
return entry ? success(changed.data.revision, input.workspaceRevision, entry) : failure2("recovery_required", "reconciled decision disappeared");
|
|
11474
11725
|
}
|
|
11475
11726
|
var bindingCovers = scopeCovers;
|
|
11476
11727
|
var verifyDecisionContent = verifyContentRefs;
|
|
@@ -11496,8 +11747,8 @@ var compareCodeUnits2 = (left, right) => {
|
|
|
11496
11747
|
}
|
|
11497
11748
|
return left.length - right.length;
|
|
11498
11749
|
};
|
|
11499
|
-
var stableUnique = (values) => [...new Set(values)].
|
|
11500
|
-
var stableList = (values) => [...values].
|
|
11750
|
+
var stableUnique = (values) => [...new Set(values)].toSorted(compareCodeUnits2);
|
|
11751
|
+
var stableList = (values) => [...values].toSorted((left, right) => compareCodeUnits2(canonicalJson(left), canonicalJson(right)));
|
|
11501
11752
|
var normalizedScope = (scope) => ({
|
|
11502
11753
|
description: scope.description,
|
|
11503
11754
|
paths: stableUnique(scope.paths),
|
|
@@ -11570,11 +11821,11 @@ var invalidFields = (error) => ({
|
|
|
11570
11821
|
function normalizeResolverInput(input) {
|
|
11571
11822
|
const parsed = resolverInputSchema.safeParse(input);
|
|
11572
11823
|
if (!parsed.success)
|
|
11573
|
-
return
|
|
11824
|
+
return failure2("invalid_input", "resolver input is invalid", invalidFields(parsed.error));
|
|
11574
11825
|
const value = parsed.data;
|
|
11575
11826
|
const signals = value.assessment.signals;
|
|
11576
11827
|
if (signals.behaviorChange.value === true && signals.mechanicalLowRisk.value === true)
|
|
11577
|
-
return
|
|
11828
|
+
return failure2("invalid_input", "behavioral change cannot be wholly mechanical", {
|
|
11578
11829
|
fields: [
|
|
11579
11830
|
{
|
|
11580
11831
|
path: "assessment.signals",
|
|
@@ -11584,11 +11835,11 @@ function normalizeResolverInput(input) {
|
|
|
11584
11835
|
});
|
|
11585
11836
|
const ids = value.constraints.map((constraint) => constraint.id);
|
|
11586
11837
|
if (new Set(ids).size !== ids.length)
|
|
11587
|
-
return
|
|
11838
|
+
return failure2("invalid_input", "constraint IDs must be unique", {
|
|
11588
11839
|
fields: [{ path: "constraints", reason: "duplicate constraint id" }]
|
|
11589
11840
|
});
|
|
11590
11841
|
if (value.preferences?.fast && value.preferences.thorough)
|
|
11591
|
-
return
|
|
11842
|
+
return failure2("invalid_input", "fast and thorough preferences contradict", {
|
|
11592
11843
|
fields: [{ path: "preferences", reason: "fast and thorough cannot both be enabled" }]
|
|
11593
11844
|
});
|
|
11594
11845
|
const normalized = {
|
|
@@ -11772,7 +12023,7 @@ function resolvePolicy(input) {
|
|
|
11772
12023
|
};
|
|
11773
12024
|
const parsed = policySchema.safeParse(policy);
|
|
11774
12025
|
if (!parsed.success)
|
|
11775
|
-
return
|
|
12026
|
+
return failure2("invalid_input", "resolved policy is invalid", invalidFields(parsed.error));
|
|
11776
12027
|
return success(null, null, parsed.data);
|
|
11777
12028
|
}
|
|
11778
12029
|
function diffPolicy(previous, next, reason, now) {
|
|
@@ -11780,10 +12031,10 @@ function diffPolicy(previous, next, reason, now) {
|
|
|
11780
12031
|
throw new TypeError("previous policy is invalid");
|
|
11781
12032
|
if (!policySchema.safeParse(next).success)
|
|
11782
12033
|
throw new TypeError("next policy is invalid");
|
|
11783
|
-
const oldIds = new Set(previous?.requirements.map((
|
|
11784
|
-
const newIds = new Set(next.requirements.map((
|
|
11785
|
-
const added = [...newIds].filter((id) => !oldIds.has(id)).
|
|
11786
|
-
const retired = [...oldIds].filter((id) => !newIds.has(id)).
|
|
12034
|
+
const oldIds = new Set(previous?.requirements.map((item) => item.id) ?? []);
|
|
12035
|
+
const newIds = new Set(next.requirements.map((item) => item.id));
|
|
12036
|
+
const added = [...newIds].filter((id) => !oldIds.has(id)).toSorted(compareCodeUnits2);
|
|
12037
|
+
const retired = [...oldIds].filter((id) => !newIds.has(id)).toSorted(compareCodeUnits2);
|
|
11787
12038
|
if (added.length === 0 && retired.length === 0)
|
|
11788
12039
|
return null;
|
|
11789
12040
|
const normalizedReason = reason.trim();
|
|
@@ -11860,7 +12111,7 @@ var gitPaths = (root) => {
|
|
|
11860
12111
|
return {
|
|
11861
12112
|
paths: [],
|
|
11862
12113
|
uncertain: !/not a git repository/i.test(stderr),
|
|
11863
|
-
git:
|
|
12114
|
+
git: !/not a git repository/i.test(stderr)
|
|
11864
12115
|
};
|
|
11865
12116
|
}
|
|
11866
12117
|
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path10.sep).join("/")) : [];
|
|
@@ -11905,15 +12156,15 @@ var scopeRoots = (root, scope) => {
|
|
|
11905
12156
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
11906
12157
|
const target = path10.resolve(root, item);
|
|
11907
12158
|
if (!inside(root, target))
|
|
11908
|
-
return
|
|
12159
|
+
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` }] });
|
|
11909
12160
|
let ancestor = target;
|
|
11910
12161
|
while (!fs7.existsSync(ancestor) && ancestor !== root)
|
|
11911
12162
|
ancestor = path10.dirname(ancestor);
|
|
11912
12163
|
try {
|
|
11913
12164
|
if (!inside(root, fs7.realpathSync(ancestor)))
|
|
11914
|
-
return
|
|
12165
|
+
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` }] });
|
|
11915
12166
|
} catch {
|
|
11916
|
-
return
|
|
12167
|
+
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
11917
12168
|
}
|
|
11918
12169
|
roots.push(target);
|
|
11919
12170
|
}
|
|
@@ -11924,11 +12175,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11924
12175
|
try {
|
|
11925
12176
|
checkout = fs7.realpathSync(root);
|
|
11926
12177
|
} catch {
|
|
11927
|
-
return
|
|
12178
|
+
return failure2("invalid_input", "candidate root does not exist");
|
|
11928
12179
|
}
|
|
11929
12180
|
const normalizedScope = canonicalScope(scope);
|
|
11930
12181
|
if (!normalizedScope)
|
|
11931
|
-
return
|
|
12182
|
+
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" }] });
|
|
11932
12183
|
const roots = scopeRoots(checkout, normalizedScope);
|
|
11933
12184
|
if (!roots.ok)
|
|
11934
12185
|
return roots;
|
|
@@ -11957,7 +12208,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11957
12208
|
names.add(item);
|
|
11958
12209
|
const files = [];
|
|
11959
12210
|
let completeness = uncertain ? "uncertain" : "known";
|
|
11960
|
-
for (const item of [...names].
|
|
12211
|
+
for (const item of [...names].toSorted()) {
|
|
11961
12212
|
if (!scopeMatches(item, normalizedScope))
|
|
11962
12213
|
continue;
|
|
11963
12214
|
const target = path10.join(checkout, item);
|
|
@@ -11991,8 +12242,8 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11991
12242
|
}));
|
|
11992
12243
|
const namesByEnvironment = supplied.map(({ name }) => name);
|
|
11993
12244
|
if (new Set(namesByEnvironment).size !== namesByEnvironment.length || namesByEnvironment.some((name) => typeof name !== "string" || !name))
|
|
11994
|
-
return
|
|
11995
|
-
const values = supplied.
|
|
12245
|
+
return failure2("invalid_input", "candidate environment names must be unique and non-empty");
|
|
12246
|
+
const values = supplied.toSorted((left, right) => compareCodeUnits3(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
|
|
11996
12247
|
if (values.some(({ value }) => value === null))
|
|
11997
12248
|
completeness = "uncertain";
|
|
11998
12249
|
const headResult = spawnSync2("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
|
|
@@ -12009,7 +12260,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
12009
12260
|
};
|
|
12010
12261
|
const candidate = { ...partial, id: candidateDigest(partial) };
|
|
12011
12262
|
const parsed = candidateSchema.safeParse(candidate);
|
|
12012
|
-
return parsed.success ? success(null, null, parsed.data) :
|
|
12263
|
+
return parsed.success ? success(null, null, parsed.data) : failure2("invalid_input", "captured candidate is invalid");
|
|
12013
12264
|
}
|
|
12014
12265
|
var fileMap = (candidate) => new Map(candidate.files.map((file) => [file.path, file]));
|
|
12015
12266
|
var changedPaths = (before, after) => {
|
|
@@ -12220,13 +12471,13 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
12220
12471
|
}
|
|
12221
12472
|
function evaluateClosure(requestedOutcome, view) {
|
|
12222
12473
|
if (requestedOutcome !== "stopped" && !view.task.policy)
|
|
12223
|
-
return
|
|
12474
|
+
return failure2("requirements_unsatisfied", "task has not been assessed");
|
|
12224
12475
|
if (view.task.policy && view.task.policy.policyVersion !== POLICY_VERSION)
|
|
12225
|
-
return
|
|
12476
|
+
return failure2("requirements_unsatisfied", "stored policy version is unsupported; reassessment is required");
|
|
12226
12477
|
const evaluations = view.requirements;
|
|
12227
12478
|
const openFindings = view.task.findings.filter((entry) => entry.data.disposition === "open");
|
|
12228
12479
|
if (requestedOutcome !== "stopped" && openFindings.length)
|
|
12229
|
-
return
|
|
12480
|
+
return failure2("requirements_unsatisfied", "open findings must be resolved before closure");
|
|
12230
12481
|
if (requestedOutcome !== "stopped") {
|
|
12231
12482
|
const evidenceById = new Map(view.evidence.map((entry) => [entry.evidenceId, entry.status]));
|
|
12232
12483
|
for (const entry of view.task.findings) {
|
|
@@ -12242,7 +12493,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12242
12493
|
});
|
|
12243
12494
|
});
|
|
12244
12495
|
if (!verified)
|
|
12245
|
-
return
|
|
12496
|
+
return failure2("requirements_unsatisfied", "fixed findings require current verification");
|
|
12246
12497
|
}
|
|
12247
12498
|
if (entry.data.disposition === "deferred") {
|
|
12248
12499
|
const valid = entry.data.resolution?.decisionIds.some((id) => {
|
|
@@ -12251,7 +12502,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12251
12502
|
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)));
|
|
12252
12503
|
});
|
|
12253
12504
|
if (!valid)
|
|
12254
|
-
return
|
|
12505
|
+
return failure2("requirements_unsatisfied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
12255
12506
|
}
|
|
12256
12507
|
}
|
|
12257
12508
|
}
|
|
@@ -12262,7 +12513,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12262
12513
|
return !requirement || requirement.before === "close";
|
|
12263
12514
|
});
|
|
12264
12515
|
if (requestedOutcome !== "stopped" && blocking.length)
|
|
12265
|
-
return
|
|
12516
|
+
return failure2("requirements_unsatisfied", "applicable requirements are unsatisfied", {
|
|
12266
12517
|
requirementIds: blocking.map((item) => item.requirementId),
|
|
12267
12518
|
requirements: blocking.map((item) => {
|
|
12268
12519
|
const requirement = view.task.policy?.requirements.find((candidate) => candidate.id === item.requirementId);
|
|
@@ -12277,7 +12528,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12277
12528
|
});
|
|
12278
12529
|
const accepted = evaluations.filter((item) => item.status === "accepted_limitation");
|
|
12279
12530
|
if (requestedOutcome === "verified" && accepted.length)
|
|
12280
|
-
return
|
|
12531
|
+
return failure2("requirements_unsatisfied", "accepted limitations cannot be reported as verified", {
|
|
12281
12532
|
requirementIds: accepted.map((item) => item.requirementId)
|
|
12282
12533
|
});
|
|
12283
12534
|
const evidenceIds = [
|
|
@@ -12428,7 +12679,7 @@ Load the skill; never act from memory of it.
|
|
|
12428
12679
|
// packages/workit-core/src/core/task-context.ts
|
|
12429
12680
|
function reconcileResume(view, observations = []) {
|
|
12430
12681
|
if (observations.length > 0)
|
|
12431
|
-
return
|
|
12682
|
+
return failure2("permission_denied", "worker observations require native host verification");
|
|
12432
12683
|
const candidate = captureCandidate(view.workspace.root, view.task.intent.data.scope, []);
|
|
12433
12684
|
if (!candidate.ok)
|
|
12434
12685
|
return candidate;
|
|
@@ -12484,7 +12735,7 @@ var compactReference = (ref) => {
|
|
|
12484
12735
|
return { kind: ref.kind };
|
|
12485
12736
|
};
|
|
12486
12737
|
function compactTaskContext(view) {
|
|
12487
|
-
const decisions = view.task.decisions.slice().
|
|
12738
|
+
const decisions = view.task.decisions.slice().toSorted((left, right) => {
|
|
12488
12739
|
const leftAt = compactTimestamp(left.recordedAt);
|
|
12489
12740
|
const rightAt = compactTimestamp(right.recordedAt);
|
|
12490
12741
|
if (leftAt !== rightAt)
|
|
@@ -12507,7 +12758,7 @@ function compactTaskContext(view) {
|
|
|
12507
12758
|
...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
|
|
12508
12759
|
...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
|
|
12509
12760
|
...view.task.progress.blockers.map((entry) => entry.reason)
|
|
12510
|
-
])).
|
|
12761
|
+
])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
|
|
12511
12762
|
const context = {
|
|
12512
12763
|
objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
|
|
12513
12764
|
status: view.task.status,
|
|
@@ -12570,14 +12821,14 @@ var sameValue = (left, right) => {
|
|
|
12570
12821
|
var validNativeProvenance = (value, caller, expected) => {
|
|
12571
12822
|
if (!provenanceSchema.safeParse(value).success)
|
|
12572
12823
|
return false;
|
|
12573
|
-
const
|
|
12574
|
-
return
|
|
12824
|
+
const observed = value;
|
|
12825
|
+
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);
|
|
12575
12826
|
};
|
|
12576
12827
|
var validDispatchProvenance = (value, caller, workerId) => {
|
|
12577
12828
|
if (!provenanceSchema.safeParse(value).success)
|
|
12578
12829
|
return false;
|
|
12579
|
-
const
|
|
12580
|
-
return
|
|
12830
|
+
const observed = value;
|
|
12831
|
+
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);
|
|
12581
12832
|
};
|
|
12582
12833
|
var validResumeApproval = (task, workspace, authorityRefs, context) => authorityRefs.some((ref) => {
|
|
12583
12834
|
if (ref.kind !== "record" || ref.collection !== "decisions")
|
|
@@ -12594,16 +12845,16 @@ var validResumeApproval = (task, workspace, authorityRefs, context) => authority
|
|
|
12594
12845
|
});
|
|
12595
12846
|
var verifyNativeWorker = (verifier, input, binding) => {
|
|
12596
12847
|
if (!verifier)
|
|
12597
|
-
return
|
|
12848
|
+
return failure2("permission_denied", "native worker verifier is unavailable");
|
|
12598
12849
|
let result;
|
|
12599
12850
|
try {
|
|
12600
12851
|
result = verifier.verifyWorker(input);
|
|
12601
12852
|
} catch (error) {
|
|
12602
|
-
return
|
|
12853
|
+
return failure2("permission_denied", `native worker observation failed: ${String(error)}`);
|
|
12603
12854
|
}
|
|
12604
12855
|
const expected = input.expected;
|
|
12605
12856
|
if (!result.ok || !validNativeProvenance(result.data, input.caller, expected))
|
|
12606
|
-
return
|
|
12857
|
+
return failure2("permission_denied", "native worker observation was not attested");
|
|
12607
12858
|
const token = {};
|
|
12608
12859
|
verifiedWorkers.set(token, {
|
|
12609
12860
|
taskId: expected.taskId,
|
|
@@ -12630,7 +12881,7 @@ var takeWorker = (token, binding, expected) => {
|
|
|
12630
12881
|
};
|
|
12631
12882
|
var applyWorkerLifecycle = (input) => {
|
|
12632
12883
|
if (!input.store || !input.authority || !input.authorityOwner)
|
|
12633
|
-
return
|
|
12884
|
+
return failure2("invalid_input", "native worker observation preconditions are required");
|
|
12634
12885
|
const authority = takeWorker(input.authority, {
|
|
12635
12886
|
owner: input.authorityOwner,
|
|
12636
12887
|
store: input.store,
|
|
@@ -12638,7 +12889,7 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12638
12889
|
caller: input.caller
|
|
12639
12890
|
}, input);
|
|
12640
12891
|
if (!authority)
|
|
12641
|
-
return
|
|
12892
|
+
return failure2("permission_denied", "native worker observation is not verified");
|
|
12642
12893
|
const task = input.store.readTask(input.taskId);
|
|
12643
12894
|
if (!task.ok)
|
|
12644
12895
|
return task;
|
|
@@ -12646,35 +12897,35 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12646
12897
|
if (!workspace.ok)
|
|
12647
12898
|
return workspace;
|
|
12648
12899
|
if (!workspace.data)
|
|
12649
|
-
return
|
|
12900
|
+
return failure2("not_found", "workspace not found");
|
|
12650
12901
|
if (task.data.workspaceId !== authority.workspaceId || workspace.data.id !== authority.workspaceId)
|
|
12651
|
-
return
|
|
12902
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
12652
12903
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
12653
12904
|
if (!entry)
|
|
12654
|
-
return
|
|
12905
|
+
return failure2("not_found", "worker not found");
|
|
12655
12906
|
if (task.data.status === "closed")
|
|
12656
|
-
return
|
|
12907
|
+
return failure2("invalid_transition", "closed task cannot observe workers");
|
|
12657
12908
|
if (task.data.status === "paused" && (input.state === "running" || input.state === "cancelling"))
|
|
12658
|
-
return
|
|
12909
|
+
return failure2("invalid_transition", "paused task cannot run a worker");
|
|
12659
12910
|
const notStarted = input.dispatch === true;
|
|
12660
12911
|
if (notStarted && entry.data.state === "stopped" && input.session === null)
|
|
12661
12912
|
return success(task.data.revision, workspace.data.revision, entry);
|
|
12662
12913
|
if (notStarted && (input.state !== "stopped" || input.session !== null))
|
|
12663
|
-
return
|
|
12914
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
12664
12915
|
if (notStarted && entry.data.session !== null)
|
|
12665
|
-
return
|
|
12916
|
+
return failure2("invalid_transition", "worker already has an observed session");
|
|
12666
12917
|
if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
|
|
12667
|
-
return
|
|
12918
|
+
return failure2("invalid_transition", "worker launch was not claimed");
|
|
12668
12919
|
if (input.report && input.state !== "stopped")
|
|
12669
|
-
return
|
|
12920
|
+
return failure2("invalid_input", "worker reports require a stopped worker");
|
|
12670
12921
|
if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
|
|
12671
|
-
return
|
|
12922
|
+
return failure2("invalid_input", "running worker observations require a session");
|
|
12672
12923
|
if (entry.data.session && !sameValue(entry.data.session, input.session))
|
|
12673
|
-
return
|
|
12924
|
+
return failure2("permission_denied", "worker session does not match its assignment");
|
|
12674
12925
|
if (input.state !== "running" && entry.data.state === "assigned" && input.state !== "stopped")
|
|
12675
|
-
return
|
|
12926
|
+
return failure2("invalid_transition", "worker has not started");
|
|
12676
12927
|
if (input.state === "running" && entry.data.state === "stopped")
|
|
12677
|
-
return
|
|
12928
|
+
return failure2("invalid_transition", "stopped worker cannot run again");
|
|
12678
12929
|
const terminalCancel = entry.data.state === "cancelling" && input.state === "running";
|
|
12679
12930
|
const nextEntry = {
|
|
12680
12931
|
...entry,
|
|
@@ -12708,7 +12959,7 @@ var applyWorkerLifecycle = (input) => {
|
|
|
12708
12959
|
if (!changed.ok)
|
|
12709
12960
|
return changed;
|
|
12710
12961
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
12711
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
12962
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
|
|
12712
12963
|
};
|
|
12713
12964
|
var refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] }));
|
|
12714
12965
|
var trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now;
|
|
@@ -12792,13 +13043,13 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12792
13043
|
])
|
|
12793
13044
|
allocate(entry.id);
|
|
12794
13045
|
const fresh = (id) => allocate(id);
|
|
12795
|
-
const
|
|
13046
|
+
const imported = importedProvenance(context);
|
|
12796
13047
|
const remap = (ref) => mapRef(ref, ids);
|
|
12797
13048
|
const intent = {
|
|
12798
13049
|
...source.intent,
|
|
12799
13050
|
id: fresh(source.intent.id),
|
|
12800
13051
|
recordedAt: timestamp,
|
|
12801
|
-
provenance,
|
|
13052
|
+
provenance: imported,
|
|
12802
13053
|
data: rewriteRecordRefs(source.intent.data, intentSchema, remap)
|
|
12803
13054
|
};
|
|
12804
13055
|
const assessments = source.assessments.map((entry) => {
|
|
@@ -12807,7 +13058,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12807
13058
|
...entry,
|
|
12808
13059
|
id: fresh(entry.id),
|
|
12809
13060
|
recordedAt: timestamp,
|
|
12810
|
-
provenance,
|
|
13061
|
+
provenance: imported,
|
|
12811
13062
|
data: rewriteRecordRefs(data, assessmentSchema, remap)
|
|
12812
13063
|
};
|
|
12813
13064
|
});
|
|
@@ -12815,14 +13066,14 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12815
13066
|
...entry,
|
|
12816
13067
|
id: fresh(entry.id),
|
|
12817
13068
|
recordedAt: timestamp,
|
|
12818
|
-
provenance,
|
|
13069
|
+
provenance: imported,
|
|
12819
13070
|
data: rewriteRecordRefs(entry.data, evidenceSchema, remap)
|
|
12820
13071
|
}));
|
|
12821
13072
|
const decisions = source.decisions.map((entry) => ({
|
|
12822
13073
|
...entry,
|
|
12823
13074
|
id: fresh(entry.id),
|
|
12824
13075
|
recordedAt: timestamp,
|
|
12825
|
-
provenance
|
|
13076
|
+
provenance: imported
|
|
12826
13077
|
}));
|
|
12827
13078
|
const findings = source.findings.map((entry) => {
|
|
12828
13079
|
const data = rewriteRecordRefs(entry.data, findingSchema, remap);
|
|
@@ -12830,7 +13081,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12830
13081
|
...entry,
|
|
12831
13082
|
id: fresh(entry.id),
|
|
12832
13083
|
recordedAt: timestamp,
|
|
12833
|
-
provenance,
|
|
13084
|
+
provenance: imported,
|
|
12834
13085
|
data: {
|
|
12835
13086
|
...data,
|
|
12836
13087
|
resolution: data.resolution ? {
|
|
@@ -12845,7 +13096,7 @@ var importedTask = (source, bundle, destinationWorkspaceId, context, timestamp)
|
|
|
12845
13096
|
...entry,
|
|
12846
13097
|
id: fresh(entry.id),
|
|
12847
13098
|
recordedAt: timestamp,
|
|
12848
|
-
provenance,
|
|
13099
|
+
provenance: imported,
|
|
12849
13100
|
data: {
|
|
12850
13101
|
...entry.data,
|
|
12851
13102
|
state: "stopped",
|
|
@@ -12940,9 +13191,9 @@ class WorkitCore {
|
|
|
12940
13191
|
contextRootError() {
|
|
12941
13192
|
try {
|
|
12942
13193
|
if (realpathSync6(this.context.root) !== this.store.root)
|
|
12943
|
-
return
|
|
13194
|
+
return failure2("invalid_input", "operation context root does not match the task store root");
|
|
12944
13195
|
} catch {
|
|
12945
|
-
return
|
|
13196
|
+
return failure2("invalid_input", "operation context root cannot be resolved");
|
|
12946
13197
|
}
|
|
12947
13198
|
return success(null, null, null);
|
|
12948
13199
|
}
|
|
@@ -12961,16 +13212,16 @@ class WorkitCore {
|
|
|
12961
13212
|
helperEntry(task, requireSession = false, requireActive = false) {
|
|
12962
13213
|
const workerId = this.context.workerId ?? null;
|
|
12963
13214
|
if (workerId === null)
|
|
12964
|
-
return
|
|
13215
|
+
return failure2("permission_denied", "operation is lead-only");
|
|
12965
13216
|
const worker = task.workers.find((entry) => entry.id === workerId);
|
|
12966
13217
|
if (!worker)
|
|
12967
|
-
return
|
|
13218
|
+
return failure2("permission_denied", "worker is not assigned to this task");
|
|
12968
13219
|
if (worker.data.session && !sameSession2(worker.data.session, this.context))
|
|
12969
|
-
return
|
|
13220
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
12970
13221
|
if (requireSession && (!worker.data.session || !sameSession2(worker.data.session, this.context)))
|
|
12971
|
-
return
|
|
13222
|
+
return failure2("permission_denied", "worker session has not been observed");
|
|
12972
13223
|
if (requireActive && worker.data.state !== "running")
|
|
12973
|
-
return
|
|
13224
|
+
return failure2("permission_denied", "worker is not active");
|
|
12974
13225
|
return success(null, null, worker);
|
|
12975
13226
|
}
|
|
12976
13227
|
helperTaskGuard(task, allowRead = false) {
|
|
@@ -12979,13 +13230,13 @@ class WorkitCore {
|
|
|
12979
13230
|
const worker = this.helperEntry(task);
|
|
12980
13231
|
if (!worker.ok)
|
|
12981
13232
|
return worker;
|
|
12982
|
-
return allowRead ? success(null, null, null) :
|
|
13233
|
+
return allowRead ? success(null, null, null) : failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
12983
13234
|
}
|
|
12984
13235
|
activeWorkerBlocker(task, workspace) {
|
|
12985
13236
|
if (workspace.writer)
|
|
12986
|
-
return
|
|
13237
|
+
return failure2("recovery_required", "writer ownership must be released first");
|
|
12987
13238
|
if (task.workers.some((entry) => workerBlocksTransition("close", entry.data.state)))
|
|
12988
|
-
return
|
|
13239
|
+
return failure2("recovery_required", "worker state requires reconciliation");
|
|
12989
13240
|
return null;
|
|
12990
13241
|
}
|
|
12991
13242
|
state(request) {
|
|
@@ -12993,7 +13244,7 @@ class WorkitCore {
|
|
|
12993
13244
|
if (!root.ok)
|
|
12994
13245
|
return root;
|
|
12995
13246
|
if ((this.context.workerId ?? null) !== null)
|
|
12996
|
-
return
|
|
13247
|
+
return failure2("permission_denied", "helpers cannot control task state");
|
|
12997
13248
|
const parsed = parseOperation("state", request);
|
|
12998
13249
|
if (!parsed.ok)
|
|
12999
13250
|
return parsed;
|
|
@@ -13006,10 +13257,10 @@ class WorkitCore {
|
|
|
13006
13257
|
if (!workspace.ok)
|
|
13007
13258
|
return workspace;
|
|
13008
13259
|
if (!workspace.data)
|
|
13009
|
-
return
|
|
13260
|
+
return failure2("not_found", "workspace not found");
|
|
13010
13261
|
const portable = taskRecordSchema.safeParse(portableTask(task.data));
|
|
13011
13262
|
if (!portable.success)
|
|
13012
|
-
return
|
|
13263
|
+
return failure2("storage_error", "portable task is invalid after sanitization");
|
|
13013
13264
|
const bundle = {
|
|
13014
13265
|
schemaVersion: 1,
|
|
13015
13266
|
exportedAt: trustedNow(this.context),
|
|
@@ -13021,13 +13272,13 @@ class WorkitCore {
|
|
|
13021
13272
|
digest: exportDigest(bundle)
|
|
13022
13273
|
});
|
|
13023
13274
|
if (!checked.success)
|
|
13024
|
-
return
|
|
13275
|
+
return failure2("storage_error", "portable export bundle is invalid");
|
|
13025
13276
|
return success(task.data.revision, workspace.data.revision, checked.data);
|
|
13026
13277
|
}
|
|
13027
13278
|
if (input.action === "import") {
|
|
13028
13279
|
const checked = exportBundleSchema.safeParse(input.bundle);
|
|
13029
13280
|
if (!checked.success)
|
|
13030
|
-
return
|
|
13281
|
+
return failure2("invalid_input", "export bundle is invalid");
|
|
13031
13282
|
const bundle = checked.data;
|
|
13032
13283
|
if (bundle.sourceWorkspaceId !== bundle.task.workspaceId || exportDigest({
|
|
13033
13284
|
schemaVersion: bundle.schemaVersion,
|
|
@@ -13035,7 +13286,7 @@ class WorkitCore {
|
|
|
13035
13286
|
sourceWorkspaceId: bundle.sourceWorkspaceId,
|
|
13036
13287
|
task: bundle.task
|
|
13037
13288
|
}) !== bundle.digest)
|
|
13038
|
-
return
|
|
13289
|
+
return failure2("invalid_input", "export bundle digest is invalid");
|
|
13039
13290
|
const workspace = this.store.readWorkspace();
|
|
13040
13291
|
if (!workspace.ok)
|
|
13041
13292
|
return workspace;
|
|
@@ -13054,7 +13305,7 @@ class WorkitCore {
|
|
|
13054
13305
|
return this.summary(imported.data);
|
|
13055
13306
|
}
|
|
13056
13307
|
if (!this.context.nativeRecovery)
|
|
13057
|
-
return
|
|
13308
|
+
return failure2("permission_denied", "native recovery authority is unavailable");
|
|
13058
13309
|
const processEvidence = (lock, writer) => this.context.nativeRecovery({
|
|
13059
13310
|
lock,
|
|
13060
13311
|
writer,
|
|
@@ -13074,12 +13325,12 @@ class WorkitCore {
|
|
|
13074
13325
|
if (!workspace.ok)
|
|
13075
13326
|
return workspace;
|
|
13076
13327
|
if (!workspace.data)
|
|
13077
|
-
return
|
|
13328
|
+
return failure2("not_found", "workspace not found");
|
|
13078
13329
|
this.fillRevisions(input, undefined, workspace.data);
|
|
13079
13330
|
if (input.target === "workspace" && input.taskId !== undefined)
|
|
13080
|
-
return
|
|
13331
|
+
return failure2("invalid_input", "workspace recovery takes no task ID");
|
|
13081
13332
|
if (input.target === "task" && input.taskId === undefined)
|
|
13082
|
-
return
|
|
13333
|
+
return failure2("invalid_input", "task recovery requires a task ID");
|
|
13083
13334
|
return this.store.recoverTask(input.taskId, {
|
|
13084
13335
|
expectedBytes: input.expectedBytes,
|
|
13085
13336
|
snapshotDigest: input.snapshotDigest,
|
|
@@ -13099,7 +13350,7 @@ class WorkitCore {
|
|
|
13099
13350
|
const input = parsed.data;
|
|
13100
13351
|
if ((this.context.workerId ?? null) !== null) {
|
|
13101
13352
|
if (input.action !== "inspect" && input.action !== "list")
|
|
13102
|
-
return
|
|
13353
|
+
return failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
13103
13354
|
}
|
|
13104
13355
|
switch (input.action) {
|
|
13105
13356
|
case "start": {
|
|
@@ -13136,14 +13387,14 @@ class WorkitCore {
|
|
|
13136
13387
|
objective: task.intent.data.objective,
|
|
13137
13388
|
progress: task.progress,
|
|
13138
13389
|
decisions: task.decisions.map(({ data }) => data)
|
|
13139
|
-
}).toLowerCase().includes(term))).
|
|
13390
|
+
}).toLowerCase().includes(term))).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, limit);
|
|
13140
13391
|
if (selected.length === 0)
|
|
13141
13392
|
return success(null, null, []);
|
|
13142
13393
|
const workspace = this.store.readWorkspace();
|
|
13143
13394
|
if (!workspace.ok)
|
|
13144
13395
|
return workspace;
|
|
13145
13396
|
if (!workspace.data)
|
|
13146
|
-
return
|
|
13397
|
+
return failure2("not_found", "workspace not found");
|
|
13147
13398
|
const tasks = selected.map((task) => ({
|
|
13148
13399
|
id: task.id,
|
|
13149
13400
|
revision: task.revision,
|
|
@@ -13185,7 +13436,7 @@ class WorkitCore {
|
|
|
13185
13436
|
case "close":
|
|
13186
13437
|
return this.close(input);
|
|
13187
13438
|
default:
|
|
13188
|
-
return
|
|
13439
|
+
return failure2("invalid_transition", `task action ${input.action} is not implemented`);
|
|
13189
13440
|
}
|
|
13190
13441
|
}
|
|
13191
13442
|
policy(request) {
|
|
@@ -13202,7 +13453,7 @@ class WorkitCore {
|
|
|
13202
13453
|
if (input.action === "explain")
|
|
13203
13454
|
return success(task.data.revision, null, task.data.policy);
|
|
13204
13455
|
if ((this.context.workerId ?? null) !== null)
|
|
13205
|
-
return
|
|
13456
|
+
return failure2("permission_denied", "helpers cannot change task requirements");
|
|
13206
13457
|
this.fillRevisions(input, task.data);
|
|
13207
13458
|
const resolved = this.resolve(task.data, input.assessment);
|
|
13208
13459
|
if (!resolved.ok)
|
|
@@ -13210,10 +13461,10 @@ class WorkitCore {
|
|
|
13210
13461
|
if (input.action === "preview")
|
|
13211
13462
|
return success(null, null, resolved.data);
|
|
13212
13463
|
if (input.action !== "assess")
|
|
13213
|
-
return
|
|
13464
|
+
return failure2("invalid_transition", "unsupported policy action");
|
|
13214
13465
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13215
13466
|
if (current.status === "closed")
|
|
13216
|
-
return
|
|
13467
|
+
return failure2("invalid_transition", "closed task cannot be assessed");
|
|
13217
13468
|
const nextChange = diffPolicy(current.policy, resolved.data, "policy reassessed", mutation.now);
|
|
13218
13469
|
const assessment = {
|
|
13219
13470
|
id: newId(),
|
|
@@ -13246,17 +13497,17 @@ class WorkitCore {
|
|
|
13246
13497
|
if (!task.ok)
|
|
13247
13498
|
return task;
|
|
13248
13499
|
if (task.data.status === "closed")
|
|
13249
|
-
return
|
|
13500
|
+
return failure2("invalid_transition", "closed task cannot record evidence");
|
|
13250
13501
|
this.fillRevisions(input, task.data);
|
|
13251
13502
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
13252
13503
|
if (helper && !helper.ok)
|
|
13253
13504
|
return helper;
|
|
13254
13505
|
const evidence = input.evidence;
|
|
13255
13506
|
if ((evidence.result === "missing" || evidence.result === "skipped") && !evidence.summary.trim())
|
|
13256
|
-
return
|
|
13507
|
+
return failure2("invalid_input", "missing or skipped evidence requires a reason");
|
|
13257
13508
|
if (evidence.kind === "review") {
|
|
13258
13509
|
if (!sameSession2(evidence.reviewContext, this.context))
|
|
13259
|
-
return
|
|
13510
|
+
return failure2("invalid_input", "review context must match the trusted caller session");
|
|
13260
13511
|
}
|
|
13261
13512
|
const currentCandidate = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
13262
13513
|
if (!currentCandidate.ok)
|
|
@@ -13266,12 +13517,12 @@ class WorkitCore {
|
|
|
13266
13517
|
if (helper?.ok) {
|
|
13267
13518
|
const assignment = helper.data.data.assignment;
|
|
13268
13519
|
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))
|
|
13269
|
-
return
|
|
13520
|
+
return failure2("permission_denied", "evidence is outside the worker assignment");
|
|
13270
13521
|
}
|
|
13271
13522
|
const knownCandidates = new Set(task.data.candidates.map((candidate) => candidate.id));
|
|
13272
13523
|
for (const candidateId of [bound.beforeCandidateId, bound.candidateId]) {
|
|
13273
13524
|
if (candidateId && candidateId !== currentCandidate.data.id && !knownCandidates.has(candidateId))
|
|
13274
|
-
return
|
|
13525
|
+
return failure2("invalid_input", "evidence candidate is not a captured candidate");
|
|
13275
13526
|
}
|
|
13276
13527
|
const boundEvidence = { ...evidence, ...bound };
|
|
13277
13528
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
@@ -13328,38 +13579,38 @@ class WorkitCore {
|
|
|
13328
13579
|
return parsed;
|
|
13329
13580
|
const input = parsed.data;
|
|
13330
13581
|
if (nativeRequired && input.action !== "record")
|
|
13331
|
-
return
|
|
13582
|
+
return failure2("permission_denied", "native observation is only valid for recording decisions");
|
|
13332
13583
|
const stated = input.action === "record" && input.response === "stated";
|
|
13333
13584
|
if (stated && input.purpose === "action")
|
|
13334
|
-
return
|
|
13585
|
+
return failure2("permission_denied", "stated choices cannot authorize mutating actions");
|
|
13335
13586
|
if (stated && !input.binding?.statedChoice)
|
|
13336
|
-
return
|
|
13587
|
+
return failure2("invalid_input", "stated choices require binding.statedChoice");
|
|
13337
13588
|
if (nativeRequired && nativeObservation === undefined && !stated && !standing)
|
|
13338
|
-
return
|
|
13589
|
+
return failure2("permission_denied", "native decision observation is required");
|
|
13339
13590
|
if (standing && (!input.binding?.standing || input.purpose !== "action" || input.response !== "approved"))
|
|
13340
|
-
return
|
|
13591
|
+
return failure2("invalid_input", "standing approvals need an approved action binding with a standing rule");
|
|
13341
13592
|
const task = this.store.readTask(input.taskId);
|
|
13342
13593
|
if (!task.ok)
|
|
13343
13594
|
return task;
|
|
13344
13595
|
if ((this.context.workerId ?? null) !== null)
|
|
13345
|
-
return
|
|
13596
|
+
return failure2("permission_denied", "helpers cannot record or revoke decisions");
|
|
13346
13597
|
this.fillRevisions(input, task.data);
|
|
13347
13598
|
if (input.action === "record") {
|
|
13348
13599
|
if (task.data.status === "closed")
|
|
13349
|
-
return
|
|
13600
|
+
return failure2("invalid_transition", "closed task cannot record a decision");
|
|
13350
13601
|
const workspace = this.store.readWorkspace();
|
|
13351
13602
|
if (!workspace.ok)
|
|
13352
13603
|
return workspace;
|
|
13353
13604
|
if (!workspace.data)
|
|
13354
|
-
return
|
|
13605
|
+
return failure2("not_found", "workspace not found");
|
|
13355
13606
|
if (input.binding.taskId !== task.data.id || input.binding.workspaceId !== workspace.data.id)
|
|
13356
|
-
return
|
|
13607
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
13357
13608
|
const content = verifyDecisionContent(this.store, input.binding);
|
|
13358
13609
|
if (!content.ok)
|
|
13359
13610
|
return content;
|
|
13360
13611
|
const knownRequirements = new Set(task.data.policy?.requirements.map((item) => item.id) ?? []);
|
|
13361
13612
|
if (input.requirementIds.some((id) => !knownRequirements.has(id)))
|
|
13362
|
-
return
|
|
13613
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
13363
13614
|
const base = {
|
|
13364
13615
|
purpose: input.purpose,
|
|
13365
13616
|
binding: input.binding,
|
|
@@ -13390,16 +13641,16 @@ class WorkitCore {
|
|
|
13390
13641
|
return native;
|
|
13391
13642
|
const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
|
|
13392
13643
|
if (native?.ok && !nativeProvenance)
|
|
13393
|
-
return
|
|
13644
|
+
return failure2("permission_denied", "native decision authority was retired");
|
|
13394
13645
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13395
|
-
const
|
|
13396
|
-
if (!
|
|
13397
|
-
return
|
|
13646
|
+
const latestContent = verifyDecisionContent(this.store, input.binding);
|
|
13647
|
+
if (!latestContent.ok)
|
|
13648
|
+
return latestContent;
|
|
13398
13649
|
const known = new Set(current.policy?.requirements.map((item) => item.id) ?? []);
|
|
13399
13650
|
if (input.requirementIds.some((id) => !known.has(id)))
|
|
13400
|
-
return
|
|
13651
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
13401
13652
|
if (nativeProvenance && current.decisions.some((entry) => entry.provenance.receipts.some((existingReceipt) => nativeProvenance.receipts.some((receipt) => canonicalJson(receipt) === canonicalJson(existingReceipt)))))
|
|
13402
|
-
return
|
|
13653
|
+
return failure2("permission_denied", "native decision receipt was already consumed");
|
|
13403
13654
|
const entry = {
|
|
13404
13655
|
id: newId(),
|
|
13405
13656
|
recordedAt: mutation.now,
|
|
@@ -13417,21 +13668,21 @@ class WorkitCore {
|
|
|
13417
13668
|
}
|
|
13418
13669
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13419
13670
|
if (!decision)
|
|
13420
|
-
return
|
|
13671
|
+
return failure2("not_found", "decision not found");
|
|
13421
13672
|
if (!input.reason.trim())
|
|
13422
|
-
return
|
|
13673
|
+
return failure2("invalid_input", "decision revocation requires a reason");
|
|
13423
13674
|
if (decision.data.revoked)
|
|
13424
|
-
return
|
|
13675
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13425
13676
|
if (decision.data.consumption)
|
|
13426
|
-
return
|
|
13677
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13427
13678
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13428
13679
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13429
13680
|
if (!entry)
|
|
13430
|
-
return
|
|
13681
|
+
return failure2("not_found", "decision not found");
|
|
13431
13682
|
if (entry.data.revoked)
|
|
13432
|
-
return
|
|
13683
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13433
13684
|
if (entry.data.consumption)
|
|
13434
|
-
return
|
|
13685
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13435
13686
|
const data = {
|
|
13436
13687
|
...entry.data,
|
|
13437
13688
|
revoked: { at: mutation.now, reason: input.reason }
|
|
@@ -13445,7 +13696,7 @@ class WorkitCore {
|
|
|
13445
13696
|
if (!changed.ok)
|
|
13446
13697
|
return changed;
|
|
13447
13698
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13448
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13699
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
|
|
13449
13700
|
}
|
|
13450
13701
|
finding(request) {
|
|
13451
13702
|
const root = this.contextRootError();
|
|
@@ -13459,7 +13710,7 @@ class WorkitCore {
|
|
|
13459
13710
|
if (!task.ok)
|
|
13460
13711
|
return task;
|
|
13461
13712
|
if (task.data.status === "closed")
|
|
13462
|
-
return
|
|
13713
|
+
return failure2("invalid_transition", "closed task cannot mutate findings");
|
|
13463
13714
|
this.fillRevisions(input, task.data);
|
|
13464
13715
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
13465
13716
|
if (helper && !helper.ok)
|
|
@@ -13468,10 +13719,10 @@ class WorkitCore {
|
|
|
13468
13719
|
if (helper?.ok) {
|
|
13469
13720
|
const assignment = helper.data.data.assignment;
|
|
13470
13721
|
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))
|
|
13471
|
-
return
|
|
13722
|
+
return failure2("permission_denied", "finding is outside the worker assignment");
|
|
13472
13723
|
}
|
|
13473
13724
|
if (input.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.candidateId))
|
|
13474
|
-
return
|
|
13725
|
+
return failure2("invalid_input", "finding candidate is not a captured candidate");
|
|
13475
13726
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13476
13727
|
const entry = {
|
|
13477
13728
|
id: newId(),
|
|
@@ -13497,16 +13748,16 @@ class WorkitCore {
|
|
|
13497
13748
|
return success(changed.data.revision, null, changed.data.findings.at(-1));
|
|
13498
13749
|
}
|
|
13499
13750
|
if (helper?.ok)
|
|
13500
|
-
return
|
|
13751
|
+
return failure2("permission_denied", "helpers cannot resolve findings");
|
|
13501
13752
|
const finding = task.data.findings.find((entry) => entry.id === input.findingId);
|
|
13502
13753
|
if (!finding)
|
|
13503
|
-
return
|
|
13754
|
+
return failure2("not_found", "finding not found");
|
|
13504
13755
|
if (!input.reason.trim())
|
|
13505
|
-
return
|
|
13756
|
+
return failure2("invalid_input", "finding resolution requires a reason");
|
|
13506
13757
|
const evidence = task.data.evidence.filter((entry) => input.evidenceIds.includes(entry.id));
|
|
13507
13758
|
const decisions = task.data.decisions.filter((entry) => input.decisionIds.includes(entry.id));
|
|
13508
13759
|
if (evidence.length !== input.evidenceIds.length || decisions.length !== input.decisionIds.length)
|
|
13509
|
-
return
|
|
13760
|
+
return failure2("invalid_input", "finding resolution references an unknown record");
|
|
13510
13761
|
if (input.disposition === "fixed") {
|
|
13511
13762
|
const current = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
13512
13763
|
if (!current.ok)
|
|
@@ -13521,10 +13772,10 @@ class WorkitCore {
|
|
|
13521
13772
|
});
|
|
13522
13773
|
});
|
|
13523
13774
|
if (!verified)
|
|
13524
|
-
return
|
|
13775
|
+
return failure2("permission_denied", "fixed findings require passing verification evidence");
|
|
13525
13776
|
}
|
|
13526
13777
|
if (input.disposition === "dismissed" && evidence.length === 0)
|
|
13527
|
-
return
|
|
13778
|
+
return failure2("permission_denied", "dismissal requires supporting evidence");
|
|
13528
13779
|
if (input.disposition === "dismissed") {
|
|
13529
13780
|
const relevant = evidence.every((entry) => {
|
|
13530
13781
|
if (entry.data.result === "missing" || entry.data.result === "skipped")
|
|
@@ -13534,22 +13785,22 @@ class WorkitCore {
|
|
|
13534
13785
|
return candidateMatches && (referenceMatches || entry.data.claim === finding.data.claim);
|
|
13535
13786
|
});
|
|
13536
13787
|
if (!relevant)
|
|
13537
|
-
return
|
|
13788
|
+
return failure2("permission_denied", "dismissal evidence is unrelated to the finding");
|
|
13538
13789
|
}
|
|
13539
13790
|
if (input.disposition === "deferred") {
|
|
13540
13791
|
const workspace = this.store.readWorkspace();
|
|
13541
13792
|
if (!workspace.ok)
|
|
13542
13793
|
return workspace;
|
|
13543
13794
|
if (!workspace.data)
|
|
13544
|
-
return
|
|
13795
|
+
return failure2("not_found", "workspace not found");
|
|
13545
13796
|
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)));
|
|
13546
13797
|
if (!allowed)
|
|
13547
|
-
return
|
|
13798
|
+
return failure2("permission_denied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
13548
13799
|
}
|
|
13549
13800
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13550
13801
|
const existing = current.findings.find((entry) => entry.id === input.findingId);
|
|
13551
13802
|
if (!existing)
|
|
13552
|
-
return
|
|
13803
|
+
return failure2("not_found", "finding not found");
|
|
13553
13804
|
const data = input.disposition === "open" ? { ...existing.data, disposition: "open", resolution: null } : {
|
|
13554
13805
|
...existing.data,
|
|
13555
13806
|
disposition: input.disposition,
|
|
@@ -13568,7 +13819,7 @@ class WorkitCore {
|
|
|
13568
13819
|
if (!changed.ok)
|
|
13569
13820
|
return changed;
|
|
13570
13821
|
const entry = changed.data.findings.find((candidate) => candidate.id === input.findingId);
|
|
13571
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13822
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
|
|
13572
13823
|
}
|
|
13573
13824
|
worker(request) {
|
|
13574
13825
|
const root = this.contextRootError();
|
|
@@ -13585,16 +13836,16 @@ class WorkitCore {
|
|
|
13585
13836
|
if (!workspace.ok)
|
|
13586
13837
|
return workspace;
|
|
13587
13838
|
if (!workspace.data)
|
|
13588
|
-
return
|
|
13839
|
+
return failure2("not_found", "workspace not found");
|
|
13589
13840
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13590
13841
|
const helperId = this.context.workerId ?? null;
|
|
13591
13842
|
if (input.action === "assign") {
|
|
13592
13843
|
if (helperId !== null)
|
|
13593
|
-
return
|
|
13844
|
+
return failure2("permission_denied", "helpers cannot assign workers");
|
|
13594
13845
|
if (task.data.status !== "active")
|
|
13595
|
-
return
|
|
13846
|
+
return failure2("invalid_transition", "paused or closed tasks cannot assign workers");
|
|
13596
13847
|
if (!bindingCovers(task.data.intent.data.scope, input.assignment.scope))
|
|
13597
|
-
return
|
|
13848
|
+
return failure2("permission_denied", "worker assignment is outside task scope", {
|
|
13598
13849
|
fields: [
|
|
13599
13850
|
{
|
|
13600
13851
|
path: "assignment.scope",
|
|
@@ -13607,14 +13858,14 @@ class WorkitCore {
|
|
|
13607
13858
|
]
|
|
13608
13859
|
});
|
|
13609
13860
|
if (input.assignment.decisionIds.some((id) => !task.data.decisions.some((entry) => entry.id === id)))
|
|
13610
|
-
return
|
|
13861
|
+
return failure2("invalid_input", "worker assignment references an unknown decision");
|
|
13611
13862
|
if (input.assignment.requirementIds.some((id) => !task.data.policy?.requirements.some((requirement) => requirement.id === id)))
|
|
13612
|
-
return
|
|
13863
|
+
return failure2("invalid_input", "worker assignment references an unknown requirement");
|
|
13613
13864
|
const reviewRequirements = (task.data.policy?.requirements ?? []).filter((requirement) => requirement.dimension === "review");
|
|
13614
13865
|
if (input.assignment.role === "reviewer" && input.assignment.requirementIds.length === 0 && reviewRequirements.length)
|
|
13615
|
-
return
|
|
13866
|
+
return failure2("invalid_input", "reviewer assignment needs the review requirement ids it will evidence", { requirementIds: reviewRequirements.map((requirement) => requirement.id) });
|
|
13616
13867
|
if (input.assignment.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.assignment.candidateId))
|
|
13617
|
-
return
|
|
13868
|
+
return failure2("invalid_input", "worker assignment references an unknown candidate");
|
|
13618
13869
|
input.assignment.candidateId ??= null;
|
|
13619
13870
|
const workerId = newId();
|
|
13620
13871
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
@@ -13642,19 +13893,19 @@ class WorkitCore {
|
|
|
13642
13893
|
}
|
|
13643
13894
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13644
13895
|
if (!entry)
|
|
13645
|
-
return
|
|
13896
|
+
return failure2("not_found", "worker not found");
|
|
13646
13897
|
if (input.action === "report") {
|
|
13647
13898
|
if (helperId === null || helperId !== input.workerId)
|
|
13648
|
-
return
|
|
13899
|
+
return failure2("permission_denied", "workers can submit only their own report");
|
|
13649
13900
|
const helper = this.helperEntry(task.data, true, true);
|
|
13650
13901
|
if (!helper.ok)
|
|
13651
13902
|
return helper;
|
|
13652
13903
|
const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
|
|
13653
13904
|
const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
|
|
13654
13905
|
if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
|
|
13655
|
-
return
|
|
13906
|
+
return failure2("invalid_input", "worker report references an unknown record");
|
|
13656
13907
|
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)))
|
|
13657
|
-
return
|
|
13908
|
+
return failure2("permission_denied", "worker report is outside the worker assignment");
|
|
13658
13909
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
13659
13910
|
taskId: task.data.id,
|
|
13660
13911
|
expectedRevision: input.expectedRevision,
|
|
@@ -13673,14 +13924,14 @@ class WorkitCore {
|
|
|
13673
13924
|
if (!changed.ok)
|
|
13674
13925
|
return changed;
|
|
13675
13926
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
13676
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
13927
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
|
|
13677
13928
|
}
|
|
13678
13929
|
if (helperId !== null)
|
|
13679
|
-
return
|
|
13930
|
+
return failure2("permission_denied", "helpers cannot cancel or control workers");
|
|
13680
13931
|
if (task.data.status === "closed")
|
|
13681
|
-
return
|
|
13932
|
+
return failure2("invalid_transition", "closed task cannot cancel workers");
|
|
13682
13933
|
if (entry.data.state === "unknown")
|
|
13683
|
-
return
|
|
13934
|
+
return failure2("recovery_required", "worker state requires recovery");
|
|
13684
13935
|
if (entry.data.state === "stopped") {
|
|
13685
13936
|
const stopped = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13686
13937
|
return success(task.data.revision, workspace.data.revision, stopped);
|
|
@@ -13712,7 +13963,7 @@ class WorkitCore {
|
|
|
13712
13963
|
if (!root.ok)
|
|
13713
13964
|
return root;
|
|
13714
13965
|
if (this.context.workerId !== undefined && this.context.workerId !== null && this.context.workerId !== input.workerId)
|
|
13715
|
-
return
|
|
13966
|
+
return failure2("permission_denied", "worker observation does not match the caller");
|
|
13716
13967
|
const task = this.store.readTask(input.taskId);
|
|
13717
13968
|
if (!task.ok)
|
|
13718
13969
|
return task;
|
|
@@ -13720,7 +13971,7 @@ class WorkitCore {
|
|
|
13720
13971
|
if (!workspace.ok)
|
|
13721
13972
|
return workspace;
|
|
13722
13973
|
if (!workspace.data)
|
|
13723
|
-
return
|
|
13974
|
+
return failure2("not_found", "workspace not found");
|
|
13724
13975
|
const authority = verifyNativeWorker(this.context.nativeWorker, {
|
|
13725
13976
|
observation: input.observation,
|
|
13726
13977
|
expected: { ...input, workspaceId: workspace.data.id },
|
|
@@ -13746,7 +13997,7 @@ class WorkitCore {
|
|
|
13746
13997
|
verifyDispatch(stage, input, workspaceId) {
|
|
13747
13998
|
const verifier = this.context.nativeWorker?.verifyDispatch;
|
|
13748
13999
|
if (!verifier)
|
|
13749
|
-
return
|
|
14000
|
+
return failure2("permission_denied", "native worker dispatch attestation is unavailable");
|
|
13750
14001
|
let result;
|
|
13751
14002
|
try {
|
|
13752
14003
|
result = verifier({
|
|
@@ -13762,10 +14013,10 @@ class WorkitCore {
|
|
|
13762
14013
|
caller: this.context.caller
|
|
13763
14014
|
});
|
|
13764
14015
|
} catch (error) {
|
|
13765
|
-
return
|
|
14016
|
+
return failure2("permission_denied", `native worker dispatch failed: ${String(error)}`);
|
|
13766
14017
|
}
|
|
13767
14018
|
if (!result.ok || !validDispatchProvenance(result.data, this.context.caller, input.workerId))
|
|
13768
|
-
return
|
|
14019
|
+
return failure2("permission_denied", "worker dispatch was not attested by the host");
|
|
13769
14020
|
return result;
|
|
13770
14021
|
}
|
|
13771
14022
|
prepareWorkerDispatch(input) {
|
|
@@ -13773,7 +14024,7 @@ class WorkitCore {
|
|
|
13773
14024
|
if (!root.ok)
|
|
13774
14025
|
return root;
|
|
13775
14026
|
if ((this.context.workerId ?? null) !== null)
|
|
13776
|
-
return
|
|
14027
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13777
14028
|
const task = this.store.readTask(input.taskId);
|
|
13778
14029
|
if (!task.ok)
|
|
13779
14030
|
return task;
|
|
@@ -13781,16 +14032,16 @@ class WorkitCore {
|
|
|
13781
14032
|
if (!workspace.ok)
|
|
13782
14033
|
return workspace;
|
|
13783
14034
|
if (!workspace.data)
|
|
13784
|
-
return
|
|
14035
|
+
return failure2("not_found", "workspace not found");
|
|
13785
14036
|
if (task.data.workspaceId !== workspace.data.id)
|
|
13786
|
-
return
|
|
14037
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13787
14038
|
if (task.data.status !== "active")
|
|
13788
|
-
return
|
|
14039
|
+
return failure2("invalid_transition", "paused or closed tasks cannot dispatch workers");
|
|
13789
14040
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13790
14041
|
if (!entry)
|
|
13791
|
-
return
|
|
14042
|
+
return failure2("not_found", "worker not found");
|
|
13792
14043
|
if (entry.data.state !== "assigned" || entry.data.session !== null)
|
|
13793
|
-
return
|
|
14044
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13794
14045
|
const attested = this.verifyDispatch("prepare", input, workspace.data.id);
|
|
13795
14046
|
if (!attested.ok)
|
|
13796
14047
|
return attested;
|
|
@@ -13803,9 +14054,9 @@ class WorkitCore {
|
|
|
13803
14054
|
task: (current, mutation) => {
|
|
13804
14055
|
const candidate = current.workers.find((item) => item.id === input.workerId);
|
|
13805
14056
|
if (!candidate)
|
|
13806
|
-
return
|
|
14057
|
+
return failure2("not_found", "worker not found");
|
|
13807
14058
|
if (candidate.data.state !== "assigned" || candidate.data.session !== null)
|
|
13808
|
-
return
|
|
14059
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13809
14060
|
return success(mutation.revision, null, {
|
|
13810
14061
|
...current,
|
|
13811
14062
|
workers: current.workers.map((item) => item.id === input.workerId ? {
|
|
@@ -13844,17 +14095,17 @@ class WorkitCore {
|
|
|
13844
14095
|
if (!root.ok)
|
|
13845
14096
|
return root;
|
|
13846
14097
|
if ((this.context.workerId ?? null) !== null)
|
|
13847
|
-
return
|
|
14098
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13848
14099
|
const reservation = dispatchReservations.get(input.dispatch);
|
|
13849
14100
|
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)
|
|
13850
|
-
return
|
|
14101
|
+
return failure2("permission_denied", "worker dispatch reservation is not live");
|
|
13851
14102
|
const workspace = this.store.readWorkspace();
|
|
13852
14103
|
if (!workspace.ok)
|
|
13853
14104
|
return workspace;
|
|
13854
14105
|
if (!workspace.data)
|
|
13855
|
-
return
|
|
14106
|
+
return failure2("not_found", "workspace not found");
|
|
13856
14107
|
if (workspace.data.id !== reservation.workspaceId)
|
|
13857
|
-
return
|
|
14108
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13858
14109
|
const observation = {
|
|
13859
14110
|
taskId: input.taskId,
|
|
13860
14111
|
workerId: input.workerId,
|
|
@@ -13867,7 +14118,7 @@ class WorkitCore {
|
|
|
13867
14118
|
let authority;
|
|
13868
14119
|
if (input.outcome === "started") {
|
|
13869
14120
|
if (!input.session)
|
|
13870
|
-
return
|
|
14121
|
+
return failure2("invalid_input", "a started worker requires a session");
|
|
13871
14122
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
13872
14123
|
observation: input.observation,
|
|
13873
14124
|
expected: { ...observation, workspaceId: workspace.data.id },
|
|
@@ -13883,7 +14134,7 @@ class WorkitCore {
|
|
|
13883
14134
|
authority = verified.data;
|
|
13884
14135
|
} else {
|
|
13885
14136
|
if (input.session !== null)
|
|
13886
|
-
return
|
|
14137
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
13887
14138
|
const attested = this.verifyDispatch("not_started", input, workspace.data.id);
|
|
13888
14139
|
if (!attested.ok)
|
|
13889
14140
|
return attested;
|
|
@@ -13932,31 +14183,31 @@ class WorkitCore {
|
|
|
13932
14183
|
if (!workspace.ok)
|
|
13933
14184
|
return workspace;
|
|
13934
14185
|
if (!workspace.data)
|
|
13935
|
-
return
|
|
14186
|
+
return failure2("not_found", "workspace not found");
|
|
13936
14187
|
if (task.data.status !== "active")
|
|
13937
|
-
return
|
|
14188
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
13938
14189
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13939
14190
|
const helperId = this.context.workerId ?? null;
|
|
13940
14191
|
if (input.action === "acquire") {
|
|
13941
14192
|
if (input.workerId === undefined)
|
|
13942
14193
|
input.workerId = helperId;
|
|
13943
14194
|
if (input.workerId !== helperId)
|
|
13944
|
-
return
|
|
14195
|
+
return failure2("permission_denied", "writer identity does not match the caller");
|
|
13945
14196
|
if (workspace.data.writer) {
|
|
13946
14197
|
if (workspace.data.writer.state === "uncertain")
|
|
13947
|
-
return
|
|
14198
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
13948
14199
|
owner: workspace.data.writer.owner
|
|
13949
14200
|
});
|
|
13950
14201
|
const currentOwner = workspace.data.writer.owner;
|
|
13951
14202
|
if (currentOwner.workerId) {
|
|
13952
14203
|
const ownerWorker = task.data.workers.find((candidate) => candidate.id === currentOwner.workerId);
|
|
13953
14204
|
if (ownerWorker?.data.state === "cancelling" || ownerWorker?.data.state === "unknown")
|
|
13954
|
-
return
|
|
14205
|
+
return failure2("recovery_required", "current worker has not stopped", {
|
|
13955
14206
|
owner: currentOwner
|
|
13956
14207
|
});
|
|
13957
14208
|
}
|
|
13958
14209
|
if (currentOwner.workerId !== null || helperId !== null)
|
|
13959
|
-
return
|
|
14210
|
+
return failure2("writer_conflict", "checkout already has a writer", {
|
|
13960
14211
|
owner: currentOwner
|
|
13961
14212
|
});
|
|
13962
14213
|
}
|
|
@@ -13965,17 +14216,17 @@ class WorkitCore {
|
|
|
13965
14216
|
if (!helper.ok)
|
|
13966
14217
|
return helper;
|
|
13967
14218
|
if (helper.data.data.assignment.role !== "implementer")
|
|
13968
|
-
return
|
|
14219
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
13969
14220
|
if (helper.data.data.state !== "running" || !helper.data.data.session)
|
|
13970
|
-
return
|
|
14221
|
+
return failure2("permission_denied", "writer ownership requires an observed running worker");
|
|
13971
14222
|
if (!sameSession2(helper.data.data.session, this.context))
|
|
13972
|
-
return
|
|
14223
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
13973
14224
|
}
|
|
13974
14225
|
const gate = this.view(task.data);
|
|
13975
14226
|
if (gate.ok) {
|
|
13976
14227
|
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")));
|
|
13977
14228
|
if (writeGates.length)
|
|
13978
|
-
return
|
|
14229
|
+
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) });
|
|
13979
14230
|
}
|
|
13980
14231
|
const owner = {
|
|
13981
14232
|
taskId: task.data.id,
|
|
@@ -14003,19 +14254,19 @@ class WorkitCore {
|
|
|
14003
14254
|
}
|
|
14004
14255
|
const current = workspace.data.writer;
|
|
14005
14256
|
if (!current)
|
|
14006
|
-
return
|
|
14257
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
14007
14258
|
if (current.state === "uncertain")
|
|
14008
|
-
return
|
|
14259
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
14009
14260
|
owner: current.owner
|
|
14010
14261
|
});
|
|
14011
14262
|
if (current.owner.taskId !== task.data.id || current.owner.workerId !== helperId || !sameSession2(current.owner.session, this.context))
|
|
14012
|
-
return
|
|
14263
|
+
return failure2("permission_denied", "only the current writer can release ownership");
|
|
14013
14264
|
if (helperId !== null) {
|
|
14014
14265
|
const helper = this.helperEntry(task.data);
|
|
14015
14266
|
if (!helper.ok)
|
|
14016
14267
|
return helper;
|
|
14017
14268
|
if (helper.data.data.state !== "running")
|
|
14018
|
-
return
|
|
14269
|
+
return failure2("recovery_required", "worker must be observed stopped before release");
|
|
14019
14270
|
}
|
|
14020
14271
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
14021
14272
|
taskId: task.data.id,
|
|
@@ -14047,9 +14298,9 @@ class WorkitCore {
|
|
|
14047
14298
|
if (!root.ok)
|
|
14048
14299
|
return root;
|
|
14049
14300
|
if ((this.context.workerId ?? null) !== null)
|
|
14050
|
-
return
|
|
14301
|
+
return failure2("permission_denied", "helpers cannot reserve external actions");
|
|
14051
14302
|
if (input.observation === undefined)
|
|
14052
|
-
return
|
|
14303
|
+
return failure2("invalid_input", "native action observation is required");
|
|
14053
14304
|
const task = this.store.readTask(input.taskId);
|
|
14054
14305
|
if (!task.ok)
|
|
14055
14306
|
return task;
|
|
@@ -14057,10 +14308,10 @@ class WorkitCore {
|
|
|
14057
14308
|
if (!workspace.ok)
|
|
14058
14309
|
return workspace;
|
|
14059
14310
|
if (!workspace.data)
|
|
14060
|
-
return
|
|
14311
|
+
return failure2("not_found", "workspace not found");
|
|
14061
14312
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14062
14313
|
if (!decision)
|
|
14063
|
-
return
|
|
14314
|
+
return failure2("not_found", "decision not found");
|
|
14064
14315
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
14065
14316
|
observation: input.observation,
|
|
14066
14317
|
expected: {
|
|
@@ -14085,7 +14336,7 @@ class WorkitCore {
|
|
|
14085
14336
|
const evaluations = new Map(view.data.requirements.map((entry) => [entry.requirementId, entry.status]));
|
|
14086
14337
|
const blocked = (view.data.task.policy?.requirements ?? []).filter((requirement) => requirement.dependentAction === operation && (evaluations.get(requirement.id) === "unsatisfied" || evaluations.get(requirement.id) === "unavailable"));
|
|
14087
14338
|
if (blocked.length)
|
|
14088
|
-
return
|
|
14339
|
+
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) });
|
|
14089
14340
|
}
|
|
14090
14341
|
return reserveAction({
|
|
14091
14342
|
...input,
|
|
@@ -14101,9 +14352,9 @@ class WorkitCore {
|
|
|
14101
14352
|
if (!root.ok)
|
|
14102
14353
|
return root;
|
|
14103
14354
|
if ((this.context.workerId ?? null) !== null)
|
|
14104
|
-
return
|
|
14355
|
+
return failure2("permission_denied", "helpers cannot settle external actions");
|
|
14105
14356
|
if (input.observation === undefined)
|
|
14106
|
-
return
|
|
14357
|
+
return failure2("invalid_input", "native action observation is required");
|
|
14107
14358
|
const task = this.store.readTask(input.taskId);
|
|
14108
14359
|
if (!task.ok)
|
|
14109
14360
|
return task;
|
|
@@ -14111,10 +14362,10 @@ class WorkitCore {
|
|
|
14111
14362
|
if (!workspace.ok)
|
|
14112
14363
|
return workspace;
|
|
14113
14364
|
if (!workspace.data)
|
|
14114
|
-
return
|
|
14365
|
+
return failure2("not_found", "workspace not found");
|
|
14115
14366
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14116
14367
|
if (!decision)
|
|
14117
|
-
return
|
|
14368
|
+
return failure2("not_found", "decision not found");
|
|
14118
14369
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
14119
14370
|
observation: input.observation,
|
|
14120
14371
|
expected: {
|
|
@@ -14145,7 +14396,7 @@ class WorkitCore {
|
|
|
14145
14396
|
if (!root.ok)
|
|
14146
14397
|
return root;
|
|
14147
14398
|
if ((this.context.workerId ?? null) !== null)
|
|
14148
|
-
return
|
|
14399
|
+
return failure2("permission_denied", "helpers cannot reconcile external actions");
|
|
14149
14400
|
const task = this.store.readTask(input.taskId);
|
|
14150
14401
|
if (!task.ok)
|
|
14151
14402
|
return task;
|
|
@@ -14153,10 +14404,10 @@ class WorkitCore {
|
|
|
14153
14404
|
if (!workspace.ok)
|
|
14154
14405
|
return workspace;
|
|
14155
14406
|
if (!workspace.data)
|
|
14156
|
-
return
|
|
14407
|
+
return failure2("not_found", "workspace not found");
|
|
14157
14408
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
14158
14409
|
if (!decision)
|
|
14159
|
-
return
|
|
14410
|
+
return failure2("not_found", "decision not found");
|
|
14160
14411
|
const authority = verifyNativeReconciliation(this.context.nativeAuthority, {
|
|
14161
14412
|
observation: input.observation,
|
|
14162
14413
|
expected: {
|
|
@@ -14203,7 +14454,7 @@ class WorkitCore {
|
|
|
14203
14454
|
if (!workspace.ok)
|
|
14204
14455
|
return workspace;
|
|
14205
14456
|
if (!workspace.data)
|
|
14206
|
-
return
|
|
14457
|
+
return failure2("not_found", "workspace not found");
|
|
14207
14458
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
14208
14459
|
const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
|
|
14209
14460
|
if (!current.ok)
|
|
@@ -14246,7 +14497,7 @@ class WorkitCore {
|
|
|
14246
14497
|
if (!workspace.ok)
|
|
14247
14498
|
return workspace;
|
|
14248
14499
|
if (!workspace.data)
|
|
14249
|
-
return
|
|
14500
|
+
return failure2("not_found", "workspace not found");
|
|
14250
14501
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
14251
14502
|
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);
|
|
14252
14503
|
if (!current.ok)
|
|
@@ -14266,14 +14517,14 @@ class WorkitCore {
|
|
|
14266
14517
|
if (!root.ok)
|
|
14267
14518
|
return root;
|
|
14268
14519
|
if ((this.context.workerId ?? null) !== null)
|
|
14269
|
-
return
|
|
14520
|
+
return failure2("permission_denied", "helpers cannot reconcile task workers");
|
|
14270
14521
|
if (view.task.workspaceId !== view.workspace.id)
|
|
14271
|
-
return
|
|
14522
|
+
return failure2("invalid_input", "task and workspace bindings are invalid");
|
|
14272
14523
|
try {
|
|
14273
14524
|
if (realpathSync6(view.workspace.root) !== this.store.root)
|
|
14274
|
-
return
|
|
14525
|
+
return failure2("invalid_input", "task view root does not match the task store");
|
|
14275
14526
|
} catch {
|
|
14276
|
-
return
|
|
14527
|
+
return failure2("invalid_input", "task view root cannot be resolved");
|
|
14277
14528
|
}
|
|
14278
14529
|
const updates = [];
|
|
14279
14530
|
const seen = new Set;
|
|
@@ -14285,7 +14536,7 @@ class WorkitCore {
|
|
|
14285
14536
|
};
|
|
14286
14537
|
for (const observation of observations) {
|
|
14287
14538
|
if (seen.has(observation.workerId))
|
|
14288
|
-
return
|
|
14539
|
+
return failure2("invalid_input", "worker observations must be unique");
|
|
14289
14540
|
seen.add(observation.workerId);
|
|
14290
14541
|
const freshTask = this.store.readTask(view.task.id);
|
|
14291
14542
|
const freshWorkspace = this.store.readWorkspace();
|
|
@@ -14294,11 +14545,11 @@ class WorkitCore {
|
|
|
14294
14545
|
if (!freshWorkspace.ok)
|
|
14295
14546
|
return freshWorkspace;
|
|
14296
14547
|
if (!freshWorkspace.data)
|
|
14297
|
-
return
|
|
14548
|
+
return failure2("not_found", "workspace not found");
|
|
14298
14549
|
if (observation.taskId !== view.task.id || observation.expectedRevision !== freshTask.data.revision || observation.expectedWorkspaceRevision !== freshWorkspace.data.revision)
|
|
14299
|
-
return
|
|
14550
|
+
return failure2("revision_conflict", "worker observation is stale");
|
|
14300
14551
|
if (!view.task.workers.some((entry) => entry.id === observation.workerId))
|
|
14301
|
-
return
|
|
14552
|
+
return failure2("permission_denied", "worker observation is not assigned");
|
|
14302
14553
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
14303
14554
|
observation: observation.observation,
|
|
14304
14555
|
expected: { ...observation, workspaceId: view.workspace.id },
|
|
@@ -14307,7 +14558,7 @@ class WorkitCore {
|
|
|
14307
14558
|
if (!verified.ok)
|
|
14308
14559
|
return verified;
|
|
14309
14560
|
if (!takeWorker(verified.data, binding, observation))
|
|
14310
|
-
return
|
|
14561
|
+
return failure2("permission_denied", "worker observation authority was not retained");
|
|
14311
14562
|
updates.push(observation);
|
|
14312
14563
|
}
|
|
14313
14564
|
const observedStates = new Map(updates.map((entry) => [entry.workerId, entry.state]));
|
|
@@ -14345,19 +14596,19 @@ class WorkitCore {
|
|
|
14345
14596
|
if (!helper.ok)
|
|
14346
14597
|
return helper;
|
|
14347
14598
|
if (status === "paused" && task.data.status !== "active" || status === "active" && task.data.status !== "paused")
|
|
14348
|
-
return
|
|
14599
|
+
return failure2("invalid_transition", `cannot transition ${task.data.status} to ${status}`);
|
|
14349
14600
|
const workspace = this.store.readWorkspace();
|
|
14350
14601
|
if (!workspace.ok)
|
|
14351
14602
|
return workspace;
|
|
14352
14603
|
if (!workspace.data)
|
|
14353
|
-
return
|
|
14604
|
+
return failure2("not_found", "workspace not found");
|
|
14354
14605
|
this.fillRevisions(input, task.data, workspace.data);
|
|
14355
14606
|
let resumeCandidate = null;
|
|
14356
14607
|
if (status === "active" && task.data.origin) {
|
|
14357
14608
|
if (!task.data.policy)
|
|
14358
|
-
return
|
|
14609
|
+
return failure2("needs_input", "imported task requires a current policy");
|
|
14359
14610
|
if (task.data.policy.policyVersion !== POLICY_VERSION)
|
|
14360
|
-
return
|
|
14611
|
+
return failure2("needs_input", "stored policy version is unsupported; reassessment is required");
|
|
14361
14612
|
const view = this.view(task.data);
|
|
14362
14613
|
if (!view.ok)
|
|
14363
14614
|
return view;
|
|
@@ -14366,20 +14617,20 @@ class WorkitCore {
|
|
|
14366
14617
|
return current;
|
|
14367
14618
|
const requirements = view.data.requirements;
|
|
14368
14619
|
if (requirements.some((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable"))
|
|
14369
|
-
return
|
|
14620
|
+
return failure2("requirements_unsatisfied", "imported task requires current requirements", {
|
|
14370
14621
|
requirementIds: requirements.filter((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable").map((requirement) => requirement.requirementId)
|
|
14371
14622
|
});
|
|
14372
14623
|
if (current.data.reassessmentRequired)
|
|
14373
|
-
return
|
|
14624
|
+
return failure2("needs_input", "imported task requires destination policy reassessment");
|
|
14374
14625
|
if (current.data.staleEvidenceIds.length)
|
|
14375
|
-
return
|
|
14626
|
+
return failure2("needs_input", "imported task requires fresh destination evidence");
|
|
14376
14627
|
if (current.data.blockers.some((blocker) => blocker.dependentAction === "resume" || blocker.reason === "worker state requires reconciliation"))
|
|
14377
|
-
return
|
|
14628
|
+
return failure2("recovery_required", "imported task requires resume reconciliation");
|
|
14378
14629
|
if (!validResumeApproval(task.data, workspace.data, input.authorityRefs ?? [], this.context))
|
|
14379
|
-
return
|
|
14630
|
+
return failure2("permission_denied", "imported resume requires native destination approval");
|
|
14380
14631
|
resumeCandidate = current.data.candidate;
|
|
14381
14632
|
}
|
|
14382
|
-
const blocker = status === "paused" ? workspace.data.writer ?
|
|
14633
|
+
const blocker = status === "paused" ? workspace.data.writer ? failure2("recovery_required", "writer ownership must be released first") : null : this.activeWorkerBlocker(task.data, workspace.data);
|
|
14383
14634
|
if (blocker)
|
|
14384
14635
|
return blocker;
|
|
14385
14636
|
let pauseCandidate = null;
|
|
@@ -14394,7 +14645,7 @@ class WorkitCore {
|
|
|
14394
14645
|
expectedRevision: input.expectedRevision,
|
|
14395
14646
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14396
14647
|
now: trustedNow(this.context),
|
|
14397
|
-
workspace: (
|
|
14648
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14398
14649
|
task: (current, context) => success(context.revision, null, {
|
|
14399
14650
|
...current,
|
|
14400
14651
|
status,
|
|
@@ -14415,7 +14666,7 @@ class WorkitCore {
|
|
|
14415
14666
|
if (!helper.ok)
|
|
14416
14667
|
return helper;
|
|
14417
14668
|
if (task.data.status === "closed")
|
|
14418
|
-
return
|
|
14669
|
+
return failure2("invalid_transition", "closed task cannot update progress");
|
|
14419
14670
|
this.fillRevisions(input, task.data);
|
|
14420
14671
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, context) => success(context.revision, null, { ...current, progress: input.progress }), trustedNow(this.context));
|
|
14421
14672
|
if (!changed.ok)
|
|
@@ -14430,12 +14681,12 @@ class WorkitCore {
|
|
|
14430
14681
|
if (!helper.ok)
|
|
14431
14682
|
return helper;
|
|
14432
14683
|
if (task.data.status === "closed")
|
|
14433
|
-
return
|
|
14684
|
+
return failure2("invalid_transition", "closed task cannot be revised");
|
|
14434
14685
|
const workspace = this.store.readWorkspace();
|
|
14435
14686
|
if (!workspace.ok)
|
|
14436
14687
|
return workspace;
|
|
14437
14688
|
if (!workspace.data)
|
|
14438
|
-
return
|
|
14689
|
+
return failure2("not_found", "workspace not found");
|
|
14439
14690
|
const revisionBlocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14440
14691
|
if (revisionBlocker)
|
|
14441
14692
|
return revisionBlocker;
|
|
@@ -14445,7 +14696,7 @@ class WorkitCore {
|
|
|
14445
14696
|
expectedRevision: input.expectedRevision,
|
|
14446
14697
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14447
14698
|
now: trustedNow(this.context),
|
|
14448
|
-
workspace: (
|
|
14699
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14449
14700
|
task: (current, context) => success(context.revision, null, {
|
|
14450
14701
|
...current,
|
|
14451
14702
|
intent: {
|
|
@@ -14470,12 +14721,12 @@ class WorkitCore {
|
|
|
14470
14721
|
if (!helper.ok)
|
|
14471
14722
|
return helper;
|
|
14472
14723
|
if (task.data.status !== "active" && task.data.status !== "paused")
|
|
14473
|
-
return
|
|
14724
|
+
return failure2("invalid_transition", "closed task cannot be reopened or closed again");
|
|
14474
14725
|
const workspace = this.store.readWorkspace();
|
|
14475
14726
|
if (!workspace.ok)
|
|
14476
14727
|
return workspace;
|
|
14477
14728
|
if (!workspace.data)
|
|
14478
|
-
return
|
|
14729
|
+
return failure2("not_found", "workspace not found");
|
|
14479
14730
|
const blocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14480
14731
|
if (blocker)
|
|
14481
14732
|
return blocker;
|
|
@@ -14863,7 +15114,7 @@ var unfinishedTaskOffer2 = (input, excludedTaskId) => {
|
|
|
14863
15114
|
if (!listed.ok)
|
|
14864
15115
|
return null;
|
|
14865
15116
|
const host = detectCodexSurface(process.env);
|
|
14866
|
-
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === host && task.intent.provenance.session.handle === input.session_id) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === host && worker.data.session.handle === input.session_id)).
|
|
15117
|
+
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === host && task.intent.provenance.session.handle === input.session_id) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === host && worker.data.session.handle === input.session_id)).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, 3);
|
|
14867
15118
|
if (tasks.length === 0)
|
|
14868
15119
|
return null;
|
|
14869
15120
|
const quote = (value) => JSON.stringify(value.replace(/[<>]/g, " ").slice(0, 120));
|