@lssm/lib.contracts 0.0.0-canary-20251220041653 → 0.0.0-canary-20251221114240

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 (65) hide show
  1. package/README.md +4 -4
  2. package/dist/app-config/contracts.d.ts +60 -60
  3. package/dist/app-config/contracts.js +1 -1
  4. package/dist/app-config/events.d.ts +27 -27
  5. package/dist/app-config/lifecycle-contracts.d.ts +90 -90
  6. package/dist/app-config/lifecycle-contracts.js +1 -1
  7. package/dist/docs/tech/contracts/README.docblock.js +2 -2
  8. package/dist/docs/tech/contracts/openapi-export.docblock.js +6 -6
  9. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +2 -2
  10. package/dist/docs/tech/contracts/tests.docblock.js +2 -2
  11. package/dist/experiments/spec-resolver.d.ts +2 -2
  12. package/dist/features.d.ts +5 -5
  13. package/dist/index.d.ts +6 -4
  14. package/dist/index.js +5 -3
  15. package/dist/install.d.ts +16 -16
  16. package/dist/integrations/contracts.d.ts +111 -111
  17. package/dist/integrations/contracts.js +1 -1
  18. package/dist/integrations/openbanking/contracts/accounts.d.ts +73 -73
  19. package/dist/integrations/openbanking/contracts/accounts.js +1 -1
  20. package/dist/integrations/openbanking/contracts/balances.d.ts +40 -40
  21. package/dist/integrations/openbanking/contracts/balances.js +1 -1
  22. package/dist/integrations/openbanking/contracts/index.d.ts +2 -2
  23. package/dist/integrations/openbanking/contracts/transactions.d.ts +54 -54
  24. package/dist/integrations/openbanking/contracts/transactions.js +1 -1
  25. package/dist/integrations/openbanking/models.d.ts +55 -55
  26. package/dist/jsonschema.d.ts +5 -5
  27. package/dist/knowledge/contracts.d.ts +75 -75
  28. package/dist/knowledge/contracts.js +1 -1
  29. package/dist/llm/exporters.d.ts +8 -8
  30. package/dist/llm/exporters.js +1 -1
  31. package/dist/llm/prompts.d.ts +7 -7
  32. package/dist/llm/types.d.ts +3 -3
  33. package/dist/markdown.d.ts +3 -3
  34. package/dist/markdown.js +1 -1
  35. package/dist/onboarding-base.d.ts +32 -32
  36. package/dist/onboarding-base.js +1 -1
  37. package/dist/openapi.d.ts +2 -2
  38. package/dist/{spec.d.ts → operation.d.ts} +12 -12
  39. package/dist/{spec.js → operation.js} +1 -1
  40. package/dist/policy/docs/policy.docblock.js +1 -1
  41. package/dist/presentations.d.ts +3 -3
  42. package/dist/registry.d.ts +13 -14
  43. package/dist/registry.js +5 -5
  44. package/dist/server/graphql-pothos.d.ts +6 -6
  45. package/dist/server/graphql-pothos.js +4 -4
  46. package/dist/server/mcp/createMcpServer.d.ts +3 -3
  47. package/dist/server/mcp/createMcpServer.js +1 -1
  48. package/dist/server/mcp/registerTools.d.ts +2 -2
  49. package/dist/server/rest-elysia.d.ts +2 -2
  50. package/dist/server/rest-express.d.ts +2 -2
  51. package/dist/server/rest-generic.d.ts +3 -3
  52. package/dist/server/rest-generic.js +1 -1
  53. package/dist/server/rest-next-app.d.ts +4 -4
  54. package/dist/server/rest-next-app.js +2 -2
  55. package/dist/server/rest-next-mcp.d.ts +2 -2
  56. package/dist/server/rest-next-pages.d.ts +2 -2
  57. package/dist/telemetry/docs/telemetry.docblock.js +1 -1
  58. package/dist/tests/runner.d.ts +2 -2
  59. package/dist/types/all.d.ts +2 -2
  60. package/dist/workflow/validation.d.ts +2 -2
  61. package/dist/workspace-config/contractsrc-schema.d.ts +188 -0
  62. package/dist/workspace-config/contractsrc-schema.js +114 -0
  63. package/dist/workspace-config/index.d.ts +2 -0
  64. package/dist/workspace-config/index.js +3 -0
  65. package/package.json +13 -11
@@ -1,308 +1,308 @@
1
1
  import { EventSpec } from "../events.js";
2
- import { ContractSpec } from "../spec.js";
3
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpec } from "../operation.js";
3
+ import { OperationSpecRegistry } from "../registry.js";
4
4
  import "../index.js";
5
- import * as _lssm_lib_schema172 from "@lssm/lib.schema";
5
+ import * as _lssm_lib_schema317 from "@lssm/lib.schema";
6
6
  import { SchemaModel } from "@lssm/lib.schema";
7
7
 
8
8
  //#region src/app-config/lifecycle-contracts.d.ts
9
- declare const CreateTenantConfigDraftCommand: ContractSpec<SchemaModel<{
9
+ declare const CreateTenantConfigDraftCommand: OperationSpec<SchemaModel<{
10
10
  tenantId: {
11
- type: _lssm_lib_schema172.FieldType<string, string>;
11
+ type: _lssm_lib_schema317.FieldType<string, string>;
12
12
  isOptional: false;
13
13
  };
14
14
  appId: {
15
- type: _lssm_lib_schema172.FieldType<string, string>;
15
+ type: _lssm_lib_schema317.FieldType<string, string>;
16
16
  isOptional: false;
17
17
  };
18
18
  blueprintName: {
19
- type: _lssm_lib_schema172.FieldType<string, string>;
19
+ type: _lssm_lib_schema317.FieldType<string, string>;
20
20
  isOptional: false;
21
21
  };
22
22
  blueprintVersion: {
23
- type: _lssm_lib_schema172.FieldType<number, number>;
23
+ type: _lssm_lib_schema317.FieldType<number, number>;
24
24
  isOptional: false;
25
25
  };
26
26
  environment: {
27
- type: _lssm_lib_schema172.FieldType<string, string>;
27
+ type: _lssm_lib_schema317.FieldType<string, string>;
28
28
  isOptional: true;
29
29
  };
30
30
  fromVersion: {
31
- type: _lssm_lib_schema172.FieldType<number, number>;
31
+ type: _lssm_lib_schema317.FieldType<number, number>;
32
32
  isOptional: true;
33
33
  };
34
34
  createdBy: {
35
- type: _lssm_lib_schema172.FieldType<string, string>;
35
+ type: _lssm_lib_schema317.FieldType<string, string>;
36
36
  isOptional: false;
37
37
  };
38
38
  }>, SchemaModel<{
39
39
  version: {
40
- type: _lssm_lib_schema172.FieldType<number, number>;
40
+ type: _lssm_lib_schema317.FieldType<number, number>;
41
41
  isOptional: false;
42
42
  };
43
43
  status: {
44
- type: _lssm_lib_schema172.FieldType<string, string>;
44
+ type: _lssm_lib_schema317.FieldType<string, string>;
45
45
  isOptional: false;
46
46
  };
47
47
  createdAt: {
48
- type: _lssm_lib_schema172.FieldType<Date, string>;
48
+ type: _lssm_lib_schema317.FieldType<Date, string>;
49
49
  isOptional: false;
50
50
  };
51
51
  }>, {
52
52
  ref: EventSpec<SchemaModel<{
53
53
  tenantId: {
54
- type: _lssm_lib_schema172.FieldType<string, string>;
54
+ type: _lssm_lib_schema317.FieldType<string, string>;
55
55
  isOptional: false;
56
56
  };
57
57
  appId: {
58
- type: _lssm_lib_schema172.FieldType<string, string>;
58
+ type: _lssm_lib_schema317.FieldType<string, string>;
59
59
  isOptional: false;
60
60
  };
61
61
  version: {
62
- type: _lssm_lib_schema172.FieldType<number, number>;
62
+ type: _lssm_lib_schema317.FieldType<number, number>;
63
63
  isOptional: false;
64
64
  };
65
65
  blueprintName: {
66
- type: _lssm_lib_schema172.FieldType<string, string>;
66
+ type: _lssm_lib_schema317.FieldType<string, string>;
67
67
  isOptional: false;
68
68
  };
69
69
  blueprintVersion: {
70
- type: _lssm_lib_schema172.FieldType<number, number>;
70
+ type: _lssm_lib_schema317.FieldType<number, number>;
71
71
  isOptional: false;
72
72
  };
73
73
  createdBy: {
74
- type: _lssm_lib_schema172.FieldType<string, string>;
74
+ type: _lssm_lib_schema317.FieldType<string, string>;
75
75
  isOptional: false;
76
76
  };
77
77
  clonedFrom: {
78
- type: _lssm_lib_schema172.FieldType<number, number>;
78
+ type: _lssm_lib_schema317.FieldType<number, number>;
79
79
  isOptional: true;
80
80
  };
81
81
  }>>;
82
82
  when: string;
83
83
  }[]>;
84
- declare const PromoteTenantConfigToPreviewCommand: ContractSpec<SchemaModel<{
84
+ declare const PromoteTenantConfigToPreviewCommand: OperationSpec<SchemaModel<{
85
85
  tenantId: {
86
- type: _lssm_lib_schema172.FieldType<string, string>;
86
+ type: _lssm_lib_schema317.FieldType<string, string>;
87
87
  isOptional: false;
88
88
  };
89
89
  appId: {
90
- type: _lssm_lib_schema172.FieldType<string, string>;
90
+ type: _lssm_lib_schema317.FieldType<string, string>;
91
91
  isOptional: false;
92
92
  };
93
93
  version: {
94
- type: _lssm_lib_schema172.FieldType<number, number>;
94
+ type: _lssm_lib_schema317.FieldType<number, number>;
95
95
  isOptional: false;
96
96
  };
97
97
  promotedBy: {
98
- type: _lssm_lib_schema172.FieldType<string, string>;
98
+ type: _lssm_lib_schema317.FieldType<string, string>;
99
99
  isOptional: false;
100
100
  };
101
101
  }>, SchemaModel<{
102
102
  version: {
103
- type: _lssm_lib_schema172.FieldType<number, number>;
103
+ type: _lssm_lib_schema317.FieldType<number, number>;
104
104
  isOptional: false;
105
105
  };
106
106
  status: {
107
- type: _lssm_lib_schema172.FieldType<string, string>;
107
+ type: _lssm_lib_schema317.FieldType<string, string>;
108
108
  isOptional: false;
109
109
  };
110
110
  warnings: {
111
- type: _lssm_lib_schema172.FieldType<string, string>;
111
+ type: _lssm_lib_schema317.FieldType<string, string>;
112
112
  isOptional: true;
113
113
  isArray: true;
114
114
  };
115
115
  }>, {
116
116
  ref: EventSpec<SchemaModel<{
117
117
  tenantId: {
118
- type: _lssm_lib_schema172.FieldType<string, string>;
118
+ type: _lssm_lib_schema317.FieldType<string, string>;
119
119
  isOptional: false;
120
120
  };
121
121
  appId: {
122
- type: _lssm_lib_schema172.FieldType<string, string>;
122
+ type: _lssm_lib_schema317.FieldType<string, string>;
123
123
  isOptional: false;
124
124
  };
125
125
  version: {
126
- type: _lssm_lib_schema172.FieldType<number, number>;
126
+ type: _lssm_lib_schema317.FieldType<number, number>;
127
127
  isOptional: false;
128
128
  };
129
129
  promotedBy: {
130
- type: _lssm_lib_schema172.FieldType<string, string>;
130
+ type: _lssm_lib_schema317.FieldType<string, string>;
131
131
  isOptional: false;
132
132
  };
133
133
  warnings: {
134
- type: _lssm_lib_schema172.FieldType<string, string>;
134
+ type: _lssm_lib_schema317.FieldType<string, string>;
135
135
  isOptional: true;
136
136
  isArray: true;
137
137
  };
138
138
  }>>;
139
139
  when: string;
140
140
  }[]>;
141
- declare const PublishTenantConfigCommand: ContractSpec<SchemaModel<{
141
+ declare const PublishTenantConfigCommand: OperationSpec<SchemaModel<{
142
142
  tenantId: {
143
- type: _lssm_lib_schema172.FieldType<string, string>;
143
+ type: _lssm_lib_schema317.FieldType<string, string>;
144
144
  isOptional: false;
145
145
  };
146
146
  appId: {
147
- type: _lssm_lib_schema172.FieldType<string, string>;
147
+ type: _lssm_lib_schema317.FieldType<string, string>;
148
148
  isOptional: false;
149
149
  };
150
150
  version: {
151
- type: _lssm_lib_schema172.FieldType<number, number>;
151
+ type: _lssm_lib_schema317.FieldType<number, number>;
152
152
  isOptional: false;
153
153
  };
154
154
  environment: {
155
- type: _lssm_lib_schema172.FieldType<string, string>;
155
+ type: _lssm_lib_schema317.FieldType<string, string>;
156
156
  isOptional: true;
157
157
  };
158
158
  publishedBy: {
159
- type: _lssm_lib_schema172.FieldType<string, string>;
159
+ type: _lssm_lib_schema317.FieldType<string, string>;
160
160
  isOptional: false;
161
161
  };
162
162
  changeSummary: {
163
- type: _lssm_lib_schema172.FieldType<string, string>;
163
+ type: _lssm_lib_schema317.FieldType<string, string>;
164
164
  isOptional: true;
165
165
  };
166
166
  }>, SchemaModel<{
167
167
  version: {
168
- type: _lssm_lib_schema172.FieldType<number, number>;
168
+ type: _lssm_lib_schema317.FieldType<number, number>;
169
169
  isOptional: false;
170
170
  };
171
171
  status: {
172
- type: _lssm_lib_schema172.FieldType<string, string>;
172
+ type: _lssm_lib_schema317.FieldType<string, string>;
173
173
  isOptional: false;
174
174
  };
175
175
  previousVersion: {
176
- type: _lssm_lib_schema172.FieldType<number, number>;
176
+ type: _lssm_lib_schema317.FieldType<number, number>;
177
177
  isOptional: true;
178
178
  };
179
179
  publishedAt: {
180
- type: _lssm_lib_schema172.FieldType<Date, string>;
180
+ type: _lssm_lib_schema317.FieldType<Date, string>;
181
181
  isOptional: false;
182
182
  };
183
183
  }>, {
184
184
  ref: EventSpec<SchemaModel<{
185
185
  tenantId: {
186
- type: _lssm_lib_schema172.FieldType<string, string>;
186
+ type: _lssm_lib_schema317.FieldType<string, string>;
187
187
  isOptional: false;
188
188
  };
189
189
  appId: {
190
- type: _lssm_lib_schema172.FieldType<string, string>;
190
+ type: _lssm_lib_schema317.FieldType<string, string>;
191
191
  isOptional: false;
192
192
  };
193
193
  version: {
194
- type: _lssm_lib_schema172.FieldType<number, number>;
194
+ type: _lssm_lib_schema317.FieldType<number, number>;
195
195
  isOptional: false;
196
196
  };
197
197
  previousVersion: {
198
- type: _lssm_lib_schema172.FieldType<number, number>;
198
+ type: _lssm_lib_schema317.FieldType<number, number>;
199
199
  isOptional: true;
200
200
  };
201
201
  publishedBy: {
202
- type: _lssm_lib_schema172.FieldType<string, string>;
202
+ type: _lssm_lib_schema317.FieldType<string, string>;
203
203
  isOptional: false;
204
204
  };
205
205
  changeSummary: {
206
- type: _lssm_lib_schema172.FieldType<string, string>;
206
+ type: _lssm_lib_schema317.FieldType<string, string>;
207
207
  isOptional: true;
208
208
  };
209
209
  changedSections: {
210
- type: _lssm_lib_schema172.FieldType<string, string>;
210
+ type: _lssm_lib_schema317.FieldType<string, string>;
211
211
  isOptional: true;
212
212
  isArray: true;
213
213
  };
214
214
  }>>;
215
215
  when: string;
216
216
  }[]>;
217
- declare const RollbackTenantConfigCommand: ContractSpec<SchemaModel<{
217
+ declare const RollbackTenantConfigCommand: OperationSpec<SchemaModel<{
218
218
  tenantId: {
219
- type: _lssm_lib_schema172.FieldType<string, string>;
219
+ type: _lssm_lib_schema317.FieldType<string, string>;
220
220
  isOptional: false;
221
221
  };
222
222
  appId: {
223
- type: _lssm_lib_schema172.FieldType<string, string>;
223
+ type: _lssm_lib_schema317.FieldType<string, string>;
224
224
  isOptional: false;
225
225
  };
226
226
  toVersion: {
227
- type: _lssm_lib_schema172.FieldType<number, number>;
227
+ type: _lssm_lib_schema317.FieldType<number, number>;
228
228
  isOptional: false;
229
229
  };
230
230
  environment: {
231
- type: _lssm_lib_schema172.FieldType<string, string>;
231
+ type: _lssm_lib_schema317.FieldType<string, string>;
232
232
  isOptional: true;
233
233
  };
234
234
  rolledBackBy: {
235
- type: _lssm_lib_schema172.FieldType<string, string>;
235
+ type: _lssm_lib_schema317.FieldType<string, string>;
236
236
  isOptional: false;
237
237
  };
238
238
  reason: {
239
- type: _lssm_lib_schema172.FieldType<string, string>;
239
+ type: _lssm_lib_schema317.FieldType<string, string>;
240
240
  isOptional: false;
241
241
  };
242
242
  }>, SchemaModel<{
243
243
  newVersion: {
244
- type: _lssm_lib_schema172.FieldType<number, number>;
244
+ type: _lssm_lib_schema317.FieldType<number, number>;
245
245
  isOptional: false;
246
246
  };
247
247
  status: {
248
- type: _lssm_lib_schema172.FieldType<string, string>;
248
+ type: _lssm_lib_schema317.FieldType<string, string>;
249
249
  isOptional: false;
250
250
  };
251
251
  rolledBackFrom: {
252
- type: _lssm_lib_schema172.FieldType<number, number>;
252
+ type: _lssm_lib_schema317.FieldType<number, number>;
253
253
  isOptional: false;
254
254
  };
255
255
  }>, {
256
256
  ref: EventSpec<SchemaModel<{
257
257
  tenantId: {
258
- type: _lssm_lib_schema172.FieldType<string, string>;
258
+ type: _lssm_lib_schema317.FieldType<string, string>;
259
259
  isOptional: false;
260
260
  };
261
261
  appId: {
262
- type: _lssm_lib_schema172.FieldType<string, string>;
262
+ type: _lssm_lib_schema317.FieldType<string, string>;
263
263
  isOptional: false;
264
264
  };
265
265
  newVersion: {
266
- type: _lssm_lib_schema172.FieldType<number, number>;
266
+ type: _lssm_lib_schema317.FieldType<number, number>;
267
267
  isOptional: false;
268
268
  };
269
269
  rolledBackFrom: {
270
- type: _lssm_lib_schema172.FieldType<number, number>;
270
+ type: _lssm_lib_schema317.FieldType<number, number>;
271
271
  isOptional: false;
272
272
  };
273
273
  rolledBackTo: {
274
- type: _lssm_lib_schema172.FieldType<number, number>;
274
+ type: _lssm_lib_schema317.FieldType<number, number>;
275
275
  isOptional: false;
276
276
  };
277
277
  rolledBackBy: {
278
- type: _lssm_lib_schema172.FieldType<string, string>;
278
+ type: _lssm_lib_schema317.FieldType<string, string>;
279
279
  isOptional: false;
280
280
  };
281
281
  reason: {
282
- type: _lssm_lib_schema172.FieldType<string, string>;
282
+ type: _lssm_lib_schema317.FieldType<string, string>;
283
283
  isOptional: false;
284
284
  };
285
285
  }>>;
286
286
  when: string;
287
287
  }[]>;
288
- declare const ListTenantConfigVersionsQuery: ContractSpec<SchemaModel<{
288
+ declare const ListTenantConfigVersionsQuery: OperationSpec<SchemaModel<{
289
289
  tenantId: {
290
- type: _lssm_lib_schema172.FieldType<string, string>;
290
+ type: _lssm_lib_schema317.FieldType<string, string>;
291
291
  isOptional: false;
292
292
  };
293
293
  appId: {
294
- type: _lssm_lib_schema172.FieldType<string, string>;
294
+ type: _lssm_lib_schema317.FieldType<string, string>;
295
295
  isOptional: false;
296
296
  };
297
297
  }>, SchemaModel<{
298
298
  versions: {
299
299
  type: SchemaModel<{
300
300
  meta: {
301
- type: _lssm_lib_schema172.FieldType<Record<string, unknown>, Record<string, unknown>>;
301
+ type: _lssm_lib_schema317.FieldType<Record<string, unknown>, Record<string, unknown>>;
302
302
  isOptional: false;
303
303
  };
304
304
  config: {
305
- type: _lssm_lib_schema172.FieldType<Record<string, unknown>, Record<string, unknown>>;
305
+ type: _lssm_lib_schema317.FieldType<Record<string, unknown>, Record<string, unknown>>;
306
306
  isOptional: false;
307
307
  };
308
308
  }>;
@@ -312,35 +312,35 @@ declare const ListTenantConfigVersionsQuery: ContractSpec<SchemaModel<{
312
312
  transitions: {
313
313
  type: SchemaModel<{
314
314
  tenantId: {
315
- type: _lssm_lib_schema172.FieldType<string, string>;
315
+ type: _lssm_lib_schema317.FieldType<string, string>;
316
316
  isOptional: false;
317
317
  };
318
318
  appId: {
319
- type: _lssm_lib_schema172.FieldType<string, string>;
319
+ type: _lssm_lib_schema317.FieldType<string, string>;
320
320
  isOptional: false;
321
321
  };
322
322
  fromStatus: {
323
- type: _lssm_lib_schema172.FieldType<string, string>;
323
+ type: _lssm_lib_schema317.FieldType<string, string>;
324
324
  isOptional: false;
325
325
  };
326
326
  toStatus: {
327
- type: _lssm_lib_schema172.FieldType<string, string>;
327
+ type: _lssm_lib_schema317.FieldType<string, string>;
328
328
  isOptional: false;
329
329
  };
330
330
  version: {
331
- type: _lssm_lib_schema172.FieldType<number, number>;
331
+ type: _lssm_lib_schema317.FieldType<number, number>;
332
332
  isOptional: false;
333
333
  };
334
334
  timestamp: {
335
- type: _lssm_lib_schema172.FieldType<Date, string>;
335
+ type: _lssm_lib_schema317.FieldType<Date, string>;
336
336
  isOptional: false;
337
337
  };
338
338
  actor: {
339
- type: _lssm_lib_schema172.FieldType<string, string>;
339
+ type: _lssm_lib_schema317.FieldType<string, string>;
340
340
  isOptional: false;
341
341
  };
342
342
  reason: {
343
- type: _lssm_lib_schema172.FieldType<string, string>;
343
+ type: _lssm_lib_schema317.FieldType<string, string>;
344
344
  isOptional: true;
345
345
  };
346
346
  }>;
@@ -348,35 +348,35 @@ declare const ListTenantConfigVersionsQuery: ContractSpec<SchemaModel<{
348
348
  isArray: true;
349
349
  };
350
350
  }>, undefined>;
351
- declare const GetTenantConfigVersionQuery: ContractSpec<SchemaModel<{
351
+ declare const GetTenantConfigVersionQuery: OperationSpec<SchemaModel<{
352
352
  tenantId: {
353
- type: _lssm_lib_schema172.FieldType<string, string>;
353
+ type: _lssm_lib_schema317.FieldType<string, string>;
354
354
  isOptional: false;
355
355
  };
356
356
  appId: {
357
- type: _lssm_lib_schema172.FieldType<string, string>;
357
+ type: _lssm_lib_schema317.FieldType<string, string>;
358
358
  isOptional: false;
359
359
  };
360
360
  version: {
361
- type: _lssm_lib_schema172.FieldType<number, number>;
361
+ type: _lssm_lib_schema317.FieldType<number, number>;
362
362
  isOptional: false;
363
363
  };
364
364
  }>, SchemaModel<{
365
365
  version: {
366
366
  type: SchemaModel<{
367
367
  meta: {
368
- type: _lssm_lib_schema172.FieldType<Record<string, unknown>, Record<string, unknown>>;
368
+ type: _lssm_lib_schema317.FieldType<Record<string, unknown>, Record<string, unknown>>;
369
369
  isOptional: false;
370
370
  };
371
371
  config: {
372
- type: _lssm_lib_schema172.FieldType<Record<string, unknown>, Record<string, unknown>>;
372
+ type: _lssm_lib_schema317.FieldType<Record<string, unknown>, Record<string, unknown>>;
373
373
  isOptional: false;
374
374
  };
375
375
  }>;
376
376
  isOptional: false;
377
377
  };
378
378
  }>, undefined>;
379
- declare const lifecycleContracts: Record<string, ContractSpec<any, any>>;
380
- declare function registerAppConfigLifecycleContracts(registry: SpecRegistry): SpecRegistry;
379
+ declare const lifecycleContracts: Record<string, OperationSpec<any, any>>;
380
+ declare function registerAppConfigLifecycleContracts(registry: OperationSpecRegistry): OperationSpecRegistry;
381
381
  //#endregion
382
382
  export { CreateTenantConfigDraftCommand, GetTenantConfigVersionQuery, ListTenantConfigVersionsQuery, PromoteTenantConfigToPreviewCommand, PublishTenantConfigCommand, RollbackTenantConfigCommand, lifecycleContracts, registerAppConfigLifecycleContracts };
@@ -1,5 +1,5 @@
1
1
  import { E5, x8 } from "../schema/dist/index.js";
2
- import { defineCommand, defineQuery } from "../spec.js";
2
+ import { defineCommand, defineQuery } from "../operation.js";
3
3
  import { OwnersEnum, StabilityEnum, TagsEnum } from "../ownership.js";
4
4
  import { ConfigDraftCreatedEvent, ConfigPromotedToPreviewEvent, ConfigPublishedEvent, ConfigRolledBackEvent } from "./events.js";
5
5
 
@@ -4,7 +4,7 @@ import { registerDocBlocks } from "../../registry.js";
4
4
  const tech_contracts_README_DocBlocks = [{
5
5
  id: "docs.tech.contracts.README",
6
6
  title: "Contracts: Specs, Registry, Handlers, Adapters",
7
- summary: "- `packages/lssm/libs/contracts` defines the contracts core (SpecRegistry, ContractSpec, install helpers, REST/MCP adapters).",
7
+ summary: "- `packages/lssm/libs/contracts` defines the contracts core (OperationSpecRegistry, OperationSpec, PresentationSpec, install helpers, REST/MCP adapters, ...).",
8
8
  kind: "reference",
9
9
  visibility: "public",
10
10
  route: "/docs/tech/contracts/README",
@@ -13,7 +13,7 @@ const tech_contracts_README_DocBlocks = [{
13
13
  "contracts",
14
14
  "README"
15
15
  ],
16
- body: "## Contracts: Specs, Registry, Handlers, Adapters\n\n### What lives where\n\n- `packages/lssm/libs/contracts` defines the contracts core (SpecRegistry, ContractSpec, install helpers, REST/MCP adapters).\n- `packages/lssm/libs/schema` defines the schema dictionary (`SchemaModel`, `FieldType`) used to describe I/O once and map to multiple targets (zod, GraphQL, JSON Schema).\n- App adapters (e.g. GraphQL) live close to the app. Example: `packages/hcircle/apps/api-coliving/src/graphql/contracts-adapter.ts`.\n\n### npm distribution\n\n- `@lssm/lib.contracts` (root) keeps the legacy \\\"everything\\\" surface for backward compatibility.\n- `@lssm/lib.contracts/client` exposes only browser-safe helpers (React renderers, client SDK, drivers). Import from this entry when bundling for the web or React Native to avoid dragging server adapters.\n- `@lssm/lib.contracts/server` covers HTTP/MCP adapters, registries, integrations, and other Node-only helpers.\n- `@lssm/lib.contracts/types` exports the runtime handler context utilities, while `@lssm/lib.contracts/types/all` re-exports every type alias/interface across the package via `export type` so consumers can import a single module for typings without shipping runtime code.\n- `@lssm/lib.schema`, `@lssm/lib.design-system`, `@lssm/lib.ui-kit`, `@lssm/lib.ui-kit-web`, `@lssm/lib.accessibility`, and the presentation runtime packages are published to npm alongside contracts; prefer the scoped packages to keep tree-shaking intact.\n- Bundlers with conditional exports should resolve subpaths first; keep root imports for server-only code paths.\n\n### Core concepts\n\n- **ContractSpec**: immutable description of an operation.\n - `meta`: `{ name, version, kind: 'query' | 'command' }`\n - `io`: `{ input: SchemaModel | zod schema, output: SchemaModel | zod schema }`\n - `policy`: `{ auth?: {...}, rateLimit?: {...}, flags?: string[] }`\n - `transport.gql.field?`: explicit GraphQL field name (otherwise derived via `defaultGqlField`).\n- **SpecRegistry**: registry of specs + handlers. Use `installOp(reg, spec, handler)` to attach a handler.\n- **Handler**: `(ctx, input) => Promise<output>` implementing the operation.\n- **CapabilitySpec**: canonical capability declaration stored in `src/capabilities.ts`. Tracks `meta` (`{ key, version, kind, title, description, domain, owners, tags, stability }`), `provides` surfaces (`operation`, `event`, `workflow`, `presentation`, `resource`), and `requires` which other capabilities must be present. Enforced during `installFeature`.\n- **PolicySpec**: declarative policy rules (`src/policy/spec.ts`) covering ABAC/ReBAC, consent + rate limit requirements, field-level controls, and PII guidance. `PolicyEngine` evaluates refs, while `OPAPolicyAdapter` lets OPA override/augment runtime decisions.\n- **TelemetrySpec**: analytics definitions (`src/telemetry/spec.ts`) describing event semantics, privacy level, retention, sampling, and anomaly detection. `TelemetryTracker` handles redaction/sampling, `TelemetryAnomalyMonitor` raises alerts, and specs integrate with contracts/workflows via `ctx.telemetry`.\n- **TestSpec**: declarative scenario definitions in `src/tests/spec.ts`. `TestRunner` executes fixtures/actions/assertions against a `SpecRegistry`, and the CLI (`contractspec test`) wraps the runner for automation.\n- **ExperimentSpec**: experiment definitions (`src/experiments/spec.ts`) describing variants, allocation strategies, and success metrics. `ExperimentEvaluator` assigns variants (random/sticky/targeted) and integrates with Policy/Telemetry for safe experimentation.\n- **AppBlueprintSpec / TenantAppConfig**: global blueprints and per-tenant overrides (`src/app-config/spec.ts`). `resolveAppConfig()` merges the two into a `ResolvedAppConfig`, while `composeAppConfig()` hydrates the merged view against registries and reports missing references for safe rollout.\n- **RegeneratorService**: background daemon (`src/regenerator/service.ts`) that consumes telemetry/error/behavior signals, evaluates regeneration rules, and produces `SpecChangeProposal`s for Studio review.\n- **DataViewSpec**: declarative data presentation layer in `src/data-views.ts`. Describes entity projections (`fields`, `filters`, `actions`) with `view.kind` (`list`, `table`, `detail`, `grid`), ties to query operations via `source.primary`, and exposes optional presentation-based empty/error states.\n- **ThemeSpec**: design token + component variant definitions in `src/themes.ts`. Supports inheritance (`extends`), tenant/user overrides, and component-specific variant metadata for the design system.\n- **MigrationSpec**: schema/data migration descriptors (`src/migrations.ts`) with ordered step plans, dependency tracking, and pre/post checks to support automated database/content migrations.\n- **WorkflowSpec**: typed definition of multi-step workflows living in `src/workflow/spec.ts`. `WorkflowRegistry` stores versioned specs, and `validateWorkflowSpec()` (in `src/workflow/validation.ts`) checks graph integrity, step references, and reachability.\n\n### Lifecycle\n\n1. Define the spec (I/O via `SchemaModel` or zod) in a vertical lib (e.g. `contracts-coliving`).\n2. Register it: `installOp(registry, spec, handler)` within the app/service.\n3. Expose it via an adapter (REST, GraphQL, MCP). Each adapter maps the I/O to its transport and enforces policy.\n4. Validate at runtime: parse `input` before executing, parse `output` before returning.\n\n### Adapters\n\n- **REST**: see `packages/lssm/libs/contracts/src/server/rest-*`. Binds routes, validates request/response, maps errors/policies.\n- **MCP**: see `packages/lssm/libs/contracts/src/server/provider-mcp.ts` (standalone MCP server) and `packages/lssm/libs/contracts/src/server/rest-next-mcp.ts` (MCP over Next.js route). Provides tools/resources/prompts.\n - Tools + resources are registered from Zod schemas.\n - Resource templates are keyed by full `ResourceMeta.uriTemplate` (e.g. `docs://list`, `docs://doc/{id}`), so multiple templates can share a scheme (`docs://*`) without collisions.\n- **GraphQL (Pothos)**: see `packages/lssm/libs/contracts/src/server/graphql-pothos.ts`. Adds Query/Mutation fields by transforming contract I/O to GraphQL types.\n\n### GraphQL adapter behaviour (summary)\n\n- Field naming: `spec.transport.gql.field` or `<name_with_dots>_v<version>`.\n- Input/Output types from `SchemaModel` (preferred) or fallback zod introspection.\n- Scalars: String/Int/Float/Boolean/Date/JSON; Objects/Arrays/Enums; unions for outputs; input unions => JSON.\n- Policy: auth gate checks GraphQL context; optional feature flag gating.\n- Complexity & tracing: attaches hints and records timings; log includes `{ specName, version }`.\n\n#### Returns mapping and hydration\n\n- `spec.transport.gql.returns` can declare the GraphQL return wrapper: e.g. `\"Spot\"` or `[Spot]`. If omitted, the adapter infers from `io.output` (SchemaModel) or `resourceRef.graphQLType`.\n- Resource outputs: when `io.output` is a `resourceRef(...)` or `transport.gql.resource` is set, the adapter will optionally hydrate via a `ResourceRegistry` using `contracts-adapter-hydration.ts`:\n - Grammar is parsed with `parseReturns()`.\n - Entities are resolved via `hydrateResourceIfNeeded(resources, result, { template, varName, returns })` after handler execution.\n\n### Resource outputs\n\n- Declare resource outputs using `resourceRef(uriTemplate, opts)`.\n- `opts.varName` (default `id`) selects the identifier field returned by the handler for URI substitution.\n- `opts.graphQLType` is the GraphQL return type name (e.g., `Spot`) or list form (e.g., `[Spot]`).\n- `opts.many: true` indicates the handler returns an array of resources. The handler type becomes an array of items that include the identifier field.\n\nExample:\n\n```ts\nio: {\n input: ListThingsInput,\n output: resourceRef('myapp://thing/{id}', { graphQLType: '[Thing]', many: true }),\n}\n```\n\nHandler return (simplified): `{ id: string | number }[]`.\n\n### Errors\n\n- Validation errors → transport 400/GraphQL UserInputError.\n- Policy/auth errors → 401/403 or GraphQL ForbiddenError.\n- Handler errors → mapped to transport error with safe message.\n\n### Versioning & naming\n\n- Keep `meta.version` monotonic. Clients should pin to a versioned field/key.\n- Avoid renaming existing fields; add new fields with new versions.\n\n### Ownership metadata (OwnerShipMeta)\n\nAll contracts, events, features, and presentations reference a shared ownership schema (source of truth in `packages/lssm/libs/contracts/src/ownership.ts`).\n\n- Required fields: `title`, `description`, `domain`, `owners[]`, `tags[]`, `stability`.\n- Curated enums: the library exports suggested constants for owners and tags; free-form strings are still allowed for forward-compatibility.\n- Operations (`spec.ts`): `meta` requires `stability`, `owners`, and `tags` alongside `name`, `version`, `kind`, `description`, `goal`, and `context`.\n- Presentations V2: `meta` is a partial of ownership plus `description`.\n- Events: may specify `ownership` (recommended) for discoverability and docs.\n\n### Quick start\n\n```ts\n// app bootstrap\nconst reg = new SpecRegistry();\ninstallOp(reg, BeginSignupSpec, beginSignupHandler);\nregisterContractsOnBuilder(gqlSchemaBuilder, reg); // GraphQL\n// or: createRestRouter(reg) // REST\n```\n"
16
+ body: "## Contracts: Specs, Registry, Handlers, Adapters\n\n### What lives where\n\n- `packages/lssm/libs/contracts` defines the contracts core (OperationSpecRegistry, OperationSpec, PresentationSpec, install helpers, REST/MCP adapters).\n- `packages/lssm/libs/schema` defines the schema dictionary (`SchemaModel`, `FieldType`) used to describe I/O once and map to multiple targets (zod, GraphQL, JSON Schema).\n- App adapters (e.g. GraphQL) live close to the app. Example: `packages/hcircle/apps/api-coliving/src/graphql/contracts-adapter.ts`.\n\n### npm distribution\n\n- `@lssm/lib.contracts` (root) keeps the legacy \\\"everything\\\" surface for backward compatibility.\n- `@lssm/lib.contracts/client` exposes only browser-safe helpers (React renderers, client SDK, drivers). Import from this entry when bundling for the web or React Native to avoid dragging server adapters.\n- `@lssm/lib.contracts/server` covers HTTP/MCP adapters, registries, integrations, and other Node-only helpers.\n- `@lssm/lib.contracts/types` exports the runtime handler context utilities, while `@lssm/lib.contracts/types/all` re-exports every type alias/interface across the package via `export type` so consumers can import a single module for typings without shipping runtime code.\n- `@lssm/lib.schema`, `@lssm/lib.design-system`, `@lssm/lib.ui-kit`, `@lssm/lib.ui-kit-web`, `@lssm/lib.accessibility`, and the presentation runtime packages are published to npm alongside contracts; prefer the scoped packages to keep tree-shaking intact.\n- Bundlers with conditional exports should resolve subpaths first; keep root imports for server-only code paths.\n\n### Core concepts\n\n- **OperationSpec**: immutable description of an operation.\n - `meta`: `{ name, version, kind: 'query' | 'command' }`\n - `io`: `{ input: SchemaModel | zod schema, output: SchemaModel | zod schema }`\n - `policy`: `{ auth?: {...}, rateLimit?: {...}, flags?: string[] }`\n - `transport.gql.field?`: explicit GraphQL field name (otherwise derived via `defaultGqlField`).\n- **OperationSpecRegistry**: registry of specs + handlers. Use `installOp(reg, spec, handler)` to attach a handler.\n- **Handler**: `(ctx, input) => Promise<output>` implementing the operation.\n- **CapabilitySpec**: canonical capability declaration stored in `src/capabilities.ts`. Tracks `meta` (`{ key, version, kind, title, description, domain, owners, tags, stability }`), `provides` surfaces (`operation`, `event`, `workflow`, `presentation`, `resource`), and `requires` which other capabilities must be present. Enforced during `installFeature`.\n- **PolicySpec**: declarative policy rules (`src/policy/spec.ts`) covering ABAC/ReBAC, consent + rate limit requirements, field-level controls, and PII guidance. `PolicyEngine` evaluates refs, while `OPAPolicyAdapter` lets OPA override/augment runtime decisions.\n- **TelemetrySpec**: analytics definitions (`src/telemetry/spec.ts`) describing event semantics, privacy level, retention, sampling, and anomaly detection. `TelemetryTracker` handles redaction/sampling, `TelemetryAnomalyMonitor` raises alerts, and specs integrate with contracts/workflows via `ctx.telemetry`.\n- **TestSpec**: declarative scenario definitions in `src/tests/spec.ts`. `TestRunner` executes fixtures/actions/assertions against a `OperationSpecRegistry`, and the CLI (`contractspec test`) wraps the runner for automation.\n- **ExperimentSpec**: experiment definitions (`src/experiments/spec.ts`) describing variants, allocation strategies, and success metrics. `ExperimentEvaluator` assigns variants (random/sticky/targeted) and integrates with Policy/Telemetry for safe experimentation.\n- **AppBlueprintSpec / TenantAppConfig**: global blueprints and per-tenant overrides (`src/app-config/spec.ts`). `resolveAppConfig()` merges the two into a `ResolvedAppConfig`, while `composeAppConfig()` hydrates the merged view against registries and reports missing references for safe rollout.\n- **RegeneratorService**: background daemon (`src/regenerator/service.ts`) that consumes telemetry/error/behavior signals, evaluates regeneration rules, and produces `SpecChangeProposal`s for Studio review.\n- **DataViewSpec**: declarative data presentation layer in `src/data-views.ts`. Describes entity projections (`fields`, `filters`, `actions`) with `view.kind` (`list`, `table`, `detail`, `grid`), ties to query operations via `source.primary`, and exposes optional presentation-based empty/error states.\n- **ThemeSpec**: design token + component variant definitions in `src/themes.ts`. Supports inheritance (`extends`), tenant/user overrides, and component-specific variant metadata for the design system.\n- **MigrationSpec**: schema/data migration descriptors (`src/migrations.ts`) with ordered step plans, dependency tracking, and pre/post checks to support automated database/content migrations.\n- **WorkflowSpec**: typed definition of multi-step workflows living in `src/workflow/spec.ts`. `WorkflowRegistry` stores versioned specs, and `validateWorkflowSpec()` (in `src/workflow/validation.ts`) checks graph integrity, step references, and reachability.\n\n### Lifecycle\n\n1. Define the spec (I/O via `SchemaModel` or zod) in a vertical lib (e.g. `contracts-coliving`).\n2. Register it: `installOp(registry, spec, handler)` within the app/service.\n3. Expose it via an adapter (REST, GraphQL, MCP). Each adapter maps the I/O to its transport and enforces policy.\n4. Validate at runtime: parse `input` before executing, parse `output` before returning.\n\n### Adapters\n\n- **REST**: see `packages/lssm/libs/contracts/src/server/rest-*`. Binds routes, validates request/response, maps errors/policies.\n- **MCP**: see `packages/lssm/libs/contracts/src/server/provider-mcp.ts` (standalone MCP server) and `packages/lssm/libs/contracts/src/server/rest-next-mcp.ts` (MCP over Next.js route). Provides tools/resources/prompts.\n - Tools + resources are registered from Zod schemas.\n - Resource templates are keyed by full `ResourceMeta.uriTemplate` (e.g. `docs://list`, `docs://doc/{id}`), so multiple templates can share a scheme (`docs://*`) without collisions.\n- **GraphQL (Pothos)**: see `packages/lssm/libs/contracts/src/server/graphql-pothos.ts`. Adds Query/Mutation fields by transforming contract I/O to GraphQL types.\n\n### GraphQL adapter behaviour (summary)\n\n- Field naming: `spec.transport.gql.field` or `<name_with_dots>_v<version>`.\n- Input/Output types from `SchemaModel` (preferred) or fallback zod introspection.\n- Scalars: String/Int/Float/Boolean/Date/JSON; Objects/Arrays/Enums; unions for outputs; input unions => JSON.\n- Policy: auth gate checks GraphQL context; optional feature flag gating.\n- Complexity & tracing: attaches hints and records timings; log includes `{ specName, version }`.\n\n#### Returns mapping and hydration\n\n- `spec.transport.gql.returns` can declare the GraphQL return wrapper: e.g. `\"Spot\"` or `[Spot]`. If omitted, the adapter infers from `io.output` (SchemaModel) or `resourceRef.graphQLType`.\n- Resource outputs: when `io.output` is a `resourceRef(...)` or `transport.gql.resource` is set, the adapter will optionally hydrate via a `ResourceRegistry` using `contracts-adapter-hydration.ts`:\n - Grammar is parsed with `parseReturns()`.\n - Entities are resolved via `hydrateResourceIfNeeded(resources, result, { template, varName, returns })` after handler execution.\n\n### Resource outputs\n\n- Declare resource outputs using `resourceRef(uriTemplate, opts)`.\n- `opts.varName` (default `id`) selects the identifier field returned by the handler for URI substitution.\n- `opts.graphQLType` is the GraphQL return type name (e.g., `Spot`) or list form (e.g., `[Spot]`).\n- `opts.many: true` indicates the handler returns an array of resources. The handler type becomes an array of items that include the identifier field.\n\nExample:\n\n```ts\nio: {\n input: ListThingsInput,\n output: resourceRef('myapp://thing/{id}', { graphQLType: '[Thing]', many: true }),\n}\n```\n\nHandler return (simplified): `{ id: string | number }[]`.\n\n### Errors\n\n- Validation errors → transport 400/GraphQL UserInputError.\n- Policy/auth errors → 401/403 or GraphQL ForbiddenError.\n- Handler errors → mapped to transport error with safe message.\n\n### Versioning & naming\n\n- Keep `meta.version` monotonic. Clients should pin to a versioned field/key.\n- Avoid renaming existing fields; add new fields with new versions.\n\n### Ownership metadata (OwnerShipMeta)\n\nAll contracts, events, features, and presentations reference a shared ownership schema (source of truth in `packages/lssm/libs/contracts/src/ownership.ts`).\n\n- Required fields: `title`, `description`, `domain`, `owners[]`, `tags[]`, `stability`.\n- Curated enums: the library exports suggested constants for owners and tags; free-form strings are still allowed for forward-compatibility.\n- Operations (`spec.ts`): `meta` requires `stability`, `owners`, and `tags` alongside `name`, `version`, `kind`, `description`, `goal`, and `context`.\n- Presentations V2: `meta` is a partial of ownership plus `description`.\n- Events: may specify `ownership` (recommended) for discoverability and docs.\n\n### Quick start\n\n```ts\n// app bootstrap\nconst reg = new OperationSpecRegistry();\ninstallOp(reg, BeginSignupSpec, beginSignupHandler);\nregisterContractsOnBuilder(gqlSchemaBuilder, reg); // GraphQL\n// or: createRestRouter(reg) // REST\n```\n"
17
17
  }];
18
18
  registerDocBlocks(tech_contracts_README_DocBlocks);
19
19
 
@@ -3,8 +3,8 @@ import { registerDocBlocks } from "../../registry.js";
3
3
  //#region src/docs/tech/contracts/openapi-export.docblock.ts
4
4
  const tech_contracts_openapi_export_DocBlocks = [{
5
5
  id: "docs.tech.contracts.openapi-export",
6
- title: "OpenAPI export (OpenAPI 3.1) from SpecRegistry",
7
- summary: "Generate a deterministic OpenAPI document from a SpecRegistry using jsonSchemaForSpec + REST transport metadata.",
6
+ title: "OpenAPI export (OpenAPI 3.1) from OperationSpecRegistry",
7
+ summary: "Generate a deterministic OpenAPI document from a OperationSpecRegistry using jsonSchemaForSpec + REST transport metadata.",
8
8
  kind: "reference",
9
9
  visibility: "public",
10
10
  route: "/docs/tech/contracts/openapi-export",
@@ -13,7 +13,7 @@ const tech_contracts_openapi_export_DocBlocks = [{
13
13
  "openapi",
14
14
  "rest"
15
15
  ],
16
- body: `## OpenAPI export (OpenAPI 3.1) from SpecRegistry
16
+ body: `## OpenAPI export (OpenAPI 3.1) from OperationSpecRegistry
17
17
 
18
18
  ### Purpose
19
19
 
@@ -42,9 +42,9 @@ contractspec openapi --registry ./src/registry.ts --out ./openapi.json
42
42
 
43
43
  The registry module must export one of:
44
44
 
45
- - \`registry: SpecRegistry\`
46
- - \`default(): SpecRegistry | Promise<SpecRegistry>\`
47
- - \`createRegistry(): SpecRegistry | Promise<SpecRegistry>\`
45
+ - \`registry: OperationSpecRegistry\`
46
+ - \`default(): OperationSpecRegistry | Promise<OperationSpecRegistry>\`
47
+ - \`createRegistry(): OperationSpecRegistry | Promise<OperationSpecRegistry>\`
48
48
 
49
49
  ### Notes / limitations (current)
50
50
 
@@ -4,7 +4,7 @@ import { registerDocBlocks } from "../../registry.js";
4
4
  const tech_contracts_ops_to_presentation_linking_DocBlocks = [{
5
5
  id: "docs.tech.contracts.ops-to-presentation-linking",
6
6
  title: "Ops ↔ Presentation linking (V2)",
7
- summary: "This document explains how operations (ContractSpec) are linked to Presentations (PresentationDescriptorV2) via Feature modules.",
7
+ summary: "This document explains how operations (OperationSpec) are linked to Presentations (PresentationDescriptorV2) via Feature modules.",
8
8
  kind: "reference",
9
9
  visibility: "public",
10
10
  route: "/docs/tech/contracts/ops-to-presentation-linking",
@@ -13,7 +13,7 @@ const tech_contracts_ops_to_presentation_linking_DocBlocks = [{
13
13
  "contracts",
14
14
  "ops-to-presentation-linking"
15
15
  ],
16
- body: "### Ops ↔ Presentation linking (V2)\n\nThis document explains how operations (ContractSpec) are linked to Presentations (PresentationDescriptorV2) via Feature modules.\n\n- Location: `@lssm/lib.contracts/src/features.ts`\n- Field: `FeatureModuleSpec.opToPresentation?: { op: { name; version }; pres: { name; version } }[]`\n- Validation: `installFeature()` validates that linked ops exist in `SpecRegistry` and linked presentations exist in the registry, and that declared targets are present.\n\nExample:\n\n```ts\nimport type { SpecRegistry } from '@lssm/lib.contracts/src/registry';\nimport { FeatureRegistry, createFeatureModule } from '@lssm/lib.contracts';\n\nexport function buildFeaturesWithOps(ops: SpecRegistry) {\n const features = new FeatureRegistry();\n features.register(\n createFeatureModule(\n {\n key: 'myapp.widgets.linkage',\n title: 'Widgets (linked)',\n description: 'Links create/update ops to UI presentations',\n domain: 'widgets',\n tags: ['widgets', 'linkage'],\n stability: 'beta',\n },\n {\n operations: [\n { name: 'widgets.create', version: 1 },\n { name: 'widgets.update', version: 1 },\n ],\n presentations: [{ name: 'myapp.widgets.editor.page', version: 1 }],\n opToPresentation: [\n {\n op: { name: 'widgets.create', version: 1 },\n pres: { name: 'myapp.widgets.editor.page', version: 1 },\n },\n {\n op: { name: 'widgets.update', version: 1 },\n pres: { name: 'myapp.widgets.editor.page', version: 1 },\n },\n ],\n presentationsTargets: [\n {\n name: 'myapp.widgets.editor.page',\n version: 1,\n targets: ['react', 'markdown'],\n },\n ],\n }\n )\n );\n return { features };\n}\n```\n\nNotes\n\n- This enables traceability: the UI flow that realizes an op is discoverable via the feature catalog.\n- Presentations can target multiple outputs (`react`, `markdown`, `application/json`, `application/xml`).\n- Use `renderFeaturePresentation()` to render a descriptor to a given target with a component map.\n"
16
+ body: "### Ops ↔ Presentation linking (V2)\n\nThis document explains how operations (OperationSpec) are linked to Presentations (PresentationDescriptorV2) via Feature modules.\n\n- Location: `@lssm/lib.contracts/src/features.ts`\n- Field: `FeatureModuleSpec.opToPresentation?: { op: { name; version }; pres: { name; version } }[]`\n- Validation: `installFeature()` validates that linked ops exist in `OperationSpecRegistry` and linked presentations exist in the registry, and that declared targets are present.\n\nExample:\n\n```ts\nimport type { OperationSpecRegistry } from '@lssm/lib.contracts/src/registry';\nimport { FeatureRegistry, createFeatureModule } from '@lssm/lib.contracts';\n\nexport function buildFeaturesWithOps(ops: OperationSpecRegistry) {\n const features = new FeatureRegistry();\n features.register(\n createFeatureModule(\n {\n key: 'myapp.widgets.linkage',\n title: 'Widgets (linked)',\n description: 'Links create/update ops to UI presentations',\n domain: 'widgets',\n tags: ['widgets', 'linkage'],\n stability: 'beta',\n },\n {\n operations: [\n { name: 'widgets.create', version: 1 },\n { name: 'widgets.update', version: 1 },\n ],\n presentations: [{ name: 'myapp.widgets.editor.page', version: 1 }],\n opToPresentation: [\n {\n op: { name: 'widgets.create', version: 1 },\n pres: { name: 'myapp.widgets.editor.page', version: 1 },\n },\n {\n op: { name: 'widgets.update', version: 1 },\n pres: { name: 'myapp.widgets.editor.page', version: 1 },\n },\n ],\n presentationsTargets: [\n {\n name: 'myapp.widgets.editor.page',\n version: 1,\n targets: ['react', 'markdown'],\n },\n ],\n }\n )\n );\n return { features };\n}\n```\n\nNotes\n\n- This enables traceability: the UI flow that realizes an op is discoverable via the feature catalog.\n- Presentations can target multiple outputs (`react`, `markdown`, `application/json`, `application/xml`).\n- Use `renderFeaturePresentation()` to render a descriptor to a given target with a component map.\n"
17
17
  }];
18
18
  registerDocBlocks(tech_contracts_ops_to_presentation_linking_DocBlocks);
19
19
 
@@ -4,7 +4,7 @@ import { registerDocBlocks } from "../../registry.js";
4
4
  const tech_contracts_tests_DocBlocks = [{
5
5
  id: "docs.tech.contracts.tests",
6
6
  title: "TestSpec & TestRunner",
7
- summary: "Use `TestSpec` to describe end-to-end scenarios for contracts and workflows. Specs live alongside your contracts and exercise the same SpecRegistry handlers the app uses.",
7
+ summary: "Use `TestSpec` to describe end-to-end scenarios for contracts and workflows. Specs live alongside your contracts and exercise the same OperationSpecRegistry handlers the app uses.",
8
8
  kind: "reference",
9
9
  visibility: "public",
10
10
  route: "/docs/tech/contracts/tests",
@@ -13,7 +13,7 @@ const tech_contracts_tests_DocBlocks = [{
13
13
  "contracts",
14
14
  "tests"
15
15
  ],
16
- body: "## TestSpec & TestRunner\n\nUse `TestSpec` to describe end-to-end scenarios for contracts and workflows. Specs live alongside your contracts and exercise the same SpecRegistry handlers the app uses.\n\n- Types & registry: `packages/libs/contracts/src/tests/spec.ts`\n- Runtime runner: `packages/libs/contracts/src/tests/runner.ts`\n- CLI: `contractspec test`\n\n### Structure\n\n```ts\nexport interface TestSpec {\n meta: TestSpecMeta;\n target: TestTarget; // contract or workflow\n fixtures?: Fixture[]; // optional shared setup before each scenario\n scenarios: TestScenario[];\n coverage?: CoverageRequirement;\n}\n```\n\n- `Fixture`: run an operation before the scenario (`operation`, optional `input`)\n- `Action`: operation input that the scenario exercises\n- `Assertion`:\n - `expectOutput` `{ match }` deep-equals the handler output\n - `expectError` `{ messageIncludes? }` ensures an error was thrown\n - `expectEvents` `{ events: [{ name, version, min?, max? }] }` checks emitted events\n\n### Example\n\n```ts\nimport { defineCommand, type TestSpec } from '@lssm/lib.contracts';\n\nexport const AddNumbersSpec = defineCommand({\n meta: { name: 'math.add', version: 1, /* … */ },\n io: {\n input: AddNumbersInput,\n output: AddNumbersOutput,\n },\n policy: { auth: 'user' },\n});\n\nexport const MathAddTests: TestSpec = {\n meta: {\n name: 'math.add.tests',\n version: 1,\n title: 'Math add scenarios',\n owners: ['@team.math'],\n tags: ['math'],\n stability: StabilityEnum.Experimental,\n },\n target: { type: 'contract', operation: { name: 'math.add' } },\n scenarios: [\n {\n name: 'adds positive numbers',\n when: {\n operation: { name: 'math.add' },\n input: { a: 2, b: 3 },\n },\n then: [\n { type: 'expectOutput', match: { sum: 5 } },\n {\n type: 'expectEvents',\n events: [{ name: 'math.sum_calculated', version: 1, min: 1 }],\n },\n ],\n },\n ],\n};\n```\n\n### Running tests\n\n1. Register the contract handlers in a `SpecRegistry`:\n\n```ts\nexport function createRegistry() {\n const registry = new SpecRegistry();\n registry.register(AddNumbersSpec);\n registry.bind(AddNumbersSpec, addNumbersHandler);\n return registry;\n}\n```\n\n2. Run the CLI:\n\n```\ncontractspec test apps/math/tests/math.add.tests.ts \\\n --registry apps/math/tests/registry.ts\n```\n\n- The CLI loads the TestSpec, instantiates the registry (via the provided module), and executes each scenario via `TestRunner`.\n- `--json` outputs machine-readable results.\n\n### Programmatic usage\n\n```ts\nconst runner = new TestRunner({\n registry,\n createContext: () => ({ actor: 'user', organizationId: 'tenant-1' }),\n});\n\nconst result = await runner.run(MathAddTests);\nconsole.log(result.passed, result.failed);\n```\n\n- `createContext` can supply default `HandlerCtx` values.\n- `beforeEach` / `afterEach` hooks let you seed databases or reset state.\n\n### Best practices\n\n- Keep fixtures idempotent so scenarios can run in parallel in the future.\n- Use `expectEvents` to guard analytics/telemetry expectations.\n- Add specs to `TestRegistry` for discovery and documentation.\n- `coverage` captures desired coverage metrics (enforced by future tooling).\n- Pair TestSpec files with CI using `contractspec test --json` and fail builds when `failed > 0`.\n\n### Mocking with Bun's `vi`\n\n- Pass a single function type to `vi.fn<TFunction>()` so calls retain typed arguments:\n\n```ts\nconst handler = vi.fn<typeof fetch>();\nconst fetchImpl: typeof fetch = ((...args) => handler(...args)) as typeof fetch;\nObject.defineProperty(fetchImpl, 'preconnect', {\n value: vi.fn<typeof fetch.preconnect>(),\n});\n```\n\n- When you need to inspect calls, use the typed mock (`handler.mock.calls`) rather than casting to `any`.\n- Narrow optional request data defensively (e.g., check for headers before reading them) so tests remain type-safe under strict `tsconfig` settings.\n\n"
16
+ body: "## TestSpec & TestRunner\n\nUse `TestSpec` to describe end-to-end scenarios for contracts and workflows. Specs live alongside your contracts and exercise the same OperationSpecRegistry handlers the app uses.\n\n- Types & registry: `packages/libs/contracts/src/tests/spec.ts`\n- Runtime runner: `packages/libs/contracts/src/tests/runner.ts`\n- CLI: `contractspec test`\n\n### Structure\n\n```ts\nexport interface TestSpec {\n meta: TestSpecMeta;\n target: TestTarget; // contract or workflow\n fixtures?: Fixture[]; // optional shared setup before each scenario\n scenarios: TestScenario[];\n coverage?: CoverageRequirement;\n}\n```\n\n- `Fixture`: run an operation before the scenario (`operation`, optional `input`)\n- `Action`: operation input that the scenario exercises\n- `Assertion`:\n - `expectOutput` `{ match }` deep-equals the handler output\n - `expectError` `{ messageIncludes? }` ensures an error was thrown\n - `expectEvents` `{ events: [{ name, version, min?, max? }] }` checks emitted events\n\n### Example\n\n```ts\nimport { defineCommand, type TestSpec } from '@lssm/lib.contracts';\n\nexport const AddNumbersSpec = defineCommand({\n meta: { name: 'math.add', version: 1, /* … */ },\n io: {\n input: AddNumbersInput,\n output: AddNumbersOutput,\n },\n policy: { auth: 'user' },\n});\n\nexport const MathAddTests: TestSpec = {\n meta: {\n name: 'math.add.tests',\n version: 1,\n title: 'Math add scenarios',\n owners: ['@team.math'],\n tags: ['math'],\n stability: StabilityEnum.Experimental,\n },\n target: { type: 'contract', operation: { name: 'math.add' } },\n scenarios: [\n {\n name: 'adds positive numbers',\n when: {\n operation: { name: 'math.add' },\n input: { a: 2, b: 3 },\n },\n then: [\n { type: 'expectOutput', match: { sum: 5 } },\n {\n type: 'expectEvents',\n events: [{ name: 'math.sum_calculated', version: 1, min: 1 }],\n },\n ],\n },\n ],\n};\n```\n\n### Running tests\n\n1. Register the contract handlers in a `OperationSpecRegistry`:\n\n```ts\nexport function createRegistry() {\n const registry = new OperationSpecRegistry();\n registry.register(AddNumbersSpec);\n registry.bind(AddNumbersSpec, addNumbersHandler);\n return registry;\n}\n```\n\n2. Run the CLI:\n\n```\ncontractspec test apps/math/tests/math.add.tests.ts \\\n --registry apps/math/tests/registry.ts\n```\n\n- The CLI loads the TestSpec, instantiates the registry (via the provided module), and executes each scenario via `TestRunner`.\n- `--json` outputs machine-readable results.\n\n### Programmatic usage\n\n```ts\nconst runner = new TestRunner({\n registry,\n createContext: () => ({ actor: 'user', organizationId: 'tenant-1' }),\n});\n\nconst result = await runner.run(MathAddTests);\nconsole.log(result.passed, result.failed);\n```\n\n- `createContext` can supply default `HandlerCtx` values.\n- `beforeEach` / `afterEach` hooks let you seed databases or reset state.\n\n### Best practices\n\n- Keep fixtures idempotent so scenarios can run in parallel in the future.\n- Use `expectEvents` to guard analytics/telemetry expectations.\n- Add specs to `TestRegistry` for discovery and documentation.\n- `coverage` captures desired coverage metrics (enforced by future tooling).\n- Pair TestSpec files with CI using `contractspec test --json` and fail builds when `failed > 0`.\n\n### Mocking with Bun's `vi`\n\n- Pass a single function type to `vi.fn<TFunction>()` so calls retain typed arguments:\n\n```ts\nconst handler = vi.fn<typeof fetch>();\nconst fetchImpl: typeof fetch = ((...args) => handler(...args)) as typeof fetch;\nObject.defineProperty(fetchImpl, 'preconnect', {\n value: vi.fn<typeof fetch.preconnect>(),\n});\n```\n\n- When you need to inspect calls, use the typed mock (`handler.mock.calls`) rather than casting to `any`.\n- Narrow optional request data defensively (e.g., check for headers before reading them) so tests remain type-safe under strict `tsconfig` settings.\n\n"
17
17
  }];
18
18
  registerDocBlocks(tech_contracts_tests_DocBlocks);
19
19
 
@@ -1,10 +1,10 @@
1
1
  import { ResourceRefDescriptor } from "../resources.js";
2
- import { ContractSpec, OpKind } from "../spec.js";
2
+ import { OpKind, OperationSpec } from "../operation.js";
3
3
  import { HandlerCtx } from "../types.js";
4
4
  import { AnySchemaModel } from "@lssm/lib.schema";
5
5
 
6
6
  //#region src/experiments/spec-resolver.d.ts
7
- type RuntimeContract = ContractSpec<AnySchemaModel, AnySchemaModel | ResourceRefDescriptor<boolean>>;
7
+ type RuntimeContract = OperationSpec<AnySchemaModel, AnySchemaModel | ResourceRefDescriptor<boolean>>;
8
8
  interface SpecVariantResolver {
9
9
  resolve(operation: {
10
10
  name: string;