@ixo/topic-protocol 0.7.0 → 0.8.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.
Files changed (37) hide show
  1. package/README.md +4 -2
  2. package/dist/schemas/action-receipt.schema.json +105 -11
  3. package/dist/schemas/decision-to-pay-template.schema.json +346 -0
  4. package/dist/schemas/payable-obligation.schema.json +312 -0
  5. package/dist/schemas/payment-terms.schema.json +287 -0
  6. package/dist/schemas/topic-action-request.schema.json +30 -0
  7. package/dist/schemas/topic-contract-state.schema.json +29 -3
  8. package/dist/schemas/topic-flow-binding.schema.json +28 -0
  9. package/dist/schemas/topic-kind-profile.schema.json +32 -2
  10. package/dist/schemas/topic-operation.schema.json +2 -2
  11. package/dist/src/action-runtime/types.d.ts +101 -0
  12. package/dist/src/action-runtime/types.js +12 -0
  13. package/dist/src/action-runtime/types.js.map +1 -0
  14. package/dist/src/contracts/schemas.d.ts +2608 -463
  15. package/dist/src/contracts/schemas.js +10 -0
  16. package/dist/src/contracts/schemas.js.map +1 -1
  17. package/dist/src/contracts/topic-contract.d.ts +8 -1
  18. package/dist/src/contracts/topic-contract.js.map +1 -1
  19. package/dist/src/contracts/topic-kind-profile.d.ts +29 -0
  20. package/dist/src/contracts/topic-kind-profile.js +31 -0
  21. package/dist/src/contracts/topic-kind-profile.js.map +1 -1
  22. package/dist/src/index.d.ts +2 -1
  23. package/dist/src/index.js +2 -1
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/projector/payload.d.ts +18 -0
  26. package/dist/src/projector/payload.js +57 -1
  27. package/dist/src/projector/payload.js.map +1 -1
  28. package/dist/src/projector/state.js +144 -0
  29. package/dist/src/projector/state.js.map +1 -1
  30. package/dist/src/projector/types.d.ts +13 -3
  31. package/dist/src/projector/types.js.map +1 -1
  32. package/package.json +4 -2
  33. package/templates/decision-to-pay/README.md +59 -0
  34. package/templates/decision-to-pay/milestone-payment-release.template.json +195 -0
  35. package/templates/decision-to-pay/outcome-payment-claim.template.json +198 -0
  36. package/templates/decision-to-pay/payment-on-delivery.template.json +198 -0
  37. package/templates/decision-to-pay/verified-work-payment.template.json +283 -0
package/README.md CHANGED
@@ -9,7 +9,7 @@ identity of a discussion.
9
9
 
10
10
  ## Status
11
11
 
12
- **Version:** 0.7.0
12
+ **Version:** 0.8.0
13
13
 
14
14
  **Maturity:** Draft implementation candidate
15
15
  **Execution source of truth:** [Linear Topic Protocol project](https://linear.app/ixo-world/project/topic-protocol-4ea58bc7910d)
@@ -24,6 +24,7 @@ and external action execution require their dedicated conformance evidence.
24
24
  - [Architecture decisions](docs/adr/README.md)
25
25
  - [Why Topics matter](docs/topics-feature-guide.md) — a non-technical feature guide
26
26
  - [Extending Topic Kinds](docs/extending-topic-kinds.md) — third-party custom Kind and Kind Profile guide
27
+ - [Decision-to-Pay templates](templates/decision-to-pay/README.md) — governed payment decision contract pack
27
28
  - [Protocol chapters](docs/protocol/README.md)
28
29
  - [Machine-readable contracts](contracts/README.md)
29
30
  - [Reference implementation](docs/reference-implementation.md)
@@ -40,7 +41,7 @@ key-value adapter at its integration boundary.
40
41
 
41
42
  The package includes:
42
43
 
43
- - strict Draft 2020-12 validation for all 29 contracts, including Kind Profiles, Job Cards, external work, delivery, evaluation, claims, and settlement receipts;
44
+ - strict Draft 2020-12 validation for all 32 contracts, including Kind Profiles, Job Cards, payment terms, payable obligations, external work, delivery, evaluation, claims, and settlement receipts;
44
45
  - pinned, declarative Kind Profiles with safe standard-Kind fallback;
45
46
  - deterministic Topic-index reconciliation, structured search, and personal ranking;
46
47
  - deterministic Topic projection from a root and authorised operations;
@@ -147,6 +148,7 @@ examples/ Valid reference vectors
147
148
  api/ OpenAPI and MCP contract surfaces
148
149
  scripts/ Dependency-free validation and integrity tooling
149
150
  checksums/ Reproducible SHA-256 manifest
151
+ templates/ Machine-readable Topic Template packs
150
152
  src/ TypeScript contract and projection reference library
151
153
  test/ TDD contract, behavior, and edge-case tests
152
154
  ```
@@ -3,16 +3,110 @@
3
3
  "$id": "https://topic-protocol.ixo.world/schemas/action-receipt.schema.json",
4
4
  "title": "Action receipt",
5
5
  "type": "object",
6
- "required": ["receiptId", "topicId", "action", "actor", "status", "idempotencyKey", "createdAt"],
7
- "properties": {
8
- "receiptId": { "type": "string", "minLength": 1 },
6
+ "required": [],
7
+ "properties": {},
8
+ "oneOf": [{ "$ref": "#/$defs/v1" }, { "$ref": "#/$defs/v2" }],
9
+ "$defs": {
9
10
  "topicId": { "type": "string", "pattern": "^ixo:topic:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" },
10
- "action": { "type": "string", "minLength": 1 },
11
- "actor": { "type": "string", "minLength": 1 },
12
- "status": { "type": "string", "enum": ["requested", "confirmed", "succeeded", "failed", "rejected"] },
13
- "idempotencyKey": { "type": "string", "minLength": 1 },
14
- "createdAt": { "type": "string", "format": "date-time" },
15
- "capability": { "type": "string" }
16
- },
17
- "additionalProperties": true
11
+ "digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
12
+ "reference": {
13
+ "type": "object",
14
+ "required": ["digest"],
15
+ "properties": {
16
+ "digest": { "$ref": "#/$defs/digest" },
17
+ "ref": { "type": "string", "minLength": 1 },
18
+ "summary": { "type": "object", "maxProperties": 20 }
19
+ },
20
+ "additionalProperties": false
21
+ },
22
+ "v1": {
23
+ "type": "object",
24
+ "required": ["receiptId", "topicId", "action", "actor", "status", "idempotencyKey", "createdAt"],
25
+ "properties": {
26
+ "receiptId": { "type": "string", "minLength": 1 },
27
+ "topicId": { "$ref": "#/$defs/topicId" },
28
+ "action": { "type": "string", "minLength": 1 },
29
+ "actor": { "type": "string", "minLength": 1 },
30
+ "status": { "enum": ["requested", "confirmed", "succeeded", "failed", "rejected"] },
31
+ "idempotencyKey": { "type": "string", "minLength": 1 },
32
+ "createdAt": { "type": "string", "format": "date-time" },
33
+ "capability": { "type": "string" }
34
+ },
35
+ "additionalProperties": true
36
+ },
37
+ "v2": {
38
+ "type": "object",
39
+ "required": ["version", "receiptId", "sequence", "requestId", "topicId", "topicRevision", "action", "runtime", "actorDid", "executorDid", "status", "idempotencyKey", "occurredAt", "authorization", "input", "issuerDid", "signature"],
40
+ "properties": {
41
+ "version": { "const": 2 },
42
+ "receiptId": { "type": "string", "minLength": 1 },
43
+ "sequence": { "type": "integer", "minimum": 1 },
44
+ "requestId": { "type": "string", "minLength": 1 },
45
+ "topicId": { "$ref": "#/$defs/topicId" },
46
+ "topicRevision": { "type": "string", "minLength": 1 },
47
+ "action": {
48
+ "type": "object",
49
+ "required": ["type", "can", "registryVersion", "contractDigest"],
50
+ "properties": {
51
+ "type": { "type": "string", "pattern": "^qi/" },
52
+ "can": { "type": "string", "minLength": 3 },
53
+ "registryVersion": { "type": "string", "minLength": 1 },
54
+ "contractDigest": { "$ref": "#/$defs/digest" }
55
+ },
56
+ "additionalProperties": false
57
+ },
58
+ "runtime": {
59
+ "type": "object",
60
+ "required": ["provider", "executionId"],
61
+ "properties": {
62
+ "provider": { "enum": ["qi-flow", "qiforge", "mcp"] },
63
+ "bindingId": { "type": "string", "minLength": 1 },
64
+ "flowUri": { "type": "string", "minLength": 1 },
65
+ "sessionRunId": { "type": "string", "minLength": 1 },
66
+ "nodeId": { "type": "string", "minLength": 1 },
67
+ "executionId": { "type": "string", "minLength": 1 }
68
+ },
69
+ "additionalProperties": false
70
+ },
71
+ "actorDid": { "type": "string", "pattern": "^did:" },
72
+ "executorDid": { "type": "string", "pattern": "^did:" },
73
+ "status": { "enum": ["requested", "awaiting_confirmation", "running", "succeeded", "failed", "rejected", "cancelled", "needs_verification"] },
74
+ "idempotencyKey": { "type": "string", "minLength": 1 },
75
+ "occurredAt": { "type": "string", "format": "date-time" },
76
+ "authorization": {
77
+ "type": "object",
78
+ "required": ["capability"],
79
+ "properties": {
80
+ "capability": { "type": "string", "minLength": 1 },
81
+ "invocation": { "type": "string", "minLength": 1 },
82
+ "confirmation": { "type": "string", "minLength": 1 }
83
+ },
84
+ "additionalProperties": false
85
+ },
86
+ "input": { "$ref": "#/$defs/reference" },
87
+ "output": { "$ref": "#/$defs/reference" },
88
+ "proof": {
89
+ "type": "object",
90
+ "required": ["kind", "digest"],
91
+ "properties": {
92
+ "kind": { "enum": ["fields", "custom", "host-receipt"] },
93
+ "digest": { "$ref": "#/$defs/digest" },
94
+ "refs": { "type": "array", "uniqueItems": true, "maxItems": 50, "items": { "type": "string", "minLength": 1 } }
95
+ },
96
+ "additionalProperties": false
97
+ },
98
+ "evidenceRefs": { "type": "array", "uniqueItems": true, "maxItems": 100, "items": { "type": "string", "minLength": 1 } },
99
+ "traceRef": { "type": "string", "minLength": 1 },
100
+ "error": {
101
+ "type": "object",
102
+ "required": ["message"],
103
+ "properties": { "code": { "type": "string", "maxLength": 80 }, "message": { "type": "string", "maxLength": 2000 } },
104
+ "additionalProperties": false
105
+ },
106
+ "issuerDid": { "type": "string", "pattern": "^did:" },
107
+ "signature": { "type": "string", "minLength": 1 }
108
+ },
109
+ "additionalProperties": false
110
+ }
111
+ }
18
112
  }
@@ -0,0 +1,346 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://topic-protocol.ixo.world/schemas/decision-to-pay-template.schema.json",
4
+ "title": "IXO Decision-to-Pay Topic Template manifest v1",
5
+ "type": "object",
6
+ "required": [
7
+ "$schema",
8
+ "version",
9
+ "id",
10
+ "templateVersion",
11
+ "label",
12
+ "description",
13
+ "maturity",
14
+ "compatibility",
15
+ "topic",
16
+ "actors",
17
+ "resources",
18
+ "protocolContracts",
19
+ "operations",
20
+ "gates",
21
+ "settlement",
22
+ "privacy",
23
+ "acceptanceCriteria"
24
+ ],
25
+ "properties": {
26
+ "$schema": { "type": "string", "minLength": 1 },
27
+ "version": { "const": 1 },
28
+ "id": { "type": "string", "pattern": "^urn:ixo:decision-to-pay:template:[a-z0-9-]+$" },
29
+ "templateVersion": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
30
+ "label": { "type": "string", "minLength": 1, "maxLength": 120 },
31
+ "description": { "type": "string", "minLength": 1, "maxLength": 1000 },
32
+ "maturity": { "enum": ["draft", "incubating", "candidate", "stable"] },
33
+ "compatibility": { "$ref": "#/$defs/compatibility" },
34
+ "topic": { "$ref": "#/$defs/topic" },
35
+ "topology": { "$ref": "#/$defs/topology" },
36
+ "actors": {
37
+ "type": "array",
38
+ "minItems": 2,
39
+ "items": { "$ref": "#/$defs/actor" }
40
+ },
41
+ "resources": {
42
+ "type": "array",
43
+ "minItems": 1,
44
+ "items": { "$ref": "#/$defs/resource" }
45
+ },
46
+ "protocolContracts": {
47
+ "type": "array",
48
+ "minItems": 1,
49
+ "items": { "$ref": "#/$defs/protocolContract" }
50
+ },
51
+ "operations": {
52
+ "type": "array",
53
+ "minItems": 1,
54
+ "uniqueItems": true,
55
+ "items": { "$ref": "#/$defs/topicOperation" }
56
+ },
57
+ "gates": {
58
+ "type": "array",
59
+ "minItems": 1,
60
+ "items": { "$ref": "#/$defs/gate" }
61
+ },
62
+ "settlement": { "$ref": "#/$defs/settlement" },
63
+ "privacy": { "$ref": "#/$defs/privacy" },
64
+ "acceptanceCriteria": {
65
+ "type": "array",
66
+ "minItems": 1,
67
+ "items": { "$ref": "#/$defs/acceptanceCriterion" }
68
+ },
69
+ "extensions": { "type": "object" }
70
+ },
71
+ "additionalProperties": false,
72
+ "$defs": {
73
+ "digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
74
+ "did": { "type": "string", "pattern": "^did:[a-z0-9]+:.+" },
75
+ "jsonPointer": { "type": "string", "pattern": "^/" },
76
+ "compatibility": {
77
+ "type": "object",
78
+ "required": ["protocolPackage", "protocolVersion", "sourceCommit", "implementationStatus", "requiredExtensions"],
79
+ "properties": {
80
+ "protocolPackage": { "const": "@ixo/topic-protocol" },
81
+ "protocolVersion": { "const": "0.7.0" },
82
+ "sourceCommit": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
83
+ "implementationStatus": {
84
+ "enum": ["draft_contract_extension", "design_ready", "design_ready_extension_required", "implemented"]
85
+ },
86
+ "requiredExtensions": {
87
+ "type": "array",
88
+ "uniqueItems": true,
89
+ "items": { "type": "string", "minLength": 1 }
90
+ },
91
+ "constraints": {
92
+ "type": "array",
93
+ "items": { "type": "string", "minLength": 1 }
94
+ }
95
+ },
96
+ "additionalProperties": false
97
+ },
98
+ "persistedKind": {
99
+ "enum": ["task", "agent_task", "proposal", "evaluation", "claims", "question", "discussion", "incident"]
100
+ },
101
+ "recipe": {
102
+ "enum": ["project", "flow", "proposal", "evaluation", "claims", "research", "discussion", "incident"]
103
+ },
104
+ "kindRef": {
105
+ "oneOf": [
106
+ {
107
+ "type": "object",
108
+ "required": ["source", "kind"],
109
+ "properties": {
110
+ "source": { "const": "standard" },
111
+ "kind": { "$ref": "#/$defs/persistedKind" }
112
+ },
113
+ "additionalProperties": false
114
+ },
115
+ {
116
+ "type": "object",
117
+ "required": ["source", "customId", "label", "baseKind"],
118
+ "properties": {
119
+ "source": { "const": "custom" },
120
+ "customId": { "type": "string", "pattern": "^[a-z][a-z0-9.-]+$" },
121
+ "label": { "type": "string", "minLength": 1, "maxLength": 80 },
122
+ "baseKind": { "$ref": "#/$defs/persistedKind" }
123
+ },
124
+ "additionalProperties": false
125
+ }
126
+ ]
127
+ },
128
+ "kindProfile": {
129
+ "type": "object",
130
+ "required": ["id", "version", "schema", "digest"],
131
+ "properties": {
132
+ "id": { "type": "string", "format": "uri" },
133
+ "version": { "type": "string", "minLength": 1 },
134
+ "schema": { "type": "string", "format": "uri" },
135
+ "digest": { "$ref": "#/$defs/digest" }
136
+ },
137
+ "additionalProperties": false
138
+ },
139
+ "topic": {
140
+ "type": "object",
141
+ "required": ["primaryRole", "kindRef", "recipe", "workingMode", "temporalMode", "acceptance", "lifecyclePolicy"],
142
+ "properties": {
143
+ "primaryRole": { "enum": ["work_case", "delivery_case", "payable_milestone", "payment_claim"] },
144
+ "kindRef": { "$ref": "#/$defs/kindRef" },
145
+ "kindProfile": { "$ref": "#/$defs/kindProfile" },
146
+ "recipe": { "$ref": "#/$defs/recipe" },
147
+ "workingMode": { "enum": ["solo", "team", "client"] },
148
+ "temporalMode": { "enum": ["finite", "ongoing"] },
149
+ "acceptance": {
150
+ "type": "object",
151
+ "required": ["requiredTopicContractPaths", "allowHonestDraft"],
152
+ "properties": {
153
+ "requiredTopicContractPaths": {
154
+ "type": "array",
155
+ "uniqueItems": true,
156
+ "items": { "$ref": "#/$defs/jsonPointer" }
157
+ },
158
+ "allowHonestDraft": { "const": true }
159
+ },
160
+ "additionalProperties": false
161
+ },
162
+ "lifecyclePolicy": {
163
+ "type": "object",
164
+ "required": ["separateTopicContractOutcomeAxes", "resolveRule"],
165
+ "properties": {
166
+ "separateTopicContractOutcomeAxes": { "const": true },
167
+ "resolveRule": { "type": "string", "minLength": 1 },
168
+ "waitingRule": { "type": "string", "minLength": 1 }
169
+ },
170
+ "additionalProperties": false
171
+ }
172
+ },
173
+ "additionalProperties": false
174
+ },
175
+ "topology": {
176
+ "type": "object",
177
+ "required": ["requiresParentTopic", "onePayableUnitPerTopic"],
178
+ "properties": {
179
+ "requiresParentTopic": { "type": "boolean" },
180
+ "parentBaseKind": { "$ref": "#/$defs/persistedKind" },
181
+ "relation": { "enum": ["branches_from", "merged_into", "redirects_to", "references", "produced"] },
182
+ "onePayableUnitPerTopic": { "type": "boolean" }
183
+ },
184
+ "additionalProperties": false
185
+ },
186
+ "actor": {
187
+ "type": "object",
188
+ "required": ["role", "label", "required", "identity", "capabilities"],
189
+ "properties": {
190
+ "role": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
191
+ "label": { "type": "string", "minLength": 1 },
192
+ "required": { "type": "boolean" },
193
+ "identity": { "const": "did" },
194
+ "capabilities": {
195
+ "type": "array",
196
+ "uniqueItems": true,
197
+ "items": { "type": "string", "minLength": 1 }
198
+ },
199
+ "constraints": {
200
+ "type": "array",
201
+ "items": { "type": "string", "minLength": 1 }
202
+ }
203
+ },
204
+ "additionalProperties": false
205
+ },
206
+ "resource": {
207
+ "type": "object",
208
+ "required": ["role", "type", "required", "binding", "authority", "availability", "confidentiality"],
209
+ "properties": {
210
+ "role": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
211
+ "type": { "type": "string", "minLength": 1 },
212
+ "required": { "type": "boolean" },
213
+ "binding": { "enum": ["kind_resource", "typed_context", "vfs_attachment", "protocol_record", "external_reference"] },
214
+ "authority": { "enum": ["topic_contract", "bound_resource", "external_system", "protocol_record"] },
215
+ "availability": { "enum": ["topic_protocol_0.7", "contract_pack", "proposed_extension", "external"] },
216
+ "schemaRef": { "type": "string", "format": "uri-reference" },
217
+ "confidentiality": { "enum": ["room_encrypted", "vfs_ucan", "external_authority", "public"] },
218
+ "notes": { "type": "string", "minLength": 1 }
219
+ },
220
+ "additionalProperties": false
221
+ },
222
+ "protocolContract": {
223
+ "type": "object",
224
+ "required": ["name", "source", "schemaRef"],
225
+ "properties": {
226
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
227
+ "source": { "enum": ["topic_protocol", "contract_pack", "proposed_extension"] },
228
+ "schemaRef": { "type": "string", "format": "uri-reference" },
229
+ "required": { "type": "boolean" }
230
+ },
231
+ "additionalProperties": false
232
+ },
233
+ "topicOperation": {
234
+ "enum": [
235
+ "propose-contract",
236
+ "update-contract",
237
+ "accept-contract",
238
+ "supersede-contract",
239
+ "bind-external-work",
240
+ "sync-external-work",
241
+ "unlink-external-work",
242
+ "submit-delivery",
243
+ "record-delivery-decision",
244
+ "record-evaluation",
245
+ "record-approval",
246
+ "record-claim",
247
+ "record-settlement",
248
+ "record-decision",
249
+ "change-status",
250
+ "redirect",
251
+ "branch",
252
+ "merge",
253
+ "resolve-conflict"
254
+ ]
255
+ },
256
+ "gateCondition": {
257
+ "type": "object",
258
+ "required": ["contract", "path", "operator"],
259
+ "properties": {
260
+ "contract": {
261
+ "enum": [
262
+ "topic-contract-state",
263
+ "payment-terms",
264
+ "payable-obligation",
265
+ "external-work-binding",
266
+ "delivery-packet",
267
+ "delivery-decision",
268
+ "evaluation-assertion",
269
+ "approval-decision",
270
+ "claim-record",
271
+ "settlement-receipt",
272
+ "operator-verification"
273
+ ]
274
+ },
275
+ "path": { "$ref": "#/$defs/jsonPointer" },
276
+ "operator": { "enum": ["exists", "equals", "min_count", "all_equal", "digest_matches"] },
277
+ "value": {}
278
+ },
279
+ "additionalProperties": false
280
+ },
281
+ "gate": {
282
+ "type": "object",
283
+ "required": ["id", "stage", "description", "all", "onFailure"],
284
+ "properties": {
285
+ "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
286
+ "stage": { "enum": ["terms", "delivery", "evaluation", "approval", "claim", "settlement", "exception"] },
287
+ "description": { "type": "string", "minLength": 1 },
288
+ "all": {
289
+ "type": "array",
290
+ "minItems": 1,
291
+ "items": { "$ref": "#/$defs/gateCondition" }
292
+ },
293
+ "onFailure": { "enum": ["block", "human_review", "return_for_changes", "open_incident"] }
294
+ },
295
+ "additionalProperties": false
296
+ },
297
+ "settlement": {
298
+ "type": "object",
299
+ "required": ["movesFunds", "requiresExternalAdapter", "failClosed", "requiredAxes", "exactMatchFields", "terminalState"],
300
+ "properties": {
301
+ "movesFunds": { "const": false },
302
+ "requiresExternalAdapter": { "const": true },
303
+ "failClosed": { "const": true },
304
+ "requiredAxes": {
305
+ "type": "array",
306
+ "minItems": 4,
307
+ "uniqueItems": true,
308
+ "items": { "enum": ["delivery", "evaluation", "approval", "claim", "settlement"] }
309
+ },
310
+ "exactMatchFields": {
311
+ "type": "array",
312
+ "minItems": 3,
313
+ "uniqueItems": true,
314
+ "items": { "enum": ["topicId", "deliveryPacketId", "deliveryPacketDigest", "evaluationIds", "approvalId", "claimId", "amount", "asset", "recipient"] }
315
+ },
316
+ "terminalState": { "const": "confirmed" }
317
+ },
318
+ "additionalProperties": false
319
+ },
320
+ "privacy": {
321
+ "type": "object",
322
+ "required": ["topicIsConfidentialityBoundary", "topicCapabilityGrantsVfsAccess", "sensitiveResourceStorage", "minimumRoomVisibleFields"],
323
+ "properties": {
324
+ "topicIsConfidentialityBoundary": { "const": false },
325
+ "topicCapabilityGrantsVfsAccess": { "const": false },
326
+ "sensitiveResourceStorage": { "const": "encrypted_room_or_ucan_vfs" },
327
+ "minimumRoomVisibleFields": {
328
+ "type": "array",
329
+ "uniqueItems": true,
330
+ "items": { "type": "string", "minLength": 1 }
331
+ }
332
+ },
333
+ "additionalProperties": false
334
+ },
335
+ "acceptanceCriterion": {
336
+ "type": "object",
337
+ "required": ["id", "statement"],
338
+ "properties": {
339
+ "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
340
+ "statement": { "type": "string", "minLength": 1 },
341
+ "verification": { "type": "string", "minLength": 1 }
342
+ },
343
+ "additionalProperties": false
344
+ }
345
+ }
346
+ }