@openwop/openwop-conformance 2.45.2 → 2.45.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +2 -2
  3. package/dist/cli.js +1 -1
  4. package/dist/lib/certification-bundle-verify.js +22 -1
  5. package/dist/lib/profiles.js +17 -2
  6. package/dist/lib/requirement-registry.js +15 -0
  7. package/dist/lib/scenario-disposition.js +50 -9
  8. package/dist/spec-artifacts.lock.json +2 -2
  9. package/fixtures/conformance-fs-probe.json +25 -0
  10. package/fixtures/conformance-queue-consume.json +27 -0
  11. package/fixtures/conformance-queue-publish.json +29 -0
  12. package/fixtures/conformance-safefetch-probe.json +23 -0
  13. package/fixtures/conformance-secret-resolve-then-fail.json +33 -0
  14. package/fixtures/conformance-storage-probe.json +27 -0
  15. package/fixtures/conformance-tool-scope-probe.json +27 -0
  16. package/fixtures/openwop-secrets-run-witness.json +29 -0
  17. package/fixtures.md +102 -1
  18. package/package.json +2 -2
  19. package/requirement-aliases.json +72 -71
  20. package/requirements.json +1011 -43
  21. package/scenario-majors.json +39 -3
  22. package/schemas/CORPUS-STAMP.json +22 -22
  23. package/src/cli.ts +1 -1
  24. package/src/lib/certification-bundle-verify.ts +23 -2
  25. package/src/lib/driver.ts +61 -2
  26. package/src/lib/memoryAttribution.ts +41 -6
  27. package/src/lib/polling.ts +2 -18
  28. package/src/lib/profiles.ts +26 -2
  29. package/src/lib/requirement-registry.ts +12 -0
  30. package/src/lib/run-secrets-witness.ts +240 -0
  31. package/src/lib/scenario-disposition.ts +45 -7
  32. package/src/lib/secret-scan.ts +141 -0
  33. package/src/lib/timeout-scale.ts +25 -0
  34. package/src/lib/triggerBridge.ts +69 -1
  35. package/src/scenarios/byok-roundtrip.test.ts +20 -4
  36. package/src/scenarios/runner-ledger.test.ts +6 -1
  37. package/src/scenarios/secrets-run-witness.test.ts +154 -0
  38. package/src/scenarios/trigger-bridge-delivery.test.ts +183 -126
  39. package/src/scenarios/trigger-refused-event-keeps-subscription.test.ts +141 -0
  40. package/src/scenarios/v2-eval-mode-unadvertised-refused.test.ts +55 -0
  41. package/src/scenarios/v2-fs-sandbox-escape-refused.test.ts +161 -0
  42. package/src/scenarios/v2-memory-cross-tenant-isolation.test.ts +113 -0
  43. package/src/scenarios/v2-queue-cross-tenant-isolation.test.ts +118 -0
  44. package/src/scenarios/v2-safefetch-ssrf-refused.test.ts +198 -0
  45. package/src/scenarios/v2-secret-canary-absent.test.ts +211 -0
  46. package/src/scenarios/v2-secrets-run-witness.test.ts +167 -0
  47. package/src/scenarios/v2-storage-cross-tenant-isolation.test.ts +213 -0
  48. package/src/scenarios/v2-tool-authorization-fail-closed.test.ts +197 -0
  49. package/src/scenarios/v2-workspace-scope-from-identity.test.ts +146 -0
package/requirements.json CHANGED
@@ -2,11 +2,11 @@
2
2
  "$comment": "GENERATED by conformance/scripts/generate-requirement-registry.mjs — do not edit. One record per it()/test() in src/scenarios. Ids: openwop.it.<file-stem>.<title-slug>[~n] (src/lib/requirement-ids.ts). A record with id null has an interpolated title; its run-time row is keyed by the rendered title and maps here by file+line only. Renamed ids need a row in requirement-aliases.json.",
3
3
  "generatedFrom": "src/scenarios/*.test.ts",
4
4
  "counts": {
5
- "files": 650,
6
- "tests": 2496,
7
- "withStableId": 2496,
5
+ "files": 662,
6
+ "tests": 2535,
7
+ "withStableId": 2535,
8
8
  "interpolatedTitles": 0,
9
- "explicitIds": 2375
9
+ "explicitIds": 2411
10
10
  },
11
11
  "records": [
12
12
  {
@@ -6846,7 +6846,7 @@
6846
6846
  {
6847
6847
  "id": "openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h",
6848
6848
  "file": "byok-roundtrip.test.ts",
6849
- "line": 51,
6849
+ "line": 67,
6850
6850
  "title": "the canary fixture run MUST resolve a host-provisioned secret and emit SHA-256 hex",
6851
6851
  "explicitId": "openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h",
6852
6852
  "citations": [
@@ -6871,7 +6871,7 @@
6871
6871
  {
6872
6872
  "id": "openwop.it.byok-roundtrip.byok-fixture-run-must-emit-a-node-completed-event-for-the-resolve-step",
6873
6873
  "file": "byok-roundtrip.test.ts",
6874
- "line": 116,
6874
+ "line": 132,
6875
6875
  "title": "BYOK fixture run MUST emit a node.completed event for the resolve step",
6876
6876
  "explicitId": "openwop.it.byok-roundtrip.byok-fixture-run-must-emit-a-node-completed-event-for-the-resolve-step",
6877
6877
  "citations": [
@@ -6884,7 +6884,7 @@
6884
6884
  {
6885
6885
  "id": "openwop.it.byok-roundtrip.byok-fixture-run-event-log-must-not-echo-the-resolved-secret-value-redaction",
6886
6886
  "file": "byok-roundtrip.test.ts",
6887
- "line": 143,
6887
+ "line": 159,
6888
6888
  "title": "BYOK fixture run event log MUST NOT echo the resolved secret value (redaction)",
6889
6889
  "explicitId": "openwop.it.byok-roundtrip.byok-fixture-run-event-log-must-not-echo-the-resolved-secret-value-redaction",
6890
6890
  "citations": [
@@ -23601,7 +23601,7 @@
23601
23601
  {
23602
23602
  "id": "openwop.it.runner-ledger.a-floor-file-that-vitest-passed-but-that-recorded-nothing-is-unclassified-when-a",
23603
23603
  "file": "runner-ledger.test.ts",
23604
- "line": 141,
23604
+ "line": 146,
23605
23605
  "title": "a floor file that vitest passed but that recorded NOTHING is unclassified when a ledger exists — silence is not a witness",
23606
23606
  "explicitId": "openwop.it.runner-ledger.a-floor-file-that-vitest-passed-but-that-recorded-nothing-is-unclassified-when-a",
23607
23607
  "citations": [
@@ -23614,7 +23614,7 @@
23614
23614
  {
23615
23615
  "id": "openwop.it.runner-ledger.a-vacuous-pass-executed-pass-with-assertioncount-0-on-a-claimed-floor-is-unclass",
23616
23616
  "file": "runner-ledger.test.ts",
23617
- "line": 153,
23617
+ "line": 158,
23618
23618
  "title": "a VACUOUS pass (executed-pass with assertionCount 0) on a claimed floor is unclassified and REJECTS certification",
23619
23619
  "explicitId": "openwop.it.runner-ledger.a-vacuous-pass-executed-pass-with-assertioncount-0-on-a-claimed-floor-is-unclass",
23620
23620
  "citations": [
@@ -23627,7 +23627,7 @@
23627
23627
  {
23628
23628
  "id": "openwop.it.runner-ledger.a-skipped-file-with-no-ledger-entry-is-blocked-unclassified-and-it-never-reads-a",
23629
23629
  "file": "runner-ledger.test.ts",
23630
- "line": 162,
23630
+ "line": 167,
23631
23631
  "title": "a skipped file with no ledger entry is blocked (unclassified) — and it never reads as skipped/inapplicable",
23632
23632
  "explicitId": "openwop.it.runner-ledger.a-skipped-file-with-no-ledger-entry-is-blocked-unclassified-and-it-never-reads-a",
23633
23633
  "citations": [
@@ -23640,7 +23640,7 @@
23640
23640
  {
23641
23641
  "id": "openwop.it.runner-ledger.a-recorded-inapplicable-skipped-is-certifiable-and-not-unclassified-a-recorded-e",
23642
23642
  "file": "runner-ledger.test.ts",
23643
- "line": 174,
23643
+ "line": 179,
23644
23644
  "title": "a recorded inapplicable/skipped is certifiable and NOT unclassified; a recorded executed-fail blocks but is classified",
23645
23645
  "explicitId": "openwop.it.runner-ledger.a-recorded-inapplicable-skipped-is-certifiable-and-not-unclassified-a-recorded-e",
23646
23646
  "citations": [
@@ -23653,7 +23653,7 @@
23653
23653
  {
23654
23654
  "id": "openwop.it.runner-ledger.a-discoveryonly-profile-certifies-with-an-empty-floor-an-unknown-profile-does-no",
23655
23655
  "file": "runner-ledger.test.ts",
23656
- "line": 187,
23656
+ "line": 192,
23657
23657
  "title": "a discoveryOnly profile certifies with an empty floor; an unknown profile does not",
23658
23658
  "explicitId": "openwop.it.runner-ledger.a-discoveryonly-profile-certifies-with-an-empty-floor-an-unknown-profile-does-no",
23659
23659
  "citations": [
@@ -23666,7 +23666,7 @@
23666
23666
  {
23667
23667
  "id": "openwop.it.runner-ledger.a-runtime-derived-profile-openwop-node-packs-is-held-only-when-every-floor-row-i",
23668
23668
  "file": "runner-ledger.test.ts",
23669
- "line": 194,
23669
+ "line": 199,
23670
23670
  "title": "a RUNTIME-DERIVED profile (openwop-node-packs) is HELD only when every floor row is a witnessed pass; otherwise it is not held — not rejected, not blocked",
23671
23671
  "explicitId": "openwop.it.runner-ledger.a-runtime-derived-profile-openwop-node-packs-is-held-only-when-every-floor-row-i",
23672
23672
  "citations": [
@@ -23683,7 +23683,7 @@
23683
23683
  {
23684
23684
  "id": "openwop.it.runner-ledger.the-runner-s-a-resolution-of-a-silent-zero-assertion-file-blocked-marker-is-stil",
23685
23685
  "file": "runner-ledger.test.ts",
23686
- "line": 229,
23686
+ "line": 234,
23687
23687
  "title": "the runner's §A resolution of a silent zero-assertion file (blocked + marker) is STILL unclassified for a claimed floor",
23688
23688
  "explicitId": "openwop.it.runner-ledger.the-runner-s-a-resolution-of-a-silent-zero-assertion-file-blocked-marker-is-stil",
23689
23689
  "citations": [
@@ -23696,7 +23696,7 @@
23696
23696
  {
23697
23697
  "id": "openwop.it.runner-ledger.with-no-ledger-at-all-every-skipped-file-is-blocked-and-the-runner-says-so-the-p",
23698
23698
  "file": "runner-ledger.test.ts",
23699
- "line": 242,
23699
+ "line": 247,
23700
23700
  "title": "with no ledger at all, every skipped file is blocked and the runner says so (the pre-S6 honest reading)",
23701
23701
  "explicitId": "openwop.it.runner-ledger.with-no-ledger-at-all-every-skipped-file-is-blocked-and-the-runner-says-so-the-p",
23702
23702
  "citations": [
@@ -23709,7 +23709,7 @@
23709
23709
  {
23710
23710
  "id": "openwop.it.runner-ledger.notes-are-keyed-to-the-current-test-file-worst-first-when-mixed-and-read-back-wi",
23711
23711
  "file": "runner-ledger.test.ts",
23712
- "line": 252,
23712
+ "line": 257,
23713
23713
  "title": "notes are keyed to the current test file, worst-first when mixed, and read back with joined reasons",
23714
23714
  "explicitId": "openwop.it.runner-ledger.notes-are-keyed-to-the-current-test-file-worst-first-when-mixed-and-read-back-wi",
23715
23715
  "citations": [
@@ -23722,7 +23722,7 @@
23722
23722
  {
23723
23723
  "id": "openwop.it.runner-ledger.files-that-finished-before-this-one-appear-in-the-ledger-file-with-an-assertion",
23724
23724
  "file": "runner-ledger.test.ts",
23725
- "line": 274,
23725
+ "line": 279,
23726
23726
  "title": "files that finished before this one appear in the ledger file with an assertion count",
23727
23727
  "explicitId": "openwop.it.runner-ledger.files-that-finished-before-this-one-appear-in-the-ledger-file-with-an-assertion",
23728
23728
  "citations": [
@@ -24657,6 +24657,103 @@
24657
24657
  }
24658
24658
  ]
24659
24659
  },
24660
+ {
24661
+ "id": "openwop.it.secrets-run-witness.a-run-supplied-secret-resolves-intact-matched-true-for-its-digest-false-for-anot",
24662
+ "file": "secrets-run-witness.test.ts",
24663
+ "line": 72,
24664
+ "title": "a run-supplied secret resolves intact: matched true for its digest, false for another",
24665
+ "explicitId": "openwop.requirement.secrets.run-witness-resolves",
24666
+ "citations": [
24667
+ {
24668
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24669
+ "requirement": null,
24670
+ "interpolated": true
24671
+ },
24672
+ {
24673
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24674
+ "requirement": "the witness run with a matching digest MUST complete"
24675
+ },
24676
+ {
24677
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24678
+ "requirement": "the witness run with a different digest MUST complete (a mismatch is an output, not a failure)"
24679
+ },
24680
+ {
24681
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24682
+ "requirement": "witness MUST output matched: true when expectedSha256 is the digest of the supplied value"
24683
+ },
24684
+ {
24685
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24686
+ "requirement": "witness MUST output matched: false when expectedSha256 is the digest of a different value"
24687
+ }
24688
+ ]
24689
+ },
24690
+ {
24691
+ "id": "openwop.it.secrets-run-witness.a-run-supplied-secret-appears-on-no-readable-surface-in-any-encoding-or-as-its-d",
24692
+ "file": "secrets-run-witness.test.ts",
24693
+ "line": 88,
24694
+ "title": "a run-supplied secret appears on no readable surface, in any encoding or as its digest",
24695
+ "explicitId": "openwop.requirement.secrets.run-witness-redacted",
24696
+ "citations": [
24697
+ {
24698
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24699
+ "requirement": null,
24700
+ "interpolated": true
24701
+ }
24702
+ ]
24703
+ },
24704
+ {
24705
+ "id": "openwop.it.secrets-run-witness.a-run-ref-resolves-only-within-the-run-that-supplied-it-and-the-witness-refuses",
24706
+ "file": "secrets-run-witness.test.ts",
24707
+ "line": 99,
24708
+ "title": "a run: ref resolves only within the run that supplied it, and the witness refuses any other ref",
24709
+ "explicitId": "openwop.requirement.secrets.run-witness-scope-bound",
24710
+ "citations": [
24711
+ {
24712
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24713
+ "requirement": null,
24714
+ "interpolated": true
24715
+ },
24716
+ {
24717
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24718
+ "requirement": "a branch fork taken before witness MUST NOT inherit runSecrets: witness fails credential_not_found"
24719
+ }
24720
+ ]
24721
+ },
24722
+ {
24723
+ "id": "openwop.it.secrets-run-witness.the-idempotency-request-digest-excludes-runsecrets-a-retry-differing-only-there",
24724
+ "file": "secrets-run-witness.test.ts",
24725
+ "line": 131,
24726
+ "title": "the idempotency request digest excludes runSecrets: a retry differing only there replays, and its value is discarded",
24727
+ "explicitId": "openwop.requirement.secrets.run-secrets-outside-request-digest",
24728
+ "citations": [
24729
+ {
24730
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24731
+ "requirement": "a host advertising runSecrets MUST accept a well-formed runSecrets on createRun"
24732
+ },
24733
+ {
24734
+ "section": null,
24735
+ "requirement": "a same-key retry differing only in runSecrets MUST NOT be 409 idempotency_key_mismatch — the request digest MUST NOT cover runSecrets",
24736
+ "interpolated": true
24737
+ },
24738
+ {
24739
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24740
+ "requirement": "the retry MUST be answered from cache with the original 201"
24741
+ },
24742
+ {
24743
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24744
+ "requirement": "the retry MUST name the original runId"
24745
+ },
24746
+ {
24747
+ "section": "idempotency.md §Outcomes",
24748
+ "requirement": "a response served from cache MUST carry OpenWOP-Idempotent-Replay: true"
24749
+ },
24750
+ {
24751
+ "section": "capabilities.md §\"Run-supplied secrets\" (RFC 0229)",
24752
+ "requirement": null,
24753
+ "interpolated": true
24754
+ }
24755
+ ]
24756
+ },
24660
24757
  {
24661
24758
  "id": "openwop.it.self-hosted-runner.capabilities-schema-json-declares-selfhostedrunner-supported-with-required-suppo",
24662
24759
  "file": "self-hosted-runner.test.ts",
@@ -26212,62 +26309,118 @@
26212
26309
  ]
26213
26310
  },
26214
26311
  {
26215
- "id": "openwop.it.trigger-bridge-delivery.de-dups-by-dedupkey-retries-to-dead-letter-and-links-delivery-run-causation",
26312
+ "id": "openwop.it.trigger-bridge-delivery.de-dups-by-dedupkey-a-repeated-delivery-is-effectively-once",
26216
26313
  "file": "trigger-bridge-delivery.test.ts",
26217
- "line": 55,
26218
- "title": "de-dups by dedupKey, retries to dead-letter, and links delivery→run causation",
26219
- "explicitId": "openwop.it.trigger-bridge-delivery.de-dups-by-dedupkey-retries-to-dead-letter-and-links-delivery-run-causation",
26314
+ "line": 149,
26315
+ "title": "de-dups by dedupKey: a repeated delivery is effectively-once",
26316
+ "explicitId": "openwop.requirement.0083.trigger-delivery.dedup",
26220
26317
  "citations": [
26221
26318
  {
26222
- "section": "trigger-bridge.md §C-1",
26223
- "requirement": "a repeated dedupKey MUST be effectively-once — EXACTLY one delivered attempt (not zero, not two)"
26319
+ "section": "trigger-bridge.md §F.6",
26320
+ "requirement": null,
26321
+ "interpolated": true
26224
26322
  },
26225
26323
  {
26226
- "section": "run-event-payloads.schema.json#triggerDeliveryAttempted",
26227
- "requirement": "outcome MUST be delivered|retrying|dead-lettered"
26324
+ "section": "trigger-bridge.md §F.6",
26325
+ "requirement": null,
26326
+ "interpolated": true
26228
26327
  },
26229
26328
  {
26230
- "section": "trigger-bridge.md §C-2",
26231
- "requirement": "the exhaust scenario MUST be wired when the delivery seam is"
26329
+ "section": "trigger-bridge.md §F.6",
26330
+ "requirement": "a 202 MUST carry the started runId"
26232
26331
  },
26233
26332
  {
26234
- "section": "trigger-bridge.md §C-2",
26235
- "requirement": "an exhausted delivery MUST emit ≥1 trigger.delivery.attempted"
26333
+ "section": "trigger-bridge.md §F.6 / §C-1",
26334
+ "requirement": null,
26335
+ "interpolated": true
26236
26336
  },
26237
26337
  {
26238
- "section": "trigger-bridge.md §C-2",
26239
- "requirement": "an exhausted retry policy MUST terminate in a dead-lettered delivery"
26338
+ "section": "trigger-bridge.md §F.6",
26339
+ "requirement": "the dedup no-op MUST say outcome \"duplicate\""
26240
26340
  },
26241
26341
  {
26242
- "section": "trigger-bridge.md §B",
26243
- "requirement": "exhaustion MUST emit ≥1 trigger.subscription.state.changed"
26342
+ "section": "trigger-bridge.md §F.4",
26343
+ "requirement": "a dedup no-op MUST return the PRIOR runId"
26344
+ }
26345
+ ]
26346
+ },
26347
+ {
26348
+ "id": "openwop.it.trigger-bridge-delivery.dead-letters-an-exhausted-or-refused-delivery-without-starting-a-run",
26349
+ "file": "trigger-bridge-delivery.test.ts",
26350
+ "line": 172,
26351
+ "title": "dead-letters an exhausted or refused delivery without starting a run",
26352
+ "explicitId": "openwop.requirement.0083.trigger-delivery.dead-letter",
26353
+ "citations": [
26354
+ {
26355
+ "section": "trigger-bridge.md §F.6",
26356
+ "requirement": null,
26357
+ "interpolated": true
26244
26358
  },
26245
26359
  {
26246
- "section": "trigger-bridge.md §B",
26247
- "requirement": "the subscription MUST transition to dead-lettered on exhaustion"
26360
+ "section": "trigger-bridge.md §F.6",
26361
+ "requirement": null,
26362
+ "interpolated": true
26248
26363
  },
26249
26364
  {
26250
- "section": "trigger-bridge.md §B",
26251
- "requirement": "toState MUST be in the four-state vocabulary"
26365
+ "section": "trigger-bridge.md §F.2",
26366
+ "requirement": "a required-verification failure MUST NOT start a run"
26252
26367
  },
26253
26368
  {
26254
- "section": "trigger-bridge.md §C",
26255
- "requirement": "a successful delivery MUST create a run"
26369
+ "section": "trigger-bridge.md §F.6 (RFC 0230 §C.1)",
26370
+ "requirement": null,
26371
+ "interpolated": true
26372
+ },
26373
+ {
26374
+ "section": "trigger-bridge.md §F.6 (RFC 0230 §C.1)",
26375
+ "requirement": null,
26376
+ "interpolated": true
26377
+ }
26378
+ ]
26379
+ },
26380
+ {
26381
+ "id": "openwop.it.trigger-bridge-delivery.links-delivery-run-causation-on-run-started",
26382
+ "file": "trigger-bridge-delivery.test.ts",
26383
+ "line": 194,
26384
+ "title": "links delivery→run causation on run.started",
26385
+ "explicitId": "openwop.requirement.0083.trigger-delivery.causation",
26386
+ "citations": [
26387
+ {
26388
+ "section": "trigger-bridge.md §F.6",
26389
+ "requirement": null,
26390
+ "interpolated": true
26391
+ },
26392
+ {
26393
+ "section": "trigger-bridge.md §F.6",
26394
+ "requirement": null,
26395
+ "interpolated": true
26256
26396
  },
26257
26397
  {
26258
- "section": "trigger-bridge.md §C-1",
26259
- "requirement": "a successful delivery MUST emit a trigger.delivery.attempted{outcome:delivered}"
26398
+ "section": "trigger-bridge.md §F.6",
26399
+ "requirement": "a 202 MUST carry the started runId"
26260
26400
  },
26261
26401
  {
26262
26402
  "section": "trigger-bridge.md §C",
26263
- "requirement": "a delivered run MUST emit run.started"
26403
+ "requirement": null,
26404
+ "interpolated": true
26264
26405
  },
26265
26406
  {
26266
26407
  "section": "trigger-bridge.md §C / RFC 0040",
26267
- "requirement": "run.started.causationId MUST EQUAL the delivery id (the trigger.delivery.attempted{delivered} eventId) — resolvable via /ancestry"
26408
+ "requirement": "run.started MUST carry the delivery id as causationId"
26409
+ },
26410
+ {
26411
+ "section": "trigger-bridge.md §C / RFC 0040",
26412
+ "requirement": "run.started.causationId MUST EQUAL the delivered attempt event id"
26268
26413
  }
26269
26414
  ]
26270
26415
  },
26416
+ {
26417
+ "id": "openwop.it.trigger-bridge-delivery.keeps-the-run-less-trigger-events-content-free",
26418
+ "file": "trigger-bridge-delivery.test.ts",
26419
+ "line": 222,
26420
+ "title": "keeps the run-less trigger events content-free",
26421
+ "explicitId": null,
26422
+ "citations": []
26423
+ },
26271
26424
  {
26272
26425
  "id": "openwop.it.trigger-bridge-shape.a-conforming-subscription-validates",
26273
26426
  "file": "trigger-bridge-shape.test.ts",
@@ -26576,6 +26729,67 @@
26576
26729
  }
26577
26730
  ]
26578
26731
  },
26732
+ {
26733
+ "id": "openwop.it.trigger-refused-event-keeps-subscription.a-refused-event-dead-letters-only-its-delivery-the-subscription-stays-active-and",
26734
+ "file": "trigger-refused-event-keeps-subscription.test.ts",
26735
+ "line": 55,
26736
+ "title": "a refused event dead-letters only its delivery; the subscription stays active and a verified event then delivers",
26737
+ "explicitId": "openwop.requirement.trigger-bridge.refused-event-keeps-subscription",
26738
+ "citations": [
26739
+ {
26740
+ "section": "host-sample-test-seams.md (trigger-bridge delivery seam)",
26741
+ "requirement": "scenario \"refused\" MUST answer 200"
26742
+ },
26743
+ {
26744
+ "section": "host-sample-test-seams.md (trigger-bridge delivery seam)",
26745
+ "requirement": "scenario \"refused\" MUST return the subscriptionId it drove"
26746
+ },
26747
+ {
26748
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26749
+ "requirement": "an event failing a required verification MUST NOT start a run; its delivery is dead-lettered"
26750
+ },
26751
+ {
26752
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26753
+ "requirement": "the refused delivery MUST be recorded as trigger.delivery.attempted { outcome: \"dead-lettered\" }"
26754
+ },
26755
+ {
26756
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26757
+ "requirement": "an event failing a required verification MUST NOT be delivered"
26758
+ },
26759
+ {
26760
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26761
+ "requirement": "an event failing a required verification MUST NOT start a run"
26762
+ },
26763
+ {
26764
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26765
+ "requirement": "a refused event MUST NOT emit trigger.subscription.state.changed — one bad post must not disable the integration"
26766
+ },
26767
+ {
26768
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26769
+ "requirement": "a refused event MUST NOT change the subscription's state: it stays active"
26770
+ },
26771
+ {
26772
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26773
+ "requirement": "the normative subscription read MUST still show state active after a refused event"
26774
+ },
26775
+ {
26776
+ "section": "host-sample-test-seams.md (trigger-bridge delivery seam)",
26777
+ "requirement": "scenario \"deliver\" with the refused subscriptionId MUST answer 200"
26778
+ },
26779
+ {
26780
+ "section": "host-sample-test-seams.md (trigger-bridge delivery seam)",
26781
+ "requirement": "scenario \"deliver\" MUST deliver on the subscriptionId it was given"
26782
+ },
26783
+ {
26784
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26785
+ "requirement": "after a refused event, a verified event on the same subscription MUST start a run"
26786
+ },
26787
+ {
26788
+ "section": "trigger-bridge.md §F.2 (corrected 2026-09-30)",
26789
+ "requirement": "after a refused event, the next verified delivery on the subscription MUST be recorded delivered"
26790
+ }
26791
+ ]
26792
+ },
26579
26793
  {
26580
26794
  "id": "openwop.it.trigger-stream-cdc-sources.the-canonical-stream-triggerevent-fixture-validates",
26581
26795
  "file": "trigger-stream-cdc-sources.test.ts",
@@ -29844,6 +30058,24 @@
29844
30058
  }
29845
30059
  ]
29846
30060
  },
30061
+ {
30062
+ "id": "openwop.it.v2-eval-mode-unadvertised-refused.post-runs-mode-eval-answers-422-capability-not-provided-and-creates-no-run",
30063
+ "file": "v2-eval-mode-unadvertised-refused.test.ts",
30064
+ "line": 32,
30065
+ "title": "POST /runs {mode: \"eval\"} answers 422 capability_not_provided and creates no run",
30066
+ "explicitId": "openwop.requirement.runs.eval-mode-unadvertised-refused",
30067
+ "citations": [
30068
+ {
30069
+ "section": "spec/v2/core/runs.md §Refusals",
30070
+ "requirement": null,
30071
+ "interpolated": true
30072
+ },
30073
+ {
30074
+ "section": "spec/v2/core/runs.md §Refusals",
30075
+ "requirement": "the 422 for an unadvertised eval mode MUST carry the registered code capability_not_provided"
30076
+ }
30077
+ ]
30078
+ },
29847
30079
  {
29848
30080
  "id": "openwop.it.v2-event-type-closed.every-emitted-type-is-a-registered-protocol-type-or-a-vendor-type-under-an-adver",
29849
30081
  "file": "v2-event-type-closed.test.ts",
@@ -30124,6 +30356,107 @@
30124
30356
  }
30125
30357
  ]
30126
30358
  },
30359
+ {
30360
+ "id": "openwop.it.v2-fs-sandbox-escape-refused.a-path-inside-the-sandbox-root-is-written-and-read-back",
30361
+ "file": "v2-fs-sandbox-escape-refused.test.ts",
30362
+ "line": 116,
30363
+ "title": "a path inside the sandbox root is written and read back",
30364
+ "explicitId": "openwop.requirement.storage.fs-inside-root-read",
30365
+ "citations": [
30366
+ {
30367
+ "section": "spec/v2/core/storage.md §fs",
30368
+ "requirement": null,
30369
+ "interpolated": true
30370
+ },
30371
+ {
30372
+ "section": "spec/v2/core/storage.md §fs",
30373
+ "requirement": null,
30374
+ "interpolated": true
30375
+ },
30376
+ {
30377
+ "section": "conformance/fixtures.md §The storage probe fixtures",
30378
+ "requirement": "the read MUST return the bytes written"
30379
+ }
30380
+ ]
30381
+ },
30382
+ {
30383
+ "id": "openwop.it.v2-fs-sandbox-escape-refused.an-absolute-path-outside-the-root-is-refused-forbidden-path-outside-sandbox",
30384
+ "file": "v2-fs-sandbox-escape-refused.test.ts",
30385
+ "line": 129,
30386
+ "title": "an absolute path outside the root is refused forbidden, path-outside-sandbox",
30387
+ "explicitId": "openwop.requirement.storage.fs-absolute-escape-refused",
30388
+ "citations": [
30389
+ {
30390
+ "section": "spec/v2/core/storage.md §fs",
30391
+ "requirement": null,
30392
+ "interpolated": true
30393
+ },
30394
+ {
30395
+ "section": "spec/v2/core/storage.md §Shared rules",
30396
+ "requirement": "a sandbox escape is `forbidden`"
30397
+ },
30398
+ {
30399
+ "section": "spec/v2/core/storage.md §Shared rules",
30400
+ "requirement": "a sandbox escape carries details.reason: path-outside-sandbox"
30401
+ },
30402
+ {
30403
+ "section": "spec/v2/core/errors.md §Host-service refusals",
30404
+ "requirement": "a generic code MUST carry details.service, the family key"
30405
+ }
30406
+ ]
30407
+ },
30408
+ {
30409
+ "id": "openwop.it.v2-fs-sandbox-escape-refused.a-dot-dot-path-that-climbs-out-of-the-root-is-refused-forbidden-path-outside-san",
30410
+ "file": "v2-fs-sandbox-escape-refused.test.ts",
30411
+ "line": 140,
30412
+ "title": "a dot-dot path that climbs out of the root is refused forbidden, path-outside-sandbox",
30413
+ "explicitId": "openwop.requirement.storage.fs-dotdot-escape-refused",
30414
+ "citations": [
30415
+ {
30416
+ "section": "spec/v2/core/storage.md §fs",
30417
+ "requirement": null,
30418
+ "interpolated": true
30419
+ },
30420
+ {
30421
+ "section": "spec/v2/core/storage.md §Shared rules",
30422
+ "requirement": "a sandbox escape is `forbidden`"
30423
+ },
30424
+ {
30425
+ "section": "spec/v2/core/storage.md §Shared rules",
30426
+ "requirement": "a sandbox escape carries details.reason: path-outside-sandbox"
30427
+ },
30428
+ {
30429
+ "section": "spec/v2/core/errors.md §Host-service refusals",
30430
+ "requirement": "a generic code MUST carry details.service, the family key"
30431
+ }
30432
+ ]
30433
+ },
30434
+ {
30435
+ "id": "openwop.it.v2-fs-sandbox-escape-refused.a-symlink-inside-the-root-that-points-outside-it-is-refused-forbidden-path-outsi",
30436
+ "file": "v2-fs-sandbox-escape-refused.test.ts",
30437
+ "line": 151,
30438
+ "title": "a symlink inside the root that points outside it is refused forbidden, path-outside-sandbox",
30439
+ "explicitId": "openwop.requirement.storage.fs-symlink-escape-refused",
30440
+ "citations": [
30441
+ {
30442
+ "section": "spec/v2/core/storage.md §fs",
30443
+ "requirement": null,
30444
+ "interpolated": true
30445
+ },
30446
+ {
30447
+ "section": "spec/v2/core/storage.md §Shared rules",
30448
+ "requirement": "a sandbox escape is `forbidden`"
30449
+ },
30450
+ {
30451
+ "section": "spec/v2/core/storage.md §Shared rules",
30452
+ "requirement": "a sandbox escape carries details.reason: path-outside-sandbox"
30453
+ },
30454
+ {
30455
+ "section": "spec/v2/core/errors.md §Host-service refusals",
30456
+ "requirement": "a generic code MUST carry details.service, the family key"
30457
+ }
30458
+ ]
30459
+ },
30127
30460
  {
30128
30461
  "id": "openwop.it.v2-header-scheme.no-removed-header-family-appears-on-any-response",
30129
30462
  "file": "v2-header-scheme.test.ts",
@@ -31756,6 +32089,30 @@
31756
32089
  }
31757
32090
  ]
31758
32091
  },
32092
+ {
32093
+ "id": "openwop.it.v2-memory-cross-tenant-isolation.a-second-tenant-listing-the-same-memoryref-sees-none-of-the-first-tenant-s-entri",
32094
+ "file": "v2-memory-cross-tenant-isolation.test.ts",
32095
+ "line": 87,
32096
+ "title": "a second tenant listing the same memoryRef sees none of the first tenant's entries",
32097
+ "explicitId": "openwop.requirement.0004.memory-ref-one-tenant",
32098
+ "citations": [
32099
+ {
32100
+ "section": "spec/v2/core/host-services.md §memory",
32101
+ "requirement": null,
32102
+ "interpolated": true
32103
+ },
32104
+ {
32105
+ "section": "spec/v2/core/host-services.md §memory",
32106
+ "requirement": null,
32107
+ "interpolated": true
32108
+ },
32109
+ {
32110
+ "section": "spec/v2/core/host-services.md §memory",
32111
+ "requirement": null,
32112
+ "interpolated": true
32113
+ }
32114
+ ]
32115
+ },
31759
32116
  {
31760
32117
  "id": "openwop.it.v2-min-client-version.a-client-below-minclientversion-is-refused-with-426-client-version-unsupported",
31761
32118
  "file": "v2-min-client-version.test.ts",
@@ -32938,6 +33295,45 @@
32938
33295
  }
32939
33296
  ]
32940
33297
  },
33298
+ {
33299
+ "id": "openwop.it.v2-queue-cross-tenant-isolation.a-message-tenant-a-publishes-on-topic-t-is-never-consumed-by-tenant-b-on-t-and-a",
33300
+ "file": "v2-queue-cross-tenant-isolation.test.ts",
33301
+ "line": 92,
33302
+ "title": "a message tenant A publishes on topic T is never consumed by tenant B on T, and A's own consumer receives it",
33303
+ "explicitId": "openwop.requirement.queueBus.cross-tenant-isolation",
33304
+ "citations": [
33305
+ {
33306
+ "section": null,
33307
+ "requirement": null,
33308
+ "interpolated": true
33309
+ },
33310
+ {
33311
+ "section": null,
33312
+ "requirement": null,
33313
+ "interpolated": true
33314
+ },
33315
+ {
33316
+ "section": null,
33317
+ "requirement": "the consume node MUST output `consumed` as an array ([] when nothing arrived), never leave it unset — an unset output would pass the isolation check vacuously",
33318
+ "interpolated": true
33319
+ },
33320
+ {
33321
+ "section": "spec/v2/core/host-services.md §queueBus",
33322
+ "requirement": null,
33323
+ "interpolated": true
33324
+ },
33325
+ {
33326
+ "section": null,
33327
+ "requirement": null,
33328
+ "interpolated": true
33329
+ },
33330
+ {
33331
+ "section": null,
33332
+ "requirement": null,
33333
+ "interpolated": true
33334
+ }
33335
+ ]
33336
+ },
32941
33337
  {
32942
33338
  "id": "openwop.it.v2-refresh-sla.refreshedat-on-each-embedded-protocol-facet-is-within-90-days-of-now",
32943
33339
  "file": "v2-refresh-sla.test.ts",
@@ -33716,6 +34112,210 @@
33716
34112
  }
33717
34113
  ]
33718
34114
  },
34115
+ {
34116
+ "id": "openwop.it.v2-safefetch-ssrf-refused.a-loopback-target-is-refused-egress-denied-ssrf-blocked-before-any-connection",
34117
+ "file": "v2-safefetch-ssrf-refused.test.ts",
34118
+ "line": 159,
34119
+ "title": "a loopback target is refused egress_denied, ssrf-blocked, before any connection",
34120
+ "explicitId": "openwop.requirement.httpClient.ssrf-loopback-refused",
34121
+ "citations": [
34122
+ {
34123
+ "section": "spec/v2/core/host-services.md §httpClient",
34124
+ "requirement": "the guard MUST refuse BEFORE connecting — these probe requests reached the suite's loopback listener"
34125
+ }
34126
+ ]
34127
+ },
34128
+ {
34129
+ "id": "openwop.it.v2-safefetch-ssrf-refused.an-rfc-1918-target-is-refused-egress-denied-ssrf-blocked",
34130
+ "file": "v2-safefetch-ssrf-refused.test.ts",
34131
+ "line": 166,
34132
+ "title": "an RFC 1918 target is refused egress_denied, ssrf-blocked",
34133
+ "explicitId": null,
34134
+ "citations": []
34135
+ },
34136
+ {
34137
+ "id": "openwop.it.v2-safefetch-ssrf-refused.a-link-local-or-cloud-metadata-target-is-refused-egress-denied-ssrf-blocked",
34138
+ "file": "v2-safefetch-ssrf-refused.test.ts",
34139
+ "line": 172,
34140
+ "title": "a link-local or cloud-metadata target is refused egress_denied, ssrf-blocked",
34141
+ "explicitId": null,
34142
+ "citations": []
34143
+ },
34144
+ {
34145
+ "id": "openwop.it.v2-safefetch-ssrf-refused.the-same-addresses-in-decimal-octal-short-and-ipv4-mapped-ipv6-spellings-are-ref",
34146
+ "file": "v2-safefetch-ssrf-refused.test.ts",
34147
+ "line": 178,
34148
+ "title": "the same addresses in decimal, octal, short and IPv4-mapped IPv6 spellings are refused",
34149
+ "explicitId": "openwop.requirement.httpClient.ssrf-address-spellings-refused",
34150
+ "citations": [
34151
+ {
34152
+ "section": "spec/v2/core/host-services.md §httpClient",
34153
+ "requirement": "the guard MUST refuse BEFORE connecting — these probe requests reached the suite's loopback listener"
34154
+ }
34155
+ ]
34156
+ },
34157
+ {
34158
+ "id": "openwop.it.v2-safefetch-ssrf-refused.a-name-that-resolves-to-loopback-is-refused-on-its-resolved-address",
34159
+ "file": "v2-safefetch-ssrf-refused.test.ts",
34160
+ "line": 192,
34161
+ "title": "a name that resolves to loopback is refused on its resolved address",
34162
+ "explicitId": "openwop.requirement.httpClient.ssrf-resolved-name-refused",
34163
+ "citations": [
34164
+ {
34165
+ "section": "spec/v2/core/host-services.md §httpClient",
34166
+ "requirement": "the host MUST resolve the target and reject a loopback address before connecting — the probe reached the suite's loopback listener"
34167
+ }
34168
+ ]
34169
+ },
34170
+ {
34171
+ "id": "openwop.it.v2-secret-canary-absent.a-secret-resolved-from-the-host-s-store-appears-on-no-readable-surface-of-the-ru",
34172
+ "file": "v2-secret-canary-absent.test.ts",
34173
+ "line": 168,
34174
+ "title": "a secret resolved from the host's store appears on no readable surface of the run",
34175
+ "explicitId": "openwop.requirement.secrets.resolved-secret-absent",
34176
+ "citations": [
34177
+ {
34178
+ "section": "conformance/fixtures.md §openwop-smoke-byok-roundtrip",
34179
+ "requirement": null,
34180
+ "interpolated": true
34181
+ },
34182
+ {
34183
+ "section": "spec/v2/core/host-services.md §secrets",
34184
+ "requirement": null,
34185
+ "interpolated": true
34186
+ }
34187
+ ]
34188
+ },
34189
+ {
34190
+ "id": "openwop.it.v2-secret-canary-absent.a-secret-resolved-by-a-run-that-then-fails-appears-on-no-readable-surface-the-er",
34191
+ "file": "v2-secret-canary-absent.test.ts",
34192
+ "line": 178,
34193
+ "title": "a secret resolved by a run that then fails appears on no readable surface, the error included",
34194
+ "explicitId": "openwop.requirement.secrets.resolved-secret-absent-on-failure",
34195
+ "citations": [
34196
+ {
34197
+ "section": null,
34198
+ "requirement": null,
34199
+ "interpolated": true
34200
+ },
34201
+ {
34202
+ "section": "spec/v2/core/host-services.md §secrets",
34203
+ "requirement": null,
34204
+ "interpolated": true
34205
+ }
34206
+ ]
34207
+ },
34208
+ {
34209
+ "id": "openwop.it.v2-secret-canary-absent.a-replay-fork-re-resolves-the-secret-and-still-carries-it-on-no-readable-surface",
34210
+ "file": "v2-secret-canary-absent.test.ts",
34211
+ "line": 191,
34212
+ "title": "a replay fork re-resolves the secret and still carries it on no readable surface",
34213
+ "explicitId": "openwop.requirement.secrets.resolved-secret-absent-in-fork",
34214
+ "citations": [
34215
+ {
34216
+ "section": "spec/v2/core/host-services.md §secrets",
34217
+ "requirement": null,
34218
+ "interpolated": true
34219
+ }
34220
+ ]
34221
+ },
34222
+ {
34223
+ "id": "openwop.it.v2-secrets-run-witness.a-run-supplied-secret-resolves-intact-matched-true-for-its-digest-false-for-anot",
34224
+ "file": "v2-secrets-run-witness.test.ts",
34225
+ "line": 85,
34226
+ "title": "a run-supplied secret resolves intact: matched true for its digest, false for another",
34227
+ "explicitId": "openwop.requirement.secrets.run-witness-resolves",
34228
+ "citations": [
34229
+ {
34230
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34231
+ "requirement": null,
34232
+ "interpolated": true
34233
+ },
34234
+ {
34235
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34236
+ "requirement": "the witness run with a matching digest MUST complete"
34237
+ },
34238
+ {
34239
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34240
+ "requirement": "the witness run with a different digest MUST complete (a mismatch is an output, not a failure)"
34241
+ },
34242
+ {
34243
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34244
+ "requirement": "witness MUST output matched: true when expectedSha256 is the digest of the supplied value"
34245
+ },
34246
+ {
34247
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34248
+ "requirement": "witness MUST output matched: false when expectedSha256 is the digest of a different value"
34249
+ }
34250
+ ]
34251
+ },
34252
+ {
34253
+ "id": "openwop.it.v2-secrets-run-witness.a-run-supplied-secret-appears-on-no-readable-surface-in-any-encoding-or-as-its-d",
34254
+ "file": "v2-secrets-run-witness.test.ts",
34255
+ "line": 101,
34256
+ "title": "a run-supplied secret appears on no readable surface, in any encoding or as its digest",
34257
+ "explicitId": "openwop.requirement.secrets.run-witness-redacted",
34258
+ "citations": [
34259
+ {
34260
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34261
+ "requirement": null,
34262
+ "interpolated": true
34263
+ }
34264
+ ]
34265
+ },
34266
+ {
34267
+ "id": "openwop.it.v2-secrets-run-witness.a-run-ref-resolves-only-within-the-run-that-supplied-it-and-the-witness-refuses",
34268
+ "file": "v2-secrets-run-witness.test.ts",
34269
+ "line": 112,
34270
+ "title": "a run: ref resolves only within the run that supplied it, and the witness refuses any other ref",
34271
+ "explicitId": "openwop.requirement.secrets.run-witness-scope-bound",
34272
+ "citations": [
34273
+ {
34274
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34275
+ "requirement": null,
34276
+ "interpolated": true
34277
+ },
34278
+ {
34279
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34280
+ "requirement": "a branch fork taken before witness MUST NOT inherit runSecrets: witness fails credential_not_found"
34281
+ }
34282
+ ]
34283
+ },
34284
+ {
34285
+ "id": "openwop.it.v2-secrets-run-witness.the-idempotency-request-digest-excludes-runsecrets-a-retry-differing-only-there",
34286
+ "file": "v2-secrets-run-witness.test.ts",
34287
+ "line": 144,
34288
+ "title": "the idempotency request digest excludes runSecrets: a retry differing only there replays, and its value is discarded",
34289
+ "explicitId": "openwop.requirement.secrets.run-secrets-outside-request-digest",
34290
+ "citations": [
34291
+ {
34292
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34293
+ "requirement": "a host advertising runSecrets MUST accept a well-formed runSecrets on createRun"
34294
+ },
34295
+ {
34296
+ "section": null,
34297
+ "requirement": "a same-key retry differing only in runSecrets MUST NOT be 409 idempotency_key_mismatch — the request digest MUST NOT cover runSecrets",
34298
+ "interpolated": true
34299
+ },
34300
+ {
34301
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34302
+ "requirement": "the retry MUST be answered from cache with the original 201"
34303
+ },
34304
+ {
34305
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34306
+ "requirement": "the retry MUST name the original runId"
34307
+ },
34308
+ {
34309
+ "section": "idempotency.md §Outcomes",
34310
+ "requirement": "a response served from cache MUST carry OpenWOP-Idempotent-Replay: true"
34311
+ },
34312
+ {
34313
+ "section": "host-services.md §Run-supplied secrets (RFC 0229)",
34314
+ "requirement": null,
34315
+ "interpolated": true
34316
+ }
34317
+ ]
34318
+ },
33719
34319
  {
33720
34320
  "id": "openwop.it.v2-sse-last-event-id-cursor.a-last-event-id-past-the-log-is-an-exclusive-cursor-a-terminal-run-answers-200-w",
33721
34321
  "file": "v2-sse-last-event-id-cursor.test.ts",
@@ -33863,6 +34463,206 @@
33863
34463
  }
33864
34464
  ]
33865
34465
  },
34466
+ {
34467
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.kvstorage-a-read-for-tenant-b-never-returns-what-tenant-a-wrote-under-the-same-k",
34468
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34469
+ "line": 150,
34470
+ "title": "kvStorage: a read for tenant B never returns what tenant A wrote under the same key (get and list)",
34471
+ "explicitId": "openwop.requirement.storage.cross-tenant-kv-storage",
34472
+ "citations": [
34473
+ {
34474
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34475
+ "requirement": "tenant A's own read MUST return the value it wrote (positive control)"
34476
+ },
34477
+ {
34478
+ "section": "spec/v2/core/storage.md §Shared rules",
34479
+ "requirement": "tenant B's read MUST complete or be refused with a storage refusal code"
34480
+ },
34481
+ {
34482
+ "section": "spec/v2/core/storage.md §Shared rules",
34483
+ "requirement": "a kvStorage get for tenant B MUST NOT return data tenant A wrote under an identical key"
34484
+ },
34485
+ {
34486
+ "section": "spec/v2/core/storage.md §Shared rules",
34487
+ "requirement": "a kvStorage list for tenant B MUST NOT return a key tenant A wrote"
34488
+ }
34489
+ ]
34490
+ },
34491
+ {
34492
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.tablestorage-a-read-for-tenant-b-never-returns-what-tenant-a-wrote-in-the-same-t",
34493
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34494
+ "line": 158,
34495
+ "title": "tableStorage: a read for tenant B never returns what tenant A wrote in the same table (get and query)",
34496
+ "explicitId": "openwop.requirement.storage.cross-tenant-table-storage",
34497
+ "citations": [
34498
+ {
34499
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34500
+ "requirement": "tenant A's own read MUST return the value it wrote (positive control)"
34501
+ },
34502
+ {
34503
+ "section": "spec/v2/core/storage.md §Shared rules",
34504
+ "requirement": "tenant B's read MUST complete or be refused with a storage refusal code"
34505
+ },
34506
+ {
34507
+ "section": "spec/v2/core/storage.md §Shared rules",
34508
+ "requirement": "a tableStorage get or query for tenant B MUST NOT return a row tenant A wrote in the identically named table"
34509
+ },
34510
+ {
34511
+ "section": "spec/v2/core/storage.md §Shared rules",
34512
+ "requirement": "a tableStorage query for tenant B MUST NOT return a row tenant A wrote"
34513
+ }
34514
+ ]
34515
+ },
34516
+ {
34517
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.blobstorage-a-read-for-tenant-b-never-returns-what-tenant-a-wrote-under-the-same",
34518
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34519
+ "line": 166,
34520
+ "title": "blobStorage: a read for tenant B never returns what tenant A wrote under the same bucket and key",
34521
+ "explicitId": "openwop.requirement.storage.cross-tenant-blob-storage",
34522
+ "citations": [
34523
+ {
34524
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34525
+ "requirement": "tenant A's own read MUST return the object it wrote (positive control)"
34526
+ },
34527
+ {
34528
+ "section": "spec/v2/core/storage.md §Shared rules",
34529
+ "requirement": "tenant B's read MUST complete or be refused with a storage refusal code"
34530
+ },
34531
+ {
34532
+ "section": "spec/v2/core/storage.md §Shared rules",
34533
+ "requirement": "a blobStorage get for tenant B MUST NOT return an object tenant A wrote under an identical bucket and key"
34534
+ },
34535
+ {
34536
+ "section": "spec/v2/core/storage.md §Shared rules",
34537
+ "requirement": "a blobStorage list for tenant B MUST NOT return a key tenant A wrote"
34538
+ }
34539
+ ]
34540
+ },
34541
+ {
34542
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.cache-a-get-for-tenant-b-never-returns-what-tenant-a-put-under-the-same-key",
34543
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34544
+ "line": 174,
34545
+ "title": "cache: a get for tenant B never returns what tenant A put under the same key",
34546
+ "explicitId": "openwop.requirement.storage.cross-tenant-cache",
34547
+ "citations": [
34548
+ {
34549
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34550
+ "requirement": "tenant A's own read MUST return the value it put (positive control)"
34551
+ },
34552
+ {
34553
+ "section": "spec/v2/core/storage.md §Shared rules",
34554
+ "requirement": "tenant B's read MUST complete or be refused with a storage refusal code"
34555
+ },
34556
+ {
34557
+ "section": "spec/v2/core/storage.md §Shared rules",
34558
+ "requirement": "a cache get for tenant B MUST NOT return data tenant A wrote under an identical key"
34559
+ },
34560
+ {
34561
+ "section": "spec/v2/core/storage.md §Shared rules",
34562
+ "requirement": "a cache read for tenant B MUST NOT return a key tenant A wrote"
34563
+ }
34564
+ ]
34565
+ },
34566
+ {
34567
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.vectorstore-a-query-for-tenant-b-never-matches-a-vector-tenant-a-upserted-in-the",
34568
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34569
+ "line": 182,
34570
+ "title": "vectorStore: a query for tenant B never matches a vector tenant A upserted in the same collection",
34571
+ "explicitId": "openwop.requirement.storage.cross-tenant-vector-store",
34572
+ "citations": [
34573
+ {
34574
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34575
+ "requirement": "tenant A's own query MUST return the vector it upserted (positive control)"
34576
+ },
34577
+ {
34578
+ "section": "spec/v2/core/storage.md §Shared rules",
34579
+ "requirement": "tenant B's query MUST complete or be refused with a storage refusal code"
34580
+ },
34581
+ {
34582
+ "section": "spec/v2/core/storage.md §Shared rules",
34583
+ "requirement": "a vectorStore query for tenant B MUST NOT return metadata tenant A wrote in the identically named collection"
34584
+ },
34585
+ {
34586
+ "section": "spec/v2/core/storage.md §Shared rules",
34587
+ "requirement": "a vectorStore query for tenant B MUST NOT return an id tenant A upserted"
34588
+ }
34589
+ ]
34590
+ },
34591
+ {
34592
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.searchindex-a-query-for-tenant-b-never-hits-a-document-tenant-a-indexed-in-the-s",
34593
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34594
+ "line": 190,
34595
+ "title": "searchIndex: a query for tenant B never hits a document tenant A indexed in the same index",
34596
+ "explicitId": "openwop.requirement.storage.cross-tenant-search-index",
34597
+ "citations": [
34598
+ {
34599
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34600
+ "requirement": "tenant A's own query MUST return the document it indexed (positive control)"
34601
+ },
34602
+ {
34603
+ "section": "spec/v2/core/storage.md §Shared rules",
34604
+ "requirement": "tenant B's query MUST complete or be refused with a storage refusal code"
34605
+ },
34606
+ {
34607
+ "section": "spec/v2/core/storage.md §Shared rules",
34608
+ "requirement": "a searchIndex query for tenant B MUST NOT return fields tenant A indexed in the identically named index"
34609
+ },
34610
+ {
34611
+ "section": "spec/v2/core/storage.md §Shared rules",
34612
+ "requirement": "a searchIndex query for tenant B MUST NOT return an id tenant A indexed"
34613
+ }
34614
+ ]
34615
+ },
34616
+ {
34617
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.sql-tenant-b-reading-the-same-named-datasource-never-sees-a-row-tenant-a-inserte",
34618
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34619
+ "line": 198,
34620
+ "title": "sql: tenant B reading the same-named datasource never sees a row tenant A inserted",
34621
+ "explicitId": "openwop.requirement.storage.cross-tenant-sql",
34622
+ "citations": [
34623
+ {
34624
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34625
+ "requirement": "tenant A's own query MUST return the row it inserted (positive control)"
34626
+ },
34627
+ {
34628
+ "section": "spec/v2/core/storage.md §Shared rules",
34629
+ "requirement": "tenant B's query MUST complete or be refused with a storage refusal code"
34630
+ },
34631
+ {
34632
+ "section": "spec/v2/core/storage.md §Shared rules",
34633
+ "requirement": "sql datasources are scoped per tenant: tenant B MUST NOT read a row tenant A inserted"
34634
+ },
34635
+ {
34636
+ "section": "spec/v2/core/storage.md §Shared rules",
34637
+ "requirement": "sql datasources are scoped per tenant: tenant B MUST NOT see a key tenant A inserted"
34638
+ }
34639
+ ]
34640
+ },
34641
+ {
34642
+ "id": "openwop.it.v2-storage-cross-tenant-isolation.nosql-tenant-b-reading-the-same-named-datasource-never-sees-a-document-tenant-a",
34643
+ "file": "v2-storage-cross-tenant-isolation.test.ts",
34644
+ "line": 206,
34645
+ "title": "nosql: tenant B reading the same-named datasource never sees a document tenant A inserted (get and query)",
34646
+ "explicitId": "openwop.requirement.storage.cross-tenant-nosql",
34647
+ "citations": [
34648
+ {
34649
+ "section": "conformance/fixtures.md §The storage probe fixtures",
34650
+ "requirement": "tenant A's own query MUST return the document it inserted (positive control)"
34651
+ },
34652
+ {
34653
+ "section": "spec/v2/core/storage.md §Shared rules",
34654
+ "requirement": "tenant B's read MUST complete or be refused with a storage refusal code"
34655
+ },
34656
+ {
34657
+ "section": "spec/v2/core/storage.md §Shared rules",
34658
+ "requirement": "nosql datasources are scoped per tenant: tenant B MUST NOT read a document tenant A inserted, by query or by its id"
34659
+ },
34660
+ {
34661
+ "section": "spec/v2/core/storage.md §Shared rules",
34662
+ "requirement": "nosql datasources are scoped per tenant: tenant B MUST NOT see a key tenant A inserted"
34663
+ }
34664
+ ]
34665
+ },
33866
34666
  {
33867
34667
  "id": "openwop.it.v2-stream-mode-refusal.a-value-outside-the-pattern-a-forbidden-combination-and-an-unimplemented-mode-ar",
33868
34668
  "file": "v2-stream-mode-refusal.test.ts",
@@ -34071,6 +34871,114 @@
34071
34871
  }
34072
34872
  ]
34073
34873
  },
34874
+ {
34875
+ "id": "openwop.it.v2-tool-authorization-fail-closed.a-tool-whose-required-scope-the-principal-lacks-is-not-invoked-and-is-refused-fo",
34876
+ "file": "v2-tool-authorization-fail-closed.test.ts",
34877
+ "line": 158,
34878
+ "title": "a tool whose required scope the principal lacks is not invoked and is refused forbidden",
34879
+ "explicitId": "openwop.requirement.toolHooks.authorization-fail-closed-missing-scope",
34880
+ "citations": [
34881
+ {
34882
+ "section": "conformance/fixtures.md §conformance-tool-scope-probe",
34883
+ "requirement": null,
34884
+ "interpolated": true
34885
+ },
34886
+ {
34887
+ "section": "conformance/fixtures.md §conformance-tool-scope-probe",
34888
+ "requirement": null,
34889
+ "interpolated": true
34890
+ },
34891
+ {
34892
+ "section": "spec/v2/core/host-services.md §toolHooks",
34893
+ "requirement": null,
34894
+ "interpolated": true
34895
+ },
34896
+ {
34897
+ "section": "spec/v2/core/host-services.md §toolHooks",
34898
+ "requirement": null,
34899
+ "interpolated": true
34900
+ },
34901
+ {
34902
+ "section": "spec/v2/core/host-services.md §toolHooks",
34903
+ "requirement": "a refused tool MUST NOT also return ok"
34904
+ },
34905
+ {
34906
+ "section": "schemas/v2/run-event-payloads.schema.json#/$defs/agentToolReturned",
34907
+ "requirement": "durationMs is absent when the call never started (forbidden)"
34908
+ },
34909
+ {
34910
+ "section": "spec/v2/core/host-services.md §toolHooks",
34911
+ "requirement": null,
34912
+ "interpolated": true
34913
+ },
34914
+ {
34915
+ "section": "spec/v2/core/host-services.md §toolHooks",
34916
+ "requirement": "the forbidden refusal MUST carry details.scope: \"tool\""
34917
+ },
34918
+ {
34919
+ "section": "spec/v2/core/host-services.md §toolHooks",
34920
+ "requirement": "the forbidden refusal MUST carry details.toolName"
34921
+ },
34922
+ {
34923
+ "section": "spec/v2/core/host-services.md §toolHooks",
34924
+ "requirement": "the forbidden refusal MUST carry details.requiredScopes naming the tool's scopes"
34925
+ }
34926
+ ]
34927
+ },
34928
+ {
34929
+ "id": "openwop.it.v2-tool-authorization-fail-closed.a-tool-whose-required-scope-cannot-be-evaluated-is-not-invoked-and-is-refused-fo",
34930
+ "file": "v2-tool-authorization-fail-closed.test.ts",
34931
+ "line": 178,
34932
+ "title": "a tool whose required scope cannot be evaluated is not invoked and is refused forbidden",
34933
+ "explicitId": "openwop.requirement.toolHooks.authorization-fail-closed-unevaluable-scope",
34934
+ "citations": [
34935
+ {
34936
+ "section": "conformance/fixtures.md §conformance-tool-scope-probe",
34937
+ "requirement": null,
34938
+ "interpolated": true
34939
+ },
34940
+ {
34941
+ "section": "conformance/fixtures.md §conformance-tool-scope-probe",
34942
+ "requirement": null,
34943
+ "interpolated": true
34944
+ },
34945
+ {
34946
+ "section": "spec/v2/core/host-services.md §toolHooks",
34947
+ "requirement": null,
34948
+ "interpolated": true
34949
+ },
34950
+ {
34951
+ "section": "spec/v2/core/host-services.md §toolHooks",
34952
+ "requirement": null,
34953
+ "interpolated": true
34954
+ },
34955
+ {
34956
+ "section": "spec/v2/core/host-services.md §toolHooks",
34957
+ "requirement": "a refused tool MUST NOT also return ok"
34958
+ },
34959
+ {
34960
+ "section": "schemas/v2/run-event-payloads.schema.json#/$defs/agentToolReturned",
34961
+ "requirement": "durationMs is absent when the call never started (forbidden)"
34962
+ },
34963
+ {
34964
+ "section": "spec/v2/core/host-services.md §toolHooks",
34965
+ "requirement": null,
34966
+ "interpolated": true
34967
+ },
34968
+ {
34969
+ "section": "spec/v2/core/host-services.md §toolHooks",
34970
+ "requirement": "the forbidden refusal MUST carry details.scope: \"tool\""
34971
+ },
34972
+ {
34973
+ "section": "spec/v2/core/host-services.md §toolHooks",
34974
+ "requirement": "the forbidden refusal MUST carry details.toolName"
34975
+ },
34976
+ {
34977
+ "section": "spec/v2/core/host-services.md §toolHooks",
34978
+ "requirement": "the forbidden refusal MUST carry details.requiredScopes naming the tool's scopes"
34979
+ }
34980
+ ]
34981
+ },
34074
34982
  {
34075
34983
  "id": "openwop.it.v2-tool-catalog-annotations.every-published-annotations-object-is-the-table-function-of-the-descriptor",
34076
34984
  "file": "v2-tool-catalog-annotations.test.ts",
@@ -35056,6 +35964,66 @@
35056
35964
  }
35057
35965
  ]
35058
35966
  },
35967
+ {
35968
+ "id": "openwop.it.v2-workspace-scope-from-identity.a-second-tenant-cannot-read-or-list-a-file-the-first-tenant-wrote",
35969
+ "file": "v2-workspace-scope-from-identity.test.ts",
35970
+ "line": 100,
35971
+ "title": "a second tenant cannot read or list a file the first tenant wrote",
35972
+ "explicitId": "openwop.requirement.0059.workspace-scope-from-identity",
35973
+ "citations": [
35974
+ {
35975
+ "section": "spec/v2/core/host-services.md §workspace",
35976
+ "requirement": "positive control: the owning scope MUST read its own file (200)"
35977
+ },
35978
+ {
35979
+ "section": "spec/v2/core/host-services.md §workspace",
35980
+ "requirement": "positive control: the owner reads back the content it wrote"
35981
+ },
35982
+ {
35983
+ "section": "spec/v2/core/host-services.md §workspace",
35984
+ "requirement": "positive control: the owner's list names its own file"
35985
+ },
35986
+ {
35987
+ "section": "spec/v2/core/host-services.md §workspace",
35988
+ "requirement": null,
35989
+ "interpolated": true
35990
+ },
35991
+ {
35992
+ "section": "spec/v2/core/host-services.md §workspace",
35993
+ "requirement": "another scope's read MUST NOT disclose the file's content"
35994
+ },
35995
+ {
35996
+ "section": "spec/v2/core/host-services.md §workspace",
35997
+ "requirement": "another scope's list MUST NOT disclose the file"
35998
+ }
35999
+ ]
36000
+ },
36001
+ {
36002
+ "id": "openwop.it.v2-workspace-scope-from-identity.naming-the-first-tenant-s-scope-in-the-request-does-not-widen-the-second-tenant",
36003
+ "file": "v2-workspace-scope-from-identity.test.ts",
36004
+ "line": 122,
36005
+ "title": "naming the first tenant's scope in the request does not widen the second tenant's scope",
36006
+ "explicitId": "openwop.requirement.0059.workspace-scope-not-request-named",
36007
+ "citations": [
36008
+ {
36009
+ "section": "spec/v2/core/host-services.md §workspace",
36010
+ "requirement": "positive control: the owning scope MUST read its own file (200)"
36011
+ },
36012
+ {
36013
+ "section": "spec/v2/core/host-services.md §workspace",
36014
+ "requirement": null,
36015
+ "interpolated": true
36016
+ },
36017
+ {
36018
+ "section": "spec/v2/core/host-services.md §workspace",
36019
+ "requirement": "a request naming another scope MUST NOT disclose that scope's file"
36020
+ },
36021
+ {
36022
+ "section": "spec/v2/core/host-services.md §workspace",
36023
+ "requirement": "a list naming another scope MUST NOT disclose that scope's file"
36024
+ }
36025
+ ]
36026
+ },
35059
36027
  {
35060
36028
  "id": "openwop.it.vector-knn-roundtrip.capabilities-vectorstore-is-either-absent-or-a-well-formed-object",
35061
36029
  "file": "vector-knn-roundtrip.test.ts",