@brainervirus/workit-cursor 2.1.4 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +1126 -889
- package/dist/mcp-server.js +10129 -13299
- package/dist/workit-hook.js +1132 -881
- package/package.json +3 -3
|
@@ -27,18 +27,23 @@ function jsonStringifyReplacer(_, value) {
|
|
|
27
27
|
return value.toString();
|
|
28
28
|
return value;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
|
|
31
|
+
class Cached {
|
|
32
|
+
constructor(getter) {
|
|
33
|
+
this._getter = getter;
|
|
34
|
+
this._value = undefined;
|
|
35
|
+
}
|
|
36
|
+
get value() {
|
|
37
|
+
const getter = this._getter;
|
|
38
|
+
if (getter !== undefined) {
|
|
39
|
+
this._value = getter();
|
|
40
|
+
this._getter = undefined;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
return this._value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function cached(getter) {
|
|
46
|
+
return new Cached(getter);
|
|
42
47
|
}
|
|
43
48
|
function nullish(input) {
|
|
44
49
|
return input === null || input === undefined;
|
|
@@ -64,6 +69,56 @@ function assignProp(target, prop, value) {
|
|
|
64
69
|
configurable: true
|
|
65
70
|
});
|
|
66
71
|
}
|
|
72
|
+
function rawShape(def) {
|
|
73
|
+
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
74
|
+
return desc?.get ? desc.get.raw : desc?.value;
|
|
75
|
+
}
|
|
76
|
+
function sourceShape(schema) {
|
|
77
|
+
return rawShape(schema._zod.def) ?? schema._zod.def.shape;
|
|
78
|
+
}
|
|
79
|
+
function deferProp(target, key, getter) {
|
|
80
|
+
Object.defineProperty(target, key, {
|
|
81
|
+
get() {
|
|
82
|
+
const value = getter();
|
|
83
|
+
assignProp(this, key, value);
|
|
84
|
+
return value;
|
|
85
|
+
},
|
|
86
|
+
enumerable: true,
|
|
87
|
+
configurable: true
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function putProp(target, key, value) {
|
|
91
|
+
if (key in target)
|
|
92
|
+
assignProp(target, key, value);
|
|
93
|
+
else
|
|
94
|
+
target[key] = value;
|
|
95
|
+
}
|
|
96
|
+
function mirrorShape(target, source, keys, wrap) {
|
|
97
|
+
const raw = sourceShape(source);
|
|
98
|
+
for (const key of keys) {
|
|
99
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
100
|
+
if (!desc.enumerable)
|
|
101
|
+
continue;
|
|
102
|
+
if (desc.get) {
|
|
103
|
+
deferProp(target, key, () => {
|
|
104
|
+
const value = source._zod.def.shape[key];
|
|
105
|
+
return wrap ? wrap(value, key) : value;
|
|
106
|
+
});
|
|
107
|
+
} else
|
|
108
|
+
putProp(target, key, wrap ? wrap(desc.value, key) : desc.value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function mirrorProps(target, source) {
|
|
112
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
113
|
+
const desc = Object.getOwnPropertyDescriptor(source, key);
|
|
114
|
+
if (!desc.enumerable)
|
|
115
|
+
continue;
|
|
116
|
+
if (desc.get)
|
|
117
|
+
deferProp(target, key, () => source[key]);
|
|
118
|
+
else
|
|
119
|
+
putProp(target, key, desc.value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
67
122
|
function mergeDefs(...defs) {
|
|
68
123
|
const mergedDescriptors = {};
|
|
69
124
|
for (const def of defs) {
|
|
@@ -152,23 +207,21 @@ function pick(schema, mask) {
|
|
|
152
207
|
if (hasChecks) {
|
|
153
208
|
throw new Error(".pick() cannot be used on object schemas containing refinements");
|
|
154
209
|
}
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
});
|
|
171
|
-
return clone(schema, def);
|
|
210
|
+
const newShape = {};
|
|
211
|
+
mirrorShape(newShape, schema, maskedKeys(schema, mask));
|
|
212
|
+
return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
|
|
213
|
+
}
|
|
214
|
+
function maskedKeys(schema, mask) {
|
|
215
|
+
const raw = sourceShape(schema);
|
|
216
|
+
const keys = [];
|
|
217
|
+
for (const key of Reflect.ownKeys(mask)) {
|
|
218
|
+
if (!Object.getOwnPropertyDescriptor(raw, key)?.enumerable) {
|
|
219
|
+
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
220
|
+
}
|
|
221
|
+
if (mask[key])
|
|
222
|
+
keys.push(key);
|
|
223
|
+
}
|
|
224
|
+
return keys;
|
|
172
225
|
}
|
|
173
226
|
function omit(schema, mask) {
|
|
174
227
|
const currDef = schema._zod.def;
|
|
@@ -177,23 +230,10 @@ function omit(schema, mask) {
|
|
|
177
230
|
if (hasChecks) {
|
|
178
231
|
throw new Error(".omit() cannot be used on object schemas containing refinements");
|
|
179
232
|
}
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (!Object.prototype.hasOwnProperty.call(currDef.shape, key)) {
|
|
185
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
186
|
-
}
|
|
187
|
-
if (!mask[key])
|
|
188
|
-
continue;
|
|
189
|
-
delete newShape[key];
|
|
190
|
-
}
|
|
191
|
-
assignProp(this, "shape", newShape);
|
|
192
|
-
return newShape;
|
|
193
|
-
},
|
|
194
|
-
checks: []
|
|
195
|
-
});
|
|
196
|
-
return clone(schema, def);
|
|
233
|
+
const omitted = new Set(maskedKeys(schema, mask));
|
|
234
|
+
const newShape = {};
|
|
235
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)).filter((key) => !omitted.has(key)));
|
|
236
|
+
return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
|
|
197
237
|
}
|
|
198
238
|
function extend(schema, shape) {
|
|
199
239
|
if (!isPlainObject(shape)) {
|
|
@@ -202,34 +242,26 @@ function extend(schema, shape) {
|
|
|
202
242
|
const checks = schema._zod.def.checks;
|
|
203
243
|
const hasChecks = checks && checks.length > 0;
|
|
204
244
|
if (hasChecks) {
|
|
205
|
-
const existingShape = schema
|
|
245
|
+
const existingShape = sourceShape(schema);
|
|
206
246
|
for (const key of Reflect.ownKeys(shape)) {
|
|
207
247
|
if (Object.getOwnPropertyDescriptor(existingShape, key) !== undefined) {
|
|
208
248
|
throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
|
|
209
249
|
}
|
|
210
250
|
}
|
|
211
251
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return clone(schema, def);
|
|
252
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
253
|
+
}
|
|
254
|
+
function extended(schema, shape) {
|
|
255
|
+
const newShape = {};
|
|
256
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)));
|
|
257
|
+
mirrorProps(newShape, shape);
|
|
258
|
+
return newShape;
|
|
220
259
|
}
|
|
221
260
|
function safeExtend(schema, shape) {
|
|
222
261
|
if (!isPlainObject(shape)) {
|
|
223
262
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
224
263
|
}
|
|
225
|
-
|
|
226
|
-
get shape() {
|
|
227
|
-
const _shape = { ...schema._zod.def.shape, ...shape };
|
|
228
|
-
assignProp(this, "shape", _shape);
|
|
229
|
-
return _shape;
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
return clone(schema, def);
|
|
264
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
233
265
|
}
|
|
234
266
|
function merge(a, b) {
|
|
235
267
|
if (!b?._zod?.def) {
|
|
@@ -238,12 +270,11 @@ function merge(a, b) {
|
|
|
238
270
|
if (a._zod.def.checks?.length) {
|
|
239
271
|
throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
|
|
240
272
|
}
|
|
273
|
+
const newShape = {};
|
|
274
|
+
mirrorShape(newShape, a, Reflect.ownKeys(sourceShape(a)));
|
|
275
|
+
mirrorShape(newShape, b, Reflect.ownKeys(sourceShape(b)));
|
|
241
276
|
const def = mergeDefs(a._zod.def, {
|
|
242
|
-
|
|
243
|
-
const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };
|
|
244
|
-
assignProp(this, "shape", _shape);
|
|
245
|
-
return _shape;
|
|
246
|
-
},
|
|
277
|
+
shape: newShape,
|
|
247
278
|
get catchall() {
|
|
248
279
|
return b._zod.def.catchall;
|
|
249
280
|
},
|
|
@@ -258,67 +289,16 @@ function partial(Class, schema, mask, name = "partial") {
|
|
|
258
289
|
if (hasChecks) {
|
|
259
290
|
throw new Error(`.${name}() cannot be used on object schemas containing refinements`);
|
|
260
291
|
}
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (mask) {
|
|
266
|
-
for (const key of Reflect.ownKeys(mask)) {
|
|
267
|
-
if (!Object.prototype.hasOwnProperty.call(oldShape, key)) {
|
|
268
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
269
|
-
}
|
|
270
|
-
if (!mask[key])
|
|
271
|
-
continue;
|
|
272
|
-
shape[key] = Class ? new Class({
|
|
273
|
-
type: "optional",
|
|
274
|
-
innerType: oldShape[key]
|
|
275
|
-
}) : oldShape[key];
|
|
276
|
-
}
|
|
277
|
-
} else {
|
|
278
|
-
for (const key of Reflect.ownKeys(oldShape)) {
|
|
279
|
-
shape[key] = Class ? new Class({
|
|
280
|
-
type: "optional",
|
|
281
|
-
innerType: oldShape[key]
|
|
282
|
-
}) : oldShape[key];
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
assignProp(this, "shape", shape);
|
|
286
|
-
return shape;
|
|
287
|
-
},
|
|
288
|
-
checks: []
|
|
289
|
-
});
|
|
290
|
-
return clone(schema, def);
|
|
292
|
+
const selected = mask ? new Set(maskedKeys(schema, mask)) : undefined;
|
|
293
|
+
const newShape = {};
|
|
294
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), Class && ((value, key) => selected && !selected.has(key) ? value : new Class({ type: "optional", innerType: value })));
|
|
295
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: newShape, checks: [] }));
|
|
291
296
|
}
|
|
292
297
|
function required(Class, schema, mask) {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (mask) {
|
|
298
|
-
for (const key of Reflect.ownKeys(mask)) {
|
|
299
|
-
if (!Object.prototype.hasOwnProperty.call(shape, key)) {
|
|
300
|
-
throw new Error(`Unrecognized key: "${String(key)}"`);
|
|
301
|
-
}
|
|
302
|
-
if (!mask[key])
|
|
303
|
-
continue;
|
|
304
|
-
shape[key] = new Class({
|
|
305
|
-
type: "nonoptional",
|
|
306
|
-
innerType: oldShape[key]
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
} else {
|
|
310
|
-
for (const key of Reflect.ownKeys(oldShape)) {
|
|
311
|
-
shape[key] = new Class({
|
|
312
|
-
type: "nonoptional",
|
|
313
|
-
innerType: oldShape[key]
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
assignProp(this, "shape", shape);
|
|
318
|
-
return shape;
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
return clone(schema, def);
|
|
298
|
+
const selected = mask ? new Set(maskedKeys(schema, mask)) : undefined;
|
|
299
|
+
const newShape = {};
|
|
300
|
+
mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), (value, key) => selected && !selected.has(key) ? value : new Class({ type: "nonoptional", innerType: value }));
|
|
301
|
+
return clone(schema, mergeDefs(schema._zod.def, { shape: newShape }));
|
|
322
302
|
}
|
|
323
303
|
function aborted(x, startIndex = 0) {
|
|
324
304
|
if (x.aborted === true)
|
|
@@ -368,13 +348,18 @@ function finalizeIssue(iss, ctx, config) {
|
|
|
368
348
|
}
|
|
369
349
|
const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : undefined;
|
|
370
350
|
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";
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
351
|
+
const full = {};
|
|
352
|
+
for (const k of Object.keys(iss)) {
|
|
353
|
+
if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
|
|
354
|
+
continue;
|
|
355
|
+
full[k] = iss[k];
|
|
356
|
+
}
|
|
357
|
+
full.path ?? (full.path = []);
|
|
358
|
+
full.message = message;
|
|
374
359
|
if (ctx?.reportInput) {
|
|
375
|
-
|
|
360
|
+
full.input = iss.input;
|
|
376
361
|
}
|
|
377
|
-
return
|
|
362
|
+
return full;
|
|
378
363
|
}
|
|
379
364
|
function codePointLength(str) {
|
|
380
365
|
const units = str.length;
|
|
@@ -445,6 +430,22 @@ function own(inst, key, value, enumerable = true) {
|
|
|
445
430
|
function hide(inst, key, value) {
|
|
446
431
|
return own(inst, key, value, false);
|
|
447
432
|
}
|
|
433
|
+
function derived(computes, table) {
|
|
434
|
+
for (const key in computes) {
|
|
435
|
+
const compute = computes[key];
|
|
436
|
+
Object.defineProperty(table, key, {
|
|
437
|
+
configurable: true,
|
|
438
|
+
enumerable: true,
|
|
439
|
+
get() {
|
|
440
|
+
return own(this, key, compute(this));
|
|
441
|
+
},
|
|
442
|
+
set(value) {
|
|
443
|
+
own(this, key, value);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
return table;
|
|
448
|
+
}
|
|
448
449
|
function defineBound(proto, key, fn) {
|
|
449
450
|
Object.defineProperty(proto, key, {
|
|
450
451
|
configurable: true,
|
|
@@ -515,7 +516,7 @@ function constantCatch(value) {
|
|
|
515
516
|
fn[CONSTANT_CATCH] = true;
|
|
516
517
|
return fn;
|
|
517
518
|
}
|
|
518
|
-
var captureStackTrace, allowsEval, propertyKeyTypes, NUMBER_FORMAT_RANGES, highSurrogate, installing, broke = false, breaker, CONSTANT_CATCH = "~constantCatch";
|
|
519
|
+
var captureStackTrace, allowsEval, propertyKeyTypes, NUMBER_FORMAT_RANGES, BIGINT_FORMAT_RANGES, highSurrogate, installing, broke = false, breaker, CONSTANT_CATCH = "~constantCatch";
|
|
519
520
|
var init_util = __esm(() => {
|
|
520
521
|
init_core();
|
|
521
522
|
captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {};
|
|
@@ -542,6 +543,10 @@ var init_util = __esm(() => {
|
|
|
542
543
|
float32: [-340282346638528860000000000000000000000, 340282346638528860000000000000000000000],
|
|
543
544
|
float64: [-Number.MAX_VALUE, Number.MAX_VALUE]
|
|
544
545
|
}))();
|
|
546
|
+
BIGINT_FORMAT_RANGES = {
|
|
547
|
+
int64: [/* @__PURE__ */ BigInt("-9223372036854775808"), /* @__PURE__ */ BigInt("9223372036854775807")],
|
|
548
|
+
uint64: [/* @__PURE__ */ BigInt(0), /* @__PURE__ */ BigInt("18446744073709551615")]
|
|
549
|
+
};
|
|
545
550
|
highSurrogate = /[\uD800-\uDBFF]/;
|
|
546
551
|
breaker = {
|
|
547
552
|
configurable: true,
|
|
@@ -591,8 +596,7 @@ function $constructor(name, initializer, proto, params) {
|
|
|
591
596
|
} finally {
|
|
592
597
|
_zodDesc.value = undefined;
|
|
593
598
|
}
|
|
594
|
-
}
|
|
595
|
-
if (inst._zod.traits.has(name)) {
|
|
599
|
+
} else if (inst._zod.traits.has(name)) {
|
|
596
600
|
return;
|
|
597
601
|
}
|
|
598
602
|
inst._zod.traits.add(name);
|
|
@@ -753,13 +757,10 @@ function formatError(error, mapper = (issue) => issue.message) {
|
|
|
753
757
|
processError(error);
|
|
754
758
|
return fieldErrors;
|
|
755
759
|
}
|
|
756
|
-
var _messageDesc,
|
|
760
|
+
var _messageDesc, _issuesDesc, _installedToString, initializer = (inst, def) => {
|
|
757
761
|
inst.name = "$ZodError";
|
|
758
|
-
_zodDesc2.value = inst._zod;
|
|
759
|
-
Object.defineProperty(inst, "_zod", _zodDesc2);
|
|
760
762
|
_issuesDesc.value = def;
|
|
761
763
|
Object.defineProperty(inst, "issues", _issuesDesc);
|
|
762
|
-
_zodDesc2.value = undefined;
|
|
763
764
|
_issuesDesc.value = undefined;
|
|
764
765
|
Object.defineProperty(inst, "message", _messageDesc);
|
|
765
766
|
const proto = Object.getPrototypeOf(inst);
|
|
@@ -788,7 +789,6 @@ var init_errors = __esm(() => {
|
|
|
788
789
|
enumerable: true,
|
|
789
790
|
configurable: true
|
|
790
791
|
};
|
|
791
|
-
_zodDesc2 = { value: undefined, enumerable: false };
|
|
792
792
|
_issuesDesc = { value: undefined, enumerable: false };
|
|
793
793
|
_installedToString = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
|
|
794
794
|
$ZodError = $constructor("$ZodError", initializer);
|
|
@@ -801,6 +801,40 @@ var init_errors = __esm(() => {
|
|
|
801
801
|
function finalizeParams(callee, params) {
|
|
802
802
|
return { callee: params?.callee ?? callee, Err: params?.Err };
|
|
803
803
|
}
|
|
804
|
+
function failure(Err, issues, ctx) {
|
|
805
|
+
let error;
|
|
806
|
+
return {
|
|
807
|
+
success: false,
|
|
808
|
+
get error() {
|
|
809
|
+
if (!error) {
|
|
810
|
+
error = new Err(issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
811
|
+
issues = undefined;
|
|
812
|
+
ctx = undefined;
|
|
813
|
+
}
|
|
814
|
+
return error;
|
|
815
|
+
},
|
|
816
|
+
set error(e) {
|
|
817
|
+
error = e;
|
|
818
|
+
issues = undefined;
|
|
819
|
+
ctx = undefined;
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
function validateFallback(schema, value, _ctx) {
|
|
824
|
+
const ctx = _ctx ? { ..._ctx, async: false, abortEarly: true } : { async: false, abortEarly: true };
|
|
825
|
+
const fallbackRun = schema._zod.bag.fallbackRun;
|
|
826
|
+
let result;
|
|
827
|
+
if (fallbackRun) {
|
|
828
|
+
ctx[COMPILE_FALLBACK] = true;
|
|
829
|
+
result = fallbackRun({ value, issues: [] }, ctx);
|
|
830
|
+
} else {
|
|
831
|
+
result = schema._zod.run({ value, issues: [] }, ctx);
|
|
832
|
+
}
|
|
833
|
+
if (result instanceof Promise) {
|
|
834
|
+
throw new $ZodAsyncError;
|
|
835
|
+
}
|
|
836
|
+
return result.issues.length === 0;
|
|
837
|
+
}
|
|
804
838
|
var _parse = (_Err) => {
|
|
805
839
|
const fn = (schema, value, _ctx, _params) => {
|
|
806
840
|
const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
|
|
@@ -836,20 +870,29 @@ var _parse = (_Err) => {
|
|
|
836
870
|
if (result instanceof Promise) {
|
|
837
871
|
throw new $ZodAsyncError;
|
|
838
872
|
}
|
|
839
|
-
return result.issues.length ? {
|
|
840
|
-
|
|
841
|
-
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
842
|
-
} : { success: true, data: result.value };
|
|
843
|
-
}, safeParse, _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
873
|
+
return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
|
|
874
|
+
}, _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
844
875
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
845
876
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
846
877
|
if (result instanceof Promise)
|
|
847
878
|
result = await result;
|
|
848
|
-
return result.issues.length ? {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
879
|
+
return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
|
|
880
|
+
}, COMPILE_INVALID, COMPILE_FALLBACK, validate = (schema, value, _ctx) => {
|
|
881
|
+
const validator = schema._zod.bag.validator;
|
|
882
|
+
if (validator !== undefined) {
|
|
883
|
+
if (validator(value) !== COMPILE_INVALID)
|
|
884
|
+
return true;
|
|
885
|
+
if (validator.definite === true && _ctx === undefined)
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
return validateFallback(schema, value, _ctx);
|
|
889
|
+
}, validateAsync = async (schema, value, _ctx) => {
|
|
890
|
+
const ctx = _ctx ? { ..._ctx, async: true, abortEarly: true } : { async: true, abortEarly: true };
|
|
891
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
892
|
+
if (result instanceof Promise)
|
|
893
|
+
result = await result;
|
|
894
|
+
return result.issues.length === 0;
|
|
895
|
+
}, _encode = (_Err) => {
|
|
853
896
|
const parse = _parse(_Err);
|
|
854
897
|
const fn = (schema, value, _ctx, _params) => {
|
|
855
898
|
const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
|
|
@@ -888,10 +931,9 @@ var _parse = (_Err) => {
|
|
|
888
931
|
};
|
|
889
932
|
var init_parse = __esm(() => {
|
|
890
933
|
init_core();
|
|
891
|
-
init_errors();
|
|
892
934
|
init_util();
|
|
893
|
-
|
|
894
|
-
|
|
935
|
+
COMPILE_INVALID = /* @__PURE__ */ Symbol.for("zod.compile.invalid");
|
|
936
|
+
COMPILE_FALLBACK = /* @__PURE__ */ Symbol.for("zod.compile.fallback");
|
|
895
937
|
});
|
|
896
938
|
|
|
897
939
|
// node_modules/zod/v4/core/regexes.js
|
|
@@ -924,10 +966,7 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, guid, uuid = (version) => {
|
|
|
924
966
|
if (!version)
|
|
925
967
|
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)$/;
|
|
926
968
|
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})$`);
|
|
927
|
-
}, email, _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, cidrv4, cidrv6, base64, base64url, httpProtocol, e164, creditCard, 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])))`, date,
|
|
928
|
-
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
929
|
-
return new RegExp(`^${regex}$`);
|
|
930
|
-
}, integer, number, boolean, lowercase, uppercase;
|
|
969
|
+
}, email, _emoji = `^(?=[\\s\\S]*[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u20E3])[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, cidrv4, cidrv6, base64, base64url, httpProtocol, e164, creditCard, iban, 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])))`, date, anyString, integer, number, boolean, lowercase, uppercase;
|
|
931
970
|
var init_regexes = __esm(() => {
|
|
932
971
|
cuid = /^[cC][0-9a-z]{6,}$/;
|
|
933
972
|
cuid2 = /^[0-9a-z]+$/;
|
|
@@ -937,17 +976,19 @@ var init_regexes = __esm(() => {
|
|
|
937
976
|
nanoid = /^[a-zA-Z0-9_-]{21}$/;
|
|
938
977
|
duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
939
978
|
guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
940
|
-
email = /^(
|
|
979
|
+
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,}$/;
|
|
941
980
|
ipv4 = /^(?:(?: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])$/;
|
|
942
981
|
ipv6 = /^(([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}|:))$/;
|
|
943
982
|
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])$/;
|
|
944
983
|
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])$/;
|
|
945
984
|
base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
946
|
-
base64url = /^[A-Za-z0-9_-]
|
|
985
|
+
base64url = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/;
|
|
947
986
|
httpProtocol = /^https?$/;
|
|
948
987
|
e164 = /^\+[1-9]\d{6,14}$/;
|
|
949
988
|
creditCard = /^\d(?:[ -]?\d){11,18}$/;
|
|
989
|
+
iban = /^[A-Z]{2}(?!00|01|99)\d{2}[A-Z0-9]{11,30}$/;
|
|
950
990
|
date = /* @__PURE__ */ anchor(dateSource);
|
|
991
|
+
anyString = /^[\s\S]{0,}$/;
|
|
951
992
|
integer = /^-?\d+$/;
|
|
952
993
|
number = /^-?\d+(?:\.\d+)?$/;
|
|
953
994
|
boolean = /^(?:true|false)$/i;
|
|
@@ -978,16 +1019,6 @@ var init_checks = __esm(() => {
|
|
|
978
1019
|
$ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst, def) => {
|
|
979
1020
|
$ZodCheck.init(inst, def);
|
|
980
1021
|
const origin = numericOriginMap[typeof def.value];
|
|
981
|
-
inst._zod.onattach.push((inst) => {
|
|
982
|
-
const bag = inst._zod.bag;
|
|
983
|
-
const curr = (def.inclusive ? bag.maximum : bag.exclusiveMaximum) ?? Number.POSITIVE_INFINITY;
|
|
984
|
-
if (def.value < curr) {
|
|
985
|
-
if (def.inclusive)
|
|
986
|
-
bag.maximum = def.value;
|
|
987
|
-
else
|
|
988
|
-
bag.exclusiveMaximum = def.value;
|
|
989
|
-
}
|
|
990
|
-
});
|
|
991
1022
|
inst._zod.check = (payload) => {
|
|
992
1023
|
if (def.inclusive ? payload.value <= def.value : payload.value < def.value) {
|
|
993
1024
|
return;
|
|
@@ -1006,16 +1037,6 @@ var init_checks = __esm(() => {
|
|
|
1006
1037
|
$ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
|
|
1007
1038
|
$ZodCheck.init(inst, def);
|
|
1008
1039
|
const origin = numericOriginMap[typeof def.value];
|
|
1009
|
-
inst._zod.onattach.push((inst) => {
|
|
1010
|
-
const bag = inst._zod.bag;
|
|
1011
|
-
const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
|
|
1012
|
-
if (def.value > curr) {
|
|
1013
|
-
if (def.inclusive)
|
|
1014
|
-
bag.minimum = def.value;
|
|
1015
|
-
else
|
|
1016
|
-
bag.exclusiveMinimum = def.value;
|
|
1017
|
-
}
|
|
1018
|
-
});
|
|
1019
1040
|
inst._zod.check = (payload) => {
|
|
1020
1041
|
if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
|
|
1021
1042
|
return;
|
|
@@ -1033,10 +1054,6 @@ var init_checks = __esm(() => {
|
|
|
1033
1054
|
});
|
|
1034
1055
|
$ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (inst, def) => {
|
|
1035
1056
|
$ZodCheck.init(inst, def);
|
|
1036
|
-
inst._zod.onattach.push((inst) => {
|
|
1037
|
-
var _a;
|
|
1038
|
-
(_a = inst._zod.bag).multipleOf ?? (_a.multipleOf = def.value);
|
|
1039
|
-
});
|
|
1040
1057
|
inst._zod.check = (payload) => {
|
|
1041
1058
|
if (typeof payload.value !== typeof def.value)
|
|
1042
1059
|
throw new Error("Cannot mix number and bigint in multiple_of check.");
|
|
@@ -1059,14 +1076,6 @@ var init_checks = __esm(() => {
|
|
|
1059
1076
|
const isInt = def.format?.includes("int");
|
|
1060
1077
|
const origin = isInt ? "int" : "number";
|
|
1061
1078
|
const [minimum, maximum] = NUMBER_FORMAT_RANGES[def.format];
|
|
1062
|
-
inst._zod.onattach.push((inst) => {
|
|
1063
|
-
const bag = inst._zod.bag;
|
|
1064
|
-
bag.format = def.format;
|
|
1065
|
-
bag.minimum = minimum;
|
|
1066
|
-
bag.maximum = maximum;
|
|
1067
|
-
if (isInt)
|
|
1068
|
-
bag.pattern = integer;
|
|
1069
|
-
});
|
|
1070
1079
|
inst._zod.check = (payload) => {
|
|
1071
1080
|
const input = payload.value;
|
|
1072
1081
|
if (isInt) {
|
|
@@ -1136,11 +1145,6 @@ var init_checks = __esm(() => {
|
|
|
1136
1145
|
var _a;
|
|
1137
1146
|
$ZodCheck.init(inst, def);
|
|
1138
1147
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1139
|
-
inst._zod.onattach.push((inst) => {
|
|
1140
|
-
const curr = inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY;
|
|
1141
|
-
if (def.maximum < curr)
|
|
1142
|
-
inst._zod.bag.maximum = def.maximum;
|
|
1143
|
-
});
|
|
1144
1148
|
inst._zod.check = (payload) => {
|
|
1145
1149
|
const input = payload.value;
|
|
1146
1150
|
const units = input.length;
|
|
@@ -1163,11 +1167,6 @@ var init_checks = __esm(() => {
|
|
|
1163
1167
|
var _a;
|
|
1164
1168
|
$ZodCheck.init(inst, def);
|
|
1165
1169
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1166
|
-
inst._zod.onattach.push((inst) => {
|
|
1167
|
-
const curr = inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY;
|
|
1168
|
-
if (def.minimum > curr)
|
|
1169
|
-
inst._zod.bag.minimum = def.minimum;
|
|
1170
|
-
});
|
|
1171
1170
|
inst._zod.check = (payload) => {
|
|
1172
1171
|
const input = payload.value;
|
|
1173
1172
|
const units = input.length;
|
|
@@ -1190,12 +1189,6 @@ var init_checks = __esm(() => {
|
|
|
1190
1189
|
var _a;
|
|
1191
1190
|
$ZodCheck.init(inst, def);
|
|
1192
1191
|
(_a = inst._zod.def).when ?? (_a.when = _whenHasLength);
|
|
1193
|
-
inst._zod.onattach.push((inst) => {
|
|
1194
|
-
const bag = inst._zod.bag;
|
|
1195
|
-
bag.minimum = def.length;
|
|
1196
|
-
bag.maximum = def.length;
|
|
1197
|
-
bag.length = def.length;
|
|
1198
|
-
});
|
|
1199
1192
|
inst._zod.check = (payload) => {
|
|
1200
1193
|
const input = payload.value;
|
|
1201
1194
|
const units = input.length;
|
|
@@ -1218,14 +1211,6 @@ var init_checks = __esm(() => {
|
|
|
1218
1211
|
$ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat", (inst, def) => {
|
|
1219
1212
|
var _a, _b;
|
|
1220
1213
|
$ZodCheck.init(inst, def);
|
|
1221
|
-
inst._zod.onattach.push((inst) => {
|
|
1222
|
-
const bag = inst._zod.bag;
|
|
1223
|
-
bag.format = def.format;
|
|
1224
|
-
if (def.pattern) {
|
|
1225
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1226
|
-
bag.patterns.add(def.pattern);
|
|
1227
|
-
}
|
|
1228
|
-
});
|
|
1229
1214
|
if (def.pattern)
|
|
1230
1215
|
(_a = inst._zod).check ?? (_a.check = (payload) => {
|
|
1231
1216
|
def.pattern.lastIndex = 0;
|
|
@@ -1274,11 +1259,6 @@ var init_checks = __esm(() => {
|
|
|
1274
1259
|
const escapedRegex = escapeRegex(def.includes);
|
|
1275
1260
|
const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position},}${escapedRegex}` : escapedRegex);
|
|
1276
1261
|
def.pattern = pattern;
|
|
1277
|
-
inst._zod.onattach.push((inst) => {
|
|
1278
|
-
const bag = inst._zod.bag;
|
|
1279
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1280
|
-
bag.patterns.add(pattern);
|
|
1281
|
-
});
|
|
1282
1262
|
inst._zod.check = (payload) => {
|
|
1283
1263
|
if (payload.value.includes(def.includes, def.position))
|
|
1284
1264
|
return;
|
|
@@ -1297,11 +1277,6 @@ var init_checks = __esm(() => {
|
|
|
1297
1277
|
$ZodCheck.init(inst, def);
|
|
1298
1278
|
const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
|
|
1299
1279
|
def.pattern ?? (def.pattern = pattern);
|
|
1300
|
-
inst._zod.onattach.push((inst) => {
|
|
1301
|
-
const bag = inst._zod.bag;
|
|
1302
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1303
|
-
bag.patterns.add(pattern);
|
|
1304
|
-
});
|
|
1305
1280
|
inst._zod.check = (payload) => {
|
|
1306
1281
|
if (payload.value.startsWith(def.prefix))
|
|
1307
1282
|
return;
|
|
@@ -1320,11 +1295,6 @@ var init_checks = __esm(() => {
|
|
|
1320
1295
|
$ZodCheck.init(inst, def);
|
|
1321
1296
|
const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
|
|
1322
1297
|
def.pattern ?? (def.pattern = pattern);
|
|
1323
|
-
inst._zod.onattach.push((inst) => {
|
|
1324
|
-
const bag = inst._zod.bag;
|
|
1325
|
-
bag.patterns ?? (bag.patterns = new Set);
|
|
1326
|
-
bag.patterns.add(pattern);
|
|
1327
|
-
});
|
|
1328
1298
|
inst._zod.check = (payload) => {
|
|
1329
1299
|
if (payload.value.endsWith(def.suffix))
|
|
1330
1300
|
return;
|
|
@@ -1357,8 +1327,11 @@ class Doc {
|
|
|
1357
1327
|
}
|
|
1358
1328
|
indented(fn) {
|
|
1359
1329
|
this.indent += 1;
|
|
1360
|
-
|
|
1361
|
-
|
|
1330
|
+
try {
|
|
1331
|
+
fn(this);
|
|
1332
|
+
} finally {
|
|
1333
|
+
this.indent -= 1;
|
|
1334
|
+
}
|
|
1362
1335
|
}
|
|
1363
1336
|
write(arg) {
|
|
1364
1337
|
if (typeof arg === "function") {
|
|
@@ -1391,30 +1364,57 @@ var version;
|
|
|
1391
1364
|
var init_versions = __esm(() => {
|
|
1392
1365
|
version = {
|
|
1393
1366
|
major: 4,
|
|
1394
|
-
minor:
|
|
1395
|
-
patch:
|
|
1367
|
+
minor: 6,
|
|
1368
|
+
patch: 5
|
|
1396
1369
|
};
|
|
1397
1370
|
});
|
|
1398
1371
|
|
|
1399
1372
|
// node_modules/zod/v4/core/schemas.js
|
|
1373
|
+
async function validateAsync2(inst, value) {
|
|
1374
|
+
const ctx = { async: true };
|
|
1375
|
+
return toStandardResult(await inst._zod.run({ value, issues: [] }, ctx), ctx);
|
|
1376
|
+
}
|
|
1400
1377
|
function standardProps(inst) {
|
|
1401
1378
|
return {
|
|
1402
1379
|
validate: (value) => {
|
|
1380
|
+
const ctx = { async: false };
|
|
1403
1381
|
try {
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
}
|
|
1382
|
+
const r = inst._zod.run({ value, issues: [] }, ctx);
|
|
1383
|
+
if (!(r instanceof Promise))
|
|
1384
|
+
return toStandardResult(r, ctx);
|
|
1385
|
+
} catch (_) {}
|
|
1386
|
+
return validateAsync2(inst, value);
|
|
1408
1387
|
},
|
|
1409
1388
|
vendor: "zod",
|
|
1410
1389
|
version: 1
|
|
1411
1390
|
};
|
|
1412
1391
|
}
|
|
1392
|
+
function canParseURL(input) {
|
|
1393
|
+
try {
|
|
1394
|
+
if (typeof URL !== "undefined" && typeof URL.canParse === "function")
|
|
1395
|
+
return URL.canParse(input);
|
|
1396
|
+
new URL(input);
|
|
1397
|
+
return true;
|
|
1398
|
+
} catch {
|
|
1399
|
+
return false;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
function validateURL(trimmed, def) {
|
|
1403
|
+
if (!("normalize" in def) && !("hostname" in def) && !("protocol" in def)) {
|
|
1404
|
+
return canParseURL(trimmed) || URL_UNPARSEABLE;
|
|
1405
|
+
}
|
|
1406
|
+
return parseURLObject(trimmed, def);
|
|
1407
|
+
}
|
|
1413
1408
|
function parseURLObject(trimmed, def) {
|
|
1414
1409
|
if (!def.normalize && def.protocol?.source === httpProtocol.source && !/^https?:\/\//i.test(trimmed)) {
|
|
1415
1410
|
return URL_BAD_FORMAT;
|
|
1416
1411
|
}
|
|
1417
1412
|
try {
|
|
1413
|
+
if (typeof URL !== "undefined") {
|
|
1414
|
+
const URLStatic = URL;
|
|
1415
|
+
if (typeof URLStatic.parse === "function")
|
|
1416
|
+
return URLStatic.parse(trimmed) ?? URL_UNPARSEABLE;
|
|
1417
|
+
}
|
|
1418
1418
|
return new URL(trimmed);
|
|
1419
1419
|
} catch {
|
|
1420
1420
|
return URL_UNPARSEABLE;
|
|
@@ -1434,12 +1434,7 @@ function urlProtocolOk(url, protocol) {
|
|
|
1434
1434
|
function isValidIPv6(value) {
|
|
1435
1435
|
if (!ipv6Alphabet.test(value))
|
|
1436
1436
|
return false;
|
|
1437
|
-
|
|
1438
|
-
new URL(`http://[${value}]`);
|
|
1439
|
-
return true;
|
|
1440
|
-
} catch {
|
|
1441
|
-
return false;
|
|
1442
|
-
}
|
|
1437
|
+
return canParseURL(`http://[${value}]`);
|
|
1443
1438
|
}
|
|
1444
1439
|
function isValidCIDRv6(value) {
|
|
1445
1440
|
const parts = value.split("/");
|
|
@@ -1470,7 +1465,7 @@ function isValidBase64(data) {
|
|
|
1470
1465
|
}
|
|
1471
1466
|
}
|
|
1472
1467
|
function isValidBase64URL(data) {
|
|
1473
|
-
if (!
|
|
1468
|
+
if (!base64urlCharset.test(data))
|
|
1474
1469
|
return false;
|
|
1475
1470
|
const base64 = data.replace(/[-_]/g, (c) => c === "-" ? "+" : "/");
|
|
1476
1471
|
const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
|
|
@@ -1481,7 +1476,7 @@ function isLuhnAlgo(digits) {
|
|
|
1481
1476
|
let bit = 1;
|
|
1482
1477
|
let sum = 0;
|
|
1483
1478
|
while (length) {
|
|
1484
|
-
const value =
|
|
1479
|
+
const value = digits.charCodeAt(--length) - 48;
|
|
1485
1480
|
bit ^= 1;
|
|
1486
1481
|
sum += bit ? [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][value] : value;
|
|
1487
1482
|
}
|
|
@@ -1492,6 +1487,24 @@ function isValidCreditCard(input) {
|
|
|
1492
1487
|
return false;
|
|
1493
1488
|
return isLuhnAlgo(input.replace(CC_SANITIZE, ""));
|
|
1494
1489
|
}
|
|
1490
|
+
function isIso7064Mod97(iban2) {
|
|
1491
|
+
let remainder = 0;
|
|
1492
|
+
const len = iban2.length;
|
|
1493
|
+
for (let i = 4;i < len; i++) {
|
|
1494
|
+
const code = iban2.charCodeAt(i);
|
|
1495
|
+
remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
|
|
1496
|
+
}
|
|
1497
|
+
for (let i = 0;i < 4; i++) {
|
|
1498
|
+
const code = iban2.charCodeAt(i);
|
|
1499
|
+
remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
|
|
1500
|
+
}
|
|
1501
|
+
return remainder === 1;
|
|
1502
|
+
}
|
|
1503
|
+
function isValidIBAN(input) {
|
|
1504
|
+
if (!iban.test(input))
|
|
1505
|
+
return false;
|
|
1506
|
+
return isIso7064Mod97(input);
|
|
1507
|
+
}
|
|
1495
1508
|
function isValidJWT(token, algorithm = null) {
|
|
1496
1509
|
try {
|
|
1497
1510
|
const tokensParts = token.split(".");
|
|
@@ -1542,7 +1555,7 @@ function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
|
1542
1555
|
return;
|
|
1543
1556
|
}
|
|
1544
1557
|
if (result.value === undefined) {
|
|
1545
|
-
if (isPresent) {
|
|
1558
|
+
if (isPresent || optin === "defaulted" && !isOptionalOut) {
|
|
1546
1559
|
final.value[key] = undefined;
|
|
1547
1560
|
}
|
|
1548
1561
|
} else {
|
|
@@ -1569,14 +1582,20 @@ function normalizeDef(def) {
|
|
|
1569
1582
|
optionalKeys: new Set(okeys)
|
|
1570
1583
|
};
|
|
1571
1584
|
}
|
|
1572
|
-
function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
1585
|
+
function handleCatchall(proms, input, payload, ctx, def, inst, abortEarly) {
|
|
1573
1586
|
const unrecognized = [];
|
|
1574
1587
|
const keySet = def.keySet;
|
|
1575
1588
|
const _catchall = def.catchall._zod;
|
|
1576
1589
|
const t = _catchall.def.type;
|
|
1577
1590
|
const optin = _catchall.optin;
|
|
1578
1591
|
const optout = _catchall.optout;
|
|
1592
|
+
let seen = 0;
|
|
1579
1593
|
for (const key in input) {
|
|
1594
|
+
if (abortEarly && payload.issues.length !== seen) {
|
|
1595
|
+
if (aborted(payload, seen))
|
|
1596
|
+
break;
|
|
1597
|
+
seen = payload.issues.length;
|
|
1598
|
+
}
|
|
1580
1599
|
if (keySet.has(key))
|
|
1581
1600
|
continue;
|
|
1582
1601
|
if (key === "__proto__") {
|
|
@@ -1630,6 +1649,24 @@ function handleUnionResults(results, final, inst, ctx) {
|
|
|
1630
1649
|
});
|
|
1631
1650
|
return final;
|
|
1632
1651
|
}
|
|
1652
|
+
function discriminatorMap(def) {
|
|
1653
|
+
const map = new Map;
|
|
1654
|
+
for (const option of def.options) {
|
|
1655
|
+
const values = option._zod.propValues?.[def.discriminator];
|
|
1656
|
+
if (!values || values.size === 0)
|
|
1657
|
+
throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(option)}"`);
|
|
1658
|
+
for (const value of values) {
|
|
1659
|
+
if (map.has(value)) {
|
|
1660
|
+
if (value !== undefined)
|
|
1661
|
+
throw new Error(`Duplicate discriminator value "${String(value)}"`);
|
|
1662
|
+
map.set(value, null);
|
|
1663
|
+
} else {
|
|
1664
|
+
map.set(value, option);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
return map;
|
|
1669
|
+
}
|
|
1633
1670
|
function mergeValues(a, b) {
|
|
1634
1671
|
if (a === b) {
|
|
1635
1672
|
return { valid: true, data: a };
|
|
@@ -1793,11 +1830,10 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
1793
1830
|
payload.issues.push(issue(_iss));
|
|
1794
1831
|
}
|
|
1795
1832
|
}
|
|
1796
|
-
var $ZodType, toStandardResult = (r) => r.
|
|
1833
|
+
var $ZodType, toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value }, $ZodString, $ZodStringFormat, $ZodGUID, $ZodUUID, $ZodEmail, URL_BAD_FORMAT = 1, URL_UNPARSEABLE = 2, asciiTabOrNewline, $ZodURL, $ZodEmoji, $ZodNanoID, $ZodCUID, $ZodCUID2, $ZodULID, $ZodXID, $ZodKSUID, $ZodISODateTime, $ZodISODate, $ZodISOTime, $ZodISODuration, $ZodIPv4, ipv6Alphabet, $ZodIPv6, $ZodCIDRv4, $ZodCIDRv6, base64Charset, $ZodBase64, base64urlCharset, $ZodBase64URL, $ZodE164, CC_SANITIZE, $ZodJWT, $ZodNumber, $ZodNumberFormat, $ZodBoolean, $ZodUnknown, $ZodNever, $ZodArray, NO_SYMBOL_KEYS, $ZodObject, $ZodObjectJIT, $ZodUnion, $ZodDiscriminatedUnion, $ZodIntersection, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodTransform, $ZodOptional, $ZodExactOptional, $ZodNullable, $ZodDefault, $ZodPrefault, $ZodNonOptional, $ZodCatch, $ZodPipe, $ZodReadonly, $ZodCustom;
|
|
1797
1834
|
var init_schemas = __esm(() => {
|
|
1798
1835
|
init_checks();
|
|
1799
1836
|
init_core();
|
|
1800
|
-
init_parse();
|
|
1801
1837
|
init_regexes();
|
|
1802
1838
|
init_util();
|
|
1803
1839
|
init_versions();
|
|
@@ -1912,7 +1948,7 @@ var init_schemas = __esm(() => {
|
|
|
1912
1948
|
});
|
|
1913
1949
|
$ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
|
|
1914
1950
|
$ZodType.init(inst, def);
|
|
1915
|
-
inst._zod.pattern =
|
|
1951
|
+
inst._zod.pattern = def.pattern ?? anyString;
|
|
1916
1952
|
inst._zod.parse = (payload, _) => {
|
|
1917
1953
|
if (def.coerce)
|
|
1918
1954
|
try {
|
|
@@ -1967,7 +2003,7 @@ var init_schemas = __esm(() => {
|
|
|
1967
2003
|
inst._zod.check = (payload) => {
|
|
1968
2004
|
try {
|
|
1969
2005
|
const trimmed = payload.value.trim();
|
|
1970
|
-
const url =
|
|
2006
|
+
const url = validateURL(trimmed, def);
|
|
1971
2007
|
if (url === URL_BAD_FORMAT) {
|
|
1972
2008
|
payload.issues.push({
|
|
1973
2009
|
code: "invalid_format",
|
|
@@ -1989,6 +2025,10 @@ var init_schemas = __esm(() => {
|
|
|
1989
2025
|
});
|
|
1990
2026
|
return;
|
|
1991
2027
|
}
|
|
2028
|
+
if (url === true) {
|
|
2029
|
+
payload.value = stripTabAndNewline(trimmed);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
1992
2032
|
if (def.hostname && !urlHostnameOk(url, def.hostname)) {
|
|
1993
2033
|
payload.issues.push({
|
|
1994
2034
|
code: "invalid_format",
|
|
@@ -2057,12 +2097,6 @@ var init_schemas = __esm(() => {
|
|
|
2057
2097
|
$ZodISODateTime = /* @__PURE__ */ $constructor("$ZodISODateTime", (inst, def) => {
|
|
2058
2098
|
def.pattern ?? (def.pattern = datetime(def));
|
|
2059
2099
|
$ZodStringFormat.init(inst, def);
|
|
2060
|
-
if (def.local || def.precision === -1) {
|
|
2061
|
-
inst._zod.bag.laxFormat = true;
|
|
2062
|
-
inst._zod.onattach.push((s) => {
|
|
2063
|
-
s._zod.bag.laxFormat = true;
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
2100
|
});
|
|
2067
2101
|
$ZodISODate = /* @__PURE__ */ $constructor("$ZodISODate", (inst, def) => {
|
|
2068
2102
|
def.pattern ?? (def.pattern = date);
|
|
@@ -2079,13 +2113,11 @@ var init_schemas = __esm(() => {
|
|
|
2079
2113
|
$ZodIPv4 = /* @__PURE__ */ $constructor("$ZodIPv4", (inst, def) => {
|
|
2080
2114
|
def.pattern ?? (def.pattern = ipv4);
|
|
2081
2115
|
$ZodStringFormat.init(inst, def);
|
|
2082
|
-
inst._zod.bag.format = `ipv4`;
|
|
2083
2116
|
});
|
|
2084
2117
|
ipv6Alphabet = /^[0-9a-fA-F:.]+$/;
|
|
2085
2118
|
$ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
|
|
2086
2119
|
def.pattern ?? (def.pattern = ipv6);
|
|
2087
2120
|
$ZodStringFormat.init(inst, def);
|
|
2088
|
-
inst._zod.bag.format = `ipv6`;
|
|
2089
2121
|
inst._zod.check = (payload) => {
|
|
2090
2122
|
if (!isValidIPv6(payload.value)) {
|
|
2091
2123
|
payload.issues.push({
|
|
@@ -2117,10 +2149,10 @@ var init_schemas = __esm(() => {
|
|
|
2117
2149
|
}
|
|
2118
2150
|
};
|
|
2119
2151
|
});
|
|
2152
|
+
base64Charset = /^[0-9a-zA-Z+/]*={0,2}$/;
|
|
2120
2153
|
$ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
2121
|
-
def.pattern ?? (def.pattern =
|
|
2154
|
+
def.pattern ?? (def.pattern = base64Charset);
|
|
2122
2155
|
$ZodStringFormat.init(inst, def);
|
|
2123
|
-
inst._zod.bag.contentEncoding = "base64";
|
|
2124
2156
|
inst._zod.check = (payload) => {
|
|
2125
2157
|
if (isValidBase64(payload.value))
|
|
2126
2158
|
return;
|
|
@@ -2133,10 +2165,10 @@ var init_schemas = __esm(() => {
|
|
|
2133
2165
|
});
|
|
2134
2166
|
};
|
|
2135
2167
|
});
|
|
2168
|
+
base64urlCharset = /^[A-Za-z0-9_-]*$/;
|
|
2136
2169
|
$ZodBase64URL = /* @__PURE__ */ $constructor("$ZodBase64URL", (inst, def) => {
|
|
2137
|
-
def.pattern ?? (def.pattern =
|
|
2170
|
+
def.pattern ?? (def.pattern = base64urlCharset);
|
|
2138
2171
|
$ZodStringFormat.init(inst, def);
|
|
2139
|
-
inst._zod.bag.contentEncoding = "base64url";
|
|
2140
2172
|
inst._zod.check = (payload) => {
|
|
2141
2173
|
if (isValidBase64URL(payload.value))
|
|
2142
2174
|
return;
|
|
@@ -2170,7 +2202,7 @@ var init_schemas = __esm(() => {
|
|
|
2170
2202
|
});
|
|
2171
2203
|
$ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
2172
2204
|
$ZodType.init(inst, def);
|
|
2173
|
-
inst._zod.pattern =
|
|
2205
|
+
inst._zod.pattern = number;
|
|
2174
2206
|
inst._zod.parse = (payload, _ctx) => {
|
|
2175
2207
|
if (def.coerce)
|
|
2176
2208
|
try {
|
|
@@ -2248,6 +2280,7 @@ var init_schemas = __esm(() => {
|
|
|
2248
2280
|
}
|
|
2249
2281
|
payload.value = memo ? memo.alloc(inst, payload, Array(input.length), ctx) : Array(input.length);
|
|
2250
2282
|
const proms = [];
|
|
2283
|
+
const abortEarly = ctx?.abortEarly;
|
|
2251
2284
|
for (let i = 0;i < input.length; i++) {
|
|
2252
2285
|
const item = input[i];
|
|
2253
2286
|
const result = def.element._zod.run({
|
|
@@ -2258,6 +2291,8 @@ var init_schemas = __esm(() => {
|
|
|
2258
2291
|
proms.push(result.then((result) => handleArrayResult(result, payload, i)));
|
|
2259
2292
|
} else {
|
|
2260
2293
|
handleArrayResult(result, payload, i);
|
|
2294
|
+
if (abortEarly && result.issues.length !== 0 && aborted(result))
|
|
2295
|
+
break;
|
|
2261
2296
|
}
|
|
2262
2297
|
}
|
|
2263
2298
|
if (proms.length) {
|
|
@@ -2267,23 +2302,19 @@ var init_schemas = __esm(() => {
|
|
|
2267
2302
|
};
|
|
2268
2303
|
});
|
|
2269
2304
|
NO_SYMBOL_KEYS = [];
|
|
2270
|
-
propShapes = new WeakMap;
|
|
2271
2305
|
$ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
2272
2306
|
$ZodType.init(inst, def);
|
|
2273
2307
|
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
return newSh;
|
|
2285
|
-
}
|
|
2286
|
-
});
|
|
2308
|
+
const sh = desc?.get ? desc.get.raw : def.shape ?? {};
|
|
2309
|
+
if (sh) {
|
|
2310
|
+
const get = () => {
|
|
2311
|
+
const newSh = { ...sh };
|
|
2312
|
+
Object.defineProperty(def, "shape", { value: newSh });
|
|
2313
|
+
get.raw = newSh;
|
|
2314
|
+
return newSh;
|
|
2315
|
+
};
|
|
2316
|
+
get.raw = sh;
|
|
2317
|
+
Object.defineProperty(def, "shape", { get });
|
|
2287
2318
|
}
|
|
2288
2319
|
const _normalized = cached(() => normalizeDef(def));
|
|
2289
2320
|
defineLazyInternal(inst, "propValues", (zod) => {
|
|
@@ -2323,7 +2354,14 @@ var init_schemas = __esm(() => {
|
|
|
2323
2354
|
payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};
|
|
2324
2355
|
const proms = [];
|
|
2325
2356
|
const shape = value.shape;
|
|
2357
|
+
const abortEarly = ctx?.abortEarly;
|
|
2358
|
+
let seen = payload.issues.length;
|
|
2326
2359
|
for (const key of value.allKeys) {
|
|
2360
|
+
if (abortEarly && payload.issues.length !== seen) {
|
|
2361
|
+
if (aborted(payload, seen))
|
|
2362
|
+
break;
|
|
2363
|
+
seen = payload.issues.length;
|
|
2364
|
+
}
|
|
2327
2365
|
if (key === "__proto__")
|
|
2328
2366
|
continue;
|
|
2329
2367
|
const el = shape[key];
|
|
@@ -2339,7 +2377,7 @@ var init_schemas = __esm(() => {
|
|
|
2339
2377
|
if (!catchall) {
|
|
2340
2378
|
return proms.length ? Promise.all(proms).then(() => payload) : payload;
|
|
2341
2379
|
}
|
|
2342
|
-
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst);
|
|
2380
|
+
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst, abortEarly === true);
|
|
2343
2381
|
};
|
|
2344
2382
|
});
|
|
2345
2383
|
$ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => {
|
|
@@ -2353,10 +2391,16 @@ var init_schemas = __esm(() => {
|
|
|
2353
2391
|
const doc = new Doc(["payload", "ctx"], { shape, inst, memo, syms });
|
|
2354
2392
|
const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
2355
2393
|
const prefixStr = (id, k) => `
|
|
2394
|
+
let ${id}_ab = false;
|
|
2356
2395
|
for (let i = 0; i < ${id}.issues.length; i++) {
|
|
2357
2396
|
const iss = ${id}.issues[i];
|
|
2358
2397
|
iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
|
|
2359
2398
|
payload.issues.push(iss);
|
|
2399
|
+
if (iss.continue !== true) ${id}_ab = true;
|
|
2400
|
+
}
|
|
2401
|
+
if (${id}_ab && ctx && ctx.abortEarly) {
|
|
2402
|
+
payload.value = newResult;
|
|
2403
|
+
return payload;
|
|
2360
2404
|
}`;
|
|
2361
2405
|
doc.write(`const input = payload.value;`);
|
|
2362
2406
|
const ids = Object.create(null);
|
|
@@ -2402,6 +2446,10 @@ var init_schemas = __esm(() => {
|
|
|
2402
2446
|
input: undefined,
|
|
2403
2447
|
path: [${k}]
|
|
2404
2448
|
});
|
|
2449
|
+
if (ctx && ctx.abortEarly) {
|
|
2450
|
+
payload.value = newResult;
|
|
2451
|
+
return payload;
|
|
2452
|
+
}
|
|
2405
2453
|
}
|
|
2406
2454
|
|
|
2407
2455
|
if (${id}_present) {
|
|
@@ -2413,16 +2461,16 @@ var init_schemas = __esm(() => {
|
|
|
2413
2461
|
doc.write(`
|
|
2414
2462
|
if (${id}.issues.length) {${prefixStr(id, k)}
|
|
2415
2463
|
}
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
}
|
|
2464
|
+
`);
|
|
2465
|
+
if (optin === "defaulted") {
|
|
2466
|
+
doc.write(`newResult[${k}] = ${id}.value;`);
|
|
2467
|
+
} else {
|
|
2468
|
+
doc.write(`
|
|
2469
|
+
if (${id}.value !== undefined || ${isPresent}) {
|
|
2422
2470
|
newResult[${k}] = ${id}.value;
|
|
2423
2471
|
}
|
|
2424
|
-
|
|
2425
2472
|
`);
|
|
2473
|
+
}
|
|
2426
2474
|
}
|
|
2427
2475
|
}
|
|
2428
2476
|
doc.write(`payload.value = newResult;`);
|
|
@@ -2454,7 +2502,7 @@ var init_schemas = __esm(() => {
|
|
|
2454
2502
|
payload = fastpass(payload, ctx);
|
|
2455
2503
|
if (!catchall)
|
|
2456
2504
|
return payload;
|
|
2457
|
-
return handleCatchall([], input, payload, ctx, value, inst);
|
|
2505
|
+
return handleCatchall([], input, payload, ctx, value, inst, ctx?.abortEarly === true);
|
|
2458
2506
|
}
|
|
2459
2507
|
return superParse(payload, ctx);
|
|
2460
2508
|
};
|
|
@@ -2510,10 +2558,13 @@ var init_schemas = __esm(() => {
|
|
|
2510
2558
|
const _super = inst._zod.parse;
|
|
2511
2559
|
defineLazyInternal(inst, "propValues", (zod) => {
|
|
2512
2560
|
const propValues = {};
|
|
2561
|
+
let undefinedCount = 0;
|
|
2513
2562
|
for (const option of zod.def.options) {
|
|
2514
2563
|
const pv = option._zod.propValues;
|
|
2515
2564
|
if (!pv || Object.keys(pv).length === 0)
|
|
2516
2565
|
throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
|
|
2566
|
+
if (pv[zod.def.discriminator]?.has(undefined))
|
|
2567
|
+
undefinedCount++;
|
|
2517
2568
|
for (const [k, v] of Object.entries(pv)) {
|
|
2518
2569
|
if (!Object.prototype.hasOwnProperty.call(propValues, k)) {
|
|
2519
2570
|
assignProp(propValues, k, new Set);
|
|
@@ -2523,30 +2574,17 @@ var init_schemas = __esm(() => {
|
|
|
2523
2574
|
}
|
|
2524
2575
|
}
|
|
2525
2576
|
}
|
|
2577
|
+
if (!zod.def.unionFallback && undefinedCount > 1)
|
|
2578
|
+
propValues[zod.def.discriminator]?.delete(undefined);
|
|
2526
2579
|
return propValues;
|
|
2527
2580
|
});
|
|
2528
2581
|
def.options.forEach((option, i) => {
|
|
2529
|
-
const propShape =
|
|
2582
|
+
const propShape = rawShape(option._zod.def);
|
|
2530
2583
|
if (propShape && !Object.prototype.hasOwnProperty.call(propShape, def.discriminator)) {
|
|
2531
2584
|
throw new Error(`Invalid discriminated union option at index "${i}"`);
|
|
2532
2585
|
}
|
|
2533
2586
|
});
|
|
2534
|
-
const disc = cached(() =>
|
|
2535
|
-
const opts = def.options;
|
|
2536
|
-
const map = new Map;
|
|
2537
|
-
for (const o of opts) {
|
|
2538
|
-
const values = o._zod.propValues?.[def.discriminator];
|
|
2539
|
-
if (!values || values.size === 0)
|
|
2540
|
-
throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(o)}"`);
|
|
2541
|
-
for (const v of values) {
|
|
2542
|
-
if (map.has(v)) {
|
|
2543
|
-
throw new Error(`Duplicate discriminator value "${String(v)}"`);
|
|
2544
|
-
}
|
|
2545
|
-
map.set(v, o);
|
|
2546
|
-
}
|
|
2547
|
-
}
|
|
2548
|
-
return map;
|
|
2549
|
-
});
|
|
2587
|
+
const disc = cached(() => discriminatorMap(def));
|
|
2550
2588
|
inst._zod.parse = (payload, ctx) => {
|
|
2551
2589
|
const input = payload.value;
|
|
2552
2590
|
if (!isObject(input)) {
|
|
@@ -2558,8 +2596,9 @@ var init_schemas = __esm(() => {
|
|
|
2558
2596
|
});
|
|
2559
2597
|
return payload;
|
|
2560
2598
|
}
|
|
2561
|
-
const
|
|
2562
|
-
|
|
2599
|
+
const value = input?.[def.discriminator];
|
|
2600
|
+
const opt = disc.value.get(value);
|
|
2601
|
+
if (opt && (value !== undefined || ctx.direction !== "backward")) {
|
|
2563
2602
|
return opt._zod.run(payload, ctx);
|
|
2564
2603
|
}
|
|
2565
2604
|
if (def.unionFallback || ctx.direction === "backward") {
|
|
@@ -2570,7 +2609,7 @@ var init_schemas = __esm(() => {
|
|
|
2570
2609
|
errors: [],
|
|
2571
2610
|
note: "No matching discriminator",
|
|
2572
2611
|
discriminator: def.discriminator,
|
|
2573
|
-
options: Array.from(disc.value.keys()),
|
|
2612
|
+
options: Array.from(disc.value.keys()).filter((value) => disc.value.get(value) !== null),
|
|
2574
2613
|
input,
|
|
2575
2614
|
path: [def.discriminator],
|
|
2576
2615
|
inst
|
|
@@ -2753,8 +2792,10 @@ var init_schemas = __esm(() => {
|
|
|
2753
2792
|
const values = getEnumValues(def.entries);
|
|
2754
2793
|
const valuesSet = new Set(values);
|
|
2755
2794
|
inst._zod.values = valuesSet;
|
|
2756
|
-
|
|
2757
|
-
|
|
2795
|
+
defineLazyInternal(inst, "pattern", (zod) => {
|
|
2796
|
+
const patternValues = getEnumValues(zod.def.entries).filter((k) => propertyKeyTypes.has(typeof k));
|
|
2797
|
+
return new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join("|")})$` : "^[^\\s\\S]$");
|
|
2798
|
+
});
|
|
2758
2799
|
inst._zod.parse = (payload, _ctx) => {
|
|
2759
2800
|
const input = payload.value;
|
|
2760
2801
|
if (valuesSet.has(input)) {
|
|
@@ -2773,7 +2814,10 @@ var init_schemas = __esm(() => {
|
|
|
2773
2814
|
$ZodType.init(inst, def);
|
|
2774
2815
|
const values = new Set(def.values);
|
|
2775
2816
|
inst._zod.values = values;
|
|
2776
|
-
inst
|
|
2817
|
+
defineLazyInternal(inst, "pattern", (zod) => {
|
|
2818
|
+
const vals = zod.def.values;
|
|
2819
|
+
return new RegExp(vals.length ? `^(${vals.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$` : "^[^\\s\\S]$");
|
|
2820
|
+
});
|
|
2777
2821
|
inst._zod.parse = (payload, _ctx) => {
|
|
2778
2822
|
const input = payload.value;
|
|
2779
2823
|
if (values.has(input)) {
|
|
@@ -2980,27 +3024,49 @@ var init_schemas = __esm(() => {
|
|
|
2980
3024
|
});
|
|
2981
3025
|
|
|
2982
3026
|
// node_modules/zod/v4/core/memoizer.js
|
|
3027
|
+
function isRef(value) {
|
|
3028
|
+
return value !== null && typeof value === "object";
|
|
3029
|
+
}
|
|
2983
3030
|
function cloneIssues(issues) {
|
|
2984
3031
|
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
|
|
2985
3032
|
}
|
|
2986
|
-
function isRecursive(inst, stack) {
|
|
3033
|
+
function isRecursive(inst, stack, resolve) {
|
|
2987
3034
|
const cached = recursive.get(inst);
|
|
2988
3035
|
if (cached !== undefined)
|
|
2989
|
-
return cached;
|
|
3036
|
+
return cached ? PROVEN : NONE;
|
|
2990
3037
|
if (stack.has(inst))
|
|
2991
|
-
return
|
|
3038
|
+
return PROVEN;
|
|
2992
3039
|
stack.add(inst);
|
|
2993
|
-
let result =
|
|
3040
|
+
let result = NONE;
|
|
2994
3041
|
const check = (child) => {
|
|
2995
|
-
if (
|
|
2996
|
-
|
|
3042
|
+
if (result !== PROVEN && child?._zod) {
|
|
3043
|
+
const answer = isRecursive(child, stack, resolve);
|
|
3044
|
+
if (answer > result)
|
|
3045
|
+
result = answer;
|
|
3046
|
+
}
|
|
3047
|
+
};
|
|
3048
|
+
const shape = (sh, spread) => {
|
|
3049
|
+
let answer = NONE;
|
|
3050
|
+
for (const key of Reflect.ownKeys(sh)) {
|
|
3051
|
+
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
3052
|
+
if (spread && !desc.enumerable)
|
|
3053
|
+
continue;
|
|
3054
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
|
|
3055
|
+
if (child > answer)
|
|
3056
|
+
answer = child;
|
|
3057
|
+
}
|
|
3058
|
+
return answer;
|
|
3059
|
+
};
|
|
3060
|
+
const merge = (answer) => {
|
|
3061
|
+
if (answer > result)
|
|
3062
|
+
result = answer;
|
|
2997
3063
|
};
|
|
2998
3064
|
const def = inst._zod.def;
|
|
2999
3065
|
const kind = def.type;
|
|
3000
3066
|
switch (kind) {
|
|
3001
3067
|
case "object": {
|
|
3002
|
-
|
|
3003
|
-
|
|
3068
|
+
const raw = rawShape(def);
|
|
3069
|
+
merge(raw ? shape(raw, true) : ASSUMED);
|
|
3004
3070
|
check(def.catchall);
|
|
3005
3071
|
break;
|
|
3006
3072
|
}
|
|
@@ -3047,9 +3113,11 @@ function isRecursive(inst, stack) {
|
|
|
3047
3113
|
check(def.input);
|
|
3048
3114
|
check(def.output);
|
|
3049
3115
|
break;
|
|
3050
|
-
case "lazy":
|
|
3051
|
-
|
|
3116
|
+
case "lazy": {
|
|
3117
|
+
const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : undefined);
|
|
3118
|
+
merge(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
3052
3119
|
break;
|
|
3120
|
+
}
|
|
3053
3121
|
case "template_literal":
|
|
3054
3122
|
case "string":
|
|
3055
3123
|
case "number":
|
|
@@ -3088,16 +3156,20 @@ function isRecursive(inst, stack) {
|
|
|
3088
3156
|
}
|
|
3089
3157
|
}
|
|
3090
3158
|
stack.delete(inst);
|
|
3091
|
-
|
|
3092
|
-
|
|
3159
|
+
return settle(inst, result);
|
|
3160
|
+
}
|
|
3161
|
+
function settle(inst, answer) {
|
|
3162
|
+
if (answer !== ASSUMED)
|
|
3163
|
+
recursive.set(inst, answer === PROVEN);
|
|
3164
|
+
return answer;
|
|
3093
3165
|
}
|
|
3094
3166
|
function isRecursiveSchema(inst) {
|
|
3095
|
-
return isRecursive(inst, new Set);
|
|
3167
|
+
return isRecursive(inst, new Set, true) !== NONE;
|
|
3096
3168
|
}
|
|
3097
3169
|
function bucketFor(state, inst) {
|
|
3098
3170
|
let bucket = state.buckets.get(inst);
|
|
3099
3171
|
if (!bucket) {
|
|
3100
|
-
bucket = new
|
|
3172
|
+
bucket = new WeakMap;
|
|
3101
3173
|
state.buckets.set(inst, bucket);
|
|
3102
3174
|
}
|
|
3103
3175
|
return bucket;
|
|
@@ -3107,10 +3179,11 @@ function memoizer() {
|
|
|
3107
3179
|
}
|
|
3108
3180
|
function isBackEdge(ctx, value) {
|
|
3109
3181
|
const backEdges = ctx[STATE]?.backEdges;
|
|
3110
|
-
return backEdges !== undefined && value
|
|
3182
|
+
return backEdges !== undefined && isRef(value) && backEdges.has(value);
|
|
3111
3183
|
}
|
|
3112
|
-
var $ZodCyclicError, STATE = "~memo", NO_ISSUES, recursive, handoff, open, memo;
|
|
3184
|
+
var $ZodCyclicError, STATE = "~memo", NO_ISSUES, recursive, NONE = 0, ASSUMED = 1, PROVEN = 2, handoff, open, memo;
|
|
3113
3185
|
var init_memoizer = __esm(() => {
|
|
3186
|
+
init_util();
|
|
3114
3187
|
$ZodCyclicError = class $ZodCyclicError extends Error {
|
|
3115
3188
|
constructor() {
|
|
3116
3189
|
super(`Cannot parse a reference cycle that closes through a transform`);
|
|
@@ -3149,6 +3222,7 @@ var init_memoizer = __esm(() => {
|
|
|
3149
3222
|
attach(inst) {
|
|
3150
3223
|
var _a;
|
|
3151
3224
|
let isRecursiveInst;
|
|
3225
|
+
let rechecked = false;
|
|
3152
3226
|
let lastCtx;
|
|
3153
3227
|
let lastBucket;
|
|
3154
3228
|
(_a = inst._zod).deferred ?? (_a.deferred = []);
|
|
@@ -3156,20 +3230,24 @@ var init_memoizer = __esm(() => {
|
|
|
3156
3230
|
const base = inst._zod.parse;
|
|
3157
3231
|
const wrapped = (payload, ctx) => {
|
|
3158
3232
|
if (isRecursiveInst === undefined) {
|
|
3159
|
-
|
|
3160
|
-
if (
|
|
3233
|
+
const walked = isRecursive(inst, new Set, false);
|
|
3234
|
+
if (walked === NONE) {
|
|
3161
3235
|
inst._zod.parse = base;
|
|
3162
3236
|
if (inst._zod.run === wrapped)
|
|
3163
3237
|
inst._zod.run = base;
|
|
3164
3238
|
return base(payload, ctx);
|
|
3165
3239
|
}
|
|
3240
|
+
if (walked === PROVEN || rechecked)
|
|
3241
|
+
isRecursiveInst = true;
|
|
3242
|
+
else
|
|
3243
|
+
rechecked = true;
|
|
3166
3244
|
}
|
|
3167
3245
|
const input = payload.value;
|
|
3168
|
-
if (input
|
|
3246
|
+
if (!isRef(input))
|
|
3169
3247
|
return base(payload, ctx);
|
|
3170
3248
|
let state = ctx[STATE];
|
|
3171
3249
|
if (!state) {
|
|
3172
|
-
state = { buckets: new
|
|
3250
|
+
state = { buckets: new WeakMap, backEdges: undefined };
|
|
3173
3251
|
ctx[STATE] = state;
|
|
3174
3252
|
}
|
|
3175
3253
|
let bucket;
|
|
@@ -3188,7 +3266,7 @@ var init_memoizer = __esm(() => {
|
|
|
3188
3266
|
payload.issues.push(...cloneIssues(hit.issues));
|
|
3189
3267
|
} else {
|
|
3190
3268
|
payload.memo = true;
|
|
3191
|
-
state.backEdges ?? (state.backEdges = new
|
|
3269
|
+
state.backEdges ?? (state.backEdges = new WeakSet);
|
|
3192
3270
|
state.backEdges.add(hit.value);
|
|
3193
3271
|
}
|
|
3194
3272
|
return payload;
|
|
@@ -3262,7 +3340,9 @@ var error = () => {
|
|
|
3262
3340
|
base64url: "base64url-encoded string",
|
|
3263
3341
|
json_string: "JSON string",
|
|
3264
3342
|
e164: "E.164 number",
|
|
3343
|
+
currency_code: "currency code",
|
|
3265
3344
|
credit_card: "credit card number",
|
|
3345
|
+
iban: "IBAN",
|
|
3266
3346
|
jwt: "JWT",
|
|
3267
3347
|
template_literal: "input"
|
|
3268
3348
|
};
|
|
@@ -3405,38 +3485,46 @@ function compileValidator(schema, parser) {
|
|
|
3405
3485
|
function compile(schema, options) {
|
|
3406
3486
|
try {
|
|
3407
3487
|
const parser = compileFn(schema);
|
|
3408
|
-
const
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
const wrapped = (payload, ctx) => {
|
|
3412
|
-
if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
|
|
3413
|
-
return originalRun(payload, ctx);
|
|
3414
|
-
}
|
|
3415
|
-
if (ctx && isBackEdge(ctx, payload.value)) {
|
|
3416
|
-
return originalRun(payload, ctx);
|
|
3417
|
-
}
|
|
3418
|
-
const out = parser(payload.value);
|
|
3419
|
-
if (out !== INVALID) {
|
|
3420
|
-
payload.value = out;
|
|
3421
|
-
return payload;
|
|
3422
|
-
}
|
|
3423
|
-
if (ctx)
|
|
3424
|
-
ctx[FALLBACK_FLAG] = true;
|
|
3425
|
-
return originalRun(payload, ctx);
|
|
3426
|
-
};
|
|
3427
|
-
wrapped.__originalRun = originalRun;
|
|
3428
|
-
clone2._zod.bag.fallbackRun = originalRun;
|
|
3429
|
-
clone2._zod.bag.validator = compileValidator(schema, parser);
|
|
3430
|
-
clone2._zod.run = wrapped;
|
|
3431
|
-
if (!liveRun.__originalRun)
|
|
3432
|
-
installCompiledUserMethods(clone2, schema, parser);
|
|
3433
|
-
return clone2;
|
|
3488
|
+
const clone = withParser(schema, parser);
|
|
3489
|
+
clone._zod.bag.validator = compileValidator(schema, parser);
|
|
3490
|
+
return clone;
|
|
3434
3491
|
} catch (err) {
|
|
3435
3492
|
if (options?.strict)
|
|
3436
3493
|
throw err;
|
|
3437
3494
|
return schema;
|
|
3438
3495
|
}
|
|
3439
3496
|
}
|
|
3497
|
+
function withParser(schema, parser) {
|
|
3498
|
+
if (isRecursiveSchema(schema)) {
|
|
3499
|
+
throw new ZodCompileUnsupportedError("a schema whose subtree contains a reference cycle");
|
|
3500
|
+
}
|
|
3501
|
+
const clone2 = clone(schema);
|
|
3502
|
+
const liveRun = schema._zod.run;
|
|
3503
|
+
const originalRun = liveRun.__originalRun ?? liveRun;
|
|
3504
|
+
const wrapped = (payload, ctx) => {
|
|
3505
|
+
if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
|
|
3506
|
+
return originalRun(payload, ctx);
|
|
3507
|
+
}
|
|
3508
|
+
if (ctx && isBackEdge(ctx, payload.value)) {
|
|
3509
|
+
return originalRun(payload, ctx);
|
|
3510
|
+
}
|
|
3511
|
+
const out = parser(payload.value);
|
|
3512
|
+
if (out !== INVALID) {
|
|
3513
|
+
payload.value = out;
|
|
3514
|
+
return payload;
|
|
3515
|
+
}
|
|
3516
|
+
if (ctx)
|
|
3517
|
+
ctx[FALLBACK_FLAG] = true;
|
|
3518
|
+
return originalRun(payload, ctx);
|
|
3519
|
+
};
|
|
3520
|
+
wrapped.__originalRun = originalRun;
|
|
3521
|
+
clone2._zod.bag.fallbackRun = originalRun;
|
|
3522
|
+
clone2._zod.bag.validator = parser;
|
|
3523
|
+
clone2._zod.run = wrapped;
|
|
3524
|
+
if (!liveRun.__originalRun)
|
|
3525
|
+
installCompiledUserMethods(clone2, schema, parser);
|
|
3526
|
+
return clone2;
|
|
3527
|
+
}
|
|
3440
3528
|
function installCompiledUserMethods(target, source, parser) {
|
|
3441
3529
|
const targetAny = target;
|
|
3442
3530
|
const sourceAny = source;
|
|
@@ -3472,7 +3560,8 @@ function compileFn(schema, options) {
|
|
|
3472
3560
|
const ctx = {
|
|
3473
3561
|
constants: new Map,
|
|
3474
3562
|
constantCounter: 0,
|
|
3475
|
-
varCounter: 0
|
|
3563
|
+
varCounter: 0,
|
|
3564
|
+
definite: true
|
|
3476
3565
|
};
|
|
3477
3566
|
const doc = new Doc(["input"]);
|
|
3478
3567
|
const outputAccessor = generateCheck(doc, ctx, schema, "input", !options?.assertOnly);
|
|
@@ -3497,6 +3586,7 @@ ${code}
|
|
|
3497
3586
|
if (options?.debug) {
|
|
3498
3587
|
fn.code = fullCode;
|
|
3499
3588
|
}
|
|
3589
|
+
fn.definite = ctx.definite;
|
|
3500
3590
|
return fn;
|
|
3501
3591
|
}
|
|
3502
3592
|
function addConstant(ctx, value) {
|
|
@@ -3508,6 +3598,10 @@ function addConstant(ctx, value) {
|
|
|
3508
3598
|
ctx.constants.set(name, value);
|
|
3509
3599
|
return name;
|
|
3510
3600
|
}
|
|
3601
|
+
function addUserConstant(ctx, fn) {
|
|
3602
|
+
ctx.definite = false;
|
|
3603
|
+
return addConstant(ctx, fn);
|
|
3604
|
+
}
|
|
3511
3605
|
function newVar(ctx) {
|
|
3512
3606
|
return `v${ctx.varCounter++}`;
|
|
3513
3607
|
}
|
|
@@ -3540,6 +3634,7 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
3540
3634
|
}
|
|
3541
3635
|
}
|
|
3542
3636
|
function emitRuntimeIsland(doc, ctx, schema, accessor) {
|
|
3637
|
+
ctx.definite = false;
|
|
3543
3638
|
const schemaConst = addConstant(ctx, schema);
|
|
3544
3639
|
const runConst = addConstant(ctx, runtimeRun);
|
|
3545
3640
|
const outVar = newVar(ctx);
|
|
@@ -3612,6 +3707,9 @@ function generateChecks(doc, ctx, schema, accessor) {
|
|
|
3612
3707
|
case "property":
|
|
3613
3708
|
generatePropertyCheck(doc, ctx, def, currentAccessor);
|
|
3614
3709
|
break;
|
|
3710
|
+
case "properties":
|
|
3711
|
+
generatePropertiesChecks(doc, ctx, def, currentAccessor);
|
|
3712
|
+
break;
|
|
3615
3713
|
case "overwrite": {
|
|
3616
3714
|
const newAccessor = newVar(ctx);
|
|
3617
3715
|
generateOverwriteCheck(doc, ctx, check, currentAccessor, newAccessor);
|
|
@@ -3717,6 +3815,19 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
|
|
|
3717
3815
|
doc.write(`if (!${mimeSet}.has(${accessor}.type)) return INVALID;`);
|
|
3718
3816
|
}
|
|
3719
3817
|
}
|
|
3818
|
+
function generatePropertiesChecks(doc, ctx, def, accessor) {
|
|
3819
|
+
if (def.when) {
|
|
3820
|
+
throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
|
|
3821
|
+
}
|
|
3822
|
+
doc.write(`if (${accessor} == null) return INVALID;`);
|
|
3823
|
+
const shape = def.shape;
|
|
3824
|
+
for (const key of Reflect.ownKeys(shape)) {
|
|
3825
|
+
const keyExpr = typeof key === "symbol" ? addConstant(ctx, key) : esc(key);
|
|
3826
|
+
const inputVar = newVar(ctx);
|
|
3827
|
+
doc.write(`const ${inputVar} = ${accessor}[${keyExpr}];`);
|
|
3828
|
+
compileChild(doc, ctx, shape[key], inputVar, false);
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3720
3831
|
function generatePropertyCheck(doc, ctx, def, accessor) {
|
|
3721
3832
|
const propAccessor = `${accessor}[${JSON.stringify(def.property)}]`;
|
|
3722
3833
|
generateCheck(doc, ctx, def.schema, propAccessor);
|
|
@@ -3744,7 +3855,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
|
|
|
3744
3855
|
if (isAsyncFunction(def.fn)) {
|
|
3745
3856
|
throw new ZodCompileAsyncError("z.compile: async .refine() predicates are not supported");
|
|
3746
3857
|
}
|
|
3747
|
-
const fnConst =
|
|
3858
|
+
const fnConst = addUserConstant(ctx, def.fn);
|
|
3748
3859
|
const throwAsyncConst = addConstant(ctx, throwAsync);
|
|
3749
3860
|
const resVar = newVar(ctx);
|
|
3750
3861
|
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
|
|
@@ -3764,7 +3875,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
|
|
|
3764
3875
|
throwAsync();
|
|
3765
3876
|
return fakePayload.issues.length === 0 ? fakePayload.value : INVALID;
|
|
3766
3877
|
};
|
|
3767
|
-
const helperConst =
|
|
3878
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
3768
3879
|
const outVar = newVar(ctx);
|
|
3769
3880
|
doc.write(`const ${outVar} = ${helperConst}(${accessor});`);
|
|
3770
3881
|
doc.write(`if (${outVar} === INVALID) return INVALID;`);
|
|
@@ -3772,7 +3883,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
|
|
|
3772
3883
|
}
|
|
3773
3884
|
throw new ZodCompileUnsupportedError("custom check without a predicate or check function");
|
|
3774
3885
|
}
|
|
3775
|
-
function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
3886
|
+
function generateStringFormatCheck(doc, ctx, def, accessor, needsValue = true) {
|
|
3776
3887
|
const fmt = def.format;
|
|
3777
3888
|
if (fmt === "base64") {
|
|
3778
3889
|
const validator = addConstant(ctx, isValidBase64);
|
|
@@ -3805,9 +3916,14 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
|
3805
3916
|
doc.write(`if (!${validator}(${accessor})) return INVALID;`);
|
|
3806
3917
|
return accessor;
|
|
3807
3918
|
}
|
|
3919
|
+
if (fmt === "iban") {
|
|
3920
|
+
const validator = addConstant(ctx, isValidIBAN);
|
|
3921
|
+
doc.write(`if (!${validator}(${accessor})) return INVALID;`);
|
|
3922
|
+
return accessor;
|
|
3923
|
+
}
|
|
3808
3924
|
const formatDef = def;
|
|
3809
3925
|
if (fmt === "url" || fmt === "httpurl" || formatDef.normalize || formatDef.hostname !== undefined || formatDef.protocol !== undefined) {
|
|
3810
|
-
const parseConst = addConstant(ctx,
|
|
3926
|
+
const parseConst = addConstant(ctx, validateURL);
|
|
3811
3927
|
const defConst = addConstant(ctx, def);
|
|
3812
3928
|
const trimVar = newVar(ctx);
|
|
3813
3929
|
const urlVar = newVar(ctx);
|
|
@@ -3822,6 +3938,8 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
|
|
|
3822
3938
|
const protocolConst = addConstant(ctx, urlProtocolOk);
|
|
3823
3939
|
doc.write(`if (!${protocolConst}(${urlVar}, ${defConst}.protocol)) return INVALID;`);
|
|
3824
3940
|
}
|
|
3941
|
+
if (!needsValue)
|
|
3942
|
+
return null;
|
|
3825
3943
|
const outputVar = newVar(ctx);
|
|
3826
3944
|
const outputExpr = formatDef.normalize ? `${urlVar}.href` : `${addConstant(ctx, stripTabAndNewline)}(${trimVar})`;
|
|
3827
3945
|
doc.write(`const ${outputVar} = ${outputExpr};`);
|
|
@@ -3880,7 +3998,7 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
3880
3998
|
let typeAccessor;
|
|
3881
3999
|
switch (type) {
|
|
3882
4000
|
case "string":
|
|
3883
|
-
typeAccessor = generateStringCheck(doc, ctx, schema, accessor);
|
|
4001
|
+
typeAccessor = generateStringCheck(doc, ctx, schema, accessor, buildsValue);
|
|
3884
4002
|
break;
|
|
3885
4003
|
case "number":
|
|
3886
4004
|
typeAccessor = generateNumberCheck(doc, schema, accessor);
|
|
@@ -4000,12 +4118,12 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
4000
4118
|
return null;
|
|
4001
4119
|
return generateChecks(doc, ctx, schema, typeAccessor);
|
|
4002
4120
|
}
|
|
4003
|
-
function generateStringCheck(doc, ctx, schema, accessor) {
|
|
4121
|
+
function generateStringCheck(doc, ctx, schema, accessor, needsValue = true) {
|
|
4004
4122
|
doc.write(`if (typeof ${accessor} !== "string") return INVALID;`);
|
|
4005
4123
|
const def = schema._zod.def;
|
|
4006
4124
|
if (def.format === undefined)
|
|
4007
4125
|
return accessor;
|
|
4008
|
-
return generateStringFormatCheck(doc, ctx, def, accessor);
|
|
4126
|
+
return generateStringFormatCheck(doc, ctx, def, accessor, needsValue);
|
|
4009
4127
|
}
|
|
4010
4128
|
function generateNumberCheck(doc, schema, accessor) {
|
|
4011
4129
|
doc.write(`if (typeof ${accessor} !== "number" || !Number.isFinite(${accessor})) return INVALID;`);
|
|
@@ -4123,7 +4241,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
4123
4241
|
}
|
|
4124
4242
|
}
|
|
4125
4243
|
const outputVar = newVar(ctx);
|
|
4126
|
-
const hasConditionalKeys = allKeys.some((k) =>
|
|
4244
|
+
const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
|
|
4127
4245
|
if (!buildsValue) {
|
|
4128
4246
|
if (unknownKeysMode === "schema") {
|
|
4129
4247
|
const knownSet = keys.length > 0 ? addConstant(ctx, new Set(keys)) : null;
|
|
@@ -4150,7 +4268,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
4150
4268
|
const out = propOutputs.get(k);
|
|
4151
4269
|
if (dropsWhenAbsent(propShape[k])) {
|
|
4152
4270
|
doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
|
|
4153
|
-
} else if (
|
|
4271
|
+
} else if (mayOmitUndefined(propShape[k])) {
|
|
4154
4272
|
doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
|
|
4155
4273
|
} else {
|
|
4156
4274
|
doc.write(`${outputVar}[${kx}] = ${out};`);
|
|
@@ -4283,6 +4401,9 @@ function fastPathAcceptsAbsence(schema) {
|
|
|
4283
4401
|
function dropsWhenAbsent(schema) {
|
|
4284
4402
|
return schema._zod.optin === "optional" && schema._zod.optout === "optional";
|
|
4285
4403
|
}
|
|
4404
|
+
function mayOmitUndefined(schema) {
|
|
4405
|
+
return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
|
|
4406
|
+
}
|
|
4286
4407
|
function mayOutputUndefined(schema) {
|
|
4287
4408
|
const def = schema._zod.def;
|
|
4288
4409
|
switch (def.type) {
|
|
@@ -4625,6 +4746,7 @@ function literalEquality(ctx, accessor, value) {
|
|
|
4625
4746
|
}
|
|
4626
4747
|
function generateIntersectionCheck(doc, ctx, schema, accessor) {
|
|
4627
4748
|
const def = schema._zod.def;
|
|
4749
|
+
ctx.definite = false;
|
|
4628
4750
|
const leftOutput = compileChild(doc, ctx, def.left, accessor);
|
|
4629
4751
|
const rightOutput = compileChild(doc, ctx, def.right, accessor);
|
|
4630
4752
|
const mergeConst = addConstant(ctx, mergeValues);
|
|
@@ -4678,14 +4800,13 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
|
|
|
4678
4800
|
const keyIsBareString = keyDef.type === "string" && keyDef.format === undefined && !keyDef.coerce && (keyDef.checks?.length ?? 0) === 0;
|
|
4679
4801
|
if (!keyIsBareString) {
|
|
4680
4802
|
const isLoose = def.mode === "loose";
|
|
4681
|
-
const
|
|
4803
|
+
const keyFn = compileFn(def.keyType);
|
|
4804
|
+
if (keyFn.definite === false)
|
|
4805
|
+
ctx.definite = false;
|
|
4806
|
+
const keyFast = addConstant(ctx, keyFn);
|
|
4682
4807
|
const numericConst = addConstant(ctx, number);
|
|
4683
|
-
const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
|
|
4684
4808
|
const outKeyVar = newVar(ctx);
|
|
4685
|
-
doc
|
|
4686
|
-
doc.indented((d) => {
|
|
4687
|
-
d.write(`if (${kVar} === "__proto__") continue;`);
|
|
4688
|
-
d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4809
|
+
emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
|
|
4689
4810
|
d.write(`let ${outKeyVar} = ${keyFast}(${kVar});`);
|
|
4690
4811
|
d.write(`if (${outKeyVar} === INVALID && typeof ${kVar} === "string" && ${numericConst}.test(${kVar})) ${outKeyVar} = ${keyFast}(Number(${kVar}));`);
|
|
4691
4812
|
if (isLoose) {
|
|
@@ -4699,21 +4820,39 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
|
|
|
4699
4820
|
const valOutput = compileChild(d, ctx, def.valueType, valueVar);
|
|
4700
4821
|
d.write(`${outputVar}[${outKeyVar}] = ${valOutput};`);
|
|
4701
4822
|
});
|
|
4702
|
-
doc.write(`}`);
|
|
4703
4823
|
return outputVar;
|
|
4704
4824
|
}
|
|
4705
|
-
|
|
4706
|
-
doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
|
|
4707
|
-
doc.indented((d) => {
|
|
4708
|
-
d.write(`if (${kVar} === "__proto__") continue;`);
|
|
4709
|
-
d.write(`if (!${propIsEnumerable}.call(${accessor}, ${kVar})) continue;`);
|
|
4710
|
-
d.write(`if (typeof ${kVar} !== "string") return INVALID;`);
|
|
4825
|
+
emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
|
|
4711
4826
|
d.write(`const ${valVar} = ${accessor}[${kVar}];`);
|
|
4712
4827
|
const valOutput = compileChild(d, ctx, def.valueType, valVar);
|
|
4713
4828
|
d.write(`${outputVar}[${kVar}] = ${valOutput};`);
|
|
4829
|
+
}, `return INVALID;`);
|
|
4830
|
+
return outputVar;
|
|
4831
|
+
}
|
|
4832
|
+
function emitOwnKeys(doc, ctx, accessor, kVar, body, onSymbol) {
|
|
4833
|
+
const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
|
|
4834
|
+
const symsVar = newVar(ctx);
|
|
4835
|
+
const keysVar = newVar(ctx);
|
|
4836
|
+
const iVar = newVar(ctx);
|
|
4837
|
+
doc.write(`const ${symsVar} = Object.getOwnPropertySymbols(${accessor});`);
|
|
4838
|
+
doc.write(`const ${keysVar} = Object.getOwnPropertyNames(${accessor});`);
|
|
4839
|
+
doc.write(`for (let ${iVar} = 0; ${iVar} < ${keysVar}.length; ${iVar}++) {`);
|
|
4840
|
+
doc.indented((d) => {
|
|
4841
|
+
d.write(`const ${kVar} = ${keysVar}[${iVar}];`);
|
|
4842
|
+
d.write(`if (${kVar} === "__proto__" || !${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4843
|
+
body(d);
|
|
4844
|
+
});
|
|
4845
|
+
doc.write(`}`);
|
|
4846
|
+
doc.write(`for (let ${iVar} = 0; ${iVar} < ${symsVar}.length; ${iVar}++) {`);
|
|
4847
|
+
doc.indented((d) => {
|
|
4848
|
+
d.write(`const ${kVar} = ${symsVar}[${iVar}];`);
|
|
4849
|
+
d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
|
|
4850
|
+
if (onSymbol)
|
|
4851
|
+
d.write(onSymbol);
|
|
4852
|
+
else
|
|
4853
|
+
body(d);
|
|
4714
4854
|
});
|
|
4715
4855
|
doc.write(`}`);
|
|
4716
|
-
return outputVar;
|
|
4717
4856
|
}
|
|
4718
4857
|
function literalPropertyKey(ctx, key) {
|
|
4719
4858
|
if (typeof key === "string")
|
|
@@ -4766,7 +4905,7 @@ function generateTemplateLiteralCheck(doc, ctx, schema, accessor) {
|
|
|
4766
4905
|
}
|
|
4767
4906
|
function generateLazyCheck(doc, ctx, schema, accessor) {
|
|
4768
4907
|
const def = schema._zod.def;
|
|
4769
|
-
const getterConst =
|
|
4908
|
+
const getterConst = addUserConstant(ctx, def.getter);
|
|
4770
4909
|
const cacheConst = addConstant(ctx, { parser: null });
|
|
4771
4910
|
doc.write(`if (!${cacheConst}.parser) {`);
|
|
4772
4911
|
doc.indented((d) => {
|
|
@@ -4799,7 +4938,7 @@ function generatePipeCheck(doc, ctx, schema, accessor) {
|
|
|
4799
4938
|
return INVALID;
|
|
4800
4939
|
return fakePayload.issues.length === 0 ? result : INVALID;
|
|
4801
4940
|
};
|
|
4802
|
-
const helperConst =
|
|
4941
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
4803
4942
|
const transformedVar = newVar(ctx);
|
|
4804
4943
|
doc.write(`const ${transformedVar} = ${helperConst}(${inputOutput});`);
|
|
4805
4944
|
doc.write(`if (${transformedVar} === INVALID) return INVALID;`);
|
|
@@ -4817,7 +4956,7 @@ function generateCustomCheck(doc, ctx, schema, accessor) {
|
|
|
4817
4956
|
if (isAsyncFunction(def.fn)) {
|
|
4818
4957
|
throw new ZodCompileAsyncError("z.compile: async custom predicates are not supported");
|
|
4819
4958
|
}
|
|
4820
|
-
const fnConst =
|
|
4959
|
+
const fnConst = addUserConstant(ctx, def.fn);
|
|
4821
4960
|
const throwAsyncConst = addConstant(ctx, throwAsync);
|
|
4822
4961
|
const resVar = newVar(ctx);
|
|
4823
4962
|
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
|
|
@@ -4850,7 +4989,7 @@ function generateCatchCheck(doc, ctx, schema, accessor) {
|
|
|
4850
4989
|
});
|
|
4851
4990
|
doc.write(`})();`);
|
|
4852
4991
|
const innerConst = addConstant(ctx, def.innerType);
|
|
4853
|
-
const catchConst =
|
|
4992
|
+
const catchConst = addUserConstant(ctx, def.catchValue);
|
|
4854
4993
|
const catchHelperConst = addConstant(ctx, runtimeCatch);
|
|
4855
4994
|
doc.write(`if (${outputVar} === INVALID) {`);
|
|
4856
4995
|
doc.indented((d) => {
|
|
@@ -4874,7 +5013,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
|
|
|
4874
5013
|
return INVALID;
|
|
4875
5014
|
return fakePayload.issues.length === 0 ? result : INVALID;
|
|
4876
5015
|
};
|
|
4877
|
-
const helperConst =
|
|
5016
|
+
const helperConst = addUserConstant(ctx, helperFn);
|
|
4878
5017
|
const outputVar = newVar(ctx);
|
|
4879
5018
|
doc.write(`const ${outputVar} = ${helperConst}(${accessor});`);
|
|
4880
5019
|
doc.write(`if (${outputVar} === INVALID) return INVALID;`);
|
|
@@ -4941,11 +5080,13 @@ var init_compile = __esm(() => {
|
|
|
4941
5080
|
});
|
|
4942
5081
|
|
|
4943
5082
|
// node_modules/zod/v4/core/api.js
|
|
5083
|
+
function snapshotChecks(def) {
|
|
5084
|
+
if (def.checks)
|
|
5085
|
+
def.checks = [...def.checks];
|
|
5086
|
+
return def;
|
|
5087
|
+
}
|
|
4944
5088
|
function _string(Class, params) {
|
|
4945
|
-
return new Class({
|
|
4946
|
-
type: "string",
|
|
4947
|
-
...normalizeParams(params)
|
|
4948
|
-
});
|
|
5089
|
+
return new Class(snapshotChecks({ type: "string", ...normalizeParams(params) }));
|
|
4949
5090
|
}
|
|
4950
5091
|
function _email(Class, params) {
|
|
4951
5092
|
return new Class({
|
|
@@ -5185,11 +5326,7 @@ function _isoDuration(Class, params) {
|
|
|
5185
5326
|
});
|
|
5186
5327
|
}
|
|
5187
5328
|
function _number(Class, params) {
|
|
5188
|
-
return new Class({
|
|
5189
|
-
type: "number",
|
|
5190
|
-
checks: [],
|
|
5191
|
-
...normalizeParams(params)
|
|
5192
|
-
});
|
|
5329
|
+
return new Class(snapshotChecks({ type: "number", checks: [], ...normalizeParams(params) }));
|
|
5193
5330
|
}
|
|
5194
5331
|
function _int(Class, params) {
|
|
5195
5332
|
return new Class({
|
|
@@ -5450,7 +5587,7 @@ function handleUnrepresentable(schema, ctx, json, params, message) {
|
|
|
5450
5587
|
Object.assign(json, result);
|
|
5451
5588
|
return true;
|
|
5452
5589
|
}
|
|
5453
|
-
function
|
|
5590
|
+
function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
5454
5591
|
var _a;
|
|
5455
5592
|
const def = schema._zod.def;
|
|
5456
5593
|
const seen = ctx.seen.get(schema);
|
|
@@ -5489,7 +5626,7 @@ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
|
5489
5626
|
if (parent) {
|
|
5490
5627
|
if (!result.ref)
|
|
5491
5628
|
result.ref = parent;
|
|
5492
|
-
|
|
5629
|
+
processSchema(parent, ctx, params);
|
|
5493
5630
|
ctx.seen.get(parent).isParent = true;
|
|
5494
5631
|
}
|
|
5495
5632
|
}
|
|
@@ -5594,7 +5731,6 @@ function extractDefs(ctx, schema) {
|
|
|
5594
5731
|
if (seen.count > 1) {
|
|
5595
5732
|
if (ctx.reused === "ref") {
|
|
5596
5733
|
extractToDef(entry);
|
|
5597
|
-
continue;
|
|
5598
5734
|
}
|
|
5599
5735
|
}
|
|
5600
5736
|
}
|
|
@@ -5917,13 +6053,13 @@ function isTransforming(_schema, _ctx) {
|
|
|
5917
6053
|
}
|
|
5918
6054
|
var FOLDABLE_KEYS, UNION_KEYS, createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
5919
6055
|
const ctx = initializeContext({ ...params, processors });
|
|
5920
|
-
|
|
6056
|
+
processSchema(schema, ctx);
|
|
5921
6057
|
extractDefs(ctx, schema);
|
|
5922
6058
|
return finalize(ctx, schema);
|
|
5923
6059
|
}, createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
|
|
5924
6060
|
const { libraryOptions, target } = params ?? {};
|
|
5925
6061
|
const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
|
|
5926
|
-
|
|
6062
|
+
processSchema(schema, ctx);
|
|
5927
6063
|
extractDefs(ctx, schema);
|
|
5928
6064
|
return finalize(ctx, schema);
|
|
5929
6065
|
};
|
|
@@ -5935,6 +6071,34 @@ var init_to_json_schema = __esm(() => {
|
|
|
5935
6071
|
});
|
|
5936
6072
|
|
|
5937
6073
|
// node_modules/zod/v4/core/json-schema-processors.js
|
|
6074
|
+
function aggregateChecks(schema) {
|
|
6075
|
+
const agg = {};
|
|
6076
|
+
const def = schema._zod.def;
|
|
6077
|
+
const list = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
|
|
6078
|
+
for (const ch of list)
|
|
6079
|
+
contributors[ch._zod.def.check]?.(agg, ch._zod.def);
|
|
6080
|
+
const bag = schema._zod.bag;
|
|
6081
|
+
if (bag.minimum !== undefined)
|
|
6082
|
+
narrowMin(agg, "minimum", bag.minimum);
|
|
6083
|
+
if (bag.exclusiveMinimum !== undefined)
|
|
6084
|
+
narrowMin(agg, "exclusiveMinimum", bag.exclusiveMinimum);
|
|
6085
|
+
if (bag.maximum !== undefined)
|
|
6086
|
+
narrowMax(agg, "maximum", bag.maximum);
|
|
6087
|
+
if (bag.exclusiveMaximum !== undefined)
|
|
6088
|
+
narrowMax(agg, "exclusiveMaximum", bag.exclusiveMaximum);
|
|
6089
|
+
if (bag.multipleOf !== undefined)
|
|
6090
|
+
addDivisor(agg, bag.multipleOf);
|
|
6091
|
+
if (bag.format !== undefined) {
|
|
6092
|
+
agg.format ?? (agg.format = bag.format);
|
|
6093
|
+
if (bag.format.includes("int"))
|
|
6094
|
+
agg.isInt = true;
|
|
6095
|
+
}
|
|
6096
|
+
if (bag.mime)
|
|
6097
|
+
intersectMime(agg, bag.mime);
|
|
6098
|
+
for (const pattern of bag.patterns ?? [])
|
|
6099
|
+
addPattern(agg, pattern);
|
|
6100
|
+
return agg;
|
|
6101
|
+
}
|
|
5938
6102
|
function inputOptin(schema) {
|
|
5939
6103
|
const def = schema._zod.def;
|
|
5940
6104
|
if (def.type === "pipe" && def.in._zod.traits.has("$ZodTransform")) {
|
|
@@ -6020,10 +6184,37 @@ function serializeDefaultValue(value, schema, ctx, json, params) {
|
|
|
6020
6184
|
handleUnrepresentable(schema, ctx, json, params, "BigInt defaults cannot be represented in JSON Schema");
|
|
6021
6185
|
return UNREPRESENTABLE_DEFAULT;
|
|
6022
6186
|
}
|
|
6023
|
-
var
|
|
6187
|
+
var narrowMin = (agg, key, value) => {
|
|
6188
|
+
if (agg[key] === undefined || value > agg[key])
|
|
6189
|
+
agg[key] = value;
|
|
6190
|
+
}, narrowMax = (agg, key, value) => {
|
|
6191
|
+
if (agg[key] === undefined || value < agg[key])
|
|
6192
|
+
agg[key] = value;
|
|
6193
|
+
}, narrowBoth = (agg, value) => {
|
|
6194
|
+
narrowMin(agg, "minimum", value);
|
|
6195
|
+
narrowMax(agg, "maximum", value);
|
|
6196
|
+
}, addDivisor = (agg, value) => {
|
|
6197
|
+
agg.multipleOf ?? (agg.multipleOf = []);
|
|
6198
|
+
if (!agg.multipleOf.includes(value))
|
|
6199
|
+
agg.multipleOf.push(value);
|
|
6200
|
+
}, addPattern = (agg, pattern) => {
|
|
6201
|
+
agg.patterns ?? (agg.patterns = new Set);
|
|
6202
|
+
agg.patterns.add(pattern);
|
|
6203
|
+
}, intersectMime = (agg, mime) => {
|
|
6204
|
+
agg.mime = agg.mime ? agg.mime.filter((m) => mime.includes(m)) : [...mime];
|
|
6205
|
+
}, setFormat = (agg, format) => {
|
|
6206
|
+
agg.format = format;
|
|
6207
|
+
if (format.includes("int"))
|
|
6208
|
+
agg.isInt = true;
|
|
6209
|
+
}, minContributor = (agg, def) => narrowMin(agg, "minimum", def.minimum), maxContributor = (agg, def) => narrowMax(agg, "maximum", def.maximum), formatContributor = (ranges) => (agg, def) => {
|
|
6210
|
+
setFormat(agg, def.format);
|
|
6211
|
+
const [minimum, maximum] = ranges[def.format];
|
|
6212
|
+
narrowMin(agg, "minimum", minimum);
|
|
6213
|
+
narrowMax(agg, "maximum", maximum);
|
|
6214
|
+
}, contributors, formatMap, exactPatterns, exactPattern = (p) => exactPatterns.get(p) ?? p, stringProcessor = (schema, ctx, _json, _params) => {
|
|
6024
6215
|
const json = _json;
|
|
6025
6216
|
json.type = "string";
|
|
6026
|
-
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = schema
|
|
6217
|
+
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
6027
6218
|
if (typeof minimum === "number")
|
|
6028
6219
|
json.minLength = minimum;
|
|
6029
6220
|
if (typeof maximum === "number")
|
|
@@ -6039,7 +6230,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6039
6230
|
if (contentEncoding)
|
|
6040
6231
|
json.contentEncoding = contentEncoding;
|
|
6041
6232
|
if (patterns && patterns.size > 0) {
|
|
6042
|
-
const patternList = [...patterns];
|
|
6233
|
+
const patternList = [...patterns].map(exactPattern);
|
|
6043
6234
|
if (patternList.length === 1)
|
|
6044
6235
|
json.pattern = patternList[0].source;
|
|
6045
6236
|
else if (patternList.length > 1) {
|
|
@@ -6053,11 +6244,8 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6053
6244
|
}
|
|
6054
6245
|
}, numberProcessor = (schema, ctx, _json, params) => {
|
|
6055
6246
|
const json = _json;
|
|
6056
|
-
const { minimum, maximum,
|
|
6057
|
-
|
|
6058
|
-
json.type = "integer";
|
|
6059
|
-
else
|
|
6060
|
-
json.type = "number";
|
|
6247
|
+
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
|
|
6248
|
+
json.type = isInt ? "integer" : "number";
|
|
6061
6249
|
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
6062
6250
|
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
|
|
6063
6251
|
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
|
|
@@ -6081,11 +6269,19 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6081
6269
|
} else if (typeof maximum === "number") {
|
|
6082
6270
|
json.maximum = maximum;
|
|
6083
6271
|
}
|
|
6084
|
-
if (
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6272
|
+
if (multipleOf) {
|
|
6273
|
+
const divisors = new Set;
|
|
6274
|
+
for (const divisor of multipleOf) {
|
|
6275
|
+
if (Number.isFinite(divisor) && divisor !== 0)
|
|
6276
|
+
divisors.add(Math.abs(divisor));
|
|
6277
|
+
else
|
|
6278
|
+
handleUnrepresentable(schema, ctx, json, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
|
|
6279
|
+
}
|
|
6280
|
+
const [first, ...rest] = divisors;
|
|
6281
|
+
if (first !== undefined)
|
|
6282
|
+
json.multipleOf = first;
|
|
6283
|
+
if (rest.length)
|
|
6284
|
+
json.allOf = [...json.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
|
|
6089
6285
|
}
|
|
6090
6286
|
}, booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
6091
6287
|
json.type = "boolean";
|
|
@@ -6148,13 +6344,13 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6148
6344
|
}, arrayProcessor = (schema, ctx, _json, params) => {
|
|
6149
6345
|
const json = _json;
|
|
6150
6346
|
const def = schema._zod.def;
|
|
6151
|
-
const { minimum, maximum } = schema
|
|
6347
|
+
const { minimum, maximum } = aggregateChecks(schema);
|
|
6152
6348
|
if (typeof minimum === "number")
|
|
6153
6349
|
json.minItems = minimum;
|
|
6154
6350
|
if (typeof maximum === "number")
|
|
6155
6351
|
json.maxItems = maximum;
|
|
6156
6352
|
json.type = "array";
|
|
6157
|
-
json.items =
|
|
6353
|
+
json.items = processSchema(def.element, ctx, {
|
|
6158
6354
|
...params,
|
|
6159
6355
|
path: [...params.path, "items"]
|
|
6160
6356
|
});
|
|
@@ -6169,22 +6365,20 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6169
6365
|
json.type = "object";
|
|
6170
6366
|
json.properties = {};
|
|
6171
6367
|
for (const key in shape) {
|
|
6172
|
-
assignProp(json.properties, key,
|
|
6368
|
+
assignProp(json.properties, key, processSchema(shape[key], ctx, {
|
|
6173
6369
|
...params,
|
|
6174
6370
|
path: [...params.path, "properties", key]
|
|
6175
6371
|
}));
|
|
6176
6372
|
}
|
|
6177
|
-
const
|
|
6178
|
-
const
|
|
6373
|
+
const requiredKeys = [];
|
|
6374
|
+
for (const key of Object.keys(shape)) {
|
|
6179
6375
|
const field = def.shape[key];
|
|
6180
|
-
if (ctx.io === "input") {
|
|
6181
|
-
|
|
6182
|
-
} else {
|
|
6183
|
-
return field._zod.optout === undefined;
|
|
6376
|
+
if (ctx.io === "input" ? inputOptin(field) === undefined : field._zod.optout === undefined) {
|
|
6377
|
+
requiredKeys.push(key);
|
|
6184
6378
|
}
|
|
6185
|
-
}
|
|
6186
|
-
if (requiredKeys.
|
|
6187
|
-
json.required =
|
|
6379
|
+
}
|
|
6380
|
+
if (requiredKeys.length > 0) {
|
|
6381
|
+
json.required = requiredKeys;
|
|
6188
6382
|
}
|
|
6189
6383
|
if (def.catchall?._zod.def.type === "never") {
|
|
6190
6384
|
json.additionalProperties = false;
|
|
@@ -6192,7 +6386,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6192
6386
|
if (ctx.io === "output")
|
|
6193
6387
|
json.additionalProperties = false;
|
|
6194
6388
|
} else if (def.catchall) {
|
|
6195
|
-
json.additionalProperties =
|
|
6389
|
+
json.additionalProperties = processSchema(def.catchall, ctx, {
|
|
6196
6390
|
...params,
|
|
6197
6391
|
path: [...params.path, "additionalProperties"]
|
|
6198
6392
|
});
|
|
@@ -6200,7 +6394,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6200
6394
|
}, unionProcessor = (schema, ctx, json, params) => {
|
|
6201
6395
|
const def = schema._zod.def;
|
|
6202
6396
|
const isExclusive = def.inclusive === false;
|
|
6203
|
-
const options = def.options.map((x, i) =>
|
|
6397
|
+
const options = def.options.map((x, i) => processSchema(x, ctx, {
|
|
6204
6398
|
...params,
|
|
6205
6399
|
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
|
|
6206
6400
|
}));
|
|
@@ -6211,11 +6405,11 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6211
6405
|
}
|
|
6212
6406
|
}, intersectionProcessor = (schema, ctx, json, params) => {
|
|
6213
6407
|
const def = schema._zod.def;
|
|
6214
|
-
const a =
|
|
6408
|
+
const a = processSchema(def.left, ctx, {
|
|
6215
6409
|
...params,
|
|
6216
6410
|
path: [...params.path, "allOf", 0]
|
|
6217
6411
|
});
|
|
6218
|
-
const b =
|
|
6412
|
+
const b = processSchema(def.right, ctx, {
|
|
6219
6413
|
...params,
|
|
6220
6414
|
path: [...params.path, "allOf", 1]
|
|
6221
6415
|
});
|
|
@@ -6231,20 +6425,19 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6231
6425
|
const def = schema._zod.def;
|
|
6232
6426
|
json.type = "object";
|
|
6233
6427
|
const keyType = def.keyType;
|
|
6234
|
-
const
|
|
6235
|
-
const patterns = keyBag?.patterns;
|
|
6428
|
+
const patterns = aggregateChecks(keyType).patterns;
|
|
6236
6429
|
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
6237
|
-
const valueSchema =
|
|
6430
|
+
const valueSchema = processSchema(def.valueType, ctx, {
|
|
6238
6431
|
...params,
|
|
6239
6432
|
path: [...params.path, "patternProperties", "*"]
|
|
6240
6433
|
});
|
|
6241
6434
|
json.patternProperties = {};
|
|
6242
6435
|
for (const pattern of patterns) {
|
|
6243
|
-
assignProp(json.patternProperties, pattern.source, valueSchema);
|
|
6436
|
+
assignProp(json.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
6244
6437
|
}
|
|
6245
6438
|
} else {
|
|
6246
6439
|
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
6247
|
-
json.propertyNames =
|
|
6440
|
+
json.propertyNames = processSchema(def.keyType, ctx, {
|
|
6248
6441
|
...params,
|
|
6249
6442
|
path: [...params.path, "propertyNames"]
|
|
6250
6443
|
});
|
|
@@ -6256,7 +6449,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6256
6449
|
}
|
|
6257
6450
|
pending.push(schema);
|
|
6258
6451
|
}
|
|
6259
|
-
json.additionalProperties =
|
|
6452
|
+
json.additionalProperties = processSchema(def.valueType, ctx, {
|
|
6260
6453
|
...params,
|
|
6261
6454
|
path: [...params.path, "additionalProperties"]
|
|
6262
6455
|
});
|
|
@@ -6271,7 +6464,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6271
6464
|
}
|
|
6272
6465
|
}, nullableProcessor = (schema, ctx, json, params) => {
|
|
6273
6466
|
const def = schema._zod.def;
|
|
6274
|
-
const inner =
|
|
6467
|
+
const inner = processSchema(def.innerType, ctx, params);
|
|
6275
6468
|
const seen = ctx.seen.get(schema);
|
|
6276
6469
|
if (ctx.target === "openapi-3.0") {
|
|
6277
6470
|
seen.ref = def.innerType;
|
|
@@ -6281,12 +6474,12 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6281
6474
|
}
|
|
6282
6475
|
}, nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
6283
6476
|
const def = schema._zod.def;
|
|
6284
|
-
|
|
6477
|
+
processSchema(def.innerType, ctx, params);
|
|
6285
6478
|
const seen = ctx.seen.get(schema);
|
|
6286
6479
|
seen.ref = def.innerType;
|
|
6287
6480
|
}, UNREPRESENTABLE_DEFAULT, defaultProcessor = (schema, ctx, json, params) => {
|
|
6288
6481
|
const def = schema._zod.def;
|
|
6289
|
-
|
|
6482
|
+
processSchema(def.innerType, ctx, params);
|
|
6290
6483
|
const seen = ctx.seen.get(schema);
|
|
6291
6484
|
seen.ref = def.innerType;
|
|
6292
6485
|
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);
|
|
@@ -6294,7 +6487,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6294
6487
|
json.default = value;
|
|
6295
6488
|
}, prefaultProcessor = (schema, ctx, json, params) => {
|
|
6296
6489
|
const def = schema._zod.def;
|
|
6297
|
-
|
|
6490
|
+
processSchema(def.innerType, ctx, params);
|
|
6298
6491
|
const seen = ctx.seen.get(schema);
|
|
6299
6492
|
seen.ref = def.innerType;
|
|
6300
6493
|
if (ctx.io !== "input")
|
|
@@ -6304,7 +6497,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6304
6497
|
json._prefault = value;
|
|
6305
6498
|
}, catchProcessor = (schema, ctx, json, params) => {
|
|
6306
6499
|
const def = schema._zod.def;
|
|
6307
|
-
|
|
6500
|
+
processSchema(def.innerType, ctx, params);
|
|
6308
6501
|
const seen = ctx.seen.get(schema);
|
|
6309
6502
|
seen.ref = def.innerType;
|
|
6310
6503
|
let catchValue;
|
|
@@ -6319,25 +6512,49 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
6319
6512
|
const def = schema._zod.def;
|
|
6320
6513
|
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
|
|
6321
6514
|
const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
|
|
6322
|
-
|
|
6515
|
+
processSchema(innerType, ctx, params);
|
|
6323
6516
|
const seen = ctx.seen.get(schema);
|
|
6324
6517
|
seen.ref = innerType;
|
|
6325
6518
|
}, readonlyProcessor = (schema, ctx, json, params) => {
|
|
6326
6519
|
const def = schema._zod.def;
|
|
6327
|
-
|
|
6520
|
+
processSchema(def.innerType, ctx, params);
|
|
6328
6521
|
const seen = ctx.seen.get(schema);
|
|
6329
6522
|
seen.ref = def.innerType;
|
|
6330
6523
|
json.readOnly = true;
|
|
6331
6524
|
}, optionalProcessor = (schema, ctx, _json, params) => {
|
|
6332
6525
|
const def = schema._zod.def;
|
|
6333
|
-
|
|
6526
|
+
processSchema(def.innerType, ctx, params);
|
|
6334
6527
|
const seen = ctx.seen.get(schema);
|
|
6335
6528
|
seen.ref = def.innerType;
|
|
6336
6529
|
};
|
|
6337
6530
|
var init_json_schema_processors = __esm(() => {
|
|
6338
6531
|
init_regexes();
|
|
6532
|
+
init_schemas();
|
|
6339
6533
|
init_to_json_schema();
|
|
6340
6534
|
init_util();
|
|
6535
|
+
contributors = {
|
|
6536
|
+
greater_than: (agg, def) => narrowMin(agg, def.inclusive ? "minimum" : "exclusiveMinimum", def.value),
|
|
6537
|
+
less_than: (agg, def) => narrowMax(agg, def.inclusive ? "maximum" : "exclusiveMaximum", def.value),
|
|
6538
|
+
multiple_of: (agg, def) => addDivisor(agg, def.value),
|
|
6539
|
+
number_format: formatContributor(NUMBER_FORMAT_RANGES),
|
|
6540
|
+
bigint_format: formatContributor(BIGINT_FORMAT_RANGES),
|
|
6541
|
+
min_length: minContributor,
|
|
6542
|
+
max_length: maxContributor,
|
|
6543
|
+
length_equals: (agg, def) => narrowBoth(agg, def.length),
|
|
6544
|
+
min_size: minContributor,
|
|
6545
|
+
max_size: maxContributor,
|
|
6546
|
+
size_equals: (agg, def) => narrowBoth(agg, def.size),
|
|
6547
|
+
string_format: (agg, def) => {
|
|
6548
|
+
setFormat(agg, def.format);
|
|
6549
|
+
if (def.pattern)
|
|
6550
|
+
addPattern(agg, def.pattern);
|
|
6551
|
+
if (def.format === "base64" || def.format === "base64url")
|
|
6552
|
+
agg.contentEncoding = def.format;
|
|
6553
|
+
if (def.local || def.precision === -1)
|
|
6554
|
+
agg.laxFormat = true;
|
|
6555
|
+
},
|
|
6556
|
+
mime_type: (agg, def) => intersectMime(agg, def.mime)
|
|
6557
|
+
};
|
|
6341
6558
|
formatMap = {
|
|
6342
6559
|
guid: "uuid",
|
|
6343
6560
|
url: "uri",
|
|
@@ -6345,6 +6562,10 @@ var init_json_schema_processors = __esm(() => {
|
|
|
6345
6562
|
json_string: "json-string",
|
|
6346
6563
|
regex: ""
|
|
6347
6564
|
};
|
|
6565
|
+
exactPatterns = new Map([
|
|
6566
|
+
[base64Charset, base64],
|
|
6567
|
+
[base64urlCharset, base64url]
|
|
6568
|
+
]);
|
|
6348
6569
|
pendingRecords = new WeakMap;
|
|
6349
6570
|
UNREPRESENTABLE_DEFAULT = Symbol();
|
|
6350
6571
|
});
|
|
@@ -6427,14 +6648,15 @@ var init_errors2 = __esm(() => {
|
|
|
6427
6648
|
});
|
|
6428
6649
|
|
|
6429
6650
|
// node_modules/zod/v4/classic/parse.js
|
|
6430
|
-
var
|
|
6651
|
+
var parse2, parseAsync, safeParse, safeParseAsync, encode, decode, encodeAsync, decodeAsync, safeEncode, safeDecode, safeEncodeAsync, safeDecodeAsync;
|
|
6431
6652
|
var init_parse2 = __esm(() => {
|
|
6432
6653
|
init_core2();
|
|
6433
6654
|
init_errors2();
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6655
|
+
init_core2();
|
|
6656
|
+
parse2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
6657
|
+
parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
6658
|
+
safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
6659
|
+
safeParseAsync = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
6438
6660
|
encode = /* @__PURE__ */ _encode(ZodRealError);
|
|
6439
6661
|
decode = /* @__PURE__ */ _decode(ZodRealError);
|
|
6440
6662
|
encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
@@ -6737,16 +6959,16 @@ var init_schemas2 = __esm(() => {
|
|
|
6737
6959
|
own(this, "~standard", value);
|
|
6738
6960
|
},
|
|
6739
6961
|
parse: function _parse(data, params) {
|
|
6740
|
-
return
|
|
6962
|
+
return parse2(this, data, params, { callee: _parse });
|
|
6741
6963
|
},
|
|
6742
6964
|
parseAsync: async function _parseAsync(data, params) {
|
|
6743
|
-
return await
|
|
6965
|
+
return await parseAsync(this, data, params, { callee: _parseAsync });
|
|
6744
6966
|
},
|
|
6745
6967
|
safeParse(data, params) {
|
|
6746
|
-
return
|
|
6968
|
+
return safeParse(this, data, params);
|
|
6747
6969
|
},
|
|
6748
6970
|
async safeParseAsync(data, params) {
|
|
6749
|
-
return
|
|
6971
|
+
return safeParseAsync(this, data, params);
|
|
6750
6972
|
},
|
|
6751
6973
|
get spa() {
|
|
6752
6974
|
return this?.safeParseAsync;
|
|
@@ -6754,6 +6976,12 @@ var init_schemas2 = __esm(() => {
|
|
|
6754
6976
|
set spa(value) {
|
|
6755
6977
|
own(this, "spa", value);
|
|
6756
6978
|
},
|
|
6979
|
+
validate(data, params) {
|
|
6980
|
+
return validate(this, data, params);
|
|
6981
|
+
},
|
|
6982
|
+
validateAsync(data, params) {
|
|
6983
|
+
return validateAsync(this, data, params);
|
|
6984
|
+
},
|
|
6757
6985
|
encode: function _encode(data, params) {
|
|
6758
6986
|
return encode(this, data, params, { callee: _encode });
|
|
6759
6987
|
},
|
|
@@ -6792,10 +7020,10 @@ var init_schemas2 = __esm(() => {
|
|
|
6792
7020
|
$ZodString.init(inst, def);
|
|
6793
7021
|
ZodType.init(inst, def);
|
|
6794
7022
|
inst._zod.processJSONSchema = (ctx, json, params) => stringProcessor(inst, ctx, json, params);
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
7023
|
+
}, /* @__PURE__ */ derived({
|
|
7024
|
+
format: (inst) => aggregateChecks(inst).format ?? null,
|
|
7025
|
+
minLength: (inst) => aggregateChecks(inst).minimum ?? null,
|
|
7026
|
+
maxLength: (inst) => aggregateChecks(inst).maximum ?? null
|
|
6799
7027
|
}, {
|
|
6800
7028
|
regex(...args) {
|
|
6801
7029
|
return this.check(_regex(...args));
|
|
@@ -6842,7 +7070,7 @@ var init_schemas2 = __esm(() => {
|
|
|
6842
7070
|
slugify() {
|
|
6843
7071
|
return this.check(_slugify());
|
|
6844
7072
|
}
|
|
6845
|
-
});
|
|
7073
|
+
}));
|
|
6846
7074
|
ZodString = /* @__PURE__ */ $constructor("ZodString", (inst, def) => {
|
|
6847
7075
|
$ZodString.init(inst, def);
|
|
6848
7076
|
_ZodString.init(inst, def);
|
|
@@ -7026,12 +7254,21 @@ var init_schemas2 = __esm(() => {
|
|
|
7026
7254
|
$ZodNumber.init(inst, def);
|
|
7027
7255
|
ZodType.init(inst, def);
|
|
7028
7256
|
inst._zod.processJSONSchema = (ctx, json, params) => numberProcessor(inst, ctx, json, params);
|
|
7029
|
-
const bag = inst._zod.bag;
|
|
7030
|
-
inst.minValue = Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null;
|
|
7031
|
-
inst.maxValue = Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null;
|
|
7032
|
-
inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5);
|
|
7033
7257
|
inst.isFinite = true;
|
|
7034
|
-
|
|
7258
|
+
}, /* @__PURE__ */ derived({
|
|
7259
|
+
minValue: (inst) => {
|
|
7260
|
+
const { minimum, exclusiveMinimum } = aggregateChecks(inst);
|
|
7261
|
+
return Math.max(minimum ?? Number.NEGATIVE_INFINITY, exclusiveMinimum ?? Number.NEGATIVE_INFINITY);
|
|
7262
|
+
},
|
|
7263
|
+
maxValue: (inst) => {
|
|
7264
|
+
const { maximum, exclusiveMaximum } = aggregateChecks(inst);
|
|
7265
|
+
return Math.min(maximum ?? Number.POSITIVE_INFINITY, exclusiveMaximum ?? Number.POSITIVE_INFINITY);
|
|
7266
|
+
},
|
|
7267
|
+
isInt: (inst) => {
|
|
7268
|
+
const { isInt, multipleOf } = aggregateChecks(inst);
|
|
7269
|
+
return !!isInt || !!multipleOf?.some(Number.isSafeInteger);
|
|
7270
|
+
},
|
|
7271
|
+
format: (inst) => aggregateChecks(inst).format ?? null
|
|
7035
7272
|
}, {
|
|
7036
7273
|
gt(value, params) {
|
|
7037
7274
|
return this.check(_gt(value, params));
|
|
@@ -7078,7 +7315,7 @@ var init_schemas2 = __esm(() => {
|
|
|
7078
7315
|
finite() {
|
|
7079
7316
|
return this;
|
|
7080
7317
|
}
|
|
7081
|
-
});
|
|
7318
|
+
}));
|
|
7082
7319
|
ZodNumberFormat = /* @__PURE__ */ $constructor("ZodNumberFormat", (inst, def) => {
|
|
7083
7320
|
$ZodNumberFormat.init(inst, def);
|
|
7084
7321
|
ZodNumber.init(inst, def);
|
|
@@ -7132,19 +7369,19 @@ var init_schemas2 = __esm(() => {
|
|
|
7132
7369
|
return _enum(Object.keys(this._zod.def.shape));
|
|
7133
7370
|
},
|
|
7134
7371
|
catchall(catchall) {
|
|
7135
|
-
return this.clone(
|
|
7372
|
+
return this.clone(mergeDefs(this._zod.def, { catchall }));
|
|
7136
7373
|
},
|
|
7137
7374
|
passthrough() {
|
|
7138
|
-
return this.clone(
|
|
7375
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));
|
|
7139
7376
|
},
|
|
7140
7377
|
loose() {
|
|
7141
|
-
return this.clone(
|
|
7378
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));
|
|
7142
7379
|
},
|
|
7143
7380
|
strict() {
|
|
7144
|
-
return this.clone(
|
|
7381
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: never() }));
|
|
7145
7382
|
},
|
|
7146
7383
|
strip() {
|
|
7147
|
-
return this.clone(
|
|
7384
|
+
return this.clone(mergeDefs(this._zod.def, { catchall: undefined }));
|
|
7148
7385
|
},
|
|
7149
7386
|
extend(incoming) {
|
|
7150
7387
|
return extend(this, incoming);
|
|
@@ -7199,7 +7436,7 @@ var init_schemas2 = __esm(() => {
|
|
|
7199
7436
|
ZodType.init(inst, def);
|
|
7200
7437
|
inst._zod.processJSONSchema = (ctx, json, params) => enumProcessor(inst, ctx, json, params);
|
|
7201
7438
|
inst.enum = def.entries;
|
|
7202
|
-
inst.options =
|
|
7439
|
+
inst.options = [...inst._zod.values];
|
|
7203
7440
|
const keys = new Set(Object.keys(def.entries));
|
|
7204
7441
|
inst.extract = (values, params) => {
|
|
7205
7442
|
const newEntries = {};
|
|
@@ -7380,7 +7617,7 @@ var init_zod = __esm(() => {
|
|
|
7380
7617
|
import { createHash, randomUUID } from "node:crypto";
|
|
7381
7618
|
function parseOperation(family, input) {
|
|
7382
7619
|
if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
|
|
7383
|
-
return
|
|
7620
|
+
return failure2("unsupported_version", "unsupported schema version", { operation: family });
|
|
7384
7621
|
const compiled = compiledOperationSchemas[family].safeParse(input);
|
|
7385
7622
|
const parsed = compiled.success ? operationSchemas[family].safeParse(input) : compiled;
|
|
7386
7623
|
if (parsed.success)
|
|
@@ -7389,7 +7626,7 @@ function parseOperation(family, input) {
|
|
|
7389
7626
|
path: issue.code === "unrecognized_keys" ? issue.keys.join(".") : issue.path.join("."),
|
|
7390
7627
|
reason: issue.message
|
|
7391
7628
|
}));
|
|
7392
|
-
return
|
|
7629
|
+
return failure2("invalid_input", "operation input is invalid", { fields });
|
|
7393
7630
|
}
|
|
7394
7631
|
function canonical(value, seen) {
|
|
7395
7632
|
if (value === null || typeof value === "boolean" || typeof value === "string") {
|
|
@@ -7421,7 +7658,7 @@ function canonical(value, seen) {
|
|
|
7421
7658
|
throw new TypeError("symbol key is not JSON");
|
|
7422
7659
|
if (Object.keys(value).some((key) => invalidUnicode(key)))
|
|
7423
7660
|
throw new TypeError("invalid Unicode");
|
|
7424
|
-
result = Object.fromEntries(Object.keys(value).
|
|
7661
|
+
result = Object.fromEntries(Object.keys(value).toSorted().map((key) => [key, canonical(value[key], seen)]));
|
|
7425
7662
|
}
|
|
7426
7663
|
seen.delete(value);
|
|
7427
7664
|
return result;
|
|
@@ -7452,14 +7689,14 @@ function decisionDigest(input) {
|
|
|
7452
7689
|
function candidateDigest(input) {
|
|
7453
7690
|
const normalizedScope = {
|
|
7454
7691
|
description: input.scope.description,
|
|
7455
|
-
paths: [...input.scope.paths].
|
|
7456
|
-
exclusions: [...input.scope.exclusions].
|
|
7692
|
+
paths: [...input.scope.paths].toSorted(compareCodeUnits),
|
|
7693
|
+
exclusions: [...input.scope.exclusions].toSorted(compareCodeUnits)
|
|
7457
7694
|
};
|
|
7458
7695
|
return sha256({
|
|
7459
7696
|
scope: normalizedScope,
|
|
7460
7697
|
completeness: input.completeness,
|
|
7461
|
-
files: [...input.files].
|
|
7462
|
-
environment: input.environment.map(({ name, value }) => ({ name, value })).
|
|
7698
|
+
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)),
|
|
7699
|
+
environment: input.environment.map(({ name, value }) => ({ name, value })).toSorted((left, right) => compareCodeUnits(left.name, right.name) || compareNullableText(left.value, right.value)),
|
|
7463
7700
|
head: input.head
|
|
7464
7701
|
});
|
|
7465
7702
|
}
|
|
@@ -7468,8 +7705,8 @@ function requirementId(input) {
|
|
|
7468
7705
|
...input,
|
|
7469
7706
|
scope: {
|
|
7470
7707
|
description: input.scope.description,
|
|
7471
|
-
paths: [...input.scope.paths].
|
|
7472
|
-
exclusions: [...input.scope.exclusions].
|
|
7708
|
+
paths: [...input.scope.paths].toSorted(compareCodeUnits),
|
|
7709
|
+
exclusions: [...input.scope.exclusions].toSorted(compareCodeUnits)
|
|
7473
7710
|
}
|
|
7474
7711
|
});
|
|
7475
7712
|
}
|
|
@@ -7593,7 +7830,7 @@ var SCHEMA_VERSION = 1, POLICY_VERSION = "1.0.0", OPERATION_FAMILIES, uuidPatter
|
|
|
7593
7830
|
revision: revisionValue,
|
|
7594
7831
|
workspaceRevision: workspaceRevisionValue,
|
|
7595
7832
|
data
|
|
7596
|
-
}),
|
|
7833
|
+
}), failure2 = (code, error, details = {}) => ({ ok: false, schemaVersion: 1, code, error, details }), compareCodeUnits = (left, right) => {
|
|
7597
7834
|
const length = Math.min(left.length, right.length);
|
|
7598
7835
|
for (let index = 0;index < length; index += 1) {
|
|
7599
7836
|
const difference = left.charCodeAt(index) - right.charCodeAt(index);
|
|
@@ -8908,18 +9145,18 @@ class TaskStore {
|
|
|
8908
9145
|
}
|
|
8909
9146
|
readTask(taskId) {
|
|
8910
9147
|
if (!validId(taskId))
|
|
8911
|
-
return
|
|
9148
|
+
return failure2("invalid_input", "task ID is invalid", { taskId });
|
|
8912
9149
|
const result = this.readRecord(path4.join(this.tasksDir, `${taskId}.json`), taskRecordSchema);
|
|
8913
9150
|
if (!result.exists)
|
|
8914
|
-
return
|
|
9151
|
+
return failure2("not_found", "task not found", { taskId });
|
|
8915
9152
|
if (result.result.ok && result.result.data.id !== taskId)
|
|
8916
|
-
return
|
|
9153
|
+
return failure2("recovery_required", "task filename and record ID differ", { taskId });
|
|
8917
9154
|
if (result.result.ok) {
|
|
8918
9155
|
const workspace = this.readWorkspace();
|
|
8919
9156
|
if (!workspace.ok)
|
|
8920
9157
|
return workspace;
|
|
8921
9158
|
if (!workspace.data || result.result.data.workspaceId !== workspace.data.id)
|
|
8922
|
-
return
|
|
9159
|
+
return failure2("recovery_required", "task workspace binding is invalid", { taskId });
|
|
8923
9160
|
}
|
|
8924
9161
|
return result.result;
|
|
8925
9162
|
}
|
|
@@ -8930,7 +9167,7 @@ class TaskStore {
|
|
|
8930
9167
|
try {
|
|
8931
9168
|
names = fs4.readdirSync(this.tasksDir).filter((name) => name.endsWith(".json"));
|
|
8932
9169
|
} catch (error) {
|
|
8933
|
-
return
|
|
9170
|
+
return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
|
|
8934
9171
|
path: this.tasksDir
|
|
8935
9172
|
});
|
|
8936
9173
|
}
|
|
@@ -8938,20 +9175,20 @@ class TaskStore {
|
|
|
8938
9175
|
if (!workspace.ok)
|
|
8939
9176
|
return workspace;
|
|
8940
9177
|
if (!workspace.data)
|
|
8941
|
-
return
|
|
9178
|
+
return failure2("recovery_required", "task workspace binding is invalid", {
|
|
8942
9179
|
path: this.workspacePath
|
|
8943
9180
|
});
|
|
8944
9181
|
const tasks = [];
|
|
8945
|
-
for (const name of names.
|
|
9182
|
+
for (const name of names.toSorted()) {
|
|
8946
9183
|
const item = this.readRecord(path4.join(this.tasksDir, name), taskRecordSchema);
|
|
8947
9184
|
if (!item.exists)
|
|
8948
9185
|
continue;
|
|
8949
9186
|
if (!item.result.ok)
|
|
8950
9187
|
return item.result;
|
|
8951
9188
|
if (!validId(name.slice(0, -5)) || item.result.data.id !== name.slice(0, -5))
|
|
8952
|
-
return
|
|
9189
|
+
return failure2("recovery_required", "task filename and record ID differ", { path: name });
|
|
8953
9190
|
if (item.result.data.workspaceId !== workspace.data.id)
|
|
8954
|
-
return
|
|
9191
|
+
return failure2("recovery_required", "task workspace binding is invalid", { path: name });
|
|
8955
9192
|
tasks.push(item.result.data);
|
|
8956
9193
|
}
|
|
8957
9194
|
return success(null, null, tasks);
|
|
@@ -8963,7 +9200,7 @@ class TaskStore {
|
|
|
8963
9200
|
try {
|
|
8964
9201
|
names = fs4.readdirSync(this.tasksDir).filter((name) => name.endsWith(".json"));
|
|
8965
9202
|
} catch (error) {
|
|
8966
|
-
return
|
|
9203
|
+
return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
|
|
8967
9204
|
path: this.tasksDir
|
|
8968
9205
|
});
|
|
8969
9206
|
}
|
|
@@ -8971,13 +9208,13 @@ class TaskStore {
|
|
|
8971
9208
|
if (!workspace.ok)
|
|
8972
9209
|
return workspace;
|
|
8973
9210
|
if (!workspace.data)
|
|
8974
|
-
return
|
|
9211
|
+
return failure2("recovery_required", "task workspace binding is invalid", {
|
|
8975
9212
|
path: this.workspacePath
|
|
8976
9213
|
});
|
|
8977
9214
|
const stored = this.readIndex(workspace.data.id);
|
|
8978
9215
|
const entries = [];
|
|
8979
9216
|
let changed = Object.keys(stored).length !== names.length;
|
|
8980
|
-
for (const name of names.
|
|
9217
|
+
for (const name of names.toSorted()) {
|
|
8981
9218
|
const file = path4.join(this.tasksDir, name);
|
|
8982
9219
|
const signature = fileSignature(file);
|
|
8983
9220
|
if (signature === null) {
|
|
@@ -8995,9 +9232,9 @@ class TaskStore {
|
|
|
8995
9232
|
if (!item.result.ok)
|
|
8996
9233
|
return item.result;
|
|
8997
9234
|
if (!validId(name.slice(0, -5)) || item.result.data.id !== name.slice(0, -5))
|
|
8998
|
-
return
|
|
9235
|
+
return failure2("recovery_required", "task filename and record ID differ", { path: name });
|
|
8999
9236
|
if (item.result.data.workspaceId !== workspace.data.id)
|
|
9000
|
-
return
|
|
9237
|
+
return failure2("recovery_required", "task workspace binding is invalid", { path: name });
|
|
9001
9238
|
const entry = indexEntry(item.result.data, signature);
|
|
9002
9239
|
if (!cached || canonicalJson(cached) !== canonicalJson(entry))
|
|
9003
9240
|
changed = true;
|
|
@@ -9012,7 +9249,7 @@ class TaskStore {
|
|
|
9012
9249
|
if (!item.exists)
|
|
9013
9250
|
return success(null, null, null);
|
|
9014
9251
|
if (item.result.ok && item.result.data.root !== this.root && !sameDirectoryIdentity(item.result.data.root, this.root))
|
|
9015
|
-
return
|
|
9252
|
+
return failure2("recovery_required", "workspace root binding is invalid", {
|
|
9016
9253
|
path: this.workspacePath
|
|
9017
9254
|
});
|
|
9018
9255
|
return item.result;
|
|
@@ -9028,18 +9265,18 @@ class TaskStore {
|
|
|
9028
9265
|
if (!current.ok)
|
|
9029
9266
|
return current;
|
|
9030
9267
|
if (current.data ? value.expectedWorkspaceRevision !== current.data.revision : value.expectedWorkspaceRevision !== null) {
|
|
9031
|
-
return
|
|
9268
|
+
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", {
|
|
9032
9269
|
expectedWorkspaceRevision: value.expectedWorkspaceRevision,
|
|
9033
9270
|
actualWorkspaceRevision: current.data?.revision ?? null
|
|
9034
9271
|
});
|
|
9035
9272
|
}
|
|
9036
9273
|
if (!value.provenance)
|
|
9037
|
-
return
|
|
9274
|
+
return failure2("invalid_input", "provenance is required");
|
|
9038
9275
|
if (!intentSchema.safeParse(value.intent).success || !provenanceSchema.safeParse(value.provenance).success)
|
|
9039
|
-
return
|
|
9276
|
+
return failure2("invalid_input", "task intent or provenance is invalid");
|
|
9040
9277
|
const previousWorkspaceBytes = current.data ? this.snapshotBytes(this.workspacePath) : null;
|
|
9041
9278
|
if (current.data && !previousWorkspaceBytes)
|
|
9042
|
-
return
|
|
9279
|
+
return failure2("storage_error", "workspace snapshot disappeared during creation");
|
|
9043
9280
|
const workspace = current.data ? {
|
|
9044
9281
|
...current.data,
|
|
9045
9282
|
revision: newRevision(),
|
|
@@ -9090,9 +9327,9 @@ class TaskStore {
|
|
|
9090
9327
|
if (current.data && previousWorkspaceBytes) {
|
|
9091
9328
|
const restored = this.replaceSnapshot(this.workspacePath, current.data, this.snapshotBytes(this.workspacePath));
|
|
9092
9329
|
if (!restored.ok)
|
|
9093
|
-
return
|
|
9330
|
+
return failure2("external_outcome_unknown", "task creation failed and workspace restoration is uncertain", { operation: "create", outcome: "unknown" });
|
|
9094
9331
|
}
|
|
9095
|
-
return
|
|
9332
|
+
return failure2("external_outcome_unknown", "workspace created but task write is uncertain", { operation: "create", outcome: "unknown" });
|
|
9096
9333
|
}
|
|
9097
9334
|
return success(task.revision, workspace.revision, task);
|
|
9098
9335
|
});
|
|
@@ -9110,29 +9347,29 @@ class TaskStore {
|
|
|
9110
9347
|
return success(source.data.revision, current.data.revision, source.data);
|
|
9111
9348
|
if (source.code !== "not_found")
|
|
9112
9349
|
return source;
|
|
9113
|
-
return
|
|
9350
|
+
return failure2("not_found", "source task is not present in this shared workspace");
|
|
9114
9351
|
}
|
|
9115
9352
|
const tasks = this.listTasks();
|
|
9116
9353
|
if (!tasks.ok)
|
|
9117
9354
|
return tasks;
|
|
9118
9355
|
const prior = tasks.data.filter((task) => task.origin?.workspaceId === origin.workspaceId && task.origin?.taskId === origin.taskId);
|
|
9119
9356
|
if (prior.length > 1)
|
|
9120
|
-
return
|
|
9357
|
+
return failure2("recovery_required", `source task has multiple imported mappings: ${prior.map((task) => task.id).join(", ")}`);
|
|
9121
9358
|
if (prior.length === 1) {
|
|
9122
9359
|
const existing = prior[0];
|
|
9123
9360
|
if (existing.origin.exportDigest !== origin.exportDigest)
|
|
9124
|
-
return
|
|
9361
|
+
return failure2("revision_conflict", "source task export changed; reconcile the mapped destination task before importing", { taskId: existing.id });
|
|
9125
9362
|
return success(existing.revision, current.data.revision, existing);
|
|
9126
9363
|
}
|
|
9127
9364
|
}
|
|
9128
9365
|
if (current.data ? input.expectedWorkspaceRevision !== current.data.revision : input.expectedWorkspaceRevision !== null)
|
|
9129
|
-
return
|
|
9366
|
+
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", {
|
|
9130
9367
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
9131
9368
|
actualWorkspaceRevision: current.data?.revision ?? null
|
|
9132
9369
|
});
|
|
9133
9370
|
const previousWorkspaceBytes = current.data ? this.snapshotBytes(this.workspacePath) : null;
|
|
9134
9371
|
if (current.data && !previousWorkspaceBytes)
|
|
9135
|
-
return
|
|
9372
|
+
return failure2("storage_error", "workspace snapshot disappeared during import");
|
|
9136
9373
|
const timestamp = input.now ?? now();
|
|
9137
9374
|
const workspace = current.data ? {
|
|
9138
9375
|
...current.data,
|
|
@@ -9160,7 +9397,7 @@ class TaskStore {
|
|
|
9160
9397
|
};
|
|
9161
9398
|
const validTask = taskRecordSchema.safeParse(task);
|
|
9162
9399
|
if (!validTask.success)
|
|
9163
|
-
return
|
|
9400
|
+
return failure2("invalid_input", "imported task does not satisfy its schema");
|
|
9164
9401
|
const writtenWorkspace = this.replaceSnapshot(this.workspacePath, workspace, previousWorkspaceBytes);
|
|
9165
9402
|
if (!writtenWorkspace.ok)
|
|
9166
9403
|
return writtenWorkspace;
|
|
@@ -9169,9 +9406,9 @@ class TaskStore {
|
|
|
9169
9406
|
if (current.data && previousWorkspaceBytes) {
|
|
9170
9407
|
const restored = this.replaceSnapshot(this.workspacePath, current.data, this.snapshotBytes(this.workspacePath));
|
|
9171
9408
|
if (!restored.ok)
|
|
9172
|
-
return
|
|
9409
|
+
return failure2("external_outcome_unknown", "import failed and workspace restoration is uncertain", { operation: "import", outcome: "unknown" });
|
|
9173
9410
|
}
|
|
9174
|
-
return
|
|
9411
|
+
return failure2("external_outcome_unknown", `workspace created but task import is uncertain: ${writtenTask.error}`, {
|
|
9175
9412
|
operation: "import",
|
|
9176
9413
|
outcome: "unknown",
|
|
9177
9414
|
path: writtenTask.details.path
|
|
@@ -9189,13 +9426,13 @@ class TaskStore {
|
|
|
9189
9426
|
return this.conflict(expected, current.data.revision);
|
|
9190
9427
|
const previousBytes = this.snapshotBytes(this.taskPath(taskId));
|
|
9191
9428
|
if (!previousBytes)
|
|
9192
|
-
return
|
|
9429
|
+
return failure2("storage_error", "task snapshot disappeared during mutation");
|
|
9193
9430
|
const context = { now: timestamp ?? now(), revision: newRevision() };
|
|
9194
9431
|
let changed;
|
|
9195
9432
|
try {
|
|
9196
9433
|
changed = update(current.data, Object.freeze({ ...context }));
|
|
9197
9434
|
} catch (error) {
|
|
9198
|
-
return
|
|
9435
|
+
return failure2("storage_error", `task mutation failed: ${String(error)}`);
|
|
9199
9436
|
}
|
|
9200
9437
|
if (!changed.ok)
|
|
9201
9438
|
return changed;
|
|
@@ -9210,7 +9447,7 @@ class TaskStore {
|
|
|
9210
9447
|
};
|
|
9211
9448
|
const valid = taskRecordSchema.safeParse(record);
|
|
9212
9449
|
if (!valid.success)
|
|
9213
|
-
return
|
|
9450
|
+
return failure2("invalid_input", "task mutation produced an invalid record");
|
|
9214
9451
|
const written = this.replaceSnapshot(this.taskPath(taskId), valid.data, previousBytes);
|
|
9215
9452
|
return written.ok ? success(valid.data.revision, null, valid.data) : written;
|
|
9216
9453
|
});
|
|
@@ -9221,18 +9458,18 @@ class TaskStore {
|
|
|
9221
9458
|
if (!current.ok)
|
|
9222
9459
|
return current;
|
|
9223
9460
|
if (!current.data)
|
|
9224
|
-
return
|
|
9461
|
+
return failure2("not_found", "workspace not found");
|
|
9225
9462
|
if (current.data.revision !== expected)
|
|
9226
9463
|
return this.conflict(expected, current.data.revision);
|
|
9227
9464
|
const previousBytes = this.snapshotBytes(this.workspacePath);
|
|
9228
9465
|
if (!previousBytes)
|
|
9229
|
-
return
|
|
9466
|
+
return failure2("storage_error", "workspace snapshot disappeared during mutation");
|
|
9230
9467
|
const context = { now: now(), revision: newRevision() };
|
|
9231
9468
|
let changed;
|
|
9232
9469
|
try {
|
|
9233
9470
|
changed = update(current.data, Object.freeze({ ...context }));
|
|
9234
9471
|
} catch (error) {
|
|
9235
|
-
return
|
|
9472
|
+
return failure2("storage_error", `workspace mutation failed: ${String(error)}`);
|
|
9236
9473
|
}
|
|
9237
9474
|
if (!changed.ok)
|
|
9238
9475
|
return changed;
|
|
@@ -9245,7 +9482,7 @@ class TaskStore {
|
|
|
9245
9482
|
};
|
|
9246
9483
|
const valid = workspaceRecordSchema.safeParse(record);
|
|
9247
9484
|
if (!valid.success)
|
|
9248
|
-
return
|
|
9485
|
+
return failure2("invalid_input", "workspace mutation produced an invalid record");
|
|
9249
9486
|
const written = this.replaceSnapshot(this.workspacePath, valid.data, previousBytes);
|
|
9250
9487
|
return written.ok ? success(valid.data.revision, valid.data.revision, valid.data) : written;
|
|
9251
9488
|
});
|
|
@@ -9259,10 +9496,10 @@ class TaskStore {
|
|
|
9259
9496
|
if (!workspace.ok)
|
|
9260
9497
|
return workspace;
|
|
9261
9498
|
if (!workspace.data)
|
|
9262
|
-
return
|
|
9499
|
+
return failure2("not_found", "workspace not found");
|
|
9263
9500
|
const expected = input.expectedRevision;
|
|
9264
9501
|
if (!expected)
|
|
9265
|
-
return
|
|
9502
|
+
return failure2("invalid_input", "task revision is required");
|
|
9266
9503
|
if (task.data.revision !== expected)
|
|
9267
9504
|
return this.conflict(expected, task.data.revision);
|
|
9268
9505
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
@@ -9270,13 +9507,13 @@ class TaskStore {
|
|
|
9270
9507
|
const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
|
|
9271
9508
|
const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
|
|
9272
9509
|
if (!previousWorkspaceBytes || !previousTaskBytes)
|
|
9273
|
-
return
|
|
9510
|
+
return failure2("storage_error", "snapshot disappeared during coupled mutation");
|
|
9274
9511
|
const workspaceContext = { now: input.now ?? now(), revision: newRevision() };
|
|
9275
9512
|
let changedWorkspace;
|
|
9276
9513
|
try {
|
|
9277
9514
|
changedWorkspace = input.workspace(workspace.data, Object.freeze({ ...workspaceContext }));
|
|
9278
9515
|
} catch (error) {
|
|
9279
|
-
return
|
|
9516
|
+
return failure2("storage_error", `workspace mutation failed: ${String(error)}`);
|
|
9280
9517
|
}
|
|
9281
9518
|
if (!changedWorkspace.ok)
|
|
9282
9519
|
return changedWorkspace;
|
|
@@ -9288,7 +9525,7 @@ class TaskStore {
|
|
|
9288
9525
|
runtime: stampNew(workspace.data)
|
|
9289
9526
|
});
|
|
9290
9527
|
if (!nextWorkspace.success)
|
|
9291
|
-
return
|
|
9528
|
+
return failure2("invalid_input", "workspace mutation produced an invalid record");
|
|
9292
9529
|
const reserved = this.replaceSnapshot(this.workspacePath, nextWorkspace.data, previousWorkspaceBytes);
|
|
9293
9530
|
if (!reserved.ok)
|
|
9294
9531
|
return reserved;
|
|
@@ -9298,11 +9535,11 @@ class TaskStore {
|
|
|
9298
9535
|
changedTask = input.task(task.data, Object.freeze({ ...taskContext }));
|
|
9299
9536
|
} catch (error) {
|
|
9300
9537
|
this.markUncertain(nextWorkspace.data);
|
|
9301
|
-
return
|
|
9538
|
+
return failure2("external_outcome_unknown", `workspace reserved but task mutation threw: ${String(error)}`, { operation: "coupled_mutation", outcome: "unknown" });
|
|
9302
9539
|
}
|
|
9303
9540
|
if (!changedTask.ok) {
|
|
9304
9541
|
this.markUncertain(nextWorkspace.data);
|
|
9305
|
-
return
|
|
9542
|
+
return failure2("external_outcome_unknown", "workspace reserved but task update is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9306
9543
|
}
|
|
9307
9544
|
const nextTask = taskRecordSchema.safeParse({
|
|
9308
9545
|
...changedTask.data,
|
|
@@ -9315,12 +9552,12 @@ class TaskStore {
|
|
|
9315
9552
|
});
|
|
9316
9553
|
if (!nextTask.success) {
|
|
9317
9554
|
this.markUncertain(nextWorkspace.data);
|
|
9318
|
-
return
|
|
9555
|
+
return failure2("external_outcome_unknown", "workspace reserved but task update is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9319
9556
|
}
|
|
9320
9557
|
const written = this.replaceSnapshot(this.taskPath(input.taskId), nextTask.data, previousTaskBytes);
|
|
9321
9558
|
if (!written.ok) {
|
|
9322
9559
|
this.markUncertain(nextWorkspace.data);
|
|
9323
|
-
return
|
|
9560
|
+
return failure2("external_outcome_unknown", "workspace reserved but task replacement is uncertain", { operation: "coupled_mutation", outcome: "unknown" });
|
|
9324
9561
|
}
|
|
9325
9562
|
return success(nextTask.data.revision, nextWorkspace.data.revision, {
|
|
9326
9563
|
task: nextTask.data,
|
|
@@ -9344,7 +9581,7 @@ class TaskStore {
|
|
|
9344
9581
|
}
|
|
9345
9582
|
return success(null, null, candidates);
|
|
9346
9583
|
} catch (error) {
|
|
9347
|
-
return
|
|
9584
|
+
return failure2("storage_error", `unable to list recovery: ${String(error)}`, {
|
|
9348
9585
|
path: this.recoveryDir
|
|
9349
9586
|
});
|
|
9350
9587
|
}
|
|
@@ -9357,11 +9594,11 @@ class TaskStore {
|
|
|
9357
9594
|
}
|
|
9358
9595
|
recover(target, taskId, input) {
|
|
9359
9596
|
if (taskId !== null && !validId(taskId))
|
|
9360
|
-
return
|
|
9597
|
+
return failure2("invalid_input", "task ID is invalid", { taskId });
|
|
9361
9598
|
if (!input.reason || !Array.isArray(input.authorityRefs) || typeof input.processEvidence !== "function" || !validDigest(input.expectedBytes) || !validDigest(input.snapshotDigest))
|
|
9362
|
-
return
|
|
9599
|
+
return failure2("invalid_input", "recovery authority is invalid");
|
|
9363
9600
|
if (input.authorityRefs.some((ref) => !refSchema.safeParse(ref).success))
|
|
9364
|
-
return
|
|
9601
|
+
return failure2("invalid_input", "recovery references are invalid");
|
|
9365
9602
|
try {
|
|
9366
9603
|
const workspace = this.readWorkspace();
|
|
9367
9604
|
if (!workspace.ok && target === "task")
|
|
@@ -9372,14 +9609,14 @@ class TaskStore {
|
|
|
9372
9609
|
const file = target === "workspace" ? this.workspacePath : this.taskPath(taskId);
|
|
9373
9610
|
const currentBytes = this.snapshotBytes(file);
|
|
9374
9611
|
if (!currentBytes)
|
|
9375
|
-
return
|
|
9612
|
+
return failure2("not_found", "snapshot not found");
|
|
9376
9613
|
if (digestBytes(currentBytes) !== input.expectedBytes)
|
|
9377
|
-
return
|
|
9614
|
+
return failure2("revision_conflict", "snapshot bytes do not match expected bytes");
|
|
9378
9615
|
let selectedBytes = currentBytes;
|
|
9379
9616
|
if (digestBytes(currentBytes) !== input.snapshotDigest) {
|
|
9380
9617
|
const candidate = this.findRecovery(target, taskId, input.snapshotDigest, workspaceValue);
|
|
9381
9618
|
if (!candidate)
|
|
9382
|
-
return
|
|
9619
|
+
return failure2("recovery_required", "validated recovery snapshot not found");
|
|
9383
9620
|
selectedBytes = candidate;
|
|
9384
9621
|
}
|
|
9385
9622
|
const selectedRecord = target === "workspace" ? this.parseBytes(selectedBytes, workspaceRecordSchema) : this.parseBytes(selectedBytes, taskRecordSchema);
|
|
@@ -9388,11 +9625,11 @@ class TaskStore {
|
|
|
9388
9625
|
if (target === "workspace") {
|
|
9389
9626
|
const parsed = selectedRecord;
|
|
9390
9627
|
if (!parsed.ok || parsed.data.root !== this.root)
|
|
9391
|
-
return
|
|
9628
|
+
return failure2("recovery_required", "workspace recovery binding is invalid");
|
|
9392
9629
|
} else {
|
|
9393
9630
|
const parsed = selectedRecord;
|
|
9394
9631
|
if (!parsed.ok || parsed.data.id !== taskId || !workspaceValue || parsed.data.workspaceId !== workspaceValue.id)
|
|
9395
|
-
return
|
|
9632
|
+
return failure2("recovery_required", "task recovery binding is invalid");
|
|
9396
9633
|
}
|
|
9397
9634
|
const lock = this.readLockSnapshot();
|
|
9398
9635
|
if (!lock.ok)
|
|
@@ -9402,28 +9639,28 @@ class TaskStore {
|
|
|
9402
9639
|
if (!evidence.ok)
|
|
9403
9640
|
return evidence;
|
|
9404
9641
|
if (lock.data && (evidence.data.pid !== lock.data.data.pid || evidence.data.processStart !== lock.data.data.processStart))
|
|
9405
|
-
return
|
|
9642
|
+
return failure2("recovery_required", "process evidence does not match metadata lock");
|
|
9406
9643
|
if (writer && (evidence.data.state !== "accounted_for" || evidence.data.ownerDigest !== sha256(canonicalJson(writer))))
|
|
9407
|
-
return
|
|
9644
|
+
return failure2("recovery_required", "workspace writer is not accounted for");
|
|
9408
9645
|
const recoveryGate = { reclaimed: false };
|
|
9409
9646
|
const result = this.withLock((handle) => {
|
|
9410
9647
|
if (lock.data && !recoveryGate.reclaimed)
|
|
9411
|
-
return
|
|
9648
|
+
return failure2("recovery_required", "metadata lock changed during recovery", {
|
|
9412
9649
|
path: this.lockPath
|
|
9413
9650
|
});
|
|
9414
9651
|
if (!handle.verifyStillHeld())
|
|
9415
|
-
return
|
|
9652
|
+
return failure2("recovery_required", "metadata lock was compromised", {
|
|
9416
9653
|
path: this.lockPath
|
|
9417
9654
|
});
|
|
9418
9655
|
const reacquiredBytes = this.snapshotBytes(file);
|
|
9419
9656
|
if (!reacquiredBytes)
|
|
9420
|
-
return
|
|
9657
|
+
return failure2("recovery_required", "snapshot disappeared during recovery");
|
|
9421
9658
|
if (digestBytes(reacquiredBytes) !== input.expectedBytes)
|
|
9422
|
-
return
|
|
9659
|
+
return failure2("revision_conflict", "snapshot changed during recovery");
|
|
9423
9660
|
if (target === "task") {
|
|
9424
9661
|
const currentWorkspace = this.readWorkspace();
|
|
9425
9662
|
if (!currentWorkspace.ok || !currentWorkspace.data)
|
|
9426
|
-
return
|
|
9663
|
+
return failure2("recovery_required", "workspace changed during recovery");
|
|
9427
9664
|
if (currentWorkspace.data.revision !== input.expectedWorkspaceRevision)
|
|
9428
9665
|
return this.conflict(input.expectedWorkspaceRevision, currentWorkspace.data.revision);
|
|
9429
9666
|
}
|
|
@@ -9449,7 +9686,7 @@ class TaskStore {
|
|
|
9449
9686
|
}, this.recoveryLockOptions(lock.data, evidence.data, recoveryGate));
|
|
9450
9687
|
return result;
|
|
9451
9688
|
} catch (error) {
|
|
9452
|
-
return
|
|
9689
|
+
return failure2("recovery_required", `recovery protocol failed: ${String(error)}`);
|
|
9453
9690
|
}
|
|
9454
9691
|
}
|
|
9455
9692
|
processEvidence(input, lock, writer) {
|
|
@@ -9460,15 +9697,15 @@ class TaskStore {
|
|
|
9460
9697
|
try {
|
|
9461
9698
|
const result = input.processEvidence(lockCopy, writerCopy);
|
|
9462
9699
|
if (lockCopy && sha256(canonicalJson(lockCopy)) !== lockDigest)
|
|
9463
|
-
return
|
|
9700
|
+
return failure2("recovery_required", "process evidence mutated lock identity");
|
|
9464
9701
|
if (writerCopy && sha256(canonicalJson(writerCopy)) !== writerDigest)
|
|
9465
|
-
return
|
|
9702
|
+
return failure2("recovery_required", "process evidence mutated writer identity");
|
|
9466
9703
|
if (!result.ok)
|
|
9467
9704
|
return result;
|
|
9468
9705
|
const parsed = processEvidenceSchema.safeParse(result.data);
|
|
9469
|
-
return parsed.success ? success(null, null, parsed.data) :
|
|
9706
|
+
return parsed.success ? success(null, null, parsed.data) : failure2("recovery_required", "process evidence is invalid");
|
|
9470
9707
|
} catch (error) {
|
|
9471
|
-
return
|
|
9708
|
+
return failure2("recovery_required", `process evidence failed: ${String(error)}`);
|
|
9472
9709
|
}
|
|
9473
9710
|
}
|
|
9474
9711
|
deepFreeze(value) {
|
|
@@ -9483,7 +9720,7 @@ class TaskStore {
|
|
|
9483
9720
|
try {
|
|
9484
9721
|
const stat = fs4.lstatSync(this.lockPath);
|
|
9485
9722
|
if (!stat.isFile() || stat.isSymbolicLink())
|
|
9486
|
-
return
|
|
9723
|
+
return failure2("recovery_required", "metadata lock is not a regular file", {
|
|
9487
9724
|
path: this.lockPath
|
|
9488
9725
|
});
|
|
9489
9726
|
const raw = fs4.readFileSync(this.lockPath, "utf8");
|
|
@@ -9491,7 +9728,7 @@ class TaskStore {
|
|
|
9491
9728
|
} catch (error) {
|
|
9492
9729
|
if (error?.code === "ENOENT")
|
|
9493
9730
|
return success(null, null, null);
|
|
9494
|
-
return
|
|
9731
|
+
return failure2("recovery_required", `metadata lock is invalid: ${String(error)}`, {
|
|
9495
9732
|
path: this.lockPath
|
|
9496
9733
|
});
|
|
9497
9734
|
}
|
|
@@ -9524,7 +9761,7 @@ class TaskStore {
|
|
|
9524
9761
|
try {
|
|
9525
9762
|
this.initializeMutationStorage();
|
|
9526
9763
|
} catch (error) {
|
|
9527
|
-
return
|
|
9764
|
+
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
9528
9765
|
path: this.workitDir
|
|
9529
9766
|
});
|
|
9530
9767
|
}
|
|
@@ -9537,7 +9774,7 @@ class TaskStore {
|
|
|
9537
9774
|
let result;
|
|
9538
9775
|
try {
|
|
9539
9776
|
if (!handle.verifyStillHeld())
|
|
9540
|
-
result =
|
|
9777
|
+
result = failure2("recovery_required", "metadata lock was compromised", {
|
|
9541
9778
|
path: this.lockPath
|
|
9542
9779
|
});
|
|
9543
9780
|
else {
|
|
@@ -9545,25 +9782,25 @@ class TaskStore {
|
|
|
9545
9782
|
const run = () => operation();
|
|
9546
9783
|
result = await (reentrant ? externalActionLockRoots.run(new Set([...activeRoots ?? [], this.root]), run) : run());
|
|
9547
9784
|
} catch {
|
|
9548
|
-
result =
|
|
9785
|
+
result = failure2("external_outcome_unknown", "external action outcome is unknown", {
|
|
9549
9786
|
outcome: "unknown"
|
|
9550
9787
|
});
|
|
9551
9788
|
}
|
|
9552
9789
|
try {
|
|
9553
9790
|
if (!handle.verifyStillHeld())
|
|
9554
|
-
result =
|
|
9791
|
+
result = failure2("external_outcome_unknown", "metadata lock was compromised", {
|
|
9555
9792
|
outcome: "unknown",
|
|
9556
9793
|
path: this.lockPath
|
|
9557
9794
|
});
|
|
9558
9795
|
} catch {
|
|
9559
|
-
result =
|
|
9796
|
+
result = failure2("external_outcome_unknown", "metadata lock could not be verified", {
|
|
9560
9797
|
outcome: "unknown",
|
|
9561
9798
|
path: this.lockPath
|
|
9562
9799
|
});
|
|
9563
9800
|
}
|
|
9564
9801
|
}
|
|
9565
9802
|
} catch {
|
|
9566
|
-
result =
|
|
9803
|
+
result = failure2("external_outcome_unknown", "external action lock operation failed", {
|
|
9567
9804
|
outcome: "unknown",
|
|
9568
9805
|
path: this.lockPath
|
|
9569
9806
|
});
|
|
@@ -9573,10 +9810,10 @@ class TaskStore {
|
|
|
9573
9810
|
} catch (error) {
|
|
9574
9811
|
const released = this.lockFailure(error);
|
|
9575
9812
|
const releaseError = released.ok ? "metadata lock release failed" : released.error;
|
|
9576
|
-
return result.ok ?
|
|
9813
|
+
return result.ok ? failure2("external_outcome_unknown", "external action metadata lock release is uncertain", {
|
|
9577
9814
|
outcome: "unknown",
|
|
9578
9815
|
path: this.lockPath
|
|
9579
|
-
}) :
|
|
9816
|
+
}) : failure2("recovery_required", `${result.error}; ${releaseError}`, result.details);
|
|
9580
9817
|
}
|
|
9581
9818
|
return result;
|
|
9582
9819
|
}
|
|
@@ -9607,12 +9844,12 @@ class TaskStore {
|
|
|
9607
9844
|
try {
|
|
9608
9845
|
this.initializeMutationStorage();
|
|
9609
9846
|
} catch (error) {
|
|
9610
|
-
return
|
|
9847
|
+
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
9611
9848
|
path: this.workitDir
|
|
9612
9849
|
});
|
|
9613
9850
|
}
|
|
9614
9851
|
let handle;
|
|
9615
|
-
let result =
|
|
9852
|
+
let result = failure2("storage_error", "metadata lock operation did not produce a result");
|
|
9616
9853
|
try {
|
|
9617
9854
|
handle = acquireFileLockSync(this.workspacePath, options);
|
|
9618
9855
|
} catch (error) {
|
|
@@ -9621,14 +9858,14 @@ class TaskStore {
|
|
|
9621
9858
|
if (handle) {
|
|
9622
9859
|
try {
|
|
9623
9860
|
if (!handle.verifyStillHeld())
|
|
9624
|
-
result =
|
|
9861
|
+
result = failure2("recovery_required", "metadata lock was compromised", {
|
|
9625
9862
|
path: this.lockPath
|
|
9626
9863
|
});
|
|
9627
9864
|
else {
|
|
9628
9865
|
try {
|
|
9629
9866
|
result = operation(handle);
|
|
9630
9867
|
} catch (error) {
|
|
9631
|
-
result =
|
|
9868
|
+
result = failure2("storage_error", `mutation failed: ${String(error)}`);
|
|
9632
9869
|
}
|
|
9633
9870
|
}
|
|
9634
9871
|
} catch (error) {
|
|
@@ -9641,7 +9878,7 @@ class TaskStore {
|
|
|
9641
9878
|
} catch (error) {
|
|
9642
9879
|
const releaseFailure = this.lockFailure(error);
|
|
9643
9880
|
const releaseError = releaseFailure.ok ? "metadata lock release failed" : releaseFailure.error;
|
|
9644
|
-
result = result.ok ? releaseFailure :
|
|
9881
|
+
result = result.ok ? releaseFailure : failure2("recovery_required", `${result.error}; ${releaseError}`, result.details);
|
|
9645
9882
|
}
|
|
9646
9883
|
}
|
|
9647
9884
|
return result;
|
|
@@ -9652,13 +9889,13 @@ class TaskStore {
|
|
|
9652
9889
|
if (code === "EEXIST" || code === "file_lock_timeout") {
|
|
9653
9890
|
const lock = this.readLockSnapshot();
|
|
9654
9891
|
if (lock.ok && lock.data?.data.externalAction)
|
|
9655
|
-
return
|
|
9892
|
+
return failure2("writer_conflict", "workspace is reserved by a managed external action", {
|
|
9656
9893
|
outcome: "not_started",
|
|
9657
9894
|
path: this.lockPath
|
|
9658
9895
|
});
|
|
9659
9896
|
}
|
|
9660
9897
|
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));
|
|
9661
|
-
return
|
|
9898
|
+
return failure2(recovery ? "recovery_required" : "storage_error", `metadata lock operation failed: ${String(error)}`, { path: this.lockPath });
|
|
9662
9899
|
}
|
|
9663
9900
|
initializeMutationStorage() {
|
|
9664
9901
|
fs4.mkdirSync(this.tasksDir, { recursive: true });
|
|
@@ -9690,7 +9927,7 @@ class TaskStore {
|
|
|
9690
9927
|
this.indexTaskWrite(file, value);
|
|
9691
9928
|
return success(null, null, value);
|
|
9692
9929
|
} catch (error) {
|
|
9693
|
-
return
|
|
9930
|
+
return failure2("storage_error", `snapshot replacement failed: ${String(error)}`, {
|
|
9694
9931
|
path: file
|
|
9695
9932
|
});
|
|
9696
9933
|
} finally {
|
|
@@ -9846,7 +10083,7 @@ class TaskStore {
|
|
|
9846
10083
|
return { exists: false, result: success(null, null, null) };
|
|
9847
10084
|
return {
|
|
9848
10085
|
exists: true,
|
|
9849
|
-
result:
|
|
10086
|
+
result: failure2("recovery_required", `snapshot cannot be read: ${String(error)}`, {
|
|
9850
10087
|
path: file
|
|
9851
10088
|
})
|
|
9852
10089
|
};
|
|
@@ -9857,17 +10094,17 @@ class TaskStore {
|
|
|
9857
10094
|
try {
|
|
9858
10095
|
value = JSON.parse(typeof bytes === "string" ? bytes : bytes.toString("utf8"));
|
|
9859
10096
|
} catch {
|
|
9860
|
-
return
|
|
10097
|
+
return failure2("recovery_required", "snapshot JSON is corrupt");
|
|
9861
10098
|
}
|
|
9862
10099
|
if (isObject2(value) && "schemaVersion" in value && value.schemaVersion !== SCHEMA_VERSION)
|
|
9863
|
-
return
|
|
10100
|
+
return failure2("unsupported_version", "unsupported snapshot schema version");
|
|
9864
10101
|
const parsed = schema.safeParse(value);
|
|
9865
10102
|
if (parsed.success)
|
|
9866
10103
|
return success(null, null, parsed.data);
|
|
9867
10104
|
const writerVersion = isObject2(value) && isObject2(value.runtime) ? value.runtime.updatedWith : null;
|
|
9868
10105
|
if (typeof writerVersion === "string" && isNewerVersion(writerVersion, runtimeVersion()))
|
|
9869
|
-
return
|
|
9870
|
-
return
|
|
10106
|
+
return failure2("recovery_required", `snapshot was written by workit ${writerVersion}; upgrade Workit before mutating this checkout`);
|
|
10107
|
+
return failure2("recovery_required", "snapshot does not satisfy its schema");
|
|
9871
10108
|
}
|
|
9872
10109
|
processStart(pid) {
|
|
9873
10110
|
try {
|
|
@@ -9877,7 +10114,7 @@ class TaskStore {
|
|
|
9877
10114
|
}
|
|
9878
10115
|
}
|
|
9879
10116
|
conflict(expected, actual) {
|
|
9880
|
-
return
|
|
10117
|
+
return failure2("revision_conflict", "snapshot revision does not match; omit expectedRevision to use the current record", {
|
|
9881
10118
|
expectedRevision: expected,
|
|
9882
10119
|
actualRevision: actual
|
|
9883
10120
|
});
|
|
@@ -9955,10 +10192,10 @@ var processEvidenceSchema, metadataLockSchema, INDEX_VERSION = 1, hostSession =
|
|
|
9955
10192
|
updatedWith: runtimeVersion()
|
|
9956
10193
|
}), isNewerVersion = (candidate, current) => {
|
|
9957
10194
|
const parts = (value) => value.split("-")[0].split(".").map((item) => Number.parseInt(item, 10) || 0);
|
|
9958
|
-
const [
|
|
10195
|
+
const [candidateParts, currentParts] = [parts(candidate), parts(current)];
|
|
9959
10196
|
for (let index = 0;index < 3; index += 1) {
|
|
9960
|
-
const left =
|
|
9961
|
-
const right =
|
|
10197
|
+
const left = candidateParts[index] ?? 0;
|
|
10198
|
+
const right = currentParts[index] ?? 0;
|
|
9962
10199
|
if (left !== right)
|
|
9963
10200
|
return left > right;
|
|
9964
10201
|
}
|
|
@@ -10406,7 +10643,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
10406
10643
|
} catch (error) {
|
|
10407
10644
|
if (error.code === "ENOENT")
|
|
10408
10645
|
return null;
|
|
10409
|
-
throw new Error(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}
|
|
10646
|
+
throw new Error(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
10410
10647
|
}
|
|
10411
10648
|
let parsed;
|
|
10412
10649
|
try {
|
|
@@ -10766,9 +11003,9 @@ var init_branch = __esm(() => {
|
|
|
10766
11003
|
// packages/workit-core/src/core/workers.ts
|
|
10767
11004
|
function assertProductWriteAllowed(input) {
|
|
10768
11005
|
if (!Array.isArray(input.paths) || input.paths.some((path) => !validPath(path)))
|
|
10769
|
-
return
|
|
11006
|
+
return failure2("invalid_input", "invalid product write path");
|
|
10770
11007
|
if (!input.store)
|
|
10771
|
-
return
|
|
11008
|
+
return failure2("permission_denied", "write authorization requires core state");
|
|
10772
11009
|
const task = input.store.readTask(input.task.id);
|
|
10773
11010
|
if (!task.ok)
|
|
10774
11011
|
return task;
|
|
@@ -10776,29 +11013,29 @@ function assertProductWriteAllowed(input) {
|
|
|
10776
11013
|
if (!workspace.ok)
|
|
10777
11014
|
return workspace;
|
|
10778
11015
|
if (!workspace.data)
|
|
10779
|
-
return
|
|
11016
|
+
return failure2("not_found", "workspace not found");
|
|
10780
11017
|
const workspaceRecord = workspace.data;
|
|
10781
11018
|
if (task.data.status !== "active")
|
|
10782
|
-
return
|
|
11019
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
10783
11020
|
if (workspaceRecord.id !== task.data.workspaceId || workspaceRecord.root.length === 0)
|
|
10784
|
-
return
|
|
11021
|
+
return failure2("recovery_required", "task and workspace bindings are invalid");
|
|
10785
11022
|
const writer = workspaceRecord.writer;
|
|
10786
11023
|
if (!writer)
|
|
10787
|
-
return
|
|
11024
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
10788
11025
|
if (writer.state === "uncertain")
|
|
10789
|
-
return
|
|
11026
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
10790
11027
|
owner: writer.owner
|
|
10791
11028
|
});
|
|
10792
11029
|
const caller = callerValue(input.caller);
|
|
10793
11030
|
const workerId = workerIdOf(input.caller);
|
|
10794
11031
|
const owner = writer.owner;
|
|
10795
11032
|
if (owner.taskId !== task.data.id || owner.workerId !== workerId || owner.session.host !== caller.host || owner.session.handle !== caller.actor)
|
|
10796
|
-
return
|
|
11033
|
+
return failure2("writer_conflict", "checkout is owned by another validated actor", { owner });
|
|
10797
11034
|
const worker = workerId === null ? null : task.data.workers.find((entry) => entry.id === workerId);
|
|
10798
11035
|
if (workerId !== null && (!worker || worker.data.assignment.role !== "implementer"))
|
|
10799
|
-
return
|
|
11036
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
10800
11037
|
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))))
|
|
10801
|
-
return
|
|
11038
|
+
return failure2("recovery_required", "worker session is not an active writer");
|
|
10802
11039
|
return success(null, workspaceRecord.revision, owner);
|
|
10803
11040
|
}
|
|
10804
11041
|
var same = (left, right) => {
|
|
@@ -10807,7 +11044,7 @@ var same = (left, right) => {
|
|
|
10807
11044
|
} catch {
|
|
10808
11045
|
return false;
|
|
10809
11046
|
}
|
|
10810
|
-
}, UNCERTAIN_WORKER_STATES, isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state), workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state), callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor }, validPath = (value) => typeof value === "string" && value.length > 0 && !
|
|
11047
|
+
}, UNCERTAIN_WORKER_STATES, isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state), workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state), callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor }, validPath = (value) => typeof value === "string" && value.length > 0 && !Array.from(value).some((char) => {
|
|
10811
11048
|
const code = char.charCodeAt(0);
|
|
10812
11049
|
return code < 32 || code === 127;
|
|
10813
11050
|
}) && !value.split(/[\\/]/).includes(".."), callerValue = (value) => ({ host: value.host, actor: value.actor }), workerIdOf = (value) => value.workerId ?? null, currentWriterOwnsTask = (task, workspace, caller) => {
|
|
@@ -10898,15 +11135,15 @@ var AUTO_CLASSES, OPERATION_CLASS, operationAutoClass = (operation) => typeof op
|
|
|
10898
11135
|
};
|
|
10899
11136
|
}, verifyStandingApproval = (root, task, caller, binding) => {
|
|
10900
11137
|
if (task.status !== "active")
|
|
10901
|
-
return
|
|
11138
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
10902
11139
|
const workspace = new TaskStore(root).readWorkspace();
|
|
10903
11140
|
if (!workspace.ok)
|
|
10904
11141
|
return workspace;
|
|
10905
11142
|
if (!workspace.data || !currentWriterOwnsTask(task, workspace.data, caller))
|
|
10906
|
-
return
|
|
11143
|
+
return failure2("permission_denied", "standing approval requires the current writer session");
|
|
10907
11144
|
const standing = binding.standing;
|
|
10908
11145
|
if (!standing || typeof standing.workspace !== "string" || typeof standing.class !== "string")
|
|
10909
|
-
return
|
|
11146
|
+
return failure2("invalid_input", "standing approval needs a workspace and class");
|
|
10910
11147
|
let operation;
|
|
10911
11148
|
try {
|
|
10912
11149
|
operation = typeof binding.approvedContent === "string" ? JSON.parse(binding.approvedContent).operation : null;
|
|
@@ -10915,22 +11152,22 @@ var AUTO_CLASSES, OPERATION_CLASS, operationAutoClass = (operation) => typeof op
|
|
|
10915
11152
|
}
|
|
10916
11153
|
const cls = operationAutoClass(operation);
|
|
10917
11154
|
if (!cls || cls !== standing.class)
|
|
10918
|
-
return
|
|
11155
|
+
return failure2("permission_denied", "standing approval does not cover this operation");
|
|
10919
11156
|
const target = targetOf(root, binding.approvedContent);
|
|
10920
11157
|
if (!target)
|
|
10921
|
-
return
|
|
11158
|
+
return failure2("permission_denied", "standing action target is invalid");
|
|
10922
11159
|
const resolved = resolveAutoApproval(target);
|
|
10923
11160
|
if (resolved.status !== "on" || resolved.workspace !== standing.workspace || !resolved.classes.includes(cls))
|
|
10924
|
-
return
|
|
11161
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
10925
11162
|
if (cls === "push") {
|
|
10926
|
-
const
|
|
10927
|
-
const provider =
|
|
11163
|
+
const targetWorkspace = resolveWorkspaceFrom(target, configDir());
|
|
11164
|
+
const provider = targetWorkspace?.vcs?.provider;
|
|
10928
11165
|
const account = resolved.account;
|
|
10929
11166
|
if (!provider || !account)
|
|
10930
|
-
return
|
|
11167
|
+
return failure2("permission_denied", "auto-push requires a workspace provider and area account");
|
|
10931
11168
|
const identity = verifyPushIdentity(target, provider, account);
|
|
10932
11169
|
if (!identity.ok)
|
|
10933
|
-
return
|
|
11170
|
+
return failure2("permission_denied", identity.error);
|
|
10934
11171
|
}
|
|
10935
11172
|
return success(null, null, {
|
|
10936
11173
|
kind: "host_observed",
|
|
@@ -10968,22 +11205,22 @@ function applicableDecision(task, purpose, binding, checkoutRoot) {
|
|
|
10968
11205
|
}
|
|
10969
11206
|
function reserveAction(input) {
|
|
10970
11207
|
if (!input.store || !input.expectedRevision || !input.expectedWorkspaceRevision)
|
|
10971
|
-
return
|
|
11208
|
+
return failure2("invalid_input", "action reservation preconditions are required");
|
|
10972
11209
|
const authority = takeAuthority(input.authority, {
|
|
10973
11210
|
owner: input.authorityOwner,
|
|
10974
11211
|
store: input.store,
|
|
10975
11212
|
root: input.store.root
|
|
10976
11213
|
}, input.authorityCaller);
|
|
10977
11214
|
if (!authority)
|
|
10978
|
-
return
|
|
11215
|
+
return failure2("permission_denied", "native reservation authority is not verified");
|
|
10979
11216
|
const changed = input.store.mutateTask(input.taskId, input.expectedRevision, (current, mutation) => {
|
|
10980
11217
|
const workspace = input.store.readWorkspace();
|
|
10981
11218
|
if (!workspace.ok)
|
|
10982
11219
|
return workspace;
|
|
10983
11220
|
if (!workspace.data)
|
|
10984
|
-
return
|
|
11221
|
+
return failure2("not_found", "workspace not found");
|
|
10985
11222
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
10986
|
-
return
|
|
11223
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
10987
11224
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
10988
11225
|
actualWorkspaceRevision: workspace.data.revision
|
|
10989
11226
|
});
|
|
@@ -10993,19 +11230,19 @@ function reserveAction(input) {
|
|
|
10993
11230
|
const { entry, workflow } = valid.data;
|
|
10994
11231
|
const existing = entry.data.consumption;
|
|
10995
11232
|
if (existing?.state === "uncertain")
|
|
10996
|
-
return
|
|
11233
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
10997
11234
|
operation: "reserve_action",
|
|
10998
11235
|
outcome: "unknown"
|
|
10999
11236
|
});
|
|
11000
11237
|
if (existing?.state === "consumed")
|
|
11001
|
-
return
|
|
11238
|
+
return failure2("permission_denied", "action approval is consumed");
|
|
11002
11239
|
if (existing?.state === "reserved" && workflow.completed.length === 0)
|
|
11003
|
-
return
|
|
11240
|
+
return failure2("permission_denied", "action approval is already reserved");
|
|
11004
11241
|
const requestedStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11005
11242
|
if (workflow.steps.length && (!requestedStep || requestedStep !== workflow.steps[workflow.completed.length]))
|
|
11006
|
-
return
|
|
11243
|
+
return failure2("permission_denied", "action step is outside the approved remaining workflow");
|
|
11007
11244
|
if (requestedStep && workflow.completed.includes(requestedStep))
|
|
11008
|
-
return
|
|
11245
|
+
return failure2("permission_denied", "action step was already completed");
|
|
11009
11246
|
const nextDecision = {
|
|
11010
11247
|
...entry.data,
|
|
11011
11248
|
consumption: { state: "reserved", at: mutation.now, actionRef: input.actionRef }
|
|
@@ -11028,10 +11265,10 @@ function reserveAction(input) {
|
|
|
11028
11265
|
return changed;
|
|
11029
11266
|
const workspace = input.store.readWorkspace();
|
|
11030
11267
|
if (!workspace.ok || !workspace.data)
|
|
11031
|
-
return
|
|
11268
|
+
return failure2("recovery_required", "workspace disappeared after reservation");
|
|
11032
11269
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11033
11270
|
if (!entry)
|
|
11034
|
-
return
|
|
11271
|
+
return failure2("recovery_required", "reserved decision disappeared");
|
|
11035
11272
|
const workflow = changed.data.actionProgress?.find((progress) => progress.decisionId === input.decisionId) ?? {
|
|
11036
11273
|
steps: [],
|
|
11037
11274
|
completedSteps: []
|
|
@@ -11048,16 +11285,16 @@ function reserveAction(input) {
|
|
|
11048
11285
|
}
|
|
11049
11286
|
function settleAction(input) {
|
|
11050
11287
|
if (!input.store || !input.taskRevision || !input.workspaceRevision)
|
|
11051
|
-
return
|
|
11288
|
+
return failure2("invalid_input", "action settlement preconditions are required");
|
|
11052
11289
|
const authority = takeAuthority(input.authority, {
|
|
11053
11290
|
owner: input.authorityOwner,
|
|
11054
11291
|
store: input.store,
|
|
11055
11292
|
root: input.store.root
|
|
11056
11293
|
}, input.authorityCaller);
|
|
11057
11294
|
if (!authority)
|
|
11058
|
-
return
|
|
11295
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11059
11296
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11060
|
-
return
|
|
11297
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11061
11298
|
if (!authorityMatches(authority, {
|
|
11062
11299
|
taskId: input.taskId,
|
|
11063
11300
|
workspaceId: authority.workspaceId,
|
|
@@ -11067,14 +11304,14 @@ function settleAction(input) {
|
|
|
11067
11304
|
workspaceRevision: input.workspaceRevision,
|
|
11068
11305
|
outcome: input.outcome
|
|
11069
11306
|
}))
|
|
11070
|
-
return
|
|
11307
|
+
return failure2("permission_denied", "native settlement authority is not verified");
|
|
11071
11308
|
let outcomeResult = null;
|
|
11072
11309
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11073
11310
|
const workspace = input.store.readWorkspace();
|
|
11074
11311
|
if (!workspace.ok)
|
|
11075
11312
|
return workspace;
|
|
11076
11313
|
if (!workspace.data)
|
|
11077
|
-
return
|
|
11314
|
+
return failure2("not_found", "workspace not found");
|
|
11078
11315
|
if (!authorityMatches(authority, {
|
|
11079
11316
|
taskId: input.taskId,
|
|
11080
11317
|
workspaceId: workspace.data.id,
|
|
@@ -11084,39 +11321,39 @@ function settleAction(input) {
|
|
|
11084
11321
|
workspaceRevision: input.workspaceRevision,
|
|
11085
11322
|
outcome: input.outcome
|
|
11086
11323
|
}))
|
|
11087
|
-
return
|
|
11324
|
+
return failure2("permission_denied", "native settlement authority does not match context");
|
|
11088
11325
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11089
|
-
return
|
|
11326
|
+
return failure2("revision_conflict", "workspace revision does not match", {
|
|
11090
11327
|
expectedWorkspaceRevision: input.workspaceRevision,
|
|
11091
11328
|
actualWorkspaceRevision: workspace.data.revision
|
|
11092
11329
|
});
|
|
11093
11330
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11094
11331
|
if (!entry)
|
|
11095
|
-
return
|
|
11332
|
+
return failure2("not_found", "decision not found");
|
|
11096
11333
|
if (!authorityDecisionMatches(authority, entry.data))
|
|
11097
|
-
return
|
|
11334
|
+
return failure2("permission_denied", "native settlement authority does not match decision");
|
|
11098
11335
|
if (!approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11099
|
-
return
|
|
11336
|
+
return failure2("permission_denied", "native settlement caller does not match approval");
|
|
11100
11337
|
if (entry.data.purpose !== "action" || entry.data.digest !== decisionDigest(entry.data))
|
|
11101
|
-
return
|
|
11338
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11102
11339
|
if (entry.data.consumption?.state === "uncertain")
|
|
11103
|
-
return
|
|
11340
|
+
return failure2("external_outcome_unknown", "previous action outcome is unknown", {
|
|
11104
11341
|
operation: "settle_action",
|
|
11105
11342
|
outcome: "unknown"
|
|
11106
11343
|
});
|
|
11107
11344
|
if (entry.data.consumption?.state !== "reserved")
|
|
11108
|
-
return
|
|
11345
|
+
return failure2("permission_denied", "action is not reserved");
|
|
11109
11346
|
if (canonicalJson(entry.data.consumption.actionRef) !== canonicalJson(input.actionRef))
|
|
11110
|
-
return
|
|
11347
|
+
return failure2("permission_denied", "settlement reference does not match reservation");
|
|
11111
11348
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11112
11349
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: [], completed: [] };
|
|
11113
11350
|
if (entry.data.binding.approvedContent && !stored && (parseSteps(entry.data.binding.approvedContent) ?? []).length)
|
|
11114
|
-
return
|
|
11351
|
+
return failure2("recovery_required", "bounded action progress is missing");
|
|
11115
11352
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11116
11353
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11117
|
-
return
|
|
11354
|
+
return failure2("permission_denied", "settlement step is outside the approved workflow");
|
|
11118
11355
|
if (input.outcome === "unknown") {
|
|
11119
|
-
outcomeResult =
|
|
11356
|
+
outcomeResult = failure2("external_outcome_unknown", "external action outcome is unknown", {
|
|
11120
11357
|
operation: "settle_action",
|
|
11121
11358
|
outcome: "unknown"
|
|
11122
11359
|
});
|
|
@@ -11168,45 +11405,45 @@ function settleAction(input) {
|
|
|
11168
11405
|
return changed;
|
|
11169
11406
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11170
11407
|
if (!entry)
|
|
11171
|
-
return
|
|
11408
|
+
return failure2("recovery_required", "settled decision disappeared");
|
|
11172
11409
|
if (outcomeResult)
|
|
11173
11410
|
return outcomeResult;
|
|
11174
11411
|
return success(changed.data.revision, input.workspaceRevision, entry);
|
|
11175
11412
|
}
|
|
11176
11413
|
function reconcileAction(input) {
|
|
11177
11414
|
if (!input.store || !input.taskRevision || !input.workspaceRevision || !input.evidenceDigest)
|
|
11178
|
-
return
|
|
11415
|
+
return failure2("invalid_input", "action reconciliation preconditions are required");
|
|
11179
11416
|
const authority = takeAuthority(input.authority, { owner: input.authorityOwner, store: input.store, root: input.store.root }, input.authorityCaller);
|
|
11180
11417
|
if (!authority || authority.kind !== "reconciliation")
|
|
11181
|
-
return
|
|
11418
|
+
return failure2("permission_denied", "native reconciliation authority is not verified");
|
|
11182
11419
|
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)
|
|
11183
|
-
return
|
|
11420
|
+
return failure2("permission_denied", "native reconciliation authority is not bound");
|
|
11184
11421
|
const changed = input.store.mutateTask(input.taskId, input.taskRevision, (current, mutation) => {
|
|
11185
11422
|
const workspace = input.store.readWorkspace();
|
|
11186
11423
|
if (!workspace.ok)
|
|
11187
11424
|
return workspace;
|
|
11188
11425
|
if (!workspace.data)
|
|
11189
|
-
return
|
|
11426
|
+
return failure2("not_found", "workspace not found");
|
|
11190
11427
|
if (authority.workspaceId !== workspace.data.id)
|
|
11191
|
-
return
|
|
11428
|
+
return failure2("permission_denied", "native reconciliation workspace does not match");
|
|
11192
11429
|
if (workspace.data.revision !== input.workspaceRevision)
|
|
11193
|
-
return
|
|
11430
|
+
return failure2("revision_conflict", "workspace revision does not match");
|
|
11194
11431
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11195
11432
|
if (!entry || entry.data.purpose !== "action")
|
|
11196
|
-
return
|
|
11433
|
+
return failure2("not_found", "decision not found");
|
|
11197
11434
|
if (!authorityDecisionMatches(authority, entry.data) || !approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
|
|
11198
|
-
return
|
|
11435
|
+
return failure2("permission_denied", "native reconciliation caller does not match approval");
|
|
11199
11436
|
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)
|
|
11200
|
-
return
|
|
11437
|
+
return failure2("permission_denied", "reconciliation decision binding is invalid");
|
|
11201
11438
|
if (entry.data.consumption?.state !== "uncertain")
|
|
11202
|
-
return
|
|
11439
|
+
return failure2("external_outcome_unknown", "only an uncertain action can be reconciled");
|
|
11203
11440
|
if (!sameRef(entry.data.consumption.actionRef, input.actionRef))
|
|
11204
|
-
return
|
|
11441
|
+
return failure2("permission_denied", "reconciliation reference does not match reservation");
|
|
11205
11442
|
const stored = current.actionProgress?.find((progress) => progress.decisionId === input.decisionId);
|
|
11206
11443
|
const workflow = stored ? { steps: [...stored.steps], completed: [...stored.completedSteps] } : { steps: [], completed: [] };
|
|
11207
11444
|
const currentStep = input.step ?? workflow.steps[workflow.completed.length];
|
|
11208
11445
|
if (workflow.steps.length && (!currentStep || currentStep !== workflow.steps[workflow.completed.length]))
|
|
11209
|
-
return
|
|
11446
|
+
return failure2("permission_denied", "reconciliation step is outside the approved workflow");
|
|
11210
11447
|
if (input.outcome === "not_started") {
|
|
11211
11448
|
return success(mutation.revision, null, {
|
|
11212
11449
|
...current,
|
|
@@ -11237,7 +11474,7 @@ function reconcileAction(input) {
|
|
|
11237
11474
|
if (!changed.ok)
|
|
11238
11475
|
return changed;
|
|
11239
11476
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11240
|
-
return entry ? success(changed.data.revision, input.workspaceRevision, entry) :
|
|
11477
|
+
return entry ? success(changed.data.revision, input.workspaceRevision, entry) : failure2("recovery_required", "reconciled decision disappeared");
|
|
11241
11478
|
}
|
|
11242
11479
|
var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding, caller) => {
|
|
11243
11480
|
const token = {};
|
|
@@ -11294,10 +11531,10 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11294
11531
|
return provenance.kind === "host_observed" && provenance.host === caller.host && provenance.session?.kind === "host" && provenance.session.host === caller.host && provenance.session.handle === caller.actor && provenance.receipts.some((receipt) => receipt.kind === "host" && receipt.host === caller.host);
|
|
11295
11532
|
}, verifyNativeDecision = (verifier, input, binding) => {
|
|
11296
11533
|
if (!verifier)
|
|
11297
|
-
return
|
|
11534
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
11298
11535
|
const result = verifier.verifyDecision(input);
|
|
11299
11536
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
11300
|
-
return
|
|
11537
|
+
return failure2("permission_denied", "native decision observation was not attested");
|
|
11301
11538
|
return success(null, null, trustedAuthority("decision", result.data, {
|
|
11302
11539
|
taskId: input.expected.taskId,
|
|
11303
11540
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11310,10 +11547,10 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11310
11547
|
}, binding, input.caller));
|
|
11311
11548
|
}, verifyNativeAction = (verifier, input, binding) => {
|
|
11312
11549
|
if (!verifier)
|
|
11313
|
-
return
|
|
11550
|
+
return failure2("permission_denied", "native authority verifier is unavailable");
|
|
11314
11551
|
const result = verifier.verifyAction(input);
|
|
11315
11552
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
11316
|
-
return
|
|
11553
|
+
return failure2("permission_denied", "native action observation was not attested");
|
|
11317
11554
|
return success(null, null, trustedAuthority("action", result.data, {
|
|
11318
11555
|
taskId: input.expected.taskId,
|
|
11319
11556
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11330,10 +11567,10 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11330
11567
|
}, binding, input.caller));
|
|
11331
11568
|
}, verifyNativeReconciliation = (verifier, input, binding) => {
|
|
11332
11569
|
if (!verifier?.verifyReconciliation)
|
|
11333
|
-
return
|
|
11570
|
+
return failure2("permission_denied", "native reconciliation authority is unavailable");
|
|
11334
11571
|
const result = verifier.verifyReconciliation(input);
|
|
11335
11572
|
if (!result.ok || !validProvenance(result.data, input.caller))
|
|
11336
|
-
return
|
|
11573
|
+
return failure2("permission_denied", "native reconciliation observation was not attested");
|
|
11337
11574
|
return success(null, null, trustedAuthority("reconciliation", result.data, {
|
|
11338
11575
|
taskId: input.expected.taskId,
|
|
11339
11576
|
workspaceId: input.expected.workspaceId,
|
|
@@ -11367,16 +11604,16 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11367
11604
|
try {
|
|
11368
11605
|
root = fs6.realpathSync(checkoutRoot);
|
|
11369
11606
|
} catch {
|
|
11370
|
-
return
|
|
11607
|
+
return failure2("permission_denied", "checkout root is unavailable");
|
|
11371
11608
|
}
|
|
11372
11609
|
for (const reference of binding.contentRefs) {
|
|
11373
11610
|
if (reference.kind !== "file")
|
|
11374
11611
|
continue;
|
|
11375
11612
|
if (!reference.digest)
|
|
11376
|
-
return
|
|
11613
|
+
return failure2("invalid_input", "document references require a byte digest");
|
|
11377
11614
|
const target = path9.resolve(root, reference.path);
|
|
11378
11615
|
if (target !== root && !target.startsWith(`${root}${path9.sep}`))
|
|
11379
|
-
return
|
|
11616
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11380
11617
|
fields: [
|
|
11381
11618
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
11382
11619
|
]
|
|
@@ -11391,7 +11628,7 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11391
11628
|
const stat = fs6.lstatSync(current);
|
|
11392
11629
|
const real = fs6.realpathSync(current);
|
|
11393
11630
|
if (real !== root && !real.startsWith(`${root}${path9.sep}`))
|
|
11394
|
-
return
|
|
11631
|
+
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
11395
11632
|
fields: [
|
|
11396
11633
|
{
|
|
11397
11634
|
path: "contentRefs.path",
|
|
@@ -11400,16 +11637,16 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11400
11637
|
]
|
|
11401
11638
|
});
|
|
11402
11639
|
if (stat.isSymbolicLink())
|
|
11403
|
-
return
|
|
11640
|
+
return failure2("invalid_input", "document reference uses a symlink");
|
|
11404
11641
|
if (current === target && !stat.isFile())
|
|
11405
|
-
return
|
|
11642
|
+
return failure2("invalid_input", "document reference is not a regular file");
|
|
11406
11643
|
if (current !== target && !stat.isDirectory())
|
|
11407
|
-
return
|
|
11644
|
+
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
11408
11645
|
}
|
|
11409
11646
|
if (digestBytes2(fs6.readFileSync(target)) !== reference.digest)
|
|
11410
|
-
return
|
|
11647
|
+
return failure2("permission_denied", "approved document bytes have changed");
|
|
11411
11648
|
} catch {
|
|
11412
|
-
return
|
|
11649
|
+
return failure2("invalid_input", "approved document is unavailable");
|
|
11413
11650
|
}
|
|
11414
11651
|
}
|
|
11415
11652
|
return success(null, null, null);
|
|
@@ -11428,15 +11665,15 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11428
11665
|
});
|
|
11429
11666
|
}, validateAction = (store, task, workspaceId, input, authority) => {
|
|
11430
11667
|
if (task.status !== "active")
|
|
11431
|
-
return
|
|
11668
|
+
return failure2("invalid_transition", "only active tasks can authorize actions");
|
|
11432
11669
|
if (!refSchema.safeParse(input.actionRef).success)
|
|
11433
|
-
return
|
|
11670
|
+
return failure2("invalid_input", "action reference is invalid");
|
|
11434
11671
|
const entry = task.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
11435
11672
|
if (!entry)
|
|
11436
|
-
return
|
|
11673
|
+
return failure2("not_found", "decision not found");
|
|
11437
11674
|
const decision = entry.data;
|
|
11438
11675
|
if (decision.purpose !== "action")
|
|
11439
|
-
return
|
|
11676
|
+
return failure2("permission_denied", "decision is not an action approval");
|
|
11440
11677
|
if (!authorityMatches(authority, {
|
|
11441
11678
|
taskId: task.id,
|
|
11442
11679
|
workspaceId,
|
|
@@ -11446,13 +11683,13 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11446
11683
|
workspaceRevision: input.expectedWorkspaceRevision,
|
|
11447
11684
|
outcome: "reserve"
|
|
11448
11685
|
}))
|
|
11449
|
-
return
|
|
11686
|
+
return failure2("permission_denied", "native reservation authority is not bound");
|
|
11450
11687
|
if (!authorityDecisionMatches(authority, decision))
|
|
11451
|
-
return
|
|
11688
|
+
return failure2("permission_denied", "native reservation authority does not match decision");
|
|
11452
11689
|
if (decision.response !== "approved")
|
|
11453
|
-
return
|
|
11690
|
+
return failure2("permission_denied", "decision was rejected");
|
|
11454
11691
|
if (!approvalAuthorityMatches(store, task, entry.provenance, authority.provenance))
|
|
11455
|
-
return
|
|
11692
|
+
return failure2("permission_denied", "action approval lacks native receipt assurance");
|
|
11456
11693
|
const receipts = entry.provenance.receipts;
|
|
11457
11694
|
const standing = receipts.filter((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "standing");
|
|
11458
11695
|
const questionBacked = receipts.some((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "host");
|
|
@@ -11465,28 +11702,28 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
11465
11702
|
}
|
|
11466
11703
|
const cls = operationAutoClass(operation);
|
|
11467
11704
|
if (!cls || !standing.some((receipt) => standingApprovalLive(store.root, receipt, cls, undefined, decision.binding.approvedContent)))
|
|
11468
|
-
return
|
|
11705
|
+
return failure2("permission_denied", "standing auto-approval is not live for this operation");
|
|
11469
11706
|
}
|
|
11470
11707
|
if (decision.revoked)
|
|
11471
|
-
return
|
|
11708
|
+
return failure2("permission_denied", "decision is revoked");
|
|
11472
11709
|
if (decision.digest !== decisionDigest(decision))
|
|
11473
|
-
return
|
|
11710
|
+
return failure2("permission_denied", "decision binding is invalid");
|
|
11474
11711
|
if (decision.binding.taskId !== task.id || decision.binding.workspaceId !== workspaceId)
|
|
11475
|
-
return
|
|
11712
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
11476
11713
|
if (input.binding && canonicalJson(input.binding) !== canonicalJson(decision.binding))
|
|
11477
|
-
return
|
|
11714
|
+
return failure2("permission_denied", "action binding does not match the approved decision");
|
|
11478
11715
|
const content = verifyContentRefs(store, decision.binding);
|
|
11479
11716
|
if (!content.ok)
|
|
11480
11717
|
return content;
|
|
11481
11718
|
const requestedSteps = parseSteps(decision.binding.approvedContent);
|
|
11482
11719
|
if (requestedSteps === null)
|
|
11483
|
-
return
|
|
11720
|
+
return failure2("invalid_input", "bounded action steps must be a unique non-empty array");
|
|
11484
11721
|
if (input.steps && canonicalJson(input.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11485
|
-
return
|
|
11722
|
+
return failure2("permission_denied", "bounded action steps do not match approved content");
|
|
11486
11723
|
const stored = task.actionProgress?.find((item) => item.decisionId === input.decisionId);
|
|
11487
11724
|
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: requestedSteps.map(chainStepKey), completed: [] };
|
|
11488
11725
|
if (workflow.steps.length && requestedSteps.length && canonicalJson(workflow.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
11489
|
-
return
|
|
11726
|
+
return failure2("permission_denied", "bounded action scope changed");
|
|
11490
11727
|
return success(null, null, { entry, workflow });
|
|
11491
11728
|
}, bindingCovers, verifyDecisionContent;
|
|
11492
11729
|
var init_authority = __esm(() => {
|
|
@@ -11502,11 +11739,11 @@ var init_authority = __esm(() => {
|
|
|
11502
11739
|
function normalizeResolverInput(input) {
|
|
11503
11740
|
const parsed = resolverInputSchema.safeParse(input);
|
|
11504
11741
|
if (!parsed.success)
|
|
11505
|
-
return
|
|
11742
|
+
return failure2("invalid_input", "resolver input is invalid", invalidFields(parsed.error));
|
|
11506
11743
|
const value = parsed.data;
|
|
11507
11744
|
const signals = value.assessment.signals;
|
|
11508
11745
|
if (signals.behaviorChange.value === true && signals.mechanicalLowRisk.value === true)
|
|
11509
|
-
return
|
|
11746
|
+
return failure2("invalid_input", "behavioral change cannot be wholly mechanical", {
|
|
11510
11747
|
fields: [
|
|
11511
11748
|
{
|
|
11512
11749
|
path: "assessment.signals",
|
|
@@ -11516,11 +11753,11 @@ function normalizeResolverInput(input) {
|
|
|
11516
11753
|
});
|
|
11517
11754
|
const ids = value.constraints.map((constraint) => constraint.id);
|
|
11518
11755
|
if (new Set(ids).size !== ids.length)
|
|
11519
|
-
return
|
|
11756
|
+
return failure2("invalid_input", "constraint IDs must be unique", {
|
|
11520
11757
|
fields: [{ path: "constraints", reason: "duplicate constraint id" }]
|
|
11521
11758
|
});
|
|
11522
11759
|
if (value.preferences?.fast && value.preferences.thorough)
|
|
11523
|
-
return
|
|
11760
|
+
return failure2("invalid_input", "fast and thorough preferences contradict", {
|
|
11524
11761
|
fields: [{ path: "preferences", reason: "fast and thorough cannot both be enabled" }]
|
|
11525
11762
|
});
|
|
11526
11763
|
const normalized = {
|
|
@@ -11693,7 +11930,7 @@ function resolvePolicy(input) {
|
|
|
11693
11930
|
};
|
|
11694
11931
|
const parsed = policySchema.safeParse(policy);
|
|
11695
11932
|
if (!parsed.success)
|
|
11696
|
-
return
|
|
11933
|
+
return failure2("invalid_input", "resolved policy is invalid", invalidFields(parsed.error));
|
|
11697
11934
|
return success(null, null, parsed.data);
|
|
11698
11935
|
}
|
|
11699
11936
|
function diffPolicy(previous, next, reason, now) {
|
|
@@ -11701,10 +11938,10 @@ function diffPolicy(previous, next, reason, now) {
|
|
|
11701
11938
|
throw new TypeError("previous policy is invalid");
|
|
11702
11939
|
if (!policySchema.safeParse(next).success)
|
|
11703
11940
|
throw new TypeError("next policy is invalid");
|
|
11704
|
-
const oldIds = new Set(previous?.requirements.map((
|
|
11705
|
-
const newIds = new Set(next.requirements.map((
|
|
11706
|
-
const added = [...newIds].filter((id) => !oldIds.has(id)).
|
|
11707
|
-
const retired = [...oldIds].filter((id) => !newIds.has(id)).
|
|
11941
|
+
const oldIds = new Set(previous?.requirements.map((item) => item.id) ?? []);
|
|
11942
|
+
const newIds = new Set(next.requirements.map((item) => item.id));
|
|
11943
|
+
const added = [...newIds].filter((id) => !oldIds.has(id)).toSorted(compareCodeUnits2);
|
|
11944
|
+
const retired = [...oldIds].filter((id) => !newIds.has(id)).toSorted(compareCodeUnits2);
|
|
11708
11945
|
if (added.length === 0 && retired.length === 0)
|
|
11709
11946
|
return null;
|
|
11710
11947
|
const normalizedReason = reason.trim();
|
|
@@ -11730,7 +11967,7 @@ var resolverInputSchema, compareCodeUnits2 = (left, right) => {
|
|
|
11730
11967
|
return difference;
|
|
11731
11968
|
}
|
|
11732
11969
|
return left.length - right.length;
|
|
11733
|
-
}, stableUnique = (values) => [...new Set(values)].
|
|
11970
|
+
}, stableUnique = (values) => [...new Set(values)].toSorted(compareCodeUnits2), stableList = (values) => [...values].toSorted((left, right) => compareCodeUnits2(canonicalJson(left), canonicalJson(right))), normalizedScope = (scope) => ({
|
|
11734
11971
|
description: scope.description,
|
|
11735
11972
|
paths: stableUnique(scope.paths),
|
|
11736
11973
|
exclusions: stableUnique(scope.exclusions)
|
|
@@ -11827,11 +12064,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11827
12064
|
try {
|
|
11828
12065
|
checkout = fs7.realpathSync(root);
|
|
11829
12066
|
} catch {
|
|
11830
|
-
return
|
|
12067
|
+
return failure2("invalid_input", "candidate root does not exist");
|
|
11831
12068
|
}
|
|
11832
12069
|
const normalizedScope = canonicalScope(scope);
|
|
11833
12070
|
if (!normalizedScope)
|
|
11834
|
-
return
|
|
12071
|
+
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" }] });
|
|
11835
12072
|
const roots = scopeRoots(checkout, normalizedScope);
|
|
11836
12073
|
if (!roots.ok)
|
|
11837
12074
|
return roots;
|
|
@@ -11860,7 +12097,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11860
12097
|
names.add(item);
|
|
11861
12098
|
const files = [];
|
|
11862
12099
|
let completeness = uncertain ? "uncertain" : "known";
|
|
11863
|
-
for (const item of [...names].
|
|
12100
|
+
for (const item of [...names].toSorted()) {
|
|
11864
12101
|
if (!scopeMatches(item, normalizedScope))
|
|
11865
12102
|
continue;
|
|
11866
12103
|
const target = path10.join(checkout, item);
|
|
@@ -11894,8 +12131,8 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11894
12131
|
}));
|
|
11895
12132
|
const namesByEnvironment = supplied.map(({ name }) => name);
|
|
11896
12133
|
if (new Set(namesByEnvironment).size !== namesByEnvironment.length || namesByEnvironment.some((name) => typeof name !== "string" || !name))
|
|
11897
|
-
return
|
|
11898
|
-
const values = supplied.
|
|
12134
|
+
return failure2("invalid_input", "candidate environment names must be unique and non-empty");
|
|
12135
|
+
const values = supplied.toSorted((left, right) => compareCodeUnits3(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
|
|
11899
12136
|
if (values.some(({ value }) => value === null))
|
|
11900
12137
|
completeness = "uncertain";
|
|
11901
12138
|
const headResult = spawnSync2("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
|
|
@@ -11912,7 +12149,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
11912
12149
|
};
|
|
11913
12150
|
const candidate = { ...partial, id: candidateDigest(partial) };
|
|
11914
12151
|
const parsed = candidateSchema.safeParse(candidate);
|
|
11915
|
-
return parsed.success ? success(null, null, parsed.data) :
|
|
12152
|
+
return parsed.success ? success(null, null, parsed.data) : failure2("invalid_input", "captured candidate is invalid");
|
|
11916
12153
|
}
|
|
11917
12154
|
function evaluateEvidence(task, candidate) {
|
|
11918
12155
|
const current = candidate ?? task.candidates.at(-1) ?? null;
|
|
@@ -12055,13 +12292,13 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
12055
12292
|
}
|
|
12056
12293
|
function evaluateClosure(requestedOutcome, view) {
|
|
12057
12294
|
if (requestedOutcome !== "stopped" && !view.task.policy)
|
|
12058
|
-
return
|
|
12295
|
+
return failure2("requirements_unsatisfied", "task has not been assessed");
|
|
12059
12296
|
if (view.task.policy && view.task.policy.policyVersion !== POLICY_VERSION)
|
|
12060
|
-
return
|
|
12297
|
+
return failure2("requirements_unsatisfied", "stored policy version is unsupported; reassessment is required");
|
|
12061
12298
|
const evaluations = view.requirements;
|
|
12062
12299
|
const openFindings = view.task.findings.filter((entry) => entry.data.disposition === "open");
|
|
12063
12300
|
if (requestedOutcome !== "stopped" && openFindings.length)
|
|
12064
|
-
return
|
|
12301
|
+
return failure2("requirements_unsatisfied", "open findings must be resolved before closure");
|
|
12065
12302
|
if (requestedOutcome !== "stopped") {
|
|
12066
12303
|
const evidenceById = new Map(view.evidence.map((entry) => [entry.evidenceId, entry.status]));
|
|
12067
12304
|
for (const entry of view.task.findings) {
|
|
@@ -12077,7 +12314,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12077
12314
|
});
|
|
12078
12315
|
});
|
|
12079
12316
|
if (!verified)
|
|
12080
|
-
return
|
|
12317
|
+
return failure2("requirements_unsatisfied", "fixed findings require current verification");
|
|
12081
12318
|
}
|
|
12082
12319
|
if (entry.data.disposition === "deferred") {
|
|
12083
12320
|
const valid = entry.data.resolution?.decisionIds.some((id) => {
|
|
@@ -12086,7 +12323,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12086
12323
|
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)));
|
|
12087
12324
|
});
|
|
12088
12325
|
if (!valid)
|
|
12089
|
-
return
|
|
12326
|
+
return failure2("requirements_unsatisfied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
12090
12327
|
}
|
|
12091
12328
|
}
|
|
12092
12329
|
}
|
|
@@ -12097,7 +12334,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12097
12334
|
return !requirement || requirement.before === "close";
|
|
12098
12335
|
});
|
|
12099
12336
|
if (requestedOutcome !== "stopped" && blocking.length)
|
|
12100
|
-
return
|
|
12337
|
+
return failure2("requirements_unsatisfied", "applicable requirements are unsatisfied", {
|
|
12101
12338
|
requirementIds: blocking.map((item) => item.requirementId),
|
|
12102
12339
|
requirements: blocking.map((item) => {
|
|
12103
12340
|
const requirement = view.task.policy?.requirements.find((candidate) => candidate.id === item.requirementId);
|
|
@@ -12112,7 +12349,7 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
12112
12349
|
});
|
|
12113
12350
|
const accepted = evaluations.filter((item) => item.status === "accepted_limitation");
|
|
12114
12351
|
if (requestedOutcome === "verified" && accepted.length)
|
|
12115
|
-
return
|
|
12352
|
+
return failure2("requirements_unsatisfied", "accepted limitations cannot be reported as verified", {
|
|
12116
12353
|
requirementIds: accepted.map((item) => item.requirementId)
|
|
12117
12354
|
});
|
|
12118
12355
|
const evidenceIds = [
|
|
@@ -12178,7 +12415,7 @@ var digestBytes3 = (value) => createHash6("sha256").update(value).digest("hex"),
|
|
|
12178
12415
|
return {
|
|
12179
12416
|
paths: [],
|
|
12180
12417
|
uncertain: !/not a git repository/i.test(stderr),
|
|
12181
|
-
git:
|
|
12418
|
+
git: !/not a git repository/i.test(stderr)
|
|
12182
12419
|
};
|
|
12183
12420
|
}
|
|
12184
12421
|
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path10.sep).join("/")) : [];
|
|
@@ -12221,15 +12458,15 @@ var digestBytes3 = (value) => createHash6("sha256").update(value).digest("hex"),
|
|
|
12221
12458
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
12222
12459
|
const target = path10.resolve(root, item);
|
|
12223
12460
|
if (!inside(root, target))
|
|
12224
|
-
return
|
|
12461
|
+
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` }] });
|
|
12225
12462
|
let ancestor = target;
|
|
12226
12463
|
while (!fs7.existsSync(ancestor) && ancestor !== root)
|
|
12227
12464
|
ancestor = path10.dirname(ancestor);
|
|
12228
12465
|
try {
|
|
12229
12466
|
if (!inside(root, fs7.realpathSync(ancestor)))
|
|
12230
|
-
return
|
|
12467
|
+
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` }] });
|
|
12231
12468
|
} catch {
|
|
12232
|
-
return
|
|
12469
|
+
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
12233
12470
|
}
|
|
12234
12471
|
roots.push(target);
|
|
12235
12472
|
}
|
|
@@ -12424,7 +12661,7 @@ var init_methods = __esm(() => {
|
|
|
12424
12661
|
// packages/workit-core/src/core/task-context.ts
|
|
12425
12662
|
function reconcileResume(view, observations = []) {
|
|
12426
12663
|
if (observations.length > 0)
|
|
12427
|
-
return
|
|
12664
|
+
return failure2("permission_denied", "worker observations require native host verification");
|
|
12428
12665
|
const candidate = captureCandidate(view.workspace.root, view.task.intent.data.scope, []);
|
|
12429
12666
|
if (!candidate.ok)
|
|
12430
12667
|
return candidate;
|
|
@@ -12445,7 +12682,7 @@ function reconcileResume(view, observations = []) {
|
|
|
12445
12682
|
});
|
|
12446
12683
|
}
|
|
12447
12684
|
function compactTaskContext(view) {
|
|
12448
|
-
const decisions = view.task.decisions.slice().
|
|
12685
|
+
const decisions = view.task.decisions.slice().toSorted((left, right) => {
|
|
12449
12686
|
const leftAt = compactTimestamp(left.recordedAt);
|
|
12450
12687
|
const rightAt = compactTimestamp(right.recordedAt);
|
|
12451
12688
|
if (leftAt !== rightAt)
|
|
@@ -12468,7 +12705,7 @@ function compactTaskContext(view) {
|
|
|
12468
12705
|
...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
|
|
12469
12706
|
...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
|
|
12470
12707
|
...view.task.progress.blockers.map((entry) => entry.reason)
|
|
12471
|
-
])).
|
|
12708
|
+
])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
|
|
12472
12709
|
const context = {
|
|
12473
12710
|
objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
|
|
12474
12711
|
status: view.task.status,
|
|
@@ -12551,9 +12788,9 @@ class WorkitCore {
|
|
|
12551
12788
|
contextRootError() {
|
|
12552
12789
|
try {
|
|
12553
12790
|
if (realpathSync6(this.context.root) !== this.store.root)
|
|
12554
|
-
return
|
|
12791
|
+
return failure2("invalid_input", "operation context root does not match the task store root");
|
|
12555
12792
|
} catch {
|
|
12556
|
-
return
|
|
12793
|
+
return failure2("invalid_input", "operation context root cannot be resolved");
|
|
12557
12794
|
}
|
|
12558
12795
|
return success(null, null, null);
|
|
12559
12796
|
}
|
|
@@ -12572,16 +12809,16 @@ class WorkitCore {
|
|
|
12572
12809
|
helperEntry(task, requireSession = false, requireActive = false) {
|
|
12573
12810
|
const workerId = this.context.workerId ?? null;
|
|
12574
12811
|
if (workerId === null)
|
|
12575
|
-
return
|
|
12812
|
+
return failure2("permission_denied", "operation is lead-only");
|
|
12576
12813
|
const worker = task.workers.find((entry) => entry.id === workerId);
|
|
12577
12814
|
if (!worker)
|
|
12578
|
-
return
|
|
12815
|
+
return failure2("permission_denied", "worker is not assigned to this task");
|
|
12579
12816
|
if (worker.data.session && !sameSession2(worker.data.session, this.context))
|
|
12580
|
-
return
|
|
12817
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
12581
12818
|
if (requireSession && (!worker.data.session || !sameSession2(worker.data.session, this.context)))
|
|
12582
|
-
return
|
|
12819
|
+
return failure2("permission_denied", "worker session has not been observed");
|
|
12583
12820
|
if (requireActive && worker.data.state !== "running")
|
|
12584
|
-
return
|
|
12821
|
+
return failure2("permission_denied", "worker is not active");
|
|
12585
12822
|
return success(null, null, worker);
|
|
12586
12823
|
}
|
|
12587
12824
|
helperTaskGuard(task, allowRead = false) {
|
|
@@ -12590,13 +12827,13 @@ class WorkitCore {
|
|
|
12590
12827
|
const worker = this.helperEntry(task);
|
|
12591
12828
|
if (!worker.ok)
|
|
12592
12829
|
return worker;
|
|
12593
|
-
return allowRead ? success(null, null, null) :
|
|
12830
|
+
return allowRead ? success(null, null, null) : failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
12594
12831
|
}
|
|
12595
12832
|
activeWorkerBlocker(task, workspace) {
|
|
12596
12833
|
if (workspace.writer)
|
|
12597
|
-
return
|
|
12834
|
+
return failure2("recovery_required", "writer ownership must be released first");
|
|
12598
12835
|
if (task.workers.some((entry) => workerBlocksTransition("close", entry.data.state)))
|
|
12599
|
-
return
|
|
12836
|
+
return failure2("recovery_required", "worker state requires reconciliation");
|
|
12600
12837
|
return null;
|
|
12601
12838
|
}
|
|
12602
12839
|
state(request) {
|
|
@@ -12604,7 +12841,7 @@ class WorkitCore {
|
|
|
12604
12841
|
if (!root.ok)
|
|
12605
12842
|
return root;
|
|
12606
12843
|
if ((this.context.workerId ?? null) !== null)
|
|
12607
|
-
return
|
|
12844
|
+
return failure2("permission_denied", "helpers cannot control task state");
|
|
12608
12845
|
const parsed = parseOperation("state", request);
|
|
12609
12846
|
if (!parsed.ok)
|
|
12610
12847
|
return parsed;
|
|
@@ -12617,10 +12854,10 @@ class WorkitCore {
|
|
|
12617
12854
|
if (!workspace.ok)
|
|
12618
12855
|
return workspace;
|
|
12619
12856
|
if (!workspace.data)
|
|
12620
|
-
return
|
|
12857
|
+
return failure2("not_found", "workspace not found");
|
|
12621
12858
|
const portable = taskRecordSchema.safeParse(portableTask(task.data));
|
|
12622
12859
|
if (!portable.success)
|
|
12623
|
-
return
|
|
12860
|
+
return failure2("storage_error", "portable task is invalid after sanitization");
|
|
12624
12861
|
const bundle = {
|
|
12625
12862
|
schemaVersion: 1,
|
|
12626
12863
|
exportedAt: trustedNow(this.context),
|
|
@@ -12632,13 +12869,13 @@ class WorkitCore {
|
|
|
12632
12869
|
digest: exportDigest(bundle)
|
|
12633
12870
|
});
|
|
12634
12871
|
if (!checked.success)
|
|
12635
|
-
return
|
|
12872
|
+
return failure2("storage_error", "portable export bundle is invalid");
|
|
12636
12873
|
return success(task.data.revision, workspace.data.revision, checked.data);
|
|
12637
12874
|
}
|
|
12638
12875
|
if (input.action === "import") {
|
|
12639
12876
|
const checked = exportBundleSchema.safeParse(input.bundle);
|
|
12640
12877
|
if (!checked.success)
|
|
12641
|
-
return
|
|
12878
|
+
return failure2("invalid_input", "export bundle is invalid");
|
|
12642
12879
|
const bundle = checked.data;
|
|
12643
12880
|
if (bundle.sourceWorkspaceId !== bundle.task.workspaceId || exportDigest({
|
|
12644
12881
|
schemaVersion: bundle.schemaVersion,
|
|
@@ -12646,7 +12883,7 @@ class WorkitCore {
|
|
|
12646
12883
|
sourceWorkspaceId: bundle.sourceWorkspaceId,
|
|
12647
12884
|
task: bundle.task
|
|
12648
12885
|
}) !== bundle.digest)
|
|
12649
|
-
return
|
|
12886
|
+
return failure2("invalid_input", "export bundle digest is invalid");
|
|
12650
12887
|
const workspace = this.store.readWorkspace();
|
|
12651
12888
|
if (!workspace.ok)
|
|
12652
12889
|
return workspace;
|
|
@@ -12665,7 +12902,7 @@ class WorkitCore {
|
|
|
12665
12902
|
return this.summary(imported.data);
|
|
12666
12903
|
}
|
|
12667
12904
|
if (!this.context.nativeRecovery)
|
|
12668
|
-
return
|
|
12905
|
+
return failure2("permission_denied", "native recovery authority is unavailable");
|
|
12669
12906
|
const processEvidence = (lock, writer) => this.context.nativeRecovery({
|
|
12670
12907
|
lock,
|
|
12671
12908
|
writer,
|
|
@@ -12685,12 +12922,12 @@ class WorkitCore {
|
|
|
12685
12922
|
if (!workspace.ok)
|
|
12686
12923
|
return workspace;
|
|
12687
12924
|
if (!workspace.data)
|
|
12688
|
-
return
|
|
12925
|
+
return failure2("not_found", "workspace not found");
|
|
12689
12926
|
this.fillRevisions(input, undefined, workspace.data);
|
|
12690
12927
|
if (input.target === "workspace" && input.taskId !== undefined)
|
|
12691
|
-
return
|
|
12928
|
+
return failure2("invalid_input", "workspace recovery takes no task ID");
|
|
12692
12929
|
if (input.target === "task" && input.taskId === undefined)
|
|
12693
|
-
return
|
|
12930
|
+
return failure2("invalid_input", "task recovery requires a task ID");
|
|
12694
12931
|
return this.store.recoverTask(input.taskId, {
|
|
12695
12932
|
expectedBytes: input.expectedBytes,
|
|
12696
12933
|
snapshotDigest: input.snapshotDigest,
|
|
@@ -12710,7 +12947,7 @@ class WorkitCore {
|
|
|
12710
12947
|
const input = parsed.data;
|
|
12711
12948
|
if ((this.context.workerId ?? null) !== null) {
|
|
12712
12949
|
if (input.action !== "inspect" && input.action !== "list")
|
|
12713
|
-
return
|
|
12950
|
+
return failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
12714
12951
|
}
|
|
12715
12952
|
switch (input.action) {
|
|
12716
12953
|
case "start": {
|
|
@@ -12747,14 +12984,14 @@ class WorkitCore {
|
|
|
12747
12984
|
objective: task.intent.data.objective,
|
|
12748
12985
|
progress: task.progress,
|
|
12749
12986
|
decisions: task.decisions.map(({ data }) => data)
|
|
12750
|
-
}).toLowerCase().includes(term))).
|
|
12987
|
+
}).toLowerCase().includes(term))).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, limit);
|
|
12751
12988
|
if (selected.length === 0)
|
|
12752
12989
|
return success(null, null, []);
|
|
12753
12990
|
const workspace = this.store.readWorkspace();
|
|
12754
12991
|
if (!workspace.ok)
|
|
12755
12992
|
return workspace;
|
|
12756
12993
|
if (!workspace.data)
|
|
12757
|
-
return
|
|
12994
|
+
return failure2("not_found", "workspace not found");
|
|
12758
12995
|
const tasks = selected.map((task) => ({
|
|
12759
12996
|
id: task.id,
|
|
12760
12997
|
revision: task.revision,
|
|
@@ -12796,7 +13033,7 @@ class WorkitCore {
|
|
|
12796
13033
|
case "close":
|
|
12797
13034
|
return this.close(input);
|
|
12798
13035
|
default:
|
|
12799
|
-
return
|
|
13036
|
+
return failure2("invalid_transition", `task action ${input.action} is not implemented`);
|
|
12800
13037
|
}
|
|
12801
13038
|
}
|
|
12802
13039
|
policy(request) {
|
|
@@ -12813,7 +13050,7 @@ class WorkitCore {
|
|
|
12813
13050
|
if (input.action === "explain")
|
|
12814
13051
|
return success(task.data.revision, null, task.data.policy);
|
|
12815
13052
|
if ((this.context.workerId ?? null) !== null)
|
|
12816
|
-
return
|
|
13053
|
+
return failure2("permission_denied", "helpers cannot change task requirements");
|
|
12817
13054
|
this.fillRevisions(input, task.data);
|
|
12818
13055
|
const resolved = this.resolve(task.data, input.assessment);
|
|
12819
13056
|
if (!resolved.ok)
|
|
@@ -12821,10 +13058,10 @@ class WorkitCore {
|
|
|
12821
13058
|
if (input.action === "preview")
|
|
12822
13059
|
return success(null, null, resolved.data);
|
|
12823
13060
|
if (input.action !== "assess")
|
|
12824
|
-
return
|
|
13061
|
+
return failure2("invalid_transition", "unsupported policy action");
|
|
12825
13062
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
12826
13063
|
if (current.status === "closed")
|
|
12827
|
-
return
|
|
13064
|
+
return failure2("invalid_transition", "closed task cannot be assessed");
|
|
12828
13065
|
const nextChange = diffPolicy(current.policy, resolved.data, "policy reassessed", mutation.now);
|
|
12829
13066
|
const assessment = {
|
|
12830
13067
|
id: newId(),
|
|
@@ -12857,17 +13094,17 @@ class WorkitCore {
|
|
|
12857
13094
|
if (!task.ok)
|
|
12858
13095
|
return task;
|
|
12859
13096
|
if (task.data.status === "closed")
|
|
12860
|
-
return
|
|
13097
|
+
return failure2("invalid_transition", "closed task cannot record evidence");
|
|
12861
13098
|
this.fillRevisions(input, task.data);
|
|
12862
13099
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
12863
13100
|
if (helper && !helper.ok)
|
|
12864
13101
|
return helper;
|
|
12865
13102
|
const evidence = input.evidence;
|
|
12866
13103
|
if ((evidence.result === "missing" || evidence.result === "skipped") && !evidence.summary.trim())
|
|
12867
|
-
return
|
|
13104
|
+
return failure2("invalid_input", "missing or skipped evidence requires a reason");
|
|
12868
13105
|
if (evidence.kind === "review") {
|
|
12869
13106
|
if (!sameSession2(evidence.reviewContext, this.context))
|
|
12870
|
-
return
|
|
13107
|
+
return failure2("invalid_input", "review context must match the trusted caller session");
|
|
12871
13108
|
}
|
|
12872
13109
|
const currentCandidate = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
12873
13110
|
if (!currentCandidate.ok)
|
|
@@ -12877,12 +13114,12 @@ class WorkitCore {
|
|
|
12877
13114
|
if (helper?.ok) {
|
|
12878
13115
|
const assignment = helper.data.data.assignment;
|
|
12879
13116
|
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))
|
|
12880
|
-
return
|
|
13117
|
+
return failure2("permission_denied", "evidence is outside the worker assignment");
|
|
12881
13118
|
}
|
|
12882
13119
|
const knownCandidates = new Set(task.data.candidates.map((candidate) => candidate.id));
|
|
12883
13120
|
for (const candidateId of [bound.beforeCandidateId, bound.candidateId]) {
|
|
12884
13121
|
if (candidateId && candidateId !== currentCandidate.data.id && !knownCandidates.has(candidateId))
|
|
12885
|
-
return
|
|
13122
|
+
return failure2("invalid_input", "evidence candidate is not a captured candidate");
|
|
12886
13123
|
}
|
|
12887
13124
|
const boundEvidence = { ...evidence, ...bound };
|
|
12888
13125
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
@@ -12939,38 +13176,38 @@ class WorkitCore {
|
|
|
12939
13176
|
return parsed;
|
|
12940
13177
|
const input = parsed.data;
|
|
12941
13178
|
if (nativeRequired && input.action !== "record")
|
|
12942
|
-
return
|
|
13179
|
+
return failure2("permission_denied", "native observation is only valid for recording decisions");
|
|
12943
13180
|
const stated = input.action === "record" && input.response === "stated";
|
|
12944
13181
|
if (stated && input.purpose === "action")
|
|
12945
|
-
return
|
|
13182
|
+
return failure2("permission_denied", "stated choices cannot authorize mutating actions");
|
|
12946
13183
|
if (stated && !input.binding?.statedChoice)
|
|
12947
|
-
return
|
|
13184
|
+
return failure2("invalid_input", "stated choices require binding.statedChoice");
|
|
12948
13185
|
if (nativeRequired && nativeObservation === undefined && !stated && !standing)
|
|
12949
|
-
return
|
|
13186
|
+
return failure2("permission_denied", "native decision observation is required");
|
|
12950
13187
|
if (standing && (!input.binding?.standing || input.purpose !== "action" || input.response !== "approved"))
|
|
12951
|
-
return
|
|
13188
|
+
return failure2("invalid_input", "standing approvals need an approved action binding with a standing rule");
|
|
12952
13189
|
const task = this.store.readTask(input.taskId);
|
|
12953
13190
|
if (!task.ok)
|
|
12954
13191
|
return task;
|
|
12955
13192
|
if ((this.context.workerId ?? null) !== null)
|
|
12956
|
-
return
|
|
13193
|
+
return failure2("permission_denied", "helpers cannot record or revoke decisions");
|
|
12957
13194
|
this.fillRevisions(input, task.data);
|
|
12958
13195
|
if (input.action === "record") {
|
|
12959
13196
|
if (task.data.status === "closed")
|
|
12960
|
-
return
|
|
13197
|
+
return failure2("invalid_transition", "closed task cannot record a decision");
|
|
12961
13198
|
const workspace = this.store.readWorkspace();
|
|
12962
13199
|
if (!workspace.ok)
|
|
12963
13200
|
return workspace;
|
|
12964
13201
|
if (!workspace.data)
|
|
12965
|
-
return
|
|
13202
|
+
return failure2("not_found", "workspace not found");
|
|
12966
13203
|
if (input.binding.taskId !== task.data.id || input.binding.workspaceId !== workspace.data.id)
|
|
12967
|
-
return
|
|
13204
|
+
return failure2("permission_denied", "decision task or workspace binding is invalid");
|
|
12968
13205
|
const content = verifyDecisionContent(this.store, input.binding);
|
|
12969
13206
|
if (!content.ok)
|
|
12970
13207
|
return content;
|
|
12971
13208
|
const knownRequirements = new Set(task.data.policy?.requirements.map((item) => item.id) ?? []);
|
|
12972
13209
|
if (input.requirementIds.some((id) => !knownRequirements.has(id)))
|
|
12973
|
-
return
|
|
13210
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
12974
13211
|
const base = {
|
|
12975
13212
|
purpose: input.purpose,
|
|
12976
13213
|
binding: input.binding,
|
|
@@ -13001,16 +13238,16 @@ class WorkitCore {
|
|
|
13001
13238
|
return native;
|
|
13002
13239
|
const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
|
|
13003
13240
|
if (native?.ok && !nativeProvenance)
|
|
13004
|
-
return
|
|
13241
|
+
return failure2("permission_denied", "native decision authority was retired");
|
|
13005
13242
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13006
|
-
const
|
|
13007
|
-
if (!
|
|
13008
|
-
return
|
|
13243
|
+
const latestContent = verifyDecisionContent(this.store, input.binding);
|
|
13244
|
+
if (!latestContent.ok)
|
|
13245
|
+
return latestContent;
|
|
13009
13246
|
const known = new Set(current.policy?.requirements.map((item) => item.id) ?? []);
|
|
13010
13247
|
if (input.requirementIds.some((id) => !known.has(id)))
|
|
13011
|
-
return
|
|
13248
|
+
return failure2("invalid_input", "decision references an unknown requirement");
|
|
13012
13249
|
if (nativeProvenance && current.decisions.some((entry) => entry.provenance.receipts.some((existingReceipt) => nativeProvenance.receipts.some((receipt) => canonicalJson(receipt) === canonicalJson(existingReceipt)))))
|
|
13013
|
-
return
|
|
13250
|
+
return failure2("permission_denied", "native decision receipt was already consumed");
|
|
13014
13251
|
const entry = {
|
|
13015
13252
|
id: newId(),
|
|
13016
13253
|
recordedAt: mutation.now,
|
|
@@ -13028,21 +13265,21 @@ class WorkitCore {
|
|
|
13028
13265
|
}
|
|
13029
13266
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13030
13267
|
if (!decision)
|
|
13031
|
-
return
|
|
13268
|
+
return failure2("not_found", "decision not found");
|
|
13032
13269
|
if (!input.reason.trim())
|
|
13033
|
-
return
|
|
13270
|
+
return failure2("invalid_input", "decision revocation requires a reason");
|
|
13034
13271
|
if (decision.data.revoked)
|
|
13035
|
-
return
|
|
13272
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13036
13273
|
if (decision.data.consumption)
|
|
13037
|
-
return
|
|
13274
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13038
13275
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13039
13276
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13040
13277
|
if (!entry)
|
|
13041
|
-
return
|
|
13278
|
+
return failure2("not_found", "decision not found");
|
|
13042
13279
|
if (entry.data.revoked)
|
|
13043
|
-
return
|
|
13280
|
+
return failure2("invalid_transition", "decision is already revoked");
|
|
13044
13281
|
if (entry.data.consumption)
|
|
13045
|
-
return
|
|
13282
|
+
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
13046
13283
|
const data = {
|
|
13047
13284
|
...entry.data,
|
|
13048
13285
|
revoked: { at: mutation.now, reason: input.reason }
|
|
@@ -13056,7 +13293,7 @@ class WorkitCore {
|
|
|
13056
13293
|
if (!changed.ok)
|
|
13057
13294
|
return changed;
|
|
13058
13295
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
13059
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13296
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
|
|
13060
13297
|
}
|
|
13061
13298
|
finding(request) {
|
|
13062
13299
|
const root = this.contextRootError();
|
|
@@ -13070,7 +13307,7 @@ class WorkitCore {
|
|
|
13070
13307
|
if (!task.ok)
|
|
13071
13308
|
return task;
|
|
13072
13309
|
if (task.data.status === "closed")
|
|
13073
|
-
return
|
|
13310
|
+
return failure2("invalid_transition", "closed task cannot mutate findings");
|
|
13074
13311
|
this.fillRevisions(input, task.data);
|
|
13075
13312
|
const helper = (this.context.workerId ?? null) === null ? null : this.helperEntry(task.data, true, true);
|
|
13076
13313
|
if (helper && !helper.ok)
|
|
@@ -13079,10 +13316,10 @@ class WorkitCore {
|
|
|
13079
13316
|
if (helper?.ok) {
|
|
13080
13317
|
const assignment = helper.data.data.assignment;
|
|
13081
13318
|
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))
|
|
13082
|
-
return
|
|
13319
|
+
return failure2("permission_denied", "finding is outside the worker assignment");
|
|
13083
13320
|
}
|
|
13084
13321
|
if (input.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.candidateId))
|
|
13085
|
-
return
|
|
13322
|
+
return failure2("invalid_input", "finding candidate is not a captured candidate");
|
|
13086
13323
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13087
13324
|
const entry = {
|
|
13088
13325
|
id: newId(),
|
|
@@ -13108,16 +13345,16 @@ class WorkitCore {
|
|
|
13108
13345
|
return success(changed.data.revision, null, changed.data.findings.at(-1));
|
|
13109
13346
|
}
|
|
13110
13347
|
if (helper?.ok)
|
|
13111
|
-
return
|
|
13348
|
+
return failure2("permission_denied", "helpers cannot resolve findings");
|
|
13112
13349
|
const finding = task.data.findings.find((entry) => entry.id === input.findingId);
|
|
13113
13350
|
if (!finding)
|
|
13114
|
-
return
|
|
13351
|
+
return failure2("not_found", "finding not found");
|
|
13115
13352
|
if (!input.reason.trim())
|
|
13116
|
-
return
|
|
13353
|
+
return failure2("invalid_input", "finding resolution requires a reason");
|
|
13117
13354
|
const evidence = task.data.evidence.filter((entry) => input.evidenceIds.includes(entry.id));
|
|
13118
13355
|
const decisions = task.data.decisions.filter((entry) => input.decisionIds.includes(entry.id));
|
|
13119
13356
|
if (evidence.length !== input.evidenceIds.length || decisions.length !== input.decisionIds.length)
|
|
13120
|
-
return
|
|
13357
|
+
return failure2("invalid_input", "finding resolution references an unknown record");
|
|
13121
13358
|
if (input.disposition === "fixed") {
|
|
13122
13359
|
const current = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
13123
13360
|
if (!current.ok)
|
|
@@ -13132,10 +13369,10 @@ class WorkitCore {
|
|
|
13132
13369
|
});
|
|
13133
13370
|
});
|
|
13134
13371
|
if (!verified)
|
|
13135
|
-
return
|
|
13372
|
+
return failure2("permission_denied", "fixed findings require passing verification evidence");
|
|
13136
13373
|
}
|
|
13137
13374
|
if (input.disposition === "dismissed" && evidence.length === 0)
|
|
13138
|
-
return
|
|
13375
|
+
return failure2("permission_denied", "dismissal requires supporting evidence");
|
|
13139
13376
|
if (input.disposition === "dismissed") {
|
|
13140
13377
|
const relevant = evidence.every((entry) => {
|
|
13141
13378
|
if (entry.data.result === "missing" || entry.data.result === "skipped")
|
|
@@ -13145,22 +13382,22 @@ class WorkitCore {
|
|
|
13145
13382
|
return candidateMatches && (referenceMatches || entry.data.claim === finding.data.claim);
|
|
13146
13383
|
});
|
|
13147
13384
|
if (!relevant)
|
|
13148
|
-
return
|
|
13385
|
+
return failure2("permission_denied", "dismissal evidence is unrelated to the finding");
|
|
13149
13386
|
}
|
|
13150
13387
|
if (input.disposition === "deferred") {
|
|
13151
13388
|
const workspace = this.store.readWorkspace();
|
|
13152
13389
|
if (!workspace.ok)
|
|
13153
13390
|
return workspace;
|
|
13154
13391
|
if (!workspace.data)
|
|
13155
|
-
return
|
|
13392
|
+
return failure2("not_found", "workspace not found");
|
|
13156
13393
|
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)));
|
|
13157
13394
|
if (!allowed)
|
|
13158
|
-
return
|
|
13395
|
+
return failure2("permission_denied", "deferred findings require an approved limitation decision that references an acceptanceAllowed requirement and covers the finding scope");
|
|
13159
13396
|
}
|
|
13160
13397
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
13161
13398
|
const existing = current.findings.find((entry) => entry.id === input.findingId);
|
|
13162
13399
|
if (!existing)
|
|
13163
|
-
return
|
|
13400
|
+
return failure2("not_found", "finding not found");
|
|
13164
13401
|
const data = input.disposition === "open" ? { ...existing.data, disposition: "open", resolution: null } : {
|
|
13165
13402
|
...existing.data,
|
|
13166
13403
|
disposition: input.disposition,
|
|
@@ -13179,7 +13416,7 @@ class WorkitCore {
|
|
|
13179
13416
|
if (!changed.ok)
|
|
13180
13417
|
return changed;
|
|
13181
13418
|
const entry = changed.data.findings.find((candidate) => candidate.id === input.findingId);
|
|
13182
|
-
return entry ? success(changed.data.revision, null, entry) :
|
|
13419
|
+
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
|
|
13183
13420
|
}
|
|
13184
13421
|
worker(request) {
|
|
13185
13422
|
const root = this.contextRootError();
|
|
@@ -13196,16 +13433,16 @@ class WorkitCore {
|
|
|
13196
13433
|
if (!workspace.ok)
|
|
13197
13434
|
return workspace;
|
|
13198
13435
|
if (!workspace.data)
|
|
13199
|
-
return
|
|
13436
|
+
return failure2("not_found", "workspace not found");
|
|
13200
13437
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13201
13438
|
const helperId = this.context.workerId ?? null;
|
|
13202
13439
|
if (input.action === "assign") {
|
|
13203
13440
|
if (helperId !== null)
|
|
13204
|
-
return
|
|
13441
|
+
return failure2("permission_denied", "helpers cannot assign workers");
|
|
13205
13442
|
if (task.data.status !== "active")
|
|
13206
|
-
return
|
|
13443
|
+
return failure2("invalid_transition", "paused or closed tasks cannot assign workers");
|
|
13207
13444
|
if (!bindingCovers(task.data.intent.data.scope, input.assignment.scope))
|
|
13208
|
-
return
|
|
13445
|
+
return failure2("permission_denied", "worker assignment is outside task scope", {
|
|
13209
13446
|
fields: [
|
|
13210
13447
|
{
|
|
13211
13448
|
path: "assignment.scope",
|
|
@@ -13218,14 +13455,14 @@ class WorkitCore {
|
|
|
13218
13455
|
]
|
|
13219
13456
|
});
|
|
13220
13457
|
if (input.assignment.decisionIds.some((id) => !task.data.decisions.some((entry) => entry.id === id)))
|
|
13221
|
-
return
|
|
13458
|
+
return failure2("invalid_input", "worker assignment references an unknown decision");
|
|
13222
13459
|
if (input.assignment.requirementIds.some((id) => !task.data.policy?.requirements.some((requirement) => requirement.id === id)))
|
|
13223
|
-
return
|
|
13460
|
+
return failure2("invalid_input", "worker assignment references an unknown requirement");
|
|
13224
13461
|
const reviewRequirements = (task.data.policy?.requirements ?? []).filter((requirement) => requirement.dimension === "review");
|
|
13225
13462
|
if (input.assignment.role === "reviewer" && input.assignment.requirementIds.length === 0 && reviewRequirements.length)
|
|
13226
|
-
return
|
|
13463
|
+
return failure2("invalid_input", "reviewer assignment needs the review requirement ids it will evidence", { requirementIds: reviewRequirements.map((requirement) => requirement.id) });
|
|
13227
13464
|
if (input.assignment.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.assignment.candidateId))
|
|
13228
|
-
return
|
|
13465
|
+
return failure2("invalid_input", "worker assignment references an unknown candidate");
|
|
13229
13466
|
input.assignment.candidateId ??= null;
|
|
13230
13467
|
const workerId = newId();
|
|
13231
13468
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
@@ -13253,19 +13490,19 @@ class WorkitCore {
|
|
|
13253
13490
|
}
|
|
13254
13491
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13255
13492
|
if (!entry)
|
|
13256
|
-
return
|
|
13493
|
+
return failure2("not_found", "worker not found");
|
|
13257
13494
|
if (input.action === "report") {
|
|
13258
13495
|
if (helperId === null || helperId !== input.workerId)
|
|
13259
|
-
return
|
|
13496
|
+
return failure2("permission_denied", "workers can submit only their own report");
|
|
13260
13497
|
const helper = this.helperEntry(task.data, true, true);
|
|
13261
13498
|
if (!helper.ok)
|
|
13262
13499
|
return helper;
|
|
13263
13500
|
const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
|
|
13264
13501
|
const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
|
|
13265
13502
|
if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
|
|
13266
|
-
return
|
|
13503
|
+
return failure2("invalid_input", "worker report references an unknown record");
|
|
13267
13504
|
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)))
|
|
13268
|
-
return
|
|
13505
|
+
return failure2("permission_denied", "worker report is outside the worker assignment");
|
|
13269
13506
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
13270
13507
|
taskId: task.data.id,
|
|
13271
13508
|
expectedRevision: input.expectedRevision,
|
|
@@ -13284,14 +13521,14 @@ class WorkitCore {
|
|
|
13284
13521
|
if (!changed.ok)
|
|
13285
13522
|
return changed;
|
|
13286
13523
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
13287
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
13524
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
|
|
13288
13525
|
}
|
|
13289
13526
|
if (helperId !== null)
|
|
13290
|
-
return
|
|
13527
|
+
return failure2("permission_denied", "helpers cannot cancel or control workers");
|
|
13291
13528
|
if (task.data.status === "closed")
|
|
13292
|
-
return
|
|
13529
|
+
return failure2("invalid_transition", "closed task cannot cancel workers");
|
|
13293
13530
|
if (entry.data.state === "unknown")
|
|
13294
|
-
return
|
|
13531
|
+
return failure2("recovery_required", "worker state requires recovery");
|
|
13295
13532
|
if (entry.data.state === "stopped") {
|
|
13296
13533
|
const stopped = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13297
13534
|
return success(task.data.revision, workspace.data.revision, stopped);
|
|
@@ -13323,7 +13560,7 @@ class WorkitCore {
|
|
|
13323
13560
|
if (!root.ok)
|
|
13324
13561
|
return root;
|
|
13325
13562
|
if (this.context.workerId !== undefined && this.context.workerId !== null && this.context.workerId !== input.workerId)
|
|
13326
|
-
return
|
|
13563
|
+
return failure2("permission_denied", "worker observation does not match the caller");
|
|
13327
13564
|
const task = this.store.readTask(input.taskId);
|
|
13328
13565
|
if (!task.ok)
|
|
13329
13566
|
return task;
|
|
@@ -13331,7 +13568,7 @@ class WorkitCore {
|
|
|
13331
13568
|
if (!workspace.ok)
|
|
13332
13569
|
return workspace;
|
|
13333
13570
|
if (!workspace.data)
|
|
13334
|
-
return
|
|
13571
|
+
return failure2("not_found", "workspace not found");
|
|
13335
13572
|
const authority = verifyNativeWorker(this.context.nativeWorker, {
|
|
13336
13573
|
observation: input.observation,
|
|
13337
13574
|
expected: { ...input, workspaceId: workspace.data.id },
|
|
@@ -13357,7 +13594,7 @@ class WorkitCore {
|
|
|
13357
13594
|
verifyDispatch(stage, input, workspaceId) {
|
|
13358
13595
|
const verifier = this.context.nativeWorker?.verifyDispatch;
|
|
13359
13596
|
if (!verifier)
|
|
13360
|
-
return
|
|
13597
|
+
return failure2("permission_denied", "native worker dispatch attestation is unavailable");
|
|
13361
13598
|
let result;
|
|
13362
13599
|
try {
|
|
13363
13600
|
result = verifier({
|
|
@@ -13373,10 +13610,10 @@ class WorkitCore {
|
|
|
13373
13610
|
caller: this.context.caller
|
|
13374
13611
|
});
|
|
13375
13612
|
} catch (error) {
|
|
13376
|
-
return
|
|
13613
|
+
return failure2("permission_denied", `native worker dispatch failed: ${String(error)}`);
|
|
13377
13614
|
}
|
|
13378
13615
|
if (!result.ok || !validDispatchProvenance(result.data, this.context.caller, input.workerId))
|
|
13379
|
-
return
|
|
13616
|
+
return failure2("permission_denied", "worker dispatch was not attested by the host");
|
|
13380
13617
|
return result;
|
|
13381
13618
|
}
|
|
13382
13619
|
prepareWorkerDispatch(input) {
|
|
@@ -13384,7 +13621,7 @@ class WorkitCore {
|
|
|
13384
13621
|
if (!root.ok)
|
|
13385
13622
|
return root;
|
|
13386
13623
|
if ((this.context.workerId ?? null) !== null)
|
|
13387
|
-
return
|
|
13624
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13388
13625
|
const task = this.store.readTask(input.taskId);
|
|
13389
13626
|
if (!task.ok)
|
|
13390
13627
|
return task;
|
|
@@ -13392,16 +13629,16 @@ class WorkitCore {
|
|
|
13392
13629
|
if (!workspace.ok)
|
|
13393
13630
|
return workspace;
|
|
13394
13631
|
if (!workspace.data)
|
|
13395
|
-
return
|
|
13632
|
+
return failure2("not_found", "workspace not found");
|
|
13396
13633
|
if (task.data.workspaceId !== workspace.data.id)
|
|
13397
|
-
return
|
|
13634
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13398
13635
|
if (task.data.status !== "active")
|
|
13399
|
-
return
|
|
13636
|
+
return failure2("invalid_transition", "paused or closed tasks cannot dispatch workers");
|
|
13400
13637
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
13401
13638
|
if (!entry)
|
|
13402
|
-
return
|
|
13639
|
+
return failure2("not_found", "worker not found");
|
|
13403
13640
|
if (entry.data.state !== "assigned" || entry.data.session !== null)
|
|
13404
|
-
return
|
|
13641
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13405
13642
|
const attested = this.verifyDispatch("prepare", input, workspace.data.id);
|
|
13406
13643
|
if (!attested.ok)
|
|
13407
13644
|
return attested;
|
|
@@ -13414,9 +13651,9 @@ class WorkitCore {
|
|
|
13414
13651
|
task: (current, mutation) => {
|
|
13415
13652
|
const candidate = current.workers.find((item) => item.id === input.workerId);
|
|
13416
13653
|
if (!candidate)
|
|
13417
|
-
return
|
|
13654
|
+
return failure2("not_found", "worker not found");
|
|
13418
13655
|
if (candidate.data.state !== "assigned" || candidate.data.session !== null)
|
|
13419
|
-
return
|
|
13656
|
+
return failure2("invalid_transition", "worker is not awaiting dispatch");
|
|
13420
13657
|
return success(mutation.revision, null, {
|
|
13421
13658
|
...current,
|
|
13422
13659
|
workers: current.workers.map((item) => item.id === input.workerId ? {
|
|
@@ -13455,17 +13692,17 @@ class WorkitCore {
|
|
|
13455
13692
|
if (!root.ok)
|
|
13456
13693
|
return root;
|
|
13457
13694
|
if ((this.context.workerId ?? null) !== null)
|
|
13458
|
-
return
|
|
13695
|
+
return failure2("permission_denied", "helpers cannot dispatch workers");
|
|
13459
13696
|
const reservation = dispatchReservations.get(input.dispatch);
|
|
13460
13697
|
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)
|
|
13461
|
-
return
|
|
13698
|
+
return failure2("permission_denied", "worker dispatch reservation is not live");
|
|
13462
13699
|
const workspace = this.store.readWorkspace();
|
|
13463
13700
|
if (!workspace.ok)
|
|
13464
13701
|
return workspace;
|
|
13465
13702
|
if (!workspace.data)
|
|
13466
|
-
return
|
|
13703
|
+
return failure2("not_found", "workspace not found");
|
|
13467
13704
|
if (workspace.data.id !== reservation.workspaceId)
|
|
13468
|
-
return
|
|
13705
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
13469
13706
|
const observation = {
|
|
13470
13707
|
taskId: input.taskId,
|
|
13471
13708
|
workerId: input.workerId,
|
|
@@ -13478,7 +13715,7 @@ class WorkitCore {
|
|
|
13478
13715
|
let authority;
|
|
13479
13716
|
if (input.outcome === "started") {
|
|
13480
13717
|
if (!input.session)
|
|
13481
|
-
return
|
|
13718
|
+
return failure2("invalid_input", "a started worker requires a session");
|
|
13482
13719
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
13483
13720
|
observation: input.observation,
|
|
13484
13721
|
expected: { ...observation, workspaceId: workspace.data.id },
|
|
@@ -13494,7 +13731,7 @@ class WorkitCore {
|
|
|
13494
13731
|
authority = verified.data;
|
|
13495
13732
|
} else {
|
|
13496
13733
|
if (input.session !== null)
|
|
13497
|
-
return
|
|
13734
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
13498
13735
|
const attested = this.verifyDispatch("not_started", input, workspace.data.id);
|
|
13499
13736
|
if (!attested.ok)
|
|
13500
13737
|
return attested;
|
|
@@ -13543,31 +13780,31 @@ class WorkitCore {
|
|
|
13543
13780
|
if (!workspace.ok)
|
|
13544
13781
|
return workspace;
|
|
13545
13782
|
if (!workspace.data)
|
|
13546
|
-
return
|
|
13783
|
+
return failure2("not_found", "workspace not found");
|
|
13547
13784
|
if (task.data.status !== "active")
|
|
13548
|
-
return
|
|
13785
|
+
return failure2("invalid_transition", "paused or closed tasks cannot own product writes");
|
|
13549
13786
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13550
13787
|
const helperId = this.context.workerId ?? null;
|
|
13551
13788
|
if (input.action === "acquire") {
|
|
13552
13789
|
if (input.workerId === undefined)
|
|
13553
13790
|
input.workerId = helperId;
|
|
13554
13791
|
if (input.workerId !== helperId)
|
|
13555
|
-
return
|
|
13792
|
+
return failure2("permission_denied", "writer identity does not match the caller");
|
|
13556
13793
|
if (workspace.data.writer) {
|
|
13557
13794
|
if (workspace.data.writer.state === "uncertain")
|
|
13558
|
-
return
|
|
13795
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
13559
13796
|
owner: workspace.data.writer.owner
|
|
13560
13797
|
});
|
|
13561
13798
|
const currentOwner = workspace.data.writer.owner;
|
|
13562
13799
|
if (currentOwner.workerId) {
|
|
13563
13800
|
const ownerWorker = task.data.workers.find((candidate) => candidate.id === currentOwner.workerId);
|
|
13564
13801
|
if (ownerWorker?.data.state === "cancelling" || ownerWorker?.data.state === "unknown")
|
|
13565
|
-
return
|
|
13802
|
+
return failure2("recovery_required", "current worker has not stopped", {
|
|
13566
13803
|
owner: currentOwner
|
|
13567
13804
|
});
|
|
13568
13805
|
}
|
|
13569
13806
|
if (currentOwner.workerId !== null || helperId !== null)
|
|
13570
|
-
return
|
|
13807
|
+
return failure2("writer_conflict", "checkout already has a writer", {
|
|
13571
13808
|
owner: currentOwner
|
|
13572
13809
|
});
|
|
13573
13810
|
}
|
|
@@ -13576,17 +13813,17 @@ class WorkitCore {
|
|
|
13576
13813
|
if (!helper.ok)
|
|
13577
13814
|
return helper;
|
|
13578
13815
|
if (helper.data.data.assignment.role !== "implementer")
|
|
13579
|
-
return
|
|
13816
|
+
return failure2("permission_denied", "only implementers can own product writes");
|
|
13580
13817
|
if (helper.data.data.state !== "running" || !helper.data.data.session)
|
|
13581
|
-
return
|
|
13818
|
+
return failure2("permission_denied", "writer ownership requires an observed running worker");
|
|
13582
13819
|
if (!sameSession2(helper.data.data.session, this.context))
|
|
13583
|
-
return
|
|
13820
|
+
return failure2("permission_denied", "worker session does not match the caller");
|
|
13584
13821
|
}
|
|
13585
13822
|
const gate = this.view(task.data);
|
|
13586
13823
|
if (gate.ok) {
|
|
13587
13824
|
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")));
|
|
13588
13825
|
if (writeGates.length)
|
|
13589
|
-
return
|
|
13826
|
+
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) });
|
|
13590
13827
|
}
|
|
13591
13828
|
const owner = {
|
|
13592
13829
|
taskId: task.data.id,
|
|
@@ -13614,19 +13851,19 @@ class WorkitCore {
|
|
|
13614
13851
|
}
|
|
13615
13852
|
const current = workspace.data.writer;
|
|
13616
13853
|
if (!current)
|
|
13617
|
-
return
|
|
13854
|
+
return failure2("permission_denied", "checkout has no writer owner");
|
|
13618
13855
|
if (current.state === "uncertain")
|
|
13619
|
-
return
|
|
13856
|
+
return failure2("recovery_required", "checkout writer requires recovery", {
|
|
13620
13857
|
owner: current.owner
|
|
13621
13858
|
});
|
|
13622
13859
|
if (current.owner.taskId !== task.data.id || current.owner.workerId !== helperId || !sameSession2(current.owner.session, this.context))
|
|
13623
|
-
return
|
|
13860
|
+
return failure2("permission_denied", "only the current writer can release ownership");
|
|
13624
13861
|
if (helperId !== null) {
|
|
13625
13862
|
const helper = this.helperEntry(task.data);
|
|
13626
13863
|
if (!helper.ok)
|
|
13627
13864
|
return helper;
|
|
13628
13865
|
if (helper.data.data.state !== "running")
|
|
13629
|
-
return
|
|
13866
|
+
return failure2("recovery_required", "worker must be observed stopped before release");
|
|
13630
13867
|
}
|
|
13631
13868
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
13632
13869
|
taskId: task.data.id,
|
|
@@ -13658,9 +13895,9 @@ class WorkitCore {
|
|
|
13658
13895
|
if (!root.ok)
|
|
13659
13896
|
return root;
|
|
13660
13897
|
if ((this.context.workerId ?? null) !== null)
|
|
13661
|
-
return
|
|
13898
|
+
return failure2("permission_denied", "helpers cannot reserve external actions");
|
|
13662
13899
|
if (input.observation === undefined)
|
|
13663
|
-
return
|
|
13900
|
+
return failure2("invalid_input", "native action observation is required");
|
|
13664
13901
|
const task = this.store.readTask(input.taskId);
|
|
13665
13902
|
if (!task.ok)
|
|
13666
13903
|
return task;
|
|
@@ -13668,10 +13905,10 @@ class WorkitCore {
|
|
|
13668
13905
|
if (!workspace.ok)
|
|
13669
13906
|
return workspace;
|
|
13670
13907
|
if (!workspace.data)
|
|
13671
|
-
return
|
|
13908
|
+
return failure2("not_found", "workspace not found");
|
|
13672
13909
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13673
13910
|
if (!decision)
|
|
13674
|
-
return
|
|
13911
|
+
return failure2("not_found", "decision not found");
|
|
13675
13912
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
13676
13913
|
observation: input.observation,
|
|
13677
13914
|
expected: {
|
|
@@ -13696,7 +13933,7 @@ class WorkitCore {
|
|
|
13696
13933
|
const evaluations = new Map(view.data.requirements.map((entry) => [entry.requirementId, entry.status]));
|
|
13697
13934
|
const blocked = (view.data.task.policy?.requirements ?? []).filter((requirement) => requirement.dependentAction === operation && (evaluations.get(requirement.id) === "unsatisfied" || evaluations.get(requirement.id) === "unavailable"));
|
|
13698
13935
|
if (blocked.length)
|
|
13699
|
-
return
|
|
13936
|
+
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) });
|
|
13700
13937
|
}
|
|
13701
13938
|
return reserveAction({
|
|
13702
13939
|
...input,
|
|
@@ -13712,9 +13949,9 @@ class WorkitCore {
|
|
|
13712
13949
|
if (!root.ok)
|
|
13713
13950
|
return root;
|
|
13714
13951
|
if ((this.context.workerId ?? null) !== null)
|
|
13715
|
-
return
|
|
13952
|
+
return failure2("permission_denied", "helpers cannot settle external actions");
|
|
13716
13953
|
if (input.observation === undefined)
|
|
13717
|
-
return
|
|
13954
|
+
return failure2("invalid_input", "native action observation is required");
|
|
13718
13955
|
const task = this.store.readTask(input.taskId);
|
|
13719
13956
|
if (!task.ok)
|
|
13720
13957
|
return task;
|
|
@@ -13722,10 +13959,10 @@ class WorkitCore {
|
|
|
13722
13959
|
if (!workspace.ok)
|
|
13723
13960
|
return workspace;
|
|
13724
13961
|
if (!workspace.data)
|
|
13725
|
-
return
|
|
13962
|
+
return failure2("not_found", "workspace not found");
|
|
13726
13963
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13727
13964
|
if (!decision)
|
|
13728
|
-
return
|
|
13965
|
+
return failure2("not_found", "decision not found");
|
|
13729
13966
|
const authority = verifyNativeAction(this.context.nativeAuthority, {
|
|
13730
13967
|
observation: input.observation,
|
|
13731
13968
|
expected: {
|
|
@@ -13756,7 +13993,7 @@ class WorkitCore {
|
|
|
13756
13993
|
if (!root.ok)
|
|
13757
13994
|
return root;
|
|
13758
13995
|
if ((this.context.workerId ?? null) !== null)
|
|
13759
|
-
return
|
|
13996
|
+
return failure2("permission_denied", "helpers cannot reconcile external actions");
|
|
13760
13997
|
const task = this.store.readTask(input.taskId);
|
|
13761
13998
|
if (!task.ok)
|
|
13762
13999
|
return task;
|
|
@@ -13764,10 +14001,10 @@ class WorkitCore {
|
|
|
13764
14001
|
if (!workspace.ok)
|
|
13765
14002
|
return workspace;
|
|
13766
14003
|
if (!workspace.data)
|
|
13767
|
-
return
|
|
14004
|
+
return failure2("not_found", "workspace not found");
|
|
13768
14005
|
const decision = task.data.decisions.find((entry) => entry.id === input.decisionId);
|
|
13769
14006
|
if (!decision)
|
|
13770
|
-
return
|
|
14007
|
+
return failure2("not_found", "decision not found");
|
|
13771
14008
|
const authority = verifyNativeReconciliation(this.context.nativeAuthority, {
|
|
13772
14009
|
observation: input.observation,
|
|
13773
14010
|
expected: {
|
|
@@ -13814,7 +14051,7 @@ class WorkitCore {
|
|
|
13814
14051
|
if (!workspace.ok)
|
|
13815
14052
|
return workspace;
|
|
13816
14053
|
if (!workspace.data)
|
|
13817
|
-
return
|
|
14054
|
+
return failure2("not_found", "workspace not found");
|
|
13818
14055
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
13819
14056
|
const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
|
|
13820
14057
|
if (!current.ok)
|
|
@@ -13857,7 +14094,7 @@ class WorkitCore {
|
|
|
13857
14094
|
if (!workspace.ok)
|
|
13858
14095
|
return workspace;
|
|
13859
14096
|
if (!workspace.data)
|
|
13860
|
-
return
|
|
14097
|
+
return failure2("not_found", "workspace not found");
|
|
13861
14098
|
const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
|
|
13862
14099
|
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);
|
|
13863
14100
|
if (!current.ok)
|
|
@@ -13877,14 +14114,14 @@ class WorkitCore {
|
|
|
13877
14114
|
if (!root.ok)
|
|
13878
14115
|
return root;
|
|
13879
14116
|
if ((this.context.workerId ?? null) !== null)
|
|
13880
|
-
return
|
|
14117
|
+
return failure2("permission_denied", "helpers cannot reconcile task workers");
|
|
13881
14118
|
if (view.task.workspaceId !== view.workspace.id)
|
|
13882
|
-
return
|
|
14119
|
+
return failure2("invalid_input", "task and workspace bindings are invalid");
|
|
13883
14120
|
try {
|
|
13884
14121
|
if (realpathSync6(view.workspace.root) !== this.store.root)
|
|
13885
|
-
return
|
|
14122
|
+
return failure2("invalid_input", "task view root does not match the task store");
|
|
13886
14123
|
} catch {
|
|
13887
|
-
return
|
|
14124
|
+
return failure2("invalid_input", "task view root cannot be resolved");
|
|
13888
14125
|
}
|
|
13889
14126
|
const updates = [];
|
|
13890
14127
|
const seen = new Set;
|
|
@@ -13896,7 +14133,7 @@ class WorkitCore {
|
|
|
13896
14133
|
};
|
|
13897
14134
|
for (const observation of observations) {
|
|
13898
14135
|
if (seen.has(observation.workerId))
|
|
13899
|
-
return
|
|
14136
|
+
return failure2("invalid_input", "worker observations must be unique");
|
|
13900
14137
|
seen.add(observation.workerId);
|
|
13901
14138
|
const freshTask = this.store.readTask(view.task.id);
|
|
13902
14139
|
const freshWorkspace = this.store.readWorkspace();
|
|
@@ -13905,11 +14142,11 @@ class WorkitCore {
|
|
|
13905
14142
|
if (!freshWorkspace.ok)
|
|
13906
14143
|
return freshWorkspace;
|
|
13907
14144
|
if (!freshWorkspace.data)
|
|
13908
|
-
return
|
|
14145
|
+
return failure2("not_found", "workspace not found");
|
|
13909
14146
|
if (observation.taskId !== view.task.id || observation.expectedRevision !== freshTask.data.revision || observation.expectedWorkspaceRevision !== freshWorkspace.data.revision)
|
|
13910
|
-
return
|
|
14147
|
+
return failure2("revision_conflict", "worker observation is stale");
|
|
13911
14148
|
if (!view.task.workers.some((entry) => entry.id === observation.workerId))
|
|
13912
|
-
return
|
|
14149
|
+
return failure2("permission_denied", "worker observation is not assigned");
|
|
13913
14150
|
const verified = verifyNativeWorker(this.context.nativeWorker, {
|
|
13914
14151
|
observation: observation.observation,
|
|
13915
14152
|
expected: { ...observation, workspaceId: view.workspace.id },
|
|
@@ -13918,7 +14155,7 @@ class WorkitCore {
|
|
|
13918
14155
|
if (!verified.ok)
|
|
13919
14156
|
return verified;
|
|
13920
14157
|
if (!takeWorker(verified.data, binding, observation))
|
|
13921
|
-
return
|
|
14158
|
+
return failure2("permission_denied", "worker observation authority was not retained");
|
|
13922
14159
|
updates.push(observation);
|
|
13923
14160
|
}
|
|
13924
14161
|
const observedStates = new Map(updates.map((entry) => [entry.workerId, entry.state]));
|
|
@@ -13956,19 +14193,19 @@ class WorkitCore {
|
|
|
13956
14193
|
if (!helper.ok)
|
|
13957
14194
|
return helper;
|
|
13958
14195
|
if (status === "paused" && task.data.status !== "active" || status === "active" && task.data.status !== "paused")
|
|
13959
|
-
return
|
|
14196
|
+
return failure2("invalid_transition", `cannot transition ${task.data.status} to ${status}`);
|
|
13960
14197
|
const workspace = this.store.readWorkspace();
|
|
13961
14198
|
if (!workspace.ok)
|
|
13962
14199
|
return workspace;
|
|
13963
14200
|
if (!workspace.data)
|
|
13964
|
-
return
|
|
14201
|
+
return failure2("not_found", "workspace not found");
|
|
13965
14202
|
this.fillRevisions(input, task.data, workspace.data);
|
|
13966
14203
|
let resumeCandidate = null;
|
|
13967
14204
|
if (status === "active" && task.data.origin) {
|
|
13968
14205
|
if (!task.data.policy)
|
|
13969
|
-
return
|
|
14206
|
+
return failure2("needs_input", "imported task requires a current policy");
|
|
13970
14207
|
if (task.data.policy.policyVersion !== POLICY_VERSION)
|
|
13971
|
-
return
|
|
14208
|
+
return failure2("needs_input", "stored policy version is unsupported; reassessment is required");
|
|
13972
14209
|
const view = this.view(task.data);
|
|
13973
14210
|
if (!view.ok)
|
|
13974
14211
|
return view;
|
|
@@ -13977,20 +14214,20 @@ class WorkitCore {
|
|
|
13977
14214
|
return current;
|
|
13978
14215
|
const requirements = view.data.requirements;
|
|
13979
14216
|
if (requirements.some((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable"))
|
|
13980
|
-
return
|
|
14217
|
+
return failure2("requirements_unsatisfied", "imported task requires current requirements", {
|
|
13981
14218
|
requirementIds: requirements.filter((requirement) => requirement.status === "unsatisfied" || requirement.status === "unavailable").map((requirement) => requirement.requirementId)
|
|
13982
14219
|
});
|
|
13983
14220
|
if (current.data.reassessmentRequired)
|
|
13984
|
-
return
|
|
14221
|
+
return failure2("needs_input", "imported task requires destination policy reassessment");
|
|
13985
14222
|
if (current.data.staleEvidenceIds.length)
|
|
13986
|
-
return
|
|
14223
|
+
return failure2("needs_input", "imported task requires fresh destination evidence");
|
|
13987
14224
|
if (current.data.blockers.some((blocker) => blocker.dependentAction === "resume" || blocker.reason === "worker state requires reconciliation"))
|
|
13988
|
-
return
|
|
14225
|
+
return failure2("recovery_required", "imported task requires resume reconciliation");
|
|
13989
14226
|
if (!validResumeApproval(task.data, workspace.data, input.authorityRefs ?? [], this.context))
|
|
13990
|
-
return
|
|
14227
|
+
return failure2("permission_denied", "imported resume requires native destination approval");
|
|
13991
14228
|
resumeCandidate = current.data.candidate;
|
|
13992
14229
|
}
|
|
13993
|
-
const blocker = status === "paused" ? workspace.data.writer ?
|
|
14230
|
+
const blocker = status === "paused" ? workspace.data.writer ? failure2("recovery_required", "writer ownership must be released first") : null : this.activeWorkerBlocker(task.data, workspace.data);
|
|
13994
14231
|
if (blocker)
|
|
13995
14232
|
return blocker;
|
|
13996
14233
|
let pauseCandidate = null;
|
|
@@ -14005,7 +14242,7 @@ class WorkitCore {
|
|
|
14005
14242
|
expectedRevision: input.expectedRevision,
|
|
14006
14243
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14007
14244
|
now: trustedNow(this.context),
|
|
14008
|
-
workspace: (
|
|
14245
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14009
14246
|
task: (current, context) => success(context.revision, null, {
|
|
14010
14247
|
...current,
|
|
14011
14248
|
status,
|
|
@@ -14026,7 +14263,7 @@ class WorkitCore {
|
|
|
14026
14263
|
if (!helper.ok)
|
|
14027
14264
|
return helper;
|
|
14028
14265
|
if (task.data.status === "closed")
|
|
14029
|
-
return
|
|
14266
|
+
return failure2("invalid_transition", "closed task cannot update progress");
|
|
14030
14267
|
this.fillRevisions(input, task.data);
|
|
14031
14268
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, context) => success(context.revision, null, { ...current, progress: input.progress }), trustedNow(this.context));
|
|
14032
14269
|
if (!changed.ok)
|
|
@@ -14041,12 +14278,12 @@ class WorkitCore {
|
|
|
14041
14278
|
if (!helper.ok)
|
|
14042
14279
|
return helper;
|
|
14043
14280
|
if (task.data.status === "closed")
|
|
14044
|
-
return
|
|
14281
|
+
return failure2("invalid_transition", "closed task cannot be revised");
|
|
14045
14282
|
const workspace = this.store.readWorkspace();
|
|
14046
14283
|
if (!workspace.ok)
|
|
14047
14284
|
return workspace;
|
|
14048
14285
|
if (!workspace.data)
|
|
14049
|
-
return
|
|
14286
|
+
return failure2("not_found", "workspace not found");
|
|
14050
14287
|
const revisionBlocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14051
14288
|
if (revisionBlocker)
|
|
14052
14289
|
return revisionBlocker;
|
|
@@ -14056,7 +14293,7 @@ class WorkitCore {
|
|
|
14056
14293
|
expectedRevision: input.expectedRevision,
|
|
14057
14294
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
14058
14295
|
now: trustedNow(this.context),
|
|
14059
|
-
workspace: (
|
|
14296
|
+
workspace: (unchanged, context) => success(context.revision, context.revision, unchanged),
|
|
14060
14297
|
task: (current, context) => success(context.revision, null, {
|
|
14061
14298
|
...current,
|
|
14062
14299
|
intent: {
|
|
@@ -14081,12 +14318,12 @@ class WorkitCore {
|
|
|
14081
14318
|
if (!helper.ok)
|
|
14082
14319
|
return helper;
|
|
14083
14320
|
if (task.data.status !== "active" && task.data.status !== "paused")
|
|
14084
|
-
return
|
|
14321
|
+
return failure2("invalid_transition", "closed task cannot be reopened or closed again");
|
|
14085
14322
|
const workspace = this.store.readWorkspace();
|
|
14086
14323
|
if (!workspace.ok)
|
|
14087
14324
|
return workspace;
|
|
14088
14325
|
if (!workspace.data)
|
|
14089
|
-
return
|
|
14326
|
+
return failure2("not_found", "workspace not found");
|
|
14090
14327
|
const blocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
14091
14328
|
if (blocker)
|
|
14092
14329
|
return blocker;
|
|
@@ -14153,13 +14390,13 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14153
14390
|
}, validNativeProvenance = (value, caller, expected) => {
|
|
14154
14391
|
if (!provenanceSchema.safeParse(value).success)
|
|
14155
14392
|
return false;
|
|
14156
|
-
const
|
|
14157
|
-
return
|
|
14393
|
+
const observed = value;
|
|
14394
|
+
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);
|
|
14158
14395
|
}, validDispatchProvenance = (value, caller, workerId) => {
|
|
14159
14396
|
if (!provenanceSchema.safeParse(value).success)
|
|
14160
14397
|
return false;
|
|
14161
|
-
const
|
|
14162
|
-
return
|
|
14398
|
+
const observed = value;
|
|
14399
|
+
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);
|
|
14163
14400
|
}, validResumeApproval = (task, workspace, authorityRefs, context) => authorityRefs.some((ref) => {
|
|
14164
14401
|
if (ref.kind !== "record" || ref.collection !== "decisions")
|
|
14165
14402
|
return false;
|
|
@@ -14174,16 +14411,16 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14174
14411
|
return ["design", "action"].some((purpose) => applicableDecision(task, purpose, decision.binding, workspace.root).some((candidate) => candidate.digest === decision.digest));
|
|
14175
14412
|
}), verifyNativeWorker = (verifier, input, binding) => {
|
|
14176
14413
|
if (!verifier)
|
|
14177
|
-
return
|
|
14414
|
+
return failure2("permission_denied", "native worker verifier is unavailable");
|
|
14178
14415
|
let result;
|
|
14179
14416
|
try {
|
|
14180
14417
|
result = verifier.verifyWorker(input);
|
|
14181
14418
|
} catch (error) {
|
|
14182
|
-
return
|
|
14419
|
+
return failure2("permission_denied", `native worker observation failed: ${String(error)}`);
|
|
14183
14420
|
}
|
|
14184
14421
|
const expected = input.expected;
|
|
14185
14422
|
if (!result.ok || !validNativeProvenance(result.data, input.caller, expected))
|
|
14186
|
-
return
|
|
14423
|
+
return failure2("permission_denied", "native worker observation was not attested");
|
|
14187
14424
|
const token = {};
|
|
14188
14425
|
verifiedWorkers.set(token, {
|
|
14189
14426
|
taskId: expected.taskId,
|
|
@@ -14208,7 +14445,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14208
14445
|
return value;
|
|
14209
14446
|
}, applyWorkerLifecycle = (input) => {
|
|
14210
14447
|
if (!input.store || !input.authority || !input.authorityOwner)
|
|
14211
|
-
return
|
|
14448
|
+
return failure2("invalid_input", "native worker observation preconditions are required");
|
|
14212
14449
|
const authority = takeWorker(input.authority, {
|
|
14213
14450
|
owner: input.authorityOwner,
|
|
14214
14451
|
store: input.store,
|
|
@@ -14216,7 +14453,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14216
14453
|
caller: input.caller
|
|
14217
14454
|
}, input);
|
|
14218
14455
|
if (!authority)
|
|
14219
|
-
return
|
|
14456
|
+
return failure2("permission_denied", "native worker observation is not verified");
|
|
14220
14457
|
const task = input.store.readTask(input.taskId);
|
|
14221
14458
|
if (!task.ok)
|
|
14222
14459
|
return task;
|
|
@@ -14224,35 +14461,35 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14224
14461
|
if (!workspace.ok)
|
|
14225
14462
|
return workspace;
|
|
14226
14463
|
if (!workspace.data)
|
|
14227
|
-
return
|
|
14464
|
+
return failure2("not_found", "workspace not found");
|
|
14228
14465
|
if (task.data.workspaceId !== authority.workspaceId || workspace.data.id !== authority.workspaceId)
|
|
14229
|
-
return
|
|
14466
|
+
return failure2("recovery_required", "worker workspace binding is invalid");
|
|
14230
14467
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
14231
14468
|
if (!entry)
|
|
14232
|
-
return
|
|
14469
|
+
return failure2("not_found", "worker not found");
|
|
14233
14470
|
if (task.data.status === "closed")
|
|
14234
|
-
return
|
|
14471
|
+
return failure2("invalid_transition", "closed task cannot observe workers");
|
|
14235
14472
|
if (task.data.status === "paused" && (input.state === "running" || input.state === "cancelling"))
|
|
14236
|
-
return
|
|
14473
|
+
return failure2("invalid_transition", "paused task cannot run a worker");
|
|
14237
14474
|
const notStarted = input.dispatch === true;
|
|
14238
14475
|
if (notStarted && entry.data.state === "stopped" && input.session === null)
|
|
14239
14476
|
return success(task.data.revision, workspace.data.revision, entry);
|
|
14240
14477
|
if (notStarted && (input.state !== "stopped" || input.session !== null))
|
|
14241
|
-
return
|
|
14478
|
+
return failure2("invalid_input", "a never-dispatched worker stops with no session");
|
|
14242
14479
|
if (notStarted && entry.data.session !== null)
|
|
14243
|
-
return
|
|
14480
|
+
return failure2("invalid_transition", "worker already has an observed session");
|
|
14244
14481
|
if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
|
|
14245
|
-
return
|
|
14482
|
+
return failure2("invalid_transition", "worker launch was not claimed");
|
|
14246
14483
|
if (input.report && input.state !== "stopped")
|
|
14247
|
-
return
|
|
14484
|
+
return failure2("invalid_input", "worker reports require a stopped worker");
|
|
14248
14485
|
if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
|
|
14249
|
-
return
|
|
14486
|
+
return failure2("invalid_input", "running worker observations require a session");
|
|
14250
14487
|
if (entry.data.session && !sameValue(entry.data.session, input.session))
|
|
14251
|
-
return
|
|
14488
|
+
return failure2("permission_denied", "worker session does not match its assignment");
|
|
14252
14489
|
if (input.state !== "running" && entry.data.state === "assigned" && input.state !== "stopped")
|
|
14253
|
-
return
|
|
14490
|
+
return failure2("invalid_transition", "worker has not started");
|
|
14254
14491
|
if (input.state === "running" && entry.data.state === "stopped")
|
|
14255
|
-
return
|
|
14492
|
+
return failure2("invalid_transition", "stopped worker cannot run again");
|
|
14256
14493
|
const terminalCancel = entry.data.state === "cancelling" && input.state === "running";
|
|
14257
14494
|
const nextEntry = {
|
|
14258
14495
|
...entry,
|
|
@@ -14286,7 +14523,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14286
14523
|
if (!changed.ok)
|
|
14287
14524
|
return changed;
|
|
14288
14525
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
14289
|
-
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) :
|
|
14526
|
+
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
|
|
14290
14527
|
}, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now, mapRef = (ref, ids) => {
|
|
14291
14528
|
if (ref.kind !== "record")
|
|
14292
14529
|
return ref;
|
|
@@ -14360,13 +14597,13 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14360
14597
|
])
|
|
14361
14598
|
allocate(entry.id);
|
|
14362
14599
|
const fresh = (id) => allocate(id);
|
|
14363
|
-
const
|
|
14600
|
+
const imported = importedProvenance(context);
|
|
14364
14601
|
const remap = (ref) => mapRef(ref, ids);
|
|
14365
14602
|
const intent = {
|
|
14366
14603
|
...source.intent,
|
|
14367
14604
|
id: fresh(source.intent.id),
|
|
14368
14605
|
recordedAt: timestamp,
|
|
14369
|
-
provenance,
|
|
14606
|
+
provenance: imported,
|
|
14370
14607
|
data: rewriteRecordRefs(source.intent.data, intentSchema, remap)
|
|
14371
14608
|
};
|
|
14372
14609
|
const assessments = source.assessments.map((entry) => {
|
|
@@ -14375,7 +14612,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14375
14612
|
...entry,
|
|
14376
14613
|
id: fresh(entry.id),
|
|
14377
14614
|
recordedAt: timestamp,
|
|
14378
|
-
provenance,
|
|
14615
|
+
provenance: imported,
|
|
14379
14616
|
data: rewriteRecordRefs(data, assessmentSchema, remap)
|
|
14380
14617
|
};
|
|
14381
14618
|
});
|
|
@@ -14383,14 +14620,14 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14383
14620
|
...entry,
|
|
14384
14621
|
id: fresh(entry.id),
|
|
14385
14622
|
recordedAt: timestamp,
|
|
14386
|
-
provenance,
|
|
14623
|
+
provenance: imported,
|
|
14387
14624
|
data: rewriteRecordRefs(entry.data, evidenceSchema, remap)
|
|
14388
14625
|
}));
|
|
14389
14626
|
const decisions = source.decisions.map((entry) => ({
|
|
14390
14627
|
...entry,
|
|
14391
14628
|
id: fresh(entry.id),
|
|
14392
14629
|
recordedAt: timestamp,
|
|
14393
|
-
provenance
|
|
14630
|
+
provenance: imported
|
|
14394
14631
|
}));
|
|
14395
14632
|
const findings = source.findings.map((entry) => {
|
|
14396
14633
|
const data = rewriteRecordRefs(entry.data, findingSchema, remap);
|
|
@@ -14398,7 +14635,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14398
14635
|
...entry,
|
|
14399
14636
|
id: fresh(entry.id),
|
|
14400
14637
|
recordedAt: timestamp,
|
|
14401
|
-
provenance,
|
|
14638
|
+
provenance: imported,
|
|
14402
14639
|
data: {
|
|
14403
14640
|
...data,
|
|
14404
14641
|
resolution: data.resolution ? {
|
|
@@ -14413,7 +14650,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
14413
14650
|
...entry,
|
|
14414
14651
|
id: fresh(entry.id),
|
|
14415
14652
|
recordedAt: timestamp,
|
|
14416
|
-
provenance,
|
|
14653
|
+
provenance: imported,
|
|
14417
14654
|
data: {
|
|
14418
14655
|
...entry.data,
|
|
14419
14656
|
state: "stopped",
|
|
@@ -14783,7 +15020,7 @@ var hostRef = (handle) => ({ kind: "host", host: "cursor", handle }), cursorCapa
|
|
|
14783
15020
|
const listed = new TaskStore(root).listTasks();
|
|
14784
15021
|
if (!listed.ok)
|
|
14785
15022
|
return null;
|
|
14786
|
-
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === "cursor" && task.intent.provenance.session.handle === session) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === "cursor" && worker.data.session.handle === session)).
|
|
15023
|
+
const tasks = listed.data.filter((task) => task.id !== excludedTaskId && task.status !== "closed" && !(task.intent.provenance.session?.kind === "host" && task.intent.provenance.session.host === "cursor" && task.intent.provenance.session.handle === session) && !task.workers.some((worker) => worker.data.session?.kind === "host" && worker.data.session.host === "cursor" && worker.data.session.handle === session)).toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, 3);
|
|
14787
15024
|
if (tasks.length === 0)
|
|
14788
15025
|
return null;
|
|
14789
15026
|
const quote = (value) => JSON.stringify(value.replace(/[<>]/g, " ").slice(0, 120));
|
|
@@ -14803,9 +15040,9 @@ ${tasks.map((task) => `- ${task.id} [${task.status}; source ${task.intent.proven
|
|
|
14803
15040
|
const parentId = input.parent_conversation_id;
|
|
14804
15041
|
const observation = expected && input.subagent_id ? { subagent_id: subagentId, parent_conversation_id: parentId } : null;
|
|
14805
15042
|
if (!observation || !subagentId || !parentId || caller.host !== "cursor" || caller.actor !== parentId)
|
|
14806
|
-
return
|
|
15043
|
+
return failure2("permission_denied", "native subagent observation is unavailable");
|
|
14807
15044
|
if (expected.session?.kind !== "host" || expected.session.host !== "cursor" || expected.session.handle !== subagentId)
|
|
14808
|
-
return
|
|
15045
|
+
return failure2("permission_denied", "native subagent identity does not match");
|
|
14809
15046
|
return success(null, null, {
|
|
14810
15047
|
kind: "host_observed",
|
|
14811
15048
|
host: "cursor",
|