@openwop/openwop-conformance 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # `@openwop/openwop-conformance` Changelog
2
2
 
3
+ ## [2.0.2] — 2026-09-06 — 2.0.1's own fix could not run: the derived wait exceeded the harness timeout that governs it
4
+
5
+ A regression in 2.0.1, measured by the host that reported the defect 2.0.1 fixed. On a 2.0.1 re-cut one row moved, the wrong way: `0173.webhook-durable-delivery.dead-letter` went `executed-pass` → `executed-fail`.
6
+
7
+ 2.0.1 widened the retry wait to a 90 s cap and left both `it()` blocks on the harness default (`vitest.config.ts` `testTimeout: 30_000`, no per-test override). **A wait longer than the timeout that governs it can never elapse** — the test dies at 30 s with "Test timed out in 30000ms". The dead-letter leg is worse than one wait: `waitTerminal` plus **two** sequential `retryWaitMs` waits, up to 191 s inside a 30 s budget. And it took a passing row with it — `dead-letter` passed at rc.67 by observing `attempts.length > 1` inside the old 20 s window, and 2.0.1 moved that leg onto `retryWaitMs` too.
8
+
9
+ Both `it()` blocks now take a timeout **derived from the wait constant** — `RETRY_WAIT_CAP_MS + WAIT_SLACK_MS`, and twice the cap for the two-wait leg — rather than a second literal, so a later change to the wait carries its own budget.
10
+
11
+ The shape is the defect 2.0.1 fixed, displaced one layer: 2.0.1 stopped the scenario blaming a host for a deadline *the scenario* chose, then let *the harness* choose a shorter one silently, on exactly the durable hosts the widening was written to help.
12
+
3
13
  ## [2.0.1] — 2026-09-05 — the webhook durability scenario read the wrong carrier and imposed its own deadline
4
14
 
5
15
  Two defects in `v2-webhook-durable-delivery`, both reported by a host running against 2.0.0.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.0.1",
4
- "stampSha256": "58332ded443bd030809e2da256d3d4ea381d3b3bc605421b89b26336800b0acc"
3
+ "version": "2.0.2",
4
+ "stampSha256": "ae8640bf298cdf8a4efd624f16424ed1feba41be0f3f919f859bf5a5bbe0432f"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Production-ready black-box conformance suite for OpenWOP v1.0 compliant servers.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -56,6 +56,6 @@
56
56
  "@openwop/spec-artifacts": "file:../spec-artifacts"
57
57
  },
58
58
  "peerDependencies": {
59
- "@openwop/spec-artifacts": "2.0.1"
59
+ "@openwop/spec-artifacts": "2.0.2"
60
60
  }
61
61
  }
package/requirements.json CHANGED
@@ -29006,7 +29006,7 @@
29006
29006
  {
29007
29007
  "id": "openwop.it.v2-webhook-durable-delivery.a-failed-attempt-is-retried-and-the-event-is-delivered-at-least-once",
29008
29008
  "file": "v2-webhook-durable-delivery.test.ts",
29009
- "line": 196,
29009
+ "line": 221,
29010
29010
  "title": "a failed attempt is retried and the event is delivered at least once",
29011
29011
  "explicitId": "openwop.requirement.0173.webhook-durable-delivery",
29012
29012
  "citations": [
@@ -29041,7 +29041,7 @@
29041
29041
  {
29042
29042
  "id": "openwop.it.v2-webhook-durable-delivery.an-exhausted-delivery-is-dead-lettered-never-dropped",
29043
29043
  "file": "v2-webhook-durable-delivery.test.ts",
29044
- "line": 250,
29044
+ "line": 275,
29045
29045
  "title": "an exhausted delivery is dead-lettered, never dropped",
29046
29046
  "explicitId": "openwop.requirement.0173.webhook-durable-delivery.dead-letter",
29047
29047
  "citations": [
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "_comment": "Provenance of @openwop/spec-artifacts (RFC 0168 §D.2). files: SHA-256 per file; the conformance suite compares the installed peer against dist/spec-artifacts.lock.json at start.",
3
3
  "package": "@openwop/spec-artifacts",
4
- "version": "2.0.1",
5
- "corpusTag": "v2.0.1",
4
+ "version": "2.0.2",
5
+ "corpusTag": "v2.0.2",
6
6
  "files": {
7
7
  "api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
8
8
  "api/asyncapi.yaml": "d5ecb9ee6114582be3b1f662c84bfac9ae96dae7bacb853e461168f70a8e1c7d",
9
9
  "api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
10
10
  "api/openapi.yaml": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
11
11
  "api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
12
- "api/seams-v2.yaml": "3eb009580df13443f96f60f311f1b3755b76d1170e0dd4bdc44e0019a4be49bb",
13
- "api/v2/asyncapi.yaml": "3b454a919cacedd86a292475f43ea7523806c75b5c2ee4e4363cc693c103f6fd",
14
- "api/v2/openapi.yaml": "ba5ff45d479682e77ebe4f5f8e8700fdf96e09cdd70820b9c78287618b2f1072",
12
+ "api/seams-v2.yaml": "95eccbef6e1f7f51417efe2f307d8950bb520d3b86806bf9d1a316e96aa6b9b5",
13
+ "api/v2/asyncapi.yaml": "70d1a50b3acdf51763239463efe0336fc80b4eb2f9b4ab50d05860ead0490cf0",
14
+ "api/v2/openapi.yaml": "e55547a384bb43f8fe21ae93a27dfc7a16df6494f5ae50aca60028968ce039d4",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
17
17
  "schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
@@ -199,7 +199,7 @@
199
199
  "schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
200
200
  "spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
201
201
  "spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
202
- "spec/v1/core-standard-manifest.json": "321048584e70be5855e13edd75566635e980d69f3541d88d3fb7a51c38c22942",
202
+ "spec/v1/core-standard-manifest.json": "1afaf3936e9d13d5fb71a83fe63a81f8bbb18efb7417c60e523cebf63a5060e7",
203
203
  "spec/v1/deprecations.json": "1d5acb69a9b8ccb57275a95605f74aef1d920685f8407c9d382a46b59dc803bb",
204
204
  "spec/v1/deprecations.schema.json": "18c87e78bedc210431f795ae44c5b5d202f2f3317850d5cf86867d4f1fa1cdfb",
205
205
  "spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
@@ -230,8 +230,8 @@
230
230
  "spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
231
231
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
232
232
  "spec/v2/profiles.json": "0636f19fceae625390003a347e70ef4797d84766b5c24ce8a02cea52aadebca4",
233
- "spec/v2/release.json": "88167a813c554bb90f0356bcc365b57415820c2bb1f52fc2e0e15e64f032ef0e",
233
+ "spec/v2/release.json": "fea7f9b757b226e263b7626d1bfebfb680e7ea853cca86b2426c82435e8fdbd4",
234
234
  "spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624"
235
235
  },
236
- "corpusCommit": "91912e2e57a4c5ad124075780e456e63ee91eb9f"
236
+ "corpusCommit": "7cf764b47ef3b79ddcf5c6e5dfea9f37f9b60a66"
237
237
  }
@@ -175,6 +175,31 @@ function retryWaitMs(doc: Record<string, unknown>): number {
175
175
  return backoff === 'exponential' || backoff === 'fixed' ? RETRY_WAIT_CAP_MS : RETRY_WAIT_FLOOR_MS;
176
176
  }
177
177
 
178
+ /**
179
+ * The per-test budget, DERIVED from the wait above (suite 2.0.2).
180
+ *
181
+ * 2.0.1 raised the derived wait to 90 s and left the `it()` blocks on the
182
+ * harness default (`vitest.config.ts` `testTimeout: 30_000`). A wait longer
183
+ * than the timeout that governs it can never elapse: on exactly the durable
184
+ * hosts the widening was written to help, the test died at 30 s with "Test
185
+ * timed out in 30000ms" — and took `dead-letter` with it, which had passed at
186
+ * the old 20 s window. Measured by a host on 2.0.1 (`00337-dgw`): one row moved
187
+ * `executed-pass -> executed-fail` and it was this one.
188
+ *
189
+ * The shape is the defect 2.0.1 itself fixed, one layer out: 2.0.1 stopped the
190
+ * scenario blaming a host for a deadline the SCENARIO chose, and then let the
191
+ * HARNESS choose a shorter one silently. So the budget is computed from
192
+ * `RETRY_WAIT_CAP_MS` rather than written as a second literal — a later change
193
+ * to the wait carries its own timeout, the way the advert is sourced from the
194
+ * constant the delivery loop reads. `WAIT_SLACK_MS` covers `waitTerminal`,
195
+ * registration and the HTTP round trips around the waits.
196
+ */
197
+ const WAIT_SLACK_MS = 30_000;
198
+ /** One `retryWaitMs` wait (the retry leg). */
199
+ const RETRY_TEST_TIMEOUT_MS = RETRY_WAIT_CAP_MS + WAIT_SLACK_MS;
200
+ /** Two sequential `retryWaitMs` waits (the dead-letter leg: observe a retry, then exhaust). */
201
+ const DEAD_LETTER_TEST_TIMEOUT_MS = RETRY_WAIT_CAP_MS * 2 + WAIT_SLACK_MS;
202
+
178
203
  /** Register the suite receiver; null (with a note) when the host's SSRF guard refuses a loopback URL. */
179
204
  async function register(url: string): Promise<{ webhookId: string } | null> {
180
205
  const registration = resolveRegistrationUrl(url);
@@ -245,7 +270,7 @@ describe('RFC 0173 §B — webhook-durable-delivery (gated on webhooks)', () =>
245
270
 
246
271
  const del = await driver.delete(`/webhooks/${encodeURIComponent(sub.webhookId)}`);
247
272
  expect(del.status, req('openwop.requirement.0173.webhook-durable-delivery', 'webhooks.md §Surfaces', 'DELETE /webhooks/{webhookId} MUST answer 204')).toBe(204);
248
- });
273
+ }, RETRY_TEST_TIMEOUT_MS);
249
274
 
250
275
  it('an exhausted delivery is dead-lettered, never dropped', async () => {
251
276
  const doc = await discovery();
@@ -285,5 +310,5 @@ describe('RFC 0173 §B — webhook-durable-delivery (gated on webhooks)', () =>
285
310
  // (no GET /webhooks/{webhookId}/dead-letters). Without a normative read the
286
311
  // routing to the sink is not observable from the suite.
287
312
  return softSkip('blocked', 'no normative dead-letter read surface for webhook deliveries in api/v2/openapi.yaml (a GET /webhooks/{webhookId}/dead-letters projection is needed) — exhaustion was observed, routing to the sink was not');
288
- });
313
+ }, DEAD_LETTER_TEST_TIMEOUT_MS);
289
314
  });