@openwop/openwop-conformance 1.1.0 → 1.2.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/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/coverage.md +29 -17
- package/fixtures/conformance-agent-low-confidence.json +7 -4
- package/fixtures/conformance-agent-pack-handoff-schema-validation.json +30 -0
- package/fixtures/conformance-agent-reasoning.json +23 -4
- package/fixtures/conformance-dispatch-cross-worker-handoff-child-a.json +27 -0
- package/fixtures/conformance-dispatch-cross-worker-handoff-child-b.json +25 -0
- package/fixtures/conformance-dispatch-cross-worker-handoff.json +60 -0
- package/fixtures/conformance-dispatch-input-mapping-child.json +25 -0
- package/fixtures/conformance-dispatch-input-mapping.json +49 -0
- package/fixtures/conformance-dispatch-output-mapping-child.json +27 -0
- package/fixtures/conformance-dispatch-output-mapping.json +49 -0
- package/fixtures/conformance-subworkflow-input-mapping-child.json +27 -0
- package/fixtures/conformance-subworkflow-input-mapping.json +33 -0
- package/fixtures.md +12 -2
- package/package.json +1 -1
- package/schemas/README.md +7 -0
- package/schemas/agent-ref.schema.json +1 -1
- package/schemas/ai-envelope.schema.json +106 -0
- package/schemas/capabilities.schema.json +300 -3
- package/schemas/core-conformance-mock-agent-config.schema.json +147 -0
- package/schemas/dispatch-config.schema.json +26 -0
- package/schemas/envelopes/clarification.request.schema.json +43 -0
- package/schemas/envelopes/error.schema.json +26 -0
- package/schemas/envelopes/schema.request.schema.json +22 -0
- package/schemas/envelopes/schema.response.schema.json +22 -0
- package/schemas/node-pack-manifest.schema.json +5 -0
- package/schemas/pack-lockfile.schema.json +16 -0
- package/schemas/run-event-payloads.schema.json +18 -2
- package/schemas/run-event.schema.json +2 -1
- package/schemas/workflow-chain-pack-manifest.schema.json +226 -0
- package/src/lib/behavior-gate.ts +44 -5
- package/src/lib/env.ts +27 -0
- package/src/lib/webhook-receiver.ts +137 -0
- package/src/lib/workflow-chain-expansion.ts +213 -0
- package/src/scenarios/agentPackCatalog.test.ts +216 -0
- package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +146 -0
- package/src/scenarios/agentReasoningEvents.test.ts +58 -7
- package/src/scenarios/agents-run-tool-allowlist.test.ts +182 -0
- package/src/scenarios/ai-envelope-shape.test.ts +362 -0
- package/src/scenarios/aiEnvelope.capBreached.test.ts +173 -0
- package/src/scenarios/aiEnvelope.contractRefusal.test.ts +150 -0
- package/src/scenarios/aiEnvelope.correlationReplay.test.ts +69 -0
- package/src/scenarios/aiEnvelope.redaction.test.ts +73 -0
- package/src/scenarios/aiEnvelope.schemaDrift.test.ts +87 -0
- package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +143 -0
- package/src/scenarios/aiEnvelope.universalKinds.test.ts +176 -0
- package/src/scenarios/append-ordering.test.ts +44 -0
- package/src/scenarios/artifact-auth.test.ts +58 -0
- package/src/scenarios/blob-cross-tenant-isolation.test.ts +66 -0
- package/src/scenarios/blob-presign-expiry.test.ts +66 -0
- package/src/scenarios/blob-roundtrip.test.ts +48 -0
- package/src/scenarios/cache-cross-tenant-isolation.test.ts +61 -0
- package/src/scenarios/cache-ttl-expiry.test.ts +47 -0
- package/src/scenarios/dispatch-cross-worker-handoff.test.ts +98 -0
- package/src/scenarios/dispatch-input-mapping.test.ts +94 -0
- package/src/scenarios/dispatch-output-mapping.test.ts +65 -0
- package/src/scenarios/fs-path-traversal.test.ts +124 -0
- package/src/scenarios/idempotency-key-determinism.test.ts +230 -0
- package/src/scenarios/interrupt-token-matrix.test.ts +126 -0
- package/src/scenarios/kv-atomic-increment.test.ts +74 -0
- package/src/scenarios/kv-cas.test.ts +75 -0
- package/src/scenarios/kv-cross-tenant-isolation.test.ts +85 -0
- package/src/scenarios/kv-ttl-expiry.test.ts +47 -0
- package/src/scenarios/mcp-server-elicitation-bridge.test.ts +92 -0
- package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +80 -0
- package/src/scenarios/mcp-server-resource-roundtrip.test.ts +82 -0
- package/src/scenarios/mcp-server-sampling-bridge.test.ts +84 -0
- package/src/scenarios/mcp-server-tool-roundtrip.test.ts +107 -0
- package/src/scenarios/mcp-server-untrusted-args.test.ts +105 -0
- package/src/scenarios/mcp-tool-roundtrip.test.ts +13 -6
- package/src/scenarios/memory-compaction-event-emitted.test.ts +121 -0
- package/src/scenarios/memory-compaction-provenance-tag.test.ts +116 -0
- package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +127 -0
- package/src/scenarios/multi-region-idempotency.test.ts +39 -4
- package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +139 -0
- package/src/scenarios/pause-resume.test.ts +43 -0
- package/src/scenarios/queue-ack-nack-dlq.test.ts +67 -0
- package/src/scenarios/queue-cross-tenant-isolation.test.ts +66 -0
- package/src/scenarios/queue-publish-consume-roundtrip.test.ts +48 -0
- package/src/scenarios/registry-public.test.ts +91 -0
- package/src/scenarios/search-bm25-roundtrip.test.ts +47 -0
- package/src/scenarios/spec-corpus-validity.test.ts +28 -7
- package/src/scenarios/sql-injection-rejection.test.ts +84 -0
- package/src/scenarios/sql-transaction-atomicity.test.ts +66 -0
- package/src/scenarios/stream-subscribe-from-beginning.test.ts +66 -0
- package/src/scenarios/subworkflow-input-mapping.test.ts +100 -0
- package/src/scenarios/table-cross-tenant-isolation.test.ts +65 -0
- package/src/scenarios/table-cursor-pagination.test.ts +47 -0
- package/src/scenarios/table-schema-enforcement.test.ts +47 -0
- package/src/scenarios/vector-knn-roundtrip.test.ts +48 -0
- package/src/scenarios/webhook-receiver-adversarial.test.ts +210 -0
- package/src/scenarios/workflow-chain-expansion.test.ts +366 -0
- package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +232 -0
- package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +138 -0
- package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +170 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "conformance-subworkflow-input-mapping-child",
|
|
3
|
+
"name": "Conformance: subWorkflow Input Mapping (RFC 0022 §B) — child",
|
|
4
|
+
"version": "1.0",
|
|
5
|
+
"description": "Child fixture for `conformance-subworkflow-input-mapping`. Declares a single `receivedPrdId` variable with `defaultValue: 'baked-in'` — the parent's `inputMapping: { receivedPrdId: 'currentPrdId' }` MUST override this default at child-run-create time per RFC 0022 §B. The body is a noop identity node; the assertion (the child's final `receivedPrdId` variable) is read from the child run's variables_json via `GET /v1/runs/{runId}`.",
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"id": "noop",
|
|
9
|
+
"typeId": "core.identity",
|
|
10
|
+
"name": "Noop (asserts via final variables)",
|
|
11
|
+
"position": { "x": 0, "y": 0 },
|
|
12
|
+
"config": {},
|
|
13
|
+
"inputs": {}
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"edges": [],
|
|
17
|
+
"triggers": [
|
|
18
|
+
{ "id": "manual", "type": "manual", "enabled": true }
|
|
19
|
+
],
|
|
20
|
+
"variables": [
|
|
21
|
+
{ "name": "receivedPrdId", "type": "string", "defaultValue": "baked-in" }
|
|
22
|
+
],
|
|
23
|
+
"metadata": {
|
|
24
|
+
"tags": ["conformance", "rfc-0022", "subworkflow", "input-mapping", "child"]
|
|
25
|
+
},
|
|
26
|
+
"settings": { "timeout": 5000 }
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "conformance-subworkflow-input-mapping",
|
|
3
|
+
"name": "Conformance: subWorkflow Input Mapping (RFC 0022 §B)",
|
|
4
|
+
"version": "1.0",
|
|
5
|
+
"description": "RFC 0022 §B — host honors `inputMapping` on `core.subWorkflow` and seeds child variables from parent-variable projections. The parent fixture sets its `currentPrdId='prd-1'`, then invokes the child fixture (`conformance-subworkflow-input-mapping-child`) via `core.subWorkflow` with `inputMapping: { receivedPrdId: 'currentPrdId' }`. The child workflow declares `receivedPrdId.defaultValue='baked-in'` — the RFC normates that `inputMapping` MUST override matching `defaultValue` declarations. The scenario inspects the child run's final variables and asserts `receivedPrdId === 'prd-1'`. See subworkflow-input-mapping.test.ts.",
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"id": "subwf-call",
|
|
9
|
+
"typeId": "core.subWorkflow",
|
|
10
|
+
"name": "Invoke child with inputMapping",
|
|
11
|
+
"position": { "x": 0, "y": 0 },
|
|
12
|
+
"config": {
|
|
13
|
+
"workflowId": "conformance-subworkflow-input-mapping-child",
|
|
14
|
+
"waitForCompletion": true,
|
|
15
|
+
"onChildFailure": "fail-parent",
|
|
16
|
+
"inputMapping": { "receivedPrdId": "currentPrdId" }
|
|
17
|
+
},
|
|
18
|
+
"inputs": {}
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"edges": [],
|
|
22
|
+
"triggers": [
|
|
23
|
+
{ "id": "manual", "type": "manual", "enabled": true }
|
|
24
|
+
],
|
|
25
|
+
"variables": [
|
|
26
|
+
{ "name": "currentPrdId", "type": "string", "defaultValue": "prd-1" }
|
|
27
|
+
],
|
|
28
|
+
"metadata": {
|
|
29
|
+
"tags": ["conformance", "rfc-0022", "subworkflow", "input-mapping"],
|
|
30
|
+
"requiresCapability": "capabilities.subWorkflow.inputMapping"
|
|
31
|
+
},
|
|
32
|
+
"settings": { "timeout": 10000 }
|
|
33
|
+
}
|
package/fixtures.md
CHANGED
|
@@ -58,12 +58,22 @@ All fixtures MUST advertise:
|
|
|
58
58
|
| Interrupt — Auth Required | `conformance-interrupt-auth-required` | Verifies `openwop-interrupt-auth-required` profile (bearer-token resume only) | `completed` after bearer resolve | unbounded (suspends) |
|
|
59
59
|
| Interrupt — Parent/Child Cancel | `conformance-interrupt-parent-child-cancel` + `conformance-interrupt-parent-child-cancel-child` | Verifies `openwop-interrupt-parent-child` cancel cascade | `cancelled` (both runs) | ≤ 30s |
|
|
60
60
|
| Agent Identity | `conformance-agent-identity` | Phase 1 — `RunSnapshot.agent` / `runOrchestrator` AgentRef wire-shape | `completed` | ≤ 10s |
|
|
61
|
-
| Agent Reasoning | `conformance-agent-reasoning` | Phase 1 — `agent.*` event family emission + `callId` pairing | `completed` | ≤ 15s |
|
|
62
|
-
| Agent Low-Confidence | `conformance-agent-low-confidence` | Phase 1 / CP-1 — confidence < threshold
|
|
61
|
+
| Agent Reasoning | `conformance-agent-reasoning` | Phase 1 / RFC 0023 — `agent.*` event family emission + `callId` pairing on `core.conformance.mock-agent` | `completed` | ≤ 15s |
|
|
62
|
+
| Agent Low-Confidence | `conformance-agent-low-confidence` | Phase 1 / CP-1 / RFC 0023 — `core.conformance.mock-agent` emits `agent.decided` with confidence < threshold; host MUST follow with `node.suspended { reason: 'low-confidence' }` | `waiting-approval` (suspends) | unbounded (suspends) |
|
|
63
63
|
| Message Reducer | `conformance-message-reducer` | Phase 1 — `message` reducer idempotency on duplicate `messageId` | `completed` | ≤ 10s |
|
|
64
64
|
| Agent Pack Install | `conformance-agent-pack-install` | Phase 2 — pack `agents[]` surface as AgentManifest at `GET /v1/packs` | `completed` | ≤ 5s |
|
|
65
65
|
| Agent Pack Export | `conformance-agent-pack-export` | Phase 2 — workspace agents project to AgentManifest at `GET /v1/packs/export` | `completed` | ≤ 5s |
|
|
66
66
|
| Agent Pack Provenance | `conformance-agent-pack-provenance` | Phase 2 — `sourceManifestId` provenance round-trip | `completed` | ≤ 10s |
|
|
67
|
+
| Agent Pack Handoff Schema Validation | `conformance-agent-pack-handoff-schema-validation` | Phase 2 / HV-1 — host validates dispatch payloads against `handoff.taskSchemaRef` AND return payloads against `handoff.returnSchemaRef` per RFC 0003 §D. Three branches: valid-task → `completed`; invalid-task → `failed` with structured violation; mock-return-violation → violation surfaced before persistence. | varies by scenario | ≤ 5s |
|
|
68
|
+
| Dispatch Input Mapping | `conformance-dispatch-input-mapping` | RFC 0022 §A / HVMAP-1a — host honors `inputMapping` on `core.dispatch`. Capability-gated on `capabilities.agents.dispatchMapping`. | `completed` | ≤ 5s |
|
|
69
|
+
| Dispatch Output Mapping | `conformance-dispatch-output-mapping` | RFC 0022 §A / HVMAP-1b — host harvests child variables via `outputMapping` on `core.dispatch`. Capability-gated on `capabilities.agents.dispatchMapping`. | `completed` | ≤ 5s |
|
|
70
|
+
| Dispatch Cross-Worker Handoff | `conformance-dispatch-cross-worker-handoff` | RFC 0022 §A / HVMAP-1c — sequential fan-out: child-a writes via `perWorkerOutputMappings`, child-b reads via `perWorkerInputMappings`. Capability-gated on `capabilities.agents.dispatchMapping`. | `completed` | ≤ 10s |
|
|
71
|
+
| subWorkflow Input Mapping | `conformance-subworkflow-input-mapping` | RFC 0022 §B / HVMAP-2 — host honors `inputMapping` on `core.subWorkflow`; overrides matching `defaultValue` declarations on the child. Capability-gated on `capabilities.subWorkflow.inputMapping`. | `completed` | ≤ 10s |
|
|
72
|
+
| subWorkflow Input Mapping (child) | `conformance-subworkflow-input-mapping-child` | RFC 0022 §B / HVMAP-2 — child workflow for the input-mapping scenario. Declares `receivedPrdId.defaultValue='baked-in'`; parent's `inputMapping` MUST override that default. Single noop node; final variables read via `GET /v1/runs/{runId}` for the assertion. | `completed` | ≤ 5s |
|
|
73
|
+
| Dispatch Input Mapping (child) | `conformance-dispatch-input-mapping-child` | RFC 0022 §A / HVMAP-1a — child workflow for the dispatch input-mapping scenario. Single noop node; the scenario reads this child's `inputs_json` via `GET /v1/runs/{childRunId}` and asserts `inputs.childGreeting === 'Alice'`. | `completed` | ≤ 5s |
|
|
74
|
+
| Dispatch Output Mapping (child) | `conformance-dispatch-output-mapping-child` | RFC 0022 §A / HVMAP-1b — child workflow for the dispatch output-mapping scenario. Declares `childOutcome.defaultValue='done'`; on terminal, parent's `outputMapping` harvests `childOutcome → parentResult`. | `completed` | ≤ 5s |
|
|
75
|
+
| Dispatch Cross-Worker Handoff (child-a) | `conformance-dispatch-cross-worker-handoff-child-a` | RFC 0022 §A / HVMAP-1c — first child of the cross-worker-handoff scenario. Declares `output.defaultValue='hello'`; on terminal, parent's `perWorkerOutputMappings.child-a` harvests `output → sharedVar`. | `completed` | ≤ 5s |
|
|
76
|
+
| Dispatch Cross-Worker Handoff (child-b) | `conformance-dispatch-cross-worker-handoff-child-b` | RFC 0022 §A + §D / HVMAP-1c — second child of the cross-worker-handoff scenario. Sequential fan-out — runs after child-a; receives parent's `sharedVar` via `perWorkerInputMappings.child-b` onto its `input` input. Scenario reads child-b's `inputs_json` to assert `inputs.input === 'hello'`. | `completed` | ≤ 5s |
|
|
67
77
|
| Agent Memory Round-Trip | `conformance-agent-memory-roundtrip` | Phase 3 — `MemoryAdapter.list/get` write → read | `completed` | ≤ 15s |
|
|
68
78
|
| Agent Memory Cross-Tenant | `conformance-agent-memory-cross-tenant` | Phase 3 / CTI-1 — cross-tenant probe MUST return `[]` / `null` | `completed` | ≤ 10s |
|
|
69
79
|
| Agent Memory Redaction | `conformance-agent-memory-redaction` | Phase 3 / SR-1 — BYOK plaintext surfaces as `[REDACTED:<id>]` on read | `completed` | ≤ 15s |
|
package/package.json
CHANGED
package/schemas/README.md
CHANGED
|
@@ -6,11 +6,17 @@
|
|
|
6
6
|
|---|---|---|
|
|
7
7
|
| `agent-manifest.schema.json` | `node-packs.md` + agent-pack RFCs | Agent manifest entries distributed alongside node-pack manifests |
|
|
8
8
|
| `agent-ref.schema.json` | `agent-memory.md` + agent-identity RFC | Multi-Agent Shift Phase 1 — slim runtime AgentRef projection carried on `RunSnapshot.agent` / `runOrchestrator`, `WorkflowNode.agent?`, and `agent.*` event payloads |
|
|
9
|
+
| `ai-envelope.schema.json` | `ai-envelope.md` | FINAL v1.1 — inbound LLM-emission envelope. Top-level shape (`type` / `schemaVersion` / `envelopeId` / `correlationId` / `payload` / `meta` / `partial`). Per-kind payload schemas under `envelopes/`. Distinct from `RunEventDoc` (outbound) and `error-envelope.schema.json` (host HTTP errors). |
|
|
10
|
+
| `envelopes/clarification.request.schema.json` | `ai-envelope.md` §"Universal kinds" | FINAL v1.1 — payload for the universal `clarification.request` kind; engine lifts to `kind: "clarification"` `InterruptPayload`. |
|
|
11
|
+
| `envelopes/schema.request.schema.json` | `ai-envelope.md` §"Universal kinds" | FINAL v1.1 — LLM asks the engine for a kind's JSON Schema. Counts against `Capabilities.limits.schemaRounds`. |
|
|
12
|
+
| `envelopes/schema.response.schema.json` | `ai-envelope.md` §"Universal kinds" | FINAL v1.1 — side-channel ack for `schema.request`. Never surfaces to users. |
|
|
13
|
+
| `envelopes/error.schema.json` | `ai-envelope.md` §"Universal kinds" | FINAL v1.1 — LLM's deliberate error report. Distinct from `error-envelope.schema.json` (host HTTP errors). |
|
|
9
14
|
| `audit-verify-result.schema.json` | `auth-profiles.md` §`openwop-audit-log-integrity` | Response payload from `GET /v1/audit/verify` — chain-validity verdict + checkpoints + anomalies |
|
|
10
15
|
| `capabilities.schema.json` | `capabilities.md` | `/.well-known/openwop` response — protocolVersion + supportedEnvelopes + schemaVersions + limits + optional v1 discovery surface |
|
|
11
16
|
| `channel-written-payload.schema.json` | `channels-and-reducers.md` §Channel write event | Payload of the `channel.written` RunEvent — write input + reducer name |
|
|
12
17
|
| `conversation-event.schema.json` | `channels-and-reducers.md` + conversation RFC | Multi-turn conversation event shape for orchestrator-driven HITL flows |
|
|
13
18
|
| `conversation-turn.schema.json` | `channels-and-reducers.md` + conversation RFC | Conversation turn shape for user/agent/system messages |
|
|
19
|
+
| `core-conformance-mock-agent-config.schema.json` | `node-packs.md` + RFC 0023 | Config shape for the conformance-only `core.conformance.mock-agent` typeId — drives `agent.*` event emission on cue (`mockReasoning` / `mockToolCalls` / `mockHandoff` / `mockDecision` / `mockConfidence`). Hosts MUST refuse this typeId for production tenants unless `capabilities.conformance.mockAgent` is advertised. |
|
|
14
20
|
| `debug-bundle.schema.json` | `debug-bundle.md` | Portable run diagnostic export from `GET /v1/runs/{runId}/debug-bundle` |
|
|
15
21
|
| `dispatch-config.schema.json` | `node-packs.md` + dispatch RFC | Configuration shape for `core.dispatch` / sub-workflow routing |
|
|
16
22
|
| `error-envelope.schema.json` | `rest-endpoints.md` + `auth.md` | Canonical `{error, message, details?}` shape returned on every non-2xx |
|
|
@@ -27,6 +33,7 @@
|
|
|
27
33
|
| `run-snapshot.schema.json` | `rest-endpoints.md` §RunSnapshot | Projected run state from `GET /v1/runs/{runId}` |
|
|
28
34
|
| `security-advisory.schema.json` | `registry-operations.md` + INCIDENT-RESPONSE runbook | Registry-owned CVE advisory record at `registry/security/advisories.json`. One entry per disclosed vulnerability — id, severity, affected pack-name + SemVer range, optional fixedIn/advisoryUrl/credits. Enforced by `check-advisories.mjs` in `.github/workflows/registry-publish.yml`. |
|
|
29
35
|
| `suspend-request.schema.json` | `interrupt.md` | `InterruptPayload` with 8 `kind` discriminators (approval, clarification, external-event, custom, conversation.start, conversation.exchange, conversation.close, low-confidence) |
|
|
36
|
+
| `workflow-chain-pack-manifest.schema.json` | `workflow-chain-packs.md` + RFC 0013 | Manifest for workflow-chain packs (`kind: "workflow-chain"`) — pre-configured DAG fragments expanded inline at workflow-author time. Peer to `node-pack-manifest.schema.json`; disjoint via the `kind` discriminator. |
|
|
30
37
|
| `workflow-definition.schema.json` | `channels-and-reducers.md` + `node-packs.md` | DAG of nodes + edges + triggers + variables + channels |
|
|
31
38
|
|
|
32
39
|
## Validating against the schemas
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"type": "string",
|
|
11
11
|
"minLength": 3,
|
|
12
12
|
"maxLength": 256,
|
|
13
|
-
"description": "Globally-unique agent identifier. Naming convention mirrors `node-packs.md` §Naming — `<tier>.<org>.<pack>.<agent>` for vendor/community packs (`vendor.acme.support.tier1`); `core.<name>` for spec-canonical agents (`core.chat`, `core.research`); `host:<id>` slim-runtime form for host-internal AgentRefs that don't ship as packs. Host-internal `host:<id>` agents are valid AgentRefs at the wire level but MUST NOT be published as manifests (the `host:` namespace is reserved for runtime synthesis)."
|
|
13
|
+
"description": "Globally-unique agent identifier. Naming convention mirrors `node-packs.md` §Naming — `<tier>.<org>.<pack>.<agent>` for vendor/community packs (`vendor.acme.support.tier1`); `core.<name>` for spec-canonical agents (`core.chat`, `core.research`); `host:<id>` slim-runtime form for host-internal AgentRefs that don't ship as packs. Host-internal `host:<id>` agents are valid AgentRefs at the wire level but MUST NOT be published as manifests (the `host:` namespace is reserved for runtime synthesis). External-identity-system compatibility (STD-4): hosts MAY map an `agentId` to a W3C DID, an A2A AgentCard URL, an AGNTCY gateway identifier, or other external identity primitive via host-internal mapping tables. The external identifier MUST NOT be embedded as the wire-level `agentId` (doing so would force resolver dependencies on every consumer); carry it under vendor metadata or as the `host:<scheme>:<id>` form. See `spec/v1/agent-ref-positioning.md` §\"Composition rules\" for the recommended mapping conventions."
|
|
14
14
|
},
|
|
15
15
|
"name": {
|
|
16
16
|
"type": "string",
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://openwop.dev/spec/v1/ai-envelope.schema.json",
|
|
4
|
+
"title": "AIEnvelope",
|
|
5
|
+
"description": "Canonical inbound wire format for a typed, structured emission produced by an LLM during workflow execution. Distinct from `RunEventDoc` (which is the outbound run event log envelope). Per `spec/v1/ai-envelope.md`. The top-level shape is closed (`additionalProperties: false`); the `payload` shape is selected by the `type` discriminator and validated against a per-kind schema at `schemas/envelopes/{type}.schema.json` (universals) or a host-published vendor location. Hosts advertise the kind catalog via `Capabilities.supportedEnvelopes` and the per-kind active version via `Capabilities.schemaVersions`. Status: FINAL v1.1 (promoted 2026-05-18 via RFC 0021).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["type", "envelopeId", "correlationId", "payload", "meta"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"type": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"minLength": 1,
|
|
12
|
+
"maxLength": 256,
|
|
13
|
+
"description": "Discriminator for payload shape, kind routing, and Envelope Contract gate. Universal kinds (always allowed): `clarification.request`, `schema.request`, `schema.response`, `error`. Vendor kinds MUST be namespaced per `spec/v1/host-extensions.md` (e.g., `vendor.myndhyve.prd.create`). Pre-v1.x unnamespaced kinds (`prd.create`, `theme.create`, `tasks.create`) MAY appear in `Capabilities.supportedEnvelopes` for backward compatibility; v1.x hosts SHOULD prefer the namespaced form."
|
|
14
|
+
},
|
|
15
|
+
"schemaVersion": {
|
|
16
|
+
"type": "integer",
|
|
17
|
+
"minimum": 0,
|
|
18
|
+
"description": "Per-kind schema version. Absent → treat as 0. Matched against `Capabilities.schemaVersions[type]`. When the emitted version is lower than the advertised floor, engines under `envelopeStrictness: 'warn'` (default) MUST attempt validation against the advertised version and log `envelope_schema_version_drift`; engines under `envelopeStrictness: 'strict'` MUST refuse with `unknown_schema_version`. When higher than advertised, engines MUST refuse regardless of strictness."
|
|
19
|
+
},
|
|
20
|
+
"envelopeId": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"maxLength": 128,
|
|
24
|
+
"description": "Globally unique envelope id. Generated by the engine if absent on receipt; consumers MUST treat as opaque. Distinct from `correlationId` (which is the dedup/replay key)."
|
|
25
|
+
},
|
|
26
|
+
"correlationId": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1,
|
|
29
|
+
"maxLength": 128,
|
|
30
|
+
"description": "Caller-stable identifier for dedup, replay short-circuit, and causal chaining. Two envelopes in the same run with the same `correlationId` MUST be treated as a re-emission (engine returns the cached outcome). Same-`correlationId` envelopes with different `type` values MUST be refused with `envelope_correlation_conflict`. The engine propagates `correlationId` onto resulting `RunEventDoc.causationId`. Recommended construction: `${runId}:${nodeId}:${turnIndex}:${kindHash}`."
|
|
31
|
+
},
|
|
32
|
+
"nodeId": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"minLength": 1,
|
|
35
|
+
"maxLength": 128,
|
|
36
|
+
"description": "Set when the emitting node is identifiable. Lifted to top-level for per-node projection without payload coercion (mirrors `RunEventDoc.nodeId`). Engines MAY populate from execution context when absent."
|
|
37
|
+
},
|
|
38
|
+
"payload": {
|
|
39
|
+
"description": "Discriminated payload. Shape selected by `type`. Validated against the per-kind schema at `schemas/envelopes/{type}.schema.json` (universals) or a host-published vendor schema. Top-level accepts any JSON value because per-kind schemas vary; strict validation is per-kind, not at this layer.",
|
|
40
|
+
"type": ["object", "array", "string", "number", "boolean", "null"]
|
|
41
|
+
},
|
|
42
|
+
"meta": {
|
|
43
|
+
"$ref": "#/$defs/EnvelopeMeta"
|
|
44
|
+
},
|
|
45
|
+
"partial": {
|
|
46
|
+
"$ref": "#/$defs/PartialInfo"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"additionalProperties": false,
|
|
50
|
+
"$defs": {
|
|
51
|
+
"EnvelopeMeta": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"required": ["source", "ts"],
|
|
54
|
+
"properties": {
|
|
55
|
+
"source": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"enum": ["ai-generation", "user", "system"],
|
|
58
|
+
"description": "Provenance of this emission. `ai-generation` — LLM emitted this in a node turn. `user` — relayed from a user action (form fill, approval gate). `system` — engine-synthesized (e.g., resume value normalization). Gates approval-flow re-routing per `ai-envelope.md` §\"Source attribution\" (LLM-generated mutations route through approval gates; user-supplied mutations bypass them when the user is already authenticated)."
|
|
59
|
+
},
|
|
60
|
+
"contentTrust": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"enum": ["trusted", "untrusted"],
|
|
63
|
+
"description": "Trust tag mirroring `RunEventDoc.contentTrust`. Hosts MUST set `untrusted` when the payload origin is an MCP tool result per `mcp-integration.md` or an A2A inbound message per `a2a-integration.md`. The engine MUST propagate this onto any `RunEventDoc` emitted as a consequence of the envelope. Approval gates MUST refuse to advance on `untrusted` envelopes (refusal code `untrusted_content_blocks_approval`)."
|
|
64
|
+
},
|
|
65
|
+
"ts": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"format": "date-time",
|
|
68
|
+
"description": "ISO 8601 UTC timestamp of emission."
|
|
69
|
+
},
|
|
70
|
+
"traceparent": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "Optional W3C trace-context value (`traceparent` header format) for distributed tracing propagation. Engines that export OTel spans for envelope acceptance SHOULD honor this value as the parent span when present."
|
|
73
|
+
},
|
|
74
|
+
"label": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"maxLength": 256,
|
|
77
|
+
"description": "Optional human-readable label for ops dashboards (e.g., `\"Draft PRD #2\"`). Never used for routing; never persisted into event payloads in a security-relevant way. (in-flight)"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"additionalProperties": false,
|
|
81
|
+
"description": "Wire metadata. See `spec/v1/ai-envelope.md` §EnvelopeMeta."
|
|
82
|
+
},
|
|
83
|
+
"PartialInfo": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"required": ["isPartial", "index", "total"],
|
|
86
|
+
"properties": {
|
|
87
|
+
"isPartial": {
|
|
88
|
+
"type": "boolean",
|
|
89
|
+
"description": "True for all chunks of a partial emission EXCEPT the final one. The final chunk carries `isPartial: false` and signals reassembly completion. (in-flight)"
|
|
90
|
+
},
|
|
91
|
+
"index": {
|
|
92
|
+
"type": "integer",
|
|
93
|
+
"minimum": 0,
|
|
94
|
+
"description": "0-indexed chunk position. (in-flight)"
|
|
95
|
+
},
|
|
96
|
+
"total": {
|
|
97
|
+
"type": "integer",
|
|
98
|
+
"minimum": -1,
|
|
99
|
+
"description": "Total expected chunks. -1 when unknown (streaming without precount). (in-flight)"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"additionalProperties": false,
|
|
103
|
+
"description": "Present when the envelope is one fragment of a streamed emission. Cross-transport reassembly is open (see gap E1 in `ai-envelope.md`)."
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -49,6 +49,23 @@
|
|
|
49
49
|
"additionalProperties": false,
|
|
50
50
|
"description": "Hard limits enforced by the engine. See capabilities.md §3."
|
|
51
51
|
},
|
|
52
|
+
"envelopeStrictness": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"enum": ["warn", "strict"],
|
|
55
|
+
"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."
|
|
56
|
+
},
|
|
57
|
+
"envelopeContracts": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"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.",
|
|
60
|
+
"required": ["advertised"],
|
|
61
|
+
"properties": {
|
|
62
|
+
"advertised": {
|
|
63
|
+
"type": "boolean",
|
|
64
|
+
"description": "Host's node-pack manifests carry `EnvelopeContract` blocks."
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"additionalProperties": false
|
|
68
|
+
},
|
|
52
69
|
"extensions": {
|
|
53
70
|
"type": "object",
|
|
54
71
|
"description": "Optional per-canvas-type or per-workflow extensions (additional envelope types, override limits)."
|
|
@@ -84,11 +101,11 @@
|
|
|
84
101
|
},
|
|
85
102
|
"nodePackRuntimes": {
|
|
86
103
|
"type": "object",
|
|
87
|
-
"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.",
|
|
104
|
+
"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.",
|
|
88
105
|
"properties": {
|
|
89
106
|
"wasm": {
|
|
90
107
|
"type": "object",
|
|
91
|
-
"description": "WASM core-module runtime per RFC 0008. Hosts that load `runtime.language: \"wasm\"` packs MUST advertise `supported: true` and at least one entry in `abiVersions[]`.",
|
|
108
|
+
"description": "WASM core-module runtime per RFC 0008. Hosts that load `runtime.language: \"wasm\"` packs MUST advertise `supported: true` and at least one entry in `abiVersions[]`. `additionalProperties: true` preserved for future RFC 0008 amendments (e.g., per-pack memory accounting fields).",
|
|
92
109
|
"required": ["supported"],
|
|
93
110
|
"properties": {
|
|
94
111
|
"supported": {
|
|
@@ -125,7 +142,7 @@
|
|
|
125
142
|
},
|
|
126
143
|
"wasmComponent": {
|
|
127
144
|
"type": "object",
|
|
128
|
-
"description": "WASM Component Model variant (WIT-defined interfaces). Reserved for hosts that load `runtime.language: \"wasm-component\"` packs.",
|
|
145
|
+
"description": "WASM Component Model variant (WIT-defined interfaces). Reserved for hosts that load `runtime.language: \"wasm-component\"` packs. `additionalProperties: true` preserved until the Component Model spec stabilises in the v1.x line; tighten in the RFC that promotes wasm-component to a first-class runtime alongside `wasm`.",
|
|
129
146
|
"properties": {
|
|
130
147
|
"supported": { "type": "boolean" }
|
|
131
148
|
},
|
|
@@ -266,6 +283,17 @@
|
|
|
266
283
|
},
|
|
267
284
|
"additionalProperties": true
|
|
268
285
|
},
|
|
286
|
+
"conformance": {
|
|
287
|
+
"type": "object",
|
|
288
|
+
"description": "Conformance-only capability block (RFC 0023). Advertises which conformance-only typeIds (`core.conformance.*`) the host has registered. Hosts that don't ship conformance-only typeIds omit this block entirely. Production deployments SHOULD omit this block; conformance-only typeIds carry test hooks (e.g., `mockReasoning`, `mockConfidence`) that MUST NOT be reachable from production tenants.",
|
|
289
|
+
"properties": {
|
|
290
|
+
"mockAgent": {
|
|
291
|
+
"type": "boolean",
|
|
292
|
+
"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."
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
"additionalProperties": false
|
|
296
|
+
},
|
|
269
297
|
"fixtures": {
|
|
270
298
|
"type": "array",
|
|
271
299
|
"items": { "type": "string", "minLength": 1 },
|
|
@@ -311,6 +339,11 @@
|
|
|
311
339
|
"type": "boolean",
|
|
312
340
|
"description": "Phase 6. When `true`, host advertises that it implements the `core.dispatch` Core typeId AND honors the conservative-path commitment CP-2 (`core.dispatch` MUST NOT mutate the run's DAG mid-run). Implies (but does NOT require) `agents.orchestrator: true`."
|
|
313
341
|
},
|
|
342
|
+
"dispatchMapping": {
|
|
343
|
+
"type": "boolean",
|
|
344
|
+
"default": false,
|
|
345
|
+
"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'`."
|
|
346
|
+
},
|
|
314
347
|
"reasoning": {
|
|
315
348
|
"type": "object",
|
|
316
349
|
"description": "Phase 1 reasoning-event verbosity configuration.",
|
|
@@ -331,10 +364,274 @@
|
|
|
331
364
|
},
|
|
332
365
|
"additionalProperties": true
|
|
333
366
|
},
|
|
367
|
+
"memory": {
|
|
368
|
+
"type": "object",
|
|
369
|
+
"description": "MemoryAdapter capability block per RFC 0004 + the optional compaction profile per RFC 0012. Hosts that don't wire any memory surface omit the entire block.",
|
|
370
|
+
"properties": {
|
|
371
|
+
"supported": {
|
|
372
|
+
"type": "boolean",
|
|
373
|
+
"description": "When `true`, host implements the four-operation MemoryAdapter contract (`list`, `get`, `put`, `delete`) per RFC 0004 §A."
|
|
374
|
+
},
|
|
375
|
+
"maxEntrySizeBytes": {
|
|
376
|
+
"type": "integer",
|
|
377
|
+
"minimum": 1,
|
|
378
|
+
"description": "Upper bound on `MemoryEntry.content` size. Hosts SHOULD reject `put` exceeding this with `validation_error`."
|
|
379
|
+
},
|
|
380
|
+
"ttlSupported": {
|
|
381
|
+
"type": "boolean",
|
|
382
|
+
"description": "When `true`, host honors `expiresAt` per RFC 0004 §E."
|
|
383
|
+
},
|
|
384
|
+
"compaction": {
|
|
385
|
+
"type": "object",
|
|
386
|
+
"description": "RFC 0012 Memory Compaction Profile (Accepted 2026-05-15). Hosts that distill many short-lived MemoryEntry rows into fewer long-lived ones MAY advertise here; advertising implies the SR-1 carry-forward invariant (`SECURITY/invariants.yaml` row `memory-compaction-sr-1-carry-forward`).",
|
|
387
|
+
"required": ["supported"],
|
|
388
|
+
"properties": {
|
|
389
|
+
"supported": {
|
|
390
|
+
"type": "boolean",
|
|
391
|
+
"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."
|
|
392
|
+
},
|
|
393
|
+
"trigger": {
|
|
394
|
+
"type": "string",
|
|
395
|
+
"enum": ["host-managed", "client-requested", "both"],
|
|
396
|
+
"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`."
|
|
397
|
+
},
|
|
398
|
+
"maxInputEntries": {
|
|
399
|
+
"type": "integer",
|
|
400
|
+
"minimum": 1,
|
|
401
|
+
"description": "Informational ceiling on how many source entries one compaction call collapses. Not wire-enforced."
|
|
402
|
+
},
|
|
403
|
+
"maxOutputBytes": {
|
|
404
|
+
"type": "integer",
|
|
405
|
+
"minimum": 0,
|
|
406
|
+
"description": "Informational ceiling on the distilled entry size. SHOULD be ≤ `memory.maxEntrySizeBytes`."
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
"additionalProperties": false,
|
|
410
|
+
"if": { "properties": { "supported": { "const": true } }, "required": ["supported"] },
|
|
411
|
+
"then": { "required": ["supported", "trigger"] }
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
"additionalProperties": true
|
|
415
|
+
},
|
|
334
416
|
"conversationPrimitive": {
|
|
335
417
|
"type": "boolean",
|
|
336
418
|
"description": "Multi-Agent Shift Phase 4. When `true`, host advertises that it implements the `core.conversationGate` typeId AND honors the `conversation.start` / `conversation.exchange` / `conversation.close` suspend variants. Hosts that don't claim this fall back to `clarification.requested` interrupts for multi-turn user interjections."
|
|
337
419
|
},
|
|
420
|
+
"subWorkflow": {
|
|
421
|
+
"type": "object",
|
|
422
|
+
"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.",
|
|
423
|
+
"properties": {
|
|
424
|
+
"inputMapping": {
|
|
425
|
+
"type": "boolean",
|
|
426
|
+
"default": false,
|
|
427
|
+
"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."
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
"additionalProperties": false
|
|
431
|
+
},
|
|
432
|
+
"fs": {
|
|
433
|
+
"type": "object",
|
|
434
|
+
"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`.",
|
|
435
|
+
"properties": {
|
|
436
|
+
"supported": {
|
|
437
|
+
"type": "boolean",
|
|
438
|
+
"description": "Host advertises `ctx.fs.{read,write,delete,stat,list}`. `false` (or omission) signals the host does NOT expose a filesystem surface; `core.openwop.files` registration MUST refuse on such hosts."
|
|
439
|
+
},
|
|
440
|
+
"sandboxRoot": {
|
|
441
|
+
"type": "string",
|
|
442
|
+
"description": "Absolute path. Every fs operation is resolved relative to this root. MUST be set when `supported: true`."
|
|
443
|
+
},
|
|
444
|
+
"maxFileSizeBytes": {
|
|
445
|
+
"type": "integer",
|
|
446
|
+
"minimum": 0,
|
|
447
|
+
"description": "Per-file size cap enforced on write. 0 = unlimited (NOT recommended). Reads of files larger than this MAY return `file_too_large`."
|
|
448
|
+
},
|
|
449
|
+
"image": {
|
|
450
|
+
"type": "object",
|
|
451
|
+
"description": "Image-processing sub-capability. Optional.",
|
|
452
|
+
"properties": {
|
|
453
|
+
"supported": { "type": "boolean" },
|
|
454
|
+
"formats": {
|
|
455
|
+
"type": "array",
|
|
456
|
+
"items": { "type": "string", "enum": ["jpeg", "png", "webp", "avif", "gif"] }
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"additionalProperties": false
|
|
460
|
+
},
|
|
461
|
+
"pdf": {
|
|
462
|
+
"type": "object",
|
|
463
|
+
"description": "PDF-processing sub-capability. Optional.",
|
|
464
|
+
"properties": {
|
|
465
|
+
"supported": { "type": "boolean" }
|
|
466
|
+
},
|
|
467
|
+
"additionalProperties": false
|
|
468
|
+
},
|
|
469
|
+
"transport": {
|
|
470
|
+
"type": "object",
|
|
471
|
+
"description": "Network file-transport sub-capabilities. Optional.",
|
|
472
|
+
"properties": {
|
|
473
|
+
"ftp": { "type": "boolean" },
|
|
474
|
+
"sftp": { "type": "boolean" },
|
|
475
|
+
"ssh": { "type": "boolean" }
|
|
476
|
+
},
|
|
477
|
+
"additionalProperties": false
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
"if": { "properties": { "supported": { "const": true } }, "required": ["supported"] },
|
|
481
|
+
"then": { "required": ["supported", "sandboxRoot"] },
|
|
482
|
+
"additionalProperties": false
|
|
483
|
+
},
|
|
484
|
+
"kvStorage": {
|
|
485
|
+
"type": "object",
|
|
486
|
+
"description": "RFC 0015 (`Active`). TTL-aware key-value store with atomic increment + compare-and-swap. Required by `core.openwop.storage` kv-* nodes. Hosts MUST partition values by tenant (`kv-cross-tenant-isolation` invariant) and atomically apply increments + CAS when those flags are advertised.",
|
|
487
|
+
"properties": {
|
|
488
|
+
"supported": { "type": "boolean" },
|
|
489
|
+
"maxKeyBytes": { "type": "integer", "minimum": 0 },
|
|
490
|
+
"maxValueBytes": { "type": "integer", "minimum": 0 },
|
|
491
|
+
"maxTtlSeconds": { "type": "integer", "minimum": 0 },
|
|
492
|
+
"atomicIncrement": { "type": "boolean" },
|
|
493
|
+
"compareAndSwap": { "type": "boolean" }
|
|
494
|
+
},
|
|
495
|
+
"additionalProperties": false
|
|
496
|
+
},
|
|
497
|
+
"tableStorage": {
|
|
498
|
+
"type": "object",
|
|
499
|
+
"description": "RFC 0016 (`Active`). Structured-record store with user-defined schemas. Sibling to kvStorage. Cross-tenant isolation enforced (mirrors RFC 0015 invariant).",
|
|
500
|
+
"properties": {
|
|
501
|
+
"supported": { "type": "boolean" },
|
|
502
|
+
"maxRowsPerTable": { "type": "integer", "minimum": 0 },
|
|
503
|
+
"maxColumnsPerRow": { "type": "integer", "minimum": 0 },
|
|
504
|
+
"indexable": { "type": "boolean" },
|
|
505
|
+
"fullTextSearch": { "type": "boolean" }
|
|
506
|
+
},
|
|
507
|
+
"additionalProperties": false
|
|
508
|
+
},
|
|
509
|
+
"queueBus": {
|
|
510
|
+
"type": "object",
|
|
511
|
+
"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).",
|
|
512
|
+
"properties": {
|
|
513
|
+
"supported": { "type": "boolean" },
|
|
514
|
+
"backends": {
|
|
515
|
+
"type": "array",
|
|
516
|
+
"items": { "type": "string", "enum": ["rabbitmq", "kafka", "sqs", "sns", "pubsub", "mqtt", "nats", "redis-streams", "in-memory"] }
|
|
517
|
+
},
|
|
518
|
+
"deadLetterSupported": { "type": "boolean" },
|
|
519
|
+
"stream": {
|
|
520
|
+
"type": "object",
|
|
521
|
+
"properties": {
|
|
522
|
+
"supported": { "type": "boolean" },
|
|
523
|
+
"fromBeginning": { "type": "boolean" }
|
|
524
|
+
},
|
|
525
|
+
"additionalProperties": false
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"additionalProperties": false
|
|
529
|
+
},
|
|
530
|
+
"sql": {
|
|
531
|
+
"type": "object",
|
|
532
|
+
"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).",
|
|
533
|
+
"properties": {
|
|
534
|
+
"supported": { "type": "boolean" },
|
|
535
|
+
"datasources": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
|
|
536
|
+
"transactions": { "type": "boolean" },
|
|
537
|
+
"drivers": {
|
|
538
|
+
"type": "array",
|
|
539
|
+
"items": { "type": "string", "enum": ["postgres", "mysql", "mariadb", "sqlite", "mssql", "clickhouse", "snowflake", "bigquery", "duckdb"] }
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
"additionalProperties": false
|
|
543
|
+
},
|
|
544
|
+
"nosql": {
|
|
545
|
+
"type": "object",
|
|
546
|
+
"description": "RFC 0018 (`Active`). MongoDB-shape document store adapter.",
|
|
547
|
+
"properties": {
|
|
548
|
+
"supported": { "type": "boolean" },
|
|
549
|
+
"datasources": { "type": "array" },
|
|
550
|
+
"drivers": { "type": "array", "items": { "type": "string", "enum": ["mongodb", "dynamodb", "cosmosdb", "firestore"] } }
|
|
551
|
+
},
|
|
552
|
+
"additionalProperties": false
|
|
553
|
+
},
|
|
554
|
+
"vectorStore": {
|
|
555
|
+
"type": "object",
|
|
556
|
+
"description": "RFC 0018 (`Active`). Vector-DB capability for k-NN search.",
|
|
557
|
+
"properties": {
|
|
558
|
+
"supported": { "type": "boolean" },
|
|
559
|
+
"collections": { "type": "array" },
|
|
560
|
+
"backends": {
|
|
561
|
+
"type": "array",
|
|
562
|
+
"items": { "type": "string", "enum": ["pinecone", "qdrant", "weaviate", "milvus", "pgvector", "redis", "mongodb-atlas", "chroma", "azure-ai-search", "in-memory"] }
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
"additionalProperties": false
|
|
566
|
+
},
|
|
567
|
+
"searchIndex": {
|
|
568
|
+
"type": "object",
|
|
569
|
+
"description": "RFC 0018 (`Active`). Full-text search index adapter.",
|
|
570
|
+
"properties": {
|
|
571
|
+
"supported": { "type": "boolean" },
|
|
572
|
+
"indexes": { "type": "array" },
|
|
573
|
+
"backends": {
|
|
574
|
+
"type": "array",
|
|
575
|
+
"items": { "type": "string", "enum": ["elasticsearch", "opensearch", "meilisearch", "typesense", "algolia"] }
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
"additionalProperties": false
|
|
579
|
+
},
|
|
580
|
+
"blobStorage": {
|
|
581
|
+
"type": "object",
|
|
582
|
+
"description": "RFC 0019 (`Active`). Binary artifact store with presigned URLs. Per-bucket tenant isolation. Presigned URLs MUST expire at the advertised TTL.",
|
|
583
|
+
"properties": {
|
|
584
|
+
"supported": { "type": "boolean" },
|
|
585
|
+
"buckets": { "type": "array" },
|
|
586
|
+
"presignSupported": { "type": "boolean" },
|
|
587
|
+
"maxObjectBytes": { "type": "integer", "minimum": 0 }
|
|
588
|
+
},
|
|
589
|
+
"additionalProperties": false
|
|
590
|
+
},
|
|
591
|
+
"cache": {
|
|
592
|
+
"type": "object",
|
|
593
|
+
"description": "RFC 0019 (`Active`). TTL cache for HTTP / AI response memoization. Per-tenant scoping; TTL drift ≤ 1s.",
|
|
594
|
+
"properties": {
|
|
595
|
+
"supported": { "type": "boolean" },
|
|
596
|
+
"maxValueBytes": { "type": "integer", "minimum": 0 },
|
|
597
|
+
"maxTtlSeconds": { "type": "integer", "minimum": 0 }
|
|
598
|
+
},
|
|
599
|
+
"additionalProperties": false
|
|
600
|
+
},
|
|
601
|
+
"workflowChainPacks": {
|
|
602
|
+
"type": "object",
|
|
603
|
+
"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.",
|
|
604
|
+
"properties": {
|
|
605
|
+
"supported": {
|
|
606
|
+
"type": "boolean",
|
|
607
|
+
"description": "Whether the host's workflow editor implements chain expansion at author time. `false` (or omission) signals the host does NOT consume workflow-chain packs."
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
"required": ["supported"],
|
|
611
|
+
"additionalProperties": false
|
|
612
|
+
},
|
|
613
|
+
"mcp": {
|
|
614
|
+
"type": "object",
|
|
615
|
+
"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.",
|
|
616
|
+
"properties": {
|
|
617
|
+
"supported": { "type": "boolean", "description": "Host advertises a client-side MCP surface (ctx.mcp.*). See spec/v1/mcp-integration.md." },
|
|
618
|
+
"serverMount": {
|
|
619
|
+
"type": "object",
|
|
620
|
+
"description": "Server-side MCP composition (workflow IS an MCP server). When supported, the host mounts an MCP endpoint and routes inbound tools/call, resources/read, prompts/get into workflows. Inbound MUST be treated as `trustBoundary: 'untrusted'`.",
|
|
621
|
+
"properties": {
|
|
622
|
+
"supported": { "type": "boolean" },
|
|
623
|
+
"transports": {
|
|
624
|
+
"type": "array",
|
|
625
|
+
"items": { "type": "string", "enum": ["stdio", "streamable-http"] }
|
|
626
|
+
},
|
|
627
|
+
"samplingBridge": { "type": "boolean", "description": "Inbound sampling/createMessage bridges to the workflow's ctx.callAI." },
|
|
628
|
+
"elicitationBridge": { "type": "boolean", "description": "Inbound elicitation/create bridges to ctx.suspend." }
|
|
629
|
+
},
|
|
630
|
+
"additionalProperties": false
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
"additionalProperties": false
|
|
634
|
+
},
|
|
338
635
|
"compliance": {
|
|
339
636
|
"type": "object",
|
|
340
637
|
"description": "Privacy / compliance behavior advertised to clients (closes O5). Lets consumers know what masking mode is in effect so a `\"[REDACTED]\"` value in event log payloads is recognizable as a server-side mask vs an upstream null.",
|