@openwop/openwop-conformance 1.68.1 → 1.68.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1773,6 +1773,66 @@
|
|
|
1773
1773
|
}
|
|
1774
1774
|
}
|
|
1775
1775
|
},
|
|
1776
|
+
"artifactTypes": {
|
|
1777
|
+
"type": "object",
|
|
1778
|
+
"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.",
|
|
1779
|
+
"additionalProperties": false,
|
|
1780
|
+
"properties": {
|
|
1781
|
+
"supported": { "type": "boolean", "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`." },
|
|
1782
|
+
"store": { "type": "boolean", "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." },
|
|
1783
|
+
"render": { "type": "boolean", "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)." },
|
|
1784
|
+
"export": { "type": "array", "items": { "type": "string" }, "description": "Export-format identifiers the host can materialize, drawn from declared `exportFormats`. Advisory." },
|
|
1785
|
+
"types": {
|
|
1786
|
+
"type": "object",
|
|
1787
|
+
"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).",
|
|
1788
|
+
"additionalProperties": {
|
|
1789
|
+
"type": "object",
|
|
1790
|
+
"additionalProperties": false,
|
|
1791
|
+
"properties": {
|
|
1792
|
+
"validated": { "type": "boolean", "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." },
|
|
1793
|
+
"validation": { "type": "string", "enum": ["open", "closed"], "description": "Mirrors `ArtifactType.validation`, surfacing schema strictness in discovery so a consumer needn't fetch the schema. Default `\"open\"` per `COMPATIBILITY.md` §2.1." },
|
|
1794
|
+
"schemaVersion": { "type": "integer", "minimum": 0 },
|
|
1795
|
+
"store": { "type": "boolean" },
|
|
1796
|
+
"render": { "type": "boolean" },
|
|
1797
|
+
"export": { "type": "array", "items": { "type": "string" } }
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
},
|
|
1803
|
+
"forms": {
|
|
1804
|
+
"type": "object",
|
|
1805
|
+
"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.",
|
|
1806
|
+
"additionalProperties": false,
|
|
1807
|
+
"properties": {
|
|
1808
|
+
"contentPacks": { "type": "boolean", "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." }
|
|
1809
|
+
}
|
|
1810
|
+
},
|
|
1811
|
+
"aiEnvelope": {
|
|
1812
|
+
"type": "object",
|
|
1813
|
+
"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`.",
|
|
1814
|
+
"additionalProperties": false,
|
|
1815
|
+
"properties": {
|
|
1816
|
+
"supported": { "type": "boolean", "description": "`true` ⇒ `ctx.aiEnvelope.generate` is exposed. Absent/`false` ⇒ packs binding this surface fail with `host_capability_missing`." },
|
|
1817
|
+
"await": { "type": "boolean", "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." }
|
|
1818
|
+
}
|
|
1819
|
+
},
|
|
1820
|
+
"promptLibrary": {
|
|
1821
|
+
"type": "object",
|
|
1822
|
+
"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.",
|
|
1823
|
+
"additionalProperties": false,
|
|
1824
|
+
"properties": {
|
|
1825
|
+
"supported": { "type": "boolean", "description": "`true` ⇒ `ctx.promptLibrary.get(promptId)` resolves a `{ promptId, systemPrompt, version, envelopeType? }` record. The returned `version` MUST pin the prompt text for replay." }
|
|
1826
|
+
}
|
|
1827
|
+
},
|
|
1828
|
+
"agentRuntime": {
|
|
1829
|
+
"type": "object",
|
|
1830
|
+
"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.",
|
|
1831
|
+
"additionalProperties": false,
|
|
1832
|
+
"properties": {
|
|
1833
|
+
"supported": { "type": "boolean", "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." }
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1776
1836
|
"deadLetter": {
|
|
1777
1837
|
"type": "object",
|
|
1778
1838
|
"description": "RFC 0053 (`Draft`). Run-level dead-letter sink for terminally-failed runs/nodes. On retry exhaustion (RFC 0009), the run is routed to a durable, inspectable sink and a `run.dead_lettered` event is emitted; dead-lettered runs remain fork-eligible (RFC 0011) for the retention window. Distinct from `queueBus.deadLetterSupported`, which dead-letters transport *messages*, not *runs*.",
|
|
@@ -163,20 +163,35 @@ describe('webhook-signed-delivery: end-to-end HMAC v1', () => {
|
|
|
163
163
|
'webhooks.md §"Signature algorithm versioning"',
|
|
164
164
|
'every delivery MUST set X-openwop-Signature-Algorithm: v1',
|
|
165
165
|
)).toBe('v1');
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
// Header names + signature format per webhooks.md v1.1 §"Delivery headers"
|
|
167
|
+
// (the SSoT). The pre-fix scenario asserted `x-openwop-subscription-id`,
|
|
168
|
+
// `x-openwop-signature-timestamp`, and a BARE-HEX `x-openwop-signature` —
|
|
169
|
+
// three names/shapes that appear in NO spec file or RFC. webhooks.md
|
|
170
|
+
// specifies `X-openwop-Webhook-Id`, `X-openwop-Timestamp`, and
|
|
171
|
+
// `X-openwop-Signature: sha256={hex}`. (Suite↔spec divergence fixed 2026-08-09.)
|
|
172
|
+
expect(
|
|
173
|
+
first.headers['x-openwop-webhook-id'],
|
|
174
|
+
driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Webhook-Id MUST carry the subscription id'),
|
|
175
|
+
).toBe(sub.subscriptionId);
|
|
176
|
+
|
|
177
|
+
const timestamp = first.headers['x-openwop-timestamp'];
|
|
178
|
+
expect(
|
|
179
|
+
typeof timestamp === 'string' && timestamp.length > 0,
|
|
180
|
+
driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Timestamp MUST be a Unix-seconds integer string'),
|
|
181
|
+
).toBe(true);
|
|
182
|
+
|
|
183
|
+
const signature = first.headers['x-openwop-signature'] ?? '';
|
|
184
|
+
expect(
|
|
185
|
+
signature.startsWith('sha256='),
|
|
186
|
+
driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST carry the `sha256=` prefix'),
|
|
187
|
+
).toBe(true);
|
|
173
188
|
const expected = createHmac('sha256', sub.secret)
|
|
174
189
|
.update(`${timestamp}.${first.body}`, 'utf8')
|
|
175
190
|
.digest('hex');
|
|
176
|
-
expect(
|
|
177
|
-
'
|
|
178
|
-
'X-openwop-Signature MUST be HMAC-SHA256(secret, `${
|
|
179
|
-
)
|
|
191
|
+
expect(
|
|
192
|
+
signature.replace('sha256=', ''),
|
|
193
|
+
driver.describe('webhooks.md §"Delivery headers"', 'X-openwop-Signature MUST be sha256=HMAC-SHA256(secret, `${X-openwop-Timestamp}.${rawBody}`)'),
|
|
194
|
+
).toBe(expected);
|
|
180
195
|
|
|
181
196
|
// Body should parse as JSON with a run event shape.
|
|
182
197
|
const event = JSON.parse(first.body) as { type?: unknown; runId?: unknown };
|