@openwop/openwop-conformance 2.42.8 → 2.43.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.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$comment": "GENERATED by conformance/scripts/generate-scenario-majors.mjs (RFC 0168 §D.3). Do not edit; add a file to BOTH_MAJORS in the generator to target both majors.",
3
3
  "counts": {
4
- "files": 567,
5
- "v1": 451,
6
- "v2": 128
4
+ "files": 570,
5
+ "v1": 452,
6
+ "v2": 133
7
7
  },
8
8
  "majors": {
9
9
  "a2a-1-0-agent-card.test.ts": [
@@ -249,15 +249,21 @@
249
249
  "artifact-type-store-without-render.test.ts": [
250
250
  1
251
251
  ],
252
+ "audit-anomaly-shape.test.ts": [
253
+ 1,
254
+ 2
255
+ ],
252
256
  "audit-checkpoint-signature.test.ts": [
253
- 1
257
+ 1,
258
+ 2
254
259
  ],
255
260
  "audit-checkpoint-vectors.test.ts": [
256
261
  1,
257
262
  2
258
263
  ],
259
264
  "audit-log-integrity.test.ts": [
260
- 1
265
+ 1,
266
+ 2
261
267
  ],
262
268
  "auth-api-key-rotation.test.ts": [
263
269
  1
@@ -1281,6 +1287,9 @@
1281
1287
  "v2-advertised-path-space-served.test.ts": [
1282
1288
  2
1283
1289
  ],
1290
+ "v2-approval-reject-disposition.test.ts": [
1291
+ 2
1292
+ ],
1284
1293
  "v2-approver-enforced.test.ts": [
1285
1294
  2
1286
1295
  ],
@@ -1503,6 +1512,9 @@
1503
1512
  "v2-refresh-sla.test.ts": [
1504
1513
  2
1505
1514
  ],
1515
+ "v2-registry-lifecycle.test.ts": [
1516
+ 2
1517
+ ],
1506
1518
  "v2-relaxation-recorded.test.ts": [
1507
1519
  2
1508
1520
  ],
@@ -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.42.8",
5
- "corpusTag": "v2.42.8",
4
+ "version": "2.43.0",
5
+ "corpusTag": "v2.43.0",
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": "69464bc0e1e71ef3b543a73d4fa4f67202343d2603c80af8033f6c3619ef1b30",
11
11
  "api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
12
- "api/seams-v2.yaml": "deda53b9f8917a1dc4b283e50cb47985c0fd06525c96fdf853c2fdb1a2de5cb8",
13
- "api/v2/asyncapi.yaml": "a35292b35d003361a9a0a7997557e022641cd869a6aefcd31ab266d0c3fea215",
14
- "api/v2/openapi.yaml": "8381ff1d3cca7c0610a5f5a885763a625630c8b36bb5c5f6cd1d3f3cceb176a7",
12
+ "api/seams-v2.yaml": "c6d9d70e74a4c883a016a69da438fb6c87f56822334a1d45bd682c6d68bdac32",
13
+ "api/v2/asyncapi.yaml": "0b72bbd3f0f25172e3080a027a801d68d4a4130188addf2879fe92759d352de6",
14
+ "api/v2/openapi.yaml": "fdbc6bcf064de81e2c8bf3d7a896ccbc39d8b12f71f9b8c4727f825f1ae31af0",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
17
17
  "schemas/a2a-task-state.schema.json": "75d5049dea8bd873ff0e7546f1c60c8d36c219bec7084264360be54a8be30ae1",
@@ -29,7 +29,7 @@
29
29
  "schemas/annotation-create.schema.json": "567e8327777968e0ddab8e1547b4acd7beda734cf9d1fc6cde17037d8d9540d4",
30
30
  "schemas/annotation.schema.json": "b26d22f9a97e1ae7c195e8799964aca804e78452a079ca3a0d61ea013907ce91",
31
31
  "schemas/artifact-type-pack-manifest.schema.json": "60342fcb15eb7f3ab46271f0641409a30d3a4a8f318b1020c53070886b191252",
32
- "schemas/audit-verify-result.schema.json": "de9cc3b9d7b97995b906dc96438244ea6b93c26b5faaf4926320676b48ba4fcc",
32
+ "schemas/audit-verify-result.schema.json": "0d3a3088ac1c32f9df66d346c33d7adbd8037940dba040e14ea847565a1a14bd",
33
33
  "schemas/budget-policy.schema.json": "3d4fe30ae129fe136ab9ece395f2a2a42a76360786b1b9a1d5f1cbc753eb5b39",
34
34
  "schemas/capabilities.schema.json": "56b367074bce0f02ff87e0b84ccdf91856793d3d285e28f261656edba6352cc0",
35
35
  "schemas/certification-bundle-v2.schema.json": "2f85530dd04824a15810c94e96869362dee1e78396eca21fdd18e5501416bb7d",
@@ -114,9 +114,9 @@
114
114
  "schemas/v2/annotation.schema.json": "eb4813cdaa8e325412cfcaeeee5c8a28f3751c946dec64e546c7ba0ad3aad8d4",
115
115
  "schemas/v2/artifact-type-pack-manifest.schema.json": "c8820351a2ab93855bd654ad3d8a9788f97975d09b3a7a0418e374ed6114595d",
116
116
  "schemas/v2/artifact.schema.json": "85b9dc284d39b99d2a66fa8cbf47f2dd3d8526d3bd6cc411ad315b372de38975",
117
- "schemas/v2/audit-verify-result.schema.json": "2a4bfc42976717f78c10468fdba756ca6b19e49762699e6dffd418ffff08e55d",
117
+ "schemas/v2/audit-verify-result.schema.json": "14af8e9283510f0a40e48a2059c929ee44e0fc9fa3cc66a95bfbe90b17c48297",
118
118
  "schemas/v2/budget-policy.schema.json": "c7449daeb6e1d95e7a047b8c2814d3d54748697c27046972834874867d9b5f4c",
119
- "schemas/v2/capabilities.schema.json": "959b7a1b8e40aeafb8b9702bd0e4b220c0beb02a6afa3ca64fe9b04b95ae3df5",
119
+ "schemas/v2/capabilities.schema.json": "ae6f60641d6ed680351b2710df945257c401f1ed83534f7e44fa2e651dc401ab",
120
120
  "schemas/v2/certification-bundle.schema.json": "82ce31a1ed6c7e21b0ba88ff62a7b8b768fc3b176b1d06fce023203830b94725",
121
121
  "schemas/v2/channel-presence-payload.schema.json": "4eeb224910e6f7eee3ab5e7c3899559c25c83a26d0022e0ad195c4672611977a",
122
122
  "schemas/v2/channel-written-payload.schema.json": "ccecff3c71a3275ad8db035ac0e04db25e6f8d23cf091ddbcd5a60d1be1cbb6b",
@@ -142,7 +142,7 @@
142
142
  "schemas/v2/envelopes/schema.request.schema.json": "be2c5f7aa881cdd252ccff47ac02193659e1393633a1541f4297383205d384a2",
143
143
  "schemas/v2/envelopes/schema.response.schema.json": "d049a081267c06c28879c331b147f3ed821b14ccfd93005c67aff64db0a8c68e",
144
144
  "schemas/v2/envelopes/ui.a2ui-surface.schema.json": "e92a2548ba65454c9e0a34f72ea6768d18f59e61fa5da7668d0b2d5baddaddc8",
145
- "schemas/v2/error-envelope.schema.json": "467d7109c54bff71a6cfd457d3bd65a23ca34b8e5577e742d080692771a78ebf",
145
+ "schemas/v2/error-envelope.schema.json": "d1a6862930e7c3fbc8ec334ef17953ac7b716525c6c82769edf89d0809d0c94b",
146
146
  "schemas/v2/eval-summary.schema.json": "2f384daf05b8f3b4f604688cae504d6d9971ba41b8c771e55fe9a17e09e86b7a",
147
147
  "schemas/v2/export-bundle.schema.json": "bd28905a7729437ab7f2ad8bb33e13a371b2bf5605a7eb2962a0d246de312d69",
148
148
  "schemas/v2/form-content-pack-manifest.schema.json": "a1942a124e250a6e9fbdb6b811c5a125e78fbcbcaa46dfc71d0636f24710a339",
@@ -167,7 +167,7 @@
167
167
  "schemas/v2/prompt-ref.schema.json": "11538fa36a7a652c93100cac4f1857eb4130137b546e3d94890618636d44b729",
168
168
  "schemas/v2/prompt-template.schema.json": "494fc83028cb3af5dbb8a943d0e83b2348f7775e9fa02369162bcb58a6f81559",
169
169
  "schemas/v2/proposal.schema.json": "a5c582ce1e854e5fe10412ebed00e537961ee827bbaca506ca374b200a685992",
170
- "schemas/v2/registry-version-manifest.schema.json": "f05c620db2ee8f9c60fbe33f2e385cc1bc98bc92c588de8a7170c442b1bbe068",
170
+ "schemas/v2/registry-version-manifest.schema.json": "940cfd82511690cd6f2539e5676b185e7812628d0707c283fd7ffb33b6e54afd",
171
171
  "schemas/v2/residency.schema.json": "3fd23c9732beb140504e81560fc426eb6764d547e56da5fb92c5a5c7bf04db3a",
172
172
  "schemas/v2/run-ancestry-response.schema.json": "334c17f2062dea62726ca1d07b8be3f169cdc422af843c1def5fb317039814c9",
173
173
  "schemas/v2/run-diff-response.schema.json": "8bdb2045c274580038bd74781f7d062f5049839797c164a89de4ed89edc53a74",
@@ -183,7 +183,7 @@
183
183
  "schemas/v2/self-hosted-runner-result-frame.schema.json": "8e739a721f350226f3ffb4af752b4fe0a72016042a7b6f42e16c0487c3c58983",
184
184
  "schemas/v2/subject-link.schema.json": "1fc941d6c14af886534009f2ffa6611e2035eb07e30b1df918c50d6bafff026c",
185
185
  "schemas/v2/subject.schema.json": "094e981fb20052a911393e219ea5f2065d8b8417b65080a70c5ea99fd960a8fe",
186
- "schemas/v2/suspend-request.schema.json": "02b45582997d0529aa85f2b5aeaf300e3e44ff0b185c449e14daf6f47b1015d5",
186
+ "schemas/v2/suspend-request.schema.json": "29c9cfa6978342f0175e250607e6eddb5e4058ea0c4adacc1965e1f3bb4dc9ee",
187
187
  "schemas/v2/tool-descriptor.schema.json": "8c98fb5e93bc649dff859d3d1dde8075db929efd6c49c496252d0a88cccc73e1",
188
188
  "schemas/v2/trigger-event.schema.json": "710ecca8b3ecdad3a532a96768177f062192b24a589a4f798c7eb24bab64b30a",
189
189
  "schemas/v2/trigger-subscription-registration.schema.json": "04bc314a07c7e8b565577cb8df5821d968ce2af915900dfdccd4a24e928d20db",
@@ -204,24 +204,24 @@
204
204
  "schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
205
205
  "spec/v1/alias-detectors.json": "29f21e0fb2c7a232a92a5c19b4cba3a86bc3b5e16f06780452f0421c66c6ec38",
206
206
  "spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
207
- "spec/v1/core-standard-manifest.json": "1359a69ad091b8bd3fb8fb7b641b32496d0d7a70d40cb0d1b93c6f171566276e",
207
+ "spec/v1/core-standard-manifest.json": "4c43eec4ac5a43b026949f9d9c65d6b92f7b79706a185c4a147e232b1be0c945",
208
208
  "spec/v1/deprecations.json": "46df807fb4adf0aae24671c20f69975cf3496e3bc3a521cb7e6ea556bdce563c",
209
209
  "spec/v1/deprecations.schema.json": "3e393c405d2a41b467d8c5e3c468549078df1ce6a6d2588fc488097b95d9b55b",
210
210
  "spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
211
211
  "spec/v1/event-codemap.schema.json": "d05933b2e88103aff51a2f774df97b9bda065e0fc88dbd9b114cc47a32189174",
212
212
  "spec/v1/extensions.json": "79a60754aa16cbdbdb604f8e5c00038af535a1690a4d07bd5ff7c38f0256a7bc",
213
- "spec/v1/gaps.json": "2b032d91d614a758db347be4f5e617b8ac3c4622b6f95ffcfa928276c0fb7377",
213
+ "spec/v1/gaps.json": "2d4e4772cd647b471f989bdb6416ca902b11e10d17dc7f84825bb9f2eef1314c",
214
214
  "spec/v1/gaps.schema.json": "8fd83259f556553c9df0f53e7a82ca8c2a4771d471197f69b4e2ae0ceeacfd66",
215
215
  "spec/v1/migrations.json": "2efcd9064b2bc65a84a3b3d281aa86a91efd002690c1f4f14e8335c4a18194d1",
216
216
  "spec/v1/migrations.schema.json": "886779aa6c22e646db097f5df210adb018a4dd14a7b815465a18c8a7056c8f72",
217
217
  "spec/v1/operation-path-manifest.json": "fada0342815fb129c1ae61f1829bd6e34417717408ce86fcc54280f373c19e74",
218
218
  "spec/v1/spec-gaps.json": "ea9612af55bea9dae3e82223d4f714243f8f590b0193f1188257b13491a38afc",
219
219
  "spec/v2/README.md": "4fa067d377580495e60baf08a4eafc3214b8ca48d8fb270bf91fc5066fad7186",
220
- "spec/v2/core/capabilities.md": "225269a257421ebe677070dd13b05f6f297a2a343916e440b7428b839e2da9a4",
220
+ "spec/v2/core/capabilities.md": "3d1a1975cb688244ca18cd194f56f3a995cc81a9155277dbaeeaa51eabb3a0c7",
221
221
  "spec/v2/core/conformance.md": "e7bd7d54062f28801071165a1b92edbeee3774bb3710f31eed75817139b66d95",
222
222
  "spec/v2/core/connection-packs.md": "3168d2c8f1a59417a7256a678f4203570be434f64dead6b11fdec86b352686df",
223
223
  "spec/v2/core/conversation.md": "6db43d8160bc45d3944aa1151816a6f0fd1669d59d7f822267a2d6cc9db22990",
224
- "spec/v2/core/errors.md": "d14649ee60f8260ec163464163409ad7f50cb86fee7b846e0190f66070b3774b",
224
+ "spec/v2/core/errors.md": "7931c9411e50b5ebfbc20d15aaf0e7b1a5b3e0ddc558b931e432da49ce09152c",
225
225
  "spec/v2/core/events.md": "234338deb97be648731e8ab2126a90b7b8ad0a7070d98ffc85ee4689ff059791",
226
226
  "spec/v2/core/form-content-packs.md": "41d40afe0a3760bcd792a4c406e16f28b0ab0aa7b0925323110d3fa2730d5400",
227
227
  "spec/v2/core/headers.md": "5cb1624fa63acc81992b6a6d842ec392cf7271aaf2f65d1f83c8c4fa286e6730",
@@ -230,49 +230,50 @@
230
230
  "spec/v2/core/idempotency.md": "21830b7d23dd03e9e8ba4b0de253dd001fc960f166310d6b6b60b1c33cf60b30",
231
231
  "spec/v2/core/identity.md": "acb7f739729c69a1f40dcaa5b1d873ba9f32993c17bfd297f5fa56351cf47c69",
232
232
  "spec/v2/core/interop.md": "3cfa2af70ae6ba1f4b4268447d46d1d2f5fb65f7917f15bad159d9779d25b1a6",
233
- "spec/v2/core/interrupt.md": "b31b3f3be7888043ef38c82367a8d743a775c2b6bd499f7da44355ff00452435",
233
+ "spec/v2/core/interrupt.md": "5e6fe9767228638095d5a2210307e1febfcefda808f4a400f2c7c528b929c445",
234
234
  "spec/v2/core/node-pack-runtimes.md": "d52966319c53aaa03575025915b73b470a42832c039c41d73aff6931758630cb",
235
235
  "spec/v2/core/oauth.md": "57f167d899993b6959c243e4102819f4014b365299b9b2b253decd2781e6b8b7",
236
236
  "spec/v2/core/overview.md": "3dbc8c0cf7474b31816b1a12412c1edf5597066c38edcdbca4dd2e465880f65b",
237
- "spec/v2/core/packs.md": "26b0fc3b81f98adbdf70796482db89fa81a6ce3da6f830cd5e8b3d71541c497f",
237
+ "spec/v2/core/packs.md": "e46bf8cd34ac9566fe1e5601f67e7a17fce9639b8676e0f5278a10c6ca70ab29",
238
238
  "spec/v2/core/persistence.md": "bba672ed3bf6d83af6e4e65c0f4f480fc21fe12207811e321306af2108d9010d",
239
239
  "spec/v2/core/portability.md": "a35fbe66b8b5ccf63cf0216157d4b61d4c47f6dc8e757c830569ddf244e21e8a",
240
240
  "spec/v2/core/replay.md": "a5be4e05242f25f8b5a8a4fb31bd359d5abb4bf34fa8e536403a8ee5779ab876",
241
241
  "spec/v2/core/runs.md": "72a94c27d884036d84290e9b108702e98b0c6b2fb598213bbda44fba9c9f860d",
242
- "spec/v2/core/security-defaults.md": "179fdd2efcc1454453243f8ab6473335dfd4389e70cbbc2669f5b83714092973",
242
+ "spec/v2/core/security-defaults.md": "e77cf97290ffb0c201706ea10cc0883d717d034353ae0632067838ef227d3749",
243
243
  "spec/v2/core/tool-catalog.md": "6b54b8ce221107de19c718f374a720123c6a5f55db4054e6625f73d06e0a442f",
244
244
  "spec/v2/core/versioning.md": "2bfe16a72a909c46b4585fab39dc9e94c97506ed95df6b1b527f97b4cd3684ef",
245
245
  "spec/v2/core/webhooks.md": "78fe97ab5bdee20218183efe32abf5ba1996705d757cb37c8d6a4d808c44199f",
246
246
  "spec/v2/core/workflow-chain-packs.md": "35a957f1dd22016febd76bf2c4dfb79cda58b95d8efd8893b5e5babda9f79cf3",
247
- "spec/v2/corrections.json": "b19f8a80fce7e6473012a20a216e358dd38ae7411e6a348f8031e325ed1a0a01",
247
+ "spec/v2/corrections.json": "59f647f4d22477f6c2b06dcf913b682dde5d51dd5e607a5d0cf648ab60864d6e",
248
248
  "spec/v2/corrections.schema.json": "46bbffb954d13bd9995aebc912ceeb2544f7064331abf25fd6ab85c81a5cec94",
249
- "spec/v2/declaration.json": "1253a5590ec2d9ba511d15e8a9d9da5e6926c4daa981a26b73b29bc915477013",
249
+ "spec/v2/declaration.json": "48cf54bc5ab04c00df3079b3fee701802de35a5a211dbfaf62c6a16bd4d3cd06",
250
250
  "spec/v2/declaration.schema.json": "ef951633e4070899f64828f5cf1b5f4870270a0360f81dbb49b5b4d6cd407550",
251
- "spec/v2/errors.json": "b89664e9e0e7603253712263ce0843ce607e276c67d0acaf4a680c39bb2bd682",
251
+ "spec/v2/errors.json": "dc1a846abe3e888acb0ce4a33cf9d1fb98e41fcc8b49f42b3682fd65deca2eb2",
252
252
  "spec/v2/errors.schema.json": "47404ad53e6147cf9017b813483712466573e419fb33e6c4b6c12d3e7deba1bc",
253
253
  "spec/v2/event-codemap.json": "37869a03cdfd8758b57e6f350641a6ebbd383231cebda51f5473ad85f94ab74c",
254
254
  "spec/v2/event-codemap.schema.json": "b173f2a9bcc0bf9b62a474ce3b91e1431d597e64fd1560fc58662cd8606eaf9c",
255
255
  "spec/v2/ext/README.md": "e2731ebb5156ece1840ed3b96e7a347f6345e73071ff4e54df0f21c1585c5027",
256
256
  "spec/v2/ext/a2uiSurface/README.md": "5518c7f355262eb7cc584422f4ff8e548f066b211878f969274a3a578127622d",
257
- "spec/v2/ext/brand/README.md": "52b31ddb8e86820afc8fb1afd29fddf7940dc00454f60ba0dbada718a9b63157",
258
- "spec/v2/ext/canvas/README.md": "0e91b68566d2be90319feedfaebe2cd2db0bd8f72fb59c958fa723c05e38023f",
259
- "spec/v2/ext/chat/README.md": "a934ad42134a58968a1ccc03d7fe317fc8b8b14bf847d97bfe7773086c3d22b7",
260
- "spec/v2/ext/coordination/README.md": "9c3513aab388afbe3ab95db60ef15e9c9d4a7a0cd7d3e92b567136235a7183d2",
261
- "spec/v2/ext/dataIntegration/README.md": "88be31dcabacdd4e012b8c0795d9a3d82bc2cc62b67de4c05ccdd5d9afed9166",
262
- "spec/v2/ext/entities/README.md": "78096383811fefa264f3ed0d97c8174a61870fda5a78cc97a5c1bb761ac8cfd7",
257
+ "spec/v2/ext/brand/README.md": "4f9db1715219070fc57e06cc9b066f13aa130dd50f4869722d908e6e15720787",
258
+ "spec/v2/ext/canvas/README.md": "9a08469f1cbde2b0d6594ce76f8cce94b9fb5415979ef5e2ecb732f311c86bae",
259
+ "spec/v2/ext/chat/README.md": "07e9ca34b3e5fc222ace1c2af60375266e001d1695da87f38f56b58f17aeaead",
260
+ "spec/v2/ext/coordination/README.md": "c7fe0884f52405fdd02c5f9ec309ac6b585685ee06ec5f338fff7acf03c07148",
261
+ "spec/v2/ext/dataIntegration/README.md": "a18e179cf88eb5d3e2fe2e017018141747a64a984d25a4f4ed32d776ea62e26d",
262
+ "spec/v2/ext/entities/README.md": "956d4a9a2aedb8cb9c79ce8145580480920474cc6943f0e33ede32d7b20414dc",
263
263
  "spec/v2/ext/grpc-transport/README.md": "6ba378e3c6d1f2e3269b392cfdf0c40565ee9bfa259d1baaa9ee1d350e38e792",
264
- "spec/v2/ext/kanban/README.md": "1d5bc89133ae02984065cb79d38e7627c36ffd6e0d2a58eb6207aaa020e7b0ad",
265
- "spec/v2/ext/knowledge/README.md": "67be1dc97e5cdc9527d56f4836dc96841548a9c2f8f964777825d56fdf9f0e53",
266
- "spec/v2/ext/launchStudio/README.md": "c732bb855252c31ee1e971cbc2936f2ca29b234c111d548c648095634507babb",
267
- "spec/v2/ext/messaging/README.md": "32c222c0bce515e75b62a5a44b9f09d0e23c1b40f424e1ab8309deefd296c4b6",
264
+ "spec/v2/ext/kanban/README.md": "df179bea93a35c7a9d2556f2abefe2d53e05e33730b0b8cb2a9facab0e394ed2",
265
+ "spec/v2/ext/knowledge/README.md": "ab50dff74a1f285f890fab93f2d3a85f41032fff9191e4623ce9cbaed6d12124",
266
+ "spec/v2/ext/launchStudio/README.md": "ed33abe5bb000288e1be52f2b7a88175c7666a4390a599a6a77844eab564cabe",
267
+ "spec/v2/ext/messaging/README.md": "484cfa3091f89261dbdd48372afba441d3e6c16c3169a861b0ed7fc8c2902780",
268
268
  "spec/v2/ext/portability/README.md": "c59423ee446638b748a911b9e97e803c4786157be6120f656f0a060586bc7b82",
269
269
  "spec/v2/ext/provider-idempotency/README.md": "9d1bccef0ec16a19a3370ae79c2f5a1726ce0d1d25a51352907f288a2ccb15d7",
270
270
  "spec/v2/ext/provider-idempotency/registry.json": "5b5fecad604fb4ab38da39f5abe697a4e57b05406c398f8afeb377331b2bd965",
271
- "spec/v2/ext/restTransport/README.md": "d485417310616b2f1da97106d970293f3f5712f6cadb6b840f5ac84ee28bdda6",
271
+ "spec/v2/ext/restTransport/README.md": "acda51f1a973308841861a119def691db972f310c7b7250ab14f248e9c968585",
272
272
  "spec/v2/ext/sandbox-runtime-notes/README.md": "0d1290fb1e20b2e35c0b15051541ab6546e4e2a6f693b4f912cb3f7d6a65e92c",
273
- "spec/v2/ext/webResearch/README.md": "3ddca9180c4ef9971722a2e6a0c1ffb5cc783411ba554fb9fbdf15b4da624942",
273
+ "spec/v2/ext/webResearch/README.md": "3ec0fa2c798bcfe16a545c6b47a624c44b776561ff46fa754711e5f6677826f8",
274
274
  "spec/v2/facets/a2a.schema.json": "b68bf5e29e455e46c2ad7cfcccf5963730ec2310ff9db81884550d8df30fd6ef",
275
275
  "spec/v2/facets/aiProviders.schema.json": "81fb39b6698564d9d07a0d10525ecb6360c152fe3f3a5ea0439112509ca130e2",
276
+ "spec/v2/facets/auditLogIntegrity.schema.json": "9a7f81320c8f940c6f4129bc7dd895a4063231c5458a717a08c2cbf9bb886c46",
276
277
  "spec/v2/facets/auth.schema.json": "7d98bc81a0f7d307460d039eebfebd21388091bfe1d538762583940f94c0bd2a",
277
278
  "spec/v2/facets/envelopeStrictness.schema.json": "28be0a27f880bd45ec1222a16155f5e9167bbca57bf0322970fe1eb2654562aa",
278
279
  "spec/v2/facets/heartbeat.schema.json": "81d7fa1895a8b0241bd07cf00a7e7905bef0fd14eb3427325261c62eee5746a6",
@@ -297,9 +298,9 @@
297
298
  "spec/v2/path-manifest.json": "17298a245c5da9a70aa7ab0b7f2db4277e06209d6fcdd7187a8b4cea179c08f3",
298
299
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
299
300
  "spec/v2/profiles.json": "180beb9ef2d161766fa23b2987e7e829851e3d316273147cf6a4a3f324befd6b",
300
- "spec/v2/release.json": "f2f87ba5a5476f2213b3486a2618ef3c7381b47c96dd3f082bee0e07ac4a35bc",
301
+ "spec/v2/release.json": "8bd257db47f63fdc4759ed13f34df309d80cd69ee83b96a24aed8bb3a9810b1d",
301
302
  "spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624",
302
- "spec/v2/surface-baseline.json": "fce9d8eeea653476e09b19e525a0b104caab6c51a0b7b427d7d941e2b7118573"
303
+ "spec/v2/surface-baseline.json": "d47f26c3194de0e0d42a731ecaeeae1c2adfdea8c09314792d15c02b50d62efb"
303
304
  },
304
- "corpusCommit": "0ed567fece2f9c5c5ad337fed92f6926ad7547af"
305
+ "corpusCommit": "49be1aa2be9d835a80f934ce98dc4cebf0af46a4"
305
306
  }
package/src/cli.ts CHANGED
@@ -104,9 +104,8 @@ function parseArgs(argv: readonly string[]): ParsedArgs {
104
104
  let impl: string | undefined;
105
105
  let implVersion: string | undefined;
106
106
  let certify: string | undefined;
107
- // Suite 1.152.0: bundle v2 (RFC 0148) is the default. v1 stays reachable via
108
- // `--bundle-version 1` through the RFC 0148 migration window (ends
109
- // 2026-11-10) and is removed at v2.0 (spec/v1/deprecations.json).
107
+ // Suite 2.0.0-rc.1: bundle v3 (RFC 0168 §E) is the default. v2 stays reachable
108
+ // via `--bundle-version 2`, deprecated (RFC 0168 §E.3); v1 is gone.
110
109
  let bundleVersion: '2' | '3' = '3';
111
110
  let hostBuild: ParsedArgs['hostBuild'];
112
111
  let evidenceTier: ParsedArgs['evidenceTier'] = 'self';
@@ -294,7 +293,7 @@ Certification (RFC 0089):
294
293
  --signing-key <pem> v3: Ed25519 private key (PKCS8 PEM) that signs the bundle, or OPENWOP_BUNDLE_SIGNING_KEY.
295
294
  --signing-key-id <id> v3: the keyId the host publishes for that key, or OPENWOP_BUNDLE_SIGNING_KEY_ID.
296
295
  --evidence-tier <t> v3: self | steward | independent (independent needs --verifier-key/--verifier-key-id).
297
- --bundle-version <2|3> Certification bundle format. Default 2 (corrected 2026-09-03, RFC 0168 §E.4; the text said 1 while the code set 2). Version 2 (RFC 0148
296
+ --bundle-version <2|3> Certification bundle format. Default 3 (since suite 2.0.0-rc.1; 2 is DEPRECATED, RFC 0168 §E.3). Version 2 (RFC 0148
298
297
  §C) records per-requirement DISPOSITIONS instead of pass/fail/skip
299
298
  file lists, so "we could not check" stops being indistinguishable
300
299
  from "checked and it holds". See the note it prints.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The audit-log-integrity advertisement, resolved for the target major.
3
+ *
4
+ * major 1 `capabilities.auth.profiles[]` names `openwop-audit-log-integrity`
5
+ * and `capabilities.auth.auditLogIntegrity` carries the facets
6
+ * (spec/v1/auth-profiles.md §"Audit-log integrity").
7
+ * major 2 the `auditLogIntegrity` family record is present at the v2 root
8
+ * (RFC 0224; spec/v2/core/security-defaults.md §Audit-log integrity).
9
+ * Presence is the claim, so there is no `hashChain` seat.
10
+ *
11
+ * `auditVerifyPath()` is `/v1/audit/verify` at major 1 and `/audit/verify` at
12
+ * major 2, so a scenario never reports a suite 404 as a host defect.
13
+ */
14
+ import { driver } from './driver.js';
15
+ import { capabilityFamily } from './discovery-capabilities.js';
16
+ import { targetMajor } from './seams.js';
17
+ import { familyAdvertised } from './v2.js';
18
+
19
+ export const AUDIT_PROFILE = 'openwop-audit-log-integrity';
20
+
21
+ export interface AuditIntegrityCaps {
22
+ hashChain?: boolean;
23
+ checkpointSignatureAlgorithm?: string;
24
+ checkpointPublicKey?: string;
25
+ checkpointIntervalEntries?: number;
26
+ checkpointIntervalSeconds?: number;
27
+ }
28
+
29
+ /** The advertised facets, or null when the host makes no audit-log-integrity claim at the target major. */
30
+ export async function auditIntegrityAdvert(): Promise<AuditIntegrityCaps | null> {
31
+ if (targetMajor() === 2) return (await familyAdvertised('auditLogIntegrity')) as AuditIntegrityCaps | null;
32
+ const disco = await driver.get('/.well-known/openwop');
33
+ const auth = capabilityFamily<{ profiles?: string[]; auditLogIntegrity?: AuditIntegrityCaps }>(disco.json, 'auth') ?? {};
34
+ if (!(Array.isArray(auth.profiles) && auth.profiles.includes(AUDIT_PROFILE))) return null;
35
+ return auth.auditLogIntegrity ?? {};
36
+ }
37
+
38
+ /** Where the claim lives at the target major, for skip reasons and failure messages. */
39
+ export function auditClaimName(): string {
40
+ return targetMajor() === 2 ? 'the auditLogIntegrity family' : AUDIT_PROFILE;
41
+ }
42
+
43
+ export function auditVerifyPath(fromSeq: number, toSeq: number): string {
44
+ return `${targetMajor() === 2 ? '' : '/v1'}/audit/verify?fromSeq=${fromSeq}&toSeq=${toSeq}`;
45
+ }
@@ -38,3 +38,29 @@ export async function readDispatchBudgets(nodeId: string): Promise<DispatchBudge
38
38
  }
39
39
  return { ok: true, attempts: out };
40
40
  }
41
+
42
+ /**
43
+ * RFC 0033 §B: a host MAY retry a truncated emission, and the new output budget
44
+ * SHOULD be greater than the previous one. A SHOULD is recorded, not failed: the
45
+ * caller asserts only on `met`, and records `unmet` as `inapplicable` with the
46
+ * observed budgets. The comparison is between the attempts the provider actually
47
+ * received (the dispatch-budgets seam), never against the fixture's configured value.
48
+ */
49
+ export type TruncationBudgetVerdict =
50
+ | { kind: 'met'; first: number; retry: number }
51
+ | { kind: 'unmet'; first: number; retry: number }
52
+ | { kind: 'skip'; skip: 'inapplicable' | 'blocked'; reason: string };
53
+
54
+ export async function truncationBudgetVerdict(nodeId: string): Promise<TruncationBudgetVerdict> {
55
+ const budgets = await readDispatchBudgets(nodeId);
56
+ if (!budgets.ok && budgets.unserved) {
57
+ return { kind: 'skip', skip: 'inapplicable', reason: `partial witness — the §B budget SHOULD is not observed: ${budgets.reason}, so the retry's budget cannot be compared with the first attempt's` };
58
+ }
59
+ if (!budgets.ok) return { kind: 'skip', skip: 'blocked', reason: budgets.reason };
60
+ const [first, retry] = budgets.attempts;
61
+ if (budgets.attempts.length < 2) return { kind: 'skip', skip: 'inapplicable', reason: `the host made no truncation retry (RFC 0033 §B: MAY retry); per-attempt budgets ${JSON.stringify(budgets.attempts)}` };
62
+ if (typeof first !== 'number' || typeof retry !== 'number') {
63
+ return { kind: 'skip', skip: 'inapplicable', reason: `partial witness — a call carried no output budget (per-attempt budgets ${JSON.stringify(budgets.attempts)}), so the §B SHOULD cannot be compared` };
64
+ }
65
+ return retry > first ? { kind: 'met', first, retry } : { kind: 'unmet', first, retry };
66
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Cross-file isolation for the mock-AI program seam.
3
+ *
4
+ * `POST /v1/host/sample/test/mock-ai/program` is keyed by `nodeId` alone
5
+ * (host-sample-test-seams.md §5), and a node id belongs to a fixture. When two
6
+ * scenario files drive the same fixture, vitest runs them in parallel workers
7
+ * by default and each can overwrite the other's program between seeding it and
8
+ * reading the run: a flaky result that says nothing about the host.
9
+ *
10
+ * `holdMockNodes(...ids)` holds a lock per node id for the whole file, taken in
11
+ * `beforeAll` and released in `afterAll`, so files sharing a node run one after
12
+ * another. The lock is an atomic `mkdir` in the OS temp dir, keyed by the target
13
+ * base URL and the node id, so it is shared by every worker process on the
14
+ * machine and separate hosts never contend. Ids are taken in sorted order (no
15
+ * deadlock between files holding overlapping sets); a lock older than
16
+ * STALE_MS is presumed left by a killed run and is broken.
17
+ */
18
+
19
+ import { beforeAll, afterAll } from 'vitest';
20
+ import { mkdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
21
+ import { createHash } from 'node:crypto';
22
+ import { tmpdir } from 'node:os';
23
+ import { join } from 'node:path';
24
+
25
+ const POLL_MS = 200;
26
+ const WAIT_MS = 300_000;
27
+ const STALE_MS = 600_000;
28
+
29
+ function lockDir(nodeId: string): string {
30
+ const key = createHash('sha256').update(`${process.env.OPENWOP_BASE_URL ?? ''}\u0000${nodeId}`).digest('hex').slice(0, 24);
31
+ return join(tmpdir(), `openwop-mock-node-${key}`);
32
+ }
33
+
34
+ async function acquire(dir: string, nodeId: string): Promise<void> {
35
+ const deadline = Date.now() + WAIT_MS;
36
+ for (;;) {
37
+ try {
38
+ mkdirSync(dir);
39
+ writeFileSync(join(dir, 'owner'), `${process.pid} ${nodeId} ${new Date().toISOString()}\n`);
40
+ return;
41
+ } catch (e) {
42
+ if ((e as NodeJS.ErrnoException).code !== 'EEXIST') throw e;
43
+ try {
44
+ if (Date.now() - statSync(dir).mtimeMs > STALE_MS) { rmSync(dir, { recursive: true, force: true }); continue; }
45
+ } catch { continue; }
46
+ if (Date.now() > deadline) throw new Error(`mock-node lock for ${nodeId} not acquired within ${WAIT_MS / 1000}s (${dir}) — another scenario file still holds it`);
47
+ await new Promise((r) => setTimeout(r, POLL_MS));
48
+ }
49
+ }
50
+ }
51
+
52
+ /** Hold the mock-AI program slot for these node ids for the duration of the calling file. */
53
+ export function holdMockNodes(...nodeIds: string[]): void {
54
+ const held: string[] = [];
55
+ beforeAll(async () => {
56
+ if (!process.env.OPENWOP_BASE_URL) return; // server-free run: nothing to isolate
57
+ for (const id of [...new Set(nodeIds)].sort()) {
58
+ const dir = lockDir(id);
59
+ await acquire(dir, id);
60
+ held.push(dir);
61
+ }
62
+ }, WAIT_MS + 10_000);
63
+ afterAll(() => {
64
+ for (const dir of held.splice(0).reverse()) rmSync(dir, { recursive: true, force: true });
65
+ });
66
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * RFC 0218 §C — an audit anomaly's shape, server-free
3
+ * (`spec/v1/auth-profiles.md` §"Audit-log integrity" 4).
4
+ *
5
+ * A black-box caller cannot tamper with a host's audit log, so an untampered log
6
+ * serves no anomaly and `audit-log-integrity.test.ts` sees an empty array. This
7
+ * file holds the shape instead: one sample anomaly of every `kind` validates
8
+ * against `audit-verify-result.schema.json` (v1 and the derived v2 copy), and the
9
+ * shapes that must not are refused, the reference hosts' pre-§C
10
+ * `{ atSequence, kind, detail }` first among them. The host side is the tamper
11
+ * tests in openwop-examples, which assert every kind's member set.
12
+ *
13
+ * Sabotages, each of which turns a leg red: dropping the `checkpoint` conditional
14
+ * (a `merkle-mismatch` without it validates); dropping the `chain-break`
15
+ * conditional (a `chain-break` without its hashes validates); dropping the
16
+ * `else` arms (a mixed entry validates); dropping the root `chainValid`
17
+ * conditional (a forged-signature report with `chainValid: true` validates);
18
+ * admitting `atSequence` and dropping `atSeq` from `required` (the hosts' old
19
+ * hash-mismatch validates).
20
+ */
21
+
22
+ import { describe, it, expect } from 'vitest';
23
+ import { readFileSync } from 'node:fs';
24
+ import { join } from 'node:path';
25
+ import Ajv2020 from 'ajv/dist/2020.js';
26
+ import { SCHEMAS_DIR } from '../lib/paths.js';
27
+ import { req } from '../lib/requirement-ids.js';
28
+
29
+ const SPEC = 'RFC 0218 §C · spec/v1/auth-profiles.md §"Audit-log integrity" 4';
30
+ const SHAPE = 'openwop.requirement.0218.anomaly-shape';
31
+
32
+ const HASH_A = 'a'.repeat(64);
33
+ const HASH_B = 'b'.repeat(64);
34
+ const CHECKPOINT = { checkpoint: 'cp_5', atSequence: 5, merkleRoot: HASH_A, signature: 'c2ln' };
35
+
36
+ const result = (anomalies: object[], chainValid = anomalies.length === 0): object => ({
37
+ fromSeq: 1,
38
+ toSeq: 5,
39
+ chainValid,
40
+ checkpoints: [CHECKPOINT],
41
+ anomalies,
42
+ });
43
+
44
+ const VALID: Array<[string, object]> = [
45
+ ['a chain-break with both hashes', { atSeq: 4, kind: 'chain-break', expectedPrevHash: HASH_A, actualPrevHash: HASH_B, detail: 'prev_hash differs' }],
46
+ ['a chain-break at the genesis entry (null hashes)', { atSeq: 1, kind: 'chain-break', expectedPrevHash: null, actualPrevHash: HASH_B }],
47
+ ['a legacy entry without kind (a chain-break)', { atSeq: 4, expectedPrevHash: HASH_A, actualPrevHash: '' }],
48
+ ['a hash-mismatch', { atSeq: 3, kind: 'hash-mismatch', detail: 'recomputed != stored' }],
49
+ ['a missing-entry', { atSeq: 2, kind: 'missing-entry' }],
50
+ ['a merkle-mismatch with its checkpoint', { atSeq: 5, kind: 'merkle-mismatch', checkpoint: 'cp_5' }],
51
+ ['a signature-invalid with its checkpoint', { atSeq: 5, kind: 'signature-invalid', checkpoint: 'cp_5', detail: 'does not verify' }],
52
+ ];
53
+
54
+ const INVALID: Array<[string, object]> = [
55
+ // The reference hosts' pre-§C hash-mismatch, verbatim: wrong only in the
56
+ // sequence member's name, so nothing but `atSeq` can refuse it.
57
+ ['`atSequence` for `atSeq` (the reference hosts\' pre-§C shape)', { atSequence: 3, kind: 'hash-mismatch', detail: 'recomputed != stored' }],
58
+ ['a merkle-mismatch without `checkpoint`', { atSeq: 5, kind: 'merkle-mismatch' }],
59
+ ['a signature-invalid without `checkpoint`', { atSeq: 5, kind: 'signature-invalid', detail: 'x' }],
60
+ ['a chain-break without its hashes', { atSeq: 4, kind: 'chain-break', detail: 'x' }],
61
+ ['a legacy entry without kind or hashes', { atSeq: 4 }],
62
+ ['a mixed entry: a merkle-mismatch carrying the chain hashes', { atSeq: 5, kind: 'merkle-mismatch', checkpoint: 'cp_5', expectedPrevHash: HASH_A, actualPrevHash: HASH_B }],
63
+ ['a mixed entry: a chain-break carrying a checkpoint', { atSeq: 4, kind: 'chain-break', expectedPrevHash: HASH_A, actualPrevHash: HASH_B, checkpoint: 'cp_5' }],
64
+ ['a hash-mismatch carrying a checkpoint', { atSeq: 3, kind: 'hash-mismatch', checkpoint: 'cp_5' }],
65
+ ['an unknown kind', { atSeq: 3, kind: 'row-rewritten' }],
66
+ ];
67
+
68
+ const SCHEMAS = [['v1', 'audit-verify-result.schema.json'], ['v2', join('v2', 'audit-verify-result.schema.json')]].map(([label, file]) => {
69
+ const schema = JSON.parse(readFileSync(join(SCHEMAS_DIR, file!), 'utf8')) as object;
70
+ return { label: label!, validate: new Ajv2020({ strict: false, allErrors: true }).compile(schema) };
71
+ });
72
+
73
+ describe('RFC 0218 §C — audit anomaly shape (server-free, v1 and v2 schemas)', () => {
74
+ it('every anomaly kind validates in its own shape', () => {
75
+ for (const { label, validate } of SCHEMAS) {
76
+ for (const [name, anomaly] of VALID) {
77
+ const ok = validate(result([anomaly]));
78
+ expect(ok, req(SHAPE, SPEC, `${label}: ${name} validates: ${JSON.stringify(validate.errors)}`)).toBe(true);
79
+ }
80
+ expect(validate(result([])), req(SHAPE, SPEC, `${label}: an untampered result with no anomaly validates`)).toBe(true);
81
+ }
82
+ });
83
+
84
+ it('an anomaly outside its kind\'s shape is refused', () => {
85
+ for (const { label, validate } of SCHEMAS) {
86
+ for (const [name, anomaly] of INVALID) {
87
+ expect(validate(result([anomaly])), req(SHAPE, SPEC, `${label}: ${name} is refused`)).toBe(false);
88
+ }
89
+ }
90
+ });
91
+
92
+ it('chainValid is false exactly when anomalies is non-empty', () => {
93
+ const forged = { atSeq: 5, kind: 'signature-invalid', checkpoint: 'cp_5' };
94
+ for (const { label, validate } of SCHEMAS) {
95
+ expect(validate(result([forged], true)), req(SHAPE, SPEC, `${label}: chainValid: true beside a signature-invalid anomaly is refused`)).toBe(false);
96
+ expect(validate(result([], false)), req(SHAPE, SPEC, `${label}: chainValid: false with no anomaly is refused`)).toBe(false);
97
+ expect(validate(result([forged], false)), req(SHAPE, SPEC, `${label}: chainValid: false beside the anomaly validates`)).toBe(true);
98
+ }
99
+ });
100
+ });
@@ -2,8 +2,10 @@
2
2
  * RFC 0218 — a host's audit checkpoints are signed over their Merkle root
3
3
  * (`spec/v1/auth-profiles.md` §"Audit-log integrity" 3).
4
4
  *
5
- * Gated on the `openwop-audit-log-integrity` profile. Every checkpoint
6
- * `GET /v1/audit/verify` returns MUST verify under the advertised
5
+ * Gated on the `openwop-audit-log-integrity` profile at major 1 and on the
6
+ * `auditLogIntegrity` family at major 2 (RFC 0224; spec/v2/core/
7
+ * security-defaults.md §Audit-log integrity). Every checkpoint
8
+ * `GET /v1/audit/verify` (major 2: `GET /audit/verify`) returns MUST verify under the advertised
7
9
  * `checkpointPublicKey` as Ed25519 over its hex-decoded `merkleRoot`. The root
8
10
  * itself cannot be recomputed from outside (the entries are not on the wire),
9
11
  * so the black box witnesses the signature half only. The root half belongs to
@@ -15,38 +17,35 @@
15
17
 
16
18
  import { describe, it, expect } from 'vitest';
17
19
  import { driver } from '../lib/driver.js';
18
- import { capabilityFamily } from '../lib/discovery-capabilities.js';
19
20
  import { req } from '../lib/requirement-ids.js';
20
21
  import { softSkip } from '../lib/soft-skip.js';
21
22
  import { checkpointPublicKey, verifyCheckpointSignature } from '../lib/audit-checkpoint.js';
23
+ import { auditClaimName, auditIntegrityAdvert, auditVerifyPath } from '../lib/auditIntegrity.js';
22
24
 
23
- const SPEC = 'RFC 0218 · spec/v1/auth-profiles.md §"Audit-log integrity" 3';
25
+ const SPEC = 'RFC 0218 · spec/v1/auth-profiles.md §"Audit-log integrity" 3; spec/v2/core/security-defaults.md §"Audit-log integrity" (RFC 0224)';
24
26
  const SIGNED = 'openwop.requirement.0218.checkpoint-signature-over-root';
25
27
 
26
- interface AuditIntegrityCaps { checkpointPublicKey?: string }
27
- interface AuthCaps { profiles?: string[]; auditLogIntegrity?: AuditIntegrityCaps }
28
-
29
28
  describe('RFC 0218 — a host\'s checkpoints are signed over their root', () => {
30
29
  it('every checkpoint GET /v1/audit/verify returns verifies under the advertised key', async () => {
31
- const disco = await driver.get('/.well-known/openwop');
32
- const auth = capabilityFamily<AuthCaps>(disco.json, 'auth') ?? {};
33
- if (!(Array.isArray(auth.profiles) && auth.profiles.includes('openwop-audit-log-integrity'))) {
34
- return softSkip('inapplicable', 'the host does not claim openwop-audit-log-integrity');
30
+ const integrity = await auditIntegrityAdvert();
31
+ if (integrity === null) {
32
+ return softSkip('inapplicable', `the host does not claim ${auditClaimName()}`);
35
33
  }
36
- const advertised = auth.auditLogIntegrity?.checkpointPublicKey;
34
+ const advertised = integrity.checkpointPublicKey;
37
35
  if (typeof advertised !== 'string' || advertised.length === 0) {
38
36
  // A claimed profile without its key is the profile-shape leg's failure
39
37
  // (audit-log-integrity.test.ts); this row cannot be observed without it.
40
- return softSkip('blocked', 'the host claims the profile but advertises no auditLogIntegrity.checkpointPublicKey');
38
+ return softSkip('blocked', `the host claims ${auditClaimName()} but advertises no auditLogIntegrity.checkpointPublicKey`);
41
39
  }
42
40
  let key;
43
41
  try { key = checkpointPublicKey(advertised); } catch (e) {
44
42
  return softSkip('blocked', `auditLogIntegrity.checkpointPublicKey is not an Ed25519 SPKI key: ${(e as Error).message}`);
45
43
  }
46
44
 
47
- const verify = await driver.get('/v1/audit/verify?fromSeq=0&toSeq=1000000');
45
+ const path = auditVerifyPath(0, 1_000_000);
46
+ const verify = await driver.get(path);
48
47
  if (verify.status !== 200) {
49
- return softSkip('blocked', `GET /v1/audit/verify answered ${verify.status}; the verify leg of audit-log-integrity owns that contract`);
48
+ return softSkip('blocked', `GET ${path.split('?')[0]} answered ${verify.status}; the verify leg of audit-log-integrity owns that contract`);
50
49
  }
51
50
  const checkpoints = ((verify.json as { checkpoints?: Array<{ atSequence?: number; merkleRoot?: string; signature?: string }> }).checkpoints) ?? [];
52
51
  if (checkpoints.length === 0) {