@openwop/openwop-conformance 1.163.0 → 2.0.0-rc.1

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 (611) hide show
  1. package/README.md +11 -2
  2. package/dist/cli.js +262 -14
  3. package/dist/lib/certification-bundle-v3.js +142 -0
  4. package/dist/lib/paths.js +25 -3
  5. package/dist/lib/requirement-ids.js +57 -4
  6. package/dist/lib/requirement-ledger.js +1 -0
  7. package/dist/lib/scenario-disposition.js +6 -1
  8. package/dist/lib/spec-coherence.js +13 -32
  9. package/dist/spec-artifacts.lock.json +5 -0
  10. package/package.json +11 -33
  11. package/requirements.json +22892 -11701
  12. package/scenario-majors.json +1493 -0
  13. package/schemas/CORPUS-STAMP.json +137 -5
  14. package/src/cli.ts +236 -19
  15. package/src/global-setup.ts +3 -2
  16. package/src/lib/certification-bundle-v3.ts +175 -0
  17. package/src/lib/corpus-stamp.ts +29 -1
  18. package/src/lib/driver.ts +9 -1
  19. package/src/lib/era2-seed.ts +197 -0
  20. package/src/lib/paths.ts +25 -3
  21. package/src/lib/requirement-ids.ts +54 -4
  22. package/src/lib/requirement-ledger.ts +7 -1
  23. package/src/lib/scenario-disposition.ts +6 -1
  24. package/src/lib/seams.ts +45 -0
  25. package/src/lib/spec-coherence.ts +15 -32
  26. package/src/lib/v2.ts +62 -0
  27. package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
  28. package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
  29. package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
  30. package/src/scenarios/a2a-peer-authority.test.ts +7 -6
  31. package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
  32. package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
  33. package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
  34. package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
  35. package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
  36. package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
  37. package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
  38. package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
  39. package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
  40. package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
  41. package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
  42. package/src/scenarios/agent-deployment-shape.test.ts +22 -24
  43. package/src/scenarios/agent-eval-run.test.ts +19 -18
  44. package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
  45. package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
  46. package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
  47. package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
  48. package/src/scenarios/agent-live-structured-output.test.ts +7 -6
  49. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
  50. package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
  51. package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
  52. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
  53. package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
  54. package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
  55. package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
  56. package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
  57. package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
  58. package/src/scenarios/agent-platform-profile.test.ts +18 -19
  59. package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
  60. package/src/scenarios/agent-roster-attribution.test.ts +18 -17
  61. package/src/scenarios/agent-roster-shape.test.ts +17 -19
  62. package/src/scenarios/agent-verifier-shape.test.ts +11 -11
  63. package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
  64. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
  65. package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
  66. package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
  67. package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
  68. package/src/scenarios/agentMessageReducer.test.ts +2 -1
  69. package/src/scenarios/agentMetadata.test.ts +2 -1
  70. package/src/scenarios/agentPackCatalog.test.ts +23 -21
  71. package/src/scenarios/agentPackExport.test.ts +4 -2
  72. package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
  73. package/src/scenarios/agentPackInstall.test.ts +4 -2
  74. package/src/scenarios/agentPackProvenance.test.ts +2 -1
  75. package/src/scenarios/agentReasoningEvents.test.ts +3 -2
  76. package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
  77. package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
  78. package/src/scenarios/ai-envelope-shape.test.ts +31 -29
  79. package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
  80. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
  81. package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
  82. package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
  83. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
  84. package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
  85. package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
  86. package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
  87. package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
  88. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
  89. package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
  90. package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
  91. package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
  92. package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
  93. package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
  94. package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
  95. package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
  96. package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
  97. package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
  98. package/src/scenarios/append-ordering.test.ts +7 -5
  99. package/src/scenarios/approval-gate-events.test.ts +4 -3
  100. package/src/scenarios/approval-gate-flow.test.ts +4 -3
  101. package/src/scenarios/approval-payload.test.ts +5 -4
  102. package/src/scenarios/artifact-auth.test.ts +7 -6
  103. package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
  104. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
  105. package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
  106. package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
  107. package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
  108. package/src/scenarios/audit-log-integrity.test.ts +8 -6
  109. package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
  110. package/src/scenarios/auth-mtls.test.ts +22 -20
  111. package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
  112. package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
  113. package/src/scenarios/auth-saml-profile.test.ts +14 -12
  114. package/src/scenarios/auth-scim-profile.test.ts +3 -2
  115. package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
  116. package/src/scenarios/auth-subject-link.test.ts +11 -10
  117. package/src/scenarios/auth.test.ts +5 -4
  118. package/src/scenarios/authorization-fail-closed.test.ts +3 -2
  119. package/src/scenarios/authorization-roles-shape.test.ts +9 -7
  120. package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
  121. package/src/scenarios/blob-presign-expiry.test.ts +12 -10
  122. package/src/scenarios/blob-roundtrip.test.ts +0 -0
  123. package/src/scenarios/budget-enforcement.test.ts +15 -14
  124. package/src/scenarios/budget-policy-shape.test.ts +18 -19
  125. package/src/scenarios/bulk-cancel.test.ts +9 -8
  126. package/src/scenarios/byok-auth-modes.test.ts +13 -14
  127. package/src/scenarios/byok-roundtrip.test.ts +12 -10
  128. package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
  129. package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
  130. package/src/scenarios/callai-multimodal.test.ts +5 -3
  131. package/src/scenarios/cancellation.test.ts +6 -5
  132. package/src/scenarios/cap-breach.test.ts +15 -14
  133. package/src/scenarios/capability-arm-witness.test.ts +5 -3
  134. package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
  135. package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
  136. package/src/scenarios/certification-bundle-v2.test.ts +11 -10
  137. package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
  138. package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
  139. package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
  140. package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
  141. package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
  142. package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
  143. package/src/scenarios/channel-presence-shape.test.ts +11 -12
  144. package/src/scenarios/channel-ttl.test.ts +6 -5
  145. package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
  146. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
  147. package/src/scenarios/commitment-fired.test.ts +6 -5
  148. package/src/scenarios/compensation-behavior.test.ts +24 -23
  149. package/src/scenarios/compensation-recovery.test.ts +28 -27
  150. package/src/scenarios/configurable-schema.test.ts +8 -6
  151. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
  152. package/src/scenarios/conformance-execution-witness.test.ts +9 -8
  153. package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
  154. package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
  155. package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
  156. package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
  157. package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
  158. package/src/scenarios/connection-provider-resolution.test.ts +18 -16
  159. package/src/scenarios/connector-manifest-validity.test.ts +8 -7
  160. package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
  161. package/src/scenarios/context-summarization-replay.test.ts +14 -12
  162. package/src/scenarios/contract-provenance.test.ts +18 -18
  163. package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
  164. package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
  165. package/src/scenarios/conversationLifecycle.test.ts +2 -1
  166. package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
  167. package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
  168. package/src/scenarios/core-standard-profile.test.ts +8 -9
  169. package/src/scenarios/cost-attribution.test.ts +23 -21
  170. package/src/scenarios/credential-payload-redaction.test.ts +4 -3
  171. package/src/scenarios/credentials-capability-shape.test.ts +5 -4
  172. package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
  173. package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
  174. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
  175. package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
  176. package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
  177. package/src/scenarios/data-residency-admission.test.ts +15 -14
  178. package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
  179. package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
  180. package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
  181. package/src/scenarios/debugBundle.test.ts +25 -23
  182. package/src/scenarios/discovery-families-view.test.ts +5 -4
  183. package/src/scenarios/discovery.test.ts +30 -29
  184. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
  185. package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
  186. package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
  187. package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
  188. package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
  189. package/src/scenarios/dispatchLoop.test.ts +3 -2
  190. package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
  191. package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
  192. package/src/scenarios/distillation-shape.test.ts +4 -4
  193. package/src/scenarios/distillation-stable-archive.test.ts +6 -6
  194. package/src/scenarios/distillation-token-budget.test.ts +5 -5
  195. package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
  196. package/src/scenarios/egress-audience-binding.test.ts +11 -10
  197. package/src/scenarios/egress-decision-content-free.test.ts +6 -5
  198. package/src/scenarios/egress-provenance-shape.test.ts +17 -18
  199. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
  200. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
  201. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
  202. package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
  203. package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
  204. package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
  205. package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
  206. package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
  207. package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
  208. package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
  209. package/src/scenarios/envelope-truncated.test.ts +19 -17
  210. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
  211. package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
  212. package/src/scenarios/errors.test.ts +20 -19
  213. package/src/scenarios/eventOrdering.test.ts +16 -14
  214. package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
  215. package/src/scenarios/experimental-tier-shape.test.ts +17 -15
  216. package/src/scenarios/export-bundle-portability.test.ts +17 -17
  217. package/src/scenarios/failure-path.test.ts +7 -6
  218. package/src/scenarios/feedback-capability-shape.test.ts +4 -3
  219. package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
  220. package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
  221. package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
  222. package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
  223. package/src/scenarios/feedback-record-and-list.test.ts +2 -1
  224. package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
  225. package/src/scenarios/fixtures-gating.test.ts +29 -28
  226. package/src/scenarios/fixtures-valid.test.ts +16 -15
  227. package/src/scenarios/form-content-instantiation.test.ts +15 -14
  228. package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
  229. package/src/scenarios/fs-path-traversal.test.ts +14 -12
  230. package/src/scenarios/goal-standing-continuation.test.ts +21 -21
  231. package/src/scenarios/grpc-transport.test.ts +9 -7
  232. package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
  233. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
  234. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
  235. package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
  236. package/src/scenarios/highConcurrency.test.ts +14 -13
  237. package/src/scenarios/host-callback-declaration.test.ts +8 -7
  238. package/src/scenarios/http-client-ssrf.test.ts +7 -5
  239. package/src/scenarios/i18n-negotiation.test.ts +14 -12
  240. package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
  241. package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
  242. package/src/scenarios/idempotency.test.ts +8 -7
  243. package/src/scenarios/idempotencyRetry.test.ts +13 -11
  244. package/src/scenarios/identity-owner-shape.test.ts +6 -5
  245. package/src/scenarios/identity-passthrough.test.ts +4 -3
  246. package/src/scenarios/interrupt-approval.test.ts +6 -5
  247. package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
  248. package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
  249. package/src/scenarios/interrupt-clarification.test.ts +4 -3
  250. package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
  251. package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
  252. package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
  253. package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
  254. package/src/scenarios/interruptRace.test.ts +12 -10
  255. package/src/scenarios/kv-atomic-increment.test.ts +11 -9
  256. package/src/scenarios/kv-cas.test.ts +14 -12
  257. package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
  258. package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
  259. package/src/scenarios/localized-content-delivery.test.ts +24 -26
  260. package/src/scenarios/maliciousManifest.test.ts +10 -8
  261. package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
  262. package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
  263. package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
  264. package/src/scenarios/mcp-discoverability.test.ts +9 -7
  265. package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
  266. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
  267. package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
  268. package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
  269. package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
  270. package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
  271. package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
  272. package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
  273. package/src/scenarios/mcp-stateless-request.test.ts +11 -10
  274. package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
  275. package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
  276. package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
  277. package/src/scenarios/media-url-inline-cap.test.ts +21 -19
  278. package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
  279. package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
  280. package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
  281. package/src/scenarios/memory-attribution-shape.test.ts +4 -3
  282. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
  283. package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
  284. package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
  285. package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
  286. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
  287. package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
  288. package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
  289. package/src/scenarios/memory-degraded-projection.test.ts +10 -9
  290. package/src/scenarios/memory-injection-budget.test.ts +15 -14
  291. package/src/scenarios/metric-emission.test.ts +4 -3
  292. package/src/scenarios/model-capability-insufficient.test.ts +19 -17
  293. package/src/scenarios/model-capability-substituted.test.ts +20 -18
  294. package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
  295. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
  296. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
  297. package/src/scenarios/multi-node-ordering.test.ts +4 -3
  298. package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
  299. package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
  300. package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
  301. package/src/scenarios/multi-region-idempotency.test.ts +6 -5
  302. package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
  303. package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
  304. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
  305. package/src/scenarios/oauth-capability-shape.test.ts +5 -4
  306. package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
  307. package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
  308. package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
  309. package/src/scenarios/orchestratorDispatch.test.ts +2 -1
  310. package/src/scenarios/orchestratorTermination.test.ts +2 -1
  311. package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
  312. package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
  313. package/src/scenarios/otel-emission-grpc.test.ts +3 -2
  314. package/src/scenarios/otel-emission.test.ts +6 -5
  315. package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
  316. package/src/scenarios/otel-trace-propagation.test.ts +2 -1
  317. package/src/scenarios/owner-subject-echo.test.ts +13 -12
  318. package/src/scenarios/owner-subject-shape.test.ts +11 -10
  319. package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
  320. package/src/scenarios/pack-registry-isolation.test.ts +4 -3
  321. package/src/scenarios/pack-registry-publish.test.ts +65 -63
  322. package/src/scenarios/pack-registry.test.ts +38 -36
  323. package/src/scenarios/pause-resume.test.ts +18 -16
  324. package/src/scenarios/policies.test.ts +20 -18
  325. package/src/scenarios/production-backpressure.test.ts +18 -16
  326. package/src/scenarios/production-retention-expiry.test.ts +8 -6
  327. package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
  328. package/src/scenarios/profileDerivation.test.ts +34 -33
  329. package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
  330. package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
  331. package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
  332. package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
  333. package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
  334. package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
  335. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
  336. package/src/scenarios/prompt-pack-install.test.ts +14 -12
  337. package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
  338. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
  339. package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
  340. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
  341. package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
  342. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
  343. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
  344. package/src/scenarios/prompt-template-shape.test.ts +30 -28
  345. package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
  346. package/src/scenarios/protocol-versions-array.test.ts +10 -9
  347. package/src/scenarios/provider-usage.test.ts +17 -15
  348. package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
  349. package/src/scenarios/purpose-propagation.test.ts +23 -21
  350. package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
  351. package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
  352. package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
  353. package/src/scenarios/rate-limit-envelope.test.ts +6 -5
  354. package/src/scenarios/redaction.test.ts +13 -11
  355. package/src/scenarios/redactionAdversarial.test.ts +11 -9
  356. package/src/scenarios/registry-public.test.ts +12 -11
  357. package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
  358. package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
  359. package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
  360. package/src/scenarios/replay-fork.test.ts +20 -19
  361. package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
  362. package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
  363. package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
  364. package/src/scenarios/replay-retention-expiry.test.ts +11 -9
  365. package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
  366. package/src/scenarios/replayDeterminism.test.ts +13 -12
  367. package/src/scenarios/requirement-ledger.test.ts +15 -14
  368. package/src/scenarios/restart-during-run.test.ts +3 -2
  369. package/src/scenarios/route-coverage.test.ts +20 -19
  370. package/src/scenarios/run-diff.test.ts +22 -20
  371. package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
  372. package/src/scenarios/run-transport-economy.test.ts +13 -11
  373. package/src/scenarios/runner-ledger.test.ts +17 -16
  374. package/src/scenarios/runs-lifecycle.test.ts +7 -6
  375. package/src/scenarios/runtime-capabilities.test.ts +12 -10
  376. package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
  377. package/src/scenarios/runtime-requires-shape.test.ts +7 -6
  378. package/src/scenarios/safefetch-behavior.test.ts +22 -21
  379. package/src/scenarios/safefetch-live-audit.test.ts +14 -13
  380. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  381. package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
  382. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
  383. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  384. package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
  385. package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
  386. package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
  387. package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
  388. package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
  389. package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
  390. package/src/scenarios/self-hosted-runner.test.ts +26 -24
  391. package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
  392. package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
  393. package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
  394. package/src/scenarios/sql-injection-rejection.test.ts +8 -6
  395. package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
  396. package/src/scenarios/staleClaim.test.ts +5 -4
  397. package/src/scenarios/stream-modes-buffer.test.ts +8 -7
  398. package/src/scenarios/stream-modes-mixed.test.ts +10 -9
  399. package/src/scenarios/stream-modes.test.ts +12 -11
  400. package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
  401. package/src/scenarios/stream-text-fixture.test.ts +14 -13
  402. package/src/scenarios/streamReconnect.test.ts +13 -11
  403. package/src/scenarios/strict-behavior-gate.test.ts +9 -8
  404. package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
  405. package/src/scenarios/subrun-approval-gate.test.ts +3 -3
  406. package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
  407. package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
  408. package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
  409. package/src/scenarios/subworkflow.test.ts +10 -9
  410. package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
  411. package/src/scenarios/table-cursor-pagination.test.ts +8 -6
  412. package/src/scenarios/table-schema-enforcement.test.ts +7 -5
  413. package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
  414. package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
  415. package/src/scenarios/tool-catalog-projection.test.ts +11 -9
  416. package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
  417. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
  418. package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
  419. package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
  420. package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
  421. package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
  422. package/src/scenarios/tool-hooks-shape.test.ts +3 -3
  423. package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
  424. package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
  425. package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
  426. package/src/scenarios/trigger-ingestion.test.ts +19 -17
  427. package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
  428. package/src/scenarios/v2-approver-enforced.test.ts +97 -0
  429. package/src/scenarios/v2-assurance-downgrade-audited.test.ts +75 -0
  430. package/src/scenarios/v2-bundle-v3-signed.test.ts +96 -0
  431. package/src/scenarios/v2-capabilities-root-closed.test.ts +63 -0
  432. package/src/scenarios/v2-capability-record-shape.test.ts +104 -0
  433. package/src/scenarios/v2-chain-pin-exact.test.ts +118 -0
  434. package/src/scenarios/v2-coherence-not-in-bundle.test.ts +98 -0
  435. package/src/scenarios/v2-compensation-read-projection.test.ts +85 -0
  436. package/src/scenarios/v2-configurable-closed.test.ts +67 -0
  437. package/src/scenarios/v2-dual-stack-negotiation.test.ts +118 -0
  438. package/src/scenarios/v2-effect-identity-business-key.test.ts +132 -0
  439. package/src/scenarios/v2-effect-seam-manifest.test.ts +163 -0
  440. package/src/scenarios/v2-enum-growth-rule.test.ts +69 -0
  441. package/src/scenarios/v2-era-key.test.ts +86 -0
  442. package/src/scenarios/v2-error-registry.test.ts +89 -0
  443. package/src/scenarios/v2-event-type-closed.test.ts +97 -0
  444. package/src/scenarios/v2-fork-a-v1-run.test.ts +109 -0
  445. package/src/scenarios/v2-form-when-reuses-edge-conditions.test.ts +70 -0
  446. package/src/scenarios/v2-header-scheme.test.ts +67 -0
  447. package/src/scenarios/v2-id-grammar.test.ts +77 -0
  448. package/src/scenarios/v2-idempotency-key-grammar.test.ts +65 -0
  449. package/src/scenarios/v2-interrupt-token-scheme.test.ts +55 -0
  450. package/src/scenarios/v2-lane-issuer-advertised.test.ts +62 -0
  451. package/src/scenarios/v2-legacy-profiles-absent.test.ts +78 -0
  452. package/src/scenarios/v2-manifest-ceiling-refused.test.ts +130 -0
  453. package/src/scenarios/v2-manifest-hatch-carried.test.ts +120 -0
  454. package/src/scenarios/v2-min-client-version.test.ts +48 -0
  455. package/src/scenarios/v2-minimum-version-refused.test.ts +141 -0
  456. package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +95 -0
  457. package/src/scenarios/v2-negotiation-authenticated.test.ts +125 -0
  458. package/src/scenarios/v2-negotiation-decided-emitted.test.ts +149 -0
  459. package/src/scenarios/v2-no-transport-advertisement.test.ts +57 -0
  460. package/src/scenarios/v2-owner-subject-required.test.ts +72 -0
  461. package/src/scenarios/v2-pack-isolation.test.ts +147 -0
  462. package/src/scenarios/v2-payload-registry-closed.test.ts +110 -0
  463. package/src/scenarios/v2-peer-dependency-declared.test.ts +132 -0
  464. package/src/scenarios/v2-pinned-run-disposition.test.ts +124 -0
  465. package/src/scenarios/v2-poll-cursor-v2.test.ts +114 -0
  466. package/src/scenarios/v2-preferred-version-default.test.ts +83 -0
  467. package/src/scenarios/v2-profiles-derived-only.test.ts +70 -0
  468. package/src/scenarios/v2-provider-conflict.test.ts +115 -0
  469. package/src/scenarios/v2-refresh-sla.test.ts +78 -0
  470. package/src/scenarios/v2-relaxation-recorded.test.ts +134 -0
  471. package/src/scenarios/v2-revocation-honored.test.ts +66 -0
  472. package/src/scenarios/v2-subject-link-record.test.ts +102 -0
  473. package/src/scenarios/v2-unmapped-type-refused.test.ts +95 -0
  474. package/src/scenarios/v2-v1-events-translated.test.ts +105 -0
  475. package/src/scenarios/v2-v1-signed-webhook-accepted.test.ts +109 -0
  476. package/src/scenarios/v2-webhook-durable-delivery.test.ts +238 -0
  477. package/src/scenarios/v2-well-known-one-resource.test.ts +129 -0
  478. package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
  479. package/src/scenarios/verifier-gating.test.ts +8 -6
  480. package/src/scenarios/version-fold.test.ts +9 -8
  481. package/src/scenarios/version-negotiation.test.ts +12 -11
  482. package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
  483. package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
  484. package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
  485. package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
  486. package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
  487. package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
  488. package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
  489. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
  490. package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
  491. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
  492. package/src/scenarios/wasm-pack-load.test.ts +4 -3
  493. package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
  494. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
  495. package/src/scenarios/webhook-negative.test.ts +11 -9
  496. package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
  497. package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
  498. package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
  499. package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
  500. package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
  501. package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
  502. package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
  503. package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
  504. package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
  505. package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
  506. package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
  507. package/src/scenarios/workflow-variable-format.test.ts +24 -24
  508. package/src/scenarios/workload-identity-behavior.test.ts +15 -13
  509. package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
  510. package/src/scenarios/workspace-behavior.test.ts +19 -18
  511. package/src/scenarios/workspace-capability-shape.test.ts +3 -2
  512. package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
  513. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
  514. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
  515. package/src/setup.ts +44 -6
  516. package/vitest.config.ts +5 -1
  517. package/api/.redocly.lint-ignore.yaml +0 -22
  518. package/api/asyncapi.yaml +0 -834
  519. package/api/grpc/openwop.proto +0 -251
  520. package/api/openapi.yaml +0 -2693
  521. package/api/redocly.yaml +0 -23
  522. package/schemas/README.md +0 -144
  523. package/schemas/a2a-task-state.schema.json +0 -78
  524. package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
  525. package/schemas/agent-deployment-transition.schema.json +0 -49
  526. package/schemas/agent-deployment.schema.json +0 -54
  527. package/schemas/agent-eval-suite.schema.json +0 -140
  528. package/schemas/agent-inventory-response.schema.json +0 -115
  529. package/schemas/agent-manifest.schema.json +0 -156
  530. package/schemas/agent-org-chart.schema.json +0 -82
  531. package/schemas/agent-ref.schema.json +0 -63
  532. package/schemas/agent-roster-entry.schema.json +0 -81
  533. package/schemas/agent-roster-response.schema.json +0 -21
  534. package/schemas/ai-envelope.schema.json +0 -134
  535. package/schemas/annotation-create.schema.json +0 -37
  536. package/schemas/annotation.schema.json +0 -56
  537. package/schemas/artifact-type-pack-manifest.schema.json +0 -244
  538. package/schemas/audit-verify-result.schema.json +0 -90
  539. package/schemas/budget-policy.schema.json +0 -18
  540. package/schemas/capabilities.schema.json +0 -4160
  541. package/schemas/certification-bundle-v2.schema.json +0 -118
  542. package/schemas/channel-presence-payload.schema.json +0 -41
  543. package/schemas/channel-written-payload.schema.json +0 -55
  544. package/schemas/chat-card-pack-manifest.schema.json +0 -253
  545. package/schemas/compact-tool-descriptor.schema.json +0 -51
  546. package/schemas/compensation-policy.schema.json +0 -64
  547. package/schemas/conformance-certification-bundle.schema.json +0 -86
  548. package/schemas/connection-pack-manifest.schema.json +0 -353
  549. package/schemas/conversation-event.schema.json +0 -168
  550. package/schemas/conversation-turn.schema.json +0 -117
  551. package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
  552. package/schemas/credential-provenance.schema.json +0 -18
  553. package/schemas/credential-reference.schema.json +0 -21
  554. package/schemas/debug-bundle.schema.json +0 -196
  555. package/schemas/dispatch-config.schema.json +0 -112
  556. package/schemas/envelopes/clarification.request.schema.json +0 -52
  557. package/schemas/envelopes/error.schema.json +0 -30
  558. package/schemas/envelopes/media.audio.schema.json +0 -38
  559. package/schemas/envelopes/media.file.schema.json +0 -37
  560. package/schemas/envelopes/media.image.schema.json +0 -33
  561. package/schemas/envelopes/schema.request.schema.json +0 -26
  562. package/schemas/envelopes/schema.response.schema.json +0 -22
  563. package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
  564. package/schemas/error-envelope.schema.json +0 -25
  565. package/schemas/eval-summary.schema.json +0 -92
  566. package/schemas/export-bundle.schema.json +0 -66
  567. package/schemas/form-content-pack-manifest.schema.json +0 -243
  568. package/schemas/frontend-plugin-manifest.schema.json +0 -109
  569. package/schemas/goal.schema.json +0 -104
  570. package/schemas/heartbeat-evaluated.schema.json +0 -14
  571. package/schemas/heartbeat-state-changed.schema.json +0 -14
  572. package/schemas/localized-content-language-settings.schema.json +0 -26
  573. package/schemas/localized-content-page-response.schema.json +0 -60
  574. package/schemas/localized-content-page.schema.json +0 -62
  575. package/schemas/localized-content-section.schema.json +0 -51
  576. package/schemas/memory-entry.schema.json +0 -36
  577. package/schemas/memory-list-options.schema.json +0 -37
  578. package/schemas/node-pack-manifest.schema.json +0 -654
  579. package/schemas/orchestrator-decision.schema.json +0 -90
  580. package/schemas/org-chart-responsibility-view.schema.json +0 -26
  581. package/schemas/pack-lockfile.schema.json +0 -108
  582. package/schemas/prompt-kind.schema.json +0 -8
  583. package/schemas/prompt-pack-manifest.schema.json +0 -117
  584. package/schemas/prompt-ref.schema.json +0 -40
  585. package/schemas/prompt-template.schema.json +0 -149
  586. package/schemas/proposal.schema.json +0 -84
  587. package/schemas/registry-version-manifest.schema.json +0 -208
  588. package/schemas/residency.schema.json +0 -16
  589. package/schemas/run-ancestry-response.schema.json +0 -54
  590. package/schemas/run-diff-response.schema.json +0 -64
  591. package/schemas/run-event-payloads.schema.json +0 -4452
  592. package/schemas/run-event.schema.json +0 -211
  593. package/schemas/run-options.schema.json +0 -80
  594. package/schemas/run-orchestrator-decided-event.schema.json +0 -20
  595. package/schemas/run-snapshot.schema.json +0 -148
  596. package/schemas/security-advisory.schema.json +0 -109
  597. package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
  598. package/schemas/self-hosted-runner-registration.schema.json +0 -53
  599. package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
  600. package/schemas/subject.schema.json +0 -56
  601. package/schemas/suspend-request.schema.json +0 -207
  602. package/schemas/tool-descriptor.schema.json +0 -63
  603. package/schemas/trigger-event.schema.json +0 -222
  604. package/schemas/trigger-subscription-registration.schema.json +0 -67
  605. package/schemas/trigger-subscription.schema.json +0 -26
  606. package/schemas/ui-plugin-message.schema.json +0 -90
  607. package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
  608. package/schemas/workflow-definition.schema.json +0 -850
  609. package/schemas/workload-identity.schema.json +0 -79
  610. package/schemas/workspace-file-create.schema.json +0 -20
  611. package/schemas/workspace-file.schema.json +0 -39
@@ -28,6 +28,7 @@ import { driver } from '../lib/driver.js';
28
28
  import { pollUntilTerminal } from '../lib/polling.js';
29
29
  import { isFixtureAdvertised } from '../lib/fixtures.js';
30
30
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
31
+ import { req } from '../lib/requirement-ids.js';
31
32
 
32
33
  const CAP_BREACH_FIXTURE = 'conformance-wasm-pack-memory-cap-breach';
33
34
 
@@ -41,7 +42,7 @@ describe('wasm-pack-memory-cap: host advertises maxMemoryBytes', () => {
41
42
 
42
43
  // The cap is REQUIRED to enforce §K. Hosts MUST surface the configured
43
44
  // ceiling so clients can size their packs accordingly.
44
- expect(typeof wasm.maxMemoryBytes, driver.describe(
45
+ expect(typeof wasm.maxMemoryBytes, req('openwop.it.wasm-pack-memory-cap.capabilities-nodepackruntimes-wasm-maxmemorybytes-is-a-plausible-number',
45
46
  'RFCS/0008-wasm-abi.md §K',
46
47
  'capabilities.nodePackRuntimes.wasm.maxMemoryBytes MUST be advertised as a number when WASM is supported',
47
48
  )).toBe('number');
@@ -75,7 +76,7 @@ describe('wasm-pack-memory-cap: positive path via misbehaving pack', () => {
75
76
  const runId = (create.json as { runId: string }).runId;
76
77
 
77
78
  const terminal = await pollUntilTerminal(runId, { timeoutMs: 15_000 });
78
- expect(terminal.status, driver.describe(
79
+ expect(terminal.status, req('openwop.it.wasm-pack-memory-cap.misbehaving-pack-triggers-cap-breached-with-kind-wasm-memory-and-terminal-failed',
79
80
  'RFCS/0008-wasm-abi.md §K',
80
81
  'WASM memory-cap breach MUST drive terminal `failed` (RFC 0008 §K: "kill the instance, emit cap.breached")',
81
82
  )).toBe('failed');
@@ -83,14 +84,14 @@ describe('wasm-pack-memory-cap: positive path via misbehaving pack', () => {
83
84
  const events = await driver.get(`/v1/runs/${encodeURIComponent(runId)}/events`);
84
85
  const list = (events.json as { events?: Array<{ type: string; payload?: unknown }> }).events ?? [];
85
86
  const breachEvent = list.find((e) => e.type === 'cap.breached');
86
- expect(breachEvent, driver.describe(
87
+ expect(breachEvent, req('openwop.it.wasm-pack-memory-cap.misbehaving-pack-triggers-cap-breached-with-kind-wasm-memory-and-terminal-failed',
87
88
  'RFCS/0008-wasm-abi.md §K',
88
89
  'host MUST emit cap.breached when a WASM module exceeds its memory ceiling',
89
90
  )).toBeDefined();
90
91
  // Event detail rides under the canonical `payload` envelope field (per
91
92
  // run-event-payloads.schema.json + every other event scenario), not `data`.
92
93
  const breachKind = (breachEvent?.payload as { kind?: string } | undefined)?.kind;
93
- expect(breachKind, driver.describe(
94
+ expect(breachKind, req('openwop.it.wasm-pack-memory-cap.misbehaving-pack-triggers-cap-breached-with-kind-wasm-memory-and-terminal-failed',
94
95
  'RFCS/0008-wasm-abi.md §K',
95
96
  'cap.breached payload MUST carry kind: "wasm-memory" for memory-ceiling breaches',
96
97
  )).toBe('wasm-memory');
@@ -16,6 +16,7 @@ import { driver } from '../lib/driver.js';
16
16
  import { pollUntilTerminal } from '../lib/polling.js';
17
17
  import { isFixtureAdvertised } from '../lib/fixtures.js';
18
18
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
19
+ import { req } from '../lib/requirement-ids.js';
19
20
 
20
21
  const FIXTURE = 'conformance-wasm-pack-roundtrip';
21
22
 
@@ -53,7 +54,7 @@ describe('wasm-pack-replay-determinism: same inputs → same output', () => {
53
54
  const a = await run();
54
55
  const b = await run();
55
56
 
56
- expect(a, driver.describe(
57
+ expect(a, req('openwop.it.wasm-pack-replay-determinism.two-independent-runs-with-same-inputs-produce-same-wasm-output',
57
58
  'RFCS/0008-wasm-abi.md §G',
58
59
  'WASM-node output MUST be reproducible given the same inputs',
59
60
  )).not.toBeNull();
@@ -24,6 +24,8 @@ import { describe, it, expect } from 'vitest';
24
24
  import { driver } from '../lib/driver.js';
25
25
  import { discoveryFamilies } from '../lib/discovery-capabilities.js';
26
26
  import { discoverOwnedTenant } from '../lib/webhook-receiver.js';
27
+ import { req } from '../lib/requirement-ids.js';
28
+ import { softSkip } from '../lib/soft-skip.js';
27
29
 
28
30
  async function isWebhookSupported(): Promise<boolean> {
29
31
  const disco = await driver.get('/.well-known/openwop');
@@ -36,7 +38,7 @@ describe('webhook-negative: SSRF guard rejects private destinations', () => {
36
38
  if (!(await isWebhookSupported())) {
37
39
  // eslint-disable-next-line no-console
38
40
  console.warn('[webhook-negative] host does not advertise webhook support; skipping');
39
- return;
41
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isWebhookSupported())` returned early ([webhook-negative] host does not advertise webhook support; skipping)');
40
42
  }
41
43
  // Spec-complete except for the private URL, so validation passes and the
42
44
  // request reaches the SSRF guard. `{ url }` alone 400s `validation_error`
@@ -59,9 +61,9 @@ describe('webhook-negative: SSRF guard rejects private destinations', () => {
59
61
  if (body.subscriptionId) {
60
62
  await driver.delete(`/v1/webhooks/${encodeURIComponent(body.subscriptionId)}`);
61
63
  }
62
- return;
64
+ return softSkip('blocked', 'precondition not met — `reg.status === 201` returned early ([webhook-negative] host accepts loopback destinations; SSRF guard not enforced) (seam, prior step, or fixture unavailable)');
63
65
  }
64
- expect(reg.status, driver.describe(
66
+ expect(reg.status, req('openwop.it.webhook-negative.host-with-ssrf-guard-returns-400-webhook-url-rejected-for-loopback',
65
67
  'webhooks.md + review §"Webhook SSRF guard"',
66
68
  'host with SSRF guard MUST return 400 for loopback / RFC1918 / link-local destinations',
67
69
  )).toBe(400);
@@ -72,17 +74,17 @@ describe('webhook-negative: SSRF guard rejects private destinations', () => {
72
74
 
73
75
  describe('webhook-negative: validation errors', () => {
74
76
  it('malformed url returns 400 validation_error', async () => {
75
- if (!(await isWebhookSupported())) return;
77
+ if (!(await isWebhookSupported())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isWebhookSupported())` returned early');
76
78
  const reg = await driver.post('/v1/webhooks', { url: 'not a url' });
77
- expect([400, 422]).toContain(reg.status);
79
+ expect([400, 422], req('openwop.it.webhook-negative.malformed-url-returns-400-validation-error', 'webhooks.md', 'malformed url returns 400 validation_error')).toContain(reg.status);
78
80
  const body = reg.json as { error?: string };
79
81
  expect(['validation_error', 'webhook_url_rejected']).toContain(body.error);
80
82
  });
81
83
 
82
84
  it('missing url returns 400 validation_error', async () => {
83
- if (!(await isWebhookSupported())) return;
85
+ if (!(await isWebhookSupported())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isWebhookSupported())` returned early');
84
86
  const reg = await driver.post('/v1/webhooks', { eventTypes: ['run.completed'] });
85
- expect(reg.status).toBe(400);
87
+ expect(reg.status, req('openwop.it.webhook-negative.missing-url-returns-400-validation-error', 'webhooks.md', 'missing url returns 400 validation_error')).toBe(400);
86
88
  const body = reg.json as { error?: string };
87
89
  expect(body.error).toBe('validation_error');
88
90
  });
@@ -90,9 +92,9 @@ describe('webhook-negative: validation errors', () => {
90
92
 
91
93
  describe('webhook-negative: unregister of unknown subscription', () => {
92
94
  it('DELETE /v1/webhooks/{unknown} returns 404 subscription_not_found', async () => {
93
- if (!(await isWebhookSupported())) return;
95
+ if (!(await isWebhookSupported())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isWebhookSupported())` returned early');
94
96
  const del = await driver.delete('/v1/webhooks/wh-does-not-exist');
95
- expect(del.status).toBe(404);
97
+ expect(del.status, req('openwop.it.webhook-negative.delete-v1-webhooks-unknown-returns-404-subscription-not-found', 'webhooks.md', 'DELETE /v1/webhooks/{unknown} returns 404 subscription_not_found')).toBe(404);
96
98
  const body = del.json as { error?: string };
97
99
  expect(body.error).toBe('subscription_not_found');
98
100
  });
@@ -44,6 +44,7 @@ import {
44
44
  verifyWebhookDelivery,
45
45
  SIGNATURE_PREFIX,
46
46
  } from '../lib/webhook-receiver.js';
47
+ import { req } from '../lib/requirement-ids.js';
47
48
 
48
49
  describe('webhook-receiver-adversarial: receiver rejects five canonical attacks', () => {
49
50
  const secret = 'test-secret-do-not-use-in-prod';
@@ -65,7 +66,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
65
66
  );
66
67
  expect(
67
68
  result.accepted,
68
- 'webhooks.md §"Signature recipe": valid signature + fresh timestamp + correct algorithm MUST be accepted',
69
+ req('openwop.it.webhook-receiver-adversarial.positive-control-receiver-accepts-a-freshly-signed-valid-delivery', 'spec/v1/webhooks.md', 'webhooks.md §"Signature recipe": valid signature + fresh timestamp + correct algorithm MUST be accepted'),
69
70
  ).toBe(true);
70
71
  });
71
72
 
@@ -86,7 +87,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
86
87
  if (!result.accepted) {
87
88
  expect(
88
89
  result.reason,
89
- 'webhooks.md §"Signature recipe": tampered body MUST be rejected with signature_mismatch',
90
+ req('openwop.it.webhook-receiver-adversarial.case-1-tampered-body-signature-mismatch', 'spec/v1/webhooks.md', 'webhooks.md §"Signature recipe": tampered body MUST be rejected with signature_mismatch'),
90
91
  ).toBe('signature_mismatch');
91
92
  }
92
93
  });
@@ -113,7 +114,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
113
114
  state,
114
115
  { nowSeconds: nowSec },
115
116
  );
116
- expect(result.accepted).toBe(false);
117
+ expect(result.accepted, req('openwop.it.webhook-receiver-adversarial.case-2-tampered-hmac-signature-mismatch', 'spec/v1/webhooks.md', 'case 2: tampered HMAC → signature_mismatch')).toBe(false);
117
118
  if (!result.accepted) {
118
119
  expect(result.reason).toBe('signature_mismatch');
119
120
  }
@@ -136,7 +137,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
136
137
  if (!result.accepted) {
137
138
  expect(
138
139
  result.reason,
139
- 'webhooks.md §"Replay-attack resistance": timestamp older than freshness window MUST be rejected with timestamp_expired',
140
+ req('openwop.it.webhook-receiver-adversarial.case-3-stale-timestamp-timestamp-expired', 'spec/v1/webhooks.md', 'webhooks.md §"Replay-attack resistance": timestamp older than freshness window MUST be rejected with timestamp_expired'),
140
141
  ).toBe('timestamp_expired');
141
142
  }
142
143
  });
@@ -170,7 +171,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
170
171
  if (!replay.accepted) {
171
172
  expect(
172
173
  replay.reason,
173
- 'webhooks.md §"Replay-attack resistance": replay of an already-accepted signature MUST be rejected with duplicate_signature',
174
+ req('openwop.it.webhook-receiver-adversarial.case-4-replayed-signature-duplicate-signature', 'spec/v1/webhooks.md', 'webhooks.md §"Replay-attack resistance": replay of an already-accepted signature MUST be rejected with duplicate_signature'),
174
175
  ).toBe('duplicate_signature');
175
176
  }
176
177
  });
@@ -191,7 +192,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
191
192
  if (!result.accepted) {
192
193
  expect(
193
194
  result.reason,
194
- 'webhooks.md §"Signature algorithm versioning": algorithm other than v1 MUST be rejected with wrong_algorithm by a v1-only receiver',
195
+ req('openwop.it.webhook-receiver-adversarial.case-5-wrong-algorithm-wrong-algorithm', 'spec/v1/webhooks.md', 'webhooks.md §"Signature algorithm versioning": algorithm other than v1 MUST be rejected with wrong_algorithm by a v1-only receiver'),
195
196
  ).toBe('wrong_algorithm');
196
197
  }
197
198
  });
@@ -208,7 +209,7 @@ describe('webhook-receiver-adversarial: receiver rejects five canonical attacks'
208
209
  state,
209
210
  { nowSeconds: nowSec },
210
211
  );
211
- expect(result.accepted).toBe(false);
212
+ expect(result.accepted, req('openwop.it.webhook-receiver-adversarial.case-6-malformed-signature-header-malformed-signature-header', 'spec/v1/webhooks.md', 'case 6: malformed signature header → malformed_signature_header')).toBe(false);
212
213
  if (!result.accepted) {
213
214
  expect(result.reason).toBe('malformed_signature_header');
214
215
  }
@@ -16,6 +16,8 @@
16
16
  import { describe, it, expect } from 'vitest';
17
17
  import { driver } from '../lib/driver.js';
18
18
  import { discoveryFamilies } from '../lib/discovery-capabilities.js';
19
+ import { req } from '../lib/requirement-ids.js';
20
+ import { softSkip } from '../lib/soft-skip.js';
19
21
 
20
22
  interface DiscoveryWebhooks {
21
23
  webhooks?: {
@@ -33,7 +35,7 @@ describe('webhook-sig-algorithm: host advertises supported algorithm set', () =>
33
35
  if (!webhooks?.supported) {
34
36
  // eslint-disable-next-line no-console
35
37
  console.warn('[webhook-sig-algorithm] host does not advertise webhook support; skipping');
36
- return;
38
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!webhooks?.supported` returned early ([webhook-sig-algorithm] host does not advertise webhook support; skipping)');
37
39
  }
38
40
 
39
41
  const algos = webhooks.signatureAlgorithms;
@@ -45,10 +47,10 @@ describe('webhook-sig-algorithm: host advertises supported algorithm set', () =>
45
47
  console.warn(
46
48
  '[webhook-sig-algorithm] host does not advertise webhooks.signatureAlgorithms (pre-v1.1); skipping shape check',
47
49
  );
48
- return;
50
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!Array.isArray(algos)` returned early ([webhook-sig-algorithm] host does not advertise webhooks.signatureAlgorithms (pre-v1.1); skipping shape check)');
49
51
  }
50
52
 
51
- expect(algos.includes('v1'), driver.describe(
53
+ expect(algos.includes('v1'), req('openwop.it.webhook-sig-algorithm.discovery-surfaces-a-webhooks-signaturealgorithms-array-including-v1',
52
54
  'webhooks.md §"Signature algorithm versioning"',
53
55
  'webhooks.signatureAlgorithms MUST include "v1" when surfaced (canonical baseline)',
54
56
  )).toBe(true);
@@ -108,6 +108,7 @@ import { discoveryFamilies } from '../lib/discovery-capabilities.js';
108
108
  import { pollUntilTerminal } from '../lib/polling.js';
109
109
  import { isFixtureAdvertised } from '../lib/fixtures.js';
110
110
  import { discoverOwnedTenant, resolveRegistrationUrl } from '../lib/webhook-receiver.js';
111
+ import { req } from '../lib/requirement-ids.js';
111
112
 
112
113
  interface DeliveredRequest {
113
114
  readonly headers: Record<string, string>;
@@ -116,13 +117,13 @@ interface DeliveredRequest {
116
117
 
117
118
  async function startReceiver(): Promise<{ server: Server; url: string; received: DeliveredRequest[] }> {
118
119
  const received: DeliveredRequest[] = [];
119
- const server = createServer((req: IncomingMessage, res: ServerResponse) => {
120
+ const server = createServer((reqBody: IncomingMessage, res: ServerResponse) => {
120
121
  const chunks: Buffer[] = [];
121
- req.on('data', (c: Buffer) => chunks.push(c));
122
- req.on('end', () => {
122
+ reqBody.on('data', (c: Buffer) => chunks.push(c));
123
+ reqBody.on('end', () => {
123
124
  const body = Buffer.concat(chunks).toString('utf8');
124
125
  const headers: Record<string, string> = {};
125
- for (const [k, v] of Object.entries(req.headers)) {
126
+ for (const [k, v] of Object.entries(reqBody.headers)) {
126
127
  if (typeof v === 'string') headers[k.toLowerCase()] = v;
127
128
  else if (Array.isArray(v)) headers[k.toLowerCase()] = v.join(',');
128
129
  }
@@ -225,7 +226,7 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
225
226
  }
226
227
  }
227
228
 
228
- expect(reg.status, driver.describe(
229
+ expect(reg.status, req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature',
229
230
  'webhooks.md §"Register"',
230
231
  'POST /v1/webhooks MUST return 201 with webhookId + secret on success',
231
232
  )).toBe(201);
@@ -240,7 +241,7 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
240
241
  // what the spec shows. The postgres reference host returns both names, which
241
242
  // is why nothing went red here.
242
243
  const sub = reg.json as { webhookId: string; secret: string };
243
- expect(typeof sub.webhookId, driver.describe(
244
+ expect(typeof sub.webhookId, req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature',
244
245
  'api/openapi.yaml registerWebhook 201',
245
246
  'the 201 body MUST carry `webhookId` (required) — `subscriptionId` is not in the contract',
246
247
  )).toBe('string');
@@ -276,7 +277,7 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
276
277
  // has a subscriber; if nothing arrived HERE, the delivery went somewhere
277
278
  // this process cannot see and every assertion below it would be vacuous.
278
279
  // It fails — it must never soft-skip.
279
- expect(ourDeliveries.length, driver.describe(
280
+ expect(ourDeliveries.length, req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature',
280
281
  'webhooks.md §"Delivery"',
281
282
  registration.tunnelled
282
283
  ? 'host MUST POST at least one event for THIS run to the registered subscriber. ' +
@@ -289,7 +290,7 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
289
290
  // Validate the FIRST delivery's signature contract. Other deliveries
290
291
  // share the same signing rules; checking one is sufficient.
291
292
  const first = ourDeliveries[0]!;
292
- expect(first.headers['x-openwop-signature-algorithm'], driver.describe(
293
+ expect(first.headers['x-openwop-signature-algorithm'], req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature',
293
294
  'webhooks.md §"Signature algorithm versioning"',
294
295
  'every delivery MUST set X-openwop-Signature-Algorithm: v1',
295
296
  )).toBe('v1');
@@ -301,26 +302,26 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
301
302
  // `X-openwop-Signature: sha256={hex}`. (Suite↔spec divergence fixed 2026-08-09.)
302
303
  expect(
303
304
  first.headers['x-openwop-webhook-id'],
304
- driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Webhook-Id MUST carry the subscription id'),
305
+ req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'webhooks.md §"Delivery headers"', 'X-openwop-Webhook-Id MUST carry the subscription id'),
305
306
  ).toBe(sub.webhookId);
306
307
 
307
308
  const timestamp = first.headers['x-openwop-timestamp'];
308
309
  expect(
309
310
  typeof timestamp === 'string' && timestamp.length > 0,
310
- driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Timestamp MUST be a Unix-seconds integer string'),
311
+ req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'webhooks.md §"Delivery headers"', 'X-openwop-Timestamp MUST be a Unix-seconds integer string'),
311
312
  ).toBe(true);
312
313
 
313
314
  const signature = first.headers['x-openwop-signature'] ?? '';
314
315
  expect(
315
316
  signature.startsWith('sha256='),
316
- driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST carry the `sha256=` prefix'),
317
+ req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST carry the `sha256=` prefix'),
317
318
  ).toBe(true);
318
319
  const expected = createHmac('sha256', sub.secret)
319
320
  .update(`${timestamp}.${first.body}`, 'utf8')
320
321
  .digest('hex');
321
322
  expect(
322
323
  signature.replace('sha256=', ''),
323
- driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST be sha256=HMAC-SHA256(secret, `${X-openwop-Timestamp}.${rawBody}`)'),
324
+ req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST be sha256=HMAC-SHA256(secret, `${X-openwop-Timestamp}.${rawBody}`)'),
324
325
  ).toBe(expected);
325
326
 
326
327
  // RFC 0165 §C.1 — dual emission of the `OpenWOP-*` family. SHOULD-level and
@@ -337,11 +338,11 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
337
338
  ['openwop-signature', 'x-openwop-signature'],
338
339
  ['openwop-signature-algorithm', 'x-openwop-signature-algorithm'],
339
340
  ] as const) {
340
- expect(first.headers[neu], driver.describe('RFC 0165 §C.1', `${neu} MUST equal ${old} when the OpenWOP-* family is emitted`)).toBe(first.headers[old]);
341
+ expect(first.headers[neu], req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'RFC 0165 §C.1', `${neu} MUST equal ${old} when the OpenWOP-* family is emitted`)).toBe(first.headers[old]);
341
342
  }
342
343
  expect(
343
344
  String(dual).replace('sha256=', ''),
344
- driver.describe('RFC 0165 §C.1', 'OpenWOP-Signature MUST verify over the same bytes as X-openwop-Signature'),
345
+ req('openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature', 'RFC 0165 §C.1', 'OpenWOP-Signature MUST verify over the same bytes as X-openwop-Signature'),
345
346
  ).toBe(expected);
346
347
  }
347
348
 
@@ -404,7 +405,7 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
404
405
  }
405
406
  }
406
407
 
407
- expect(reg.status, driver.describe(
408
+ expect(reg.status, req('openwop.it.webhook-signed-delivery.control-with-a-tunnel-wired-the-host-still-refuses-the-loopback-receiver',
408
409
  'webhooks.md §"SSRF protection"',
409
410
  'the server MUST reject loopback subscription URLs at registration time. ' +
410
411
  'It was accepted here, so this run cannot attribute the tunnelled test\'s pass to ' +
@@ -38,6 +38,8 @@ import { describe, it, expect } from 'vitest';
38
38
  import { driver, type OpenWOPResponse } from '../lib/driver.js';
39
39
  import { behaviorGate } from '../lib/behavior-gate.js';
40
40
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
41
+ import { req } from '../lib/requirement-ids.js';
42
+ import { softSkip } from '../lib/soft-skip.js';
41
43
 
42
44
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
43
45
 
@@ -66,26 +68,26 @@ async function gateOnWebhooks(): Promise<boolean> {
66
68
  describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: advertisement shape (webhooks.md)', () => {
67
69
  it('the webhooks block is either absent or carries a boolean supported flag', async () => {
68
70
  const cap = await readCapabilityFamily<WebhooksCap>('webhooks');
69
- if (cap === undefined) return; // host doesn't advertise webhooks — conformant
71
+ if (cap === undefined) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === undefined` returned early (host doesn\'t advertise webhooks — conformant)'); // host doesn't advertise webhooks — conformant
70
72
  expect(
71
73
  typeof cap.supported,
72
- driver.describe('capabilities.schema.json §webhooks', 'webhooks.supported MUST be a boolean when present'),
74
+ req('openwop.it.webhook-tenant-isolation.the-webhooks-block-is-either-absent-or-carries-a-boolean-supported-flag', 'capabilities.schema.json §webhooks', 'webhooks.supported MUST be a boolean when present'),
73
75
  ).toBe('boolean');
74
76
  });
75
77
  });
76
78
 
77
79
  describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: two-tenant proof via the test seam (RFC 0093 §A.3)', () => {
78
80
  it('a subscription registered under tenant A is invisible to tenant B', async () => {
79
- if (!(await gateOnWebhooks())) return;
81
+ if (!(await gateOnWebhooks())) return softSkip('blocked', 'precondition not met — `!(await gateOnWebhooks())` returned early (seam, prior step, or fixture unavailable)');
80
82
 
81
83
  const reg = await seam('tenant-a', 'register', {
82
84
  url: SAFE_URL,
83
85
  events: ['run.completed'],
84
86
  });
85
- if (reg.status === 404) return; // host doesn't expose the test seam — soft-skip
86
- expect(reg.status, driver.describe('RFC 0093 §A.3', 'seam register under tenant A MUST succeed')).toBe(200);
87
+ if (reg.status === 404) return softSkip('blocked', 'precondition not met — `reg.status === 404` returned early (host doesn\'t expose the test seam — soft-skip) (seam, prior step, or fixture unavailable)'); // host doesn't expose the test seam — soft-skip
88
+ expect(reg.status, req('openwop.it.webhook-tenant-isolation.a-subscription-registered-under-tenant-a-is-invisible-to-tenant-b', 'RFC 0093 §A.3', 'seam register under tenant A MUST succeed')).toBe(200);
87
89
  const webhookId = (reg.json as { webhookId?: string }).webhookId;
88
- expect(typeof webhookId, 'seam register MUST return the new webhookId').toBe('string');
90
+ expect(typeof webhookId, req('openwop.it.webhook-tenant-isolation.a-subscription-registered-under-tenant-a-is-invisible-to-tenant-b', 'RFC 0093 §A.3', 'seam register MUST return the new webhookId')).toBe('string');
89
91
 
90
92
  try {
91
93
  const listB = await seam('tenant-b', 'list', {});
@@ -94,7 +96,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: two-tenant proof via the t
94
96
  .map((w) => w.webhookId);
95
97
  expect(
96
98
  idsB,
97
- driver.describe(
99
+ req('openwop.it.webhook-tenant-isolation.a-subscription-registered-under-tenant-a-is-invisible-to-tenant-b',
98
100
  'SECURITY/invariants.yaml webhook-cross-tenant-isolation',
99
101
  'tenant B MUST NOT see tenant A subscriptions in its list',
100
102
  ),
@@ -105,7 +107,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: two-tenant proof via the t
105
107
  .map((w) => w.webhookId);
106
108
  expect(
107
109
  idsA,
108
- driver.describe('RFC 0093 §A.3', 'tenant A MUST see its own subscription (same-tenant control)'),
110
+ req('openwop.it.webhook-tenant-isolation.a-subscription-registered-under-tenant-a-is-invisible-to-tenant-b', 'RFC 0093 §A.3', 'tenant A MUST see its own subscription (same-tenant control)'),
109
111
  ).toContain(webhookId);
110
112
  } finally {
111
113
  await seam('tenant-a', 'unregister', { webhookId });
@@ -115,7 +117,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: two-tenant proof via the t
115
117
 
116
118
  describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: black-box registration-surface scoping (webhooks.md)', () => {
117
119
  it('registering under a tenant the caller is not a member of is refused', async () => {
118
- if (!(await gateOnWebhooks())) return;
120
+ if (!(await gateOnWebhooks())) return softSkip('blocked', 'precondition not met — `!(await gateOnWebhooks())` returned early (seam, prior step, or fixture unavailable)');
119
121
 
120
122
  const foreignTenant = `openwop-conformance-foreign-${uniqueSuffix()}`;
121
123
  const reg = await driver.post('/v1/webhooks', {
@@ -135,7 +137,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: black-box registration-sur
135
137
  }
136
138
  expect(
137
139
  reg.status,
138
- driver.describe(
140
+ req('openwop.it.webhook-tenant-isolation.registering-under-a-tenant-the-caller-is-not-a-member-of-is-refused',
139
141
  'webhooks.md §Endpoints ("the caller MUST be a member of the tenant") + RFC 0093 §A.3',
140
142
  'registration under a tenant the caller is not a member of MUST be refused (403/404/400), never 201',
141
143
  ),
@@ -143,7 +145,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: black-box registration-sur
143
145
  });
144
146
 
145
147
  it('a held subscription cannot be unregistered through a foreign tenant scope', async () => {
146
- if (!(await gateOnWebhooks())) return;
148
+ if (!(await gateOnWebhooks())) return softSkip('blocked', 'precondition not met — `!(await gateOnWebhooks())` returned early (seam, prior step, or fixture unavailable)');
147
149
 
148
150
  // Register under the caller's own tenant (host defaults the scope from
149
151
  // the API key when tenantId is omitted — the same registration shape the
@@ -159,10 +161,10 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: black-box registration-sur
159
161
  console.warn(
160
162
  `[webhook-tenant-isolation] could not register a probe subscription (${reg.status}); skipping foreign-unregister leg`,
161
163
  );
162
- return;
164
+ return softSkip('blocked', 'precondition not met — `reg.status !== 201` returned early ([webhook-tenant-isolation] could not register a probe subscription (…); skipping foreign-unregister leg) (seam, prior step, or fixture unavailable)');
163
165
  }
164
166
  const webhookId = (reg.json as { webhookId?: string }).webhookId;
165
- expect(typeof webhookId, 'registration MUST return webhookId').toBe('string');
167
+ expect(typeof webhookId, req('openwop.it.webhook-tenant-isolation.a-held-subscription-cannot-be-unregistered-through-a-foreign-tenant-scope', 'webhooks.md §Unregister (403 non-member / 404 not-in-scope) + RFC 0093 §A.3', 'registration MUST return webhookId')).toBe('string');
166
168
 
167
169
  try {
168
170
  const foreignTenant = `openwop-conformance-foreign-${uniqueSuffix()}`;
@@ -171,7 +173,7 @@ describe.skipIf(HTTP_SKIP)('webhook-tenant-isolation: black-box registration-sur
171
173
  );
172
174
  expect(
173
175
  del.status !== 204 && del.status < 500,
174
- driver.describe(
176
+ req('openwop.it.webhook-tenant-isolation.a-held-subscription-cannot-be-unregistered-through-a-foreign-tenant-scope',
175
177
  'webhooks.md §Unregister (403 non-member / 404 not-in-scope) + RFC 0093 §A.3',
176
178
  `unregister through a foreign tenant scope MUST NOT succeed (got ${del.status})`,
177
179
  ),