@openwop/openwop-conformance 2.0.0-rc.12 → 2.0.0-rc.13

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.12",
4
- "stampSha256": "cda7124d9d13d004d4ff83279fefe6e4a9852b2c9ef566ae438f0eb1e70ea440"
3
+ "version": "2.0.0-rc.13",
4
+ "stampSha256": "70588d48596c9141975f89d3116b8fdc93d61d5faf5a93a7be6b9100d4e7311c"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.0-rc.12",
3
+ "version": "2.0.0-rc.13",
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.12"
59
+ "@openwop/spec-artifacts": "2.0.0-rc.13"
60
60
  }
61
61
  }
@@ -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.12",
4
+ "version": "2.0.0-rc.13",
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": "4e443d61b3466da934f5afea3253f5dff0f8131f7201eb9f6102aebcf9d9b238",
13
- "api/v2/asyncapi.yaml": "39862fff36dcc6bafe779c56b4b1b7e5147bf5cc213a8ebee99320cefe41fe81",
14
- "api/v2/openapi.yaml": "8ac2bf487ab382ce9063ede04daa0bdcbf14da28af6aceb5fa9daa10024795da",
12
+ "api/seams-v2.yaml": "fd9b0ac5fad1dbcde81c072480ab1b2054dfac801620f4b0a56cce293dd55ecf",
13
+ "api/v2/asyncapi.yaml": "17c9e96919f050e77a290025ae77f69420a835790e8a434fadea242445f6bdca",
14
+ "api/v2/openapi.yaml": "d187a8e648c4db4981dd8b73abbc7b10346febaa30124c7413de7d4f78f56b04",
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": "2fcd8083ac9a1ebf8ef0b83aebbcb9c19e4d217d54e46fa4db2c020494964da1",
201
+ "spec/v1/core-standard-manifest.json": "10b5c192827884300f77b1bd481fdb70e8fccf0b636c2e37d0a3834497ce508a",
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": "4f2df9ae2dc2975624da0cd2be429b4c6d4575de1c97bb860144f458063cc8ee"
231
+ "spec/v2/release.json": "c5a7d6f086e6d9bce497e2c21fe5a1f11d96533f30b5596f3332ad1a77898a9b"
232
232
  },
233
- "corpusCommit": "88ee26171cb6c6e2f4d74576e09a559099b5f284"
233
+ "corpusCommit": "ef6f06aafc7265609229411a104d00546fe25074"
234
234
  }
@@ -75,6 +75,17 @@ export function setup(): void {
75
75
  // Suite 2.0.0: in the published layout the contract is the spec-artifacts peer (RFC 0168 §D.2).
76
76
  const stamp = LAYOUT === 'published' ? verifyPeerContract(PKG_ROOT_PATH) : verifyCorpusStamp(PKG_ROOT_PATH, LAYOUT);
77
77
  process.stderr.write(`${describeVerdict(stamp)}\n`);
78
+ // A version skew and a digest mismatch both have to refuse, but they are
79
+ // different faults with different fixes, and reporting them in the same words
80
+ // sends the reader to debug a corrupt install when nothing is corrupt.
81
+ if (stamp.kind === 'peer-version') {
82
+ throw new Error(
83
+ `openwop-conformance: refusing to run — this suite was packed against @openwop/spec-artifacts@${stamp.lockVersion}, ` +
84
+ `but @openwop/spec-artifacts@${stamp.peerVersion} is installed. They are declared EXACT peers. ` +
85
+ `Install both at the same explicit version; do NOT install at a dist-tag such as \`next\`, which moves per package ` +
86
+ `and can name a pair that was never published together.`,
87
+ );
88
+ }
78
89
  if (stamp.kind === 'mismatch') {
79
90
  throw new Error('openwop-conformance: refusing to run — schemas/CORPUS-STAMP.json digests do not match the vendored api/ + schemas/ files. Reinstall the package; do not hand-patch vendored contract files.');
80
91
  }
@@ -39,7 +39,17 @@ export interface CorpusStamp {
39
39
  export type StampVerdict =
40
40
  | { readonly kind: 'verified'; readonly files: number }
41
41
  | { readonly kind: 'not-applicable'; readonly reason: string }
42
- | { readonly kind: 'mismatch'; readonly missing: readonly string[]; readonly altered: readonly string[]; readonly extra: readonly string[] };
42
+ | { readonly kind: 'mismatch'; readonly missing: readonly string[]; readonly altered: readonly string[]; readonly extra: readonly string[] }
43
+ /**
44
+ * The peer is INSTALLED and INTACT but is a different version than the suite
45
+ * was packed against. Its own kind because the remedy is completely different
46
+ * from a digest mismatch — nothing is corrupt, two versions are simply out of
47
+ * step — and because the generic message sends readers to debug a broken
48
+ * install. Reported by a tier-2 host that hit it through the `next` dist-tag:
49
+ * the tag moves per package, so `@next` can name an exact-peer PAIR that was
50
+ * never published together.
51
+ */
52
+ | { readonly kind: 'peer-version'; readonly peerVersion: string; readonly lockVersion: string };
43
53
 
44
54
  export const STAMP_RELATIVE_PATH = join('schemas', 'CORPUS-STAMP.json');
45
55
 
@@ -94,7 +104,11 @@ export function verifyPeerContract(pkgRoot: string): StampVerdict {
94
104
  if (!existsSync(stampPath)) return { kind: 'mismatch', missing: ['@openwop/spec-artifacts/CORPUS-STAMP.json'], altered: [], extra: [] };
95
105
  const stamp = JSON.parse(readFileSync(stampPath, 'utf8')) as { package: string; version: string; files: Record<string, string> };
96
106
  const digest = createHash('sha256').update(JSON.stringify({ package: stamp.package, version: stamp.version, files: stamp.files })).digest('hex');
97
- if (stamp.version !== lock.version || digest !== lock.stampSha256) return { kind: 'mismatch', missing: [], altered: [`@openwop/spec-artifacts ${stamp.version} (digest ${digest.slice(0, 12)}) ≠ the suite's lock ${lock.version} (${lock.stampSha256.slice(0, 12)})`], extra: [] };
107
+ // A plain version difference is NOT corruption; report it as itself so the
108
+ // message names the two versions and the fix, instead of sending the reader
109
+ // to hunt a damaged install.
110
+ if (stamp.version !== lock.version) return { kind: 'peer-version', peerVersion: stamp.version, lockVersion: lock.version };
111
+ if (digest !== lock.stampSha256) return { kind: 'mismatch', missing: [], altered: [`@openwop/spec-artifacts ${stamp.version} stamp digest ${digest.slice(0, 12)} ≠ the suite's lock ${lock.stampSha256.slice(0, 12)} — same version, different contents`], extra: [] };
98
112
  const missing: string[] = []; const altered: string[] = [];
99
113
  for (const [rel, d] of Object.entries(stamp.files)) { const p = join(peerRoot, ...rel.split('/')); if (!existsSync(p)) missing.push(rel); else if (sha256File(p) !== d) altered.push(rel); }
100
114
  if (missing.length || altered.length) return { kind: 'mismatch', missing, altered, extra: [] };
@@ -143,6 +157,14 @@ export function describeVerdict(v: StampVerdict): string {
143
157
  return `[openwop-conformance] corpus stamp VERIFIED — ${v.files} vendored api/ + schemas/ files match their SHA-256 digests`;
144
158
  case 'not-applicable':
145
159
  return `[openwop-conformance] corpus stamp not checked — ${v.reason}`;
160
+ case 'peer-version':
161
+ return (
162
+ `[openwop-conformance] peer version MISMATCH — this suite was packed against ` +
163
+ `@openwop/spec-artifacts@${v.lockVersion} but @openwop/spec-artifacts@${v.peerVersion} is installed. ` +
164
+ `Nothing is corrupt: the two are declared EXACT peers and are simply out of step. ` +
165
+ `Install both at the same explicit version — never at a dist-tag such as \`next\`, which moves per package ` +
166
+ `and can therefore name a pair that was never published together.`
167
+ );
146
168
  case 'mismatch':
147
169
  return (
148
170
  `[openwop-conformance] corpus stamp MISMATCH — the vendored contract is not the one this suite shipped ` +