@openwop/openwop-conformance 1.62.0 → 1.65.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/README.md +2 -2
- package/coverage.md +20 -0
- package/package.json +1 -1
- package/schemas/artifact-type-pack-manifest.schema.json +108 -24
- package/schemas/chat-card-pack-manifest.schema.json +125 -30
- package/schemas/connection-pack-manifest.schema.json +211 -38
- package/schemas/form-content-pack-manifest.schema.json +91 -20
- package/schemas/frontend-plugin-manifest.schema.json +10 -0
- package/schemas/node-pack-manifest.schema.json +311 -68
- package/schemas/prompt-pack-manifest.schema.json +48 -11
- package/schemas/registry-version-manifest.schema.json +5 -0
- package/schemas/workflow-chain-pack-manifest.schema.json +176 -40
- package/src/lib/artifactTypes.ts +52 -0
- package/src/lib/behavior-gate.ts +17 -0
- package/src/scenarios/artifact-type-legacy-ids.test.ts +124 -0
- package/src/scenarios/artifact-type-pack-install.test.ts +17 -6
- package/src/scenarios/artifact-type-store-without-render.test.ts +17 -4
- package/src/scenarios/chat-card-pack-execution.test.ts +17 -5
- package/src/scenarios/pack-manifest-extension-opacity.test.ts +179 -0
- package/src/scenarios/pack-manifest-extensions.test.ts +203 -0
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
"title": "ArtifactTypePackManifest",
|
|
5
5
|
"description": "Manifest for a published OpenWOP artifact-type pack — `pack.json` at the pack root with `kind: \"artifact-type\"`. Peer to `node-pack-manifest.schema.json` (RFC 0003), `workflow-chain-pack-manifest.schema.json` (RFC 0013), and `prompt-pack-manifest.schema.json` (RFC 0028); disjoint from all three via the `kind` discriminator. See `spec/v1/artifact-type-packs.md` for the canonical contract and RFC 0071 for the rationale.\n\nArtifact-type packs distribute typed artifact definitions — the JSON Schema, rendering hint, lifecycle, and export-format hints for the rich outputs workflow nodes produce — via the same signed-tarball + Ed25519 + SRI pipeline that already serves node, workflow-chain, and prompt packs. When a host installs an artifact-type pack and advertises `host.artifactTypes: { supported: true }`, it validates produced artifacts of the declared `artifactTypeId`s against their `schemaRef` before emitting `artifact.created`.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"version",
|
|
10
|
+
"kind",
|
|
11
|
+
"engines",
|
|
12
|
+
"artifactTypes"
|
|
13
|
+
],
|
|
8
14
|
"additionalProperties": false,
|
|
9
15
|
"properties": {
|
|
10
16
|
"kind": {
|
|
@@ -24,19 +30,38 @@
|
|
|
24
30
|
"description": "Pack-level SemVer 2.0.0.",
|
|
25
31
|
"pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
|
|
26
32
|
},
|
|
27
|
-
"description": {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
33
|
+
"description": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"maxLength": 1024
|
|
36
|
+
},
|
|
37
|
+
"author": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"license": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "SPDX license identifier (e.g., `Apache-2.0`, `MIT`)."
|
|
43
|
+
},
|
|
44
|
+
"homepage": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"format": "uri"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"format": "uri"
|
|
51
|
+
},
|
|
32
52
|
"keywords": {
|
|
33
53
|
"type": "array",
|
|
34
|
-
"items": {
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"maxLength": 64
|
|
57
|
+
},
|
|
35
58
|
"maxItems": 50
|
|
36
59
|
},
|
|
37
60
|
"engines": {
|
|
38
61
|
"type": "object",
|
|
39
|
-
"required": [
|
|
62
|
+
"required": [
|
|
63
|
+
"openwop"
|
|
64
|
+
],
|
|
40
65
|
"properties": {
|
|
41
66
|
"openwop": {
|
|
42
67
|
"type": "string",
|
|
@@ -47,26 +72,37 @@
|
|
|
47
72
|
},
|
|
48
73
|
"dependencies": {
|
|
49
74
|
"type": "object",
|
|
50
|
-
"additionalProperties": {
|
|
75
|
+
"additionalProperties": {
|
|
76
|
+
"type": "string"
|
|
77
|
+
},
|
|
51
78
|
"description": "Other packs this pack depends on. Map of pack name → semver range. Resolved transitively at workflow-register time."
|
|
52
79
|
},
|
|
53
80
|
"peerDependencies": {
|
|
54
81
|
"type": "object",
|
|
55
|
-
"additionalProperties": {
|
|
82
|
+
"additionalProperties": {
|
|
83
|
+
"type": "string"
|
|
84
|
+
},
|
|
56
85
|
"description": "Engine-supplied capabilities the pack consumes (e.g., `{ \"host.artifactTypes\": \"supported\" }`). Resolved against the host's advertised capabilities at register time."
|
|
57
86
|
},
|
|
58
87
|
"artifactTypes": {
|
|
59
88
|
"type": "array",
|
|
60
89
|
"minItems": 1,
|
|
61
|
-
"items": {
|
|
90
|
+
"items": {
|
|
91
|
+
"$ref": "#/$defs/ArtifactType"
|
|
92
|
+
},
|
|
62
93
|
"description": "Typed artifact definitions this pack contributes. Each MUST have a unique `artifactTypeId` within the pack."
|
|
63
94
|
},
|
|
64
|
-
"signing": {
|
|
95
|
+
"signing": {
|
|
96
|
+
"$ref": "#/$defs/Signing"
|
|
97
|
+
}
|
|
65
98
|
},
|
|
66
99
|
"$defs": {
|
|
67
100
|
"ArtifactType": {
|
|
68
101
|
"type": "object",
|
|
69
|
-
"required": [
|
|
102
|
+
"required": [
|
|
103
|
+
"artifactTypeId",
|
|
104
|
+
"schemaRef"
|
|
105
|
+
],
|
|
70
106
|
"additionalProperties": false,
|
|
71
107
|
"properties": {
|
|
72
108
|
"artifactTypeId": {
|
|
@@ -88,14 +124,19 @@
|
|
|
88
124
|
},
|
|
89
125
|
"validation": {
|
|
90
126
|
"type": "string",
|
|
91
|
-
"enum": [
|
|
127
|
+
"enum": [
|
|
128
|
+
"open",
|
|
129
|
+
"closed"
|
|
130
|
+
],
|
|
92
131
|
"description": "RFC 0075. Strictness contract of the artifact's `schemaRef` schema. `closed` ⇒ closed-world (`additionalProperties: false`); a consumer MAY rely on the absence of unknown fields. `open` (recommended for AI/LLM-produced artifacts) ⇒ the schema tolerates extra fields to absorb model drift; consumers MUST ignore unknown fields per COMPATIBILITY.md §2.1. Absent ⇒ `open` (the forward-compatible default). The `additionalProperties:false` requirement on `schemaRef` was relaxed MUST → SHOULD by RFC 0075: a closed-world artifact contract contradicts the protocol's own forward-compat mandate and the first AI-native adopter cannot meet it."
|
|
93
132
|
},
|
|
94
133
|
"displayName": {
|
|
95
134
|
"type": "string",
|
|
96
135
|
"description": "Human-readable label for artifact-management UIs. Non-normative."
|
|
97
136
|
},
|
|
98
|
-
"rendering": {
|
|
137
|
+
"rendering": {
|
|
138
|
+
"$ref": "#/$defs/RenderingHint"
|
|
139
|
+
},
|
|
99
140
|
"exportFormats": {
|
|
100
141
|
"type": "array",
|
|
101
142
|
"items": {
|
|
@@ -109,7 +150,11 @@
|
|
|
109
150
|
},
|
|
110
151
|
"syncOn": {
|
|
111
152
|
"type": "string",
|
|
112
|
-
"enum": [
|
|
153
|
+
"enum": [
|
|
154
|
+
"completion",
|
|
155
|
+
"approval",
|
|
156
|
+
"manual"
|
|
157
|
+
],
|
|
113
158
|
"description": "When the host registers the artifact as durable. Mirrors `node-pack-manifest.schema.json#/$defs/PackNode/properties/artifact/properties/syncOn`. Default `completion`."
|
|
114
159
|
},
|
|
115
160
|
"supportsCheckpoint": {
|
|
@@ -124,6 +169,11 @@
|
|
|
124
169
|
"type": "boolean",
|
|
125
170
|
"description": "True if the artifact's schema supports structural diffing (informs run-diff tooling per rest-endpoints.md §:diff). Non-normative."
|
|
126
171
|
}
|
|
172
|
+
},
|
|
173
|
+
"patternProperties": {
|
|
174
|
+
"^(x-|vendor\\.)": {
|
|
175
|
+
"description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
176
|
+
}
|
|
127
177
|
}
|
|
128
178
|
},
|
|
129
179
|
"RenderingHint": {
|
|
@@ -133,13 +183,33 @@
|
|
|
133
183
|
"properties": {
|
|
134
184
|
"display": {
|
|
135
185
|
"type": "string",
|
|
136
|
-
"enum": [
|
|
186
|
+
"enum": [
|
|
187
|
+
"markdown",
|
|
188
|
+
"code",
|
|
189
|
+
"image",
|
|
190
|
+
"audio",
|
|
191
|
+
"file"
|
|
192
|
+
],
|
|
137
193
|
"description": "How a consumer SHOULD render the artifact when it recognizes the value."
|
|
138
194
|
},
|
|
139
|
-
"mimeType": {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
195
|
+
"mimeType": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"maxLength": 255
|
|
198
|
+
},
|
|
199
|
+
"lang": {
|
|
200
|
+
"type": "string",
|
|
201
|
+
"maxLength": 64,
|
|
202
|
+
"description": "Language hint for `display: code`."
|
|
203
|
+
},
|
|
204
|
+
"alt": {
|
|
205
|
+
"type": "string",
|
|
206
|
+
"maxLength": 1024,
|
|
207
|
+
"description": "Accessibility text for image/audio/file."
|
|
208
|
+
},
|
|
209
|
+
"title": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"maxLength": 255
|
|
212
|
+
}
|
|
143
213
|
}
|
|
144
214
|
},
|
|
145
215
|
"Signing": {
|
|
@@ -147,14 +217,28 @@
|
|
|
147
217
|
"description": "Optional signing metadata. See node-packs.md §signing.",
|
|
148
218
|
"additionalProperties": false,
|
|
149
219
|
"properties": {
|
|
150
|
-
"publicKeyRef": {
|
|
151
|
-
|
|
220
|
+
"publicKeyRef": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"description": "Path inside the tarball to the Ed25519 public key (PEM-encoded)."
|
|
223
|
+
},
|
|
224
|
+
"signatureRef": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"description": "Path to the detached signature over `pack.json`."
|
|
227
|
+
},
|
|
152
228
|
"method": {
|
|
153
229
|
"type": "string",
|
|
154
|
-
"enum": [
|
|
230
|
+
"enum": [
|
|
231
|
+
"manual",
|
|
232
|
+
"sigstore"
|
|
233
|
+
],
|
|
155
234
|
"description": "Signing method. `manual` uses publicKeyRef + signatureRef; `sigstore` uses a Sigstore bundle at `pack.json.sigstore`."
|
|
156
235
|
}
|
|
157
236
|
}
|
|
158
237
|
}
|
|
238
|
+
},
|
|
239
|
+
"patternProperties": {
|
|
240
|
+
"^(x-|vendor\\.)": {
|
|
241
|
+
"description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
242
|
+
}
|
|
159
243
|
}
|
|
160
244
|
}
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
"title": "ChatCardPackManifest",
|
|
5
5
|
"description": "Manifest for a published OpenWOP AI chat card pack — `pack.json` at the pack root with `kind: \"card\"`. Peer to the node / workflow-chain / prompt / artifact-type pack manifests; disjoint via the `kind` discriminator. See `spec/v1/chat-card-packs.md` for the canonical contract and RFC 0071 Phase 2 for the rationale.\n\nA chat card pack distributes AI step cards: each card binds a prompt template (with typed input slots) to a typed output artifact. When a host advertises `host.chat.cardPacks: supported` and a registered card is invoked, the host substitutes inputs into the prompt, routes the call through `ctx.aiEnvelope.generate`, and (when `outputArtifactType` is set) validates the result against the referenced artifact-type pack's schema before emitting `artifact.created`.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"version",
|
|
10
|
+
"kind",
|
|
11
|
+
"engines",
|
|
12
|
+
"cards"
|
|
13
|
+
],
|
|
8
14
|
"additionalProperties": false,
|
|
9
15
|
"properties": {
|
|
10
16
|
"kind": {
|
|
@@ -24,46 +30,79 @@
|
|
|
24
30
|
"description": "Pack-level SemVer 2.0.0.",
|
|
25
31
|
"pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
|
|
26
32
|
},
|
|
27
|
-
"description": {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
33
|
+
"description": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"maxLength": 1024
|
|
36
|
+
},
|
|
37
|
+
"author": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"license": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "SPDX license identifier (e.g., `Apache-2.0`, `MIT`)."
|
|
43
|
+
},
|
|
44
|
+
"homepage": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"format": "uri"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"format": "uri"
|
|
51
|
+
},
|
|
32
52
|
"keywords": {
|
|
33
53
|
"type": "array",
|
|
34
|
-
"items": {
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"maxLength": 64
|
|
57
|
+
},
|
|
35
58
|
"maxItems": 50
|
|
36
59
|
},
|
|
37
60
|
"engines": {
|
|
38
61
|
"type": "object",
|
|
39
|
-
"required": [
|
|
62
|
+
"required": [
|
|
63
|
+
"openwop"
|
|
64
|
+
],
|
|
40
65
|
"properties": {
|
|
41
|
-
"openwop": {
|
|
66
|
+
"openwop": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"description": "Semver range — which openwop protocol versions this pack works against."
|
|
69
|
+
}
|
|
42
70
|
},
|
|
43
71
|
"additionalProperties": true
|
|
44
72
|
},
|
|
45
73
|
"dependencies": {
|
|
46
74
|
"type": "object",
|
|
47
|
-
"additionalProperties": {
|
|
75
|
+
"additionalProperties": {
|
|
76
|
+
"type": "string"
|
|
77
|
+
},
|
|
48
78
|
"description": "Other packs this pack depends on (e.g., the artifact-type pack declaring this card's `outputArtifactType`). Map of pack name → semver range."
|
|
49
79
|
},
|
|
50
80
|
"peerDependencies": {
|
|
51
81
|
"type": "object",
|
|
52
|
-
"additionalProperties": {
|
|
82
|
+
"additionalProperties": {
|
|
83
|
+
"type": "string"
|
|
84
|
+
},
|
|
53
85
|
"description": "Engine-supplied capabilities the pack consumes (e.g., `{ \"host.aiEnvelope\": \"supported\", \"host.chat.cards\": \"supported\" }`). Resolved against the host's advertised capabilities at register time."
|
|
54
86
|
},
|
|
55
87
|
"cards": {
|
|
56
88
|
"type": "array",
|
|
57
89
|
"minItems": 1,
|
|
58
|
-
"items": {
|
|
90
|
+
"items": {
|
|
91
|
+
"$ref": "#/$defs/Card"
|
|
92
|
+
},
|
|
59
93
|
"description": "AI chat card definitions this pack contributes. Each MUST have a unique `cardTypeId` within the pack."
|
|
60
94
|
},
|
|
61
|
-
"signing": {
|
|
95
|
+
"signing": {
|
|
96
|
+
"$ref": "#/$defs/Signing"
|
|
97
|
+
}
|
|
62
98
|
},
|
|
63
99
|
"$defs": {
|
|
64
100
|
"Card": {
|
|
65
101
|
"type": "object",
|
|
66
|
-
"required": [
|
|
102
|
+
"required": [
|
|
103
|
+
"cardTypeId",
|
|
104
|
+
"prompt"
|
|
105
|
+
],
|
|
67
106
|
"additionalProperties": false,
|
|
68
107
|
"properties": {
|
|
69
108
|
"cardTypeId": {
|
|
@@ -78,10 +117,14 @@
|
|
|
78
117
|
"minimum": 0,
|
|
79
118
|
"description": "Non-negative integer card-schema version (the envelope/artifact integer-version axis). Absent ⇒ treated as 0."
|
|
80
119
|
},
|
|
81
|
-
"prompt": {
|
|
120
|
+
"prompt": {
|
|
121
|
+
"$ref": "#/$defs/PromptSpec"
|
|
122
|
+
},
|
|
82
123
|
"inputs": {
|
|
83
124
|
"type": "array",
|
|
84
|
-
"items": {
|
|
125
|
+
"items": {
|
|
126
|
+
"$ref": "#/$defs/InputField"
|
|
127
|
+
},
|
|
85
128
|
"description": "Typed input fields the card collects. The portable subset only; host-specific widget kinds extend via `vendor.*`/`x-` prefixed `type` values."
|
|
86
129
|
},
|
|
87
130
|
"outputArtifactType": {
|
|
@@ -104,42 +147,79 @@
|
|
|
104
147
|
"maxItems": 32,
|
|
105
148
|
"description": "Model capabilities the card requires the active model to advertise. Reuses the `requiredModelCapabilities` registry in `host-capabilities.md` (spec-reserved: `structured-output`, `discriminator-enum`, `long-context`, `reasoning`, `function-calling`; host extensions `x-host-<host>-`)."
|
|
106
149
|
}
|
|
150
|
+
},
|
|
151
|
+
"patternProperties": {
|
|
152
|
+
"^(x-|vendor\\.)": {
|
|
153
|
+
"description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
154
|
+
}
|
|
107
155
|
}
|
|
108
156
|
},
|
|
109
157
|
"PromptSpec": {
|
|
110
158
|
"type": "object",
|
|
111
|
-
"required": [
|
|
159
|
+
"required": [
|
|
160
|
+
"template",
|
|
161
|
+
"placeholderMapping"
|
|
162
|
+
],
|
|
112
163
|
"additionalProperties": false,
|
|
113
164
|
"description": "The prompt the card composes. The host substitutes mapped input values into `template`/`systemPrompt` before dispatch; segments derived from card inputs are `untrusted` (RFC 0071 Trust boundary).",
|
|
114
165
|
"properties": {
|
|
115
|
-
"template": {
|
|
116
|
-
|
|
166
|
+
"template": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"minLength": 1,
|
|
169
|
+
"description": "Prompt body with `{{placeholder}}` slots."
|
|
170
|
+
},
|
|
171
|
+
"systemPrompt": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "Optional system prompt."
|
|
174
|
+
},
|
|
117
175
|
"placeholderMapping": {
|
|
118
176
|
"type": "object",
|
|
119
|
-
"additionalProperties": {
|
|
177
|
+
"additionalProperties": {
|
|
178
|
+
"type": "string"
|
|
179
|
+
},
|
|
120
180
|
"description": "Map of `{{placeholder}}` name → input path (e.g. `\"spec\": \"inputs.spec\"`)."
|
|
121
181
|
},
|
|
122
|
-
"temperature": {
|
|
123
|
-
|
|
182
|
+
"temperature": {
|
|
183
|
+
"type": "number",
|
|
184
|
+
"minimum": 0,
|
|
185
|
+
"maximum": 2
|
|
186
|
+
},
|
|
187
|
+
"maxTokens": {
|
|
188
|
+
"type": "integer",
|
|
189
|
+
"minimum": 1
|
|
190
|
+
}
|
|
124
191
|
}
|
|
125
192
|
},
|
|
126
193
|
"InputField": {
|
|
127
194
|
"type": "object",
|
|
128
|
-
"required": [
|
|
195
|
+
"required": [
|
|
196
|
+
"id",
|
|
197
|
+
"type"
|
|
198
|
+
],
|
|
129
199
|
"additionalProperties": false,
|
|
130
200
|
"properties": {
|
|
131
|
-
"id": {
|
|
201
|
+
"id": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"minLength": 1,
|
|
204
|
+
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$"
|
|
205
|
+
},
|
|
132
206
|
"type": {
|
|
133
207
|
"type": "string",
|
|
134
208
|
"description": "Closed portable subset OR a `vendor.<org>.<kind>` / `x-<kind>` host extension other hosts ignore. The portable subset (G9, resolved 2026-05-27 against MyndHyve's `CardFieldType`): `text`, `longtext`, `number`, `boolean`, `select`, `multiselect`, `file`, `artifact-ref`. MyndHyve maps `textarea`→`longtext` and `toggle`→`boolean`; its product-specific kinds (`canvas-reference`, `collection-reference`, `color`) are host extensions (`vendor.myndhyve.*`), not portable.",
|
|
135
209
|
"pattern": "^(text|longtext|number|boolean|select|multiselect|file|artifact-ref|vendor\\.[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*|x-[a-z][a-z0-9-]*)$"
|
|
136
210
|
},
|
|
137
|
-
"label": {
|
|
138
|
-
|
|
211
|
+
"label": {
|
|
212
|
+
"type": "string"
|
|
213
|
+
},
|
|
214
|
+
"required": {
|
|
215
|
+
"type": "boolean"
|
|
216
|
+
},
|
|
139
217
|
"default": {},
|
|
140
218
|
"options": {
|
|
141
219
|
"type": "array",
|
|
142
|
-
"items": {
|
|
220
|
+
"items": {
|
|
221
|
+
"type": "string"
|
|
222
|
+
},
|
|
143
223
|
"description": "Choices for `type: \"select\"`."
|
|
144
224
|
}
|
|
145
225
|
}
|
|
@@ -149,10 +229,25 @@
|
|
|
149
229
|
"description": "Optional signing metadata. See node-packs.md §signing.",
|
|
150
230
|
"additionalProperties": false,
|
|
151
231
|
"properties": {
|
|
152
|
-
"publicKeyRef": {
|
|
153
|
-
|
|
154
|
-
|
|
232
|
+
"publicKeyRef": {
|
|
233
|
+
"type": "string"
|
|
234
|
+
},
|
|
235
|
+
"signatureRef": {
|
|
236
|
+
"type": "string"
|
|
237
|
+
},
|
|
238
|
+
"method": {
|
|
239
|
+
"type": "string",
|
|
240
|
+
"enum": [
|
|
241
|
+
"manual",
|
|
242
|
+
"sigstore"
|
|
243
|
+
]
|
|
244
|
+
}
|
|
155
245
|
}
|
|
156
246
|
}
|
|
247
|
+
},
|
|
248
|
+
"patternProperties": {
|
|
249
|
+
"^(x-|vendor\\.)": {
|
|
250
|
+
"description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
251
|
+
}
|
|
157
252
|
}
|
|
158
253
|
}
|