@openwop/openwop-conformance 2.0.0-rc.28 → 2.0.0-rc.29

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.0.0-rc.28",
4
- "stampSha256": "c7d6661057eca87dffb69c7d262e9b0dd6025087be2950df2007214fda6b0e57"
3
+ "version": "2.0.0-rc.29",
4
+ "stampSha256": "fd78a025ef1ebe83882b86b21d41a34d8d64b7938615b4f6d2976065b365e293"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.0-rc.28",
3
+ "version": "2.0.0-rc.29",
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.0-rc.28"
59
+ "@openwop/spec-artifacts": "2.0.0-rc.29"
60
60
  }
61
61
  }
package/requirements.json CHANGED
@@ -26340,7 +26340,7 @@
26340
26340
  {
26341
26341
  "id": "openwop.it.v2-dual-stack-negotiation.an-unlisted-major-is-406-protocol-version-unsupported-with-details-protocolversi",
26342
26342
  "file": "v2-dual-stack-negotiation.test.ts",
26343
- "line": 108,
26343
+ "line": 111,
26344
26344
  "title": "an unlisted major is 406 protocol_version_unsupported with details.protocolVersions[]",
26345
26345
  "explicitId": "openwop.requirement.0172.dual-stack-negotiation.unlisted-major",
26346
26346
  "citations": [
@@ -26364,7 +26364,7 @@
26364
26364
  {
26365
26365
  "id": "openwop.it.v2-dual-stack-negotiation.openwop-version-2-0-on-a-v1-path-is-400-protocol-version-mismatch",
26366
26366
  "file": "v2-dual-stack-negotiation.test.ts",
26367
- "line": 119,
26367
+ "line": 122,
26368
26368
  "title": "OpenWOP-Version: 2.0 on a /v1/ path is 400 protocol_version_mismatch",
26369
26369
  "explicitId": "openwop.requirement.0172.dual-stack-negotiation.v1-path-mismatch",
26370
26370
  "citations": [
@@ -26383,7 +26383,7 @@
26383
26383
  {
26384
26384
  "id": "openwop.it.v2-dual-stack-negotiation.every-response-reports-the-contract-that-produced-it",
26385
26385
  "file": "v2-dual-stack-negotiation.test.ts",
26386
- "line": 128,
26386
+ "line": 131,
26387
26387
  "title": "every response reports the contract that produced it",
26388
26388
  "explicitId": "openwop.requirement.0172.dual-stack-negotiation.response-header",
26389
26389
  "citations": [
@@ -1,7 +1,7 @@
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.0-rc.28",
4
+ "version": "2.0.0-rc.29",
5
5
  "corpusTag": null,
6
6
  "files": {
7
7
  "api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
@@ -9,9 +9,9 @@
9
9
  "api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
10
10
  "api/openapi.yaml": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
11
11
  "api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
12
- "api/seams-v2.yaml": "d92f0832250f7e2943304c3ebb3b4ac4d94a627a5f275a8cd29f608cae48f920",
13
- "api/v2/asyncapi.yaml": "917d25c0c03d418b43b778423182de1aaa2f7b4f30a175bdeab3b7d3ffdb894a",
14
- "api/v2/openapi.yaml": "ccd9e6a5dd8084c6d6c0959157f447da96fc7493cad2479abbf97b69483f9404",
12
+ "api/seams-v2.yaml": "db41292cd3c1c1e87270c04aacf6be9fa7726e28c25961ddcc0e5a77d69ffb2e",
13
+ "api/v2/asyncapi.yaml": "0fadad06111bdeb2a2724c448f78b9e5d9722ffc2b0b733854a168aa50321c67",
14
+ "api/v2/openapi.yaml": "2a2921c71ed5b5e9de0cf277b134b156e9a08c93b31725e799bbd38a04de8f7e",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
17
17
  "schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
@@ -198,7 +198,7 @@
198
198
  "schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
199
199
  "spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
200
200
  "spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
201
- "spec/v1/core-standard-manifest.json": "bd06beb20cc52f8558e8b72598becb380e3159bb842f13389bcf92619f1fad23",
201
+ "spec/v1/core-standard-manifest.json": "722518840db1d1d9ad3ed190dcb151537860e31e92c45649307945c79eb523f1",
202
202
  "spec/v1/deprecations.json": "520d79927a8ed43ccf62c207a7cf6cf7b19b16e00bbbbdf0410667e939c19d85",
203
203
  "spec/v1/deprecations.schema.json": "4cdbbb8eb9c0092913a5704c943880f0c8581bcf0f640a7df5a84105d53c8aee",
204
204
  "spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
@@ -228,7 +228,7 @@
228
228
  "spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
229
229
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
230
230
  "spec/v2/profiles.json": "1f0ee40491131cf561ef19a0394c47ba476b4567514fe16befb6cada4a10a5a4",
231
- "spec/v2/release.json": "20a6cb7efde5fcdbbc2b663976882b6dec93ec52556d422de7290e25906f2748"
231
+ "spec/v2/release.json": "38cf198fc25ff7af322a1781bd128bc31e8c213194436ba538e6e065170ddc09"
232
232
  },
233
- "corpusCommit": "e9aa9131f3d64f814b2c0ca16535675968efad76"
233
+ "corpusCommit": "9e0c76b709aed18afa85f6b84250418047861f5a"
234
234
  }
@@ -76,32 +76,35 @@ describe('v2 dual-stack-negotiation (RFC 0172 §A.3–§A.4 — gated on two maj
76
76
  const read = await http(() => driver.get(`/runs/${encodeURIComponent(runId)}`, { headers: { 'OpenWOP-Version': '2.0' } }));
77
77
  if (read === null) return softSkip('blocked', 'GET /runs/{runId} unreachable (fetch failed)');
78
78
  expect(read.status, req('openwop.requirement.0172.dual-stack-negotiation.cross-major-read', 'spec/v2/core/versioning.md §5', 'the overlap: a run created through /v1/runs MUST be readable through GET /runs/{runId} with OpenWOP-Version: 2.0')).toBe(200);
79
- // NAMES the same run not byte-identical to the v1 id.
79
+ // The v2 read MUST name the same run BY ITS TENANT-BOUND PROJECTION.
80
80
  //
81
- // This asserted `.toBe(runId)` until 2026-09-04, which invented a
82
- // requirement. `versioning.md` §5 describes the dual-stack scenario's SHAPE
83
- // ("creates one run through /v1/runs … and reads it through /runs with
84
- // OpenWOP-Version: 2; the response headers name the contract used") and says
85
- // nothing about the identifier. `identity.md` §5 does: under major 2 a
86
- // `runId` is tenant-bound `<tenantId>/<opaque>`, a grammar in
87
- // `ids.schema.json`. A host implementing BOTH sections faithfully cannot
88
- // satisfy byte-equality, and one turned its P4-D branch red on exactly this.
81
+ // This assertion has been wrong twice, in opposite directions, and the pair
82
+ // is the point:
89
83
  //
90
- // The assertion tighter than its own prose is the mirror of the schema
91
- // looser than its own prose: both are gaps between a check and the text it
92
- // cites, and both are invisible until a host implements the text.
84
+ // until 2026-09-04 `.toBe(runId)` byte-equality with the v1 id, cited to
85
+ // versioning.md §5, which said nothing about identifiers.
86
+ // TIGHTER than its prose: it failed a host that had
87
+ // implemented identity.md §5 faithfully.
88
+ // rc.28 accepted the bare v1 id OR its projection. LOOSER than
89
+ // its prose: `run-snapshot.schema.json` binds `runId` to
90
+ // `ids.schema.json#/$defs/runId`, whose pattern REQUIRES
91
+ // the `/`. rc.28 passed a response the v2 contract
92
+ // rejects — the same defect it was written to fix,
93
+ // committed in the act of fixing it.
93
94
  //
94
- // What §5 actually requires is that the v2 read resolves to the SAME RUN.
95
- // Accept the identical id (a host that does not project) or the tenant-bound
96
- // projection of it (a host that does); reject anything else, which would be
97
- // a different run.
95
+ // §5 now states the rule outright, and the reason it is a MUST is not
96
+ // stylistic: `identity.md` §5 requires a host to refuse a tenant-bound id
97
+ // whose tenant segment is not the caller's (`403 id_tenant_mismatch`). A
98
+ // bare id HAS no tenant segment, so that mandatory check cannot run on it.
99
+ // A legacy unprefixed form would be a class of ids — precisely the ones
100
+ // carried over from v1 — exempt from major 2's tenant isolation.
101
+ //
102
+ // So: the projection, and only the projection. A bare id here is a finding.
98
103
  const readId = (read.json as { runId?: unknown } | undefined)?.runId;
99
- const namesSameRun =
100
- readId === runId || (typeof readId === 'string' && readId.endsWith(`/${runId}`) && readId.split('/').length === 2);
101
104
  expect(
102
- namesSameRun,
103
- req('openwop.requirement.0172.dual-stack-negotiation.cross-major-read', 'spec/v2/core/versioning.md §5', `the v2 read MUST name the same run: either the v1 id verbatim, or its tenant-bound projection <tenantId>/${'${runId}'} per identity.md §5. Got ${JSON.stringify(readId)} for a run created as ${JSON.stringify(runId)}`),
104
- ).toBe(true);
105
+ readId,
106
+ req('openwop.requirement.0172.dual-stack-negotiation.cross-major-read', 'spec/v2/core/versioning.md §5', `a run minted under major 1 MUST be named by its tenant-bound projection <tenantId>/${'${the v1 id}'} when read under major 2 — the bare id is not merely unconventional, it carries no tenant segment for the mandatory 403 id_tenant_mismatch check to read (identity.md §5), and ids.schema.json#/$defs/runId has no legacy branch. Got ${JSON.stringify(readId)} for a run created as ${JSON.stringify(runId)}`),
107
+ ).toMatch(new RegExp(`^[A-Za-z0-9._~-]{1,128}/${runId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`));
105
108
  expect(major(read), req('openwop.requirement.0172.dual-stack-negotiation.cross-major-read', 'spec/v2/core/versioning.md §1.4', 'the v2 read MUST report the 2.x contract that produced it')).toBe('2');
106
109
  });
107
110