@openwop/spec-artifacts 2.0.7 → 2.0.9
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/CORPUS-STAMP.json +29 -29
- package/api/seams-v2.yaml +1 -1
- package/api/v2/asyncapi.yaml +1 -1
- package/api/v2/openapi.yaml +1 -1
- package/package.json +1 -1
- package/spec/v1/core-standard-manifest.json +2 -2
- package/spec/v2/README.md +6 -2
- package/spec/v2/core/capabilities.md +1 -1
- package/spec/v2/core/conformance.md +1 -1
- package/spec/v2/core/connection-packs.md +1 -1
- package/spec/v2/core/errors.md +1 -1
- package/spec/v2/core/events.md +1 -1
- package/spec/v2/core/form-content-packs.md +1 -1
- package/spec/v2/core/headers.md +1 -1
- package/spec/v2/core/idempotency.md +1 -1
- package/spec/v2/core/identity.md +1 -1
- package/spec/v2/core/interop.md +1 -1
- package/spec/v2/core/interrupt.md +1 -1
- package/spec/v2/core/overview.md +1 -1
- package/spec/v2/core/packs.md +1 -1
- package/spec/v2/core/persistence.md +1 -1
- package/spec/v2/core/replay.md +1 -1
- package/spec/v2/core/runs.md +1 -1
- package/spec/v2/core/security-defaults.md +1 -1
- package/spec/v2/core/versioning.md +24 -4
- package/spec/v2/core/webhooks.md +1 -1
- package/spec/v2/core/workflow-chain-packs.md +1 -1
- package/spec/v2/release.json +2 -2
package/CORPUS-STAMP.json
CHANGED
|
@@ -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.
|
|
5
|
-
"corpusTag": "v2.0.
|
|
4
|
+
"version": "2.0.9",
|
|
5
|
+
"corpusTag": "v2.0.9",
|
|
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": "
|
|
13
|
-
"api/v2/asyncapi.yaml": "
|
|
14
|
-
"api/v2/openapi.yaml": "
|
|
12
|
+
"api/seams-v2.yaml": "85832b378ab3396f031b1503d17a7d252dd2f9bbf753324e05601cf8d50c6b96",
|
|
13
|
+
"api/v2/asyncapi.yaml": "029fccaec2975cf943e11465a9ea98149096d061da2893c438337906e647dc92",
|
|
14
|
+
"api/v2/openapi.yaml": "a406c3723d88f520c387d5e47ff9cabb32ac0cac7b1825c8c768ab6ec0cf27bb",
|
|
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": "
|
|
202
|
+
"spec/v1/core-standard-manifest.json": "63799de159579793a95daae66accdc4aa7149eb96994235b0841c0d2ffa132bc",
|
|
203
203
|
"spec/v1/deprecations.json": "1d5acb69a9b8ccb57275a95605f74aef1d920685f8407c9d382a46b59dc803bb",
|
|
204
204
|
"spec/v1/deprecations.schema.json": "18c87e78bedc210431f795ae44c5b5d202f2f3317850d5cf86867d4f1fa1cdfb",
|
|
205
205
|
"spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
|
|
@@ -211,27 +211,27 @@
|
|
|
211
211
|
"spec/v1/migrations.schema.json": "886779aa6c22e646db097f5df210adb018a4dd14a7b815465a18c8a7056c8f72",
|
|
212
212
|
"spec/v1/operation-path-manifest.json": "5f5f4e3842669371730ebbd1aace3fb794192615f0018dc144f484ba5db82ac3",
|
|
213
213
|
"spec/v1/spec-gaps.json": "6cc9962c6b969f632e07a78b52a4f61447ff579e2990cbae989866f584a86042",
|
|
214
|
-
"spec/v2/README.md": "
|
|
215
|
-
"spec/v2/core/capabilities.md": "
|
|
216
|
-
"spec/v2/core/conformance.md": "
|
|
217
|
-
"spec/v2/core/connection-packs.md": "
|
|
218
|
-
"spec/v2/core/errors.md": "
|
|
219
|
-
"spec/v2/core/events.md": "
|
|
220
|
-
"spec/v2/core/form-content-packs.md": "
|
|
221
|
-
"spec/v2/core/headers.md": "
|
|
222
|
-
"spec/v2/core/idempotency.md": "
|
|
223
|
-
"spec/v2/core/identity.md": "
|
|
224
|
-
"spec/v2/core/interop.md": "
|
|
225
|
-
"spec/v2/core/interrupt.md": "
|
|
226
|
-
"spec/v2/core/overview.md": "
|
|
227
|
-
"spec/v2/core/packs.md": "
|
|
228
|
-
"spec/v2/core/persistence.md": "
|
|
229
|
-
"spec/v2/core/replay.md": "
|
|
230
|
-
"spec/v2/core/runs.md": "
|
|
231
|
-
"spec/v2/core/security-defaults.md": "
|
|
232
|
-
"spec/v2/core/versioning.md": "
|
|
233
|
-
"spec/v2/core/webhooks.md": "
|
|
234
|
-
"spec/v2/core/workflow-chain-packs.md": "
|
|
214
|
+
"spec/v2/README.md": "453b56e0f9dd84889e90f3e25efda53e550275a112bc72a970252e00335b408b",
|
|
215
|
+
"spec/v2/core/capabilities.md": "3ea74e9cfbca23723e4fadac7d53a44f59940dfe9942e086533103e3677507df",
|
|
216
|
+
"spec/v2/core/conformance.md": "3cae1183d3155572004f192d0c64b921151f4f9905ce2a6a3e29f475334de688",
|
|
217
|
+
"spec/v2/core/connection-packs.md": "460019f7bc9b5c7473eaa5e2825d8e28ff2941306fbd7ba5dfe4c9e174fcbe64",
|
|
218
|
+
"spec/v2/core/errors.md": "acb7a04a0c4ac136eb8dcd8549e8bc6da19a80753bf81d903202c7008cb8802f",
|
|
219
|
+
"spec/v2/core/events.md": "ceee1671e7b585026be61ffa210759157b292d3b56c352bef5d0de98a3db9983",
|
|
220
|
+
"spec/v2/core/form-content-packs.md": "de63b1bb72bfde0c31aeb31d1f09d8f9297550604c771fd65f26d7459eac7be0",
|
|
221
|
+
"spec/v2/core/headers.md": "18c09184e5b64c5f28e4aa8c028b13da074bd9a4ca8e6ae56290faa402c277c0",
|
|
222
|
+
"spec/v2/core/idempotency.md": "9452888f1ed70ffafc4a4f6c770511b3d4e7277009d39b8b8bbca26f5a3c0a32",
|
|
223
|
+
"spec/v2/core/identity.md": "3ba7016e9f78aac6f6ec5be8a2c577c0309e3e62e2ceb6070c2eabbfc7d1b507",
|
|
224
|
+
"spec/v2/core/interop.md": "e5c166cd94050539a694cce01d4b733bd8bfbbf4d30584d6cd8ee1a85009afc5",
|
|
225
|
+
"spec/v2/core/interrupt.md": "a320811c337cb498207cfdc87e24bea8715689101be299f4eb2ae1ea54e6f202",
|
|
226
|
+
"spec/v2/core/overview.md": "6c3d32ded128237ddb9af12bcfaac4079162464906519d0f2861bba6c675ae18",
|
|
227
|
+
"spec/v2/core/packs.md": "1c6bad59fd77a90bed9c904c7d59f1649dd21cf70986962194b10650533a46b5",
|
|
228
|
+
"spec/v2/core/persistence.md": "8e4af460d7390945ffd88731edf69f95a462f55d6569a7d375bf802ca8ddff95",
|
|
229
|
+
"spec/v2/core/replay.md": "5647bc44e994d9fcb2d2fc8acbb6c0f66e1262228b7efc5a1035eb1d3b38a23f",
|
|
230
|
+
"spec/v2/core/runs.md": "ceae2f80fc915c12a22682205e2bec797d311b53dc8883000a4f02d002192778",
|
|
231
|
+
"spec/v2/core/security-defaults.md": "0837314be15d4278f1a835b97f101ba794a025952ad39fd408c6e319756ebf71",
|
|
232
|
+
"spec/v2/core/versioning.md": "d9506ec2e009a84c1ac02924af2867cf2d6b90c872902fe1b0979a8908e494d0",
|
|
233
|
+
"spec/v2/core/webhooks.md": "9a946db3a17f72adba8ad493dc004c856237681f823303599dd45c83b522226b",
|
|
234
|
+
"spec/v2/core/workflow-chain-packs.md": "e0e78926ebb6aa217cf35191d401a51903610469c5d0c464307888fb89e69037",
|
|
235
235
|
"spec/v2/declaration.json": "bd8a1dcee899a4478ac96b52da6ee07e1cb5fce4465939ac32e19e52f4d5c6b2",
|
|
236
236
|
"spec/v2/declaration.schema.json": "eac5f8080bd572f147bd57d0c4ac8ad73b14536d9236222490ae29a33b21e184",
|
|
237
237
|
"spec/v2/errors.json": "f179414a92f30b5dadf26e9e57699649a67324bd7186d5287647d17605d137d3",
|
|
@@ -268,8 +268,8 @@
|
|
|
268
268
|
"spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
|
|
269
269
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
270
270
|
"spec/v2/profiles.json": "0636f19fceae625390003a347e70ef4797d84766b5c24ce8a02cea52aadebca4",
|
|
271
|
-
"spec/v2/release.json": "
|
|
271
|
+
"spec/v2/release.json": "14eb79136a01caa739684a20dbe15384c2f5420b30f942e6e328e8c66c446745",
|
|
272
272
|
"spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624"
|
|
273
273
|
},
|
|
274
|
-
"corpusCommit": "
|
|
274
|
+
"corpusCommit": "e84395f18a99d9266ba94e9eddb23a7e73ef5c33"
|
|
275
275
|
}
|
package/api/seams-v2.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP conformance seams profile (openwop-conformance-seams-v2)
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.9
|
|
5
5
|
description: 'GENERATED by scripts/derive-v2-api.py. RFC 0168 §C: the seams are a versioned conformance profile with their
|
|
6
6
|
own document and path space (/conformance/seams/…), validated against the canonical v2 schemas with no tolerance path,
|
|
7
7
|
forbidden from the capability namespace (a host advertises the profile, never a testSeams flag). This document carries
|
package/api/v2/asyncapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
asyncapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP v2 event streams
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.9
|
|
5
5
|
description: GENERATED by scripts/derive-v2-api.py (RFC 0171 §E.1, RFC 0172 §C.2). One run-events channel whose address
|
|
6
6
|
is the OpenAPI path key; the server pathname is empty (bare origin). streamMode is a pattern over the closed set and its
|
|
7
7
|
comma-separated combinations (`values` never combines). hostEvents has a real address (RFC 0171 §E.1) — the documented
|
package/api/v2/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP v2 API
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.9
|
|
5
5
|
summary: REST surface for declaring, executing, suspending, resuming, and observing multi-step workflows.
|
|
6
6
|
description: GENERATED by scripts/derive-v2-api.py from api/openapi.yaml and the RFC 0167 children (v2 charter Phase 3,
|
|
7
7
|
P3-C). Bare origin, unversioned path keys, negotiation by `OpenWOP-Version` + `protocolVersions[]` (RFC 0172 §A). No seam
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/spec-artifacts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"description": "The OpenWOP machine-readable contract: api/ (OpenAPI, AsyncAPI, the seams profile), schemas/ (v1 and v2 JSON Schemas), the spec/v1 and spec/v2 registries (errors, event codemap, declaration, deprecations, migrations, gaps) and CORPUS-STAMP.json \u2014 published from the openwop/openwop corpus tag; the peer dependency @openwop/openwop-conformance digest-checks at start (RFC 0168 \u00a7D.2).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"provenance": {
|
|
5
5
|
"suite": {
|
|
6
6
|
"package": "@openwop/openwop-conformance",
|
|
7
|
-
"version": "2.0.
|
|
7
|
+
"version": "2.0.9"
|
|
8
8
|
},
|
|
9
9
|
"note": "Derived from the corpus at generation time. Regenerate with --write; verify with --check."
|
|
10
10
|
},
|
|
@@ -419,5 +419,5 @@
|
|
|
419
419
|
"$id": "https://openwop.dev/spec/v1/workspace-file.schema.json"
|
|
420
420
|
}
|
|
421
421
|
],
|
|
422
|
-
"digest": "
|
|
422
|
+
"digest": "40c998f2cbcc39e838184b7d5ca367ff31efdba35ca1e3d9f6b7272421571bf2"
|
|
423
423
|
}
|
package/spec/v2/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
# `spec/v2/` — the OpenWOP v2 tree (
|
|
1
|
+
# `spec/v2/` — the OpenWOP v2 tree (the current protocol major)
|
|
2
2
|
|
|
3
|
-
> **Status:
|
|
3
|
+
> **Status: released.** v2 is the current protocol major — `v2.0.0` was tagged 2026-09-05 and this tree is at corpus `v2.0.9` (`release.json`). Everything under `spec/v2/`, `schemas/v2/` and `api/v2/` is normative, is vendored into `@openwop/spec-artifacts`, and is what `@openwop/openwop-conformance` 2.x measures. A new integration targets v2.
|
|
4
|
+
>
|
|
5
|
+
> **v1 is not retired.** Through the overlap a host advertises both majors and `preferredVersion` MUST remain a `1.x` member (`core/versioning.md` §1.1); v1 clients keep working unchanged on `/v1/…`. v1 end-of-support is the later of two clocks in `core/overview.md`, earliest 2026-12-04, and until then `spec/v1/` stays the maintained parallel track. A `1.x` conformance tarball still excludes this tree (`conformance/scripts/pack-vendor.sh`).
|
|
6
|
+
>
|
|
7
|
+
> The banner that stood here until 2026-09-10 said *"in construction … until the `v2.0.0-rc.1` corpus tag"*. That tag landed 2026-09-03 and the line was never updated; a reader who trusted it concluded v2 did not exist. Status lines that are hand-kept drift; this one now names the tag and the file that carry the truth.
|
|
4
8
|
|
|
5
9
|
Layout (RFC 0167 §C; RFC 0174 §E.2 budget):
|
|
6
10
|
|
package/spec/v2/core/errors.md
CHANGED
package/spec/v2/core/events.md
CHANGED
package/spec/v2/core/headers.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Headers
|
|
2
2
|
|
|
3
|
-
> **Status:
|
|
3
|
+
> **Status: Stable · v2.0.9 (2026-09-10) · RFC 0171 §C.1, RFC 0172 §A.3–§A.4.** GENERATED by `scripts/derive-v2-api.py` from `api/v2/openapi.yaml`; do not edit.
|
|
4
4
|
|
|
5
5
|
## Why this exists
|
|
6
6
|
|
package/spec/v2/core/identity.md
CHANGED
package/spec/v2/core/interop.md
CHANGED
package/spec/v2/core/overview.md
CHANGED
package/spec/v2/core/packs.md
CHANGED
package/spec/v2/core/replay.md
CHANGED
package/spec/v2/core/runs.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Versioning and Release
|
|
2
2
|
|
|
3
|
-
> **Status:
|
|
3
|
+
> **Status: Stable · v2.0.9 (2026-09-10) · RFC 0172, 0179, 0176.**
|
|
4
4
|
|
|
5
5
|
## Why this exists
|
|
6
6
|
|
|
@@ -18,9 +18,11 @@ A v2 host MUST advertise `protocolVersions[]` (grammar `^(0|[1-9][0-9]*)\.(0|[1-
|
|
|
18
18
|
|
|
19
19
|
v1 operations keep their `/v1/…` path keys unchanged through the overlap. v2 operations are unversioned path keys on a bare origin (`servers[].url = https://{host}`): `/runs`, `/runs/{runId}`, `/.well-known/openwop`. There is no `/v2/` path space. An unversioned path is the v2 surface; the v1 MUST that servers answer `400` for unversioned roots is retracted for v2.
|
|
20
20
|
|
|
21
|
-
A host that advertises a major in `protocolVersions[]` MUST reach, under that major, every operation it serves under the other. Advertising a major is a claim about the **path space**, not about `/.well-known/openwop` alone — that resource's representation is *selected* by the request header (§1.3), so it answers correctly for a host that has mounted nothing else, and every discovery-level probe of the advertisement passes with it. Concretely: if `/v1/<op>` answers and the unversioned `/<op>` returns `404` under the advertised major, the advertisement overstates what the host serves and the host MUST NOT advertise that major until the surface is reachable. The pairing is normative because a lone `404` cannot distinguish *"this host does not serve that operation"* from *"this host serves it and did not mount it under this major"*, and only the second is a defect.
|
|
21
|
+
A host that advertises a major in `protocolVersions[]` MUST reach, under that major, every operation **named in `spec/v2/path-manifest.json`** that it serves under the other. Advertising a major is a claim about the **path space**, not about `/.well-known/openwop` alone — that resource's representation is *selected* by the request header (§1.3), so it answers correctly for a host that has mounted nothing else, and every discovery-level probe of the advertisement passes with it. Concretely: if `/v1/<op>` answers and the unversioned `/<op>` returns `404` under the advertised major, the advertisement overstates what the host serves and the host MUST NOT advertise that major until the surface is reachable. The pairing is normative because a lone `404` cannot distinguish *"this host does not serve that operation"* from *"this host serves it and did not mount it under this major"*, and only the second is a defect.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
**The manifest is the scope, and that qualifier is load-bearing.** An earlier wording quantified over *every operation it serves*, which is not jointly satisfiable with `conformance.md` §"Test seams": the seams profile mounts the real path space `/conformance/seams/…`, and that same document requires `spec/v2/path-manifest.json` and `api/v2/openapi.yaml` to contain **no** seam operation. Under the unqualified reading a host serving seams under one major owed them under the other, while the manifest against which the claim is measured was forbidden to name them. Surfaces a host serves that the manifest does not name — seam paths, and any path the protocol does not define — are **not** bound by this paragraph; §5 records what the protocol does and does not say about the second class. The narrowing does not weaken the case the rule exists for: the defect that motivated it was `POST /webhooks` answering `404` under major 2 while `POST /v1/webhooks` answered `201`, and `webhooks` is a manifest operation.
|
|
24
|
+
|
|
25
|
+
`spec/v2/path-manifest.json` (generated) carries operations (`method`, `path`, `operationId`) and channels (`name`, `address`) on a bare origin, and **every path in it is unversioned** — there are no `/v1` rows. The `/v1` twin of a manifest row is derived by prefixing, which is what the pairing above compares. OpenAPI (`api/v2/openapi.yaml`), AsyncAPI (`api/v2/asyncapi.yaml`), and any kept proto MUST resolve to identical absolute paths for the shared event stream (`scripts/check-path-parity.mjs`); the canonical OpenAPI MUST contain no seam or test-mode operation (those live in the seams profile, see `conformance.md`).
|
|
24
26
|
|
|
25
27
|
### 1.3 The request header
|
|
26
28
|
|
|
@@ -37,7 +39,19 @@ A request on a `/v1/…` path key MUST NOT carry `OpenWOP-Version` with a value
|
|
|
37
39
|
|
|
38
40
|
### 1.4 The response header
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Every protocol response MUST carry `OpenWOP-Version: <major>.<minor>` naming the contract that produced it. Reporting a version other than the one used is a silent downgrade and non-conformant; the `dual-stack-negotiation` scenario falsifies it. Emitting the header on `/v1/` responses is additive in v1.x and REQUIRED in v2.
|
|
43
|
+
|
|
44
|
+
A *protocol response* is one produced by an operation named in `spec/v2/path-manifest.json` (or its `/v1/` twin through the overlap). The quantifier is deliberately not "any path": a host may serve other things on its origin — an application shell, a hosting fallback, a proprietary route — and those responses were produced by no protocol contract, so there is no version for them to name. Errata 2026-09-10: this section previously read "a response on any path MUST carry …", which a shell page on a shared name violated literally while the rationale (a silent downgrade) could not apply to it. The same over-broad quantifier was corrected in §1.2 on 2026-09-09.
|
|
45
|
+
|
|
46
|
+
**A non-protocol response MUST NOT carry `OpenWOP-Version` and MUST NOT be `application/json`.** This is what keeps the two distinguishable, not a loophole: a reader, a cache, or the conformance suite that sees a response without the header, or with a `text/html` body, MUST NOT count it as a protocol response — it did not reach the operation (`v2-advertised-path-space-served`, `reachedUnderMajor2`; the scenario had been the rule for a week before this prose).
|
|
47
|
+
|
|
48
|
+
**Content negotiation on a shared name is permitted, with conditions.** A host MAY serve both a protocol operation and a non-protocol resource (a page) under one unversioned name, selecting on `Accept`, if all three hold:
|
|
49
|
+
|
|
50
|
+
1. A request that identifies as a protocol client MUST receive the protocol response for the applicable major (§1.3) with `OpenWOP-Version` on it. A request identifies as a protocol client when it carries `OpenWOP-Version`, **or** when its `Accept` admits `application/json` without preferring `text/html` — an absent `Accept` and `*/*` both qualify. The default is the wire, not the page; only an explicit `text/html` preference selects the page. Browsers send that; nothing that speaks the protocol does.
|
|
51
|
+
2. The non-protocol response obeys the paragraph above (no `OpenWOP-Version`, not `application/json`).
|
|
52
|
+
3. The response carries `Vary: Accept, OpenWOP-Version` so no cache serves one representation to a client that asked for the other.
|
|
53
|
+
|
|
54
|
+
A host that cannot meet all three MUST move the non-protocol resource off the shared name.
|
|
41
55
|
|
|
42
56
|
### 1.5 Client precedence and `minClientVersion`
|
|
43
57
|
|
|
@@ -100,6 +114,12 @@ The projection is mandatory rather than optional for a reason that is not stylis
|
|
|
100
114
|
|
|
101
115
|
The overlap ends at v1 end-of-support (`overview.md`), when `protocolVersions[]` drops the `1.<n>` member and every alias carrying the `v1-end-of-support` trigger is removed.
|
|
102
116
|
|
|
117
|
+
**Retirement is atomic, and that is a consequence of §1.1 rather than a separate rule.** Through the overlap `preferredVersion` MUST name a `1.x` member; a host that drops v1 from `protocolVersions[]` advertises a `2.x` `preferredVersion`. There is no legal intermediate state in which both majors are advertised and `2.x` is preferred, so flipping `preferredVersion` ahead of the drop is not a smaller first step — it is the same step. Dropping v1 therefore retires the whole `/v1` path space at once, not incrementally.
|
|
118
|
+
|
|
119
|
+
**Retirement flips every header-less request's contract.** Through the overlap a header-less request on an unversioned name is served major 1 (§1.3), and on a host whose v1 surface lives under `/v1/` that name is not a v1 key — so it falls through to whatever else the host serves there, typically an application page. The v1 default is what separates the page from the wire. At end-of-support the same header-less request is served major 2, the name *is* a v2 key, and the page starts answering the protocol operation to browsers. An inventory that counts `/v1/` paths cannot see this hazard because there is no `/v1/` in it. The test is `set(top-level segments of the manifest's paths) ∩ set(anything else the host serves unversioned)`: on the reference host the intersection is empty; a host with a non-empty intersection MUST, before end-of-support, either move the other resource off the shared name or serve it under the §1.4 content-negotiation conditions, which make the disambiguator `Accept` rather than the retiring default. Recorded 2026-09-10 from a tier-1 host whose intersection was `{agents, prompts, runs}`.
|
|
120
|
+
|
|
121
|
+
**Open gap — host-proprietary paths have no defined successor.** A host may serve `/v1` roots the manifest does not name. §1.2 does not bind them, and at end-of-support the `/v1` prefix that addressed them is gone, so the protocol says nothing about where they go. This is **undecided, not permissive**: the corpus reserves a vendor namespace for capability records (`capabilities.md` §"extensions"), error codes (`errors.md`), event types (`events.md`), and pack-document properties (`packs.md`), each keyed to an org registered in `spec/v2/declaration.json` — and has no equivalent for paths. RFC 0172 rejected a `/v2/` path space and did not reach this question. The one worked example of a legitimate path space outside the manifest is the seams profile (`conformance.md` §"Test seams"), which stays honest by advertising `openwop-conformance-seams-v2` in `profiles[]` rather than by any path-level rule. A host in this position SHOULD record the affected roots before end-of-support so the set is known when the question is decided.
|
|
122
|
+
|
|
103
123
|
## 6. Migration rows (RFC 0172)
|
|
104
124
|
|
|
105
125
|
| Row | v1 | v2 |
|
package/spec/v2/core/webhooks.md
CHANGED
package/spec/v2/release.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "RFC 0172 \u00a7D.1 \u2014 the one release identity the v2 artifacts derive from. `version` is the next corpus tag `v<version>` (the publish workflow's coordinated-release tag pattern `v*`; RFC 0172's `openwop/v2.<minor>.<patch>` spelling is amended to this at its flip). api/v2/*.yaml info.version, the suite's 2.x version and @openwop/spec-artifacts read it. Bumped by the release PR that cuts the tag, never by hand elsewhere.",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"corpusTag": "v2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
|
+
"corpusTag": "v2.0.9",
|
|
5
5
|
"updated": "2026-09-05"
|
|
6
6
|
}
|