@openwop/openwop-conformance 1.161.0 → 1.163.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.
- package/dist/cli.js +1 -1
- package/package.json +1 -1
- package/requirements.json +61 -61
- package/schemas/CORPUS-STAMP.json +3 -3
- package/schemas/capabilities.schema.json +328 -292
- package/src/cli.ts +1 -1
|
@@ -13,19 +13,27 @@
|
|
|
13
13
|
"properties": {
|
|
14
14
|
"protocolVersion": {
|
|
15
15
|
"type": "string",
|
|
16
|
-
"description": "RFC 0149
|
|
16
|
+
"description": "RFC 0149 §C — openwop protocol version the server speaks, as ASCII `<major>.<minor>` with no leading zero except zero itself. `1.0` and `1.12` are valid; `1`, `1.0.0`, `v1.0`, and `01.0` are not. The integer major is the hard compatibility boundary and the integer minor is the additive contract level; PATCH belongs to suite and SDK versions, not the spec version. Previously constrained only by `minLength: 1`, which admitted `v1.0`, `1.0.0`, and `banana` — a negotiation the wire could not decide, since neither integer can be extracted from an unconstrained string. Independent of `engineVersion` (which gates persisted-doc compatibility per version-negotiation.md).",
|
|
17
17
|
"pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
|
|
18
18
|
},
|
|
19
19
|
"protocolVersions": {
|
|
20
20
|
"type": "array",
|
|
21
21
|
"minItems": 1,
|
|
22
22
|
"uniqueItems": true,
|
|
23
|
-
"items": {
|
|
24
|
-
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
|
|
26
|
+
},
|
|
27
|
+
"description": "RFC 0165 §A. Every protocol `<major>.<minor>` this host speaks, newest first by convention. OPTIONAL in v1.x; when present it MUST contain the value of `protocolVersion` and MUST NOT name a major the host does not serve. Same grammar as `protocolVersion` (RFC 0149 §C), not the looser A2A item pattern. Consumers that do not understand it ignore it; profile derivation reads `protocolVersion` only. Reserved for v2 major negotiation."
|
|
28
|
+
},
|
|
29
|
+
"preferredVersion": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$",
|
|
32
|
+
"description": "RFC 0179 §A.1 (v1.x additive half of RFC 0172 §A.1). The `<major>.<minor>` this host serves to a header-less request. OPTIONAL in v1.x; when present MUST be a member of `protocolVersions[]` (when present) and, on a host serving a single major, MUST equal `protocolVersion`. Required at v2 with `OpenWOP-Version` negotiation."
|
|
25
33
|
},
|
|
26
34
|
"contractProvenance": {
|
|
27
35
|
"type": "object",
|
|
28
|
-
"description": "RFC 0146 (`Active`). Which corpus revision this host's contract handling corresponds to
|
|
36
|
+
"description": "RFC 0146 (`Active`). Which corpus revision this host's contract handling corresponds to — the copy it validates and serves against. OPTIONAL; absent ⇒ UNSPECIFIED provenance, neither current nor stale, and a consumer MUST NOT infer a version from its absence. ADVISORY: a consumer MUST NOT reject a request, refuse interop, or fail a run solely because this differs from its own — v1.x corpus revisions are additive, so a host on an older revision is conformant and this field detects drift rather than making drift an error. Nothing else on the wire answers this: `protocolVersion` is `1.0` across the entire v1 line (the drift happens inside that value) and `schemaVersions` is per-envelope-type. NOT an integrity check — `corpusCommit` says WHICH contract, never whether the copy was modified.",
|
|
29
37
|
"properties": {
|
|
30
38
|
"suiteVersion": {
|
|
31
39
|
"type": "string",
|
|
@@ -34,7 +42,7 @@
|
|
|
34
42
|
},
|
|
35
43
|
"corpusCommit": {
|
|
36
44
|
"type": "string",
|
|
37
|
-
"description": "Full 40-character commit SHA of the openwop repository. A vendor build identifier does NOT belong here
|
|
45
|
+
"description": "Full 40-character commit SHA of the openwop repository. A vendor build identifier does NOT belong here — `implementation` already exists for that.",
|
|
38
46
|
"pattern": "^[0-9a-f]{40}$"
|
|
39
47
|
}
|
|
40
48
|
},
|
|
@@ -107,11 +115,11 @@
|
|
|
107
115
|
"maxRequestBodyBytes": {
|
|
108
116
|
"type": "integer",
|
|
109
117
|
"minimum": 1,
|
|
110
|
-
"description": "RFC 0094
|
|
118
|
+
"description": "RFC 0094 §H. Maximum REST request body size (bytes) the host accepts. Optional v1 field per `capabilities.md` §3 (previously documented as reserved — the closed `limits` object made advertising it a schema-validation failure). Hosts that advertise it MUST enforce it."
|
|
111
119
|
}
|
|
112
120
|
},
|
|
113
121
|
"additionalProperties": false,
|
|
114
|
-
"description": "Hard limits enforced by the engine. See capabilities.md
|
|
122
|
+
"description": "Hard limits enforced by the engine. See capabilities.md §3."
|
|
115
123
|
},
|
|
116
124
|
"envelopeStrictness": {
|
|
117
125
|
"type": "string",
|
|
@@ -119,11 +127,11 @@
|
|
|
119
127
|
"warn",
|
|
120
128
|
"strict"
|
|
121
129
|
],
|
|
122
|
-
"description": "AI Envelope schema-version drift handling per `spec/v1/ai-envelope.md`
|
|
130
|
+
"description": "AI Envelope schema-version drift handling per `spec/v1/ai-envelope.md` §\"Capability handshake integration\" (DRAFT v1.x). Optional in v1.x; default when absent is `warn`. Under `warn`, the engine MUST attempt validation against the advertised version of a kind and log `envelope_schema_version_drift` when the emitted `schemaVersion` is lower than advertised. Under `strict`, the same condition MUST cause refusal with `unknown_schema_version`. Emitted `schemaVersion` higher than advertised MUST refuse regardless of strictness."
|
|
123
131
|
},
|
|
124
132
|
"envelopeContracts": {
|
|
125
133
|
"type": "object",
|
|
126
|
-
"description": "AI Envelope contract-gating advertisement per `spec/v1/ai-envelope.md`
|
|
134
|
+
"description": "AI Envelope contract-gating advertisement per `spec/v1/ai-envelope.md` §\"Capability handshake integration\" (DRAFT v1.x). Optional in v1.x. When `advertised: true`, the host's node-pack manifests carry `EnvelopeContract` blocks per `ai-envelope.md` §\"Envelope Contract\"; tooling and conformance scenarios gate on this flag. When `advertised: false` or the block is absent, hosts MAY accept envelopes without per-typeId `accepts[]` enforcement.",
|
|
127
135
|
"required": [
|
|
128
136
|
"advertised"
|
|
129
137
|
],
|
|
@@ -137,12 +145,12 @@
|
|
|
137
145
|
},
|
|
138
146
|
"envelopes": {
|
|
139
147
|
"type": "object",
|
|
140
|
-
"description": "Envelope LLM-contract advertisement container introduced by the RFC 0030
|
|
148
|
+
"description": "Envelope LLM-contract advertisement container introduced by the RFC 0030–0033 envelope-hardening track. Each sub-block is independently opt-in; hosts that adopt a subset advertise only the sub-blocks they implement. `additionalProperties: true` reserved for future RFCs that extend the track; host-private extensions go under `x-host-<host>-<key>` per `host-extensions.md` §\"Canonical-prefix table\".",
|
|
141
149
|
"additionalProperties": true,
|
|
142
150
|
"properties": {
|
|
143
151
|
"reasoning": {
|
|
144
152
|
"type": "object",
|
|
145
|
-
"description": "RFC 0030
|
|
153
|
+
"description": "RFC 0030 §A + §C. Host's envelope payload schemas support the OPTIONAL `reasoning` field on kinds where multi-step reasoning materially improves output quality; the host's system-prompt-injection helper instructs the model to populate it. Absent block = no advertisement (the field MAY still appear on envelope schemas; this advertisement signals the host's prompt-injection posture).",
|
|
146
154
|
"additionalProperties": false,
|
|
147
155
|
"required": [
|
|
148
156
|
"supported"
|
|
@@ -150,7 +158,7 @@
|
|
|
150
158
|
"properties": {
|
|
151
159
|
"supported": {
|
|
152
160
|
"type": "boolean",
|
|
153
|
-
"description": "Host's envelope payload schemas carry `reasoning` (OPTIONAL) on kinds where reasoning materially improves output quality, per RFC 0030
|
|
161
|
+
"description": "Host's envelope payload schemas carry `reasoning` (OPTIONAL) on kinds where reasoning materially improves output quality, per RFC 0030 §A. Hosts SHOULD prompt the model to populate the field; hosts MUST NOT reject envelopes where `reasoning` is absent (the field is OPTIONAL by spec); hosts SHALL NOT route on `reasoning` contents."
|
|
154
162
|
},
|
|
155
163
|
"promptDirective": {
|
|
156
164
|
"type": "string",
|
|
@@ -159,7 +167,7 @@
|
|
|
159
167
|
"advisory",
|
|
160
168
|
"off"
|
|
161
169
|
],
|
|
162
|
-
"description": "Strength of the host's system-prompt instruction to populate `reasoning`. `mandatory`: the directive is firmly worded (the host instructs the model very forcefully to emit `reasoning`). `advisory` (default when absent): the directive is suggestive. `off`: the host emits no directive
|
|
170
|
+
"description": "Strength of the host's system-prompt instruction to populate `reasoning`. `mandatory`: the directive is firmly worded (the host instructs the model very forcefully to emit `reasoning`). `advisory` (default when absent): the directive is suggestive. `off`: the host emits no directive — applications that want `reasoning` populated must inject the instruction themselves. Note: `mandatory` is a prompt-injection posture, NOT a wire-level refusal contract — hosts MUST NOT reject envelopes where `reasoning` is absent regardless of this value."
|
|
163
171
|
}
|
|
164
172
|
}
|
|
165
173
|
},
|
|
@@ -170,7 +178,7 @@
|
|
|
170
178
|
"warn",
|
|
171
179
|
"off"
|
|
172
180
|
],
|
|
173
|
-
"description": "RFC 0030
|
|
181
|
+
"description": "RFC 0030 §B + §C. Host's self-attested compliance posture for the Tier-1 cross-vendor structured-output subset documented in `spec/v1/structured-output-subset.md`. `strict`: every host-served envelope schema passes the static subset-compliance check (object-root, `additionalProperties: false` everywhere, every property in `required`, no `oneOf`/`allOf`/`not`/`prefixItems`/`propertyNames`, no string format/pattern/length constraints, no number bounds, no array bounds, ≤5 nesting depth, ≤100 property count). `warn`: host serves non-compliant schemas but logs the violations. `off` (default when absent): no self-attestation. The conformance-suite static-subset scenario gates on this flag."
|
|
174
182
|
},
|
|
175
183
|
"reliability": {
|
|
176
184
|
"type": "object",
|
|
@@ -178,7 +186,7 @@
|
|
|
178
186
|
"required": [
|
|
179
187
|
"supported"
|
|
180
188
|
],
|
|
181
|
-
"description": "RFC 0032
|
|
189
|
+
"description": "RFC 0032 §C. Host emits the envelope-reliability event family on documented adverse paths. Hosts opt into the family via `supported: true` AND explicitly list the events they emit via `events[]`. Hosts that advertise `supported: true` MUST include at least `envelope.retry.exhausted` and `envelope.refusal` in `events[]` (the two MUST-tier events). The other four (`envelope.retry.attempted`, `envelope.truncated`, `envelope.nlToFormat.engaged`, `envelope.recovery.applied`) are SHOULD/MAY-tier per RFC 0032 §B and may be omitted.",
|
|
182
190
|
"properties": {
|
|
183
191
|
"supported": {
|
|
184
192
|
"type": "boolean",
|
|
@@ -204,7 +212,7 @@
|
|
|
204
212
|
"type": "integer",
|
|
205
213
|
"minimum": 1,
|
|
206
214
|
"maximum": 16,
|
|
207
|
-
"description": "Host's retry budget per envelope emission. Conformance scenarios use this to construct fixtures that exercise the retry-exhausted path. Independent of `capabilities.limits.schemaRounds` (which is the engine-side per-emission cap)
|
|
215
|
+
"description": "Host's retry budget per envelope emission. Conformance scenarios use this to construct fixtures that exercise the retry-exhausted path. Independent of `capabilities.limits.schemaRounds` (which is the engine-side per-emission cap) — `maxRetryAttempts` reports the host's actual configured value, not the spec's upper bound."
|
|
208
216
|
},
|
|
209
217
|
"completion": {
|
|
210
218
|
"type": "object",
|
|
@@ -212,17 +220,17 @@
|
|
|
212
220
|
"required": [
|
|
213
221
|
"distinguishesTruncation"
|
|
214
222
|
],
|
|
215
|
-
"description": "RFC 0033
|
|
223
|
+
"description": "RFC 0033 §E. Host's self-attested envelope-completion contract posture — does the host distinguish truncation from schema-violation in its retry routing per RFC 0033 §A + §B + §C?",
|
|
216
224
|
"properties": {
|
|
217
225
|
"distinguishesTruncation": {
|
|
218
226
|
"type": "boolean",
|
|
219
|
-
"description": "Host implements RFC 0033's truncation-vs-schema-violation retry-routing distinction: truncation
|
|
227
|
+
"description": "Host implements RFC 0033's truncation-vs-schema-violation retry-routing distinction: truncation → increased output budget (NO corrective fragment); schema-violation → corrective system fragment (NO budget increase). When `false` or absent, the host conflates the two paths (legacy behavior); RFC 0033 conformance scenarios soft-skip."
|
|
220
228
|
},
|
|
221
229
|
"truncationBudgetMultiplier": {
|
|
222
230
|
"type": "number",
|
|
223
231
|
"minimum": 1,
|
|
224
232
|
"maximum": 8,
|
|
225
|
-
"description": "Host's per-attempt output-budget multiplier on truncation retries. Informational; clients MAY surface this in cost-estimation UIs. Defaults to 2 when absent and `distinguishesTruncation: true`. Spec recommendation is 2
|
|
233
|
+
"description": "Host's per-attempt output-budget multiplier on truncation retries. Informational; clients MAY surface this in cost-estimation UIs. Defaults to 2 when absent and `distinguishesTruncation: true`. Spec recommendation is 2× per RFC 0033 §B."
|
|
226
234
|
}
|
|
227
235
|
}
|
|
228
236
|
}
|
|
@@ -232,18 +240,18 @@
|
|
|
232
240
|
},
|
|
233
241
|
"prompts": {
|
|
234
242
|
"type": "object",
|
|
235
|
-
"description": "RFC 0027 + RFC 0028 prompt-template support advertisement. The `supported` flag gates **node-execution resolution** of PromptRef values per RFC 0027 (Phase A); the separate `endpointsSupported` flag gates the **REST surface** at `/v1/prompts*` per RFC 0028 (Phase B). The two axes are independent
|
|
243
|
+
"description": "RFC 0027 + RFC 0028 prompt-template support advertisement. The `supported` flag gates **node-execution resolution** of PromptRef values per RFC 0027 (Phase A); the separate `endpointsSupported` flag gates the **REST surface** at `/v1/prompts*` per RFC 0028 (Phase B). The two axes are independent — a host MAY implement Phase A composition without exposing the REST surface, and vice versa. Absent block = no support; consumers passing PromptRef values to such a host MUST tolerate the keys being treated as opaque strings.",
|
|
236
244
|
"required": [
|
|
237
245
|
"supported"
|
|
238
246
|
],
|
|
239
247
|
"properties": {
|
|
240
248
|
"supported": {
|
|
241
249
|
"type": "boolean",
|
|
242
|
-
"description": "RFC 0027 Phase A. When `true`, the host resolves PromptRef values in `WorkflowNode.config.{systemPromptRef, userPromptRef, additionalPromptRefs}` at node-execution time AND emits `prompt.composed` run events per spec/v1/prompts.md
|
|
250
|
+
"description": "RFC 0027 Phase A. When `true`, the host resolves PromptRef values in `WorkflowNode.config.{systemPromptRef, userPromptRef, additionalPromptRefs}` at node-execution time AND emits `prompt.composed` run events per spec/v1/prompts.md §\"Composition + observability\". Does NOT imply the `/v1/prompts*` REST surface is available — see `endpointsSupported` for that. False or absent = the PromptRef keys on `WorkflowNode.config` are treated as opaque strings and never composed."
|
|
243
251
|
},
|
|
244
252
|
"endpointsSupported": {
|
|
245
253
|
"type": "boolean",
|
|
246
|
-
"description": "RFC 0028
|
|
254
|
+
"description": "RFC 0028 §A. When `true`, the host serves the `/v1/prompts*` REST surface — at minimum the read endpoints (`listPromptTemplates`, `getPromptTemplate`, `renderPromptTemplate`). The mutating endpoints additionally require `mutableLibrary: true`; the pack-install path additionally requires `packsSupported: true`. False or absent = every `/v1/prompts*` request returns `501 capability_not_provided`. Independent of `supported` — a host MAY advertise `supported: true, endpointsSupported: false` (composition without library REST) or `supported: false, endpointsSupported: true` (library REST against an external resolver, e.g., a façade host)."
|
|
247
255
|
},
|
|
248
256
|
"templateKinds": {
|
|
249
257
|
"type": "array",
|
|
@@ -251,7 +259,7 @@
|
|
|
251
259
|
"$ref": "./prompt-kind.schema.json"
|
|
252
260
|
},
|
|
253
261
|
"uniqueItems": true,
|
|
254
|
-
"description": "Subset of PromptKind values the host accepts. Defaults to all four (`system`, `user`, `few-shot`, `schema-hint`) when omitted. The $ref resolves to the shared `prompt-kind.schema.json` `$def` per RFC 0027
|
|
262
|
+
"description": "Subset of PromptKind values the host accepts. Defaults to all four (`system`, `user`, `few-shot`, `schema-hint`) when omitted. The $ref resolves to the shared `prompt-kind.schema.json` `$def` per RFC 0027 §A — uses a relative URI so redocly's lint walker resolves it against the local file rather than fetching the openwop.dev URL."
|
|
255
263
|
},
|
|
256
264
|
"variableSources": {
|
|
257
265
|
"type": "array",
|
|
@@ -284,16 +292,16 @@
|
|
|
284
292
|
},
|
|
285
293
|
"packsSupported": {
|
|
286
294
|
"type": "boolean",
|
|
287
|
-
"description": "RFC 0028
|
|
295
|
+
"description": "RFC 0028 §C. When `true`, the host installs `kind: \"prompt\"` registry packs and exposes their templates at `GET /v1/prompts` with `meta.source: \"pack\"` + `meta.packName` + `meta.packVersion`. When `false` or absent, packs are not loaded; only host built-ins and (when `mutableLibrary: true`) user-created templates are visible."
|
|
288
296
|
},
|
|
289
297
|
"mutableLibrary": {
|
|
290
298
|
"type": "boolean",
|
|
291
|
-
"description": "RFC 0028
|
|
299
|
+
"description": "RFC 0028 §C. When `true`, the host honors the mutating endpoints `POST /v1/prompts`, `PUT /v1/prompts/{templateId}`, `DELETE /v1/prompts/{templateId}`. When `false` or absent, those endpoints return 501. Pack-sourced and host-built-in templates remain read-only even under `mutableLibrary: true` — deletion of those returns 403 per RFC 0028 §A."
|
|
292
300
|
},
|
|
293
301
|
"library": {
|
|
294
302
|
"type": "object",
|
|
295
303
|
"additionalProperties": false,
|
|
296
|
-
"description": "RFC 0028
|
|
304
|
+
"description": "RFC 0028 §C. Per-library configuration knobs that influence how clients call the prompt surface.",
|
|
297
305
|
"properties": {
|
|
298
306
|
"id": {
|
|
299
307
|
"type": "string",
|
|
@@ -314,7 +322,7 @@
|
|
|
314
322
|
"defaults": {
|
|
315
323
|
"type": "object",
|
|
316
324
|
"additionalProperties": false,
|
|
317
|
-
"description": "RFC 0029
|
|
325
|
+
"description": "RFC 0029 §B. Per-kind host-default PromptRefs that apply at resolution chain layer 4 (`host-defaults`) per `spec/v1/prompts.md` §\"Resolution chain (normative)\". Advertised so clients can preview the full chain at edit time without dispatching a node. Hosts MAY ship per-kind defaults; the openwop spec ships none.",
|
|
318
326
|
"properties": {
|
|
319
327
|
"system": {
|
|
320
328
|
"$ref": "./prompt-ref.schema.json"
|
|
@@ -332,7 +340,7 @@
|
|
|
332
340
|
},
|
|
333
341
|
"agentBindings": {
|
|
334
342
|
"type": "boolean",
|
|
335
|
-
"description": "RFC 0029
|
|
343
|
+
"description": "RFC 0029 §B. When `true`, the host honors `AgentManifest.promptOverrides[kind]` and `AgentManifest.promptLibraryRef` at resolution chain layer 2 (`agent-overrides` / `agent-library-default`) per `spec/v1/prompts.md` §\"Resolution chain (normative)\". When `false` or absent, layer 2 is skipped — the host applies only layers 1, 3, 4. Conformance scenarios for agent-binding resolution are gated on this flag."
|
|
336
344
|
}
|
|
337
345
|
},
|
|
338
346
|
"additionalProperties": false
|
|
@@ -382,7 +390,7 @@
|
|
|
382
390
|
},
|
|
383
391
|
"grpc": {
|
|
384
392
|
"type": "object",
|
|
385
|
-
"description": "RFC 0094
|
|
393
|
+
"description": "RFC 0094 §H. gRPC transport advertisement per `grpc-transport.md` §\"Capability advertisement\". Optional — absent ⇒ the host exposes no gRPC transport. A host that exposes the gRPC surface advertises this block AND includes `\"grpc\"` in `supportedTransports`. REST + SSE remain exposed regardless.",
|
|
386
394
|
"required": [
|
|
387
395
|
"supported",
|
|
388
396
|
"service",
|
|
@@ -391,7 +399,7 @@
|
|
|
391
399
|
"properties": {
|
|
392
400
|
"supported": {
|
|
393
401
|
"type": "boolean",
|
|
394
|
-
"description": "Toggle
|
|
402
|
+
"description": "Toggle — `true` when the gRPC surface is live."
|
|
395
403
|
},
|
|
396
404
|
"endpoint": {
|
|
397
405
|
"type": "string",
|
|
@@ -402,7 +410,7 @@
|
|
|
402
410
|
"service": {
|
|
403
411
|
"type": "string",
|
|
404
412
|
"const": "openwop.v1.Engine",
|
|
405
|
-
"description": "Canonical service name. v1 hosts MUST use `openwop.v1.Engine` per `grpc-transport.md`
|
|
413
|
+
"description": "Canonical service name. v1 hosts MUST use `openwop.v1.Engine` per `grpc-transport.md` §\"Field semantics\"."
|
|
406
414
|
},
|
|
407
415
|
"tls": {
|
|
408
416
|
"type": "string",
|
|
@@ -418,11 +426,11 @@
|
|
|
418
426
|
},
|
|
419
427
|
"configurable": {
|
|
420
428
|
"type": "object",
|
|
421
|
-
"description": "Optional v1 per-run overlay schema
|
|
429
|
+
"description": "Optional v1 per-run overlay schema — what `RunOptions.configurable` keys this server honors."
|
|
422
430
|
},
|
|
423
431
|
"nodePackRuntimes": {
|
|
424
432
|
"type": "object",
|
|
425
|
-
"description": "Optional v1 advertisement of node-pack runtimes the host loads. See `node-packs.md`
|
|
433
|
+
"description": "Optional v1 advertisement of node-pack runtimes the host loads. See `node-packs.md` §runtime formats and RFC 0008 (WASM ABI). Hosts that don't load packs MAY omit this block entirely. NOTE: this block intentionally uses `additionalProperties: true` (here and on the nested runtime objects) so a future RFC may add a runtime type (e.g., `python-wasm`, `js-wasm`) without a breaking-change rev of this schema; the trade is that a strict-mode validator will accept arbitrary extra keys under these objects. A future RFC that promotes the open-set fields to first-class SHOULD tighten them to `additionalProperties: false` in the same RFC.",
|
|
426
434
|
"properties": {
|
|
427
435
|
"wasm": {
|
|
428
436
|
"type": "object",
|
|
@@ -443,13 +451,13 @@
|
|
|
443
451
|
},
|
|
444
452
|
"uniqueItems": true,
|
|
445
453
|
"minItems": 1,
|
|
446
|
-
"description": "ABI versions the loader accepts. v1.1 hosts MUST include `1`. Packs declaring `openwop_abi_version()` outside this list MUST be rejected at load time per RFC 0008
|
|
454
|
+
"description": "ABI versions the loader accepts. v1.1 hosts MUST include `1`. Packs declaring `openwop_abi_version()` outside this list MUST be rejected at load time per RFC 0008 §H."
|
|
447
455
|
},
|
|
448
456
|
"maxMemoryBytes": {
|
|
449
457
|
"type": "integer",
|
|
450
458
|
"minimum": 1048576,
|
|
451
459
|
"maximum": 8589934592,
|
|
452
|
-
"description": "Per-pack memory ceiling enforced by the host loader. Range: 1 MiB
|
|
460
|
+
"description": "Per-pack memory ceiling enforced by the host loader. Range: 1 MiB ≤ value ≤ 8 GiB. RFC 0008 §K — when a pack exceeds this, the host MUST emit `cap.breached` with `kind: \"wasm-memory\"`."
|
|
453
461
|
},
|
|
454
462
|
"loadedPacks": {
|
|
455
463
|
"type": "array",
|
|
@@ -458,7 +466,7 @@
|
|
|
458
466
|
"minLength": 1
|
|
459
467
|
},
|
|
460
468
|
"uniqueItems": true,
|
|
461
|
-
"description": "Pack names that passed instantiation (ABI check + load). Packs rejected per RFC 0008
|
|
469
|
+
"description": "Pack names that passed instantiation (ABI check + load). Packs rejected per RFC 0008 §H MUST NOT appear here. Hosts MAY advertise this for observability; conformance asserts rejection by absence (Track 7)."
|
|
462
470
|
}
|
|
463
471
|
},
|
|
464
472
|
"additionalProperties": true
|
|
@@ -503,7 +511,7 @@
|
|
|
503
511
|
"testSeams": {
|
|
504
512
|
"type": "object",
|
|
505
513
|
"additionalProperties": false,
|
|
506
|
-
"description": "RFC 0034
|
|
514
|
+
"description": "RFC 0034 — Conformance-only test seams under the host-extension namespace. Hosts that opt in expose introspection endpoints so cross-host conformance scenarios can verify BYOK canaries do not leak into OTel span attributes or debug-bundle exports. Production hosts SHOULD return 404 or 403 from these seams unless an env-gate (e.g., `OPENWOP_TEST_OTEL_SCRAPE=true`) is set.",
|
|
507
515
|
"properties": {
|
|
508
516
|
"otelScrape": {
|
|
509
517
|
"type": "boolean",
|
|
@@ -545,7 +553,7 @@
|
|
|
545
553
|
]
|
|
546
554
|
},
|
|
547
555
|
"uniqueItems": true,
|
|
548
|
-
"description": "Subset of scopes the host implements. Tenant-scoped secrets are workspace-shared; user-scoped are per-end-user; run-scoped are ephemeral per-run; `workspace` (RFC 0046/0048) is the explicit sub-tenant scope. Appended `workspace` is additive
|
|
556
|
+
"description": "Subset of scopes the host implements. Tenant-scoped secrets are workspace-shared; user-scoped are per-end-user; run-scoped are ephemeral per-run; `workspace` (RFC 0046/0048) is the explicit sub-tenant scope. Appended `workspace` is additive — hosts that omit it are unaffected."
|
|
549
557
|
},
|
|
550
558
|
"resolution": {
|
|
551
559
|
"type": "string",
|
|
@@ -559,7 +567,7 @@
|
|
|
559
567
|
},
|
|
560
568
|
"connections": {
|
|
561
569
|
"type": "object",
|
|
562
|
-
"description": "RFC 0095 (`Draft`). Connection packs
|
|
570
|
+
"description": "RFC 0095 (`Draft`). Connection packs — portable, registry-distributable provider definitions (`kind: \"connection\"`, `connection-pack-manifest.schema.json`) that the RFC 0045/0047 `provider` string resolves against. Only useful alongside `oauth.supported` (RFC 0047) or `credentials.supported` (RFC 0046); a host SHOULD NOT advertise this block without at least one of those.",
|
|
563
571
|
"required": [
|
|
564
572
|
"packsSupported"
|
|
565
573
|
],
|
|
@@ -570,7 +578,7 @@
|
|
|
570
578
|
},
|
|
571
579
|
"packsSupported": {
|
|
572
580
|
"type": "boolean",
|
|
573
|
-
"description": "RFC 0095
|
|
581
|
+
"description": "RFC 0095 §C. When `true`, the host installs `kind: \"connection\"` registry packs and MUST implement the §B.6 resolution contract: an RFC 0045 connector's `auth.provider` (or an RFC 0047 `host.oauth` provider string) resolves against the installed connection pack whose `provider.id` matches, with installed-vs-built-in precedence per SemVer §11 and `connection_provider_unresolved` / `connection_provider_conflict` diagnostics. When `false` or absent, connection packs are not loaded and provider resolution stays implementation-defined."
|
|
574
582
|
}
|
|
575
583
|
},
|
|
576
584
|
"additionalProperties": false
|
|
@@ -578,7 +586,7 @@
|
|
|
578
586
|
"selfHostedRunner": {
|
|
579
587
|
"type": "object",
|
|
580
588
|
"additionalProperties": false,
|
|
581
|
-
"description": "RFC 0122 (`Active`). The host routes a run's per-step model/tool dispatch to a user-controlled RUNNER that dials OUT to the host over a persistent channel (SSE receive + POST result) and holds the local credentials the host cannot reach (a subscription CLI login per RFC 0121, a private endpoint per RFC 0108). The host stays the sole orchestration/persistence/replay authority; the runner is a stateless dispatch executor. This is the discovery-time capability shape ONLY; the per-subject `SelfHostedRunnerRegistration` record stays OFF `/.well-known/openwop`. A host MUST NOT advertise `supported: true` until RFC 0122 reaches `Accepted` and the channel is honored (truthful-advertisement, `OPENWOP_REQUIRE_BEHAVIOR=true`). Absent block
|
|
589
|
+
"description": "RFC 0122 (`Active`). The host routes a run's per-step model/tool dispatch to a user-controlled RUNNER that dials OUT to the host over a persistent channel (SSE receive + POST result) and holds the local credentials the host cannot reach (a subscription CLI login per RFC 0121, a private endpoint per RFC 0108). The host stays the sole orchestration/persistence/replay authority; the runner is a stateless dispatch executor. This is the discovery-time capability shape ONLY; the per-subject `SelfHostedRunnerRegistration` record stays OFF `/.well-known/openwop`. A host MUST NOT advertise `supported: true` until RFC 0122 reaches `Accepted` and the channel is honored (truthful-advertisement, `OPENWOP_REQUIRE_BEHAVIOR=true`). Absent block ⇒ no runner advertisement.",
|
|
582
590
|
"required": [
|
|
583
591
|
"supported"
|
|
584
592
|
],
|
|
@@ -597,21 +605,21 @@
|
|
|
597
605
|
]
|
|
598
606
|
},
|
|
599
607
|
"uniqueItems": true,
|
|
600
|
-
"description": "OPTIONAL. Which dispatch kinds the host routes to runners. A host MAY implement `model` first and add `tool` later behind the same capability gate (openwop-app ADR 0182 Phase 5 lands model-dispatch first). Absent
|
|
608
|
+
"description": "OPTIONAL. Which dispatch kinds the host routes to runners. A host MAY implement `model` first and add `tool` later behind the same capability gate (openwop-app ADR 0182 Phase 5 lands model-dispatch first). Absent ⇒ implementation-defined, but a host SHOULD enumerate what it actually routes."
|
|
601
609
|
}
|
|
602
610
|
}
|
|
603
611
|
},
|
|
604
612
|
"purposePropagation": {
|
|
605
613
|
"type": "object",
|
|
606
614
|
"additionalProperties": false,
|
|
607
|
-
"description": "RFC 0128 (`Active`). Purpose-propagation
|
|
615
|
+
"description": "RFC 0128 (`Active`). Purpose-propagation — the host reads and RE-EMITS `permittedPurposes` labels (opaque purpose strings riding the A2A `metadata.openwop.permittedPurposes` extension and the `TriggerEvent.permittedPurposes` field) on onward OpenWOP-envelope hops of the same data, narrowing at most and never widening; a `[]` label is honored as no-onward-use. This family advertises label PROPAGATION only — it does NOT claim the host enforces purpose limits on its own internal use (that is declared intent under the receiver's local governance, RFC 0128 §4, deliberately not conformance-gated). A host MUST NOT advertise `supported: true` until RFC 0128 reaches `Accepted` and propagation is honored (truthful-advertisement, `OPENWOP_REQUIRE_BEHAVIOR=true`). Absent block ⇒ labels pass through unread as unknown metadata (pre-RFC behavior).",
|
|
608
616
|
"required": [
|
|
609
617
|
"supported"
|
|
610
618
|
],
|
|
611
619
|
"properties": {
|
|
612
620
|
"supported": {
|
|
613
621
|
"type": "boolean",
|
|
614
|
-
"description": "RFC 0128. When `true`, the host preserves and re-emits received `permittedPurposes` labels per RFC 0128
|
|
622
|
+
"description": "RFC 0128. When `true`, the host preserves and re-emits received `permittedPurposes` labels per RFC 0128 §3 (re-emit on OpenWOP-envelope onward hops; MAY narrow; MUST NOT widen; derived outputs never carry a purpose absent from any contributing labelled input; `[]` ⇒ no onward hop)."
|
|
615
623
|
},
|
|
616
624
|
"propagatesOnward": {
|
|
617
625
|
"type": "boolean",
|
|
@@ -622,7 +630,7 @@
|
|
|
622
630
|
"dataResidency": {
|
|
623
631
|
"type": "object",
|
|
624
632
|
"additionalProperties": false,
|
|
625
|
-
"description": "RFC 0129 (`Active`). Data-residency
|
|
633
|
+
"description": "RFC 0129 (`Active`). Data-residency — the host advertises the operator region codes it can pin a run to, and honors-or-rejects an OPTIONAL `residency.region` on run-creation (`POST /v1/runs`): accept iff the requested region is in `regions[]`, else reject `residency_unavailable` (never silently accept-and-ignore). This family advertises the ADMISSION decision only (falsifiable over the wire) — it does NOT assert that the run's data physically remains in-region (unobservable; declared operator intent under RFC 0129 §4, not conformance-gated). A host MUST advertise a region in `regions[]` only if it can actually process a run entirely within it. Absent block ⇒ the host makes no residency promise and MAY ignore or reject a `residency` constraint (but MUST NOT claim to honor it).",
|
|
626
634
|
"required": [
|
|
627
635
|
"supported",
|
|
628
636
|
"regions"
|
|
@@ -630,7 +638,7 @@
|
|
|
630
638
|
"properties": {
|
|
631
639
|
"supported": {
|
|
632
640
|
"const": true,
|
|
633
|
-
"description": "RFC 0129. Present-and-true when the host performs region admission control per
|
|
641
|
+
"description": "RFC 0129. Present-and-true when the host performs region admission control per §3. The block is omitted entirely when the host offers no residency pinning."
|
|
634
642
|
},
|
|
635
643
|
"regions": {
|
|
636
644
|
"type": "array",
|
|
@@ -639,14 +647,14 @@
|
|
|
639
647
|
"minLength": 1
|
|
640
648
|
},
|
|
641
649
|
"uniqueItems": true,
|
|
642
|
-
"description": "RFC 0129. Opaque operator region codes the host can pin a run to (e.g. `\"eu\"`, `\"us\"`, `\"eu-west-1\"`). No closed registry
|
|
650
|
+
"description": "RFC 0129. Opaque operator region codes the host can pin a run to (e.g. `\"eu\"`, `\"us\"`, `\"eu-west-1\"`). No closed registry — codes are the host's own vocabulary (a global region enum would be unfalsifiable). A host MUST advertise a code here only if it can process a run entirely within it; a run-create `residency.region` not in this list MUST be rejected `residency_unavailable`."
|
|
643
651
|
}
|
|
644
652
|
}
|
|
645
653
|
},
|
|
646
654
|
"anonymousActor": {
|
|
647
655
|
"type": "object",
|
|
648
656
|
"additionalProperties": false,
|
|
649
|
-
"description": "RFC 0132 (`Active`). Anonymous-actor authorization for public agent surfaces
|
|
657
|
+
"description": "RFC 0132 (`Active`). Anonymous-actor authorization for public agent surfaces — an opaque, origin-bound, ephemeral, non-cross-linkable, non-PII principal (`run-snapshot.owner.principalKind: \"anonymous\"`) whose authority is a DEFAULT-DENY, explicit per-surface tool grant, never the default-on tool baseline (§C.1). Two tiers: `read` (tenant-scoped, no egress, no secret/BYOK reach — §C.2) and `bounded-write-egress` (writes/egress permitted ONLY behind a mandatory HITL/approval gate (RFC 0051) OR a hard rate-limit + per-session cap, over the RFC 0076 §B / RFC 0079 SSRF-guarded audience-bound egress path, never attaching a tenant credential out-of-audience — §C.3). Every anon tool call emits `authorization.decided` (RFC 0049) attributable to the opaque session id, carrying no PII/credential (§D). The block is OMITTED ENTIRELY when unsupported (const-true `supported`, `dataResidency`-style — never `supported: false`). Absent ⇒ the host runs no tool-enabled public surface under RFC 0132 (e.g. a no-tools single-turn public gateway needs no advertisement).",
|
|
650
658
|
"required": [
|
|
651
659
|
"supported",
|
|
652
660
|
"tiers"
|
|
@@ -654,7 +662,7 @@
|
|
|
654
662
|
"properties": {
|
|
655
663
|
"supported": {
|
|
656
664
|
"const": true,
|
|
657
|
-
"description": "RFC 0132. Present-and-true when the host honors anonymous-actor authorization per
|
|
665
|
+
"description": "RFC 0132. Present-and-true when the host honors anonymous-actor authorization per §C. The block is omitted entirely when the host runs no tool-enabled public surface (never `supported: false`)."
|
|
658
666
|
},
|
|
659
667
|
"tiers": {
|
|
660
668
|
"type": "array",
|
|
@@ -666,7 +674,7 @@
|
|
|
666
674
|
"bounded-write-egress"
|
|
667
675
|
]
|
|
668
676
|
},
|
|
669
|
-
"description": "RFC 0132
|
|
677
|
+
"description": "RFC 0132 §B. The anon capability tiers this host BEHAVIORALLY honors (truthful-advertisement — a tier the host does not enforce per §C is a dishonest claim; `OPENWOP_REQUIRE_BEHAVIOR=true` MUST fail it). `read`: tenant-scoped reads, no egress, no secrets (§C.2). `bounded-write-egress`: writes/egress ONLY behind a §C.3 control."
|
|
670
678
|
},
|
|
671
679
|
"writeEgressControls": {
|
|
672
680
|
"type": "array",
|
|
@@ -678,7 +686,7 @@
|
|
|
678
686
|
"rate-limit-session-cap"
|
|
679
687
|
]
|
|
680
688
|
},
|
|
681
|
-
"description": "RFC 0132
|
|
689
|
+
"description": "RFC 0132 §B. REQUIRED and non-empty IFF `bounded-write-egress` ∈ `tiers`; MUST be absent otherwise. The mandatory control(s) the host enforces before an anon write/egress: `hitl` = a per-action approval gate (RFC 0051 — the action suspends pending a human decision); `rate-limit-session-cap` = a hard per-IP/per-window rate limit AND a per-session action cap. A `bounded-write-egress` tier with no advertised control is the fail-open shape §B.2 forbids."
|
|
682
690
|
},
|
|
683
691
|
"failClosed": {
|
|
684
692
|
"const": true,
|
|
@@ -687,7 +695,7 @@
|
|
|
687
695
|
},
|
|
688
696
|
"allOf": [
|
|
689
697
|
{
|
|
690
|
-
"$comment": "RFC 0132
|
|
698
|
+
"$comment": "RFC 0132 §B.2 — writeEgressControls is REQUIRED and non-empty when bounded-write-egress is advertised, and MUST be absent otherwise (a control-less write/egress tier is the fail-open shape this RFC forbids).",
|
|
691
699
|
"if": {
|
|
692
700
|
"properties": {
|
|
693
701
|
"tiers": {
|
|
@@ -717,7 +725,7 @@
|
|
|
717
725
|
},
|
|
718
726
|
"credentials": {
|
|
719
727
|
"type": "object",
|
|
720
|
-
"description": "RFC 0046 (`Draft`). Portable credential resolution + lifecycle contract
|
|
728
|
+
"description": "RFC 0046 (`Draft`). Portable credential resolution + lifecycle contract — sibling to `secrets`, first-class store-at-rest + workspace sharing + two-key-overlap rotation. A pack references a credential by `{ ref, scope }` (see `credential-reference.schema.json`); the host resolves it into the node sandbox ONLY — never into inputs, persisted variables, channels, any run.* event payload, the debug bundle, or replay state (SECURITY invariant `credential-payload-redaction`). Supersedes the informal BYOK annex; the `secrets` advertisement stays valid.",
|
|
721
729
|
"required": [
|
|
722
730
|
"supported"
|
|
723
731
|
],
|
|
@@ -760,7 +768,7 @@
|
|
|
760
768
|
},
|
|
761
769
|
"feedback": {
|
|
762
770
|
"type": "object",
|
|
763
|
-
"description": "RFC 0056 (`Draft`). Non-blocking human/agent quality signals (rating / correction / label / flag) attached to a run, event, or node. Annotations are a per-run side-resource recorded via `POST /v1/runs/{runId}/annotations`, listed via `GET`, and surfaced live via the `run.annotated` SSE notification
|
|
771
|
+
"description": "RFC 0056 (`Draft`). Non-blocking human/agent quality signals (rating / correction / label / flag) attached to a run, event, or node. Annotations are a per-run side-resource recorded via `POST /v1/runs/{runId}/annotations`, listed via `GET`, and surfaced live via the `run.annotated` SSE notification — they are NOT entries in the replayable run event log (see RFC 0056 §B/§D). Hosts that do not advertise `supported: true` return `501 capability_not_provided` on the annotation endpoints.",
|
|
764
772
|
"required": [
|
|
765
773
|
"supported"
|
|
766
774
|
],
|
|
@@ -801,7 +809,7 @@
|
|
|
801
809
|
},
|
|
802
810
|
"replay": {
|
|
803
811
|
"type": "object",
|
|
804
|
-
"description": "Replay / fork surface (`spec/v1/replay.md`; profile `openwop-replay-fork`). DECLARED FOR THE FIRST TIME BY RFC 0140
|
|
812
|
+
"description": "Replay / fork surface (`spec/v1/replay.md`; profile `openwop-replay-fork`). DECLARED FOR THE FIRST TIME BY RFC 0140 — hosts have emitted this block since the fork endpoint shipped, but it was never in this schema and validated only via the root's `additionalProperties: true`. The pre-existing fields are declared here exactly as already emitted and consumed, so no host's current document is invalidated; `additionalProperties` stays permissive for the same reason.",
|
|
805
813
|
"properties": {
|
|
806
814
|
"supported": {
|
|
807
815
|
"type": "boolean",
|
|
@@ -829,7 +837,7 @@
|
|
|
829
837
|
"windowSeconds": {
|
|
830
838
|
"type": "integer",
|
|
831
839
|
"minimum": 0,
|
|
832
|
-
"description": "How long a run stays fork-eligible (`replay.md`
|
|
840
|
+
"description": "How long a run stays fork-eligible (`replay.md` §\"Retention and garbage collection\"). OPTIONAL — the spec requires hosts to document retention, not to advertise the window."
|
|
833
841
|
}
|
|
834
842
|
},
|
|
835
843
|
"description": "OPTIONAL retention metadata."
|
|
@@ -841,7 +849,7 @@
|
|
|
841
849
|
"none"
|
|
842
850
|
],
|
|
843
851
|
"default": "none",
|
|
844
|
-
"description": "RFC 0140. An ASSURANCE ADVERTISEMENT of the mechanism by which the host meets `replay.md`
|
|
852
|
+
"description": "RFC 0140. An ASSURANCE ADVERTISEMENT of the mechanism by which the host meets `replay.md` §\"Determinism guarantees\" caveat 1 for a `mode:\"replay\"` fork — NOT a gate on the obligation, which is unconditional. `recorded-outcome`: a side-effecting node does NOT execute during a replay — the host reproduces the source run's recorded terminal outcome for the same `(nodeId, attempt)`, or fails the node closed with `replay_source_missing`. The guarantee is WHOLE-RUN: a host MUST NOT advertise it if any class of side-effecting node can still fire during a replay (a partial guarantee would violate `replay.md` §C.2 observable-state equivalence for the unsuppressed classes). `none` (default; absent means this) — NO mechanism is declared. The host remains bound by `replay.md` §\"Determinism guarantees\" caveat 1 (an unconditional MUST that a node calling an external API consult the durable invocation log, so the external system is NOT called twice) exactly as before; conformance simply has nothing to probe. This is NOT permission to re-fire effects. Scoped to `replay` mode; `branch` is a new execution whose effects the operator asked for."
|
|
845
853
|
}
|
|
846
854
|
}
|
|
847
855
|
},
|
|
@@ -916,11 +924,11 @@
|
|
|
916
924
|
"properties": {
|
|
917
925
|
"supported": {
|
|
918
926
|
"type": "boolean",
|
|
919
|
-
"description": "Host implements the role
|
|
927
|
+
"description": "Host implements the role→scope authorization-decision contract."
|
|
920
928
|
},
|
|
921
929
|
"failClosed": {
|
|
922
930
|
"const": true,
|
|
923
|
-
"description": "Absent/unseeded role denies; resolver errors deny. MUST be true when present
|
|
931
|
+
"description": "Absent/unseeded role denies; resolver errors deny. MUST be true when present — see SECURITY invariant `authorization-fail-closed`."
|
|
924
932
|
},
|
|
925
933
|
"roles": {
|
|
926
934
|
"type": "array",
|
|
@@ -958,11 +966,11 @@
|
|
|
958
966
|
"minLength": 1
|
|
959
967
|
},
|
|
960
968
|
"uniqueItems": true,
|
|
961
|
-
"description": "Optional v1 host-advertised opaque capability ids that NodeModules may declare in `NodeModule.requires`. Naming convention: dotted, domain-scoped (`chat.sendPrompt`, `canvas.write`, `secrets.byok`). Provider value shapes are documented per-capability alongside consumers, NOT in the protocol package
|
|
969
|
+
"description": "Optional v1 host-advertised opaque capability ids that NodeModules may declare in `NodeModule.requires`. Naming convention: dotted, domain-scoped (`chat.sendPrompt`, `canvas.write`, `secrets.byok`). Provider value shapes are documented per-capability alongside consumers, NOT in the protocol package — the protocol owns the *check*, not domain provider contracts. A client that submits a workflow whose nodes declare a `requires` entry SHOULD first verify the host advertises that capability; a host that lacks a capability MUST refuse to dispatch nodes that declare it, terminating the run with `RunSnapshot.error.code = 'capability_not_provided'`. See `capabilities.md` §\"Runtime capabilities\"."
|
|
962
970
|
},
|
|
963
971
|
"multiPartyConversation": {
|
|
964
972
|
"type": "object",
|
|
965
|
-
"description": "RFC 0101
|
|
973
|
+
"description": "RFC 0101 — Multi-party group conversation (shared transcript + speaker attribution). When advertised with `supported: true`, the host honors the RFC 0101 normative contract: (1) it accepts an OPTIONAL `participants: AgentRef[]` roster on `conversation.opened` (`conversation-event.schema.json`); (2) it REQUIRES a `speakerId` (the roster INSTANCE id, `host:<id>` per RFC 0086) on every `role: 'agent'` turn; and (3) when a `participants` roster is present it MUST reject a turn whose `speakerId` is not a roster member. Absent block ⇒ no advertisement: the host runs single-agent conversations (RFC 0005) and treats `participants`/`speakerId` as opaque, unenforced fields. Advertising `supported: true` without honoring (1)+(2)+(3) is a dishonest wire claim (`OPENWOP_REQUIRE_BEHAVIOR=true` fails the gated conformance scenarios). Host product policy — turn-taking order, round count, synchronous vs. async rounds — stays NON-normative (RFC 0101 §Spec); only roster membership, agent-turn attribution, and this capability are normative. Requires `conversationPrimitive: true` (RFC 0005) — this block extends the single-agent conversation primitive, it does not replace it.",
|
|
966
974
|
"required": [
|
|
967
975
|
"supported"
|
|
968
976
|
],
|
|
@@ -975,13 +983,13 @@
|
|
|
975
983
|
"maxParticipants": {
|
|
976
984
|
"type": "integer",
|
|
977
985
|
"minimum": 2,
|
|
978
|
-
"description": "RFC 0101. OPTIONAL host ceiling on the size of the `conversation.opened.participants` roster. A multi-party council has at least 2 participants. When advertised, the host MUST reject a `conversation.opened` whose `participants` array exceeds this count. Absent
|
|
986
|
+
"description": "RFC 0101. OPTIONAL host ceiling on the size of the `conversation.opened.participants` roster. A multi-party council has at least 2 participants. When advertised, the host MUST reject a `conversation.opened` whose `participants` array exceeds this count. Absent ⇒ the host does not bound the roster size on the wire."
|
|
979
987
|
}
|
|
980
988
|
}
|
|
981
989
|
},
|
|
982
990
|
"conversationTurnModelProvenance": {
|
|
983
991
|
"type": "object",
|
|
984
|
-
"description": "RFC 0109
|
|
992
|
+
"description": "RFC 0109 — Conversation-turn model provenance. When advertised with `supported: true`, the host stamps the OPTIONAL `agent.model` object (`{ provider, model }`) on `role: 'agent'` conversation turns (`conversation-turn.schema.json`), recording which model produced the turn. The stamp is NON-SECRET + NON-PII (`additionalProperties: false` on `agent.model` forbids any credential/endpoint/prompt — the SR-1 guard) and is read VERBATIM on `:fork` (never re-resolved, so a forked transcript preserves the original provenance). Absent block ⇒ no advertisement: the host omits `agent.model` and treats it as an opaque, unenforced field. Advertising `supported: true` without stamping is a dishonest wire claim (`OPENWOP_REQUIRE_BEHAVIOR=true` fails the gated scenario). Additive over RFC 0005 — extends the conversation primitive, does not replace it.",
|
|
985
993
|
"required": [
|
|
986
994
|
"supported"
|
|
987
995
|
],
|
|
@@ -995,7 +1003,7 @@
|
|
|
995
1003
|
},
|
|
996
1004
|
"channelPresence": {
|
|
997
1005
|
"type": "object",
|
|
998
|
-
"description": "RFC 0110
|
|
1006
|
+
"description": "RFC 0110 — Channel presence (online + typing). When advertised with `supported: true`, the host emits the OPTIONAL `channel.presence` RunEvent (`channel-presence-payload.schema.json`) for a `type:'channel'` conversation, carrying the currently-present member subject refs + optional per-member typing. Presence is EPHEMERAL live state: the host MUST NOT persist it to the replayable event log / transcript and it MUST NOT affect replay or `:fork` (the load-bearing distinction from the persisted `conversation.exchanged` turn). Membership-gated: every ref MUST be a current participant and the event MUST NOT be delivered to a non-member (DEFAULT-DENY, CTI-1). NON-PII (opaque RFC 0041 subject refs only). Absent block ⇒ no advertisement: the host emits no presence. Advertising `supported: true` without emitting is a dishonest wire claim (`OPENWOP_REQUIRE_BEHAVIOR=true` fails the gated scenario). Additive over RFC 0005.",
|
|
999
1007
|
"required": [
|
|
1000
1008
|
"supported"
|
|
1001
1009
|
],
|
|
@@ -1009,7 +1017,7 @@
|
|
|
1009
1017
|
},
|
|
1010
1018
|
"multiAgent": {
|
|
1011
1019
|
"type": "object",
|
|
1012
|
-
"description": "RFC 0037
|
|
1020
|
+
"description": "RFC 0037 — Multi-agent execution model + handoff state machine. Hosts that advertise implement the supervisor→dispatch→harvest loop + the 4-state handoff state machine + the `core.workflowChain.event` emission contract per spec/v1/multi-agent-execution.md. Absent block = host implements RFCs 0006/0007/0022 individually with implementation flexibility on integration semantics; conformance scenarios gating on this flag soft-skip on absence.",
|
|
1013
1021
|
"additionalProperties": false,
|
|
1014
1022
|
"properties": {
|
|
1015
1023
|
"executionModel": {
|
|
@@ -1037,7 +1045,7 @@
|
|
|
1037
1045
|
"properties": {
|
|
1038
1046
|
"supported": {
|
|
1039
1047
|
"type": "boolean",
|
|
1040
|
-
"description": "Host implements the execution loop + handoff state machine per spec/v1/multi-agent-execution.md
|
|
1048
|
+
"description": "Host implements the execution loop + handoff state machine per spec/v1/multi-agent-execution.md §\"Execution loop\" + §\"Handoff state machine\". When true, the host MUST emit `core.workflowChain.event` records on every handoff transition per the §\"Transition events\" table."
|
|
1041
1049
|
},
|
|
1042
1050
|
"tier": {
|
|
1043
1051
|
"type": "string",
|
|
@@ -1046,19 +1054,19 @@
|
|
|
1046
1054
|
"experimental"
|
|
1047
1055
|
],
|
|
1048
1056
|
"default": "stable",
|
|
1049
|
-
"description": "RFC 0042
|
|
1057
|
+
"description": "RFC 0042 — stability claim for this capability advertisement. `stable` (the default when absent) means the host commits to the wire shape across v1.x minors. `experimental` means the host advertises the surface as a preview; the wire shape MAY shift compatibly without notice until the underlying RFC graduates to `Accepted` and the host re-advertises as `stable`. Hosts MUST omit the field for capabilities whose underlying RFC is already `Accepted`."
|
|
1050
1058
|
},
|
|
1051
1059
|
"experimentalUntil": {
|
|
1052
1060
|
"type": "string",
|
|
1053
1061
|
"format": "date",
|
|
1054
1062
|
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
|
|
1055
|
-
"description": "RFC 0042
|
|
1063
|
+
"description": "RFC 0042 §B — required when `tier` is `experimental`. ISO-8601 `YYYY-MM-DD` no more than 12 months past the discovery response date. Reaching this date without graduating the underlying RFC to `Accepted` MUST result in the host either flipping tier to `stable` OR retracting the capability advertisement (or — with an open deprecation RFC — extending with a new `experimentalUntil` per §B sub-block 2)."
|
|
1056
1064
|
},
|
|
1057
1065
|
"version": {
|
|
1058
1066
|
"type": "integer",
|
|
1059
1067
|
"minimum": 1,
|
|
1060
1068
|
"maximum": 6,
|
|
1061
|
-
"description": "Profile version. 1 = Phase 1 (execution-loop framework + planner
|
|
1069
|
+
"description": "Profile version. 1 = Phase 1 (execution-loop framework + planner→worker handoff). 2 = Phase 2 (confidence-floor escalation + agent-memory lifecycle, RFC 0039). 3 = Phase 3 (cross-host causation, RFC 0040). 4 = Phase 4 (replay determinism under nondeterministic models, RFC 0041). 5 = Phase 5 (stateful agent-loop lifecycle — per-iteration workspace+memory snapshot inputs, the observable `iteration` counter on `runOrchestrator.decided`, and stateful HITL resume, RFC 0061). 6 = Phase 6 (verifier/critic turn — the `agent.verified` event + `successCriteria` on the `terminate` decision, RFC 0090). A host advertising `version: N` MUST implement all phases 1..N additively."
|
|
1062
1070
|
},
|
|
1063
1071
|
"verifier": {
|
|
1064
1072
|
"type": "object",
|
|
@@ -1066,15 +1074,15 @@
|
|
|
1066
1074
|
"required": [
|
|
1067
1075
|
"supported"
|
|
1068
1076
|
],
|
|
1069
|
-
"description": "RFC 0090 (`version >= 6`). The verifier/critic turn: the host emits `agent.verified` over a prior result and (optionally) gates commit on the verdict. Absent
|
|
1077
|
+
"description": "RFC 0090 (`version >= 6`). The verifier/critic turn: the host emits `agent.verified` over a prior result and (optionally) gates commit on the verdict. Absent ⇒ no verifier turn; conformance scenarios soft-skip.",
|
|
1070
1078
|
"properties": {
|
|
1071
1079
|
"supported": {
|
|
1072
1080
|
"type": "boolean",
|
|
1073
|
-
"description": "Host emits `agent.verified` and honors RFC 0090
|
|
1081
|
+
"description": "Host emits `agent.verified` and honors RFC 0090 §A. Applies only when `version >= 6`."
|
|
1074
1082
|
},
|
|
1075
1083
|
"gating": {
|
|
1076
1084
|
"type": "boolean",
|
|
1077
|
-
"description": "Host enforces the RFC 0090
|
|
1085
|
+
"description": "Host enforces the RFC 0090 §B commit-gating contract: a `fail` verdict blocks merge/terminate (fail-closed, composing RFC 0063); `revise` routes back to an actor turn. Absent/false ⇒ the verdict is observability-only."
|
|
1078
1086
|
}
|
|
1079
1087
|
}
|
|
1080
1088
|
},
|
|
@@ -1082,7 +1090,7 @@
|
|
|
1082
1090
|
"type": "number",
|
|
1083
1091
|
"minimum": 0.5,
|
|
1084
1092
|
"maximum": 1.0,
|
|
1085
|
-
"description": "RFC 0039
|
|
1093
|
+
"description": "RFC 0039 §A. Operator-declared confidence floor at or above the spec floor of 0.5; when an OrchestratorDecision carries `confidence` below this floor, the host MUST escalate via a `clarify` or `escalate` interrupt instead of executing the decision. Absent: the spec floor 0.5 applies. Values < 0.5 are non-conformant; values > 1.0 are nonsense. Applies only when `version >= 2`."
|
|
1086
1094
|
},
|
|
1087
1095
|
"confidenceEscalationInterruptKind": {
|
|
1088
1096
|
"type": "string",
|
|
@@ -1097,7 +1105,7 @@
|
|
|
1097
1105
|
"pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
|
|
1098
1106
|
}
|
|
1099
1107
|
],
|
|
1100
|
-
"description": "RFC 0044
|
|
1108
|
+
"description": "RFC 0044 — the literal `interrupt.kind` the host emits when escalating a below-floor confidence decision per RFC 0039 §A. `clarification` and `approval` are the canonical values matching the clarify-OR-approval choice in RFC 0039 §A; vendor-extension kinds use the canonical host-extension namespace `^x-host-<host>-<kind>$` per `spec/v1/host-extensions.md` §\"Canonical prefixes\". When advertised, hosts MUST emit an interrupt of the advertised kind on every confidence-escalation event AND the host's downstream `interrupt.md` mapping determines the `waiting-*` terminal status. Absent: conformance assumes the host uses one of the two canonical kinds (the relaxed assertion accepts either). Hosts using vendor kinds MUST also publish a non-normative kind-mapping document per RFC 0044 §C."
|
|
1101
1109
|
},
|
|
1102
1110
|
"crossChildMemoryConcurrency": {
|
|
1103
1111
|
"type": "string",
|
|
@@ -1105,11 +1113,11 @@
|
|
|
1105
1113
|
"strict",
|
|
1106
1114
|
"advisory"
|
|
1107
1115
|
],
|
|
1108
|
-
"description": "RFC 0039
|
|
1116
|
+
"description": "RFC 0039 §B. Cross-child memory-write concurrency posture when version >= 2. `strict` (default when absent): the host serializes concurrent writes from sibling dispatched children to the parent's shared memory scope. `advisory`: the host opts out of the serialization MUST and documents last-write-wins semantics out-of-band. Hosts that choose advisory SHOULD also advertise their resolution rule under `crossChildMemoryConcurrencyResolution` (reserved field; follow-up clarification)."
|
|
1109
1117
|
},
|
|
1110
1118
|
"crossHostCausation": {
|
|
1111
1119
|
"type": "object",
|
|
1112
|
-
"description": "RFC 0040
|
|
1120
|
+
"description": "RFC 0040 §D — Phase 3 cross-host causation linking. When advertised, the host honors the cross-host `causationId` extension (a `causationHostId` field on event payloads pointing at the originating host), W3C `traceparent` propagation across MCP + A2A composition boundaries, and (when `ancestryEndpointSupported: true`) the `GET /v1/runs/{runId}/ancestry` cross-host parent-chain endpoint. Hosts advertising `version: 3` MUST advertise this sub-block with `supported: true` and a stable `hostId`.",
|
|
1113
1121
|
"additionalProperties": false,
|
|
1114
1122
|
"required": [
|
|
1115
1123
|
"supported"
|
|
@@ -1126,13 +1134,13 @@
|
|
|
1126
1134
|
},
|
|
1127
1135
|
"ancestryEndpointSupported": {
|
|
1128
1136
|
"type": "boolean",
|
|
1129
|
-
"description": "Host serves `GET /v1/runs/{runId}/ancestry` returning the cross-host parent chain per RFC 0040
|
|
1137
|
+
"description": "Host serves `GET /v1/runs/{runId}/ancestry` returning the cross-host parent chain per RFC 0040 §C. Optional even when crossHostCausation.supported is true — hosts that emit `causationHostId` but don't expose the ancestry-walking endpoint still satisfy the per-event chaining contract; this flag advertises the additional endpoint."
|
|
1130
1138
|
}
|
|
1131
1139
|
}
|
|
1132
1140
|
},
|
|
1133
1141
|
"replayDeterminism": {
|
|
1134
1142
|
"type": "object",
|
|
1135
|
-
"description": "RFC 0041
|
|
1143
|
+
"description": "RFC 0041 §D — Phase 4 replay determinism. When advertised, the host honors the LLM cache-key recipe in `replay.md` §\"LLM cache-key recipe\" as NORMATIVE (graduated from informative for version >= 4), emits `replay.divergedAtRefusal` events + fails with `replay_diverged_at_refusal` on refusal-divergence (RFC 0041 §B), and guarantees observable-output-sequence determinism per RFC 0041 §C. Hosts advertising `version: 4` MUST advertise this sub-block with `supported: true`.",
|
|
1136
1144
|
"additionalProperties": false,
|
|
1137
1145
|
"required": [
|
|
1138
1146
|
"supported"
|
|
@@ -1152,32 +1160,32 @@
|
|
|
1152
1160
|
"pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
|
|
1153
1161
|
}
|
|
1154
1162
|
],
|
|
1155
|
-
"description": "The LLM cache-key recipe the host honors. `spec-rfc-0041` = the canonical recipe in `replay.md`
|
|
1163
|
+
"description": "The LLM cache-key recipe the host honors. `spec-rfc-0041` = the canonical recipe in `replay.md` §\"LLM cache-key recipe\" §A + §B + §C. Vendor-specific recipes use the canonical host-extension namespace string matching `^x-host-<host>-<recipe-name>$` per `spec/v1/host-extensions.md` §\"Canonical prefixes\"; the matching algorithm MUST be documented at the host's discovery doc."
|
|
1156
1164
|
},
|
|
1157
1165
|
"refusalDivergenceEmission": {
|
|
1158
1166
|
"type": "boolean",
|
|
1159
|
-
"description": "Host emits `replay.divergedAtRefusal` events + fails replay with `error.code: replay_diverged_at_refusal` per RFC 0041
|
|
1167
|
+
"description": "Host emits `replay.divergedAtRefusal` events + fails replay with `error.code: replay_diverged_at_refusal` per RFC 0041 §B. Hosts advertising `version: 4` MUST set this to `true`."
|
|
1160
1168
|
}
|
|
1161
1169
|
}
|
|
1162
1170
|
},
|
|
1163
1171
|
"statefulResume": {
|
|
1164
1172
|
"type": "boolean",
|
|
1165
|
-
"description": "RFC 0061 (`version >= 5`). When `true`, a `clarify`/`escalate` HITL suspend resumes the execution loop at the SAME iteration
|
|
1173
|
+
"description": "RFC 0061 (`version >= 5`). When `true`, a `clarify`/`escalate` HITL suspend resumes the execution loop at the SAME iteration — the `runOrchestrator.decided.iteration` counter does not reset or skip — with the per-iteration memory (RFC 0039 MAE-3) + workspace (RFC 0059) snapshot lineage intact, so a mid-loop human interrupt does not lose progress. A distinct claim from plain replay re-entrancy (deterministic replay of a completed prefix); this is about a LIVE suspend preserving the counter. Omitted by hosts on `version < 5`."
|
|
1166
1174
|
},
|
|
1167
1175
|
"transcriptWindow": {
|
|
1168
1176
|
"type": "integer",
|
|
1169
1177
|
"minimum": 1,
|
|
1170
|
-
"description": "RFC 0061 (`version >= 5`). Host-advertised count of recent event-log entries the host feeds each orchestrator turn as the iteration's transcript input (
|
|
1178
|
+
"description": "RFC 0061 (`version >= 5`). Host-advertised count of recent event-log entries the host feeds each orchestrator turn as the iteration's transcript input (§C input 3). Advertise-and-honor; not a fixed wire constant. Absent ⇒ the host does not bound the transcript window on the wire."
|
|
1171
1179
|
},
|
|
1172
1180
|
"contextBudget": {
|
|
1173
1181
|
"type": "object",
|
|
1174
|
-
"description": "RFC 0111 (`Active`, `version >= 5`). Opt-in, token-denominated bound on the orchestrator transcript the host feeds each iteration, plus a declared summarization contract for turns evicted beyond that budget. SCOPE: governs the RFC 0061 per-iteration ORCHESTRATOR-LOOP transcript (`multi-agent-execution.md`
|
|
1182
|
+
"description": "RFC 0111 (`Active`, `version >= 5`). Opt-in, token-denominated bound on the orchestrator transcript the host feeds each iteration, plus a declared summarization contract for turns evicted beyond that budget. SCOPE: governs the RFC 0061 per-iteration ORCHESTRATOR-LOOP transcript (`multi-agent-execution.md` §\"Per-iteration state inputs\" input 3 — the same transcript `transcriptWindow` bounds), NOT a general chat-conversation history. A host whose orchestrator loop does not run real model turns (e.g. a mock supervisor) MUST NOT advertise this block, exactly as it MUST NOT dishonestly advertise `transcriptWindow`. Budget-only advertisement (`transcriptTokenBudget` + `tokenCounter` WITHOUT `summarization.supported`) is valid for a host that HAS a real orchestrator loop but does not summarize. Purely additive: a host that omits this block behaves exactly as today, including `transcriptWindow`'s `absent ⇒ unbounded` default (NOT flipped by this RFC). Complements (does not replace) the event-count `transcriptWindow`; when both bound a turn the host MUST honor whichever is tighter. Summarization here is a NONDETERMINISTIC host output governed exactly like an RFC 0041 envelope: each substitution MUST be recorded as a `context.summarized` event whose `summaryRef` artifact replay reuses (never re-summarizes) per `multi-agent-execution.md` §\"Context economy (RFC 0111)\".",
|
|
1175
1183
|
"additionalProperties": false,
|
|
1176
1184
|
"properties": {
|
|
1177
1185
|
"transcriptTokenBudget": {
|
|
1178
1186
|
"type": "integer",
|
|
1179
1187
|
"minimum": 1,
|
|
1180
|
-
"description": "RFC 0111. Max tokens of transcript the host feeds any single orchestrator turn, measured in the unit named by `tokenCounter`. Advertise-and-honor; complements (does not replace) `transcriptWindow`. When both are present the host MUST honor whichever bound is tighter for a given turn. Absent
|
|
1188
|
+
"description": "RFC 0111. Max tokens of transcript the host feeds any single orchestrator turn, measured in the unit named by `tokenCounter`. Advertise-and-honor; complements (does not replace) `transcriptWindow`. When both are present the host MUST honor whichever bound is tighter for a given turn. Absent ⇒ no token bound on the transcript (only the event-count `transcriptWindow`, if any, applies)."
|
|
1181
1189
|
},
|
|
1182
1190
|
"tokenCounter": {
|
|
1183
1191
|
"type": "string",
|
|
@@ -1187,7 +1195,7 @@
|
|
|
1187
1195
|
"chars",
|
|
1188
1196
|
"host-defined"
|
|
1189
1197
|
],
|
|
1190
|
-
"description": "RFC 0111. The unit `transcriptTokenBudget` is denominated in, so the bound is interpretable across hosts. REQUIRED when `transcriptTokenBudget` is present (enforced via the `if/then` clause). `o200k_base`/`cl100k_base` are tokenizer encodings; `chars` counts UTF-8/Unicode characters (a tokenizer-free unit a client can reason about directly); `host-defined` is an opaque host unit. Same enum as RFC 0113 `memory.injectionBudget.tokenCounter`
|
|
1198
|
+
"description": "RFC 0111. The unit `transcriptTokenBudget` is denominated in, so the bound is interpretable across hosts. REQUIRED when `transcriptTokenBudget` is present (enforced via the `if/then` clause). `o200k_base`/`cl100k_base` are tokenizer encodings; `chars` counts UTF-8/Unicode characters (a tokenizer-free unit a client can reason about directly); `host-defined` is an opaque host unit. Same enum as RFC 0113 `memory.injectionBudget.tokenCounter` — transcript (0111) and memory (0113) budgets denominate in one consistent vocabulary; no shared `$ref` (decoupled)."
|
|
1191
1199
|
},
|
|
1192
1200
|
"summarization": {
|
|
1193
1201
|
"type": "object",
|
|
@@ -1208,12 +1216,12 @@
|
|
|
1208
1216
|
"recursive",
|
|
1209
1217
|
"map-reduce"
|
|
1210
1218
|
],
|
|
1211
|
-
"description": "RFC 0111. Informational descriptor of the host's summarization strategy. `sliding-window` keeps a recent verbatim tail and summarizes the prefix; `recursive` folds prior summaries into new ones; `map-reduce` summarizes chunks then combines. Does not change the replay-determinism contract
|
|
1219
|
+
"description": "RFC 0111. Informational descriptor of the host's summarization strategy. `sliding-window` keeps a recent verbatim tail and summarizes the prefix; `recursive` folds prior summaries into new ones; `map-reduce` summarizes chunks then combines. Does not change the replay-determinism contract — all strategies record `context.summarized` and reuse `summaryRef` on replay."
|
|
1212
1220
|
},
|
|
1213
1221
|
"keepLastTurns": {
|
|
1214
1222
|
"type": "integer",
|
|
1215
1223
|
"minimum": 0,
|
|
1216
|
-
"description": "RFC 0111. Number of most-recent turns kept verbatim at the head of the window; older in-window turns MAY be replaced by a summary. The active (most recent) turn MUST NOT be summarized regardless of this value. Absent
|
|
1224
|
+
"description": "RFC 0111. Number of most-recent turns kept verbatim at the head of the window; older in-window turns MAY be replaced by a summary. The active (most recent) turn MUST NOT be summarized regardless of this value. Absent ⇒ host-defined verbatim floor."
|
|
1217
1225
|
}
|
|
1218
1226
|
}
|
|
1219
1227
|
}
|
|
@@ -1236,7 +1244,7 @@
|
|
|
1236
1244
|
},
|
|
1237
1245
|
"modelCapabilities": {
|
|
1238
1246
|
"type": "object",
|
|
1239
|
-
"description": "RFC 0031. Host implements model-capability gating + (optional) substitution per `NodeModule.requiredModelCapabilities` + `NodeModule.fallbackModel`. Distinct from `runtimeCapabilities` which gates on HOST capabilities
|
|
1247
|
+
"description": "RFC 0031. Host implements model-capability gating + (optional) substitution per `NodeModule.requiredModelCapabilities` + `NodeModule.fallbackModel`. Distinct from `runtimeCapabilities` which gates on HOST capabilities — `modelCapabilities` gates on MODEL capabilities (structured-output support, discriminator-enum support, long-context, native reasoning, function-calling). Absent block = no advertisement; NodeModules' `requiredModelCapabilities` are treated as opaque metadata and dispatch proceeds without checks.",
|
|
1240
1248
|
"additionalProperties": false,
|
|
1241
1249
|
"required": [
|
|
1242
1250
|
"supported"
|
|
@@ -1244,7 +1252,7 @@
|
|
|
1244
1252
|
"properties": {
|
|
1245
1253
|
"supported": {
|
|
1246
1254
|
"type": "boolean",
|
|
1247
|
-
"description": "Host honors `NodeModule.requiredModelCapabilities` and emits `model.capability.substituted` / `model.capability.insufficient` events per RFC 0031
|
|
1255
|
+
"description": "Host honors `NodeModule.requiredModelCapabilities` and emits `model.capability.substituted` / `model.capability.insufficient` events per RFC 0031 §B + §D. When `false` or absent, the fields are treated as opaque metadata and dispatch proceeds without capability checks."
|
|
1248
1256
|
},
|
|
1249
1257
|
"advertised": {
|
|
1250
1258
|
"type": "array",
|
|
@@ -1253,17 +1261,17 @@
|
|
|
1253
1261
|
"pattern": "^([a-z][a-z0-9-]*|x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*)$"
|
|
1254
1262
|
},
|
|
1255
1263
|
"uniqueItems": true,
|
|
1256
|
-
"description": "Capability identifiers the host's active model advertises. Clients MAY introspect this at install time to determine whether their NodeModules' `requiredModelCapabilities` are satisfiable without fallback. Spec-reserved identifiers per RFC 0031
|
|
1264
|
+
"description": "Capability identifiers the host's active model advertises. Clients MAY introspect this at install time to determine whether their NodeModules' `requiredModelCapabilities` are satisfiable without fallback. Spec-reserved identifiers per RFC 0031 §C + RFC 0055: `structured-output`, `discriminator-enum`, `long-context`, `reasoning` (model-native thinking-tokens), `function-calling`, `vision-input` (model accepts image content in the prompt), `audio-input` (model accepts audio content), `audio-output` (model emits audio content), `image-output` (model emits images directly in its completion, distinct from the host-side `aiProviders.imageGeneration` tool surface). This is an open, pattern-validated registry — NOT a closed enum; growth requires an RFC. Host-private extensions MUST prefix with `x-host-<host>-`."
|
|
1257
1265
|
},
|
|
1258
1266
|
"substitutionSupported": {
|
|
1259
1267
|
"type": "boolean",
|
|
1260
|
-
"description": "Host honors `NodeModule.fallbackModel` substitution per RFC 0031
|
|
1268
|
+
"description": "Host honors `NodeModule.fallbackModel` substitution per RFC 0031 §B step 3. When `false` or absent, hosts MUST refuse to dispatch (step 4) on any unmet capability — they MUST NOT attempt fallback even when the field is declared on the NodeModule. Recursive fallback is NOT permitted (RFC 0031 §\"Unresolved questions\" #3)."
|
|
1261
1269
|
}
|
|
1262
1270
|
}
|
|
1263
1271
|
},
|
|
1264
1272
|
"providerUsage": {
|
|
1265
1273
|
"type": "object",
|
|
1266
|
-
"description": "RFC 0026. Hosts that emit `provider.usage` events after every LLM provider invocation per RFC 0026
|
|
1274
|
+
"description": "RFC 0026. Hosts that emit `provider.usage` events after every LLM provider invocation per RFC 0026 §B. The event carries per-call token counts in the durable event log; cost rollup remains in `RunSnapshot.metrics.openwopCost`. Old hosts ignore.",
|
|
1267
1275
|
"properties": {
|
|
1268
1276
|
"supported": {
|
|
1269
1277
|
"type": "boolean",
|
|
@@ -1295,7 +1303,7 @@
|
|
|
1295
1303
|
"minLength": 1
|
|
1296
1304
|
},
|
|
1297
1305
|
"uniqueItems": true,
|
|
1298
|
-
"description": "Provider ids the host's AI-proxy can route to. Conventional ids (RFC 0067
|
|
1306
|
+
"description": "Provider ids the host's AI-proxy can route to. Conventional ids (RFC 0067 §C recommended vocabulary — advisory, not a closed set): `anthropic`, `openai`, `gemini`, `vertex`, `bedrock`, `mistral`, `cohere`, `openrouter`, `litellm`, `together`, `huggingface`, `qwen`, `ollama`, `vllm`. Hosts MAY add vendor-prefixed extensions; clients MUST tolerate unknown ids."
|
|
1299
1307
|
},
|
|
1300
1308
|
"byok": {
|
|
1301
1309
|
"type": "array",
|
|
@@ -1304,7 +1312,7 @@
|
|
|
1304
1312
|
"minLength": 1
|
|
1305
1313
|
},
|
|
1306
1314
|
"uniqueItems": true,
|
|
1307
|
-
"description": "Subset of `supported` for which BYOK is permitted. Empty array
|
|
1315
|
+
"description": "Subset of `supported` for which BYOK is permitted. Empty array → all calls use platform-managed keys; non-empty → clients MAY pass `ai.credentialRef` in `RunOptions.configurable` for matching providers."
|
|
1308
1316
|
},
|
|
1309
1317
|
"selfHosted": {
|
|
1310
1318
|
"type": "array",
|
|
@@ -1313,16 +1321,16 @@
|
|
|
1313
1321
|
"minLength": 1
|
|
1314
1322
|
},
|
|
1315
1323
|
"uniqueItems": true,
|
|
1316
|
-
"description": "RFC 0108. Subset of `supported` whose entries are operator- or tenant-configured OpenAI-compatible endpoints (e.g. an Ollama / vLLM / LM Studio / any `/v1/chat/completions`-compatible server), as opposed to a host-managed connection to a known public vendor. Each entry MUST also appear in `supported`. An entry MAY also appear in `byok` (the endpoint requires a client/tenant-supplied key) or be absent from it (the endpoint needs no key, e.g. a default Ollama). The provider id is an OPAQUE label chosen by the host; it MUST NOT encode the endpoint's network location (scheme, host, port, path, or base-URL) per RFC 0108
|
|
1324
|
+
"description": "RFC 0108. Subset of `supported` whose entries are operator- or tenant-configured OpenAI-compatible endpoints (e.g. an Ollama / vLLM / LM Studio / any `/v1/chat/completions`-compatible server), as opposed to a host-managed connection to a known public vendor. Each entry MUST also appear in `supported`. An entry MAY also appear in `byok` (the endpoint requires a client/tenant-supplied key) or be absent from it (the endpoint needs no key, e.g. a default Ollama). The provider id is an OPAQUE label chosen by the host; it MUST NOT encode the endpoint's network location (scheme, host, port, path, or base-URL) per RFC 0108 §A.3, and the endpoint location MUST NOT be disclosed on any wire surface (see the `self-hosted-endpoint-no-disclosure` SECURITY invariant). A client MUST NOT infer model capabilities from a `selfHosted` id (RFC 0108 §B); the only authoritative capability sources are `modelCapabilities.advertised[]` (RFC 0031) and `aiProviders.input.modalities` (RFC 0091)."
|
|
1317
1325
|
},
|
|
1318
1326
|
"speechSynthesis": {
|
|
1319
1327
|
"const": "supported",
|
|
1320
|
-
"description": "RFC 0105. When present (value MUST be the string `\"supported\"`), the host exposes `ctx.callSpeechSynthesizer({ text, voiceId, mimeType?, format?, languageCode?, ... })` returning a binary audio asset (host-served `url` OR inline `base64` + `mimeType`), paralleling `aiProviders.imageGeneration`. Absent
|
|
1328
|
+
"description": "RFC 0105. When present (value MUST be the string `\"supported\"`), the host exposes `ctx.callSpeechSynthesizer({ text, voiceId, mimeType?, format?, languageCode?, ... })` returning a binary audio asset (host-served `url` OR inline `base64` + `mimeType`), paralleling `aiProviders.imageGeneration`. Absent ⇒ no TTS; a call MUST be rejected with `speech_synthesis_unsupported` (never a no-op). Voices are referenced by an opaque host-resolved `voiceId`; the spec does NOT enumerate voices. TTS provider ids are advertised via the existing `aiProviders.supported[]` (the call's `provider?` MUST be a member); there is no `speechSynthesis` sub-field for providers. Per-host model/voice routing is a host choice."
|
|
1321
1329
|
},
|
|
1322
1330
|
"input": {
|
|
1323
1331
|
"type": "object",
|
|
1324
1332
|
"additionalProperties": false,
|
|
1325
|
-
"description": "RFC 0091. Multimodal PERCEPTION input on `ctx.callAI`
|
|
1333
|
+
"description": "RFC 0091. Multimodal PERCEPTION input on `ctx.callAI` — the modalities a `callAI` message ContentPart may carry as model INPUT. Absent ⇒ text-only (today's behavior); a `string` message content is always valid. Distinct from `imageGeneration` (output) and the `ai-envelope.md` media emission types (output).",
|
|
1326
1334
|
"properties": {
|
|
1327
1335
|
"modalities": {
|
|
1328
1336
|
"type": "array",
|
|
@@ -1347,7 +1355,7 @@
|
|
|
1347
1355
|
},
|
|
1348
1356
|
"authModes": {
|
|
1349
1357
|
"type": "object",
|
|
1350
|
-
"description": "RFC 0067 (`Active`), extended by RFC 0121 (`Active`). Optional per-provider advertisement of HOW the host expects a provider's credential to be supplied. Keys are provider ids appearing in `supported`; values are the auth modes the host honors for that provider. Absent
|
|
1358
|
+
"description": "RFC 0067 (`Active`), extended by RFC 0121 (`Active`). Optional per-provider advertisement of HOW the host expects a provider's credential to be supplied. Keys are provider ids appearing in `supported`; values are the auth modes the host honors for that provider. Absent ⇒ no advertisement: a provider in `byok` defaults to `apiKey` semantics (client passes `ai.credentialRef`); a provider in `supported` but not in `byok` defaults to `none` (platform-managed). This map only DESCRIBES the supply mechanism — `oauth-pkce`/`oauth-device` flow mechanics compose RFC 0047 `host.oauth` and resolve credentials by `ref` (RFC 0046), never on `ai.credentialRef`. A provider with `apiKey` MUST appear in `byok`; a provider whose modes are exactly `[\"none\"]` MUST NOT appear in `byok`. `subscription` (RFC 0121) advertises that a provider credential may be supplied by reusing the caller's existing personal, non-metered consumer subscription (e.g. Claude Pro/Max, ChatGPT Plus) rather than a metered API key; a `subscription` provider MUST appear in `byok`, is referenced by `ref` (RFC 0046) like the `oauth-*` modes (never on `ai.credentialRef`), and its credential MUST bind at `host.credentials` `scope:\"user\"` — never tenant/workspace-shared (SECURITY invariant `subscription-credential-user-scope-only`). Consumers MUST ignore an auth mode they don't recognize rather than reject the discovery doc.",
|
|
1351
1359
|
"additionalProperties": {
|
|
1352
1360
|
"type": "array",
|
|
1353
1361
|
"minItems": 1,
|
|
@@ -1366,7 +1374,7 @@
|
|
|
1366
1374
|
},
|
|
1367
1375
|
"policies": {
|
|
1368
1376
|
"type": "object",
|
|
1369
|
-
"description": "Optional v1 host-side policy enforcement modes for per-provider gating. Omitted
|
|
1377
|
+
"description": "Optional v1 host-side policy enforcement modes for per-provider gating. Omitted → no enforcement; clients see only `optional` semantics. When present, MUST declare `modes` — an empty `{}` is not a valid third state. See `capabilities.md` §`aiProviders.policies`.",
|
|
1370
1378
|
"required": [
|
|
1371
1379
|
"modes"
|
|
1372
1380
|
],
|
|
@@ -1406,12 +1414,12 @@
|
|
|
1406
1414
|
"type": "integer",
|
|
1407
1415
|
"minimum": 0,
|
|
1408
1416
|
"default": 262144,
|
|
1409
|
-
"description": "RFC 0055
|
|
1417
|
+
"description": "RFC 0055 §C rule 2 — optional cap (bytes) on inline base64 in `media.*` envelope payloads. A `media.{image,audio,file}` asset above this size MUST be served by a tenant-scoped `url` reference rather than inlined (bounds event-log + replay-payload size). Default 256 KiB (262144) when absent. A host MAY set 0 to force URL references for all emitted media."
|
|
1410
1418
|
},
|
|
1411
1419
|
"realtimeVoice": {
|
|
1412
1420
|
"type": "object",
|
|
1413
1421
|
"additionalProperties": false,
|
|
1414
|
-
"description": "RFC 0106. Optional real-time voice profile. Absent
|
|
1422
|
+
"description": "RFC 0106. Optional real-time voice profile. Absent ⇒ no live voice (a call to `ctx.callTranscriber` MUST be rejected with `transcription_unsupported`, and `stream:true` on `ctx.callSpeechSynthesizer` with `streaming_unsupported`). `ctx.callTranscriber` resolves a `Promise` at `turn_commit` with the settled final transcript and emits the interim/final/endpoint signals as `voice.*` run-events on the durable event log (the single canonical record); the streaming synthesis arm resolves a `Promise` at completion and announces clause-boundary chunks as `voice.synthesis_chunk` metadata run-events (bytes by `streamRef`/`url`, not inlined past the host cap).",
|
|
1415
1423
|
"properties": {
|
|
1416
1424
|
"transcription": {
|
|
1417
1425
|
"const": "streaming",
|
|
@@ -1445,7 +1453,7 @@
|
|
|
1445
1453
|
"promptPrefixCache": {
|
|
1446
1454
|
"type": "object",
|
|
1447
1455
|
"additionalProperties": false,
|
|
1448
|
-
"description": "RFC 0116. Host honors the AI-envelope `generate` request's optional `cachePrefixId` as a provider-cache routing hint
|
|
1456
|
+
"description": "RFC 0116. Host honors the AI-envelope `generate` request's optional `cachePrefixId` as a provider-cache routing hint — tenant-namespaced (SECURITY invariant `prompt-prefix-cache-cross-tenant-isolation`), secret-free, and replay-invariant (a cache hit/miss MUST NOT change the recorded envelope or `provider.usage.inputTokens`/`outputTokens`). Absent ⇒ a host MUST ignore `cachePrefixId` (no error, no behavior change). PROVIDER-SCOPED: prefix caching is provider-specific (e.g. Anthropic ephemeral), so this is NOT a universal claim — see `providers`.",
|
|
1449
1457
|
"properties": {
|
|
1450
1458
|
"supported": {
|
|
1451
1459
|
"type": "boolean",
|
|
@@ -1458,7 +1466,7 @@
|
|
|
1458
1466
|
"minLength": 1
|
|
1459
1467
|
},
|
|
1460
1468
|
"uniqueItems": true,
|
|
1461
|
-
"description": "RFC 0116. The subset of `aiProviders.supported[]` for which the host honors `cachePrefixId` (prefix caching is provider-specific). A request whose routed provider is NOT in this list MUST have `cachePrefixId` ignored. Absent
|
|
1469
|
+
"description": "RFC 0116. The subset of `aiProviders.supported[]` for which the host honors `cachePrefixId` (prefix caching is provider-specific). A request whose routed provider is NOT in this list MUST have `cachePrefixId` ignored. Absent ⇒ host-defined per-provider routing; NOT a universal claim across providers."
|
|
1462
1470
|
}
|
|
1463
1471
|
},
|
|
1464
1472
|
"required": [
|
|
@@ -1469,7 +1477,7 @@
|
|
|
1469
1477
|
"additionalProperties": false,
|
|
1470
1478
|
"allOf": [
|
|
1471
1479
|
{
|
|
1472
|
-
"$comment": "RFC 0106
|
|
1480
|
+
"$comment": "RFC 0106 §A closure: realtimeVoice.synthesis (streaming TTS) requires the whole-file TTS surface aiProviders.speechSynthesis to be advertised.",
|
|
1473
1481
|
"if": {
|
|
1474
1482
|
"type": "object",
|
|
1475
1483
|
"required": [
|
|
@@ -1541,12 +1549,12 @@
|
|
|
1541
1549
|
"properties": {
|
|
1542
1550
|
"mockAgent": {
|
|
1543
1551
|
"type": "boolean",
|
|
1544
|
-
"description": "RFC 0023
|
|
1552
|
+
"description": "RFC 0023 §B.2. When `true`, the host has registered the `core.conformance.mock-agent` typeId. The scenarios `agentReasoningEvents.test.ts` and `agentConfidenceEscalation.test.ts` rely on the typeId being reachable. Hosts that register the typeId only for workflow ids matching the conformance fixture prefix (`conformance-*`) and refuse it for other tenants MAY still advertise `true` — the advertisement says only that the typeId is reachable from the conformance suite, not that it is reachable from arbitrary workflows."
|
|
1545
1553
|
},
|
|
1546
1554
|
"certificationBundleUrl": {
|
|
1547
1555
|
"type": "string",
|
|
1548
1556
|
"format": "uri",
|
|
1549
|
-
"description": "OPTIONAL (RFC 0089). URL of the host's most recent conformance certification bundle (`conformance-certification-bundle.schema.json`)
|
|
1557
|
+
"description": "OPTIONAL (RFC 0089). URL of the host's most recent conformance certification bundle (`conformance-certification-bundle.schema.json`) — a machine-readable attestation binding this host's claimed profiles to the reproducible run that substantiates them. Omitting it is fully conformant; clients MUST tolerate its absence."
|
|
1550
1558
|
}
|
|
1551
1559
|
},
|
|
1552
1560
|
"additionalProperties": false
|
|
@@ -1608,7 +1616,7 @@
|
|
|
1608
1616
|
},
|
|
1609
1617
|
"memoryConsolidation": {
|
|
1610
1618
|
"type": "object",
|
|
1611
|
-
"description": "RFC 0068 (`Draft`). Background reconciliation of LONG-TERM memory (merge/dedup/supersede/strengthen)
|
|
1619
|
+
"description": "RFC 0068 (`Draft`). Background reconciliation of LONG-TERM memory (merge/dedup/supersede/strengthen) — distinct from RFC 0062 token-budgeted distillation of TRANSACTIONAL memory. A host advertising this emits `agent.memory.consolidated` (content-free) after a consolidation pass. Requires `agents.memoryBackends` to include `long-term`. SR-1 carry-forward + CTI-1 (RFC 0004) hold across the pass. Hosts that omit this block do not consolidate; the conformance scenarios skip cleanly.",
|
|
1612
1620
|
"additionalProperties": false,
|
|
1613
1621
|
"required": [
|
|
1614
1622
|
"supported"
|
|
@@ -1631,7 +1639,7 @@
|
|
|
1631
1639
|
},
|
|
1632
1640
|
"commitments": {
|
|
1633
1641
|
"type": "object",
|
|
1634
|
-
"description": "RFC 0068 (`Draft`). Inferred STANDING commitments
|
|
1642
|
+
"description": "RFC 0068 (`Draft`). Inferred STANDING commitments — durable, memory-derived intentions the host promotes into a time- or predicate-gated arm that fires a run later, without a fresh user turn. When an arm fires the host emits `commitment.fired` (content-free — the intention text lives in SR-1-redacted memory). Composes RFC 0052 (time arms) / RFC 0060 (predicate arms) for the fire substrate. Hosts that omit this block do not infer commitments; the conformance scenario skips cleanly.",
|
|
1635
1643
|
"additionalProperties": false,
|
|
1636
1644
|
"required": [
|
|
1637
1645
|
"supported"
|
|
@@ -1651,7 +1659,7 @@
|
|
|
1651
1659
|
]
|
|
1652
1660
|
},
|
|
1653
1661
|
"uniqueItems": true,
|
|
1654
|
-
"description": "Which fire-condition kinds the host supports. `time` composes RFC 0052 scheduling; `predicate` composes RFC 0060 heartbeat. Absent
|
|
1662
|
+
"description": "Which fire-condition kinds the host supports. `time` composes RFC 0052 scheduling; `predicate` composes RFC 0060 heartbeat. Absent ⇒ `['time']`."
|
|
1655
1663
|
}
|
|
1656
1664
|
}
|
|
1657
1665
|
},
|
|
@@ -1665,7 +1673,7 @@
|
|
|
1665
1673
|
},
|
|
1666
1674
|
"manifestRuntime": {
|
|
1667
1675
|
"type": "object",
|
|
1668
|
-
"description": "RFC 0070. Agent-manifest runtime floor
|
|
1676
|
+
"description": "RFC 0070. Agent-manifest runtime floor — the minimal tier that makes a published agent pack (RFC 0003) runnable. When `supported: true`, the host implements RFC 0003 `installAgents`: it loads each installed pack's `agents[]` into an in-process AgentRegistry, resolves `systemPromptRef` + `handoff.*SchemaRef` from the tarball at install (RFC 0003 §C/§D), and can DISPATCH a manifest agent on the existing `core.dispatch`/orchestrator loop (RFC 0007/0037/0061). Does NOT imply swarm/consensus (`host.agentRuntime`), long-term memory (`agents.memoryBackends`), or crews beyond `agents.dispatch`. A host advertising `host.agentRuntime: supported` is treated as also satisfying this flag (RFC 0070 §B). Hosts that omit this block do not instantiate manifest agents (today's default).",
|
|
1669
1677
|
"additionalProperties": false,
|
|
1670
1678
|
"required": [
|
|
1671
1679
|
"supported"
|
|
@@ -1673,12 +1681,12 @@
|
|
|
1673
1681
|
"properties": {
|
|
1674
1682
|
"supported": {
|
|
1675
1683
|
"type": "boolean",
|
|
1676
|
-
"description": "REQUIRED when the block is present. When `true`, the host loads + dispatches pack-declared manifest agents. A host with `supported: true` MUST enforce each dispatched agent's `toolAllowlist` (RFC 0002
|
|
1684
|
+
"description": "REQUIRED when the block is present. When `true`, the host loads + dispatches pack-declared manifest agents. A host with `supported: true` MUST enforce each dispatched agent's `toolAllowlist` (RFC 0002 §A14) and MUST NOT leak BYOK plaintext into `agent.*` events or handoff payloads (SR-1)."
|
|
1677
1685
|
},
|
|
1678
1686
|
"handoffValidation": {
|
|
1679
1687
|
"type": "boolean",
|
|
1680
1688
|
"default": false,
|
|
1681
|
-
"description": "When `true`, the host validates inbound task payloads against the agent's `handoff.taskSchemaRef` before dispatch and outbound results against `handoff.returnSchemaRef` before persistence (RFC 0003
|
|
1689
|
+
"description": "When `true`, the host validates inbound task payloads against the agent's `handoff.taskSchemaRef` before dispatch and outbound results against `handoff.returnSchemaRef` before persistence (RFC 0003 §D). When `false`/absent, manifests carrying `handoff` schemas are dispatched with opaque payloads."
|
|
1682
1690
|
},
|
|
1683
1691
|
"installScope": {
|
|
1684
1692
|
"type": "string",
|
|
@@ -1687,13 +1695,13 @@
|
|
|
1687
1695
|
"tenant"
|
|
1688
1696
|
],
|
|
1689
1697
|
"default": "host",
|
|
1690
|
-
"description": "RFC 0074. Scope at which manifest agents are installed/approved and therefore enumerated by GET /v1/agents. 'host' (default): a single host-global inventory; the endpoint returns the same set for every caller (RFC 0072's original behavior). 'tenant': agents are installed per tenant
|
|
1698
|
+
"description": "RFC 0074. Scope at which manifest agents are installed/approved and therefore enumerated by GET /v1/agents. 'host' (default): a single host-global inventory; the endpoint returns the same set for every caller (RFC 0072's original behavior). 'tenant': agents are installed per tenant·workspace (RFC 0048 owner triple); GET /v1/agents returns ONLY the agents available to the authenticated principal's workspace, and an unapproved/unknown agent 404s — the surface never discloses another tenant's inventory. Does not change dispatch (RFC 0072 §B, owner-triple-scoped POST /v1/runs) or any floor safety guarantee (toolAllowlist/systemPromptRef/SR-1 stay mandatory regardless of scope)."
|
|
1691
1699
|
}
|
|
1692
1700
|
}
|
|
1693
1701
|
},
|
|
1694
1702
|
"liveRuntime": {
|
|
1695
1703
|
"type": "object",
|
|
1696
|
-
"description": "RFC 0077. The host executes manifest agents against LIVE models and tools (not the deterministic RFC 0070 sample floor) per the normative AgentManifest
|
|
1704
|
+
"description": "RFC 0077. The host executes manifest agents against LIVE models and tools (not the deterministic RFC 0070 sample floor) per the normative AgentManifest→live-run mapping (`multi-agent-execution.md` §\"Live manifest dispatch\"), and emits the `agent.invocation.started`/`agent.invocation.completed` content-free bracket around the existing `agent.*` family. REQUIRES `agents.manifestRuntime.supported: true` — `liveRuntime` is a strict superset of the floor. The floor's mandatory safety guarantees (toolAllowlist enforcement, handoff inbound validation, tenant scoping, untrusted-model-output handling, fail-closed per-tool authorization) stay unconditional under `liveRuntime`. Hosts that omit this block run the floor only; the behavioral conformance scenarios skip cleanly.",
|
|
1697
1705
|
"additionalProperties": false,
|
|
1698
1706
|
"required": [
|
|
1699
1707
|
"supported"
|
|
@@ -1701,15 +1709,15 @@
|
|
|
1701
1709
|
"properties": {
|
|
1702
1710
|
"supported": {
|
|
1703
1711
|
"type": "boolean",
|
|
1704
|
-
"description": "REQUIRED when present. When `true`, the host performs live manifest dispatch per the
|
|
1712
|
+
"description": "REQUIRED when present. When `true`, the host performs live manifest dispatch per the §B mapping and emits the `agent.invocation.*` bracket. Gated on `agents.manifestRuntime.supported: true`."
|
|
1705
1713
|
},
|
|
1706
1714
|
"structuredOutput": {
|
|
1707
1715
|
"type": "boolean",
|
|
1708
|
-
"description": "When `true`, the host validates the terminal result against the agent's `handoff.returnSchemaRef` and fails the run with a structured-output error on a non-conforming result rather than shipping it. Absent
|
|
1716
|
+
"description": "When `true`, the host validates the terminal result against the agent's `handoff.returnSchemaRef` and fails the run with a structured-output error on a non-conforming result rather than shipping it. Absent ⇒ `false` (runs live but does not enforce `returnSchemaRef`)."
|
|
1709
1717
|
},
|
|
1710
1718
|
"confidenceEscalation": {
|
|
1711
1719
|
"type": "boolean",
|
|
1712
|
-
"description": "When `true`, the host honors `AgentManifest.confidence.defaultThreshold` and triggers the RFC 0002
|
|
1720
|
+
"description": "When `true`, the host honors `AgentManifest.confidence.defaultThreshold` and triggers the RFC 0002 §F escalation contract when an `agent.decided` confidence falls below the effective threshold, rather than silently accepting the decision. Absent ⇒ `false`."
|
|
1713
1721
|
},
|
|
1714
1722
|
"sources": {
|
|
1715
1723
|
"type": "array",
|
|
@@ -1722,13 +1730,13 @@
|
|
|
1722
1730
|
"chat-mention"
|
|
1723
1731
|
]
|
|
1724
1732
|
},
|
|
1725
|
-
"description": "Which invocation entry points the host exposes for live manifest dispatch. `workflow-node`: an agent step inside a workflow run (RFC 0072
|
|
1733
|
+
"description": "Which invocation entry points the host exposes for live manifest dispatch. `workflow-node`: an agent step inside a workflow run (RFC 0072 §B); `run-api`: an agent as the root of POST /v1/runs; `chat-mention`: a chat @agent invocation mapped onto the run surface. Enum membership is NOT mandatory — a host with no chat surface simply omits `chat-mention`. Absent ⇒ `['workflow-node']` (the RFC 0072 §B normative path). All advertised sources MUST emit the identical `agent.invocation.*` + `agent.*` event family."
|
|
1726
1734
|
}
|
|
1727
1735
|
}
|
|
1728
1736
|
},
|
|
1729
1737
|
"evalSuite": {
|
|
1730
1738
|
"type": "object",
|
|
1731
|
-
"description": "RFC 0081. The host runs portable `agent-eval-suite.schema.json` suites as eval runs (a `mode: \"eval\"` projection over POST /v1/runs, RFC 0081
|
|
1739
|
+
"description": "RFC 0081. The host runs portable `agent-eval-suite.schema.json` suites as eval runs (a `mode: \"eval\"` projection over POST /v1/runs, RFC 0081 §B), emits the `eval.started`/`eval.scored`/`eval.completed` content-free family, and terminates with an `eval-summary.schema.json` scorecard. Composes RFC 0026 (per-task cost), RFC 0054 (regression baseline diff), RFC 0056 (human override of an auto-score). Hosts that omit this block reject `mode: \"eval\"` with 501; the behavioral conformance scenario soft-skips. The summary + events are content-free (SECURITY invariant `eval-summary-no-content-leak`).",
|
|
1732
1740
|
"additionalProperties": false,
|
|
1733
1741
|
"required": [
|
|
1734
1742
|
"supported"
|
|
@@ -1751,12 +1759,12 @@
|
|
|
1751
1759
|
"live-shadow"
|
|
1752
1760
|
]
|
|
1753
1761
|
},
|
|
1754
|
-
"description": "Which eval modes the host actually implements (RFC 0081
|
|
1762
|
+
"description": "Which eval modes the host actually implements (RFC 0081 §D closed vocabulary). Truthful advertisement (RFC 0031): a host advertises ONLY the modes it gates on; a suite requesting an unadvertised mode is rejected at run-create with `400 validation_error`. Absent ⇒ no modes (the host advertises `supported` but gates nothing — effectively shape-only)."
|
|
1755
1763
|
},
|
|
1756
1764
|
"maxTasksPerSuite": {
|
|
1757
1765
|
"type": "integer",
|
|
1758
1766
|
"minimum": 1,
|
|
1759
|
-
"description": "MAY. Host ceiling on tasks per suite; a suite exceeding it is rejected at run-create (the RFC 0058
|
|
1767
|
+
"description": "MAY. Host ceiling on tasks per suite; a suite exceeding it is rejected at run-create (the RFC 0058 §A clamp pattern)."
|
|
1760
1768
|
},
|
|
1761
1769
|
"maxCostUsdPerSuite": {
|
|
1762
1770
|
"type": "number",
|
|
@@ -1767,7 +1775,7 @@
|
|
|
1767
1775
|
},
|
|
1768
1776
|
"deployment": {
|
|
1769
1777
|
"type": "object",
|
|
1770
|
-
"description": "RFC 0082. The host implements an agent deployment lifecycle: per-(agentId, version) deployment records with the seven-state machine (draft/test/staged/active/paused/deprecated/rolled-back), named-channel binding (`agentId@channel` / `@latest` resolved + pinned per-(run, agentId, channel) at first resolution per
|
|
1778
|
+
"description": "RFC 0082. The host implements an agent deployment lifecycle: per-(agentId, version) deployment records with the seven-state machine (draft/test/staged/active/paused/deprecated/rolled-back), named-channel binding (`agentId@channel` / `@latest` resolved + pinned per-(run, agentId, channel) at first resolution per §B), optional canary traffic-split, a rollback pointer, the content-free `deployment.*` audit events, and the `POST /v1/agents/{agentId}/deployments` promotion contract composing RFC 0049 (`deploy:*` fail-closed scopes) + RFC 0051 (approvalGate) + RFC 0081 (`requiredEval`). Hosts that omit this block reject a `channel`-bearing `AgentRef` with `validation_error` and 501 the deployment endpoint. The promotion endpoint + behavioral lifecycle scenario + reference-host store land at Active → Accepted.",
|
|
1771
1779
|
"additionalProperties": false,
|
|
1772
1780
|
"required": [
|
|
1773
1781
|
"supported"
|
|
@@ -1788,11 +1796,11 @@
|
|
|
1788
1796
|
},
|
|
1789
1797
|
"canary": {
|
|
1790
1798
|
"type": "boolean",
|
|
1791
|
-
"description": "When `true`, the host implements canary traffic-split (a per-run
|
|
1799
|
+
"description": "When `true`, the host implements canary traffic-split (a per-run §B draw assigns the run to one of the channel's active versions by `canaryPercent`). When `false`/absent, the host MUST reject any `canaryPercent < 100`."
|
|
1792
1800
|
},
|
|
1793
1801
|
"rollback": {
|
|
1794
1802
|
"type": "boolean",
|
|
1795
|
-
"description": "When `true`, the host implements the `rollbackPointer` recovery path (active
|
|
1803
|
+
"description": "When `true`, the host implements the `rollbackPointer` recovery path (active→rolled-back restoring a prior version to active)."
|
|
1796
1804
|
},
|
|
1797
1805
|
"states": {
|
|
1798
1806
|
"type": "array",
|
|
@@ -1815,7 +1823,7 @@
|
|
|
1815
1823
|
},
|
|
1816
1824
|
"roster": {
|
|
1817
1825
|
"type": "object",
|
|
1818
|
-
"description": "RFC 0086. The host maintains a standing agent roster: named, tenant-scoped agent INSTANCES (the 'digital-twin employee') that reference a manifest/deployment and own a workflow portfolio, discoverable via GET /v1/agents/roster, with trigger-fired portfolio runs attributed to the member via the content-free `roster.run.initiated` event. REQUIRES `agents.manifestRuntime.supported: true` (a roster entry instantiates a manifest agent). Triggers compose RFC 0052 (schedule) + RFC 0083 (durable work-item bridge)
|
|
1826
|
+
"description": "RFC 0086. The host maintains a standing agent roster: named, tenant-scoped agent INSTANCES (the 'digital-twin employee') that reference a manifest/deployment and own a workflow portfolio, discoverable via GET /v1/agents/roster, with trigger-fired portfolio runs attributed to the member via the content-free `roster.run.initiated` event. REQUIRES `agents.manifestRuntime.supported: true` (a roster entry instantiates a manifest agent). Triggers compose RFC 0052 (schedule) + RFC 0083 (durable work-item bridge) — no new WorkflowTrigger.type; the concrete work surface (a Kanban board) stays a host/vendor extension (§E). Hosts that omit this block do not maintain a roster (the roster reads 501). The roster-management endpoints + behavioral attribution scenario + reference-host store land at Active → Accepted.",
|
|
1819
1827
|
"additionalProperties": false,
|
|
1820
1828
|
"required": [
|
|
1821
1829
|
"supported"
|
|
@@ -1846,7 +1854,7 @@
|
|
|
1846
1854
|
},
|
|
1847
1855
|
"orgChart": {
|
|
1848
1856
|
"type": "object",
|
|
1849
|
-
"description": "RFC 0087. The host maintains a tenant-scoped, DESCRIPTIVE org-chart over RFC 0086 roster members: departments + roles with acyclic `reportsTo` edges + a derived responsibility roll-up, discoverable via GET /v1/agents/org-chart. The load-bearing guarantee (
|
|
1857
|
+
"description": "RFC 0087. The host maintains a tenant-scoped, DESCRIPTIVE org-chart over RFC 0086 roster members: departments + roles with acyclic `reportsTo` edges + a derived responsibility roll-up, discoverable via GET /v1/agents/org-chart. The load-bearing guarantee (§B `org-position-no-authority-escalation`): an org edge confers NO authority — it MUST NOT widen `toolAllowlist` (RFC 0002 §A14), grant an RBAC scope (RFC 0049), or bypass an approval gate (RFC 0051); org position MUST NOT be an authorization input. The schema carries no authority-bearing field, and a conformant host MUST NOT derive authority from position out-of-band. REQUIRES `agents.roster.supported: true` (the chart's members are roster entries). Hosts that omit this block have no org-chart surface (the read 501s). The org-chart-management endpoints + behavioral non-authority scenario + reference-host store land at Active → Accepted.",
|
|
1850
1858
|
"additionalProperties": false,
|
|
1851
1859
|
"required": [
|
|
1852
1860
|
"supported"
|
|
@@ -1854,7 +1862,7 @@
|
|
|
1854
1862
|
"properties": {
|
|
1855
1863
|
"supported": {
|
|
1856
1864
|
"type": "boolean",
|
|
1857
|
-
"description": "REQUIRED when present. When `true`, the host serves the tenant-scoped org-chart + the responsibility roll-up. The
|
|
1865
|
+
"description": "REQUIRED when present. When `true`, the host serves the tenant-scoped org-chart + the responsibility roll-up. The §B non-authority guarantee holds at every `installScope` — it is never gated, weakened, or opt-out."
|
|
1858
1866
|
},
|
|
1859
1867
|
"installScope": {
|
|
1860
1868
|
"type": "string",
|
|
@@ -1870,14 +1878,14 @@
|
|
|
1870
1878
|
},
|
|
1871
1879
|
"responsibilityView": {
|
|
1872
1880
|
"type": "boolean",
|
|
1873
|
-
"description": "When `true`, the host computes the
|
|
1881
|
+
"description": "When `true`, the host computes the §D responsibility roll-up (the union of a department's members' RFC 0086 portfolios) on GET /v1/agents/org-chart/{departmentId}."
|
|
1874
1882
|
}
|
|
1875
1883
|
}
|
|
1876
1884
|
},
|
|
1877
1885
|
"dispatchMapping": {
|
|
1878
1886
|
"type": "boolean",
|
|
1879
1887
|
"default": false,
|
|
1880
|
-
"description": "Phase 6.1 (RFC 0022
|
|
1888
|
+
"description": "Phase 6.1 (RFC 0022 §A). When `true`, host honors `inputMapping` / `outputMapping` / `perWorkerInputMappings` / `perWorkerOutputMappings` on `DispatchConfig` — building child inputs from parent variables before dispatch and harvesting child variables into parent variables on completion. Implies (but does NOT require) `agents.dispatch: true`. Hosts that set `agents.dispatch: true` but omit / `false` this flag MUST refuse workflows that carry non-empty mapping fields at registration with `validation_error` + `details.requiredCapability: 'agents.dispatchMapping'`."
|
|
1881
1889
|
},
|
|
1882
1890
|
"reasoning": {
|
|
1883
1891
|
"type": "object",
|
|
@@ -1908,11 +1916,11 @@
|
|
|
1908
1916
|
"subRunAttestation": {
|
|
1909
1917
|
"type": "boolean",
|
|
1910
1918
|
"default": false,
|
|
1911
|
-
"description": "RFC 0063 (`Active`). When `true`, host honors the optional `outputAttestation` block on `core.subWorkflow`: computes a content checksum (RFC 8785 JCS + SHA-256, the `replay.md` recipe) over a child's harvested outputs and surfaces it as the additive optional `attestation` object on the existing `core.workflowChain.event { phase: 'output.harvested' }` (RFC 0037) BEFORE applying `outputMapping`; when the config sets `requireApproval: true`, suspends the parent via an `approval` interrupt (RFC 0051) before merge and fails closed (no `accept`/`edit-accept`
|
|
1919
|
+
"description": "RFC 0063 (`Active`). When `true`, host honors the optional `outputAttestation` block on `core.subWorkflow`: computes a content checksum (RFC 8785 JCS + SHA-256, the `replay.md` recipe) over a child's harvested outputs and surfaces it as the additive optional `attestation` object on the existing `core.workflowChain.event { phase: 'output.harvested' }` (RFC 0037) BEFORE applying `outputMapping`; when the config sets `requireApproval: true`, suspends the parent via an `approval` interrupt (RFC 0051) before merge and fails closed (no `accept`/`edit-accept` ⇒ no merge). Reuses RFC 0051's `approval` kind + RFC 0049 scopes for `principalScope` — no new interrupt kind, event type, or error code. Hosts that omit / `false` this flag treat `outputAttestation` as inert (blind merge, today's behavior)."
|
|
1912
1920
|
},
|
|
1913
1921
|
"proposals": {
|
|
1914
1922
|
"type": "object",
|
|
1915
|
-
"description": "RFC 0096 (`Active`). Reviewable learning
|
|
1923
|
+
"description": "RFC 0096 (`Active`). Reviewable learning — the host synthesizes reusable artifacts (skills/packs/templates/automations) from run/tool traces as INERT, reviewable drafts that MUST NOT influence the resolution, planning, or execution of any run until an authorized principal activates them. A host advertising this serves the `/v1/host/sample/proposals` surface (promotable to `/v1/proposals`) and emits the content-free `proposal.created` / `proposal.activated` events. Activation is delegated to RFC 0051 approval-gate or RFC 0049 RBAC — no new authorization path. On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis). Hosts that omit this block do not synthesize proposals; the conformance scenarios skip cleanly.",
|
|
1916
1924
|
"additionalProperties": false,
|
|
1917
1925
|
"required": [
|
|
1918
1926
|
"artifactKinds",
|
|
@@ -1950,7 +1958,7 @@
|
|
|
1950
1958
|
},
|
|
1951
1959
|
"goals": {
|
|
1952
1960
|
"type": "object",
|
|
1953
|
-
"description": "RFC 0097 (`Active`). Standing goals
|
|
1961
|
+
"description": "RFC 0097 (`Active`). Standing goals — a durable objective with explicit completion criteria, evaluated by a host-side judge (RFC 0090 verifier or host evaluator), that keeps an agent working across turns/runs until the judge is satisfied, a declared RFC 0058 bound is crossed, or the agent escalates (RFC 0044). A host advertising this serves `/v1/host/sample/goals` (promotable to `/v1/goals`) and emits the content-free `goal.evaluated` / `goal.closed` events. Completion MUST be the judge's verdict — a client MUST NOT set `state: satisfied` directly. Continuation MUST be bounded. Hosts that omit this block do not run standing goals; the conformance scenarios skip cleanly.",
|
|
1954
1962
|
"additionalProperties": false,
|
|
1955
1963
|
"required": [
|
|
1956
1964
|
"judge",
|
|
@@ -1995,7 +2003,7 @@
|
|
|
1995
2003
|
"properties": {
|
|
1996
2004
|
"supported": {
|
|
1997
2005
|
"type": "boolean",
|
|
1998
|
-
"description": "When `true`, host implements the four-operation MemoryAdapter contract (`list`, `get`, `put`, `delete`) per RFC 0004
|
|
2006
|
+
"description": "When `true`, host implements the four-operation MemoryAdapter contract (`list`, `get`, `put`, `delete`) per RFC 0004 §A."
|
|
1999
2007
|
},
|
|
2000
2008
|
"maxEntrySizeBytes": {
|
|
2001
2009
|
"type": "integer",
|
|
@@ -2004,7 +2012,7 @@
|
|
|
2004
2012
|
},
|
|
2005
2013
|
"ttlSupported": {
|
|
2006
2014
|
"type": "boolean",
|
|
2007
|
-
"description": "When `true`, host honors `expiresAt` per RFC 0004
|
|
2015
|
+
"description": "When `true`, host honors `expiresAt` per RFC 0004 §E."
|
|
2008
2016
|
},
|
|
2009
2017
|
"compaction": {
|
|
2010
2018
|
"type": "object",
|
|
@@ -2015,7 +2023,7 @@
|
|
|
2015
2023
|
"properties": {
|
|
2016
2024
|
"supported": {
|
|
2017
2025
|
"type": "boolean",
|
|
2018
|
-
"description": "REQUIRED when the sub-block is present. When `true`, host performs compaction over `longTerm` memory and emits the `memory.compacted` event per `observability.md`
|
|
2026
|
+
"description": "REQUIRED when the sub-block is present. When `true`, host performs compaction over `longTerm` memory and emits the `memory.compacted` event per `observability.md` §Canonical event vocabulary."
|
|
2019
2027
|
},
|
|
2020
2028
|
"trigger": {
|
|
2021
2029
|
"type": "string",
|
|
@@ -2024,7 +2032,7 @@
|
|
|
2024
2032
|
"client-requested",
|
|
2025
2033
|
"both"
|
|
2026
2034
|
],
|
|
2027
|
-
"description": "REQUIRED when `supported: true` per RFC 0012
|
|
2035
|
+
"description": "REQUIRED when `supported: true` per RFC 0012 §A (enforced via the `if/then` clause). `host-managed` runs on a host-internal schedule clients do not control. `client-requested` and `both` are reserved enum values; v1.x normates only `host-managed`."
|
|
2028
2036
|
},
|
|
2029
2037
|
"maxInputEntries": {
|
|
2030
2038
|
"type": "integer",
|
|
@@ -2034,7 +2042,7 @@
|
|
|
2034
2042
|
"maxOutputBytes": {
|
|
2035
2043
|
"type": "integer",
|
|
2036
2044
|
"minimum": 0,
|
|
2037
|
-
"description": "Informational ceiling on the distilled entry size. SHOULD be
|
|
2045
|
+
"description": "Informational ceiling on the distilled entry size. SHOULD be ≤ `memory.maxEntrySizeBytes`."
|
|
2038
2046
|
}
|
|
2039
2047
|
},
|
|
2040
2048
|
"additionalProperties": false,
|
|
@@ -2057,7 +2065,7 @@
|
|
|
2057
2065
|
},
|
|
2058
2066
|
"distillation": {
|
|
2059
2067
|
"type": "object",
|
|
2060
|
-
"description": "RFC 0062 (`Active`). Scheduled, token-budgeted background compaction
|
|
2068
|
+
"description": "RFC 0062 (`Active`). Scheduled, token-budgeted background compaction — the 'dream' pattern — built on compaction (RFC 0012) + scheduling (RFC 0052) + the workspace index (RFC 0059). A distillation run IS a compaction run with a mandatory token budget, an optional schedule, and a retrieval index wrapped around it; it reuses the `memory.compacted` event (extended with the additive optional `distillation` sub-object) rather than a parallel `memory.distilled` event. SR-1 carry-forward (RFC 0012 §D) holds — a distilled archive MUST NOT re-expose a redacted secret. Hosts that omit this block keep plain on-demand compaction (RFC 0012) or no memory.",
|
|
2061
2069
|
"required": [
|
|
2062
2070
|
"supported"
|
|
2063
2071
|
],
|
|
@@ -2070,7 +2078,7 @@
|
|
|
2070
2078
|
"maxTokenBudget": {
|
|
2071
2079
|
"type": "integer",
|
|
2072
2080
|
"minimum": 1,
|
|
2073
|
-
"description": "Largest per-run distillation token budget the host honors. A supplied `distillation.tokenBudget` is clamped to this; absent
|
|
2081
|
+
"description": "Largest per-run distillation token budget the host honors. A supplied `distillation.tokenBudget` is clamped to this; absent ⇒ the host defaults to this."
|
|
2074
2082
|
},
|
|
2075
2083
|
"scheduled": {
|
|
2076
2084
|
"type": "boolean",
|
|
@@ -2082,7 +2090,7 @@
|
|
|
2082
2090
|
},
|
|
2083
2091
|
"tokenizerName": {
|
|
2084
2092
|
"type": "string",
|
|
2085
|
-
"description": "Identifier of the tokenizer the budget is counted against (e.g. `claude`, `gpt-4`). The budget is best-effort-honest per this tokenizer (
|
|
2093
|
+
"description": "Identifier of the tokenizer the budget is counted against (e.g. `claude`, `gpt-4`). The budget is best-effort-honest per this tokenizer (±10% conformance tolerance), not byte-exact."
|
|
2086
2094
|
},
|
|
2087
2095
|
"archiveRetention": {
|
|
2088
2096
|
"type": "string",
|
|
@@ -2110,11 +2118,11 @@
|
|
|
2110
2118
|
},
|
|
2111
2119
|
"writable": {
|
|
2112
2120
|
"type": "boolean",
|
|
2113
|
-
"description": "RFC 0080
|
|
2121
|
+
"description": "RFC 0080 §A (`write` dimension). Absent ⇒ the host implements the full RFC 0004 four-operation MemoryAdapter (`put`/`delete` available — i.e. writable), the back-compatible default. A read-only host (`get`/`list` only) MUST set `writable: false` so a consumer can distinguish a read-only store from a read/write one. Only meaningful when `supported: true`."
|
|
2114
2122
|
},
|
|
2115
2123
|
"search": {
|
|
2116
2124
|
"type": "object",
|
|
2117
|
-
"description": "RFC 0080
|
|
2125
|
+
"description": "RFC 0080 §A (`search` dimension) — NEW optional. Semantic or filtered query beyond the RFC 0004 `list` enumeration. Absent ⇒ only `list`/`get` retrieval is advertised. The query path itself stays the host-internal MemoryAdapter (RFC 0080 §B — no portable `GET /v1/memory` at v1.x).",
|
|
2118
2126
|
"required": [
|
|
2119
2127
|
"supported"
|
|
2120
2128
|
],
|
|
@@ -2134,13 +2142,13 @@
|
|
|
2134
2142
|
]
|
|
2135
2143
|
},
|
|
2136
2144
|
"uniqueItems": true,
|
|
2137
|
-
"description": "The query modes the host supports. `semantic` = embedding/similarity retrieval; `filter` = structured predicate query over entry metadata. Omitted
|
|
2145
|
+
"description": "The query modes the host supports. `semantic` = embedding/similarity retrieval; `filter` = structured predicate query over entry metadata. Omitted ⇒ unspecified mode (the host supports some query beyond `list`)."
|
|
2138
2146
|
}
|
|
2139
2147
|
}
|
|
2140
2148
|
},
|
|
2141
2149
|
"retention": {
|
|
2142
2150
|
"type": "object",
|
|
2143
|
-
"description": "RFC 0080
|
|
2151
|
+
"description": "RFC 0080 §A (`retention/forget` dimension) — NEW optional. TTL expiry (`agent-memory.md §TTL`) and/or an explicit forget operation. Absent ⇒ no TTL beyond `ttlSupported` and no forget operation advertised. `forget` is a host-managed mutation OUTSIDE the replay envelope (RFC 0080 §UQ3 / `replay.md` §Recorded-fact events — a replay re-reads the log-recorded snapshot, not live memory).",
|
|
2144
2152
|
"additionalProperties": false,
|
|
2145
2153
|
"properties": {
|
|
2146
2154
|
"ttl": {
|
|
@@ -2149,13 +2157,13 @@
|
|
|
2149
2157
|
},
|
|
2150
2158
|
"forget": {
|
|
2151
2159
|
"type": "boolean",
|
|
2152
|
-
"description": "When `true`, the host supports a tenant-scoped delete-by-subject forget operation (composes the CTI-1 cross-tenant invariant
|
|
2160
|
+
"description": "When `true`, the host supports a tenant-scoped delete-by-subject forget operation (composes the CTI-1 cross-tenant invariant — a forget MUST NOT cross tenant boundaries)."
|
|
2153
2161
|
}
|
|
2154
2162
|
}
|
|
2155
2163
|
},
|
|
2156
2164
|
"injectionBudget": {
|
|
2157
2165
|
"type": "object",
|
|
2158
|
-
"description": "RFC 0113 (`Active`). The host honors `MemoryListOptions.tokenBudget`
|
|
2166
|
+
"description": "RFC 0113 (`Active`). The host honors `MemoryListOptions.tokenBudget` — a token-denominated bound on a single injection read (the live read that feeds a turn), distinct from RFC 0062 distillation's background-compaction budget. Advertising it commits the host to return a token-bounded prefix of the ranked entry list (over-budget single entry omitted, never truncated mid-entry) over the SR-1-redacted, CTI-1-single-tenant result set. Relevance ranking is NOT advertised here — `rank:'relevance'` delegates to the existing `memory.search` semantic mode (RFC 0080), so there is exactly one relevance surface in the corpus. Hosts that omit this block do not honor `tokenBudget` (a supplied `tokenBudget` is ignored, today's `limit`/`tag` behavior).",
|
|
2159
2167
|
"additionalProperties": false,
|
|
2160
2168
|
"required": [
|
|
2161
2169
|
"supported"
|
|
@@ -2163,7 +2171,7 @@
|
|
|
2163
2171
|
"properties": {
|
|
2164
2172
|
"supported": {
|
|
2165
2173
|
"type": "boolean",
|
|
2166
|
-
"description": "REQUIRED when the sub-block is present. When `true`, the host honors `MemoryListOptions.tokenBudget` per `agent-memory.md`
|
|
2174
|
+
"description": "REQUIRED when the sub-block is present. When `true`, the host honors `MemoryListOptions.tokenBudget` per `agent-memory.md` §\"Injection budget\"."
|
|
2167
2175
|
},
|
|
2168
2176
|
"tokenCounter": {
|
|
2169
2177
|
"type": "string",
|
|
@@ -2173,7 +2181,7 @@
|
|
|
2173
2181
|
"chars",
|
|
2174
2182
|
"host-defined"
|
|
2175
2183
|
],
|
|
2176
|
-
"description": "The unit `tokenBudget` is denominated in. REQUIRED when `injectionBudget.supported` (enforced via the `if/then` clause). `o200k_base`/`cl100k_base` are tokenizer encodings; `chars` counts UTF-8/Unicode characters of the entry `content` (a tokenizer-free unit a client can reason about directly
|
|
2184
|
+
"description": "The unit `tokenBudget` is denominated in. REQUIRED when `injectionBudget.supported` (enforced via the `if/then` clause). `o200k_base`/`cl100k_base` are tokenizer encodings; `chars` counts UTF-8/Unicode characters of the entry `content` (a tokenizer-free unit a client can reason about directly — preferred over opaque `host-defined`); `host-defined` is an opaque host unit. The over-budget-single-entry-omitted rule applies regardless of unit. RFC 0111 aligns to these same values when it lands (0113 lands first); no shared `$ref` (decoupled)."
|
|
2177
2185
|
}
|
|
2178
2186
|
},
|
|
2179
2187
|
"if": {
|
|
@@ -2202,19 +2210,19 @@
|
|
|
2202
2210
|
},
|
|
2203
2211
|
"subWorkflow": {
|
|
2204
2212
|
"type": "object",
|
|
2205
|
-
"description": "Capability surface for `core.subWorkflow` extensions. The baseline `core.subWorkflow` contract (RFC 0007 + `node-packs.md`
|
|
2213
|
+
"description": "Capability surface for `core.subWorkflow` extensions. The baseline `core.subWorkflow` contract (RFC 0007 + `node-packs.md` §contract) is unconditional and does NOT require a capability flag; this object carries the additive extensions a host MAY support. Added by RFC 0022 §B + §C.",
|
|
2206
2214
|
"properties": {
|
|
2207
2215
|
"inputMapping": {
|
|
2208
2216
|
"type": "boolean",
|
|
2209
2217
|
"default": false,
|
|
2210
|
-
"description": "RFC 0022
|
|
2218
|
+
"description": "RFC 0022 §B. When `true`, host honors the `inputMapping` field on `core.subWorkflow` configs — seeding the child workflow's initial variable bag from `parentVariables[parentKey]` projections, overriding any matching `variables[].defaultValue` declaration on the child. When `false` or absent, hosts MUST refuse workflows that carry a non-empty `inputMapping` at registration with `validation_error` + `details.requiredCapability: 'subWorkflow.inputMapping'`. Silent ignore is NOT conformant."
|
|
2211
2219
|
}
|
|
2212
2220
|
},
|
|
2213
2221
|
"additionalProperties": false
|
|
2214
2222
|
},
|
|
2215
2223
|
"fs": {
|
|
2216
2224
|
"type": "object",
|
|
2217
|
-
"description": "RFC 0014 (`Active`). Filesystem capability
|
|
2225
|
+
"description": "RFC 0014 (`Active`). Filesystem capability — read/write/list/stat/delete inside a sandbox root. Required by the `core.openwop.files` pack. Hosts MUST resolve every input path relative to `sandboxRoot`, reject any path that escapes via `..` segments or symlinks, and enforce `maxFileSizeBytes` on write. Path-traversal rejection is normative — see `SECURITY/invariants.yaml` row `fs-path-traversal`.",
|
|
2218
2226
|
"properties": {
|
|
2219
2227
|
"supported": {
|
|
2220
2228
|
"type": "boolean",
|
|
@@ -2351,7 +2359,7 @@
|
|
|
2351
2359
|
},
|
|
2352
2360
|
"queueBus": {
|
|
2353
2361
|
"type": "object",
|
|
2354
|
-
"description": "RFC 0017 (`Active`). Inbound queue + stream capability
|
|
2362
|
+
"description": "RFC 0017 (`Active`). Inbound queue + stream capability — publish, consume (trigger), ack/nack/dead-letter. Cross-tenant message isolation invariant (`queue-cross-tenant-isolation`). Sibling to host.messaging (which is outbound-egress-only).",
|
|
2355
2363
|
"properties": {
|
|
2356
2364
|
"supported": {
|
|
2357
2365
|
"type": "boolean"
|
|
@@ -2393,7 +2401,7 @@
|
|
|
2393
2401
|
},
|
|
2394
2402
|
"scheduling": {
|
|
2395
2403
|
"type": "object",
|
|
2396
|
-
"description": "RFC 0052 (`Draft`). Time-based run initiation behind the `schedule` trigger
|
|
2404
|
+
"description": "RFC 0052 (`Draft`). Time-based run initiation behind the `schedule` trigger — gives the trigger a portable, durable, once-per-tick execution contract. Composes with `queueBus` (RFC 0017) where the host backs scheduling with a queue; orthogonal to the in-DAG `core.control.delay` primitive (which delays a node mid-run, not run initiation).",
|
|
2397
2405
|
"required": [
|
|
2398
2406
|
"supported"
|
|
2399
2407
|
],
|
|
@@ -2445,7 +2453,7 @@
|
|
|
2445
2453
|
},
|
|
2446
2454
|
"toolHooks": {
|
|
2447
2455
|
"type": "object",
|
|
2448
|
-
"description": "RFC 0064 (`Active`)
|
|
2456
|
+
"description": "RFC 0064 (`Active`) — sibling of `heartbeat`. Per-tool authorization + rate limiting + content-free tool-call audit fields, layered on the existing `agent.toolCalled` / `agent.toolReturned` events (RFC 0002). Generalizes the MCP-specific bridges across transports (mcp / http / native). Reuses RFC 0049's `forbidden` error + `authorization-fail-closed` invariant and the existing `rate_limited` error — no new event type, error code, or invariant.",
|
|
2449
2457
|
"required": [
|
|
2450
2458
|
"supported"
|
|
2451
2459
|
],
|
|
@@ -2470,7 +2478,7 @@
|
|
|
2470
2478
|
},
|
|
2471
2479
|
"toolCatalog": {
|
|
2472
2480
|
"type": "object",
|
|
2473
|
-
"description": "RFC 0078 (`Active`). The host exposes a read-only projection of its tool surfaces (node-pack / workflow / MCP / connector / host-extension) at `GET /v1/tools` + `GET /v1/tools/{toolId}`, returning `ToolDescriptor` records (`tool-descriptor.schema.json`). Optional; hosts that omit it expose no catalog (today's behavior) and the conformance scenarios skip cleanly. Read-only
|
|
2481
|
+
"description": "RFC 0078 (`Active`). The host exposes a read-only projection of its tool surfaces (node-pack / workflow / MCP / connector / host-extension) at `GET /v1/tools` + `GET /v1/tools/{toolId}`, returning `ToolDescriptor` records (`tool-descriptor.schema.json`). Optional; hosts that omit it expose no catalog (today's behavior) and the conformance scenarios skip cleanly. Read-only — the catalog never mutates tools; tool invocation stays on the existing surfaces (agent dispatch, `core.dispatch`, MCP). The listing is authorization-scoped + non-disclosing (RFC 0074 pattern).",
|
|
2474
2482
|
"required": [
|
|
2475
2483
|
"supported"
|
|
2476
2484
|
],
|
|
@@ -2478,7 +2486,7 @@
|
|
|
2478
2486
|
"properties": {
|
|
2479
2487
|
"supported": {
|
|
2480
2488
|
"type": "boolean",
|
|
2481
|
-
"description": "REQUIRED when present. `true`
|
|
2489
|
+
"description": "REQUIRED when present. `true` ⇒ `GET /v1/tools` + `GET /v1/tools/{toolId}` are served per RFC 0078 §B."
|
|
2482
2490
|
},
|
|
2483
2491
|
"sources": {
|
|
2484
2492
|
"type": "array",
|
|
@@ -2493,21 +2501,21 @@
|
|
|
2493
2501
|
"host-extension"
|
|
2494
2502
|
]
|
|
2495
2503
|
},
|
|
2496
|
-
"description": "Which tool sources the catalog projects. A host advertises only the sources it actually surfaces; a consumer MUST tolerate any subset. Absent
|
|
2504
|
+
"description": "Which tool sources the catalog projects. A host advertises only the sources it actually surfaces; a consumer MUST tolerate any subset. Absent ⇒ all sources the host implements."
|
|
2497
2505
|
},
|
|
2498
2506
|
"sessionLifecycle": {
|
|
2499
2507
|
"type": "boolean",
|
|
2500
|
-
"description": "`true`
|
|
2508
|
+
"description": "`true` ⇒ the host emits the RFC 0078 §D tool-session lifecycle events (`tool.session.opened`/`tool.session.closed`, content-free) bracketing the existing RFC 0064 `agent.toolCalled`/`agent.toolReturned` call events for multi-step interactions. Absent ⇒ `false` (single-shot tool calls only)."
|
|
2501
2509
|
},
|
|
2502
2510
|
"compactView": {
|
|
2503
2511
|
"type": "boolean",
|
|
2504
|
-
"description": "RFC 0112. `true`
|
|
2512
|
+
"description": "RFC 0112. `true` ⇒ the host honors `GET /v1/tools?view=compact` + `GET /v1/tools/{toolId}?view=compact`, returning the `{ tools: CompactToolDescriptor[] }` projection (`compact-tool-descriptor.schema.json`): the heavy descriptor fields (`outputSchema`/`auth`/`egress`/`approval`/`replayPolicy`/`costHint`/`latencyHint`) are dropped and any `inputSchema` is bounded to the compact structural subset. The compact `tools[]` carries the same `toolId` set as the standard view for the same principal. Absent ⇒ the host treats `view=compact` as an unknown query param (standard view)."
|
|
2505
2513
|
}
|
|
2506
2514
|
}
|
|
2507
2515
|
},
|
|
2508
2516
|
"httpClient": {
|
|
2509
2517
|
"type": "object",
|
|
2510
|
-
"description": "Host outbound-HTTP surface. The host's HTTP-client node egress (e.g. `core.http.request`) MUST be SSRF-guarded (`ssrfGuard: true`) with a positive `maxResponseBodyBytes` cap
|
|
2518
|
+
"description": "Host outbound-HTTP surface. The host's HTTP-client node egress (e.g. `core.http.request`) MUST be SSRF-guarded (`ssrfGuard: true`) with a positive `maxResponseBodyBytes` cap — the `http-client-ssrf-guard` protocol invariant. RFC 0076 §B adds the OPTIONAL `safeFetch` sub-capability: a host-mediated `ctx.http.safeFetch(url, init?)` exposed to pack runtime code, backed by the SAME SSRF guard (resolve→pin→connect, metadata-endpoint blocklist, DNS-rebinding defeat) so packs need not reach for raw DNS/sockets. See `host-capabilities.md` §host.http.",
|
|
2511
2519
|
"required": [
|
|
2512
2520
|
"supported"
|
|
2513
2521
|
],
|
|
@@ -2518,7 +2526,7 @@
|
|
|
2518
2526
|
},
|
|
2519
2527
|
"ssrfGuard": {
|
|
2520
2528
|
"type": "boolean",
|
|
2521
|
-
"description": "Host rejects egress to loopback / RFC 1918 / link-local / cloud-metadata addresses (resolve
|
|
2529
|
+
"description": "Host rejects egress to loopback / RFC 1918 / link-local / cloud-metadata addresses (resolve→pin→connect). MUST be `true` when `supported` (the `http-client-ssrf-guard` invariant)."
|
|
2522
2530
|
},
|
|
2523
2531
|
"maxResponseBodyBytes": {
|
|
2524
2532
|
"type": "integer",
|
|
@@ -2539,7 +2547,7 @@
|
|
|
2539
2547
|
},
|
|
2540
2548
|
"safeFetch": {
|
|
2541
2549
|
"type": "object",
|
|
2542
|
-
"description": "RFC 0076
|
|
2550
|
+
"description": "RFC 0076 §B. Host-provided `ctx.http.safeFetch(url, init?)` for pack runtime code — the pack-facing exposure of the SSRF-guarded client. When advertised, the host MUST apply the §host.http SSRF defense + clamps (incl. refusing `Connection: upgrade`), and — when `toolHooks.prePostEvents` is also advertised — MUST emit the `agent.toolCalled`/`agent.toolReturned` pair (`transport: 'http'`) for each call. A pack that uses `safeFetch` need not declare `net.dns` in `runtime.requires` (the host owns resolution; RFC 0076 §A).",
|
|
2543
2551
|
"required": [
|
|
2544
2552
|
"supported"
|
|
2545
2553
|
],
|
|
@@ -2553,14 +2561,14 @@
|
|
|
2553
2561
|
"egressPolicy": {
|
|
2554
2562
|
"type": "object",
|
|
2555
2563
|
"additionalProperties": false,
|
|
2556
|
-
"description": "RFC 0079. The host evaluates credential provenance (`credential-provenance.schema.json`) + the audience-binding MUST (
|
|
2564
|
+
"description": "RFC 0079. The host evaluates credential provenance (`credential-provenance.schema.json`) + the audience-binding MUST (§C) on credentialed egress and emits `egress.decided` (§B). Requires `httpClient.safeFetch` (the egress mechanism). Absent ⇒ the host does not perform provenance binding (the RFC 0076 §B SSRF guard still applies); the conformance behavioral scenarios skip cleanly. Closes the credential↔destination-binding question RFC 0076 §B parked.",
|
|
2557
2565
|
"required": [
|
|
2558
2566
|
"supported"
|
|
2559
2567
|
],
|
|
2560
2568
|
"properties": {
|
|
2561
2569
|
"supported": {
|
|
2562
2570
|
"type": "boolean",
|
|
2563
|
-
"description": "REQUIRED when present. `true`
|
|
2571
|
+
"description": "REQUIRED when present. `true` ⇒ the §C audience-binding MUST is enforced + `egress.decided` is emitted."
|
|
2564
2572
|
},
|
|
2565
2573
|
"decisions": {
|
|
2566
2574
|
"type": "array",
|
|
@@ -2574,7 +2582,7 @@
|
|
|
2574
2582
|
"approval-required"
|
|
2575
2583
|
]
|
|
2576
2584
|
},
|
|
2577
|
-
"description": "MAY
|
|
2585
|
+
"description": "MAY — which decision outcomes the host implements. Absent ⇒ at least `allowed` + `denied`."
|
|
2578
2586
|
}
|
|
2579
2587
|
}
|
|
2580
2588
|
}
|
|
@@ -2582,20 +2590,20 @@
|
|
|
2582
2590
|
},
|
|
2583
2591
|
"artifactTypes": {
|
|
2584
2592
|
"type": "object",
|
|
2585
|
-
"description": "RFC 0071, amended by RFC 0075; declared by RFC 0144. Host artifact-type surface
|
|
2593
|
+
"description": "RFC 0071, amended by RFC 0075; declared by RFC 0144. Host artifact-type surface — an advertisement (no `ctx.artifactTypes.*` method) that changes how the host treats the artifact references already on the wire (`nodes[].artifact.typeId`, `WorkflowNode.artifactType`, `artifact.created.artifactType`). Carries the corpus's only emission MUST: a host advertising `store: true` MUST persist registered artifacts and emit `artifact.created`. See `host-capabilities.md` §host.artifactTypes and `artifact-type-packs.md` §\"Host capability\". The discovery key is the PLAIN family name at the document root (RFC 0137 G16); `host.artifactTypes` is the capability IDENTIFIER used in pack `peerDependencies`, not this key.",
|
|
2586
2594
|
"additionalProperties": false,
|
|
2587
2595
|
"properties": {
|
|
2588
2596
|
"supported": {
|
|
2589
2597
|
"type": "boolean",
|
|
2590
|
-
"description": "Host honors registered artifact types
|
|
2598
|
+
"description": "Host honors registered artifact types — validates an artifact whose type is registered (pack-installed or host-native) against that type's schema before emitting `artifact.created`, setting `registered: true` + `registrationSource`. Unregistered types stay accepted unvalidated with `registered: false`."
|
|
2591
2599
|
},
|
|
2592
2600
|
"store": {
|
|
2593
2601
|
"type": "boolean",
|
|
2594
|
-
"description": "`true`
|
|
2602
|
+
"description": "`true` ⇒ the host persists artifacts of registered types AND emits `artifact.created`. Advertising this is a commitment to emit; RFC 0142 leg B is the witness."
|
|
2595
2603
|
},
|
|
2596
2604
|
"render": {
|
|
2597
2605
|
"type": "boolean",
|
|
2598
|
-
"description": "Advisory
|
|
2606
|
+
"description": "Advisory — the spec defines no rendering surface. A host advertising `false` for a type it can `store` MUST still accept and store the artifact and MUST NOT fail the run for lack of a renderer (the store-without-render negotiation guarantee)."
|
|
2599
2607
|
},
|
|
2600
2608
|
"export": {
|
|
2601
2609
|
"type": "array",
|
|
@@ -2606,14 +2614,14 @@
|
|
|
2606
2614
|
},
|
|
2607
2615
|
"types": {
|
|
2608
2616
|
"type": "object",
|
|
2609
|
-
"description": "RFC 0075 per-type facets, keyed by `artifactTypeId`. Each entry overrides the global object for that type; the global object is the fallback for any type not listed (absent
|
|
2617
|
+
"description": "RFC 0075 per-type facets, keyed by `artifactTypeId`. Each entry overrides the global object for that type; the global object is the fallback for any type not listed (absent ⇒ host-global semantics; any facet absent ⇒ the global default — additive).",
|
|
2610
2618
|
"additionalProperties": {
|
|
2611
2619
|
"type": "object",
|
|
2612
2620
|
"additionalProperties": false,
|
|
2613
2621
|
"properties": {
|
|
2614
2622
|
"validated": {
|
|
2615
2623
|
"type": "boolean",
|
|
2616
|
-
"description": "The runtime validation guarantee
|
|
2624
|
+
"description": "The runtime validation guarantee — `true` ⇒ the host validates this type before emit, so emits `registered: true`. Decoupled from `schemaVersions`, which is a version DECLARATION only."
|
|
2617
2625
|
},
|
|
2618
2626
|
"validation": {
|
|
2619
2627
|
"type": "string",
|
|
@@ -2621,7 +2629,7 @@
|
|
|
2621
2629
|
"open",
|
|
2622
2630
|
"closed"
|
|
2623
2631
|
],
|
|
2624
|
-
"description": "Mirrors `ArtifactType.validation`, surfacing schema strictness in discovery so a consumer needn't fetch the schema. Default `\"open\"` per `COMPATIBILITY.md`
|
|
2632
|
+
"description": "Mirrors `ArtifactType.validation`, surfacing schema strictness in discovery so a consumer needn't fetch the schema. Default `\"open\"` per `COMPATIBILITY.md` §2.1."
|
|
2625
2633
|
},
|
|
2626
2634
|
"schemaVersion": {
|
|
2627
2635
|
"type": "integer",
|
|
@@ -2633,7 +2641,7 @@
|
|
|
2633
2641
|
"pack",
|
|
2634
2642
|
"host"
|
|
2635
2643
|
],
|
|
2636
|
-
"description": "RFC 0145. Provenance of this registered type: `pack` (an installed artifact-type pack backs it) or `host` (host-native, validated against a host-known schema with no pack). Mirrors `artifact.created.registrationSource` and MUST match what the host would emit for this type
|
|
2644
|
+
"description": "RFC 0145. Provenance of this registered type: `pack` (an installed artifact-type pack backs it) or `host` (host-native, validated against a host-known schema with no pack). Mirrors `artifact.created.registrationSource` and MUST match what the host would emit for this type — the two surfaces MUST NOT disagree. OPTIONAL; absent ⇒ unspecified provenance, NOT a default of `pack`. Discloses which §\"Schema distribution\" regime applies: serving the canonical schema URL is a MUST for host-registered (no-pack) types and only a SHOULD for pack-backed ones, and nothing else in the advert reveals which. A host MUST NOT infer this from the identifier's shape — `vendor.*` is a registry namespace, not an installation claim."
|
|
2637
2645
|
},
|
|
2638
2646
|
"store": {
|
|
2639
2647
|
"type": "boolean"
|
|
@@ -2654,49 +2662,49 @@
|
|
|
2654
2662
|
},
|
|
2655
2663
|
"forms": {
|
|
2656
2664
|
"type": "object",
|
|
2657
|
-
"description": "RFC 0137; declared by RFC 0144. Host form-content-pack surface
|
|
2665
|
+
"description": "RFC 0137; declared by RFC 0144. Host form-content-pack surface — like `artifactTypes` it adds no `ctx.forms.*` method; it advertises that the host resolves registered form templates from installed `kind: \"form-content\"` packs and instantiates them through its own normal create path. See `host-capabilities.md` §host.forms and `form-content-packs.md`. The discovery key is the PLAIN family name at the document root (RFC 0137 G16); a host may additionally carry a deprecated dotted `\"host.forms\"` mirror during migration — root `additionalProperties` stays `true` so that document remains valid.",
|
|
2658
2666
|
"additionalProperties": false,
|
|
2659
2667
|
"properties": {
|
|
2660
2668
|
"contentPacks": {
|
|
2661
2669
|
"type": "boolean",
|
|
2662
|
-
"description": "`true`
|
|
2670
|
+
"description": "`true` ⇒ the host instantiates registered form templates. Normative consequences (`form-content-packs.md` §\"Instantiation\"): create through the SAME path a hand-authored form uses; degrade an unrecognized field type to a plain text input rather than failing; keep the instantiated form fully editable; execute nothing from the pack; sanitize/validate/authorize submissions exactly as hand-typed input. Pack-authored strings are UNTRUSTED and MUST propagate `meta.contentTrust: \"untrusted\"` into interpolated prompt segments (invariant `form-content-pack-string-trust-boundary`) — a signature proves authorship, not content safety."
|
|
2663
2671
|
}
|
|
2664
2672
|
}
|
|
2665
2673
|
},
|
|
2666
2674
|
"aiEnvelope": {
|
|
2667
2675
|
"type": "object",
|
|
2668
|
-
"description": "Declared by RFC 0144. Host typed-envelope generation surface (`ctx.aiEnvelope.generate`), routing the call through the host's BYOK provider layer. Opinionated about envelope shape, unlike the lower-level `aiProviders` capability which returns raw model output. See `host-capabilities.md`
|
|
2676
|
+
"description": "Declared by RFC 0144. Host typed-envelope generation surface (`ctx.aiEnvelope.generate`), routing the call through the host's BYOK provider layer. Opinionated about envelope shape, unlike the lower-level `aiProviders` capability which returns raw model output. See `host-capabilities.md` §host.aiEnvelope and `ai-envelope.md`.",
|
|
2669
2677
|
"additionalProperties": false,
|
|
2670
2678
|
"properties": {
|
|
2671
2679
|
"supported": {
|
|
2672
2680
|
"type": "boolean",
|
|
2673
|
-
"description": "`true`
|
|
2681
|
+
"description": "`true` ⇒ `ctx.aiEnvelope.generate` is exposed. Absent/`false` ⇒ packs binding this surface fail with `host_capability_missing`."
|
|
2674
2682
|
},
|
|
2675
2683
|
"await": {
|
|
2676
2684
|
"type": "boolean",
|
|
2677
|
-
"description": "`true`
|
|
2685
|
+
"description": "`true` ⇒ `ctx.aiEnvelope.await` is ALSO exposed. `generate` is required whenever the family is advertised; `await` is required only when this sub-flag is."
|
|
2678
2686
|
}
|
|
2679
2687
|
}
|
|
2680
2688
|
},
|
|
2681
2689
|
"promptLibrary": {
|
|
2682
2690
|
"type": "object",
|
|
2683
|
-
"description": "Declared by RFC 0144. Host prompt-lookup surface (`ctx.promptLibrary.get`), returning a prompt pinned to a specific version so replay stays deterministic. Consumed by `core.ai.callPrompt`. See `host-capabilities.md`
|
|
2691
|
+
"description": "Declared by RFC 0144. Host prompt-lookup surface (`ctx.promptLibrary.get`), returning a prompt pinned to a specific version so replay stays deterministic. Consumed by `core.ai.callPrompt`. See `host-capabilities.md` §host.promptLibrary.",
|
|
2684
2692
|
"additionalProperties": false,
|
|
2685
2693
|
"properties": {
|
|
2686
2694
|
"supported": {
|
|
2687
2695
|
"type": "boolean",
|
|
2688
|
-
"description": "`true`
|
|
2696
|
+
"description": "`true` ⇒ `ctx.promptLibrary.get(promptId)` resolves a `{ promptId, systemPrompt, version, envelopeType? }` record. The returned `version` MUST pin the prompt text for replay."
|
|
2689
2697
|
}
|
|
2690
2698
|
}
|
|
2691
2699
|
},
|
|
2692
2700
|
"agentRuntime": {
|
|
2693
2701
|
"type": "object",
|
|
2694
|
-
"description": "Declared by RFC 0144. The heavyweight swarm/consensus SUPERSET of the agent surface
|
|
2702
|
+
"description": "Declared by RFC 0144. The heavyweight swarm/consensus SUPERSET of the agent surface — spawn, delegate, consensus, message-send, skill-invoke, swarm-execute over RFC 0002/0003/0007 primitives. Advertising it IMPLIES `agents.manifestRuntime` (RFC 0070 §B), since `spawn({ manifestId })` instantiates a manifest agent; hosts needing only single-agent or crew dispatch advertise that floor and omit this family. Per-tool authorization, rate limiting, and the content-free tool-call audit trail live in the top-level `toolHooks` block, NOT under this family. See `host-capabilities.md` §host.agentRuntime.",
|
|
2695
2703
|
"additionalProperties": false,
|
|
2696
2704
|
"properties": {
|
|
2697
2705
|
"supported": {
|
|
2698
2706
|
"type": "boolean",
|
|
2699
|
-
"description": "`true`
|
|
2707
|
+
"description": "`true` ⇒ `ctx.agentRuntime.*` is exposed AND `agents.manifestRuntime` is implied (RFC 0070 §B). A multi-tenant host additionally advertises `agents.manifestRuntime.installScope: 'tenant'` (RFC 0074) so `GET /v1/agents` scopes to the caller's owner triple."
|
|
2700
2708
|
}
|
|
2701
2709
|
}
|
|
2702
2710
|
},
|
|
@@ -2720,7 +2728,7 @@
|
|
|
2720
2728
|
},
|
|
2721
2729
|
"webhooks": {
|
|
2722
2730
|
"type": "object",
|
|
2723
|
-
"description": "Webhook delivery surface (`webhooks.md`). The base contract is best-effort (5s per-attempt timeout, a circuit breaker, no durable retry). RFC 0083 adds the OPTIONAL `durable` mode: when `true`, webhook delivery participates in the trigger-bridge durable model (subscription states + retry policy + dead-letter on exhaustion) instead of the best-effort circuit-breaker-then-drop. Absent `durable`
|
|
2731
|
+
"description": "Webhook delivery surface (`webhooks.md`). The base contract is best-effort (5s per-attempt timeout, a circuit breaker, no durable retry). RFC 0083 adds the OPTIONAL `durable` mode: when `true`, webhook delivery participates in the trigger-bridge durable model (subscription states + retry policy + dead-letter on exhaustion) instead of the best-effort circuit-breaker-then-drop. Absent `durable` ⇒ the best-effort default, explicitly unchanged.",
|
|
2724
2732
|
"additionalProperties": true,
|
|
2725
2733
|
"properties": {
|
|
2726
2734
|
"supported": {
|
|
@@ -2737,13 +2745,13 @@
|
|
|
2737
2745
|
},
|
|
2738
2746
|
"durable": {
|
|
2739
2747
|
"type": "boolean",
|
|
2740
|
-
"description": "RFC 0083
|
|
2748
|
+
"description": "RFC 0083 §A — OPTIONAL opt-in. `true` ⇒ webhook delivery is durable (a trigger-bridge source); absent/`false` ⇒ the best-effort `webhooks.md` contract, unchanged. The best-effort default is NOT relaxed."
|
|
2741
2749
|
}
|
|
2742
2750
|
}
|
|
2743
2751
|
},
|
|
2744
2752
|
"triggerBridge": {
|
|
2745
2753
|
"type": "object",
|
|
2746
|
-
"description": "RFC 0083 (`Active`). Composes the existing scheduling (RFC 0052), dead-letter (RFC 0053), queue-bus (RFC 0017), webhook, and cross-host-causation (RFC 0040) primitives into one uniform durable inbound-work contract: standardized subscription states + a delivery-attempt/dedup/retry model + trigger
|
|
2754
|
+
"description": "RFC 0083 (`Active`). Composes the existing scheduling (RFC 0052), dead-letter (RFC 0053), queue-bus (RFC 0017), webhook, and cross-host-causation (RFC 0040) primitives into one uniform durable inbound-work contract: standardized subscription states + a delivery-attempt/dedup/retry model + trigger→run causation. Backs the derived `openwop-trigger-bridge` profile. Channels (Slack/email/SMS) stay vendor extensions (§E) — only their bridge into a run is uniform. Hosts that omit it have no uniform trigger contract (today's behavior); the conformance behavioral scenarios skip cleanly.",
|
|
2747
2755
|
"required": [
|
|
2748
2756
|
"supported"
|
|
2749
2757
|
],
|
|
@@ -2751,7 +2759,7 @@
|
|
|
2751
2759
|
"properties": {
|
|
2752
2760
|
"supported": {
|
|
2753
2761
|
"type": "boolean",
|
|
2754
|
-
"description": "REQUIRED when present. `true`
|
|
2762
|
+
"description": "REQUIRED when present. `true` ⇒ the host implements the §B state machine + §C delivery model + emits the two `trigger.*` events."
|
|
2755
2763
|
},
|
|
2756
2764
|
"subscriptionStates": {
|
|
2757
2765
|
"type": "array",
|
|
@@ -2765,16 +2773,16 @@
|
|
|
2765
2773
|
"dead-lettered"
|
|
2766
2774
|
]
|
|
2767
2775
|
},
|
|
2768
|
-
"description": "The subscription states the host implements (the
|
|
2776
|
+
"description": "The subscription states the host implements (the §B four-state vocabulary). Absent ⇒ at least `active` + `dead-lettered`."
|
|
2769
2777
|
},
|
|
2770
2778
|
"dedup": {
|
|
2771
2779
|
"type": "boolean",
|
|
2772
|
-
"description": "`true`
|
|
2780
|
+
"description": "`true` ⇒ the host de-duplicates inbound events by `dedupKey` within the retention window (§C-1; at-least-once becomes effectively-once)."
|
|
2773
2781
|
},
|
|
2774
2782
|
"retryPolicy": {
|
|
2775
2783
|
"type": "object",
|
|
2776
2784
|
"additionalProperties": false,
|
|
2777
|
-
"description": "The host's default delivery retry policy (
|
|
2785
|
+
"description": "The host's default delivery retry policy (§C-2).",
|
|
2778
2786
|
"properties": {
|
|
2779
2787
|
"maxAttempts": {
|
|
2780
2788
|
"type": "integer",
|
|
@@ -2807,12 +2815,12 @@
|
|
|
2807
2815
|
"change"
|
|
2808
2816
|
]
|
|
2809
2817
|
},
|
|
2810
|
-
"description": "Which trigger sources bridge uniformly. A source listed here MUST have a registerable `TriggerSubscription` driven through the four-state machine AND emit the two `trigger.*` events for that source
|
|
2818
|
+
"description": "Which trigger sources bridge uniformly. A source listed here MUST have a registerable `TriggerSubscription` driven through the four-state machine AND emit the two `trigger.*` events for that source — the list MUST NOT over-claim a source the host has as a feature but does not wire as a durable trigger subscription. A consumer MUST tolerate any subset."
|
|
2811
2819
|
},
|
|
2812
2820
|
"ingestion": {
|
|
2813
2821
|
"type": "object",
|
|
2814
2822
|
"additionalProperties": false,
|
|
2815
|
-
"description": "RFC 0099
|
|
2823
|
+
"description": "RFC 0099 §F.3 (additive). External-event ingestion advertisement — which of `sources[]` the host actually ingests from EXTERNALLY-originated events (`webhook`/`email`/`form`/`stream`/`change`), normalizing each to a `TriggerEvent` (`trigger-event.schema.json`) and starting a run. Absent ⇒ the host does NOT externally-ingest (today's behavior — schedule/queue only). A source in `externalSources[]` MUST actually accept an external event, normalize it, and start a run — over-claiming is a dishonest advertisement. A consumer MUST tolerate any subset.",
|
|
2816
2824
|
"properties": {
|
|
2817
2825
|
"externalSources": {
|
|
2818
2826
|
"type": "array",
|
|
@@ -2827,12 +2835,12 @@
|
|
|
2827
2835
|
"change"
|
|
2828
2836
|
]
|
|
2829
2837
|
},
|
|
2830
|
-
"description": "Which of `sources[]` are EXTERNALLY ingested per RFC 0099 (`stream`/`change` per RFC 0127). The honesty gate
|
|
2838
|
+
"description": "Which of `sources[]` are EXTERNALLY ingested per RFC 0099 (`stream`/`change` per RFC 0127). The honesty gate — each MUST normalize to a `TriggerEvent` and start a run."
|
|
2831
2839
|
},
|
|
2832
2840
|
"maxBodyBytes": {
|
|
2833
2841
|
"type": "integer",
|
|
2834
2842
|
"minimum": 1,
|
|
2835
|
-
"description": "Inbound body cap (webhook body / email / form), reusing the RFC 0076
|
|
2843
|
+
"description": "Inbound body cap (webhook body / email / form), reusing the RFC 0076 §B response-cap discipline."
|
|
2836
2844
|
},
|
|
2837
2845
|
"verification": {
|
|
2838
2846
|
"type": "array",
|
|
@@ -2845,11 +2853,11 @@
|
|
|
2845
2853
|
"form-origin"
|
|
2846
2854
|
]
|
|
2847
2855
|
},
|
|
2848
|
-
"description": "Which source-authenticity checks the host performs. An advertised check MUST actually be performed (RFC 0099
|
|
2856
|
+
"description": "Which source-authenticity checks the host performs. An advertised check MUST actually be performed (RFC 0099 §F.3 / UQ1)."
|
|
2849
2857
|
},
|
|
2850
2858
|
"registrationEndpoint": {
|
|
2851
2859
|
"type": "boolean",
|
|
2852
|
-
"description": "`true`
|
|
2860
|
+
"description": "`true` ⇒ the host serves `POST /v1/trigger-subscriptions` (RFC 0099 §F.2) for portable external-event subscription creation."
|
|
2853
2861
|
}
|
|
2854
2862
|
}
|
|
2855
2863
|
}
|
|
@@ -2858,7 +2866,7 @@
|
|
|
2858
2866
|
"a2a": {
|
|
2859
2867
|
"type": "object",
|
|
2860
2868
|
"additionalProperties": false,
|
|
2861
|
-
"description": "RFC 0100 (`Active`). The host exposes itself as an A2A (Agent2Agent) agent. `supported: true` alone
|
|
2869
|
+
"description": "RFC 0100 (`Active`). The host exposes itself as an A2A (Agent2Agent) agent. `supported: true` alone ⇒ the SYNCHRONOUS `message/send` → poll `tasks/get` round-trip already specified by `a2a-integration.md` (today's behavior — no regression). The optional `streaming`/`pushNotifications`/`durableTasks` flags gate the RFC 0100 async/durable additions (resubscribe re-attach, push config, persisted `A2ATaskState` so `tasks/get` returns live state after disconnect). Absent block ⇒ no A2A advertisement.",
|
|
2862
2870
|
"required": [
|
|
2863
2871
|
"supported",
|
|
2864
2872
|
"agentCardUrl"
|
|
@@ -2871,19 +2879,19 @@
|
|
|
2871
2879
|
"agentCardUrl": {
|
|
2872
2880
|
"type": "string",
|
|
2873
2881
|
"format": "uri",
|
|
2874
|
-
"description": "The A2A well-known agent card URL (`/.well-known/agent-card.json`
|
|
2882
|
+
"description": "The A2A well-known agent card URL (`/.well-known/agent-card.json` — the same path in 0.3 and 1.0; the protocol version is discovered INSIDE the 1.0 card via `supportedInterfaces[].protocolVersion`, RFC 0152 §C)."
|
|
2875
2883
|
},
|
|
2876
2884
|
"streaming": {
|
|
2877
2885
|
"type": "boolean",
|
|
2878
|
-
"description": "Host supports `message/stream` + `tasks/resubscribe` (0.3 names) / `SendStreamingMessage` + `SubscribeToTask` (1.0 names)
|
|
2886
|
+
"description": "Host supports `message/stream` + `tasks/resubscribe` (0.3 names) / `SendStreamingMessage` + `SubscribeToTask` (1.0 names) — A2A `capabilities.streaming`. Gates the RFC 0100 §3 resubscribe re-attach; MUST equal the Agent Card's `capabilities.streaming` (RFC 0152 §C)."
|
|
2879
2887
|
},
|
|
2880
2888
|
"pushNotifications": {
|
|
2881
2889
|
"type": "boolean",
|
|
2882
|
-
"description": "Host supports A2A push-notification config (A2A `capabilities.push_notifications`). Gates the RFC 0100
|
|
2890
|
+
"description": "Host supports A2A push-notification config (A2A `capabilities.push_notifications`). Gates the RFC 0100 §4 push contract; a caller-supplied `pushConfig.url` is SSRF-validated (`a2a-push-egress-ssrf`)."
|
|
2883
2891
|
},
|
|
2884
2892
|
"durableTasks": {
|
|
2885
2893
|
"type": "boolean",
|
|
2886
|
-
"description": "RFC 0100
|
|
2894
|
+
"description": "RFC 0100 §2. Host PERSISTS the projected Task (`A2ATaskState`) per backing run; `tasks/get` returns live state after disconnect. Absent/false ⇒ synchronous round-trip only."
|
|
2887
2895
|
},
|
|
2888
2896
|
"protocolVersions": {
|
|
2889
2897
|
"type": "array",
|
|
@@ -2893,12 +2901,12 @@
|
|
|
2893
2901
|
"type": "string",
|
|
2894
2902
|
"pattern": "^[0-9]+\\.[0-9]+$"
|
|
2895
2903
|
},
|
|
2896
|
-
"description": "RFC 0152
|
|
2904
|
+
"description": "RFC 0152 §A — every A2A protocol version this host speaks, newest-preferred first by convention. An A2A-capable host MUST advertise a non-empty array. `supported: true` WITHOUT versions is deprecated and CANNOT substantiate a current-A2A claim: it says the host speaks some A2A, which is not a fact a peer can negotiate against."
|
|
2897
2905
|
},
|
|
2898
2906
|
"preferredVersion": {
|
|
2899
2907
|
"type": "string",
|
|
2900
2908
|
"pattern": "^[0-9]+\\.[0-9]+$",
|
|
2901
|
-
"description": "RFC 0152
|
|
2909
|
+
"description": "RFC 0152 §A — MUST be present in `protocolVersions`. New hosts SHOULD prefer `1.0`."
|
|
2902
2910
|
},
|
|
2903
2911
|
"profiles": {
|
|
2904
2912
|
"type": "array",
|
|
@@ -2907,13 +2915,13 @@
|
|
|
2907
2915
|
"type": "string",
|
|
2908
2916
|
"pattern": "^a2a-[0-9]+\\.[0-9]+(-legacy)?$"
|
|
2909
2917
|
},
|
|
2910
|
-
"description": "RFC 0152
|
|
2918
|
+
"description": "RFC 0152 §A — named composition profiles, e.g. `a2a-1.0`, `a2a-0.3-legacy`. A legacy-only host advertises only the `-legacy` profile, which makes the deprecation explicit and time-boundable rather than implicit in a bare `supported: true`."
|
|
2911
2919
|
}
|
|
2912
2920
|
}
|
|
2913
2921
|
},
|
|
2914
2922
|
"budget": {
|
|
2915
2923
|
"type": "object",
|
|
2916
|
-
"description": "RFC 0084 (`Active`). Enforceable per-run SPEND governance
|
|
2924
|
+
"description": "RFC 0084 (`Active`). Enforceable per-run SPEND governance — the reserved `budget` run-options key (`budget-policy.schema.json`), the content-free `budget.{reserved,consumed,threshold.crossed,exhausted}` events, and hard-stop enforcement via `cap.breached{kind:\"budget-*\"}`. Orthogonal to RFC 0058 (which owns wall-time + loop-iterations via `limits.maxRunDurationMs`/`maxLoopIterations`); they share only the `cap.breached` overflow event. Hosts that omit it perform no spend enforcement (today's behavior); the conformance behavioral scenarios skip cleanly.",
|
|
2917
2925
|
"required": [
|
|
2918
2926
|
"supported"
|
|
2919
2927
|
],
|
|
@@ -2921,7 +2929,7 @@
|
|
|
2921
2929
|
"properties": {
|
|
2922
2930
|
"supported": {
|
|
2923
2931
|
"type": "boolean",
|
|
2924
|
-
"description": "REQUIRED when present. `true`
|
|
2932
|
+
"description": "REQUIRED when present. `true` ⇒ the host resolves the `budget` policy, emits the `budget.*` events, and (when `enforce: \"hard\"`) stops the run on exhaustion."
|
|
2925
2933
|
},
|
|
2926
2934
|
"dimensions": {
|
|
2927
2935
|
"type": "array",
|
|
@@ -2936,7 +2944,7 @@
|
|
|
2936
2944
|
"model"
|
|
2937
2945
|
]
|
|
2938
2946
|
},
|
|
2939
|
-
"description": "Which budget dimensions the host actually enforces (truthful
|
|
2947
|
+
"description": "Which budget dimensions the host actually enforces (truthful — advertise only what it honors). A consumer MUST tolerate any subset."
|
|
2940
2948
|
},
|
|
2941
2949
|
"enforce": {
|
|
2942
2950
|
"type": "string",
|
|
@@ -2958,13 +2966,13 @@
|
|
|
2958
2966
|
"project"
|
|
2959
2967
|
]
|
|
2960
2968
|
},
|
|
2961
|
-
"description": "Which budget scopes the host honors (
|
|
2969
|
+
"description": "Which budget scopes the host honors (§B). Absent ⇒ at least `run`."
|
|
2962
2970
|
}
|
|
2963
2971
|
}
|
|
2964
2972
|
},
|
|
2965
2973
|
"nondeterminismPolicy": {
|
|
2966
2974
|
"type": "object",
|
|
2967
|
-
"description": "RFC 0085. A host that does NOT support replay/fork (`replay.supported`) MAY instead DECLARE that it is honestly nondeterministic
|
|
2975
|
+
"description": "RFC 0085. A host that does NOT support replay/fork (`replay.supported`) MAY instead DECLARE that it is honestly nondeterministic — satisfying the `openwop-agent-platform` floor's replay-OR-policy term (`agent-platform-profile.md` §B) without claiming a replay capability it lacks. Absent ⇒ the floor's replay term must be met by `replay.supported`.",
|
|
2968
2976
|
"required": [
|
|
2969
2977
|
"declared"
|
|
2970
2978
|
],
|
|
@@ -2972,13 +2980,13 @@
|
|
|
2972
2980
|
"properties": {
|
|
2973
2981
|
"declared": {
|
|
2974
2982
|
"type": "boolean",
|
|
2975
|
-
"description": "When `true`, the host documents its nondeterminism (it does not guarantee deterministic replay). A bare flag for v1.x (RFC 0085
|
|
2983
|
+
"description": "When `true`, the host documents its nondeterminism (it does not guarantee deterministic replay). A bare flag for v1.x (RFC 0085 §UQ2); a structured per-source policy is a future refinement."
|
|
2976
2984
|
}
|
|
2977
2985
|
}
|
|
2978
2986
|
},
|
|
2979
2987
|
"workspace": {
|
|
2980
2988
|
"type": "object",
|
|
2981
|
-
"description": "RFC 0059 (`Active`). Versioned, tenant
|
|
2989
|
+
"description": "RFC 0059 (`Active`). Versioned, tenant·workspace-scoped ground-truth file store (the `host.workspace` capability). Scopes to the RFC 0048 owner triple. Atomic, optimistically-concurrent writes (`If-Match` ETag); a read snapshot is exposed to every run at `run.started` (deterministic for replay). Complements the transactional `MemoryAdapter` (RFC 0004) with a durable, path-addressable file layer. Endpoints (`/v1/host/workspace/files[/{path}]`) are gated on `supported: true`; unsupported hosts return `501 capability_not_provided`. SECURITY invariants `workspace-cross-tenant-isolation` (WCT-1) + the WSR-1 secret-redaction MUST land with their conformance tests at implementation (RFC 0059 §E).",
|
|
2982
2990
|
"required": [
|
|
2983
2991
|
"supported"
|
|
2984
2992
|
],
|
|
@@ -2989,7 +2997,7 @@
|
|
|
2989
2997
|
},
|
|
2990
2998
|
"versioned": {
|
|
2991
2999
|
"type": "boolean",
|
|
2992
|
-
"description": "Each write bumps a monotonic `version`; prior versions are retrievable via `GET
|
|
3000
|
+
"description": "Each write bumps a monotonic `version`; prior versions are retrievable via `GET …/files/{path}?version=N`. Latest-version retrieval is the MUST regardless; history is best-effort up to `maxVersions`."
|
|
2993
3001
|
},
|
|
2994
3002
|
"maxFileBytes": {
|
|
2995
3003
|
"type": "integer",
|
|
@@ -3011,7 +3019,7 @@
|
|
|
3011
3019
|
},
|
|
3012
3020
|
"uiPlugins": {
|
|
3013
3021
|
"type": "object",
|
|
3014
|
-
"description": "RFC 0117 (`Active`; amended by RFC 0119). Host loads SIGNED, SANDBOXED front-end plugin packs (`kind: \"frontend-plugin\"`)
|
|
3022
|
+
"description": "RFC 0117 (`Active`; amended by RFC 0119). Host loads SIGNED, SANDBOXED front-end plugin packs (`kind: \"frontend-plugin\"`) — canvas editors, custom artifact viewers, settings panels — in an ORIGIN/EXECUTION-ISOLATED sandbox (mechanism named by `isolation`: cross-origin iframe by default, or wasm/process/container/vm) and talks to them over the closed `ui-plugin/1` host-RPC boundary. The wire owns the boundary (isolation + RPC allowlist + manifest), NOT a renderer. Gated on `supported: true`; a host that does not advertise it rejects `kind: \"frontend-plugin\"` packs at registration and renders no plugin surface (graceful degradation to RFC 0071 host rendering). SECURITY invariants `frontend-plugin-isolation` / `frontend-plugin-egress` / `frontend-plugin-rpc-allowlist` / `frontend-plugin-no-byok` (RFC 0117 §Security).",
|
|
3015
3023
|
"required": [
|
|
3016
3024
|
"supported"
|
|
3017
3025
|
],
|
|
@@ -3037,11 +3045,11 @@
|
|
|
3037
3045
|
}
|
|
3038
3046
|
],
|
|
3039
3047
|
"default": "cross-origin-iframe",
|
|
3040
|
-
"description": "RFC 0117 (amended by RFC 0119). The categorical isolation model the host enforces for plugin bytes. `cross-origin-iframe` = a distinct-origin sandboxed browser frame (the browser default;
|
|
3048
|
+
"description": "RFC 0117 (amended by RFC 0119). The categorical isolation model the host enforces for plugin bytes. `cross-origin-iframe` = a distinct-origin sandboxed browser frame (the browser default; §Isolation). `wasm`/`process`/`container`/`vm` mirror `sandbox.isolationModel` (RFC 0035) for non-browser hosts that enforce the SAME isolation property. Vendor-specific models advertise `^x-host-<host>-<key>$` per `host-extensions.md`. ALL values denote the SAME mandatory property (`frontend-plugin-isolation`): plugin bytes execute in a boundary with no access to the host's execution context / DOM / origin-storage / credentials, deny-egress by default, and all host interaction mediated by the closed `ui-plugin/1` RPC. The field names the MECHANISM, never relaxes the property. In-process / same-origin / module-federation loading is a protocol-tier MUST NOT regardless of the advertised value."
|
|
3041
3049
|
},
|
|
3042
3050
|
"surfaces": {
|
|
3043
3051
|
"type": "array",
|
|
3044
|
-
"description": "Plugin surfaces this host renders. A pack's `uiPlugins[].surface` not in this set is installable-but-inert (
|
|
3052
|
+
"description": "Plugin surfaces this host renders. A pack's `uiPlugins[].surface` not in this set is installable-but-inert (§Degradation). `canvas-preview` (RFC 0130) mounts inside a host-owned canvas editor.",
|
|
3045
3053
|
"items": {
|
|
3046
3054
|
"type": "string",
|
|
3047
3055
|
"enum": [
|
|
@@ -3055,7 +3063,7 @@
|
|
|
3055
3063
|
},
|
|
3056
3064
|
"hostApi": {
|
|
3057
3065
|
"type": "array",
|
|
3058
|
-
"description": "The `ui-plugin/1` host-RPC methods this host honors. A plugin call to a method not in this set (regardless of the plugin's declared `hostApi`) MUST be rejected with `method_not_allowed` (`frontend-plugin-rpc-allowlist`). A host advertising `artifact.write` MUST enforce the `version`-token optimistic concurrency (RFC 0117
|
|
3066
|
+
"description": "The `ui-plugin/1` host-RPC methods this host honors. A plugin call to a method not in this set (regardless of the plugin's declared `hostApi`) MUST be rejected with `method_not_allowed` (`frontend-plugin-rpc-allowlist`). A host advertising `artifact.write` MUST enforce the `version`-token optimistic concurrency (RFC 0117 §Concurrency).",
|
|
3059
3067
|
"items": {
|
|
3060
3068
|
"type": "string",
|
|
3061
3069
|
"enum": [
|
|
@@ -3078,7 +3086,7 @@
|
|
|
3078
3086
|
},
|
|
3079
3087
|
"sql": {
|
|
3080
3088
|
"type": "object",
|
|
3081
|
-
"description": "RFC 0018 (`Active`). SQL database adapter with parametric-only enforcement. Hosts MUST reject non-parametric queries that inline user input (`sql-parametric-only` invariant
|
|
3089
|
+
"description": "RFC 0018 (`Active`). SQL database adapter with parametric-only enforcement. Hosts MUST reject non-parametric queries that inline user input (`sql-parametric-only` invariant — guards against SQL injection across every workflow).",
|
|
3082
3090
|
"properties": {
|
|
3083
3091
|
"supported": {
|
|
3084
3092
|
"type": "boolean"
|
|
@@ -3217,7 +3225,7 @@
|
|
|
3217
3225
|
},
|
|
3218
3226
|
"cache": {
|
|
3219
3227
|
"type": "object",
|
|
3220
|
-
"description": "RFC 0019 (`Active`). TTL cache for HTTP / AI response memoization. Per-tenant scoping; TTL drift
|
|
3228
|
+
"description": "RFC 0019 (`Active`). TTL cache for HTTP / AI response memoization. Per-tenant scoping; TTL drift ≤ 1s.",
|
|
3221
3229
|
"properties": {
|
|
3222
3230
|
"supported": {
|
|
3223
3231
|
"type": "boolean"
|
|
@@ -3235,7 +3243,7 @@
|
|
|
3235
3243
|
},
|
|
3236
3244
|
"workflowChainPacks": {
|
|
3237
3245
|
"type": "object",
|
|
3238
|
-
"description": "RFC 0013 (Phase 1, `Draft`). When `supported: true`, the host's workflow editor implements workflow-chain pack expansion per `workflow-chain-packs.md`
|
|
3246
|
+
"description": "RFC 0013 (Phase 1, `Draft`). When `supported: true`, the host's workflow editor implements workflow-chain pack expansion per `workflow-chain-packs.md` — author drops a chain tile, host resolves the pack, prompts for `parameters`, substitutes `{{params.<name>}}` placeholders, rewrites node ids, splices the resulting DAG into the parent workflow. Hosts that don't implement expansion omit this block (or set `supported: false`); conformance scenarios under `conformance/src/scenarios/workflow-chain-*.test.ts` skip cleanly against those hosts.",
|
|
3239
3247
|
"properties": {
|
|
3240
3248
|
"supported": {
|
|
3241
3249
|
"type": "boolean",
|
|
@@ -3243,7 +3251,7 @@
|
|
|
3243
3251
|
},
|
|
3244
3252
|
"deferredParameters": {
|
|
3245
3253
|
"type": "object",
|
|
3246
|
-
"description": "RFC 0124 (WCP4, `Active`). OPTIONAL. When `supported: true`, the host offers a capability-gated deferred-parameter expansion mode in ADDITION to expansion-time substitution (which remains the default and floor): at drop time it materializes the chain's `parameters` into top-level workflow `variables[]` (author value as `defaultValue`) and rewrites `{{params.<name>}}` into a spec'd runtime binding (PromptTemplate `{{varName}}` with `source:\"variable\"`, or a variable-sourced PortValue), so chain parameters stay overridable per run via `configurable` while the persisted definition keeps ZERO `{{params.*}}` tokens. A parameter marked `x-openwop-sensitive` MUST be deferred or the expansion fail-closed (`sensitive_param_not_deferrable`, 422)
|
|
3254
|
+
"description": "RFC 0124 (WCP4, `Active`). OPTIONAL. When `supported: true`, the host offers a capability-gated deferred-parameter expansion mode in ADDITION to expansion-time substitution (which remains the default and floor): at drop time it materializes the chain's `parameters` into top-level workflow `variables[]` (author value as `defaultValue`) and rewrites `{{params.<name>}}` into a spec'd runtime binding (PromptTemplate `{{varName}}` with `source:\"variable\"`, or a variable-sourced PortValue), so chain parameters stay overridable per run via `configurable` while the persisted definition keeps ZERO `{{params.*}}` tokens. A parameter marked `x-openwop-sensitive` MUST be deferred or the expansion fail-closed (`sensitive_param_not_deferrable`, 422) — never frozen into persisted `config`. Omission (or `supported:false`) signals the host does NOT offer deferred mode. No host may advertise `supported:true` until RFC 0124 is `Accepted`. See `workflow-chain-packs.md` §\"Deferred-parameter expansion\".",
|
|
3247
3255
|
"properties": {
|
|
3248
3256
|
"supported": {
|
|
3249
3257
|
"type": "boolean",
|
|
@@ -3257,11 +3265,11 @@
|
|
|
3257
3265
|
},
|
|
3258
3266
|
"hostExpansionSeam": {
|
|
3259
3267
|
"type": "boolean",
|
|
3260
|
-
"description": "RFC 0013 erratum (2026-07-05). OPTIONAL. A **conformance-only test seam** advertisement (category: test harness, cf. `observability.testSeams`
|
|
3268
|
+
"description": "RFC 0013 erratum (2026-07-05). OPTIONAL. A **conformance-only test seam** advertisement (category: test harness, cf. `observability.testSeams` — NOT a product capability): when `true`, the host serves `POST /v1/host/sample/workflow-chain:expand` returning the `vendor.openwop.workflow-chain-sample` v1.0.0 expansion that `conformance/src/scenarios/workflow-chain-host-expansion.test.ts` asserts against. Absent/`false` ⇒ that live-host expansion scenario soft-skips; the semantic `workflowChainPacks.supported` claim is witnessed by the server-free `workflow-chain-expansion.test.ts` legs. This flag is DISTINCT from `deferredParameters` (RFC 0124), which is witnessed through its own `POST /v1/host/sample/chain/deferred-expand` seam — so a host MAY advertise `supported` / `deferredParameters.supported` without standing up the RFC 0013 sample-pack seam it was never handed a published fixture for. Advertising `supported:true` no longer conscripts a host into the RFC 0013 host-expansion scenario."
|
|
3261
3269
|
},
|
|
3262
3270
|
"subChains": {
|
|
3263
3271
|
"type": "object",
|
|
3264
|
-
"description": "RFC 0133 (workflow-chain composition, `Accepted`). OPTIONAL. When `supported: true`, the host's `POST
|
|
3272
|
+
"description": "RFC 0133 (workflow-chain composition, `Accepted`). OPTIONAL. When `supported: true`, the host's `POST …/workflows/from-chain` implements RUNTIME sub-chain composition per `workflow-chain-packs.md` §\"Sub-chain composition (RFC 0133)\": for each `config.subChainRef` reachable from a parent chain, it resolves the referenced chain (sibling or external), recursively expands + co-registers it as its own owned workflow (deterministic TENANT-SCOPED id from `(tenantId, childChainId, version)` — two tenants never collide on the global registry, a shared child registers once across parents in a tenant, a repeat instantiation converges), rewrites the referencing node's `subChainRef` → the minted child `config.workflowId`, and dispatches the child as a child run (`core.subWorkflow` / `core.dispatch` child-run); the `from-chain` response carries `{ workflowId, subChainWorkflowIds[], nodeCount }`. Bounded by a cycle check (`sub_chain_cycle`) + a depth cap (`sub_chain_max_depth_exceeded`). A host that does NOT advertise this block MUST refuse a `subChains`-bearing chain at author/instantiate time with `sub_chain_unsupported` (422) — it never silently flattens. `producedVariables` (RFC 0133 §2) needs NO flag: it is pure variable emission under the base `workflowChainPacks.supported`. Conformance scenarios `chain-subchain-fanout.test.ts` + `chain-subchain-unsupported-refused.test.ts` gate on this flag; the server-free `chain-subchain-sibling` / `chain-subchain-cycle-rejected` / `chain-produced-var-roundtrip` legs run unconditionally against the reference library.",
|
|
3265
3273
|
"properties": {
|
|
3266
3274
|
"supported": {
|
|
3267
3275
|
"type": "boolean",
|
|
@@ -3271,7 +3279,7 @@
|
|
|
3271
3279
|
"type": "integer",
|
|
3272
3280
|
"minimum": 1,
|
|
3273
3281
|
"default": 8,
|
|
3274
|
-
"description": "RFC 0133
|
|
3282
|
+
"description": "RFC 0133 §1.3 (resolves UQ3). RECOMMENDED default 8. The maximum sub-chain nesting depth the host co-expands; exceeding it fails closed with the DISTINCT code `sub_chain_max_depth_exceeded` (the DoS depth backstop, alongside the `sub_chain_cycle` self-composition check — SECURITY `sub-chain-expansion-bounded`)."
|
|
3275
3283
|
}
|
|
3276
3284
|
},
|
|
3277
3285
|
"required": [
|
|
@@ -3287,23 +3295,23 @@
|
|
|
3287
3295
|
},
|
|
3288
3296
|
"packs": {
|
|
3289
3297
|
"type": "object",
|
|
3290
|
-
"description": "RFC 0025 (`Active`). Pack-registry surface advertisement. The baseline `/v1/packs/*` read surface (per `spec/v1/node-packs.md`
|
|
3298
|
+
"description": "RFC 0025 (`Active`). Pack-registry surface advertisement. The baseline `/v1/packs/*` read surface (per `spec/v1/node-packs.md` §\"Registry HTTP API\") is unconditional for hosts that ship a pack catalog and does NOT require a capability flag; this object carries optional sub-blocks (currently the test-mode mirror namespace). Hosts that don't expose any optional pack-registry sub-block MAY omit this block entirely.",
|
|
3291
3299
|
"properties": {
|
|
3292
3300
|
"testMode": {
|
|
3293
3301
|
"type": "object",
|
|
3294
|
-
"description": "RFC 0025
|
|
3302
|
+
"description": "RFC 0025 §A. Optional `/v1/packs-test/*` mirror surface that exposes the production publish/get/delete/sig contract against an isolated catalog. Lets the conformance suite (`pack-registry-publish.test.ts`) exercise the documented 19-code publish error catalog without `packs:publish` scope on the real registry. Hosts that advertise `supported: true` MUST honor the §C isolation guarantees and MUST surface the same error envelopes and HTTP statuses as the production `/v1/packs/*` surface.",
|
|
3295
3303
|
"properties": {
|
|
3296
3304
|
"supported": {
|
|
3297
3305
|
"type": "boolean",
|
|
3298
|
-
"description": "Host exposes `/v1/packs-test/*` per RFC 0025
|
|
3306
|
+
"description": "Host exposes `/v1/packs-test/*` per RFC 0025 §B. When `true`, the conformance suite drives publish-error-catalog assertions through the test namespace; when `false` or absent, the 26 scenarios in `pack-registry-publish.test.ts` soft-skip cleanly."
|
|
3299
3307
|
},
|
|
3300
3308
|
"isolated": {
|
|
3301
3309
|
"type": "boolean",
|
|
3302
|
-
"description": "RFC 0025
|
|
3310
|
+
"description": "RFC 0025 §C point 1. MUST be `true` when `supported` is `true` — guarantees the test catalog is persisted distinctly from the production catalog and that a pack PUT'd via `/v1/packs-test/*` MUST NOT appear in `/v1/packs/*` listings."
|
|
3303
3311
|
},
|
|
3304
3312
|
"catalogResetEndpoint": {
|
|
3305
3313
|
"type": "string",
|
|
3306
|
-
"description": "RFC 0025
|
|
3314
|
+
"description": "RFC 0025 §C point 4. Optional URL path (e.g. `/v1/packs-test/reset`) that clears the entire test catalog. When advertised, conformance-suite teardown SHOULD call it; the endpoint MUST be idempotent. Hosts MAY omit; in that case the suite leaves disposable timestamped pack names in place and relies on the next host restart to clear in-memory state.",
|
|
3307
3315
|
"pattern": "^/"
|
|
3308
3316
|
},
|
|
3309
3317
|
"scopes": {
|
|
@@ -3320,7 +3328,7 @@
|
|
|
3320
3328
|
},
|
|
3321
3329
|
"uniqueItems": true,
|
|
3322
3330
|
"minItems": 1,
|
|
3323
|
-
"description": "RFC 0025
|
|
3331
|
+
"description": "RFC 0025 §A. Which namespace scopes the test catalog accepts in pack names. Public test catalogs SHOULD refuse `private` and `local` (matching the production-registry rule for `packs.openwop.dev`); private dev catalogs MAY accept all five. When omitted, the test catalog defaults to the same scope set as the production namespace it mirrors."
|
|
3324
3332
|
}
|
|
3325
3333
|
},
|
|
3326
3334
|
"required": [
|
|
@@ -3333,7 +3341,7 @@
|
|
|
3333
3341
|
},
|
|
3334
3342
|
"mcp": {
|
|
3335
3343
|
"type": "object",
|
|
3336
|
-
"description": "RFC 0020 (`Active`). MCP (Model Context Protocol) composition surface. The client half is consumed implicitly via `host.mcp` host-surface; this block adds the optional server half
|
|
3344
|
+
"description": "RFC 0020 (`Active`). MCP (Model Context Protocol) composition surface. The client half is consumed implicitly via `host.mcp` host-surface; this block adds the optional server half — workflow exposed AS an MCP server with bidirectional sampling/elicitation bridges.",
|
|
3337
3345
|
"properties": {
|
|
3338
3346
|
"supported": {
|
|
3339
3347
|
"type": "boolean",
|
|
@@ -3347,7 +3355,7 @@
|
|
|
3347
3355
|
"type": "string",
|
|
3348
3356
|
"minLength": 1
|
|
3349
3357
|
},
|
|
3350
|
-
"description": "Where the host's MCP server mount(s) answer JSON-RPC
|
|
3358
|
+
"description": "Where the host's MCP server mount(s) answer JSON-RPC — an absolute URL or a path relative to the discovery origin (S25: a path is joined to the base URL, an absolute URL is used as-is). The v1.0 conformance baseline (`mcp-discoverability.test.ts`, spec/v1/mcp-integration.md §Conformance + interop) REQUIRES a non-empty `serverUrls` whenever `supported: true`, and since suite 1.134.0 every server-side scenario POSTs to `serverUrls[0]`. Required by the scenario and absent from this schema until 2026-08-17 (S27) — the second sibling host emitted it and measured the contradiction."
|
|
3351
3359
|
},
|
|
3352
3360
|
"serverMount": {
|
|
3353
3361
|
"type": "object",
|
|
@@ -3385,12 +3393,12 @@
|
|
|
3385
3393
|
"type": "string",
|
|
3386
3394
|
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
|
|
3387
3395
|
},
|
|
3388
|
-
"description": "RFC 0153
|
|
3396
|
+
"description": "RFC 0153 §A — MCP revisions in MCP's own date form, exactly. The pattern is date-shaped rather than free string because MCP versions ARE dates: accepting `latest` or `2026-7-28` would make two hosts disagree about which revision they share while both validating."
|
|
3389
3397
|
},
|
|
3390
3398
|
"preferredVersion": {
|
|
3391
3399
|
"type": "string",
|
|
3392
3400
|
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
|
|
3393
|
-
"description": "RFC 0153
|
|
3401
|
+
"description": "RFC 0153 §A — MUST be present in `protocolVersions`."
|
|
3394
3402
|
},
|
|
3395
3403
|
"profiles": {
|
|
3396
3404
|
"type": "array",
|
|
@@ -3399,7 +3407,7 @@
|
|
|
3399
3407
|
"type": "string",
|
|
3400
3408
|
"pattern": "^mcp-[0-9]{4}-[0-9]{2}-[0-9]{2}(-legacy)?$"
|
|
3401
3409
|
},
|
|
3402
|
-
"description": "RFC 0153
|
|
3410
|
+
"description": "RFC 0153 §A — named composition profiles. Unqualified `supported: true` is deprecated and cannot substantiate a current-MCP claim."
|
|
3403
3411
|
},
|
|
3404
3412
|
"features": {
|
|
3405
3413
|
"type": "array",
|
|
@@ -3412,14 +3420,14 @@
|
|
|
3412
3420
|
"extensions"
|
|
3413
3421
|
]
|
|
3414
3422
|
},
|
|
3415
|
-
"description": "RFC 0153
|
|
3423
|
+
"description": "RFC 0153 §A — closed feature set for the current revision. Closed rather than open because an unrecognized feature name is indistinguishable from a typo, and a peer that silently ignores one negotiates a capability neither side has."
|
|
3416
3424
|
}
|
|
3417
3425
|
},
|
|
3418
3426
|
"additionalProperties": false
|
|
3419
3427
|
},
|
|
3420
3428
|
"sandbox": {
|
|
3421
3429
|
"type": "object",
|
|
3422
|
-
"description": "RFC 0035
|
|
3430
|
+
"description": "RFC 0035 — Sandbox execution contract for pack-loaded typeIds. Hosts that advertise execute pack-loaded code inside an isolation boundary meeting the 8 failure-mode invariants in spec/v1/host-capabilities.md §'Sandbox execution contract'. Absent block = host does NOT sandbox pack-loaded code and MUST refuse to load any pack whose manifest declares `peerDependencies.host.sandbox: required`.",
|
|
3423
3431
|
"additionalProperties": false,
|
|
3424
3432
|
"required": [
|
|
3425
3433
|
"supported",
|
|
@@ -3428,7 +3436,7 @@
|
|
|
3428
3436
|
"properties": {
|
|
3429
3437
|
"supported": {
|
|
3430
3438
|
"type": "boolean",
|
|
3431
|
-
"description": "Host enforces the 8 sandbox failure-mode invariants per spec/v1/host-capabilities.md
|
|
3439
|
+
"description": "Host enforces the 8 sandbox failure-mode invariants per spec/v1/host-capabilities.md §'Sandbox execution contract'. When false, host MUST refuse to load packs declaring required sandbox isolation."
|
|
3432
3440
|
},
|
|
3433
3441
|
"isolationModel": {
|
|
3434
3442
|
"type": "string",
|
|
@@ -3445,7 +3453,7 @@
|
|
|
3445
3453
|
"pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
|
|
3446
3454
|
}
|
|
3447
3455
|
],
|
|
3448
|
-
"description": "Categorical isolation model. `wasm` = WebAssembly sandbox with explicit host imports (e.g., Wasmtime, Wasmer). `process` = OS process boundary with restricted syscalls (e.g., gVisor, seccomp, Landlock). `container` = container runtime boundary (e.g., Firecracker microVM). `vm` = full VM. Vendor-specific isolation models advertise `^x-host-<host>-<key>$` per spec/v1/host-extensions.md
|
|
3456
|
+
"description": "Categorical isolation model. `wasm` = WebAssembly sandbox with explicit host imports (e.g., Wasmtime, Wasmer). `process` = OS process boundary with restricted syscalls (e.g., gVisor, seccomp, Landlock). `container` = container runtime boundary (e.g., Firecracker microVM). `vm` = full VM. Vendor-specific isolation models advertise `^x-host-<host>-<key>$` per spec/v1/host-extensions.md §'Canonical prefixes'; documentation lives at the host's discovery doc."
|
|
3449
3457
|
},
|
|
3450
3458
|
"allowedHostCalls": {
|
|
3451
3459
|
"type": "array",
|
|
@@ -3457,18 +3465,18 @@
|
|
|
3457
3465
|
"memoryLimitBytes": {
|
|
3458
3466
|
"type": "integer",
|
|
3459
3467
|
"minimum": 1048576,
|
|
3460
|
-
"description": "Per-invocation memory cap (
|
|
3468
|
+
"description": "Per-invocation memory cap (≥ 1 MiB). Host MUST enforce; exceeding fails the node with `sandbox_memory_exceeded`."
|
|
3461
3469
|
},
|
|
3462
3470
|
"wallClockLimitMs": {
|
|
3463
3471
|
"type": "integer",
|
|
3464
3472
|
"minimum": 100,
|
|
3465
|
-
"description": "Per-invocation wall-clock cap (
|
|
3473
|
+
"description": "Per-invocation wall-clock cap (≥ 100 ms). Host MUST enforce; exceeding fails the node with `sandbox_timeout`."
|
|
3466
3474
|
}
|
|
3467
3475
|
}
|
|
3468
3476
|
},
|
|
3469
3477
|
"compensation": {
|
|
3470
3478
|
"type": "object",
|
|
3471
|
-
"description": "RFC 0151
|
|
3479
|
+
"description": "RFC 0151 §A — generic compensation (Saga) contract. OPTIONAL; absent means the host offers no generic compensation contract, NOT that it never compensates — a workflow can always model an inverse action as an ordinary node. What this advertises is that the HOST orders, persists, and retries the unwind, so a client can rely on it rather than hand-rolling one. Compensation is a second effect, not an undo: it can fail, can be partially applied, and can itself require approval, which is why the profile is security-tier high (RFC 0147 R9).",
|
|
3472
3480
|
"additionalProperties": false,
|
|
3473
3481
|
"required": [
|
|
3474
3482
|
"supported"
|
|
@@ -3492,22 +3500,22 @@
|
|
|
3492
3500
|
"dependency-graph"
|
|
3493
3501
|
]
|
|
3494
3502
|
},
|
|
3495
|
-
"description": "RFC 0151
|
|
3503
|
+
"description": "RFC 0151 §A. A host that advertises compensation MUST implement `reverse-completion` and MAY additionally implement `dependency-graph`. `dependency-graph` MUST be a DAG and preserve reverse dependency order."
|
|
3496
3504
|
},
|
|
3497
3505
|
"manualIntervention": {
|
|
3498
3506
|
"type": "boolean",
|
|
3499
|
-
"description": "RFC 0151
|
|
3507
|
+
"description": "RFC 0151 §C — the host can record `manual-intervention-required` rather than silently abandoning an unwind. Cancelling the parent MUST NOT abandon an active compensation: it continues, pauses for authorized intervention, or records this state."
|
|
3500
3508
|
}
|
|
3501
3509
|
}
|
|
3502
3510
|
},
|
|
3503
3511
|
"idempotency": {
|
|
3504
3512
|
"type": "object",
|
|
3505
|
-
"description": "RFC 0036
|
|
3513
|
+
"description": "RFC 0036 — Multi-region idempotency contract. Optional v1 advertisement. The existing `crossRegion: 'single-region'|'reconciled-records'|'fenced-effects'` categorical claim lives under `capabilities.idempotency.crossRegion` (this description named the pre-RFC-0150-§D vocabulary `'best-effort'|'strict'` until 2026-08-18 — both values were RETIRED by §D and the sibling `crossRegion` enum has been correct throughout, so only this prose was wrong; a reader of it would have believed two non-values were advertisable) per spec/v1/idempotency.md §'Multi-region idempotency (annex)'. The `multiRegion` sub-block here gives a granular advertisement that hosts SHOULD pair with the categorical `crossRegion` claim.",
|
|
3506
3514
|
"additionalProperties": true,
|
|
3507
3515
|
"properties": {
|
|
3508
3516
|
"supported": {
|
|
3509
3517
|
"type": "boolean",
|
|
3510
|
-
"description": "Whether the host implements the idempotency contract. Used in `spec/v1/idempotency.md`'s own capability example and throughout the corpus, but UNDECLARED until 2026-08-13
|
|
3518
|
+
"description": "Whether the host implements the idempotency contract. Used in `spec/v1/idempotency.md`'s own capability example and throughout the corpus, but UNDECLARED until 2026-08-13 — it validated only because this family carries `additionalProperties: true`, which meant a typo such as `suported` was accepted silently and a consumer reading it saw nothing advertised. Declaring it does not close the family; it makes the field a contract rather than a convention."
|
|
3511
3519
|
},
|
|
3512
3520
|
"multiRegion": {
|
|
3513
3521
|
"type": "object",
|
|
@@ -3518,13 +3526,13 @@
|
|
|
3518
3526
|
"properties": {
|
|
3519
3527
|
"supported": {
|
|
3520
3528
|
"type": "boolean",
|
|
3521
|
-
"description": "Host implements cross-region idempotency reconciliation per spec/v1/idempotency.md
|
|
3529
|
+
"description": "Host implements cross-region idempotency reconciliation per spec/v1/idempotency.md §'Multi-region reconciliation'. When `true`, an Idempotency-Key write succeeding in region A is read-visible in region B within `replicationLagBoundMs + safetyMargin`."
|
|
3522
3530
|
},
|
|
3523
3531
|
"replicationLagBoundMs": {
|
|
3524
3532
|
"type": "integer",
|
|
3525
3533
|
"minimum": 0,
|
|
3526
3534
|
"maximum": 60000,
|
|
3527
|
-
"description": "Conservative upper bound on cross-region replication lag (
|
|
3535
|
+
"description": "Conservative upper bound on cross-region replication lag (≤ 60s ceiling chosen to keep operator advertisement honest; production cross-region deployments typically run < 10s). Conformance asserts read-visibility after the bound."
|
|
3528
3536
|
},
|
|
3529
3537
|
"partitionRecoveryStrategy": {
|
|
3530
3538
|
"type": "string",
|
|
@@ -3538,7 +3546,7 @@
|
|
|
3538
3546
|
"pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
|
|
3539
3547
|
}
|
|
3540
3548
|
],
|
|
3541
|
-
"description": "RFC 0150
|
|
3549
|
+
"description": "RFC 0150 §D — deterministic resolution rule for conflicting idempotency-key records after a partition heals. `lexicographic-min-run-id` is the rule spec/v1/idempotency.md §'Guarantees under partition' MUSTs: the lower runId wins, deterministic without coordination. Vendor strategies use `^x-host-<host>-<key>$` and MUST still satisfy the reproducible-survivor requirement. The time-ordered `last-writer-wins` / `first-writer-wins` values were REMOVED as a safety-fix: under a partition there is no shared clock, so both regions believe they wrote last, which cannot satisfy the annex MUST that re-running the same conflict input produces the same survivor — and both select a different survivor than the lex-min rule the same document requires. Resolving a RECORD never authorizes an EFFECT; see `crossRegion`."
|
|
3542
3550
|
}
|
|
3543
3551
|
}
|
|
3544
3552
|
},
|
|
@@ -3549,13 +3557,13 @@
|
|
|
3549
3557
|
"reconciled-records",
|
|
3550
3558
|
"fenced-effects"
|
|
3551
3559
|
],
|
|
3552
|
-
"description": "RFC 0036, revised by RFC 0150
|
|
3560
|
+
"description": "RFC 0036, revised by RFC 0150 §D — categorical multi-region idempotency posture (the canonical conformance-checked surface per spec/v1/idempotency.md §'Multi-region idempotency (annex)'). The ladder is about EFFECTS, not replication latency. `single-region`: the host runs in one region and makes no cross-region claim (it MAY still implement the convergence resolver, demonstrable via the multi-region simulator seam). `reconciled-records`: cross-region reconciliation converges eventually under the annex's lex-min(runId) rule, and external effects MAY remain at-least-once — converging on which RECORD survives says nothing about how many times an effect was issued. `fenced-effects`: records converge AND every external effect is either fenced by a monotonic token from a linearizable ownership service or issued to a provider that guarantees duplicate suppression. When `reconciled-records` or `fenced-effects`, the host MUST emit the `openwop.idempotency.cross_region_conflicts_total` operator metric. The `multiRegion` sub-block above is the optional granular companion. REMOVED as a safety-fix: `best-effort` (renamed to `reconciled-records`, which states the effect caveat the old name hid) and `strict`, which promised only that read-visibility was bounded by `multiRegion.replicationLagBoundMs` — a LATENCY claim occupying the top slot of a ladder implementers read as effect safety. A host replicating synchronously at 0 ms can still issue duplicate effects from two regions, because knowing what the other region wrote is not being authorized to act. That latency bound already has its own field, so no information is lost."
|
|
3553
3561
|
}
|
|
3554
3562
|
}
|
|
3555
3563
|
},
|
|
3556
3564
|
"eventLog": {
|
|
3557
3565
|
"type": "object",
|
|
3558
|
-
"description": "RFC 0036
|
|
3566
|
+
"description": "RFC 0036 — Event-log multi-engine advertisement. Optional v1.",
|
|
3559
3567
|
"additionalProperties": false,
|
|
3560
3568
|
"properties": {
|
|
3561
3569
|
"crossEngineOrdering": {
|
|
@@ -3594,7 +3602,7 @@
|
|
|
3594
3602
|
"hash",
|
|
3595
3603
|
"passthrough"
|
|
3596
3604
|
],
|
|
3597
|
-
"description": "Server's default masking mode for fields marked sensitive. `mask` (default): replace with `\"[REDACTED]\"`. `omit`: drop the field entirely. `hash`: replace with `\"sha256:<hex>\"` for audit-only equality. `passthrough`: record as-is (NOT recommended for production). Workflow authors MAY override per-workflow via `metadata.complianceConfig.maskingMode`. See observability.md
|
|
3605
|
+
"description": "Server's default masking mode for fields marked sensitive. `mask` (default): replace with `\"[REDACTED]\"`. `omit`: drop the field entirely. `hash`: replace with `\"sha256:<hex>\"` for audit-only equality. `passthrough`: record as-is (NOT recommended for production). Workflow authors MAY override per-workflow via `metadata.complianceConfig.maskingMode`. See observability.md §Privacy classification."
|
|
3598
3606
|
},
|
|
3599
3607
|
"supportedClasses": {
|
|
3600
3608
|
"type": "array",
|
|
@@ -3627,11 +3635,11 @@
|
|
|
3627
3635
|
},
|
|
3628
3636
|
"backpressure": {
|
|
3629
3637
|
"type": "object",
|
|
3630
|
-
"description": "Backpressure envelope advertisement (production-profile.md
|
|
3638
|
+
"description": "Backpressure envelope advertisement (production-profile.md §Backpressure).",
|
|
3631
3639
|
"properties": {
|
|
3632
3640
|
"supported": {
|
|
3633
3641
|
"type": "boolean",
|
|
3634
|
-
"description": "Host returns 503 + Retry-After + canonical envelope under load per production-profile.md
|
|
3642
|
+
"description": "Host returns 503 + Retry-After + canonical envelope under load per production-profile.md §Backpressure."
|
|
3635
3643
|
},
|
|
3636
3644
|
"inflightCap": {
|
|
3637
3645
|
"type": "integer",
|
|
@@ -3642,14 +3650,14 @@
|
|
|
3642
3650
|
"type": "integer",
|
|
3643
3651
|
"minimum": 0,
|
|
3644
3652
|
"maximum": 86400,
|
|
3645
|
-
"description": "Optional advertised Retry-After value in seconds the host returns on 503. When present, MUST equal both the `Retry-After` header and the `details.retryAfter` body field per production-profile.md. Upper bound 86400 (24h)
|
|
3653
|
+
"description": "Optional advertised Retry-After value in seconds the host returns on 503. When present, MUST equal both the `Retry-After` header and the `details.retryAfter` body field per production-profile.md. Upper bound 86400 (24h) — values beyond that are operationally indistinguishable from 'permanently denied'. Hosts needing longer holds SHOULD omit `Retry-After` entirely (RFC 0009 Q#2)."
|
|
3646
3654
|
}
|
|
3647
3655
|
},
|
|
3648
3656
|
"additionalProperties": false
|
|
3649
3657
|
},
|
|
3650
3658
|
"retention": {
|
|
3651
3659
|
"type": "object",
|
|
3652
|
-
"description": "Event-retention advertisement (production-profile.md
|
|
3660
|
+
"description": "Event-retention advertisement (production-profile.md §\"Event retention\").",
|
|
3653
3661
|
"properties": {
|
|
3654
3662
|
"supported": {
|
|
3655
3663
|
"type": "boolean",
|
|
@@ -3658,18 +3666,18 @@
|
|
|
3658
3666
|
"minWindowSeconds": {
|
|
3659
3667
|
"type": "integer",
|
|
3660
3668
|
"minimum": 604800,
|
|
3661
|
-
"description": "Documented minimum retention window in seconds. Per production-profile.md
|
|
3669
|
+
"description": "Documented minimum retention window in seconds. Per production-profile.md §\"Event retention\", MUST be ≥ 604800 (7 days) for public hosts; development-only hosts MAY advertise a smaller window but MUST NOT claim `supported: true` while doing so."
|
|
3662
3670
|
},
|
|
3663
3671
|
"testForceExpire": {
|
|
3664
3672
|
"type": "boolean",
|
|
3665
|
-
"description": "Host exposes a test-only force-expire hook the conformance suite can call (URL/method supplied via `OPENWOP_TEST_FORCE_EXPIRE_URL` / `OPENWOP_TEST_FORCE_EXPIRE_METHOD` env vars). When `false`, the production-retention-expiry scenario asserts only the 410/404 envelope shape on an operator-supplied already-expired run id (via `OPENWOP_TEST_EXPIRED_RUN_ID`); otherwise it soft-skips. RFC 0009 unresolved question #1
|
|
3673
|
+
"description": "Host exposes a test-only force-expire hook the conformance suite can call (URL/method supplied via `OPENWOP_TEST_FORCE_EXPIRE_URL` / `OPENWOP_TEST_FORCE_EXPIRE_METHOD` env vars). When `false`, the production-retention-expiry scenario asserts only the 410/404 envelope shape on an operator-supplied already-expired run id (via `OPENWOP_TEST_EXPIRED_RUN_ID`); otherwise it soft-skips. RFC 0009 unresolved question #1 — endpoint normation is deferred."
|
|
3666
3674
|
}
|
|
3667
3675
|
},
|
|
3668
3676
|
"additionalProperties": false
|
|
3669
3677
|
},
|
|
3670
3678
|
"debugBundle": {
|
|
3671
3679
|
"type": "object",
|
|
3672
|
-
"description": "Debug-bundle truncation advertisement (production-profile.md
|
|
3680
|
+
"description": "Debug-bundle truncation advertisement (production-profile.md §\"Debug bundle behavior\"). Stricter than the existing `capabilities.debugBundle.supported` advertised per debug-bundle.md — this block adds the production-profile MUSTs (truncation metadata, redaction).",
|
|
3673
3681
|
"properties": {
|
|
3674
3682
|
"supported": {
|
|
3675
3683
|
"type": "boolean",
|
|
@@ -3677,7 +3685,7 @@
|
|
|
3677
3685
|
},
|
|
3678
3686
|
"truncationMetadata": {
|
|
3679
3687
|
"type": "boolean",
|
|
3680
|
-
"description": "When `true`, host surfaces `truncated: true` + non-empty `truncatedReason` per debug-bundle.md
|
|
3688
|
+
"description": "When `true`, host surfaces `truncated: true` + non-empty `truncatedReason` per debug-bundle.md §\"Bundle size limits\" when caps are reached."
|
|
3681
3689
|
}
|
|
3682
3690
|
},
|
|
3683
3691
|
"additionalProperties": false
|
|
@@ -3696,20 +3704,23 @@
|
|
|
3696
3704
|
"minLength": 1
|
|
3697
3705
|
},
|
|
3698
3706
|
"uniqueItems": true,
|
|
3699
|
-
"description": "Auth profiles the host claims. Canonical ids: `openwop-audit-log-integrity` (auth-profiles.md
|
|
3707
|
+
"description": "Auth profiles the host claims. Canonical ids: `openwop-audit-log-integrity` (auth-profiles.md §Audit-log integrity), `openwop-auth-api-key-rotation`, `openwop-auth-oauth2-client-credentials`, `openwop-auth-oidc-user-bearer`, `openwop-auth-mtls`, `openwop-auth-saml` + `openwop-auth-scim` + `openwop-auth-ldap` (RFC 0050 enterprise identity). Clients SHOULD tolerate unknown profile ids."
|
|
3700
3708
|
},
|
|
3701
3709
|
"subjectLinking": {
|
|
3702
3710
|
"type": "boolean",
|
|
3703
|
-
"description": "RFC 0164: DERIVED and DEPRECATED toward v2. A host that advertises both `openwop-auth-saml` and `openwop-auth-scim` MUST set this true (schema conditional on `profiles[]`); a document advertising both with this absent/false is invalid. Kept through v1.x for clients pinned to it; clients SHOULD derive the guarantee from the profile pair. Original (RFC 0159) semantics follow. RFC 0159 (auth-profiles.md
|
|
3711
|
+
"description": "RFC 0164: DERIVED and DEPRECATED toward v2. A host that advertises both `openwop-auth-saml` and `openwop-auth-scim` MUST set this true (schema conditional on `profiles[]`); a document advertising both with this absent/false is invalid. Kept through v1.x for clients pinned to it; clients SHOULD derive the guarantee from the profile pair. Original (RFC 0159) semantics follow. RFC 0159 (auth-profiles.md §Subject linking). When true, this host advertises BOTH `openwop-auth-saml` and `openwop-auth-scim` AND honours the cross-profile subject-linking obligation: it links the SAML and SCIM principals of one human on an opaque, IdP-stable subject id (SCIM `externalId` ↔ persistent SAML `NameID`), same-tenant only, and on SCIM deactivation fail-closes the linked SAML identity too (composing RFC 0049 §C) — so a provisioned leaver cannot still SSO in. The link key MUST NOT be a mutable/PII attribute (email, userName). Optional; absent/false means the SAML and SCIM lanes are independent and the combined leaver guarantee is NOT claimed. A host MUST NOT set this true unless both profiles are advertised and the obligation holds."
|
|
3704
3712
|
},
|
|
3705
3713
|
"subjectLinkKey": {
|
|
3706
3714
|
"type": "string",
|
|
3707
|
-
"enum": [
|
|
3708
|
-
|
|
3715
|
+
"enum": [
|
|
3716
|
+
"opaque-idp",
|
|
3717
|
+
"configured-immutable"
|
|
3718
|
+
],
|
|
3719
|
+
"description": "RFC 0163 (auth-profiles.md §Subject linking). The CLASS of opaque, IdP-stable, non-PII identifier this host joins the SAML and SCIM lanes on. A CLOSED enum of ALLOWED classes only, naming classes rather than vendor attributes: `opaque-idp` (SCIM `externalId` ↔ persistent-format SAML `NameID`) or `configured-immutable` (a host-configured attribute asserted by the same IdP on both lanes that is opaque, stable for the account lifetime, never reassigned, non-PII and not user- or operator-influenceable — e.g. a directory object id or an immutable-id claim; the attribute name stays host config, the class goes on the wire). Mutable/PII keys (email, userName, displayName) are INEXPRESSIBLE by construction — a conforming host cannot name one, which is the witness that converts RFC 0159 §A.2/§A.4's negative-existence prohibition into a positive advertisement. REQUIRED when `subjectLinking` is true: expressed BOTH as the auth-profiles.md §Subject linking MUST and as this block's `if`/`then` conditional, so a discovery document claiming linking without a class fails schema validation as well as the conformance scenario. Absent when `subjectLinking` is absent/false."
|
|
3709
3720
|
},
|
|
3710
3721
|
"rotation": {
|
|
3711
3722
|
"type": "object",
|
|
3712
|
-
"description": "API-key rotation advertisement (auth-profiles.md
|
|
3723
|
+
"description": "API-key rotation advertisement (auth-profiles.md §`openwop-auth-api-key-rotation`).",
|
|
3713
3724
|
"properties": {
|
|
3714
3725
|
"supported": {
|
|
3715
3726
|
"type": "boolean",
|
|
@@ -3718,14 +3729,14 @@
|
|
|
3718
3729
|
"minGraceSeconds": {
|
|
3719
3730
|
"type": "integer",
|
|
3720
3731
|
"minimum": 0,
|
|
3721
|
-
"description": "Minimum rotation grace window in seconds. auth-profiles.md SHOULDs production-profile hosts to
|
|
3732
|
+
"description": "Minimum rotation grace window in seconds. auth-profiles.md SHOULDs production-profile hosts to ≥ 86400 (24h). The conformance scenario tolerates any non-negative value but warns in behavior mode when < 86400."
|
|
3722
3733
|
}
|
|
3723
3734
|
},
|
|
3724
3735
|
"additionalProperties": false
|
|
3725
3736
|
},
|
|
3726
3737
|
"oauth2": {
|
|
3727
3738
|
"type": "object",
|
|
3728
|
-
"description": "OAuth2 client-credentials advertisement (auth-profiles.md
|
|
3739
|
+
"description": "OAuth2 client-credentials advertisement (auth-profiles.md §`openwop-auth-oauth2-client-credentials`).",
|
|
3729
3740
|
"properties": {
|
|
3730
3741
|
"supported": {
|
|
3731
3742
|
"type": "boolean"
|
|
@@ -3753,7 +3764,7 @@
|
|
|
3753
3764
|
},
|
|
3754
3765
|
"oidc": {
|
|
3755
3766
|
"type": "object",
|
|
3756
|
-
"description": "OIDC user-bearer advertisement (auth-profiles.md
|
|
3767
|
+
"description": "OIDC user-bearer advertisement (auth-profiles.md §`openwop-auth-oidc-user-bearer`).",
|
|
3757
3768
|
"properties": {
|
|
3758
3769
|
"supported": {
|
|
3759
3770
|
"type": "boolean"
|
|
@@ -3779,7 +3790,7 @@
|
|
|
3779
3790
|
"scope-claim",
|
|
3780
3791
|
"host-acl"
|
|
3781
3792
|
],
|
|
3782
|
-
"description": "How the host derives openwop scopes from the OIDC token. `group-claim`: from `groups` claim via host config. `scope-claim`: from `scope` claim directly. `host-acl`: from a host-side mapping table (sub
|
|
3793
|
+
"description": "How the host derives openwop scopes from the OIDC token. `group-claim`: from `groups` claim via host config. `scope-claim`: from `scope` claim directly. `host-acl`: from a host-side mapping table (sub → scope)."
|
|
3783
3794
|
},
|
|
3784
3795
|
"introspectionIntervalSeconds": {
|
|
3785
3796
|
"type": "integer",
|
|
@@ -3791,7 +3802,7 @@
|
|
|
3791
3802
|
},
|
|
3792
3803
|
"mtls": {
|
|
3793
3804
|
"type": "object",
|
|
3794
|
-
"description": "mTLS advertisement (auth-profiles.md
|
|
3805
|
+
"description": "mTLS advertisement (auth-profiles.md §`openwop-auth-mtls`).",
|
|
3795
3806
|
"properties": {
|
|
3796
3807
|
"supported": {
|
|
3797
3808
|
"type": "boolean"
|
|
@@ -3814,7 +3825,7 @@
|
|
|
3814
3825
|
},
|
|
3815
3826
|
"workloadIdentity": {
|
|
3816
3827
|
"type": "object",
|
|
3817
|
-
"description": "RFC 0154
|
|
3828
|
+
"description": "RFC 0154 §A — workload identity profile `openwop-workload-identity-v1`. A host that advertises this cryptographically verifies the presented workload identity, binds it to the request, and resolves it to an OpenWOP principal BEFORE authorization. Unresolvable identity fails closed. **Identity is not authorization** (RFC 0147 R12): proving which workload called says nothing about what it may do, and treating the two as one is the confused-deputy shape this profile exists to prevent — tenant, audience, and policy MUST still be re-evaluated at every boundary.",
|
|
3818
3829
|
"additionalProperties": false,
|
|
3819
3830
|
"required": [
|
|
3820
3831
|
"supported"
|
|
@@ -3835,7 +3846,7 @@
|
|
|
3835
3846
|
"oauth-client"
|
|
3836
3847
|
]
|
|
3837
3848
|
},
|
|
3838
|
-
"description": "RFC 0154
|
|
3849
|
+
"description": "RFC 0154 §A — closed set of identity schemes the host verifies. Closed because an unrecognized scheme is a verification path nobody implemented, and accepting the NAME without the verification is precisely the failure the profile prevents."
|
|
3839
3850
|
},
|
|
3840
3851
|
"senderConstraint": {
|
|
3841
3852
|
"type": "array",
|
|
@@ -3846,11 +3857,11 @@
|
|
|
3846
3857
|
"dpop"
|
|
3847
3858
|
]
|
|
3848
3859
|
},
|
|
3849
|
-
"description": "RFC 0154
|
|
3860
|
+
"description": "RFC 0154 §A — proof-of-possession mechanisms. Without a sender constraint a bearer credential is replayable by anyone who observes it, so a host advertising workload identity WITHOUT one is asserting who called, not that the caller held the key."
|
|
3850
3861
|
},
|
|
3851
3862
|
"delegation": {
|
|
3852
3863
|
"type": "object",
|
|
3853
|
-
"description": "RFC 0154
|
|
3864
|
+
"description": "RFC 0154 §B — delegated actor chains, advertised SEPARATELY from §A identity resolution. A host can verify workload identity without implementing delegation, and forcing one flag to cover both would make a §A-only host choose between advertising a capability it does not have and advertising nothing at all. That is the same overclaim-or-silence bind RFC 0155 §A names for `openwop-core`, and per-section advertisement is how it is avoided: `supported` means §A resolution, `delegation.supported` means §B chain verification, and a conformance run gates each section on its own flag.",
|
|
3854
3865
|
"additionalProperties": false,
|
|
3855
3866
|
"required": [
|
|
3856
3867
|
"supported"
|
|
@@ -3862,7 +3873,7 @@
|
|
|
3862
3873
|
"maxChainDepth": {
|
|
3863
3874
|
"type": "integer",
|
|
3864
3875
|
"minimum": 1,
|
|
3865
|
-
"description": "RFC 0154
|
|
3876
|
+
"description": "RFC 0154 §B — bounded chain length. Unbounded delegation is unbounded authority laundering: each hop is another party the host is trusting transitively."
|
|
3866
3877
|
}
|
|
3867
3878
|
}
|
|
3868
3879
|
}
|
|
@@ -3872,12 +3883,20 @@
|
|
|
3872
3883
|
"allOf": [
|
|
3873
3884
|
{
|
|
3874
3885
|
"if": {
|
|
3875
|
-
"properties": {
|
|
3876
|
-
|
|
3886
|
+
"properties": {
|
|
3887
|
+
"subjectLinking": {
|
|
3888
|
+
"const": true
|
|
3889
|
+
}
|
|
3890
|
+
},
|
|
3891
|
+
"required": [
|
|
3892
|
+
"subjectLinking"
|
|
3893
|
+
]
|
|
3877
3894
|
},
|
|
3878
3895
|
"then": {
|
|
3879
|
-
"required": [
|
|
3880
|
-
|
|
3896
|
+
"required": [
|
|
3897
|
+
"subjectLinkKey"
|
|
3898
|
+
],
|
|
3899
|
+
"$comment": "RFC 0163 §A.1 / §C: a host that claims subject linking MUST declare the class it joins on. A conditional required on a flag no host emitted when it landed is a tightening of an unemitted shape (COMPATIBILITY.md §2.2), not closure of a server-emitted shape (§2.1)."
|
|
3881
3900
|
}
|
|
3882
3901
|
},
|
|
3883
3902
|
{
|
|
@@ -3885,17 +3904,34 @@
|
|
|
3885
3904
|
"properties": {
|
|
3886
3905
|
"profiles": {
|
|
3887
3906
|
"allOf": [
|
|
3888
|
-
{
|
|
3889
|
-
|
|
3907
|
+
{
|
|
3908
|
+
"contains": {
|
|
3909
|
+
"const": "openwop-auth-saml"
|
|
3910
|
+
}
|
|
3911
|
+
},
|
|
3912
|
+
{
|
|
3913
|
+
"contains": {
|
|
3914
|
+
"const": "openwop-auth-scim"
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3890
3917
|
]
|
|
3891
3918
|
}
|
|
3892
3919
|
},
|
|
3893
|
-
"required": [
|
|
3920
|
+
"required": [
|
|
3921
|
+
"profiles"
|
|
3922
|
+
]
|
|
3894
3923
|
},
|
|
3895
3924
|
"then": {
|
|
3896
|
-
"properties": {
|
|
3897
|
-
|
|
3898
|
-
|
|
3925
|
+
"properties": {
|
|
3926
|
+
"subjectLinking": {
|
|
3927
|
+
"const": true
|
|
3928
|
+
}
|
|
3929
|
+
},
|
|
3930
|
+
"required": [
|
|
3931
|
+
"subjectLinking",
|
|
3932
|
+
"subjectLinkKey"
|
|
3933
|
+
],
|
|
3934
|
+
"$comment": "RFC 0164 §A.3 / §B: advertising BOTH openwop-auth-saml and openwop-auth-scim implies the combined leaver contract, so `subjectLinking` MUST be true (a derived statement of fact, deprecated toward v2) and `subjectLinkKey` MUST name the class. Binds only documents that emit both profile strings; none did when it landed (COMPATIBILITY.md §2.2 / §4 default-on row with an empty harm set)."
|
|
3899
3935
|
}
|
|
3900
3936
|
}
|
|
3901
3937
|
],
|
|
@@ -3907,7 +3943,7 @@
|
|
|
3907
3943
|
"properties": {
|
|
3908
3944
|
"authScoped": {
|
|
3909
3945
|
"type": "object",
|
|
3910
|
-
"description": "Auth-scoped discovery advertisement (capabilities-change-detection.md
|
|
3946
|
+
"description": "Auth-scoped discovery advertisement (capabilities-change-detection.md §\"Scoped capability views\"). Hosts that return a different payload when called with Authorization than when called anonymously declare it here. The authenticated view MUST still satisfy the base capabilities.schema.json shape per the spec annex.",
|
|
3911
3947
|
"properties": {
|
|
3912
3948
|
"supported": {
|
|
3913
3949
|
"type": "boolean",
|
|
@@ -3960,7 +3996,7 @@
|
|
|
3960
3996
|
},
|
|
3961
3997
|
"content": {
|
|
3962
3998
|
"type": "object",
|
|
3963
|
-
"description": "RFC 0103 (spec/v1/localized-content.md). Localized authored content (pages
|
|
3999
|
+
"description": "RFC 0103 (spec/v1/localized-content.md). Localized authored content (pages → sections) advertisement. Reuses the i18n annex's Accept-Language/Content-Language negotiation; it does NOT redeclare negotiation. Requires `i18n.supported: true`. `baseLocale` MUST equal `capabilities.i18n.defaultLocale`; `({baseLocale} ∪ supportedLocales)` MUST be a subset of `capabilities.i18n.supportedLocales`; `baseLocale` MUST NOT appear in `supportedLocales`. Hosts that omit this block serve no content surface; the conformance scenarios skip cleanly.",
|
|
3964
4000
|
"additionalProperties": false,
|
|
3965
4001
|
"required": [
|
|
3966
4002
|
"supported",
|
|
@@ -3984,13 +4020,13 @@
|
|
|
3984
4020
|
"type": "string",
|
|
3985
4021
|
"pattern": "^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8}){0,3}$"
|
|
3986
4022
|
},
|
|
3987
|
-
"description": "BCP 47 tags the host has authored content translations for. MUST NOT contain `baseLocale`; `({baseLocale}
|
|
4023
|
+
"description": "BCP 47 tags the host has authored content translations for. MUST NOT contain `baseLocale`; `({baseLocale} ∪ supportedLocales)` MUST be a subset of `i18n.supportedLocales`."
|
|
3988
4024
|
}
|
|
3989
4025
|
}
|
|
3990
4026
|
},
|
|
3991
4027
|
"portability": {
|
|
3992
4028
|
"type": "object",
|
|
3993
|
-
"description": "RFC 0098 (`Active`). Export/import of a tenant's reusable estate (agents 0070, packs 0003/0013, prompt templates 0027, connection *refs* 0045/0095, schedules 0052, roster/org-chart 0086/0087). An export bundle carries NO credential values
|
|
4029
|
+
"description": "RFC 0098 (`Active`). Export/import of a tenant's reusable estate (agents 0070, packs 0003/0013, prompt templates 0027, connection *refs* 0045/0095, schedules 0052, roster/org-chart 0086/0087). An export bundle carries NO credential values — only refs to be re-bound at the destination (RFC 0046/0079). Import maps the estate onto the destination's RFC 0048 identity, MUST offer a no-write dry-run plan, MUST be idempotent, and is gated by an RFC 0049 scope. A host advertising this serves `/v1/host/sample/{export,import}` (promotable to `/v1/{export,import}`) and emits the content-free `import.applied` event. Hosts that omit this block neither export nor import; the conformance scenarios skip cleanly.",
|
|
3994
4030
|
"additionalProperties": false,
|
|
3995
4031
|
"properties": {
|
|
3996
4032
|
"export": {
|
|
@@ -4074,12 +4110,12 @@
|
|
|
4074
4110
|
]
|
|
4075
4111
|
},
|
|
4076
4112
|
"uniqueItems": true,
|
|
4077
|
-
"description": "Which approver ref kinds the host actually resolves. `group`
|
|
4113
|
+
"description": "Which approver ref kinds the host actually resolves. `group` ⇒ honors `approverGroupRefs`; `role` ⇒ honors `approverRoleRefs`. Absent ⇒ the host resolves neither (advisory-only passthrough). Capability honesty: advertise only the kinds the host's resolver supports."
|
|
4078
4114
|
},
|
|
4079
4115
|
"audience": {
|
|
4080
4116
|
"type": "boolean",
|
|
4081
4117
|
"default": false,
|
|
4082
|
-
"description": "Host honors the `audience` notification-targeting override. Absent/`false`
|
|
4118
|
+
"description": "Host honors the `audience` notification-targeting override. Absent/`false` ⇒ the host notifies the resolved eligible union and ignores `audience`."
|
|
4083
4119
|
}
|
|
4084
4120
|
}
|
|
4085
4121
|
}
|
|
@@ -4088,7 +4124,7 @@
|
|
|
4088
4124
|
"restTransport": {
|
|
4089
4125
|
"type": "object",
|
|
4090
4126
|
"additionalProperties": false,
|
|
4091
|
-
"description": "RFC 0115 (`Active`). Conditional-GET + Content-Encoding negotiation on run reads (`GET /v1/runs/{runId}`). Optional. Distinct from the file-egress `fileHandling.transport` (ftp/sftp/ssh) sub-capability
|
|
4127
|
+
"description": "RFC 0115 (`Active`). Conditional-GET + Content-Encoding negotiation on run reads (`GET /v1/runs/{runId}`). Optional. Distinct from the file-egress `fileHandling.transport` (ftp/sftp/ssh) sub-capability — this advertises HTTP-layer poll economy on the run-read REST surface.",
|
|
4092
4128
|
"properties": {
|
|
4093
4129
|
"conditionalRunGet": {
|
|
4094
4130
|
"type": "boolean",
|
|
@@ -4104,14 +4140,14 @@
|
|
|
4104
4140
|
"zstd"
|
|
4105
4141
|
]
|
|
4106
4142
|
},
|
|
4107
|
-
"description": "RFC 0115. Content-Encoding values the host will negotiate on run reads (advertisement of standard-HTTP behavior). `gzip` is the baseline; `br`/`zstd` are OPTIONAL
|
|
4143
|
+
"description": "RFC 0115. Content-Encoding values the host will negotiate on run reads (advertisement of standard-HTTP behavior). `gzip` is the baseline; `br`/`zstd` are OPTIONAL — the host advertises only the subset it can actually serve. For each advertised value the decoded body MUST be byte-identical to the identity body."
|
|
4108
4144
|
}
|
|
4109
4145
|
}
|
|
4110
4146
|
},
|
|
4111
4147
|
"a2uiSurface": {
|
|
4112
4148
|
"type": "object",
|
|
4113
4149
|
"additionalProperties": false,
|
|
4114
|
-
"description": "RFC 0114 (`Active`). Host-side TRANSPORT features over the recorded `ui.a2ui-surface` envelope (RFC 0102). A transport optimization, NOT an envelope-payload kind
|
|
4150
|
+
"description": "RFC 0114 (`Active`). Host-side TRANSPORT features over the recorded `ui.a2ui-surface` envelope (RFC 0102). A transport optimization, NOT an envelope-payload kind — the recorded envelope stays the full surface. Optional.",
|
|
4115
4151
|
"properties": {
|
|
4116
4152
|
"deltaTransport": {
|
|
4117
4153
|
"type": "boolean",
|