@openwop/openwop-conformance 2.37.0 → 2.38.0

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 (39) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +3 -3
  3. package/dist/cli.js +8 -18
  4. package/dist/lib/certification-bundle-v3.js +46 -18
  5. package/dist/lib/jcs.js +274 -0
  6. package/dist/lib/requirement-ledger.js +44 -3
  7. package/dist/lib/scenario-disposition.js +37 -8
  8. package/dist/spec-artifacts.lock.json +2 -2
  9. package/package.json +2 -2
  10. package/requirements.json +323 -57
  11. package/scenario-majors.json +7 -3
  12. package/schemas/CORPUS-STAMP.json +30 -30
  13. package/src/cli.ts +8 -16
  14. package/src/lib/certification-bundle-v3.ts +42 -17
  15. package/src/lib/front-mux.ts +44 -2
  16. package/src/lib/jcs.ts +229 -0
  17. package/src/lib/llm-cache-key-recipe.ts +10 -20
  18. package/src/lib/requirement-ledger.ts +82 -4
  19. package/src/lib/scenario-disposition.ts +41 -3
  20. package/src/lib/scoped-receiver.ts +223 -0
  21. package/src/lib/triggerBridge.ts +49 -0
  22. package/src/scenarios/auth-subject-link.test.ts +18 -1
  23. package/src/scenarios/jcs-vectors.test.ts +108 -0
  24. package/src/scenarios/semantic-digest-vectors.test.ts +8 -0
  25. package/src/scenarios/trigger-bridge-delivery.test.ts +17 -2
  26. package/src/scenarios/trigger-stream-cdc-sources.test.ts +17 -2
  27. package/src/scenarios/v2-a2a-operation-map.test.ts +28 -0
  28. package/src/scenarios/v2-a2ui-v09-surface.test.ts +18 -4
  29. package/src/scenarios/v2-bound-id-kinds.test.ts +35 -22
  30. package/src/scenarios/v2-content-locale-keys.test.ts +10 -1
  31. package/src/scenarios/v2-idempotency-in-flight.test.ts +81 -26
  32. package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +7 -1
  33. package/src/scenarios/v2-oauth-client-pkce-state-iss.test.ts +7 -1
  34. package/src/scenarios/v2-webhook-delivery-shape.test.ts +31 -34
  35. package/src/scenarios/v2-webhook-durable-delivery.test.ts +63 -47
  36. package/src/scenarios/webhook-signed-delivery.test.ts +55 -42
  37. package/src/setup.ts +24 -4
  38. package/vectors/jcs-v1.json +294 -0
  39. package/vectors/semantic-request-digest-v2.json +52 -0
@@ -0,0 +1,294 @@
1
+ {
2
+ "$comment": [
3
+ "RFC 0212 — cross-language vectors for canonical JSON (RFC 8785 JCS) with the OpenWOP I-JSON refusal set.",
4
+ "Every signed or hashed preimage in the corpus MUST reproduce `canonical` and `sha256` for each `objects` entry, `canonical` for each `numbers` entry, and MUST refuse each `refusals` entry with a refusal (the `refuse` kind is informative).",
5
+ "Generated by a reference implementation that parses JSON TEXT (so duplicates, integer magnitude and lone surrogates are visible before coercion) and cross-checked against RFC 8785 Appendix B and §3.2.2/§3.2.3."
6
+ ],
7
+ "spec": "RFC 8785; RFC 7493 (I-JSON); RFC 0212",
8
+ "hash": "sha256, lowercase hex, over the UTF-8 bytes of `canonical`",
9
+ "numbers": [
10
+ {
11
+ "ieee754": "0000000000000000",
12
+ "canonical": "0"
13
+ },
14
+ {
15
+ "ieee754": "8000000000000000",
16
+ "canonical": "0"
17
+ },
18
+ {
19
+ "ieee754": "0000000000000001",
20
+ "canonical": "5e-324"
21
+ },
22
+ {
23
+ "ieee754": "8000000000000001",
24
+ "canonical": "-5e-324"
25
+ },
26
+ {
27
+ "ieee754": "7fefffffffffffff",
28
+ "canonical": "1.7976931348623157e+308"
29
+ },
30
+ {
31
+ "ieee754": "ffefffffffffffff",
32
+ "canonical": "-1.7976931348623157e+308"
33
+ },
34
+ {
35
+ "ieee754": "4340000000000000",
36
+ "canonical": "9007199254740992"
37
+ },
38
+ {
39
+ "ieee754": "c340000000000000",
40
+ "canonical": "-9007199254740992"
41
+ },
42
+ {
43
+ "ieee754": "4430000000000000",
44
+ "canonical": "295147905179352830000"
45
+ },
46
+ {
47
+ "ieee754": "44b52d02c7e14af5",
48
+ "canonical": "9.999999999999997e+22"
49
+ },
50
+ {
51
+ "ieee754": "44b52d02c7e14af6",
52
+ "canonical": "1e+23"
53
+ },
54
+ {
55
+ "ieee754": "44b52d02c7e14af7",
56
+ "canonical": "1.0000000000000001e+23"
57
+ },
58
+ {
59
+ "ieee754": "444b1ae4d6e2ef4e",
60
+ "canonical": "999999999999999700000"
61
+ },
62
+ {
63
+ "ieee754": "444b1ae4d6e2ef4f",
64
+ "canonical": "999999999999999900000"
65
+ },
66
+ {
67
+ "ieee754": "444b1ae4d6e2ef50",
68
+ "canonical": "1e+21"
69
+ },
70
+ {
71
+ "ieee754": "3eb0c6f7a0b5ed8c",
72
+ "canonical": "9.999999999999997e-7"
73
+ },
74
+ {
75
+ "ieee754": "3eb0c6f7a0b5ed8d",
76
+ "canonical": "0.000001"
77
+ },
78
+ {
79
+ "ieee754": "41b3de4355555553",
80
+ "canonical": "333333333.3333332"
81
+ },
82
+ {
83
+ "ieee754": "41b3de4355555554",
84
+ "canonical": "333333333.33333325"
85
+ },
86
+ {
87
+ "ieee754": "41b3de4355555555",
88
+ "canonical": "333333333.3333333"
89
+ },
90
+ {
91
+ "ieee754": "41b3de4355555556",
92
+ "canonical": "333333333.3333334"
93
+ },
94
+ {
95
+ "ieee754": "41b3de4355555557",
96
+ "canonical": "333333333.33333343"
97
+ },
98
+ {
99
+ "ieee754": "becbf647612f3696",
100
+ "canonical": "-0.0000033333333333333333"
101
+ },
102
+ {
103
+ "ieee754": "43143ff3c1cb0959",
104
+ "canonical": "1424953923781206.2"
105
+ }
106
+ ],
107
+ "numberRefusals": [
108
+ {
109
+ "ieee754": "7fffffffffffffff",
110
+ "refuse": "non-finite"
111
+ },
112
+ {
113
+ "ieee754": "7ff0000000000000",
114
+ "refuse": "non-finite"
115
+ }
116
+ ],
117
+ "objects": [
118
+ {
119
+ "id": "rfc8785-3.2.2",
120
+ "why": "RFC 8785 §3.2.2 worked example: number shortest-round-trip, string escapes, member sort.",
121
+ "input": "{\"numbers\": [333333333.33333329, 1E30, 4.50, 2e-3, 0.000000000000000000000000001], \"string\": \"\\u20ac$\\u000F\\u000aA'\\u0042\\u0022\\u005c\\\\\\\"\\/\", \"literals\": [null, true, false]}",
122
+ "canonical": "{\"literals\":[null,true,false],\"numbers\":[333333333.3333333,1e+30,4.5,0.002,1e-27],\"string\":\"€$\\u000f\\nA'B\\\"\\\\\\\\\\\"/\"}",
123
+ "sha256": "2d5e01a318d0f0879ab568c4be289c8b1f64ef8921a53c6277d5e069978baacb"
124
+ },
125
+ {
126
+ "id": "rfc8785-3.2.3-sort",
127
+ "why": "RFC 8785 §3.2.3: members sorted by UTF-16 code units — CR, \"1\", U+0080, ö, €, 😀 (surrogate pair D83D), דּ (FB33). Locale collation gives a different order.",
128
+ "input": "{\"€\":\"Euro Sign\",\"\\r\":\"Carriage Return\",\"דּ\":\"Hebrew Letter Dalet With Dagesh\",\"1\":\"One\",\"😀\":\"Emoji: Grinning Face\",\"\\u0080\":\"Control\",\"ö\":\"Latin Small Letter O With Diaeresis\"}",
129
+ "canonical": "{\"\\r\":\"Carriage Return\",\"1\":\"One\",\"€\":\"Control\",\"ö\":\"Latin Small Letter O With Diaeresis\",\"€\":\"Euro Sign\",\"😀\":\"Emoji: Grinning Face\",\"דּ\":\"Hebrew Letter Dalet With Dagesh\"}",
130
+ "sha256": "5e321556d22018a9656991a9e94f77ec175fa193e52a2429d312f8419ec8b08c"
131
+ },
132
+ {
133
+ "id": "integer-like-keys",
134
+ "why": "Keys \"10\" and \"9\" sort by code unit (\"1\" < \"9\"). A canonicalizer that rebuilds a JS object and calls JSON.stringify emits {\"9\":…,\"10\":…} — the sabotage this vector exists for.",
135
+ "input": "{\"9\":\"nine\",\"10\":\"ten\",\"a\":0}",
136
+ "canonical": "{\"10\":\"ten\",\"9\":\"nine\",\"a\":0}",
137
+ "sha256": "ac5e0767681af2d226a2a4df567cee9cd3254a7819a7643f8bddbfa690792dad"
138
+ },
139
+ {
140
+ "id": "nested-sort",
141
+ "why": "Sorting applies at every level; arrays keep their order.",
142
+ "input": "{\"b\":[{\"z\":1,\"a\":2},{\"y\":[3,1,2]}],\"a\":{\"d\":null,\"c\":true}}",
143
+ "canonical": "{\"a\":{\"c\":true,\"d\":null},\"b\":[{\"a\":2,\"z\":1},{\"y\":[3,1,2]}]}",
144
+ "sha256": "fc8d1753fb837b89a49b6335715adb82c262e9a6bbfe7f4e7b8993e297951cca"
145
+ },
146
+ {
147
+ "id": "control-escapes",
148
+ "why": "U+0000–U+001F: short forms for \\b \\t \\n \\f \\r, lowercase \\u00xx otherwise; U+007F and U+2028 are emitted raw; \"/\" is not escaped.",
149
+ "input": "{\"s\":\"\\u0000\\u0007\\b\\t\\n\\u000b\\f\\r\\u001f\\u007f
/\"}",
150
+ "canonical": "{\"s\":\"\\u0000\\u0007\\b\\t\\n\\u000b\\f\\r\\u001f
/\"}",
151
+ "sha256": "993e6efcefb9f0bc08a2f896edce693cd6e80aa50ed6337ae0921b06a656c1a3"
152
+ },
153
+ {
154
+ "id": "non-ascii-raw",
155
+ "why": "Non-ASCII is emitted as raw UTF-8, never \\u-escaped (em dash, as in 625 registry pack strings).",
156
+ "input": "{\"title\":\"a — b\",\"emoji\":\"😀\"}",
157
+ "canonical": "{\"emoji\":\"😀\",\"title\":\"a — b\"}",
158
+ "sha256": "d2a26872e24a775a770515e000f1bb85a0949c08b40621292b7e70037006d02d"
159
+ },
160
+ {
161
+ "id": "nfc-composed",
162
+ "why": "U+00E9 (composed). MUST NOT hash equal to the decomposed vector: JCS applies no Unicode normalization.",
163
+ "input": "{\"name\":\"café\"}",
164
+ "canonical": "{\"name\":\"café\"}",
165
+ "sha256": "645fa443126a8954fc6d871912b8fc67bc2ee8feae417efe55546251962ca74d"
166
+ },
167
+ {
168
+ "id": "nfd-decomposed",
169
+ "why": "U+0065 U+0301 (decomposed). Pair with nfc-composed.",
170
+ "input": "{\"name\":\"café\"}",
171
+ "canonical": "{\"name\":\"café\"}",
172
+ "sha256": "4b7186ff40a64bfae3cb4bd75ac13b0de5ee693190f20812aaff208a77560ca7"
173
+ },
174
+ {
175
+ "id": "numbers-in-document",
176
+ "why": "Numbers inside a document: -0 → 0, 1.0 → 1, 1e21 → 1e+21, 1e-7 → 1e-7, 0.1+0.2 shortest form, 2^53−1 accepted.",
177
+ "input": "{\"n\":[-0,1.0,1e21,1e-7,0.30000000000000004,9007199254740991,-9007199254740991]}",
178
+ "canonical": "{\"n\":[0,1,1e+21,1e-7,0.30000000000000004,9007199254740991,-9007199254740991]}",
179
+ "sha256": "430e3fefe48227fd5ed7df3ba8b5a6da008c2077858a44bd265d4c7812c498c1"
180
+ },
181
+ {
182
+ "id": "empty-containers",
183
+ "why": "Empty object and array.",
184
+ "input": "{\"a\":{},\"b\":[]}",
185
+ "canonical": "{\"a\":{},\"b\":[]}",
186
+ "sha256": "aeeba1e56a144077f89e26c930dad7cf933e9383cfb8e33ddff618233b29be76"
187
+ }
188
+ ],
189
+ "refusals": [
190
+ {
191
+ "id": "duplicate-name",
192
+ "why": "I-JSON §2.3: duplicate member names.",
193
+ "input": "{\"a\":1,\"a\":2}",
194
+ "refuse": "duplicate-name"
195
+ },
196
+ {
197
+ "id": "lone-high-surrogate",
198
+ "why": "I-JSON §2.1: a lone surrogate is not a Unicode scalar value.",
199
+ "input": "{\"s\":\"\\ud800\"}",
200
+ "refuse": "lone-surrogate"
201
+ },
202
+ {
203
+ "id": "lone-low-surrogate",
204
+ "why": "I-JSON §2.1.",
205
+ "input": "{\"s\":\"x\\udc00\"}",
206
+ "refuse": "lone-surrogate"
207
+ },
208
+ {
209
+ "id": "integer-above-range",
210
+ "why": "Integer literal 2^53+1 exceeds ±(2^53−1) (I-JSON §2.2); a double cannot hold it exactly and a Python verifier would keep it exact — the two canonical forms differ.",
211
+ "input": "{\"n\":9007199254740993}",
212
+ "refuse": "integer-out-of-range"
213
+ },
214
+ {
215
+ "id": "integer-below-range",
216
+ "why": "Integer literal −2^53.",
217
+ "input": "{\"n\":-9007199254740992}",
218
+ "refuse": "integer-out-of-range"
219
+ },
220
+ {
221
+ "id": "nan-token",
222
+ "why": "NaN is not JSON. A JS canonicalizer given an in-memory NaN MUST refuse, not emit null.",
223
+ "input": "{\"n\":NaN}",
224
+ "refuse": "not-json"
225
+ },
226
+ {
227
+ "id": "infinity-overflow",
228
+ "why": "1e400 parses to Infinity: non-finite.",
229
+ "input": "{\"n\":1e400}",
230
+ "refuse": "non-finite"
231
+ }
232
+ ],
233
+ "ordering": {
234
+ "why": "witnessSha256 rows[] and RFC 0150 tools[] sort by UTF-16 code units of the key. Locale collation disagrees in both listed locales; a verifier using either computes a different digest.",
235
+ "ids": [
236
+ "d",
237
+ "h",
238
+ "ch",
239
+ "i",
240
+ "chain-pin-exact",
241
+ "h2",
242
+ "get_weather",
243
+ "getWeather",
244
+ "A",
245
+ "a",
246
+ "a-b",
247
+ "ab"
248
+ ],
249
+ "codeUnit": [
250
+ "A",
251
+ "a",
252
+ "a-b",
253
+ "ab",
254
+ "ch",
255
+ "chain-pin-exact",
256
+ "d",
257
+ "getWeather",
258
+ "get_weather",
259
+ "h",
260
+ "h2",
261
+ "i"
262
+ ],
263
+ "localeCs": [
264
+ "a",
265
+ "A",
266
+ "a-b",
267
+ "ab",
268
+ "d",
269
+ "get_weather",
270
+ "getWeather",
271
+ "h",
272
+ "h2",
273
+ "ch",
274
+ "chain-pin-exact",
275
+ "i"
276
+ ],
277
+ "localeEn": [
278
+ "a",
279
+ "A",
280
+ "a-b",
281
+ "ab",
282
+ "ch",
283
+ "chain-pin-exact",
284
+ "d",
285
+ "get_weather",
286
+ "getWeather",
287
+ "h",
288
+ "h2",
289
+ "i"
290
+ ],
291
+ "differsFromCs": true,
292
+ "differsFromEn": true
293
+ }
294
+ }
@@ -141,6 +141,58 @@
141
141
  "canonical": "{\"model\":\"claude-x\",\"provider\":\"anthropic\",\"recipe\":\"openwop-semantic-request-v2\",\"request\":{\"messages\":[{\"content\":\"hello\",\"role\":\"user\"}],\"tools\":[{\"name\":\"alpha\",\"parameters\":{}},{\"name\":\"zeta\",\"parameters\":{}}]}}",
142
142
  "digest": "afb590dd7bf6c78915852e15318fd4c9d6d6e0d473288283f413e5e425ba0cd6"
143
143
  },
144
+ {
145
+ "id": "tools-code-unit-order",
146
+ "why": "RFC 0212 §D: tools sort by name in UTF-16 code units. `getWeather` (W = 0x57) precedes `get_weather` (_ = 0x5F); English collation ignores `_` and a Czech/English localeCompare orders them the other way, which is why `alpha`/`zeta` could not catch it.",
147
+ "input": {
148
+ "provider": "anthropic",
149
+ "model": "claude-x",
150
+ "messages": [
151
+ {
152
+ "role": "user",
153
+ "content": "hello"
154
+ }
155
+ ],
156
+ "tools": [
157
+ {
158
+ "name": "get_weather",
159
+ "parameters": {}
160
+ },
161
+ {
162
+ "name": "getWeather",
163
+ "parameters": {}
164
+ }
165
+ ]
166
+ },
167
+ "canonical": "{\"model\":\"claude-x\",\"provider\":\"anthropic\",\"recipe\":\"openwop-semantic-request-v2\",\"request\":{\"messages\":[{\"content\":\"hello\",\"role\":\"user\"}],\"tools\":[{\"name\":\"getWeather\",\"parameters\":{}},{\"name\":\"get_weather\",\"parameters\":{}}]}}",
168
+ "digest": "8ddc711c24f17c75efa8fd61e4060573461973ed0ae3fc79c056533d6bb1d0d0"
169
+ },
170
+ {
171
+ "id": "tools-code-unit-order-reversed",
172
+ "why": "Same two tools, opposite input order. MUST equal the previous vector.",
173
+ "input": {
174
+ "provider": "anthropic",
175
+ "model": "claude-x",
176
+ "messages": [
177
+ {
178
+ "role": "user",
179
+ "content": "hello"
180
+ }
181
+ ],
182
+ "tools": [
183
+ {
184
+ "name": "getWeather",
185
+ "parameters": {}
186
+ },
187
+ {
188
+ "name": "get_weather",
189
+ "parameters": {}
190
+ }
191
+ ]
192
+ },
193
+ "canonical": "{\"model\":\"claude-x\",\"provider\":\"anthropic\",\"recipe\":\"openwop-semantic-request-v2\",\"request\":{\"messages\":[{\"content\":\"hello\",\"role\":\"user\"}],\"tools\":[{\"name\":\"getWeather\",\"parameters\":{}},{\"name\":\"get_weather\",\"parameters\":{}}]}}",
194
+ "digest": "8ddc711c24f17c75efa8fd61e4060573461973ed0ae3fc79c056533d6bb1d0d0"
195
+ },
144
196
  {
145
197
  "id": "message-order-is-semantic",
146
198
  "why": "Message order IS semantic and MUST NOT be sorted — this must differ from a reordered twin.",