@openwop/spec-artifacts 2.44.0 → 2.44.2
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 +17 -16
- 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 +1 -1
- package/spec/v2/core/host-services.md +15 -2
- package/spec/v2/core/i18n.md +12 -2
- package/spec/v2/core/overview.md +1 -1
- package/spec/v2/core/packs.md +17 -2
- package/spec/v2/core/storage.md +73 -0
- package/spec/v2/core/webhooks.md +20 -2
- package/spec/v2/declaration.json +13 -13
- package/spec/v2/release.json +2 -2
- package/spec/v2/surface-baseline.json +1 -1
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.44.
|
|
5
|
-
"corpusTag": "v2.44.
|
|
4
|
+
"version": "2.44.2",
|
|
5
|
+
"corpusTag": "v2.44.2",
|
|
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": "
|
|
13
|
-
"api/v2/asyncapi.yaml": "
|
|
14
|
-
"api/v2/openapi.yaml": "
|
|
12
|
+
"api/seams-v2.yaml": "f24127f3cd544f1c5a942859ffc492b438d37b1b7d7a660c631fb87f70cd24f6",
|
|
13
|
+
"api/v2/asyncapi.yaml": "3283ff1bbe962dc75e6d66d2b755d4eb7d53770ce8511f2d671b923d6ca0e51a",
|
|
14
|
+
"api/v2/openapi.yaml": "4a455ba22c81718e2842adce60e5d3c5970e6f8a55b301d9154ccc8060f6cf91",
|
|
15
15
|
"api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
|
|
16
16
|
"schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
|
|
17
17
|
"schemas/a2a-task-state.schema.json": "75d5049dea8bd873ff0e7546f1c60c8d36c219bec7084264360be54a8be30ae1",
|
|
@@ -204,7 +204,7 @@
|
|
|
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": "
|
|
207
|
+
"spec/v1/core-standard-manifest.json": "3d7fd99cd02153094723c2bf383d757c282e653526aa3b199d9bdb4b9cfd7c80",
|
|
208
208
|
"spec/v1/deprecations.json": "46df807fb4adf0aae24671c20f69975cf3496e3bc3a521cb7e6ea556bdce563c",
|
|
209
209
|
"spec/v1/deprecations.schema.json": "3e393c405d2a41b467d8c5e3c468549078df1ce6a6d2588fc488097b95d9b55b",
|
|
210
210
|
"spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
|
|
@@ -216,7 +216,7 @@
|
|
|
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
|
-
"spec/v2/README.md": "
|
|
219
|
+
"spec/v2/README.md": "377639de1dad1ed71aba6dae8d34fdb6ee954fb23106e89454fe8d29cdde6349",
|
|
220
220
|
"spec/v2/core/capabilities.md": "ad728e8a761153b55d036ece55043ff62d0982121e2e629e5e7cdf560fca3c03",
|
|
221
221
|
"spec/v2/core/conformance.md": "0cfceb926eed87055550a5c23e640210c795fc8cf9dd1b2544db0e2b3842c564",
|
|
222
222
|
"spec/v2/core/connection-packs.md": "1ee129d792c537bfe82393ccb92555d8e6ddc342b1aa781a13f101b27ec38171",
|
|
@@ -225,28 +225,29 @@
|
|
|
225
225
|
"spec/v2/core/events.md": "604abb6f9e2259a04103e1cb76d728712c3701c0d84dd915d4dc2949c912ee5e",
|
|
226
226
|
"spec/v2/core/form-content-packs.md": "02931227899676fd4581a27017be2a6c4953904717be9b81c29d12f87ab3917d",
|
|
227
227
|
"spec/v2/core/headers.md": "5cb1624fa63acc81992b6a6d842ec392cf7271aaf2f65d1f83c8c4fa286e6730",
|
|
228
|
-
"spec/v2/core/host-services.md": "
|
|
229
|
-
"spec/v2/core/i18n.md": "
|
|
228
|
+
"spec/v2/core/host-services.md": "8b920bf2e9335ab04452068429b0c37d6eb8872b380a4d53368f2600d4afa241",
|
|
229
|
+
"spec/v2/core/i18n.md": "2d5a67bd3b9b956d1144acab2fbc3646cdb50b3621f97d772087eaa953798286",
|
|
230
230
|
"spec/v2/core/idempotency.md": "2084d756789c1faf5121593fb39e67ca36a4c227178e175004742e403178ea49",
|
|
231
231
|
"spec/v2/core/identity.md": "2dceb1c2697015e4a4fa8a9b28f4fbd25fa44a76ca5a919c752e2a8163c819db",
|
|
232
232
|
"spec/v2/core/interop.md": "e72e25dff864c83b2980d7366b34054cffa072af0225821199f260f6228d260e",
|
|
233
233
|
"spec/v2/core/interrupt.md": "4c825634acac72900ebd3c5ac5941f55648fa33d2df92913ef16371dcb700a34",
|
|
234
234
|
"spec/v2/core/node-pack-runtimes.md": "e1088cb69b8c3c67256c494063328916c2980ab1aa97a7063de25bab82fdb1e5",
|
|
235
235
|
"spec/v2/core/oauth.md": "c96483a44b62978c596945fbb7d7c863cf6056cd980fdb4cf4e97555e3e10b72",
|
|
236
|
-
"spec/v2/core/overview.md": "
|
|
237
|
-
"spec/v2/core/packs.md": "
|
|
236
|
+
"spec/v2/core/overview.md": "c8c3bedb8e02dd8ce244b8a7a75d23af1c30dc92a343af912489424a89674d70",
|
|
237
|
+
"spec/v2/core/packs.md": "5929e708bd4e79f6e1beea570af583c80f3b63bb21dec78a5df03c235e73364a",
|
|
238
238
|
"spec/v2/core/persistence.md": "711874f74cb08b03cd118d683056db10a063517762fcea73ec70feb5d983e6a4",
|
|
239
239
|
"spec/v2/core/portability.md": "87c4327f674f714fda6217fd79b99d2ba219ad47dc02f9751bb56c200fb2c17a",
|
|
240
240
|
"spec/v2/core/replay.md": "4d379494057746c6883f6047972e93e621863b998ed291b9a691d3aa57c1ff43",
|
|
241
241
|
"spec/v2/core/runs.md": "55e21292ae4b41d0d104199a6c2634ecb3f787c4a671f9ebc37084be38ceef03",
|
|
242
242
|
"spec/v2/core/security-defaults.md": "153884da7a2d54c30c81b5e649cfdef31e151b3a2a19dee1bc5a16c35d60a3aa",
|
|
243
|
+
"spec/v2/core/storage.md": "598ad4f3775c297c698a20daf72a7d15a6836c1231ddbca5961865c704f765b5",
|
|
243
244
|
"spec/v2/core/tool-catalog.md": "d16a9004418719c48301804aefa4d7ab6f41112a4ed83727f552aa1b92b418b0",
|
|
244
245
|
"spec/v2/core/versioning.md": "e3b3ab6d76e51035039a32173e9b412628a52c8fe7b16687ff58a2d0d983faa0",
|
|
245
|
-
"spec/v2/core/webhooks.md": "
|
|
246
|
+
"spec/v2/core/webhooks.md": "d2d33c6be777f217ade3e15dd369849e5c6ce67e1a4417216f0aa6ec5bdecc56",
|
|
246
247
|
"spec/v2/core/workflow-chain-packs.md": "fdce7a8477e269950a2bac05ee6eddbd66eb0b670b464d00054f7196ec05d29c",
|
|
247
248
|
"spec/v2/corrections.json": "59f647f4d22477f6c2b06dcf913b682dde5d51dd5e607a5d0cf648ab60864d6e",
|
|
248
249
|
"spec/v2/corrections.schema.json": "46bbffb954d13bd9995aebc912ceeb2544f7064331abf25fd6ab85c81a5cec94",
|
|
249
|
-
"spec/v2/declaration.json": "
|
|
250
|
+
"spec/v2/declaration.json": "56c85c6d49f93d08d3bd48ccf1c049191cfbc4d4c22a1cd5202c1b6252759aca",
|
|
250
251
|
"spec/v2/declaration.schema.json": "ef951633e4070899f64828f5cf1b5f4870270a0360f81dbb49b5b4d6cd407550",
|
|
251
252
|
"spec/v2/errors.json": "fa650cbbdf25a140fdaf82ec5269f95b4585ac4bdde1fa6b0b3ffe48a3f7943c",
|
|
252
253
|
"spec/v2/errors.schema.json": "47404ad53e6147cf9017b813483712466573e419fb33e6c4b6c12d3e7deba1bc",
|
|
@@ -298,9 +299,9 @@
|
|
|
298
299
|
"spec/v2/path-manifest.json": "17298a245c5da9a70aa7ab0b7f2db4277e06209d6fcdd7187a8b4cea179c08f3",
|
|
299
300
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
300
301
|
"spec/v2/profiles.json": "180beb9ef2d161766fa23b2987e7e829851e3d316273147cf6a4a3f324befd6b",
|
|
301
|
-
"spec/v2/release.json": "
|
|
302
|
+
"spec/v2/release.json": "28b407019929da55701a718110d440f08899646af0b74d62f6adc5542c9c1c91",
|
|
302
303
|
"spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624",
|
|
303
|
-
"spec/v2/surface-baseline.json": "
|
|
304
|
+
"spec/v2/surface-baseline.json": "d0540276e74001f5058dd81909100ea6ee3c1925c6ac02918418f5ec941d0661"
|
|
304
305
|
},
|
|
305
|
-
"corpusCommit": "
|
|
306
|
+
"corpusCommit": "c486eafcfa16908a7b57c98b33cfd66fdf8e599d"
|
|
306
307
|
}
|
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.44.
|
|
4
|
+
version: 2.44.2
|
|
5
5
|
description: 'The OpenWOP conformance seams profile (`openwop-conformance-seams-v2`): test-only operations in their own
|
|
6
6
|
path space, `/conformance/seams/…`. The profile is versioned and validated against the canonical v2 schemas with no tolerance
|
|
7
7
|
path. It is not a capability: a host advertises the profile, never a `testSeams` flag.
|
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.44.
|
|
4
|
+
version: 2.44.2
|
|
5
5
|
description: 'OpenWOP v2 event streams over SSE. The run-events channel''s address is the OpenAPI path key, and the server
|
|
6
6
|
pathname is empty (bare origin). `streamMode` is a stream mode from the closed set, or a comma-separated combination of
|
|
7
7
|
them; `values` never combines. `hostEvents` has a default address, `/host/events`; a host MAY declare another under `heartbeat.deliveryChannel`.
|
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.44.
|
|
4
|
+
version: 2.44.2
|
|
5
5
|
summary: REST surface for declaring, executing, suspending, resuming, and observing multi-step workflows.
|
|
6
6
|
description: 'The OpenWOP v2 REST API. Paths are unversioned and served at the bare origin; a client selects a version with
|
|
7
7
|
the `OpenWOP-Version` header from the host''s `protocolVersions[]`. Conformance seams and test-mode operations are not
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/spec-artifacts",
|
|
3
|
-
"version": "2.44.
|
|
3
|
+
"version": "2.44.2",
|
|
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 — published from the openwop/openwop corpus tag; the peer dependency @openwop/openwop-conformance digest-checks at start (RFC 0168 §D.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.44.
|
|
7
|
+
"version": "2.44.2"
|
|
8
8
|
},
|
|
9
9
|
"note": "Derived from the corpus at generation time. Regenerate with --write; verify with --check."
|
|
10
10
|
},
|
|
@@ -421,5 +421,5 @@
|
|
|
421
421
|
"$id": "https://openwop.dev/spec/v1/workspace-file.schema.json"
|
|
422
422
|
}
|
|
423
423
|
],
|
|
424
|
-
"digest": "
|
|
424
|
+
"digest": "b26ed1f28f51c00d0ceb3c5e479bee4d9d7daba38334b3cec14b06a0bbcb3e9a"
|
|
425
425
|
}
|
package/spec/v2/README.md
CHANGED
|
@@ -32,7 +32,7 @@ when v1 ends.
|
|
|
32
32
|
| --- | --- |
|
|
33
33
|
| Foundation | [`overview`](./core/overview.md), [`versioning`](./core/versioning.md), [`headers`](./core/headers.md), [`identity`](./core/identity.md), [`oauth`](./core/oauth.md), [`capabilities`](./core/capabilities.md), [`i18n`](./core/i18n.md) |
|
|
34
34
|
| Execution | [`runs`](./core/runs.md), [`events`](./core/events.md), [`interrupt`](./core/interrupt.md), [`conversation`](./core/conversation.md), [`persistence`](./core/persistence.md), [`idempotency`](./core/idempotency.md), [`replay`](./core/replay.md) |
|
|
35
|
-
| Integration | [`webhooks`](./core/webhooks.md), [`interop`](./core/interop.md), [`host services`](./core/host-services.md), [`tool catalog`](./core/tool-catalog.md), [`portability`](./core/portability.md), [`packs`](./core/packs.md), [`node-pack runtimes`](./core/node-pack-runtimes.md), [`connection packs`](./core/connection-packs.md), [`form-content packs`](./core/form-content-packs.md), [`workflow-chain packs`](./core/workflow-chain-packs.md) |
|
|
35
|
+
| Integration | [`webhooks`](./core/webhooks.md), [`interop`](./core/interop.md), [`host services`](./core/host-services.md), [`storage`](./core/storage.md), [`tool catalog`](./core/tool-catalog.md), [`portability`](./core/portability.md), [`packs`](./core/packs.md), [`node-pack runtimes`](./core/node-pack-runtimes.md), [`connection packs`](./core/connection-packs.md), [`form-content packs`](./core/form-content-packs.md), [`workflow-chain packs`](./core/workflow-chain-packs.md) |
|
|
36
36
|
| Reliability | [`errors`](./core/errors.md), [`security defaults`](./core/security-defaults.md), [`conformance`](./core/conformance.md) |
|
|
37
37
|
|
|
38
38
|
## Source-of-truth map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Host services
|
|
2
2
|
|
|
3
3
|
> **Status: Stable.**
|
|
4
|
-
> **Normative home:** `aiEnvelope`, `promptLibrary`, `agentRuntime`, `mcp`.
|
|
4
|
+
> **Normative home:** `aiEnvelope`, `promptLibrary`, `agentRuntime`, `mcp`, `workspace`.
|
|
5
5
|
|
|
6
6
|
## Why this exists
|
|
7
7
|
|
|
@@ -38,4 +38,17 @@ Each rejects only for an unknown `serverId` (`not_found`), an MCP error response
|
|
|
38
38
|
- `readResource` resolves to the `ReadResourceResult` unaltered.
|
|
39
39
|
- `serverHealth` MUST report `reachable`, `unreachable` or `incompatible` from a `server/discover` probe no older than its `ttlMs`, with the `DiscoverResult` when one was received. It MUST NOT report a connection or session state, which MCP 2026-07-28 does not have.
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
## `workspace`
|
|
42
|
+
|
|
43
|
+
A host advertising `workspace` keeps agent files (`schemas/v2/workspace-file.schema.json`) scoped to one `{tenant, workspace}`; no protocol path is defined for them. The host:
|
|
44
|
+
|
|
45
|
+
- MUST make each write atomic, bumping `version`, and emit `workspace.updated` on each write or delete; a versioned delete leaves a tombstone;
|
|
46
|
+
- MUST refuse a stale `If-Match` etag with `409 workspace_conflict` (`details.currentVersion`), and content over `maxFileBytes` with `workspace_too_large`;
|
|
47
|
+
- with `versioned`, MUST serve the latest and any retained version, retaining best-effort up to `maxVersions`; `maxFiles` caps the file count;
|
|
48
|
+
- MUST give a run, through `ctx.workspace`, an immutable snapshot taken at `run.started`, so a replay on any host sees the same files; its writes reach later runs only;
|
|
49
|
+
- MUST derive the scope from the authenticated identity and MUST NOT return or disclose another scope's file; `404` MAY stand for `403` (invariant `workspace-cross-tenant-isolation`);
|
|
50
|
+
- MUST persist `[REDACTED:<secretId>]` for any value the run's vault resolved at user, tenant or run scope (longest first, 8-character minimum).
|
|
51
|
+
|
|
52
|
+
A workflow calling `ctx.workspace` MUST NOT register on a host without the family. The memory-index manifest is the workspace file `MEMORY-INDEX.json`.
|
|
53
|
+
|
|
54
|
+
*Sources: RFCs 0059, 0144.*
|
package/spec/v2/core/i18n.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Internationalization
|
|
2
2
|
|
|
3
3
|
> **Status: Stable.**
|
|
4
|
-
> **Normative home:** `i18n`.
|
|
4
|
+
> **Normative home:** `i18n`, `content`.
|
|
5
5
|
|
|
6
6
|
## Why this exists
|
|
7
7
|
|
|
@@ -57,8 +57,18 @@ A host that negotiates locale SHOULD advertise `i18n`. A host advertising it hon
|
|
|
57
57
|
|
|
58
58
|
Locale is chosen at request time. `Content-Language` is request-scoped and not recorded in the event log, so a replay re-projects the recorded text and does not re-render it. A fork localizes by its own request's `Accept-Language`, not the parent run's.
|
|
59
59
|
|
|
60
|
+
## Localized content
|
|
61
|
+
|
|
62
|
+
A host advertising `content` serves authored pages (`schemas/v2/localized-content-*.schema.json`) on the `/content/*` operations. A section is one record, base `data` plus sparse `localizations`, never one per locale.
|
|
63
|
+
|
|
64
|
+
- A host advertising `content` MUST advertise `i18n`, with `content.baseLocale` equal to `i18n.defaultLocale` and every locale in `baseLocale` ∪ `supportedLocales` also in `i18n.supportedLocales`. It SHOULD advertise only locales it delivers, in the case §Language tags recommends.
|
|
65
|
+
- Delivery negotiates locale only by `Accept-Language` (§Fallback); a `?locale=` parameter is not defined. A section negotiated to `baseLocale` resolves to `data`; otherwise to `data` shallowly overlaid by the first `localizations` entry for the exact tag, its `ll-Ssss` script family, or its language, else `data` alone. Every host MUST resolve identically.
|
|
66
|
+
- A write names its locale in the body: `baseLocale` upserts `data`, any other its overlay.
|
|
67
|
+
- Publication is atomic across locales. Public delivery MUST serve published content only and MUST NOT cache a draft in a shared entry.
|
|
68
|
+
- Every read and write MUST be tenant-scoped; another tenant's id MUST get the same `404` as a missing one. Anonymous tenant resolution is host-defined, so identical resolution holds per resolved `(tenant, locale)`.
|
|
69
|
+
|
|
60
70
|
## Clients
|
|
61
71
|
|
|
62
72
|
A client that wants localized content MUST check discovery for `i18n` before sending `Accept-Language`. A host that does not advertise it ignores the header and returns its default locale.
|
|
63
73
|
|
|
64
|
-
*Sources:
|
|
74
|
+
*Sources: RFCs 0103, 0206.*
|
package/spec/v2/core/overview.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
6. [`events.md`](events.md), [`errors.md`](errors.md), [`headers.md`](headers.md) — event `oneOf`, payload and error registries, `OpenWOP-*` headers
|
|
17
17
|
7. [`interrupt.md`](interrupt.md), [`idempotency.md`](idempotency.md), [`replay.md`](replay.md), [`conversation.md`](conversation.md) — run-side surfaces
|
|
18
18
|
8. [`persistence.md`](persistence.md) — era key, v1 reader rule, pinned runs
|
|
19
|
-
9. [`security-defaults.md`](security-defaults.md), [`webhooks.md`](webhooks.md), [`interop.md`](interop.md), [`host-services.md`](host-services.md), [`tool-catalog.md`](tool-catalog.md), [`i18n.md`](i18n.md), [`portability.md`](portability.md) — surface obligations, signatures, A2A and MCP, host services, locale, estate export
|
|
19
|
+
9. [`security-defaults.md`](security-defaults.md), [`webhooks.md`](webhooks.md), [`interop.md`](interop.md), [`host-services.md`](host-services.md), [`storage.md`](storage.md), [`tool-catalog.md`](tool-catalog.md), [`i18n.md`](i18n.md), [`portability.md`](portability.md) — surface obligations, signatures, A2A and MCP, host services, storage, locale, estate export
|
|
20
20
|
10. [`packs.md`](packs.md), [`node-pack-runtimes.md`](node-pack-runtimes.md), [`connection-packs.md`](connection-packs.md), [`form-content-packs.md`](form-content-packs.md), [`workflow-chain-packs.md`](workflow-chain-packs.md) — pack identity, engines ceiling
|
|
21
21
|
11. [`conformance.md`](conformance.md) — requirement ids, witness classes, bundle v3, seams profile
|
|
22
22
|
|
package/spec/v2/core/packs.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Packs
|
|
2
2
|
|
|
3
3
|
> **Status: Stable.**
|
|
4
|
-
> **Normative home:** `packs`.
|
|
4
|
+
> **Normative home:** `packs`, `uiPlugins`.
|
|
5
5
|
|
|
6
6
|
## Why this exists
|
|
7
7
|
|
|
@@ -113,9 +113,24 @@ A registry MUST validate submissions against vendored copies of these schemas pi
|
|
|
113
113
|
| `pack_peer_dependency_undefined` | a peer-dependency key is not a declaration-file key or an overlap alias |
|
|
114
114
|
| `pack_signature_invalid` | the signature, key, or namespace check fails |
|
|
115
115
|
|
|
116
|
+
## Front-end plugin packs
|
|
117
|
+
|
|
118
|
+
A `frontend-plugin` pack (`schemas/v2/frontend-plugin-manifest.schema.json`) ships opaque UI bundles that reach the host only over `ui-plugin/1` (`schemas/v2/ui-plugin-message.schema.json`); both schemas' rules bind. A host advertising `uiPlugins`:
|
|
119
|
+
|
|
120
|
+
- MUST verify the pack signature before loading, failing closed;
|
|
121
|
+
- MUST run every entry sandboxed from host context, DOM, origin storage and credentials, whatever `uiPlugins.isolation` names; never in-process, same-origin or federated (invariant `frontend-plugin-isolation`);
|
|
122
|
+
- MUST serve a deny-egress policy apart from declared `connectSrc` (invariant `frontend-plugin-egress`), and let no BYOK material cross the boundary (invariant `frontend-plugin-no-byok`);
|
|
123
|
+
- MUST ignore a message whose version tag it does not know, and refuse a method outside both allowlists with `method_not_allowed`, authorizing every call itself;
|
|
124
|
+
- with `artifact.write`, MUST return an opaque `version` from each read and write and refuse a stale one with `artifact_conflict`, persisting nothing;
|
|
125
|
+
- MUST treat a plugin needing an unadvertised `surfaces` or `hostApi` entry as inert there, not an error.
|
|
126
|
+
|
|
127
|
+
A host without `uiPlugins` MUST reject the pack and render its own way.
|
|
128
|
+
|
|
129
|
+
A breaking method change is `ui-plugin/2`. `host.announce` MUST be length-capped (SHOULD ≤ 400 characters) and SHOULD be rate-limited; `host.documentChanged` SHOULD be debounced, and a plugin MUST treat the latest as authoritative and tolerate unknown `host.selectionChanged` kinds. `maxEntryBytes` caps an entry bundle.
|
|
130
|
+
|
|
116
131
|
## During the v1 overlap
|
|
117
132
|
|
|
118
133
|
- The v1 registry tree is frozen through the overlap, behind the v2 tree.
|
|
119
134
|
- `testMode` advertises the v1 `/v1/packs-test/*` mirror, a conformance seam ([conformance.md §"The seams profile"](conformance.md)). It remains advertisable through the overlap and is removed at 3.0.
|
|
120
135
|
|
|
121
|
-
*Sources: RFCs 0177, 0212, 0222.*
|
|
136
|
+
*Sources: RFCs 0117, 0119, 0130, 0177, 0212, 0222.*
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Storage
|
|
2
|
+
|
|
3
|
+
> **Status: Stable.**
|
|
4
|
+
> **Normative home:** `fs`, `kvStorage`, `tableStorage`, `sql`, `nosql`, `vectorStore`, `searchIndex`, `blobStorage`, `cache`.
|
|
5
|
+
|
|
6
|
+
## Why this exists
|
|
7
|
+
|
|
8
|
+
A node pack keeps files, records and indexes in storage services the host provides, reached through `ctx` ([host-services.md](host-services.md)). This document states what a host takes on by advertising one.
|
|
9
|
+
|
|
10
|
+
## Operations
|
|
11
|
+
|
|
12
|
+
A host advertising a family MUST expose each of its operations to pack code, returning at least the fields shown; it MAY return more. An operation marked † is required only when the named facet is `true`.
|
|
13
|
+
|
|
14
|
+
| Family | Operations |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `fs` (`ctx.fs`) | `read(path) → bytes, contentType?` · `write(path, bytes, contentType?) → path, sizeBytes` · `delete(path) → deleted` · `stat(path) → sizeBytes, modifiedAt, contentType?` · `list(prefix?, cursor?, limit?) → entries[path, sizeBytes], nextCursor?` |
|
|
17
|
+
| `kvStorage` (`ctx.storage.kv`) | `get(key) → value?, expiresAt?` · `put(key, value, ttlSeconds?) → ok` · `delete(key) → deleted` · `list(prefix?, cursor?, limit?) → entries[key], nextCursor?` · † `atomicIncrement(key, delta?) → value` · † `compareAndSwap(key, expectedValue, newValue) → swapped` |
|
|
18
|
+
| `tableStorage` (`ctx.storage.table`) | `createTable(name, schema) → ok` · `insert(table, row) → rowId` · `get(table, rowId) → row?` · `query(table, filter?, cursor?, limit?) → rows, nextCursor?` · `update(table, rowId, patch) → ok` · `delete(table, rowId) → deleted` |
|
|
19
|
+
| `sql` (`ctx.db.sql`) | `query(datasourceId, sql, params) → rows, rowCount` · `execute(datasourceId, sql, params) → rowsAffected` · † `transaction(datasourceId, operations[sql, params]) → committed` |
|
|
20
|
+
| `nosql` (`ctx.db.nosql`) | `insert(datasourceId, collection, doc) → id` · `get(…, id) → doc?` · `query(…, filter, cursor?, limit?) → docs, nextCursor?` · `update(…, id, patch) → ok` · `delete(…, id) → deleted` |
|
|
21
|
+
| `vectorStore` (`ctx.db.vector`) | `upsert(collection, vectors[id, embedding, metadata?]) → upserted` · `query(collection, embedding, k, filter?) → matches[id, score, metadata?]` · `delete(collection, ids) → deleted` |
|
|
22
|
+
| `searchIndex` (`ctx.db.search`) | `index(index, docs[id, fields]) → indexed` · `query(index, q, k?, filter?) → hits[id, score, fields?]` · `delete(index, ids) → deleted` |
|
|
23
|
+
| `blobStorage` (`ctx.storage.blob`) | `put(bucket, key, bytes, contentType?) → url, sizeBytes` · `get(bucket, key) → bytes, contentType?` · `delete(bucket, key) → deleted` · `list(bucket, prefix?, cursor?) → entries[key, sizeBytes], nextCursor?` · † `presign(bucket, key, expiresInSeconds, method) → url, expiresAt` |
|
|
24
|
+
| `cache` (`ctx.storage.cache`) | `get(key) → value?, expiresAt?` · `put(key, value, ttlSeconds) → ok` · `delete(key) → deleted` |
|
|
25
|
+
|
|
26
|
+
The facets are `kvStorage.atomicIncrement` and `kvStorage.compareAndSwap`, `sql.transactions`, and `blobStorage.presignSupported`. `presign` takes `method` `GET` or `PUT`, and `…` in a `nosql` row repeats `datasourceId, collection`.
|
|
27
|
+
|
|
28
|
+
## Shared rules
|
|
29
|
+
|
|
30
|
+
- **Tenant isolation.** A read for one tenant MUST NOT return data another tenant wrote, even under an identical key or name: `kvStorage` `get` and `list`, `tableStorage` `get` and `query`, `vectorStore` and `searchIndex` `query`, `blobStorage` and `cache` `get`.
|
|
31
|
+
- **Datasources.** `sql` and `nosql` datasources are scoped per tenant, and access to another tenant's datasource MUST be refused.
|
|
32
|
+
- **Backend-invariant.** The operation shapes of `sql` and `nosql` MUST NOT vary with the advertised `drivers`, nor those of `vectorStore` and `searchIndex` with the advertised `backends`. A host MAY back `sql` with any driver it advertises.
|
|
33
|
+
- **Size limits.** A key over `kvStorage.maxKeyBytes`, and a write over `fs.maxFileSizeBytes`, `kvStorage.maxValueBytes`, `blobStorage.maxObjectBytes` or `cache.maxValueBytes`, MUST be refused. A `tableStorage` insert MUST be refused once `maxRowsPerTable` is reached.
|
|
34
|
+
- **Expiry.** `kvStorage` and `cache` MUST honour an entry's expiry, as a read sees it, with at most one second of drift. `maxTtlSeconds` caps `ttlSeconds` for each.
|
|
35
|
+
|
|
36
|
+
What a family advertises also names its targets: `sql.datasources`, `nosql.datasources`, `vectorStore.collections`, `searchIndex.indexes` and `blobStorage.buckets`. `tableStorage` advertises `maxColumnsPerRow`, `indexable` and `fullTextSearch` as limits and features, with no further rule.
|
|
37
|
+
|
|
38
|
+
No error code specific to these families is registered; [errors.md](errors.md) governs the code a refused call carries.
|
|
39
|
+
|
|
40
|
+
## `fs`
|
|
41
|
+
|
|
42
|
+
- Every `path` MUST be normalized and resolved relative to `fs.sandboxRoot`.
|
|
43
|
+
- A path that escapes the root, whether absolute, through `..` segments or through a symlink, MUST be refused. The host MUST NOT follow such a link partially.
|
|
44
|
+
- A permission denial MUST fail the call, never succeed silently or fall through.
|
|
45
|
+
- A read of a file over `maxFileSizeBytes` MAY fail rather than stream.
|
|
46
|
+
- The `image` (with its `formats`), `pdf` and `transport` (`ftp`, `sftp`, `ssh`) sub-surfaces are optional, and gate the pack delegates that use them.
|
|
47
|
+
|
|
48
|
+
## `kvStorage`
|
|
49
|
+
|
|
50
|
+
- When `atomicIncrement` is `true`, increments MUST be atomic across concurrent callers.
|
|
51
|
+
- When `compareAndSwap` is `true`, a swap MUST be atomic, with no read-modify-write race. A stale `expectedValue` returns `swapped: false` without mutation.
|
|
52
|
+
|
|
53
|
+
## `tableStorage`
|
|
54
|
+
|
|
55
|
+
- Rows MUST conform to the table's declared schema: an insert or update whose column types diverge from it MUST be refused.
|
|
56
|
+
- `query` MUST support cursor pagination, and `nextCursor` MUST be opaque and stable across calls.
|
|
57
|
+
|
|
58
|
+
## `sql` and `nosql`
|
|
59
|
+
|
|
60
|
+
- `sql` MUST be treated as a parametric template: bound values MUST flow through `params`, never through string interpolation. A host SHOULD verify parameter binding before execution, and a pack MUST NOT concatenate user input into `sql`.
|
|
61
|
+
- When `sql.transactions` is `true`, a partial failure inside `transaction` MUST roll back the whole batch.
|
|
62
|
+
- `nosql` filter operators MUST NOT permit injection. Server-side script evaluation, such as MongoDB `$where`, MUST be refused unless an explicit allowlist is configured.
|
|
63
|
+
|
|
64
|
+
## `vectorStore` and `searchIndex`
|
|
65
|
+
|
|
66
|
+
- `vectorStore`: an `upsert` followed by a `query` with the same embedding MUST return the inserted ids in the top `k` matches when `k` is at least the number inserted.
|
|
67
|
+
- `searchIndex`: an `index` followed by a `query` with a substring of an indexed field MUST return the indexed id with `score` above 0.
|
|
68
|
+
|
|
69
|
+
## `blobStorage`
|
|
70
|
+
|
|
71
|
+
Presigned URLs MUST expire at the advertised TTL. A presigned request after expiry MUST fail at the storage layer, not after an authorization skip.
|
|
72
|
+
|
|
73
|
+
*Sources: RFCs 0014, 0015, 0016, 0018, 0019.*
|
package/spec/v2/core/webhooks.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Webhooks
|
|
2
2
|
|
|
3
3
|
> **Status: Stable.**
|
|
4
|
-
> **Normative home:** `webhooks`.
|
|
4
|
+
> **Normative home:** `webhooks`, `triggerBridge`.
|
|
5
5
|
|
|
6
6
|
## Why this exists
|
|
7
7
|
|
|
@@ -122,6 +122,24 @@ Address classification:
|
|
|
122
122
|
|
|
123
123
|
At delivery time a host MUST re-resolve the hostname, validate every resolved address against the same denied ranges plus its own denylist, connect to the validated address without re-resolving, and refuse to follow redirects (invariant `webhook-delivery-egress-revalidation`, reference-impl tier). These delivery-time rules bind an A2A push identically (interop.md §"A2A push delivery").
|
|
124
124
|
|
|
125
|
+
## Inbound triggers
|
|
126
|
+
|
|
127
|
+
A host advertising `triggerBridge` runs inbound work through subscriptions (`schemas/v2/trigger-subscription.schema.json`) that are `active`, `paused` (not delivering; a schedule skips ticks), `failed`, or `dead-lettered` (deliveries in the `deadLetter` sink); `subscriptionStates` lists those it implements. On an `active` subscription the host:
|
|
128
|
+
|
|
129
|
+
- with `dedup`, MUST answer a `dedupKey` repeated within retention (at least 24 hours) with the prior `runId`;
|
|
130
|
+
- retries per `retryPolicy`, then dead-letters, starting no run;
|
|
131
|
+
- MUST set the delivery id as `causationId` on `run.started`.
|
|
132
|
+
|
|
133
|
+
A source in `triggerBridge.sources` MUST run through these states and emit `trigger.subscription-state-changed` and `trigger.delivery-attempted`, which MUST NOT carry inbound content or credentials (`schemas/v2/run-event-payloads.schema.json`).
|
|
134
|
+
|
|
135
|
+
With `triggerBridge.ingestion`, each `externalSources` entry MUST turn an external event into a `TriggerEvent` (`schemas/v2/trigger-event.schema.json`, whose rules bind) and start a run. The host:
|
|
136
|
+
|
|
137
|
+
- MUST verify per `verification` before delivery; a failed `required` check dead-letters with reason `signature-invalid`;
|
|
138
|
+
- returns a binding secret or URL once; `stream` and `change` bindings are empty;
|
|
139
|
+
- MUST pass the event only as `ctx.triggerData`, never in an event, and replay it from cache (invariant `trigger-ingestion-content-redaction`);
|
|
140
|
+
- MUST refuse private, link-local and loopback targets and cap the body on any ingestion fetch, and never hand the run a URL (invariant `trigger-ingestion-ssrf`);
|
|
141
|
+
- SHOULD key `stream` by topic, partition and offset, `change` by table and changelog id; a key MUST survive broker redelivery.
|
|
142
|
+
|
|
125
143
|
See also: events.md, replay.md, persistence.md, security-defaults.md.
|
|
126
144
|
|
|
127
|
-
*Sources: RFCs 0053, 0165, 0171, 0173, 0176, 0188, 0196, 0201, 0215, 0217.*
|
|
145
|
+
*Sources: RFCs 0053, 0083, 0099, 0127, 0165, 0171, 0173, 0176, 0188, 0196, 0201, 0215, 0217.*
|
package/spec/v2/declaration.json
CHANGED
|
@@ -819,7 +819,7 @@
|
|
|
819
819
|
{
|
|
820
820
|
"key": "fs",
|
|
821
821
|
"kind": "family",
|
|
822
|
-
"normativeText": ["spec/
|
|
822
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
823
823
|
"anchor": "core",
|
|
824
824
|
"section": "core/capabilities.md#fs",
|
|
825
825
|
"peerDependencyId": "fs",
|
|
@@ -842,7 +842,7 @@
|
|
|
842
842
|
{
|
|
843
843
|
"key": "kvStorage",
|
|
844
844
|
"kind": "family",
|
|
845
|
-
"normativeText": ["spec/
|
|
845
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
846
846
|
"anchor": "core",
|
|
847
847
|
"section": "core/capabilities.md#kvStorage",
|
|
848
848
|
"peerDependencyId": "kvStorage",
|
|
@@ -865,7 +865,7 @@
|
|
|
865
865
|
{
|
|
866
866
|
"key": "tableStorage",
|
|
867
867
|
"kind": "family",
|
|
868
|
-
"normativeText": ["spec/
|
|
868
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
869
869
|
"anchor": "core",
|
|
870
870
|
"section": "core/capabilities.md#tableStorage",
|
|
871
871
|
"peerDependencyId": "tableStorage",
|
|
@@ -1162,7 +1162,7 @@
|
|
|
1162
1162
|
{
|
|
1163
1163
|
"key": "triggerBridge",
|
|
1164
1164
|
"kind": "family",
|
|
1165
|
-
"normativeText": ["spec/
|
|
1165
|
+
"normativeText": ["spec/v2/core/webhooks.md"],
|
|
1166
1166
|
"anchor": "core",
|
|
1167
1167
|
"section": "core/capabilities.md#triggerBridge",
|
|
1168
1168
|
"peerDependencyId": "triggerBridge",
|
|
@@ -1254,7 +1254,7 @@
|
|
|
1254
1254
|
{
|
|
1255
1255
|
"key": "workspace",
|
|
1256
1256
|
"kind": "family",
|
|
1257
|
-
"normativeText": ["spec/
|
|
1257
|
+
"normativeText": ["spec/v2/core/host-services.md"],
|
|
1258
1258
|
"anchor": "core",
|
|
1259
1259
|
"section": "core/capabilities.md#workspace",
|
|
1260
1260
|
"peerDependencyId": "workspace",
|
|
@@ -1276,7 +1276,7 @@
|
|
|
1276
1276
|
{
|
|
1277
1277
|
"key": "uiPlugins",
|
|
1278
1278
|
"kind": "family",
|
|
1279
|
-
"normativeText": ["spec/
|
|
1279
|
+
"normativeText": ["spec/v2/core/packs.md"],
|
|
1280
1280
|
"anchor": "core",
|
|
1281
1281
|
"section": "core/capabilities.md#uiPlugins",
|
|
1282
1282
|
"peerDependencyId": "uiPlugins",
|
|
@@ -1298,7 +1298,7 @@
|
|
|
1298
1298
|
{
|
|
1299
1299
|
"key": "sql",
|
|
1300
1300
|
"kind": "family",
|
|
1301
|
-
"normativeText": ["spec/
|
|
1301
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1302
1302
|
"anchor": "core",
|
|
1303
1303
|
"section": "core/capabilities.md#sql",
|
|
1304
1304
|
"peerDependencyId": "sql",
|
|
@@ -1319,7 +1319,7 @@
|
|
|
1319
1319
|
{
|
|
1320
1320
|
"key": "nosql",
|
|
1321
1321
|
"kind": "family",
|
|
1322
|
-
"normativeText": ["spec/
|
|
1322
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1323
1323
|
"anchor": "core",
|
|
1324
1324
|
"section": "core/capabilities.md#nosql",
|
|
1325
1325
|
"peerDependencyId": "nosql",
|
|
@@ -1339,7 +1339,7 @@
|
|
|
1339
1339
|
{
|
|
1340
1340
|
"key": "vectorStore",
|
|
1341
1341
|
"kind": "family",
|
|
1342
|
-
"normativeText": ["spec/
|
|
1342
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1343
1343
|
"anchor": "core",
|
|
1344
1344
|
"section": "core/capabilities.md#vectorStore",
|
|
1345
1345
|
"peerDependencyId": "vectorStore",
|
|
@@ -1359,7 +1359,7 @@
|
|
|
1359
1359
|
{
|
|
1360
1360
|
"key": "searchIndex",
|
|
1361
1361
|
"kind": "family",
|
|
1362
|
-
"normativeText": ["spec/
|
|
1362
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1363
1363
|
"anchor": "core",
|
|
1364
1364
|
"section": "core/capabilities.md#searchIndex",
|
|
1365
1365
|
"peerDependencyId": "searchIndex",
|
|
@@ -1379,7 +1379,7 @@
|
|
|
1379
1379
|
{
|
|
1380
1380
|
"key": "blobStorage",
|
|
1381
1381
|
"kind": "family",
|
|
1382
|
-
"normativeText": ["spec/
|
|
1382
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1383
1383
|
"anchor": "core",
|
|
1384
1384
|
"section": "core/capabilities.md#blobStorage",
|
|
1385
1385
|
"peerDependencyId": "blobStorage",
|
|
@@ -1400,7 +1400,7 @@
|
|
|
1400
1400
|
{
|
|
1401
1401
|
"key": "cache",
|
|
1402
1402
|
"kind": "family",
|
|
1403
|
-
"normativeText": ["spec/
|
|
1403
|
+
"normativeText": ["spec/v2/core/storage.md"],
|
|
1404
1404
|
"anchor": "core",
|
|
1405
1405
|
"section": "core/capabilities.md#cache",
|
|
1406
1406
|
"peerDependencyId": "cache",
|
|
@@ -1669,7 +1669,7 @@
|
|
|
1669
1669
|
{
|
|
1670
1670
|
"key": "content",
|
|
1671
1671
|
"kind": "family",
|
|
1672
|
-
"normativeText": ["spec/
|
|
1672
|
+
"normativeText": ["spec/v2/core/i18n.md"],
|
|
1673
1673
|
"anchor": "core",
|
|
1674
1674
|
"section": "core/capabilities.md#content",
|
|
1675
1675
|
"peerDependencyId": "content",
|
package/spec/v2/release.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "RFC 0172 §D.1 — 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.44.
|
|
4
|
-
"corpusTag": "v2.44.
|
|
3
|
+
"version": "2.44.2",
|
|
4
|
+
"corpusTag": "v2.44.2",
|
|
5
5
|
"updated": "2026-09-28"
|
|
6
6
|
}
|