@vaudience/aigentflow-flow-validator 0.19.0 → 0.20.0

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/dist/index.cjs CHANGED
@@ -432,7 +432,7 @@ function validateBasicStructure(flow, issues) {
432
432
 
433
433
  // src/spec/aigentflow-spec.json
434
434
  var aigentflow_spec_default = {
435
- specVersion: "2.820.0",
435
+ specVersion: "2.821.0",
436
436
  inputSchemaVersion: 1,
437
437
  executorSchemes: [
438
438
  "a2a",
@@ -1257,6 +1257,34 @@ var aigentflow_spec_default = {
1257
1257
  }
1258
1258
  }
1259
1259
  },
1260
+ complianceResidency: {
1261
+ code: "compliance_residency_unenforced",
1262
+ euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
1263
+ regionLaneProviders: [
1264
+ "bedrock",
1265
+ "google",
1266
+ "azure",
1267
+ "openai",
1268
+ "assemblyai",
1269
+ "speechmatics",
1270
+ "deepgram",
1271
+ "mistral"
1272
+ ],
1273
+ aiProtocol: "ai",
1274
+ protocolSeparator: "://",
1275
+ regionParam: "region",
1276
+ enforceRegionParam: "enforce_region",
1277
+ baseUrlParamSuffix: "_base_url",
1278
+ enforceRegionTrueStrings: ["true", "1", "yes"],
1279
+ stepFieldFormat: "steps.%s.executor",
1280
+ loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
1281
+ orchestratorField: "orchestrator.exons",
1282
+ siteStepFormat: "step %q",
1283
+ siteLoopStepFormat: "loop sub-step %q of step %q",
1284
+ siteOrchestrator: "the orchestrator",
1285
+ messageFormat: "%s calls provider %q, whose default endpoint commits to no jurisdiction, but sets neither region nor enforce_region, so nothing pins it to the declared residency %v. compliance.residency is a catalogue eligibility check, not endpoint evidence",
1286
+ suggestion: "Add `region: eu` and `enforce_region: true` to the call (an orchestrator: the same two keys on the orchestrator block). Prove it afterwards: the step record's diagnostics.region is stamped from the host actually dialled."
1287
+ },
1260
1288
  examples: {
1261
1289
  limits: {
1262
1290
  maxPerFlow: 50,
@@ -1852,6 +1880,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1852
1880
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1853
1881
  families: aigentflow_spec_default.credentialEndpointPairing.families
1854
1882
  };
1883
+ var COMPLIANCE_RESIDENCY = {
1884
+ code: aigentflow_spec_default.complianceResidency.code,
1885
+ euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
1886
+ regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
1887
+ aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
1888
+ protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
1889
+ regionParam: aigentflow_spec_default.complianceResidency.regionParam,
1890
+ enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
1891
+ baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
1892
+ enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
1893
+ stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
1894
+ loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
1895
+ orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
1896
+ siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
1897
+ siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
1898
+ siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
1899
+ messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
1900
+ suggestion: aigentflow_spec_default.complianceResidency.suggestion
1901
+ };
1855
1902
  var EXAMPLES = {
1856
1903
  limits: aigentflow_spec_default.examples.limits,
1857
1904
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -5204,6 +5251,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5204
5251
  }
5205
5252
  }
5206
5253
 
5254
+ // src/validators/complianceResidency.ts
5255
+ function own2(m, key) {
5256
+ if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5257
+ return m[key];
5258
+ }
5259
+ function sprintf(format, ...args) {
5260
+ let i = 0;
5261
+ return format.replace(/%[sqv]/g, (verb) => {
5262
+ const arg = args[i++] ?? "";
5263
+ return verb === "%q" ? JSON.stringify(arg) : arg;
5264
+ });
5265
+ }
5266
+ function literalOrEmpty(s) {
5267
+ const t = goTrimSpace2(s);
5268
+ return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
5269
+ }
5270
+ function euOnlyResidency(flow, issues) {
5271
+ const raw = own2(own2(flow, "compliance"), "residency");
5272
+ if (!isArray(raw)) return null;
5273
+ const codes = [];
5274
+ for (let i = 0; i < raw.length; i++) {
5275
+ if (raw[i] === null) continue;
5276
+ const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
5277
+ if (code === null) return null;
5278
+ codes.push(code);
5279
+ }
5280
+ if (codes.length === 0) return null;
5281
+ const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
5282
+ return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
5283
+ }
5284
+ function aiProvider(executor) {
5285
+ const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
5286
+ if (!executor.startsWith(prefix)) return "";
5287
+ const rest = executor.slice(prefix.length);
5288
+ const slash = rest.indexOf("/");
5289
+ const provider = slash > 0 ? rest.slice(0, slash) : "";
5290
+ return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
5291
+ }
5292
+ function isRegionLane(provider) {
5293
+ const literal = literalOrEmpty(provider);
5294
+ return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
5295
+ }
5296
+ function nonBlankString(m, key) {
5297
+ const v = own2(m, key);
5298
+ return typeof v === "string" && goTrimSpace2(v) !== "";
5299
+ }
5300
+ function queryEnforcesRegion(query) {
5301
+ const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
5302
+ if (typeof v === "boolean") return v;
5303
+ return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
5304
+ }
5305
+ function flowDirectsEndpoint(flow, provider, issues) {
5306
+ const key = provider.toLowerCase();
5307
+ const inst = own2(own2(flow, "executor_config"), key);
5308
+ if (!isRecord(inst)) return false;
5309
+ const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
5310
+ return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
5311
+ }
5312
+ function callPinsEndpoint(flow, provider, query, issues) {
5313
+ if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
5314
+ if (queryEnforcesRegion(query)) return true;
5315
+ if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
5316
+ return flowDirectsEndpoint(flow, provider, issues);
5317
+ }
5318
+ function validateResidencyEnforcement(flow, issues) {
5319
+ const residency = euOnlyResidency(flow, issues);
5320
+ if (residency === null) return;
5321
+ const warn = (site, field, stepId, provider) => {
5322
+ issues.warn({
5323
+ field,
5324
+ ...stepId === void 0 ? {} : { stepId },
5325
+ code: COMPLIANCE_RESIDENCY.code,
5326
+ message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
5327
+ suggestion: COMPLIANCE_RESIDENCY.suggestion
5328
+ });
5329
+ };
5330
+ const steps = flow.steps;
5331
+ if (isRecord(steps)) {
5332
+ for (const stepId of Object.keys(steps).sort()) {
5333
+ const step = steps[stepId];
5334
+ if (!isRecord(step)) continue;
5335
+ const calls = [
5336
+ {
5337
+ executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
5338
+ query: own2(step, "query"),
5339
+ subId: null
5340
+ }
5341
+ ];
5342
+ for (const sub of loopSubStepsOfStep(stepId, step)) {
5343
+ calls.push({
5344
+ executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
5345
+ query: own2(sub.raw, "query"),
5346
+ subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
5347
+ });
5348
+ }
5349
+ for (const call of calls) {
5350
+ const provider = aiProvider(call.executor);
5351
+ if (!isRegionLane(provider)) continue;
5352
+ if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
5353
+ if (call.subId === null) {
5354
+ warn(
5355
+ sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
5356
+ sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
5357
+ stepId,
5358
+ provider
5359
+ );
5360
+ } else {
5361
+ warn(
5362
+ sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
5363
+ sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
5364
+ stepId,
5365
+ provider
5366
+ );
5367
+ }
5368
+ }
5369
+ }
5370
+ }
5371
+ warnOrchestrator(flow, issues, warn);
5372
+ }
5373
+ function warnOrchestrator(flow, issues, warn) {
5374
+ const orch = flow.orchestrator;
5375
+ if (!isRecord(orch)) return;
5376
+ const source = issues.stringOf(orch, "exons", "orchestrator");
5377
+ if (source === null || source === "") return;
5378
+ const report = inspectExonsFrontmatter(source);
5379
+ if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
5380
+ const provider = literalOrEmpty(report.provider);
5381
+ if (!isRegionLane(provider)) return;
5382
+ const region = issues.stringOf(orch, "region", "orchestrator");
5383
+ if (region !== null && goTrimSpace2(region) !== "") return;
5384
+ if (orch.enforce_region === true) return;
5385
+ if (flowDirectsEndpoint(flow, provider, issues)) return;
5386
+ warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
5387
+ }
5388
+
5207
5389
  // src/validators/examples.ts
5208
5390
  var KEY_EXAMPLES = "examples";
5209
5391
  var VISIBILITY_PUBLIC = "public";
@@ -5281,7 +5463,7 @@ function num(n) {
5281
5463
  function has(o, key) {
5282
5464
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5283
5465
  }
5284
- function own2(o, key) {
5466
+ function own3(o, key) {
5285
5467
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5286
5468
  }
5287
5469
  function setOwn(o, key, value) {
@@ -5333,7 +5515,7 @@ function mergePatch(target, patch, depth) {
5333
5515
  continue;
5334
5516
  }
5335
5517
  if (isRecord(pv)) {
5336
- const current = own2(target, k);
5518
+ const current = own3(target, k);
5337
5519
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5338
5520
  mergePatch(existing, pv, depth + 1);
5339
5521
  setOwn(target, k, existing);
@@ -5353,7 +5535,7 @@ function asFileRef(v) {
5353
5535
  if (keys.length === 0) return null;
5354
5536
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5355
5537
  const str = (k) => {
5356
- const x = own2(v, k);
5538
+ const x = own3(v, k);
5357
5539
  return typeof x === "string" ? x : "";
5358
5540
  };
5359
5541
  return {
@@ -5421,7 +5603,7 @@ var Walker = class _Walker {
5421
5603
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5422
5604
  );
5423
5605
  }
5424
- const allHeld = examples.every((e) => isRecord(e) && own2(e, "hold_out") === true);
5606
+ const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
5425
5607
  if (allHeld) {
5426
5608
  this.warn(
5427
5609
  "examples_all_held_out",
@@ -5509,9 +5691,9 @@ var Walker = class _Walker {
5509
5691
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5510
5692
  );
5511
5693
  }
5512
- this.validateTags(path, label, own2(ex, "tags"));
5513
- this.validateWeight(`${path}.weight`, label, numberOf(own2(ex, "weight")));
5514
- const minScore = numberOf(own2(ex, "min_score"));
5694
+ this.validateTags(path, label, own3(ex, "tags"));
5695
+ this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
5696
+ const minScore = numberOf(own3(ex, "min_score"));
5515
5697
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5516
5698
  this.err(
5517
5699
  "example_min_score_range",
@@ -5527,7 +5709,7 @@ var Walker = class _Walker {
5527
5709
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5528
5710
  );
5529
5711
  }
5530
- const holdOut = own2(ex, "hold_out") === true;
5712
+ const holdOut = own3(ex, "hold_out") === true;
5531
5713
  if (holdOut && this.isPublic()) {
5532
5714
  this.err(
5533
5715
  "example_holdout_in_public_flow",
@@ -5550,17 +5732,17 @@ var Walker = class _Walker {
5550
5732
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5551
5733
  );
5552
5734
  }
5553
- const rawInput = own2(ex, "input");
5735
+ const rawInput = own3(ex, "input");
5554
5736
  const baseInput = isRecord(rawInput) ? rawInput : null;
5555
5737
  if (baseInput !== null) {
5556
5738
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5557
5739
  }
5558
- const rawInputRef = own2(ex, "input_ref");
5740
+ const rawInputRef = own3(ex, "input_ref");
5559
5741
  if (isRecord(rawInputRef)) {
5560
5742
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5561
5743
  }
5562
5744
  let binaryOnly = false;
5563
- const expected = own2(ex, "expected");
5745
+ const expected = own3(ex, "expected");
5564
5746
  if (!has(ex, "expected")) {
5565
5747
  this.err(
5566
5748
  "example_expected_missing",
@@ -5579,7 +5761,7 @@ var Walker = class _Walker {
5579
5761
  "this example can be run but not scored"
5580
5762
  );
5581
5763
  }
5582
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
5764
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5583
5765
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5584
5766
  this.scanSecretLike(i, path, ex);
5585
5767
  }
@@ -5639,8 +5821,8 @@ var Walker = class _Walker {
5639
5821
  );
5640
5822
  return;
5641
5823
  }
5642
- const schema = own2(this.flow, "input_schema");
5643
- const query = own2(this.flow, "query");
5824
+ const schema = own3(this.flow, "input_schema");
5825
+ const query = own3(this.flow, "query");
5644
5826
  if (isRecord(schema)) {
5645
5827
  this.checkInputAgainstSchema(field, label, input, schema, code);
5646
5828
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5708,29 +5890,29 @@ var Walker = class _Walker {
5708
5890
  }
5709
5891
  }
5710
5892
  schemaFields(schema) {
5711
- const raw = own2(schema, "fields");
5893
+ const raw = own3(schema, "fields");
5712
5894
  if (!Array.isArray(raw)) return [];
5713
5895
  const out = [];
5714
5896
  raw.forEach((f, i) => {
5715
5897
  if (!isRecord(f)) return;
5716
5898
  const base = `input_schema.fields[${i}]`;
5717
- const enumRaw = own2(f, "enum");
5899
+ const enumRaw = own3(f, "enum");
5718
5900
  const enumValues = [];
5719
5901
  if (Array.isArray(enumRaw)) {
5720
5902
  enumRaw.forEach((e, j) => {
5721
5903
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5722
5904
  });
5723
5905
  }
5724
- const vw = own2(f, "visible_when");
5906
+ const vw = own3(f, "visible_when");
5725
5907
  out.push({
5726
5908
  name: this.s(f, "name", base),
5727
5909
  type: this.s(f, "type", base),
5728
- required: own2(f, "required") === true,
5910
+ required: own3(f, "required") === true,
5729
5911
  enumValues,
5730
5912
  visibleWhen: isRecord(vw) ? {
5731
5913
  field: this.s(vw, "field", `${base}.visible_when`),
5732
- equals: own2(vw, "equals"),
5733
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
5914
+ equals: own3(vw, "equals"),
5915
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5734
5916
  } : null
5735
5917
  });
5736
5918
  });
@@ -5741,7 +5923,7 @@ var Walker = class _Walker {
5741
5923
  const failures = [];
5742
5924
  for (const f of fields) {
5743
5925
  if (!isVisible(f, runInput)) continue;
5744
- const raw = own2(runInput, f.name);
5926
+ const raw = own3(runInput, f.name);
5745
5927
  if (raw === void 0 || raw === null) {
5746
5928
  if (f.required) {
5747
5929
  failures.push({
@@ -5852,7 +6034,7 @@ var Walker = class _Walker {
5852
6034
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5853
6035
  outputNamesFor(kind, stepId) {
5854
6036
  if (kind === "final") {
5855
- const out = own2(this.flow, "output");
6037
+ const out = own3(this.flow, "output");
5856
6038
  const names2 = [];
5857
6039
  if (Array.isArray(out)) {
5858
6040
  out.forEach((item, i) => {
@@ -5861,10 +6043,10 @@ var Walker = class _Walker {
5861
6043
  }
5862
6044
  return { names: names2, declared: names2.length > 0 };
5863
6045
  }
5864
- const steps = own2(this.flow, "steps");
5865
- const step = isRecord(steps) ? own2(steps, stepId) : void 0;
5866
- const schema = isRecord(step) ? own2(step, "output_schema") : void 0;
5867
- const fields = isRecord(schema) ? own2(schema, "fields") : void 0;
6046
+ const steps = own3(this.flow, "steps");
6047
+ const step = isRecord(steps) ? own3(steps, stepId) : void 0;
6048
+ const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
6049
+ const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
5868
6050
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5869
6051
  const names = [];
5870
6052
  fields.forEach((f, i) => {
@@ -5883,8 +6065,8 @@ var Walker = class _Walker {
5883
6065
  );
5884
6066
  }
5885
6067
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5886
- const fieldsRec = own2(e, "fields");
5887
- const exactRec = own2(e, "exact");
6068
+ const fieldsRec = own3(e, "fields");
6069
+ const exactRec = own3(e, "exact");
5888
6070
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5889
6071
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5890
6072
  const hasFields = fieldKeys.length > 0;
@@ -5902,7 +6084,7 @@ var Walker = class _Walker {
5902
6084
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
5903
6085
  );
5904
6086
  }
5905
- const minScore = numberOf(own2(e, "min_score"));
6087
+ const minScore = numberOf(own3(e, "min_score"));
5906
6088
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5907
6089
  this.err(
5908
6090
  "example_min_score_range",
@@ -5929,7 +6111,7 @@ var Walker = class _Walker {
5929
6111
  }
5930
6112
  }
5931
6113
  }
5932
- const reference = own2(e, "reference");
6114
+ const reference = own3(e, "reference");
5933
6115
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
5934
6116
  const { names, declared } = this.outputNamesFor(kind, stepId);
5935
6117
  const checkKey = (field, key) => {
@@ -5956,12 +6138,12 @@ var Walker = class _Walker {
5956
6138
  for (const key of fieldKeys) {
5957
6139
  const fpath = `${path}.fields.${key}`;
5958
6140
  checkKey(fpath, key);
5959
- const matcher = own2(fieldsRec, key);
6141
+ const matcher = own3(fieldsRec, key);
5960
6142
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
5961
6143
  }
5962
6144
  for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
5963
- const mustNot = this.stringList(own2(e, "must_not"), `${path}.must_not`);
5964
- const mustNotContain = this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`);
6145
+ const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
6146
+ const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
5965
6147
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
5966
6148
  if (mustNot.length > L.maxMustNot) {
5967
6149
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -5982,9 +6164,9 @@ var Walker = class _Walker {
5982
6164
  }
5983
6165
  });
5984
6166
  for (const key of fieldKeys) {
5985
- const matcher = own2(fieldsRec, key);
6167
+ const matcher = own3(fieldsRec, key);
5986
6168
  if (!isRecord(matcher)) continue;
5987
- const eq = own2(matcher, "equals");
6169
+ const eq = own3(matcher, "equals");
5988
6170
  if (typeof eq !== "string" || eq === "") continue;
5989
6171
  for (const banned of mustNotContain) {
5990
6172
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6044,7 +6226,7 @@ var Walker = class _Walker {
6044
6226
  }
6045
6227
  return;
6046
6228
  }
6047
- const refRec = own2(r, "ref");
6229
+ const refRec = own3(r, "ref");
6048
6230
  if (!isRecord(refRec)) return;
6049
6231
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6050
6232
  this.validateFileRef(`${path}.ref`, ref);
@@ -6057,22 +6239,22 @@ var Walker = class _Walker {
6057
6239
  }
6058
6240
  }
6059
6241
  expectationIsBinaryReferenceOnly(e, path) {
6060
- const reference = own2(e, "reference");
6061
- const refRec = isRecord(reference) ? own2(reference, "ref") : void 0;
6242
+ const reference = own3(e, "reference");
6243
+ const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
6062
6244
  if (!isRecord(refRec)) return false;
6063
6245
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6064
6246
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6065
6247
  const status = this.s(e, "status", path);
6066
- const fields = own2(e, "fields");
6067
- const exact = own2(e, "exact");
6068
- return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(own2(e, "must_not"), `${path}.must_not`).length === 0 && this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).length === 0 && (status === "" || status === STATUS_COMPLETED);
6248
+ const fields = own3(e, "fields");
6249
+ const exact = own3(e, "exact");
6250
+ return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(own3(e, "must_not"), `${path}.must_not`).length === 0 && this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).length === 0 && (status === "" || status === STATUS_COMPLETED);
6069
6251
  }
6070
6252
  validateFieldMatcher(path, m) {
6071
6253
  const L = EXAMPLES.limits;
6072
6254
  const matches = this.s(m, "matches", path);
6073
- const oneOf = own2(m, "one_of");
6074
- const approx = numberOf(own2(m, "approx"));
6075
- const tolerance = numberOf(own2(m, "tolerance"));
6255
+ const oneOf = own3(m, "one_of");
6256
+ const approx = numberOf(own3(m, "approx"));
6257
+ const tolerance = numberOf(own3(m, "tolerance"));
6076
6258
  let operators = 0;
6077
6259
  if (has(m, "equals")) operators++;
6078
6260
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6080,7 +6262,7 @@ var Walker = class _Walker {
6080
6262
  if (matches !== "") operators++;
6081
6263
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6082
6264
  if (approx !== void 0) operators++;
6083
- if (typeof own2(m, "present") === "boolean") operators++;
6265
+ if (typeof own3(m, "present") === "boolean") operators++;
6084
6266
  if (operators !== 1) {
6085
6267
  this.err(
6086
6268
  "example_field_matcher_invalid",
@@ -6107,12 +6289,12 @@ var Walker = class _Walker {
6107
6289
  // -- checkpoints ------------------------------------------------------
6108
6290
  validateCheckpoints(path, label, cps) {
6109
6291
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6110
- const stepsRaw = own2(this.flow, "steps");
6292
+ const stepsRaw = own3(this.flow, "steps");
6111
6293
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6112
6294
  const stepIds = sortedKeys(steps);
6113
6295
  for (const id of sortedKeys(cps)) {
6114
6296
  const cpath = `${path}.checkpoints.${id}`;
6115
- const step = own2(steps, id);
6297
+ const step = own3(steps, id);
6116
6298
  if (!isRecord(step)) {
6117
6299
  this.err(
6118
6300
  "example_checkpoint_step_unknown",
@@ -6122,7 +6304,7 @@ var Walker = class _Walker {
6122
6304
  );
6123
6305
  continue;
6124
6306
  }
6125
- const next = own2(step, "next");
6307
+ const next = own3(step, "next");
6126
6308
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6127
6309
  this.err(
6128
6310
  "example_checkpoint_step_composite",
@@ -6131,7 +6313,7 @@ var Walker = class _Walker {
6131
6313
  );
6132
6314
  continue;
6133
6315
  }
6134
- const cp = own2(cps, id);
6316
+ const cp = own3(cps, id);
6135
6317
  if (cp === null || cp === void 0) {
6136
6318
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6137
6319
  } else if (isRecord(cp)) {
@@ -6142,7 +6324,7 @@ var Walker = class _Walker {
6142
6324
  // -- variants ---------------------------------------------------------
6143
6325
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6144
6326
  const L = EXAMPLES.limits;
6145
- const variants = own2(ex, "variants");
6327
+ const variants = own3(ex, "variants");
6146
6328
  if (!Array.isArray(variants) || variants.length === 0) return;
6147
6329
  if (variants.length > L.maxVariants) {
6148
6330
  this.err(
@@ -6205,8 +6387,8 @@ var Walker = class _Walker {
6205
6387
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6206
6388
  );
6207
6389
  }
6208
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6209
- const patch = own2(v, "input_patch");
6390
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6391
+ const patch = own3(v, "input_patch");
6210
6392
  const patchRec = isRecord(patch) ? patch : null;
6211
6393
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6212
6394
  const hasRef = has(v, "input_ref");
@@ -6223,7 +6405,7 @@ var Walker = class _Walker {
6223
6405
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6224
6406
  );
6225
6407
  }
6226
- const refRec = own2(v, "input_ref");
6408
+ const refRec = own3(v, "input_ref");
6227
6409
  if (isRecord(refRec)) {
6228
6410
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6229
6411
  }
@@ -6238,7 +6420,7 @@ var Walker = class _Walker {
6238
6420
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6239
6421
  }
6240
6422
  }
6241
- const expected = own2(v, "expected");
6423
+ const expected = own3(v, "expected");
6242
6424
  if (isRecord(expected)) {
6243
6425
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6244
6426
  }
@@ -6249,11 +6431,11 @@ var Walker = class _Walker {
6249
6431
  * itself supplies. A null patch value deleting a secret is fine.
6250
6432
  */
6251
6433
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6252
- const schema = own2(this.flow, "input_schema");
6434
+ const schema = own3(this.flow, "input_schema");
6253
6435
  if (isRecord(schema)) {
6254
6436
  for (const f of this.schemaFields(schema)) {
6255
6437
  if (f.type !== TYPE_SECRET) continue;
6256
- const val = own2(patch, f.name);
6438
+ const val = own3(patch, f.name);
6257
6439
  if (val !== void 0 && val !== null) {
6258
6440
  this.err(
6259
6441
  "example_secret_value",
@@ -6293,18 +6475,18 @@ var Walker = class _Walker {
6293
6475
  emit(`${path}.title`, this.s(ex, "title", path));
6294
6476
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6295
6477
  emit(`${path}.notes`, this.s(ex, "notes", path));
6296
- const input = own2(ex, "input");
6478
+ const input = own3(ex, "input");
6297
6479
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6298
- const expected = own2(ex, "expected");
6480
+ const expected = own3(ex, "expected");
6299
6481
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6300
- const cps = own2(ex, "checkpoints");
6482
+ const cps = own3(ex, "checkpoints");
6301
6483
  if (isRecord(cps)) {
6302
6484
  for (const id of sortedKeys(cps)) {
6303
- const cp = own2(cps, id);
6485
+ const cp = own3(cps, id);
6304
6486
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6305
6487
  }
6306
6488
  }
6307
- const variants = own2(ex, "variants");
6489
+ const variants = own3(ex, "variants");
6308
6490
  if (Array.isArray(variants)) {
6309
6491
  variants.forEach((v, j) => {
6310
6492
  if (!isRecord(v)) return;
@@ -6312,34 +6494,34 @@ var Walker = class _Walker {
6312
6494
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6313
6495
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6314
6496
  emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
6315
- scanLeaves(`${vpath}.input_patch`, own2(v, "input_patch"), 0, emit);
6316
- const vexp = own2(v, "expected");
6497
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6498
+ const vexp = own3(v, "expected");
6317
6499
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6318
6500
  });
6319
6501
  }
6320
6502
  }
6321
6503
  scanExpectationLeaves(path, e, emit) {
6322
6504
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6323
- const reference = own2(e, "reference");
6505
+ const reference = own3(e, "reference");
6324
6506
  if (isRecord(reference)) {
6325
6507
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6326
6508
  }
6327
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6509
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6328
6510
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6329
6511
  );
6330
- this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6512
+ this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6331
6513
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6332
6514
  );
6333
- const fields = own2(e, "fields");
6515
+ const fields = own3(e, "fields");
6334
6516
  if (isRecord(fields)) {
6335
6517
  for (const key of sortedKeys(fields)) {
6336
- const m = own2(fields, key);
6518
+ const m = own3(fields, key);
6337
6519
  if (!isRecord(m)) continue;
6338
6520
  const fpath = `${path}.fields.${key}`;
6339
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6521
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6340
6522
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6341
6523
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6342
- const oneOf = own2(m, "one_of");
6524
+ const oneOf = own3(m, "one_of");
6343
6525
  if (Array.isArray(oneOf)) {
6344
6526
  oneOf.forEach(
6345
6527
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6347,7 +6529,7 @@ var Walker = class _Walker {
6347
6529
  }
6348
6530
  }
6349
6531
  }
6350
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6532
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6351
6533
  }
6352
6534
  };
6353
6535
  function scoreInRange(v) {
@@ -6463,7 +6645,7 @@ function inputValueFailures(f, raw) {
6463
6645
  case TYPE_FILE2: {
6464
6646
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6465
6647
  if (isRecord(raw)) {
6466
- const ref = own2(raw, FILE_REF_KEY);
6648
+ const ref = own3(raw, FILE_REF_KEY);
6467
6649
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6468
6650
  }
6469
6651
  return [mismatch(f, TYPE_FILE2)];
@@ -6546,6 +6728,7 @@ function validateParsed(flow, opts, sources) {
6546
6728
  validateCredentialEndpointPairing(f, issues);
6547
6729
  validateExamples(f, issues);
6548
6730
  validateOrchestratorExons(f, issues);
6731
+ validateResidencyEnforcement(f, issues);
6549
6732
  validateUnknownKeys(f, issues);
6550
6733
  const templateStats = validateTemplates(f, issues, opts);
6551
6734
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;