@contractspec/example.workflow-system 1.57.0 → 1.58.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 (209) hide show
  1. package/dist/approval/approval.enum.d.ts +2 -7
  2. package/dist/approval/approval.enum.d.ts.map +1 -1
  3. package/dist/approval/approval.enum.js +20 -26
  4. package/dist/approval/approval.event.d.ts +108 -114
  5. package/dist/approval/approval.event.d.ts.map +1 -1
  6. package/dist/approval/approval.event.js +103 -210
  7. package/dist/approval/approval.handler.d.ts +17 -18
  8. package/dist/approval/approval.handler.d.ts.map +1 -1
  9. package/dist/approval/approval.operations.d.ts +429 -435
  10. package/dist/approval/approval.operations.d.ts.map +1 -1
  11. package/dist/approval/approval.operations.js +364 -339
  12. package/dist/approval/approval.schema.d.ts +86 -91
  13. package/dist/approval/approval.schema.d.ts.map +1 -1
  14. package/dist/approval/approval.schema.js +71 -107
  15. package/dist/approval/index.d.ts +8 -5
  16. package/dist/approval/index.d.ts.map +1 -0
  17. package/dist/approval/index.js +484 -5
  18. package/dist/browser/approval/approval.enum.js +22 -0
  19. package/dist/browser/approval/approval.event.js +112 -0
  20. package/dist/browser/approval/approval.operations.js +369 -0
  21. package/dist/browser/approval/approval.schema.js +73 -0
  22. package/dist/browser/approval/index.js +484 -0
  23. package/dist/browser/docs/index.js +103 -0
  24. package/dist/browser/docs/workflow-system.docblock.js +103 -0
  25. package/dist/browser/entities/approval.js +119 -0
  26. package/dist/browser/entities/index.js +508 -0
  27. package/dist/browser/entities/instance.js +161 -0
  28. package/dist/browser/entities/step.js +124 -0
  29. package/dist/browser/entities/workflow.js +82 -0
  30. package/dist/browser/example.js +42 -0
  31. package/dist/browser/handlers/index.js +253 -0
  32. package/dist/browser/handlers/workflow.handlers.js +253 -0
  33. package/dist/browser/index.js +3120 -0
  34. package/dist/browser/instance/index.js +677 -0
  35. package/dist/browser/instance/instance.enum.js +15 -0
  36. package/dist/browser/instance/instance.event.js +164 -0
  37. package/dist/browser/instance/instance.handler.js +356 -0
  38. package/dist/browser/instance/instance.operations.js +9 -0
  39. package/dist/browser/instance/instance.schema.js +101 -0
  40. package/dist/browser/presentations/index.js +109 -0
  41. package/dist/browser/seeders/index.js +3 -0
  42. package/dist/browser/shared/index.js +3 -0
  43. package/dist/browser/shared/mock-data.js +11 -0
  44. package/dist/browser/shared/types.js +0 -0
  45. package/dist/browser/state-machine/index.js +6 -0
  46. package/dist/browser/tests/operations.test-spec.js +6 -0
  47. package/dist/browser/ui/WorkflowDashboard.js +3 -0
  48. package/dist/browser/ui/hooks/index.js +50 -0
  49. package/dist/browser/ui/hooks/useWorkflowList.js +50 -0
  50. package/dist/browser/ui/index.js +54 -0
  51. package/dist/browser/ui/renderers/index.js +227 -0
  52. package/dist/browser/ui/renderers/workflow.markdown.js +227 -0
  53. package/dist/browser/workflow/index.js +21 -0
  54. package/dist/browser/workflow/workflow.enum.js +36 -0
  55. package/dist/browser/workflow/workflow.event.js +6 -0
  56. package/dist/browser/workflow/workflow.handler.js +5 -0
  57. package/dist/browser/workflow/workflow.operations.js +8 -0
  58. package/dist/browser/workflow/workflow.schema.js +151 -0
  59. package/dist/browser/workflow-system.capability.js +5 -0
  60. package/dist/browser/workflow-system.feature.js +3 -0
  61. package/dist/docs/index.d.ts +2 -1
  62. package/dist/docs/index.d.ts.map +1 -0
  63. package/dist/docs/index.js +104 -1
  64. package/dist/docs/workflow-system.docblock.d.ts +2 -1
  65. package/dist/docs/workflow-system.docblock.d.ts.map +1 -0
  66. package/dist/docs/workflow-system.docblock.js +45 -56
  67. package/dist/entities/approval.d.ts +35 -40
  68. package/dist/entities/approval.d.ts.map +1 -1
  69. package/dist/entities/approval.js +116 -124
  70. package/dist/entities/index.d.ts +132 -137
  71. package/dist/entities/index.d.ts.map +1 -1
  72. package/dist/entities/index.js +506 -29
  73. package/dist/entities/instance.d.ts +46 -51
  74. package/dist/entities/instance.d.ts.map +1 -1
  75. package/dist/entities/instance.js +158 -164
  76. package/dist/entities/step.d.ts +31 -36
  77. package/dist/entities/step.d.ts.map +1 -1
  78. package/dist/entities/step.js +122 -132
  79. package/dist/entities/workflow.d.ts +22 -27
  80. package/dist/entities/workflow.d.ts.map +1 -1
  81. package/dist/entities/workflow.js +80 -99
  82. package/dist/example.d.ts +2 -6
  83. package/dist/example.d.ts.map +1 -1
  84. package/dist/example.js +41 -55
  85. package/dist/handlers/index.d.ts +2 -2
  86. package/dist/handlers/index.d.ts.map +1 -0
  87. package/dist/handlers/index.js +254 -3
  88. package/dist/handlers/workflow.handlers.d.ts +107 -106
  89. package/dist/handlers/workflow.handlers.d.ts.map +1 -1
  90. package/dist/handlers/workflow.handlers.js +237 -246
  91. package/dist/index.d.ts +15 -26
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +3121 -26
  94. package/dist/instance/index.d.ts +8 -5
  95. package/dist/instance/index.d.ts.map +1 -0
  96. package/dist/instance/index.js +677 -5
  97. package/dist/instance/instance.enum.d.ts +1 -6
  98. package/dist/instance/instance.enum.d.ts.map +1 -1
  99. package/dist/instance/instance.enum.js +14 -18
  100. package/dist/instance/instance.event.d.ts +313 -319
  101. package/dist/instance/instance.event.d.ts.map +1 -1
  102. package/dist/instance/instance.event.js +151 -279
  103. package/dist/instance/instance.handler.d.ts +21 -22
  104. package/dist/instance/instance.handler.d.ts.map +1 -1
  105. package/dist/instance/instance.handler.js +352 -89
  106. package/dist/instance/instance.operations.d.ts +819 -825
  107. package/dist/instance/instance.operations.d.ts.map +1 -1
  108. package/dist/instance/instance.operations.js +10 -464
  109. package/dist/instance/instance.schema.d.ts +196 -201
  110. package/dist/instance/instance.schema.d.ts.map +1 -1
  111. package/dist/instance/instance.schema.js +97 -167
  112. package/dist/presentations/index.d.ts +23 -28
  113. package/dist/presentations/index.d.ts.map +1 -1
  114. package/dist/presentations/index.js +104 -334
  115. package/dist/seeders/index.d.ts +4 -8
  116. package/dist/seeders/index.d.ts.map +1 -1
  117. package/dist/seeders/index.js +4 -19
  118. package/dist/shared/index.d.ts +6 -3
  119. package/dist/shared/index.d.ts.map +1 -0
  120. package/dist/shared/index.js +4 -3
  121. package/dist/shared/mock-data.d.ts +16 -16
  122. package/dist/shared/mock-data.d.ts.map +1 -1
  123. package/dist/shared/mock-data.js +11 -11
  124. package/dist/shared/types.d.ts +69 -72
  125. package/dist/shared/types.d.ts.map +1 -1
  126. package/dist/shared/types.js +1 -0
  127. package/dist/state-machine/index.d.ts +92 -95
  128. package/dist/state-machine/index.d.ts.map +1 -1
  129. package/dist/state-machine/index.js +6 -157
  130. package/dist/tests/operations.test-spec.d.ts +4 -9
  131. package/dist/tests/operations.test-spec.d.ts.map +1 -1
  132. package/dist/tests/operations.test-spec.js +7 -123
  133. package/dist/ui/WorkflowDashboard.d.ts +1 -6
  134. package/dist/ui/WorkflowDashboard.d.ts.map +1 -1
  135. package/dist/ui/WorkflowDashboard.js +3 -222
  136. package/dist/ui/hooks/index.d.ts +2 -2
  137. package/dist/ui/hooks/index.d.ts.map +1 -0
  138. package/dist/ui/hooks/index.js +51 -5
  139. package/dist/ui/hooks/useWorkflowList.d.ts +15 -19
  140. package/dist/ui/hooks/useWorkflowList.d.ts.map +1 -1
  141. package/dist/ui/hooks/useWorkflowList.js +47 -51
  142. package/dist/ui/index.d.ts +7 -6
  143. package/dist/ui/index.d.ts.map +1 -0
  144. package/dist/ui/index.js +55 -6
  145. package/dist/ui/renderers/index.d.ts +2 -2
  146. package/dist/ui/renderers/index.d.ts.map +1 -0
  147. package/dist/ui/renderers/index.js +227 -2
  148. package/dist/ui/renderers/workflow.markdown.d.ts +13 -14
  149. package/dist/ui/renderers/workflow.markdown.d.ts.map +1 -1
  150. package/dist/ui/renderers/workflow.markdown.js +223 -229
  151. package/dist/workflow/index.d.ts +8 -5
  152. package/dist/workflow/index.d.ts.map +1 -0
  153. package/dist/workflow/index.js +22 -6
  154. package/dist/workflow/workflow.enum.d.ts +4 -9
  155. package/dist/workflow/workflow.enum.d.ts.map +1 -1
  156. package/dist/workflow/workflow.enum.js +32 -42
  157. package/dist/workflow/workflow.event.d.ts +112 -118
  158. package/dist/workflow/workflow.event.d.ts.map +1 -1
  159. package/dist/workflow/workflow.event.js +7 -150
  160. package/dist/workflow/workflow.handler.d.ts +23 -24
  161. package/dist/workflow/workflow.handler.d.ts.map +1 -1
  162. package/dist/workflow/workflow.handler.js +6 -66
  163. package/dist/workflow/workflow.operations.d.ts +847 -853
  164. package/dist/workflow/workflow.operations.d.ts.map +1 -1
  165. package/dist/workflow/workflow.operations.js +9 -345
  166. package/dist/workflow/workflow.schema.d.ts +229 -234
  167. package/dist/workflow/workflow.schema.d.ts.map +1 -1
  168. package/dist/workflow/workflow.schema.js +146 -243
  169. package/dist/workflow-system.capability.d.ts +3 -8
  170. package/dist/workflow-system.capability.d.ts.map +1 -1
  171. package/dist/workflow-system.capability.js +6 -34
  172. package/dist/workflow-system.feature.d.ts +1 -6
  173. package/dist/workflow-system.feature.d.ts.map +1 -1
  174. package/dist/workflow-system.feature.js +4 -346
  175. package/package.json +415 -93
  176. package/dist/approval/approval.enum.js.map +0 -1
  177. package/dist/approval/approval.event.js.map +0 -1
  178. package/dist/approval/approval.handler.js +0 -72
  179. package/dist/approval/approval.handler.js.map +0 -1
  180. package/dist/approval/approval.operations.js.map +0 -1
  181. package/dist/approval/approval.schema.js.map +0 -1
  182. package/dist/docs/workflow-system.docblock.js.map +0 -1
  183. package/dist/entities/approval.js.map +0 -1
  184. package/dist/entities/index.js.map +0 -1
  185. package/dist/entities/instance.js.map +0 -1
  186. package/dist/entities/step.js.map +0 -1
  187. package/dist/entities/workflow.js.map +0 -1
  188. package/dist/example.js.map +0 -1
  189. package/dist/handlers/workflow.handlers.js.map +0 -1
  190. package/dist/instance/instance.enum.js.map +0 -1
  191. package/dist/instance/instance.event.js.map +0 -1
  192. package/dist/instance/instance.handler.js.map +0 -1
  193. package/dist/instance/instance.operations.js.map +0 -1
  194. package/dist/instance/instance.schema.js.map +0 -1
  195. package/dist/presentations/index.js.map +0 -1
  196. package/dist/seeders/index.js.map +0 -1
  197. package/dist/shared/mock-data.js.map +0 -1
  198. package/dist/state-machine/index.js.map +0 -1
  199. package/dist/tests/operations.test-spec.js.map +0 -1
  200. package/dist/ui/WorkflowDashboard.js.map +0 -1
  201. package/dist/ui/hooks/useWorkflowList.js.map +0 -1
  202. package/dist/ui/renderers/workflow.markdown.js.map +0 -1
  203. package/dist/workflow/workflow.enum.js.map +0 -1
  204. package/dist/workflow/workflow.event.js.map +0 -1
  205. package/dist/workflow/workflow.handler.js.map +0 -1
  206. package/dist/workflow/workflow.operations.js.map +0 -1
  207. package/dist/workflow/workflow.schema.js.map +0 -1
  208. package/dist/workflow-system.capability.js.map +0 -1
  209. package/dist/workflow-system.feature.js.map +0 -1
@@ -0,0 +1,3120 @@
1
+ // src/approval/approval.enum.ts
2
+ import { defineEnum } from "@contractspec/lib.schema";
3
+ var ApprovalStatusEnum = defineEnum("ApprovalStatus", [
4
+ "PENDING",
5
+ "APPROVED",
6
+ "REJECTED",
7
+ "DELEGATED",
8
+ "ESCALATED",
9
+ "WITHDRAWN",
10
+ "EXPIRED"
11
+ ]);
12
+ var ApprovalDecisionEnum = defineEnum("ApprovalDecision", [
13
+ "APPROVE",
14
+ "REJECT",
15
+ "REQUEST_CHANGES",
16
+ "DELEGATE",
17
+ "ABSTAIN"
18
+ ]);
19
+
20
+ // src/approval/approval.event.ts
21
+ import { defineEvent, defineSchemaModel } from "@contractspec/lib.contracts";
22
+ import { ScalarTypeEnum } from "@contractspec/lib.schema";
23
+ var ApprovalRequestedPayload = defineSchemaModel({
24
+ name: "ApprovalRequestedEventPayload",
25
+ description: "Payload when approval is requested",
26
+ fields: {
27
+ requestId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
28
+ instanceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
29
+ workflowKey: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
30
+ approverId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
31
+ approverRole: {
32
+ type: ScalarTypeEnum.String_unsecure(),
33
+ isOptional: true
34
+ },
35
+ title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
36
+ dueAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
37
+ timestamp: { type: ScalarTypeEnum.DateTime(), isOptional: false }
38
+ }
39
+ });
40
+ var ApprovalDecidedPayload = defineSchemaModel({
41
+ name: "ApprovalDecidedEventPayload",
42
+ description: "Payload when approval decision is made",
43
+ fields: {
44
+ requestId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
45
+ instanceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
46
+ decision: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
47
+ decidedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
48
+ comment: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
49
+ timestamp: { type: ScalarTypeEnum.DateTime(), isOptional: false }
50
+ }
51
+ });
52
+ var ApprovalDelegatedPayload = defineSchemaModel({
53
+ name: "ApprovalDelegatedEventPayload",
54
+ description: "Payload when approval is delegated",
55
+ fields: {
56
+ requestId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
57
+ instanceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
58
+ fromUserId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
59
+ toUserId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
60
+ reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
61
+ timestamp: { type: ScalarTypeEnum.DateTime(), isOptional: false }
62
+ }
63
+ });
64
+ var ApprovalEscalatedPayload = defineSchemaModel({
65
+ name: "ApprovalEscalatedEventPayload",
66
+ description: "Payload when approval is escalated",
67
+ fields: {
68
+ requestId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
69
+ instanceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
70
+ escalationLevel: {
71
+ type: ScalarTypeEnum.Int_unsecure(),
72
+ isOptional: false
73
+ },
74
+ escalatedTo: {
75
+ type: ScalarTypeEnum.String_unsecure(),
76
+ isOptional: false
77
+ },
78
+ reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
79
+ timestamp: { type: ScalarTypeEnum.DateTime(), isOptional: false }
80
+ }
81
+ });
82
+ var ApprovalRequestedEvent = defineEvent({
83
+ meta: {
84
+ key: "workflow.approval.requested",
85
+ version: "1.0.0",
86
+ description: "An approval has been requested.",
87
+ stability: "stable",
88
+ owners: ["@workflow-team"],
89
+ tags: ["workflow", "approval", "requested"]
90
+ },
91
+ payload: ApprovalRequestedPayload
92
+ });
93
+ var ApprovalDecidedEvent = defineEvent({
94
+ meta: {
95
+ key: "workflow.approval.decided",
96
+ version: "1.0.0",
97
+ description: "An approval decision has been made.",
98
+ stability: "stable",
99
+ owners: ["@workflow-team"],
100
+ tags: ["workflow", "approval", "decided"]
101
+ },
102
+ payload: ApprovalDecidedPayload
103
+ });
104
+ var ApprovalDelegatedEvent = defineEvent({
105
+ meta: {
106
+ key: "workflow.approval.delegated",
107
+ version: "1.0.0",
108
+ description: "An approval has been delegated.",
109
+ stability: "stable",
110
+ owners: ["@workflow-team"],
111
+ tags: ["workflow", "approval", "delegated"]
112
+ },
113
+ payload: ApprovalDelegatedPayload
114
+ });
115
+ var ApprovalEscalatedEvent = defineEvent({
116
+ meta: {
117
+ key: "workflow.approval.escalated",
118
+ version: "1.0.0",
119
+ description: "An approval has been escalated.",
120
+ stability: "stable",
121
+ owners: ["@workflow-team"],
122
+ tags: ["workflow", "approval", "escalated"]
123
+ },
124
+ payload: ApprovalEscalatedPayload
125
+ });
126
+
127
+ // src/shared/mock-data.ts
128
+ var mockDataStore = {
129
+ workflows: new Map,
130
+ steps: new Map,
131
+ instances: new Map,
132
+ approvals: new Map,
133
+ stepExecutions: new Map
134
+ };
135
+
136
+ // src/state-machine/index.ts
137
+ class BasicStateMachineEngine {
138
+ canTransition(definition, state, action, context) {
139
+ if (state.status !== "RUNNING" && state.status !== "WAITING") {
140
+ return {
141
+ allowed: false,
142
+ reason: `Workflow is ${state.status}, cannot transition`
143
+ };
144
+ }
145
+ const currentStep = definition.steps[state.currentStepKey];
146
+ if (!currentStep) {
147
+ return {
148
+ allowed: false,
149
+ reason: `Step ${state.currentStepKey} not found`
150
+ };
151
+ }
152
+ const transition = currentStep.transitions[action];
153
+ if (!transition) {
154
+ return {
155
+ allowed: false,
156
+ reason: `Action ${action} not available in step ${state.currentStepKey}`
157
+ };
158
+ }
159
+ if (currentStep.allowedRoles && currentStep.allowedRoles.length > 0) {
160
+ const hasRole = currentStep.allowedRoles.some((role) => context.userRoles.includes(role));
161
+ if (!hasRole) {
162
+ return {
163
+ allowed: false,
164
+ reason: `User lacks required role for this action`
165
+ };
166
+ }
167
+ }
168
+ if (typeof transition === "object" && transition.allowedRoles && transition.allowedRoles.length > 0) {
169
+ const hasRole = transition.allowedRoles.some((role) => context.userRoles.includes(role));
170
+ if (!hasRole) {
171
+ return {
172
+ allowed: false,
173
+ reason: `User lacks required role for action ${action}`
174
+ };
175
+ }
176
+ }
177
+ return { allowed: true };
178
+ }
179
+ getAvailableActions(definition, state, context) {
180
+ if (state.status !== "RUNNING" && state.status !== "WAITING") {
181
+ return [];
182
+ }
183
+ const currentStep = definition.steps[state.currentStepKey];
184
+ if (!currentStep) {
185
+ return [];
186
+ }
187
+ return Object.keys(currentStep.transitions).filter((action) => {
188
+ const result = this.canTransition(definition, state, action, context);
189
+ return result.allowed;
190
+ });
191
+ }
192
+ transition(definition, state, action, context) {
193
+ const validation = this.canTransition(definition, state, action, context);
194
+ if (!validation.allowed) {
195
+ return {
196
+ success: false,
197
+ previousStepKey: state.currentStepKey,
198
+ currentStepKey: state.currentStepKey,
199
+ status: state.status,
200
+ error: validation.reason
201
+ };
202
+ }
203
+ const currentStep = definition.steps[state.currentStepKey];
204
+ if (!currentStep) {
205
+ return {
206
+ success: false,
207
+ previousStepKey: state.currentStepKey,
208
+ currentStepKey: state.currentStepKey,
209
+ status: state.status,
210
+ error: `Current step ${state.currentStepKey} not found`
211
+ };
212
+ }
213
+ const transition = currentStep.transitions[action];
214
+ if (!transition) {
215
+ return {
216
+ success: false,
217
+ previousStepKey: state.currentStepKey,
218
+ currentStepKey: state.currentStepKey,
219
+ status: state.status,
220
+ error: `Transition for action ${action} not found`
221
+ };
222
+ }
223
+ const targetStepKey = typeof transition === "string" ? transition : transition.targetStepKey;
224
+ const targetStep = definition.steps[targetStepKey];
225
+ if (!targetStep) {
226
+ return {
227
+ success: false,
228
+ previousStepKey: state.currentStepKey,
229
+ currentStepKey: state.currentStepKey,
230
+ status: state.status,
231
+ error: `Target step ${targetStepKey} not found`
232
+ };
233
+ }
234
+ let newStatus = "RUNNING";
235
+ if (targetStep.type === "END") {
236
+ newStatus = "COMPLETED";
237
+ } else if (targetStep.type === "APPROVAL" || targetStep.type === "WAIT") {
238
+ newStatus = "WAITING";
239
+ }
240
+ return {
241
+ success: true,
242
+ previousStepKey: state.currentStepKey,
243
+ currentStepKey: targetStepKey,
244
+ status: newStatus
245
+ };
246
+ }
247
+ evaluateCondition(expression, contextData) {
248
+ try {
249
+ const match = expression.match(/^(\w+)\s*(>=|<=|>|<|===|!==|==|!=)\s*(.+)$/);
250
+ if (match) {
251
+ const [, prop, operator, value] = match;
252
+ if (!prop || !operator || value === undefined) {
253
+ return false;
254
+ }
255
+ const propValue = contextData[prop];
256
+ const compareValue = JSON.parse(value);
257
+ switch (operator) {
258
+ case ">":
259
+ return Number(propValue) > Number(compareValue);
260
+ case "<":
261
+ return Number(propValue) < Number(compareValue);
262
+ case ">=":
263
+ return Number(propValue) >= Number(compareValue);
264
+ case "<=":
265
+ return Number(propValue) <= Number(compareValue);
266
+ case "===":
267
+ case "==":
268
+ return propValue === compareValue;
269
+ case "!==":
270
+ case "!=":
271
+ return propValue !== compareValue;
272
+ }
273
+ }
274
+ if (expression in contextData) {
275
+ return Boolean(contextData[expression]);
276
+ }
277
+ return false;
278
+ } catch {
279
+ return false;
280
+ }
281
+ }
282
+ }
283
+ function createStateMachineEngine() {
284
+ return new BasicStateMachineEngine;
285
+ }
286
+ function buildStateMachineDefinition(workflow, steps) {
287
+ const stepMap = {};
288
+ for (const step of steps) {
289
+ stepMap[step.key] = {
290
+ key: step.key,
291
+ name: step.name,
292
+ type: step.type,
293
+ transitions: step.transitions,
294
+ approvalMode: step.approvalMode,
295
+ allowedRoles: step.approverRoles,
296
+ timeoutSeconds: step.timeoutSeconds,
297
+ conditionExpression: step.conditionExpression
298
+ };
299
+ }
300
+ const startStep = steps.find((s) => s.type === "START");
301
+ const initialStepKey = startStep?.key ?? steps[0]?.key ?? "";
302
+ return {
303
+ key: workflow.key,
304
+ name: workflow.name,
305
+ version: workflow.version,
306
+ initialStepKey,
307
+ steps: stepMap
308
+ };
309
+ }
310
+ function createInitialState(definition, contextData = {}) {
311
+ return {
312
+ currentStepKey: definition.initialStepKey,
313
+ status: "RUNNING",
314
+ contextData,
315
+ history: []
316
+ };
317
+ }
318
+
319
+ // src/approval/approval.schema.ts
320
+ import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
321
+ var ApprovalRequestModel = defineSchemaModel2({
322
+ name: "ApprovalRequestModel",
323
+ description: "An approval request",
324
+ fields: {
325
+ id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
326
+ workflowInstanceId: {
327
+ type: ScalarTypeEnum2.String_unsecure(),
328
+ isOptional: false
329
+ },
330
+ stepExecutionId: {
331
+ type: ScalarTypeEnum2.String_unsecure(),
332
+ isOptional: false
333
+ },
334
+ approverId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
335
+ approverRole: {
336
+ type: ScalarTypeEnum2.String_unsecure(),
337
+ isOptional: true
338
+ },
339
+ title: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
340
+ description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
341
+ status: { type: ApprovalStatusEnum, isOptional: false },
342
+ decision: { type: ApprovalDecisionEnum, isOptional: true },
343
+ decisionComment: {
344
+ type: ScalarTypeEnum2.String_unsecure(),
345
+ isOptional: true
346
+ },
347
+ decidedAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
348
+ dueAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
349
+ contextSnapshot: { type: ScalarTypeEnum2.JSON(), isOptional: true },
350
+ sequenceOrder: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: false },
351
+ createdAt: { type: ScalarTypeEnum2.DateTime(), isOptional: false }
352
+ }
353
+ });
354
+ var ApprovalCommentModel = defineSchemaModel2({
355
+ name: "ApprovalCommentModel",
356
+ description: "A comment on an approval",
357
+ fields: {
358
+ id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
359
+ approvalRequestId: {
360
+ type: ScalarTypeEnum2.String_unsecure(),
361
+ isOptional: false
362
+ },
363
+ authorId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
364
+ content: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
365
+ isInternal: { type: ScalarTypeEnum2.Boolean(), isOptional: false },
366
+ createdAt: { type: ScalarTypeEnum2.DateTime(), isOptional: false }
367
+ }
368
+ });
369
+
370
+ // src/approval/approval.operations.ts
371
+ import {
372
+ defineCommand,
373
+ defineQuery
374
+ } from "@contractspec/lib.contracts/operations";
375
+ import { defineSchemaModel as defineSchemaModel3, ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
376
+ var OWNERS = ["@example.workflow-system"];
377
+ var SubmitDecisionContract = defineCommand({
378
+ meta: {
379
+ key: "workflow.approval.decide",
380
+ version: "1.0.0",
381
+ stability: "stable",
382
+ owners: [...OWNERS],
383
+ tags: ["workflow", "approval", "decision"],
384
+ description: "Submit an approval decision (approve/reject).",
385
+ goal: "Allow approvers to make decisions on requests.",
386
+ context: "Approval inbox, workflow detail."
387
+ },
388
+ io: {
389
+ input: defineSchemaModel3({
390
+ name: "ApproveRejectInput",
391
+ fields: {
392
+ requestId: {
393
+ type: ScalarTypeEnum3.String_unsecure(),
394
+ isOptional: false
395
+ },
396
+ decision: { type: ApprovalDecisionEnum, isOptional: false },
397
+ comment: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true },
398
+ data: { type: ScalarTypeEnum3.JSON(), isOptional: true }
399
+ }
400
+ }),
401
+ output: ApprovalRequestModel
402
+ },
403
+ policy: { auth: "user" },
404
+ sideEffects: {
405
+ emits: [
406
+ {
407
+ key: "workflow.approval.decided",
408
+ version: "1.0.0",
409
+ when: "Decision is made",
410
+ payload: ApprovalRequestModel
411
+ }
412
+ ],
413
+ audit: ["workflow.approval.decided"]
414
+ },
415
+ acceptance: {
416
+ scenarios: [
417
+ {
418
+ key: "approve-request-happy-path",
419
+ given: ["Approval request is pending", "User is assignee"],
420
+ when: ["User approves request"],
421
+ then: ["Request is approved", "ApprovalDecided event is emitted"]
422
+ }
423
+ ],
424
+ examples: [
425
+ {
426
+ key: "approve-basic",
427
+ input: {
428
+ requestId: "req-123",
429
+ decision: "approve",
430
+ comment: "Looks good"
431
+ },
432
+ output: { id: "req-123", status: "approved" }
433
+ }
434
+ ]
435
+ }
436
+ });
437
+ var DelegateApprovalContract = defineCommand({
438
+ meta: {
439
+ key: "workflow.approval.delegate",
440
+ version: "1.0.0",
441
+ stability: "stable",
442
+ owners: [...OWNERS],
443
+ tags: ["workflow", "approval", "delegate"],
444
+ description: "Delegate an approval request to another user.",
445
+ goal: "Allow approvers to pass approval to others.",
446
+ context: "Approval inbox."
447
+ },
448
+ io: {
449
+ input: defineSchemaModel3({
450
+ name: "DelegateInput",
451
+ fields: {
452
+ requestId: {
453
+ type: ScalarTypeEnum3.String_unsecure(),
454
+ isOptional: false
455
+ },
456
+ delegateTo: {
457
+ type: ScalarTypeEnum3.String_unsecure(),
458
+ isOptional: false
459
+ },
460
+ reason: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true }
461
+ }
462
+ }),
463
+ output: ApprovalRequestModel
464
+ },
465
+ policy: { auth: "user" },
466
+ sideEffects: {
467
+ emits: [
468
+ {
469
+ key: "workflow.approval.delegated",
470
+ version: "1.0.0",
471
+ when: "Approval is delegated",
472
+ payload: ApprovalRequestModel
473
+ }
474
+ ],
475
+ audit: ["workflow.approval.delegated"]
476
+ },
477
+ acceptance: {
478
+ scenarios: [
479
+ {
480
+ key: "delegate-approval-happy-path",
481
+ given: ["Approval request is pending", "User is assignee"],
482
+ when: ["User delegates to another user"],
483
+ then: ["Assignee is updated", "ApprovalDelegated event is emitted"]
484
+ }
485
+ ],
486
+ examples: [
487
+ {
488
+ key: "delegate-to-manager",
489
+ input: {
490
+ requestId: "req-123",
491
+ delegateTo: "user-456",
492
+ reason: "Out of office"
493
+ },
494
+ output: { id: "req-123", assigneeId: "user-456" }
495
+ }
496
+ ]
497
+ }
498
+ });
499
+ var AddApprovalCommentContract = defineCommand({
500
+ meta: {
501
+ key: "workflow.approval.comment.add",
502
+ version: "1.0.0",
503
+ stability: "stable",
504
+ owners: [...OWNERS],
505
+ tags: ["workflow", "approval", "comment"],
506
+ description: "Add a comment to an approval request.",
507
+ goal: "Allow discussion on approval requests.",
508
+ context: "Approval detail view."
509
+ },
510
+ io: {
511
+ input: defineSchemaModel3({
512
+ name: "AddCommentInput",
513
+ fields: {
514
+ requestId: {
515
+ type: ScalarTypeEnum3.String_unsecure(),
516
+ isOptional: false
517
+ },
518
+ content: { type: ScalarTypeEnum3.NonEmptyString(), isOptional: false },
519
+ isInternal: { type: ScalarTypeEnum3.Boolean(), isOptional: true }
520
+ }
521
+ }),
522
+ output: ApprovalCommentModel
523
+ },
524
+ policy: { auth: "user" },
525
+ sideEffects: {
526
+ emits: [
527
+ {
528
+ key: "workflow.approval.comment.added",
529
+ version: "1.0.0",
530
+ when: "Comment is added",
531
+ payload: ApprovalCommentModel
532
+ }
533
+ ]
534
+ },
535
+ acceptance: {
536
+ scenarios: [
537
+ {
538
+ key: "add-comment-happy-path",
539
+ given: ["Approval request exists"],
540
+ when: ["User adds a comment"],
541
+ then: ["Comment is added", "CommentAdded event is emitted"]
542
+ }
543
+ ],
544
+ examples: [
545
+ {
546
+ key: "add-question",
547
+ input: {
548
+ requestId: "req-123",
549
+ content: "Can you clarify budget?",
550
+ isInternal: false
551
+ },
552
+ output: { id: "com-789", content: "Can you clarify budget?" }
553
+ }
554
+ ]
555
+ }
556
+ });
557
+ var ListMyApprovalsContract = defineQuery({
558
+ meta: {
559
+ key: "workflow.approval.list.mine",
560
+ version: "1.0.0",
561
+ stability: "stable",
562
+ owners: [...OWNERS],
563
+ tags: ["workflow", "approval", "list", "inbox"],
564
+ description: "List approval requests assigned to current user.",
565
+ goal: "Show pending approvals in user inbox.",
566
+ context: "Approval inbox, dashboard widget."
567
+ },
568
+ io: {
569
+ input: defineSchemaModel3({
570
+ name: "ListMyApprovalsInput",
571
+ fields: {
572
+ status: { type: ApprovalStatusEnum, isOptional: true },
573
+ limit: {
574
+ type: ScalarTypeEnum3.Int_unsecure(),
575
+ isOptional: true,
576
+ defaultValue: 20
577
+ },
578
+ offset: {
579
+ type: ScalarTypeEnum3.Int_unsecure(),
580
+ isOptional: true,
581
+ defaultValue: 0
582
+ }
583
+ }
584
+ }),
585
+ output: defineSchemaModel3({
586
+ name: "ListMyApprovalsOutput",
587
+ fields: {
588
+ requests: {
589
+ type: ApprovalRequestModel,
590
+ isArray: true,
591
+ isOptional: false
592
+ },
593
+ total: { type: ScalarTypeEnum3.Int_unsecure(), isOptional: false },
594
+ pendingCount: {
595
+ type: ScalarTypeEnum3.Int_unsecure(),
596
+ isOptional: false
597
+ }
598
+ }
599
+ })
600
+ },
601
+ policy: { auth: "user" },
602
+ acceptance: {
603
+ scenarios: [
604
+ {
605
+ key: "list-approvals-happy-path",
606
+ given: ["User has assigned approvals"],
607
+ when: ["User lists approvals"],
608
+ then: ["List of requests is returned"]
609
+ }
610
+ ],
611
+ examples: [
612
+ {
613
+ key: "list-pending",
614
+ input: { status: "pending", limit: 10 },
615
+ output: { requests: [], total: 2, pendingCount: 2 }
616
+ }
617
+ ]
618
+ }
619
+ });
620
+ var GetApprovalContract = defineQuery({
621
+ meta: {
622
+ key: "workflow.approval.get",
623
+ version: "1.0.0",
624
+ stability: "stable",
625
+ owners: [...OWNERS],
626
+ tags: ["workflow", "approval", "get"],
627
+ description: "Get an approval request with details.",
628
+ goal: "View approval request details.",
629
+ context: "Approval detail view."
630
+ },
631
+ io: {
632
+ input: defineSchemaModel3({
633
+ name: "GetApprovalInput",
634
+ fields: {
635
+ requestId: {
636
+ type: ScalarTypeEnum3.String_unsecure(),
637
+ isOptional: false
638
+ }
639
+ }
640
+ }),
641
+ output: ApprovalRequestModel
642
+ },
643
+ policy: { auth: "user" },
644
+ acceptance: {
645
+ scenarios: [
646
+ {
647
+ key: "get-approval-happy-path",
648
+ given: ["Approval request exists"],
649
+ when: ["User requests approval details"],
650
+ then: ["Approval details are returned"]
651
+ }
652
+ ],
653
+ examples: [
654
+ {
655
+ key: "get-basic",
656
+ input: { requestId: "req-123" },
657
+ output: { id: "req-123", status: "pending" }
658
+ }
659
+ ]
660
+ }
661
+ });
662
+ // src/handlers/workflow.handlers.ts
663
+ import { web } from "@contractspec/lib.runtime-sandbox";
664
+ var { generateId } = web;
665
+ function rowToDefinition(row) {
666
+ return {
667
+ id: row.id,
668
+ projectId: row.projectId,
669
+ organizationId: row.organizationId,
670
+ name: row.name,
671
+ description: row.description ?? undefined,
672
+ type: row.type,
673
+ status: row.status,
674
+ createdAt: new Date(row.createdAt),
675
+ updatedAt: new Date(row.updatedAt)
676
+ };
677
+ }
678
+ function rowToStep(row) {
679
+ return {
680
+ id: row.id,
681
+ definitionId: row.definitionId,
682
+ name: row.name,
683
+ description: row.description ?? undefined,
684
+ stepOrder: row.stepOrder,
685
+ type: row.type,
686
+ requiredRoles: row.requiredRoles ? JSON.parse(row.requiredRoles) : [],
687
+ autoApproveCondition: row.autoApproveCondition ?? undefined,
688
+ timeoutHours: row.timeoutHours ?? undefined,
689
+ createdAt: new Date(row.createdAt)
690
+ };
691
+ }
692
+ function rowToInstance(row) {
693
+ return {
694
+ id: row.id,
695
+ projectId: row.projectId,
696
+ definitionId: row.definitionId,
697
+ status: row.status,
698
+ currentStepId: row.currentStepId ?? undefined,
699
+ data: row.data ? JSON.parse(row.data) : undefined,
700
+ requestedBy: row.requestedBy,
701
+ startedAt: new Date(row.startedAt),
702
+ completedAt: row.completedAt ? new Date(row.completedAt) : undefined
703
+ };
704
+ }
705
+ function rowToApproval(row) {
706
+ return {
707
+ id: row.id,
708
+ instanceId: row.instanceId,
709
+ stepId: row.stepId,
710
+ status: row.status,
711
+ actorId: row.actorId ?? undefined,
712
+ comment: row.comment ?? undefined,
713
+ decidedAt: row.decidedAt ? new Date(row.decidedAt) : undefined,
714
+ createdAt: new Date(row.createdAt)
715
+ };
716
+ }
717
+ function createWorkflowHandlers(db) {
718
+ async function listDefinitions(input) {
719
+ const { projectId, status, search, limit = 20, offset = 0 } = input;
720
+ let whereClause = "WHERE projectId = ?";
721
+ const params = [projectId];
722
+ if (status && status !== "all") {
723
+ whereClause += " AND status = ?";
724
+ params.push(status);
725
+ }
726
+ if (search) {
727
+ whereClause += " AND name LIKE ?";
728
+ params.push(`%${search}%`);
729
+ }
730
+ const countResult = (await db.query(`SELECT COUNT(*) as count FROM workflow_definition ${whereClause}`, params)).rows;
731
+ const total = countResult[0]?.count ?? 0;
732
+ const rows = (await db.query(`SELECT * FROM workflow_definition ${whereClause} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
733
+ return {
734
+ definitions: rows.map(rowToDefinition),
735
+ total
736
+ };
737
+ }
738
+ async function createDefinition(input, context) {
739
+ const id = generateId("wfdef");
740
+ const now = new Date().toISOString();
741
+ await db.execute(`INSERT INTO workflow_definition (id, projectId, organizationId, name, description, type, status, createdAt, updatedAt)
742
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
743
+ id,
744
+ context.projectId,
745
+ context.organizationId,
746
+ input.name,
747
+ input.description ?? null,
748
+ input.type ?? "APPROVAL",
749
+ "DRAFT",
750
+ now,
751
+ now
752
+ ]);
753
+ const rows = (await db.query(`SELECT * FROM workflow_definition WHERE id = ?`, [id])).rows;
754
+ return rowToDefinition(rows[0]);
755
+ }
756
+ async function addStep(input) {
757
+ const id = generateId("wfstep");
758
+ const now = new Date().toISOString();
759
+ const maxOrderResult = (await db.query(`SELECT MAX(stepOrder) as maxOrder FROM workflow_step WHERE definitionId = ?`, [input.definitionId])).rows;
760
+ const nextOrder = (maxOrderResult[0]?.maxOrder ?? 0) + 1;
761
+ await db.execute(`INSERT INTO workflow_step (id, definitionId, name, description, stepOrder, type, requiredRoles, autoApproveCondition, timeoutHours, createdAt)
762
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
763
+ id,
764
+ input.definitionId,
765
+ input.name,
766
+ input.description ?? null,
767
+ nextOrder,
768
+ input.type ?? "APPROVAL",
769
+ JSON.stringify(input.requiredRoles),
770
+ input.autoApproveCondition ?? null,
771
+ input.timeoutHours ?? null,
772
+ now
773
+ ]);
774
+ const rows = (await db.query(`SELECT * FROM workflow_step WHERE id = ?`, [id])).rows;
775
+ return rowToStep(rows[0]);
776
+ }
777
+ async function getSteps(definitionId) {
778
+ const rows = (await db.query(`SELECT * FROM workflow_step WHERE definitionId = ? ORDER BY stepOrder`, [definitionId])).rows;
779
+ return rows.map(rowToStep);
780
+ }
781
+ async function listInstances(input) {
782
+ const {
783
+ projectId,
784
+ definitionId,
785
+ status,
786
+ requestedBy,
787
+ limit = 20,
788
+ offset = 0
789
+ } = input;
790
+ let whereClause = "WHERE projectId = ?";
791
+ const params = [projectId];
792
+ if (definitionId) {
793
+ whereClause += " AND definitionId = ?";
794
+ params.push(definitionId);
795
+ }
796
+ if (status && status !== "all") {
797
+ whereClause += " AND status = ?";
798
+ params.push(status);
799
+ }
800
+ if (requestedBy) {
801
+ whereClause += " AND requestedBy = ?";
802
+ params.push(requestedBy);
803
+ }
804
+ const countResult = (await db.query(`SELECT COUNT(*) as count FROM workflow_instance ${whereClause}`, params)).rows;
805
+ const total = countResult[0]?.count ?? 0;
806
+ const rows = (await db.query(`SELECT * FROM workflow_instance ${whereClause} ORDER BY startedAt DESC LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
807
+ return {
808
+ instances: rows.map(rowToInstance),
809
+ total
810
+ };
811
+ }
812
+ async function startInstance(input, context) {
813
+ const id = generateId("wfinst");
814
+ const now = new Date().toISOString();
815
+ const steps = (await db.query(`SELECT * FROM workflow_step WHERE definitionId = ? ORDER BY stepOrder LIMIT 1`, [input.definitionId])).rows;
816
+ const firstStepId = steps[0]?.id ?? null;
817
+ await db.execute(`INSERT INTO workflow_instance (id, projectId, definitionId, status, currentStepId, data, requestedBy, startedAt)
818
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
819
+ id,
820
+ context.projectId,
821
+ input.definitionId,
822
+ firstStepId ? "IN_PROGRESS" : "PENDING",
823
+ firstStepId,
824
+ input.data ? JSON.stringify(input.data) : null,
825
+ context.requestedBy,
826
+ now
827
+ ]);
828
+ if (firstStepId) {
829
+ await db.execute(`INSERT INTO workflow_approval (id, instanceId, stepId, status, createdAt)
830
+ VALUES (?, ?, ?, ?, ?)`, [generateId("wfappr"), id, firstStepId, "PENDING", now]);
831
+ }
832
+ const rows = (await db.query(`SELECT * FROM workflow_instance WHERE id = ?`, [id])).rows;
833
+ return rowToInstance(rows[0]);
834
+ }
835
+ async function approveStep(input, context) {
836
+ const now = new Date().toISOString();
837
+ const instances = (await db.query(`SELECT * FROM workflow_instance WHERE id = ?`, [
838
+ input.instanceId
839
+ ])).rows;
840
+ if (!instances[0]) {
841
+ throw new Error("NOT_FOUND");
842
+ }
843
+ const instance = instances[0];
844
+ await db.execute(`UPDATE workflow_approval SET status = 'APPROVED', actorId = ?, comment = ?, decidedAt = ?
845
+ WHERE instanceId = ? AND stepId = ? AND status = 'PENDING'`, [
846
+ context.actorId,
847
+ input.comment ?? null,
848
+ now,
849
+ input.instanceId,
850
+ instance.currentStepId
851
+ ]);
852
+ const currentStep = (await db.query(`SELECT * FROM workflow_step WHERE id = ?`, [
853
+ instance.currentStepId
854
+ ])).rows;
855
+ const nextSteps = (await db.query(`SELECT * FROM workflow_step WHERE definitionId = ? AND stepOrder > ? ORDER BY stepOrder LIMIT 1`, [instance.definitionId, currentStep[0]?.stepOrder ?? 0])).rows;
856
+ if (nextSteps[0]) {
857
+ await db.execute(`UPDATE workflow_instance SET currentStepId = ? WHERE id = ?`, [nextSteps[0].id, input.instanceId]);
858
+ await db.execute(`INSERT INTO workflow_approval (id, instanceId, stepId, status, createdAt)
859
+ VALUES (?, ?, ?, ?, ?)`, [
860
+ generateId("wfappr"),
861
+ input.instanceId,
862
+ nextSteps[0].id,
863
+ "PENDING",
864
+ now
865
+ ]);
866
+ } else {
867
+ await db.execute(`UPDATE workflow_instance SET status = 'COMPLETED', currentStepId = NULL, completedAt = ? WHERE id = ?`, [now, input.instanceId]);
868
+ }
869
+ const updated = (await db.query(`SELECT * FROM workflow_instance WHERE id = ?`, [
870
+ input.instanceId
871
+ ])).rows;
872
+ return rowToInstance(updated[0]);
873
+ }
874
+ async function rejectStep(input, context) {
875
+ const now = new Date().toISOString();
876
+ const instances = (await db.query(`SELECT * FROM workflow_instance WHERE id = ?`, [
877
+ input.instanceId
878
+ ])).rows;
879
+ if (!instances[0]) {
880
+ throw new Error("NOT_FOUND");
881
+ }
882
+ await db.execute(`UPDATE workflow_approval SET status = 'REJECTED', actorId = ?, comment = ?, decidedAt = ?
883
+ WHERE instanceId = ? AND stepId = ? AND status = 'PENDING'`, [
884
+ context.actorId,
885
+ input.reason,
886
+ now,
887
+ input.instanceId,
888
+ instances[0].currentStepId
889
+ ]);
890
+ await db.execute(`UPDATE workflow_instance SET status = 'REJECTED', completedAt = ? WHERE id = ?`, [now, input.instanceId]);
891
+ const updated = (await db.query(`SELECT * FROM workflow_instance WHERE id = ?`, [
892
+ input.instanceId
893
+ ])).rows;
894
+ return rowToInstance(updated[0]);
895
+ }
896
+ async function getApprovals(instanceId) {
897
+ const rows = (await db.query(`SELECT * FROM workflow_approval WHERE instanceId = ? ORDER BY createdAt`, [instanceId])).rows;
898
+ return rows.map(rowToApproval);
899
+ }
900
+ return {
901
+ listDefinitions,
902
+ createDefinition,
903
+ addStep,
904
+ getSteps,
905
+ listInstances,
906
+ startInstance,
907
+ approveStep,
908
+ rejectStep,
909
+ getApprovals
910
+ };
911
+ }
912
+
913
+ // src/workflow/workflow.enum.ts
914
+ import { defineEnum as defineEnum2 } from "@contractspec/lib.schema";
915
+ var WorkflowStatusEnum = defineEnum2("WorkflowStatus", [
916
+ "DRAFT",
917
+ "ACTIVE",
918
+ "DEPRECATED",
919
+ "ARCHIVED"
920
+ ]);
921
+ var TriggerTypeEnum = defineEnum2("WorkflowTriggerType", [
922
+ "MANUAL",
923
+ "EVENT",
924
+ "SCHEDULED",
925
+ "API"
926
+ ]);
927
+ var StepTypeEnum = defineEnum2("StepType", [
928
+ "START",
929
+ "APPROVAL",
930
+ "TASK",
931
+ "CONDITION",
932
+ "PARALLEL",
933
+ "WAIT",
934
+ "ACTION",
935
+ "END"
936
+ ]);
937
+ var ApprovalModeEnum = defineEnum2("ApprovalMode", [
938
+ "ANY",
939
+ "ALL",
940
+ "MAJORITY",
941
+ "SEQUENTIAL"
942
+ ]);
943
+
944
+ // src/workflow/workflow.schema.ts
945
+ import { defineSchemaModel as defineSchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
946
+ var WorkflowStepModel = defineSchemaModel4({
947
+ name: "WorkflowStepModel",
948
+ description: "A step in a workflow definition",
949
+ fields: {
950
+ id: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
951
+ key: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
952
+ name: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
953
+ description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
954
+ type: { type: StepTypeEnum, isOptional: false },
955
+ position: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: false },
956
+ transitions: { type: ScalarTypeEnum4.JSON(), isOptional: false },
957
+ approvalMode: { type: ApprovalModeEnum, isOptional: true },
958
+ approverRoles: {
959
+ type: ScalarTypeEnum4.String_unsecure(),
960
+ isArray: true,
961
+ isOptional: true
962
+ }
963
+ }
964
+ });
965
+ var WorkflowDefinitionModel = defineSchemaModel4({
966
+ name: "WorkflowDefinitionModel",
967
+ description: "A workflow definition",
968
+ fields: {
969
+ id: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
970
+ name: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
971
+ key: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
972
+ description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
973
+ version: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
974
+ status: { type: WorkflowStatusEnum, isOptional: false },
975
+ triggerType: { type: TriggerTypeEnum, isOptional: false },
976
+ initialStepId: {
977
+ type: ScalarTypeEnum4.String_unsecure(),
978
+ isOptional: true
979
+ },
980
+ featureFlagKey: {
981
+ type: ScalarTypeEnum4.String_unsecure(),
982
+ isOptional: true
983
+ },
984
+ organizationId: {
985
+ type: ScalarTypeEnum4.String_unsecure(),
986
+ isOptional: false
987
+ },
988
+ createdAt: { type: ScalarTypeEnum4.DateTime(), isOptional: false },
989
+ updatedAt: { type: ScalarTypeEnum4.DateTime(), isOptional: false },
990
+ steps: { type: WorkflowStepModel, isArray: true, isOptional: true }
991
+ }
992
+ });
993
+ var CreateWorkflowInputModel = defineSchemaModel4({
994
+ name: "CreateWorkflowInput",
995
+ description: "Input for creating a workflow definition",
996
+ fields: {
997
+ name: { type: ScalarTypeEnum4.NonEmptyString(), isOptional: false },
998
+ key: { type: ScalarTypeEnum4.NonEmptyString(), isOptional: false },
999
+ description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
1000
+ triggerType: { type: TriggerTypeEnum, isOptional: true },
1001
+ triggerConfig: { type: ScalarTypeEnum4.JSON(), isOptional: true },
1002
+ featureFlagKey: {
1003
+ type: ScalarTypeEnum4.String_unsecure(),
1004
+ isOptional: true
1005
+ },
1006
+ settings: { type: ScalarTypeEnum4.JSON(), isOptional: true }
1007
+ }
1008
+ });
1009
+ var UpdateWorkflowInputModel = defineSchemaModel4({
1010
+ name: "UpdateWorkflowInput",
1011
+ description: "Input for updating a workflow definition",
1012
+ fields: {
1013
+ workflowId: {
1014
+ type: ScalarTypeEnum4.String_unsecure(),
1015
+ isOptional: false
1016
+ },
1017
+ name: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
1018
+ description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
1019
+ triggerType: { type: TriggerTypeEnum, isOptional: true },
1020
+ triggerConfig: { type: ScalarTypeEnum4.JSON(), isOptional: true },
1021
+ featureFlagKey: {
1022
+ type: ScalarTypeEnum4.String_unsecure(),
1023
+ isOptional: true
1024
+ },
1025
+ settings: { type: ScalarTypeEnum4.JSON(), isOptional: true }
1026
+ }
1027
+ });
1028
+ var AddStepInputModel = defineSchemaModel4({
1029
+ name: "AddStepInput",
1030
+ description: "Input for adding a step to a workflow",
1031
+ fields: {
1032
+ workflowId: {
1033
+ type: ScalarTypeEnum4.String_unsecure(),
1034
+ isOptional: false
1035
+ },
1036
+ key: { type: ScalarTypeEnum4.NonEmptyString(), isOptional: false },
1037
+ name: { type: ScalarTypeEnum4.NonEmptyString(), isOptional: false },
1038
+ description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
1039
+ type: { type: StepTypeEnum, isOptional: false },
1040
+ position: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true },
1041
+ transitions: { type: ScalarTypeEnum4.JSON(), isOptional: false },
1042
+ approvalMode: { type: ApprovalModeEnum, isOptional: true },
1043
+ approverRoles: {
1044
+ type: ScalarTypeEnum4.String_unsecure(),
1045
+ isArray: true,
1046
+ isOptional: true
1047
+ },
1048
+ approverUserIds: {
1049
+ type: ScalarTypeEnum4.String_unsecure(),
1050
+ isArray: true,
1051
+ isOptional: true
1052
+ },
1053
+ timeoutSeconds: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true },
1054
+ slaSeconds: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true }
1055
+ }
1056
+ });
1057
+
1058
+ // src/workflow/workflow.operations.ts
1059
+ import {
1060
+ defineCommand as defineCommand2,
1061
+ defineQuery as defineQuery2
1062
+ } from "@contractspec/lib.contracts/operations";
1063
+ import { defineSchemaModel as defineSchemaModel5, ScalarTypeEnum as ScalarTypeEnum5 } from "@contractspec/lib.schema";
1064
+ var OWNERS2 = ["@example.workflow-system"];
1065
+ var CreateWorkflowContract = defineCommand2({
1066
+ meta: {
1067
+ key: "workflow.definition.create",
1068
+ version: "1.0.0",
1069
+ stability: "stable",
1070
+ owners: [...OWNERS2],
1071
+ tags: ["workflow", "definition", "create"],
1072
+ description: "Create a new workflow definition.",
1073
+ goal: "Allow users to define new workflow blueprints.",
1074
+ context: "Workflow designer, admin panel."
1075
+ },
1076
+ io: {
1077
+ input: CreateWorkflowInputModel,
1078
+ output: WorkflowDefinitionModel
1079
+ },
1080
+ policy: { auth: "user" },
1081
+ sideEffects: {
1082
+ emits: [
1083
+ {
1084
+ key: "workflow.definition.created",
1085
+ version: "1.0.0",
1086
+ when: "Workflow is created",
1087
+ payload: WorkflowDefinitionModel
1088
+ }
1089
+ ],
1090
+ audit: ["workflow.definition.created"]
1091
+ },
1092
+ acceptance: {
1093
+ scenarios: [
1094
+ {
1095
+ key: "create-workflow-happy-path",
1096
+ given: ["User is admin"],
1097
+ when: ["User creates new workflow definition"],
1098
+ then: [
1099
+ "Definition is created",
1100
+ "WorkflowDefinitionCreated event is emitted"
1101
+ ]
1102
+ }
1103
+ ],
1104
+ examples: [
1105
+ {
1106
+ key: "create-onboarding",
1107
+ input: {
1108
+ key: "onboarding-v1",
1109
+ name: "Employee Onboarding",
1110
+ version: "1.0.0"
1111
+ },
1112
+ output: { id: "def-123", status: "draft" }
1113
+ }
1114
+ ]
1115
+ }
1116
+ });
1117
+ var UpdateWorkflowContract = defineCommand2({
1118
+ meta: {
1119
+ key: "workflow.definition.update",
1120
+ version: "1.0.0",
1121
+ stability: "stable",
1122
+ owners: [...OWNERS2],
1123
+ tags: ["workflow", "definition", "update"],
1124
+ description: "Update an existing workflow definition.",
1125
+ goal: "Allow users to modify workflow blueprints.",
1126
+ context: "Workflow designer."
1127
+ },
1128
+ io: {
1129
+ input: UpdateWorkflowInputModel,
1130
+ output: WorkflowDefinitionModel
1131
+ },
1132
+ policy: { auth: "user" },
1133
+ sideEffects: {
1134
+ emits: [
1135
+ {
1136
+ key: "workflow.definition.updated",
1137
+ version: "1.0.0",
1138
+ when: "Workflow is updated",
1139
+ payload: WorkflowDefinitionModel
1140
+ }
1141
+ ],
1142
+ audit: ["workflow.definition.updated"]
1143
+ },
1144
+ acceptance: {
1145
+ scenarios: [
1146
+ {
1147
+ key: "update-workflow-happy-path",
1148
+ given: ["Workflow definition exists"],
1149
+ when: ["User updates definition"],
1150
+ then: [
1151
+ "Definition is updated",
1152
+ "WorkflowDefinitionUpdated event is emitted"
1153
+ ]
1154
+ }
1155
+ ],
1156
+ examples: [
1157
+ {
1158
+ key: "update-name",
1159
+ input: { workflowId: "def-123", name: "New Employee Onboarding" },
1160
+ output: { id: "def-123", name: "New Employee Onboarding" }
1161
+ }
1162
+ ]
1163
+ }
1164
+ });
1165
+ var AddStepContract = defineCommand2({
1166
+ meta: {
1167
+ key: "workflow.step.add",
1168
+ version: "1.0.0",
1169
+ stability: "stable",
1170
+ owners: [...OWNERS2],
1171
+ tags: ["workflow", "step", "add"],
1172
+ description: "Add a step to a workflow definition.",
1173
+ goal: "Build workflow structure step by step.",
1174
+ context: "Workflow designer."
1175
+ },
1176
+ io: {
1177
+ input: AddStepInputModel,
1178
+ output: WorkflowStepModel
1179
+ },
1180
+ policy: { auth: "user" },
1181
+ sideEffects: {
1182
+ emits: [
1183
+ {
1184
+ key: "workflow.step.added",
1185
+ version: "1.0.0",
1186
+ when: "Step is added",
1187
+ payload: WorkflowStepModel
1188
+ }
1189
+ ],
1190
+ audit: ["workflow.step.added"]
1191
+ },
1192
+ acceptance: {
1193
+ scenarios: [
1194
+ {
1195
+ key: "add-step-happy-path",
1196
+ given: ["Workflow definition exists"],
1197
+ when: ["User adds a step"],
1198
+ then: ["Step is added", "StepAdded event is emitted"]
1199
+ }
1200
+ ],
1201
+ examples: [
1202
+ {
1203
+ key: "add-approval-step",
1204
+ input: {
1205
+ workflowId: "def-123",
1206
+ stepKey: "approve-contract",
1207
+ type: "approval"
1208
+ },
1209
+ output: { id: "step-456", key: "approve-contract" }
1210
+ }
1211
+ ]
1212
+ }
1213
+ });
1214
+ var PublishWorkflowContract = defineCommand2({
1215
+ meta: {
1216
+ key: "workflow.definition.publish",
1217
+ version: "1.0.0",
1218
+ stability: "stable",
1219
+ owners: [...OWNERS2],
1220
+ tags: ["workflow", "definition", "publish"],
1221
+ description: "Publish a workflow definition to make it available for use.",
1222
+ goal: "Activate workflow for production use.",
1223
+ context: "Workflow designer, deployment."
1224
+ },
1225
+ io: {
1226
+ input: defineSchemaModel5({
1227
+ name: "PublishWorkflowInput",
1228
+ fields: {
1229
+ workflowId: {
1230
+ type: ScalarTypeEnum5.String_unsecure(),
1231
+ isOptional: false
1232
+ }
1233
+ }
1234
+ }),
1235
+ output: WorkflowDefinitionModel
1236
+ },
1237
+ policy: { auth: "user" },
1238
+ sideEffects: {
1239
+ emits: [
1240
+ {
1241
+ key: "workflow.definition.published",
1242
+ version: "1.0.0",
1243
+ when: "Workflow is published",
1244
+ payload: WorkflowDefinitionModel
1245
+ }
1246
+ ],
1247
+ audit: ["workflow.definition.published"]
1248
+ },
1249
+ acceptance: {
1250
+ scenarios: [
1251
+ {
1252
+ key: "publish-workflow-happy-path",
1253
+ given: ["Workflow definition is valid"],
1254
+ when: ["User publishes workflow"],
1255
+ then: ["Workflow becomes active", "WorkflowPublished event is emitted"]
1256
+ }
1257
+ ],
1258
+ examples: [
1259
+ {
1260
+ key: "publish-onboarding",
1261
+ input: { workflowId: "def-123" },
1262
+ output: { id: "def-123", status: "published" }
1263
+ }
1264
+ ]
1265
+ }
1266
+ });
1267
+ var ListWorkflowsContract = defineQuery2({
1268
+ meta: {
1269
+ key: "workflow.definition.list",
1270
+ version: "1.0.0",
1271
+ stability: "stable",
1272
+ owners: [...OWNERS2],
1273
+ tags: ["workflow", "definition", "list"],
1274
+ description: "List workflow definitions with filtering.",
1275
+ goal: "Browse and search available workflows.",
1276
+ context: "Workflow list, search."
1277
+ },
1278
+ io: {
1279
+ input: defineSchemaModel5({
1280
+ name: "ListWorkflowsInput",
1281
+ fields: {
1282
+ status: { type: WorkflowStatusEnum, isOptional: true },
1283
+ search: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true },
1284
+ limit: {
1285
+ type: ScalarTypeEnum5.Int_unsecure(),
1286
+ isOptional: true,
1287
+ defaultValue: 20
1288
+ },
1289
+ offset: {
1290
+ type: ScalarTypeEnum5.Int_unsecure(),
1291
+ isOptional: true,
1292
+ defaultValue: 0
1293
+ }
1294
+ }
1295
+ }),
1296
+ output: defineSchemaModel5({
1297
+ name: "ListWorkflowsOutput",
1298
+ fields: {
1299
+ workflows: {
1300
+ type: WorkflowDefinitionModel,
1301
+ isArray: true,
1302
+ isOptional: false
1303
+ },
1304
+ total: { type: ScalarTypeEnum5.Int_unsecure(), isOptional: false }
1305
+ }
1306
+ })
1307
+ },
1308
+ policy: { auth: "user" },
1309
+ acceptance: {
1310
+ scenarios: [
1311
+ {
1312
+ key: "list-workflows-happy-path",
1313
+ given: ["Workflow definitions exist"],
1314
+ when: ["User lists workflows"],
1315
+ then: ["List of workflows is returned"]
1316
+ }
1317
+ ],
1318
+ examples: [
1319
+ {
1320
+ key: "list-all",
1321
+ input: { limit: 10 },
1322
+ output: { workflows: [], total: 5 }
1323
+ }
1324
+ ]
1325
+ }
1326
+ });
1327
+ var GetWorkflowContract = defineQuery2({
1328
+ meta: {
1329
+ key: "workflow.definition.get",
1330
+ version: "1.0.0",
1331
+ stability: "stable",
1332
+ owners: [...OWNERS2],
1333
+ tags: ["workflow", "definition", "get"],
1334
+ description: "Get a workflow definition with all steps.",
1335
+ goal: "View workflow details.",
1336
+ context: "Workflow designer, detail view."
1337
+ },
1338
+ io: {
1339
+ input: defineSchemaModel5({
1340
+ name: "GetWorkflowInput",
1341
+ fields: {
1342
+ workflowId: {
1343
+ type: ScalarTypeEnum5.String_unsecure(),
1344
+ isOptional: false
1345
+ }
1346
+ }
1347
+ }),
1348
+ output: WorkflowDefinitionModel
1349
+ },
1350
+ policy: { auth: "user" },
1351
+ acceptance: {
1352
+ scenarios: [
1353
+ {
1354
+ key: "get-workflow-happy-path",
1355
+ given: ["Workflow definition exists"],
1356
+ when: ["User requests workflow details"],
1357
+ then: ["Workflow details are returned"]
1358
+ }
1359
+ ],
1360
+ examples: [
1361
+ {
1362
+ key: "get-details",
1363
+ input: { workflowId: "def-123" },
1364
+ output: { id: "def-123", name: "Employee Onboarding" }
1365
+ }
1366
+ ]
1367
+ }
1368
+ });
1369
+
1370
+ // src/workflow/workflow.event.ts
1371
+ import { defineEvent as defineEvent2, defineSchemaModel as defineSchemaModel6 } from "@contractspec/lib.contracts";
1372
+ import { ScalarTypeEnum as ScalarTypeEnum6 } from "@contractspec/lib.schema";
1373
+ var WorkflowDefinitionPayload = defineSchemaModel6({
1374
+ name: "WorkflowDefinitionEventPayload",
1375
+ description: "Payload for workflow definition events",
1376
+ fields: {
1377
+ workflowId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1378
+ key: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1379
+ name: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1380
+ version: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1381
+ organizationId: {
1382
+ type: ScalarTypeEnum6.String_unsecure(),
1383
+ isOptional: false
1384
+ },
1385
+ createdBy: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1386
+ timestamp: { type: ScalarTypeEnum6.DateTime(), isOptional: false }
1387
+ }
1388
+ });
1389
+ var StepAddedPayload = defineSchemaModel6({
1390
+ name: "StepAddedEventPayload",
1391
+ description: "Payload when a step is added",
1392
+ fields: {
1393
+ stepId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1394
+ workflowId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1395
+ stepKey: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1396
+ stepType: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
1397
+ position: { type: ScalarTypeEnum6.Int_unsecure(), isOptional: false },
1398
+ timestamp: { type: ScalarTypeEnum6.DateTime(), isOptional: false }
1399
+ }
1400
+ });
1401
+ var WorkflowCreatedEvent = defineEvent2({
1402
+ meta: {
1403
+ key: "workflow.definition.created",
1404
+ version: "1.0.0",
1405
+ description: "A new workflow definition has been created.",
1406
+ stability: "stable",
1407
+ owners: ["@workflow-team"],
1408
+ tags: ["workflow", "definition", "created"]
1409
+ },
1410
+ payload: WorkflowDefinitionPayload
1411
+ });
1412
+ var WorkflowUpdatedEvent = defineEvent2({
1413
+ meta: {
1414
+ key: "workflow.definition.updated",
1415
+ version: "1.0.0",
1416
+ description: "A workflow definition has been updated.",
1417
+ stability: "stable",
1418
+ owners: ["@workflow-team"],
1419
+ tags: ["workflow", "definition", "updated"]
1420
+ },
1421
+ payload: WorkflowDefinitionPayload
1422
+ });
1423
+ var WorkflowPublishedEvent = defineEvent2({
1424
+ meta: {
1425
+ key: "workflow.definition.published",
1426
+ version: "1.0.0",
1427
+ description: "A workflow definition has been published and is now active.",
1428
+ stability: "stable",
1429
+ owners: ["@workflow-team"],
1430
+ tags: ["workflow", "definition", "published"]
1431
+ },
1432
+ payload: WorkflowDefinitionPayload
1433
+ });
1434
+ var StepAddedEvent = defineEvent2({
1435
+ meta: {
1436
+ key: "workflow.step.added",
1437
+ version: "1.0.0",
1438
+ description: "A step has been added to a workflow definition.",
1439
+ stability: "stable",
1440
+ owners: ["@workflow-team"],
1441
+ tags: ["workflow", "step", "added"]
1442
+ },
1443
+ payload: StepAddedPayload
1444
+ });
1445
+ // src/instance/instance.enum.ts
1446
+ import { defineEnum as defineEnum3 } from "@contractspec/lib.schema";
1447
+ var InstanceStatusEnum = defineEnum3("InstanceStatus", [
1448
+ "PENDING",
1449
+ "RUNNING",
1450
+ "WAITING",
1451
+ "PAUSED",
1452
+ "COMPLETED",
1453
+ "CANCELLED",
1454
+ "FAILED",
1455
+ "TIMEOUT"
1456
+ ]);
1457
+
1458
+ // src/instance/instance.schema.ts
1459
+ import { defineSchemaModel as defineSchemaModel7, ScalarTypeEnum as ScalarTypeEnum7 } from "@contractspec/lib.schema";
1460
+ var WorkflowInstanceModel = defineSchemaModel7({
1461
+ name: "WorkflowInstanceModel",
1462
+ description: "A running workflow instance",
1463
+ fields: {
1464
+ id: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
1465
+ workflowDefinitionId: {
1466
+ type: ScalarTypeEnum7.String_unsecure(),
1467
+ isOptional: false
1468
+ },
1469
+ referenceId: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
1470
+ referenceType: {
1471
+ type: ScalarTypeEnum7.String_unsecure(),
1472
+ isOptional: true
1473
+ },
1474
+ status: { type: InstanceStatusEnum, isOptional: false },
1475
+ currentStepId: {
1476
+ type: ScalarTypeEnum7.String_unsecure(),
1477
+ isOptional: true
1478
+ },
1479
+ contextData: { type: ScalarTypeEnum7.JSON(), isOptional: true },
1480
+ triggeredBy: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
1481
+ organizationId: {
1482
+ type: ScalarTypeEnum7.String_unsecure(),
1483
+ isOptional: false
1484
+ },
1485
+ priority: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: false },
1486
+ dueAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true },
1487
+ outcome: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
1488
+ resultData: { type: ScalarTypeEnum7.JSON(), isOptional: true },
1489
+ errorMessage: {
1490
+ type: ScalarTypeEnum7.String_unsecure(),
1491
+ isOptional: true
1492
+ },
1493
+ createdAt: { type: ScalarTypeEnum7.DateTime(), isOptional: false },
1494
+ startedAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true },
1495
+ completedAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true }
1496
+ }
1497
+ });
1498
+ var StartWorkflowInputModel = defineSchemaModel7({
1499
+ name: "StartWorkflowInput",
1500
+ description: "Input for starting a workflow",
1501
+ fields: {
1502
+ workflowKey: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
1503
+ contextData: { type: ScalarTypeEnum7.JSON(), isOptional: true },
1504
+ referenceId: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
1505
+ referenceType: {
1506
+ type: ScalarTypeEnum7.String_unsecure(),
1507
+ isOptional: true
1508
+ },
1509
+ priority: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: true },
1510
+ dueAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true }
1511
+ }
1512
+ });
1513
+ var TransitionInputModel = defineSchemaModel7({
1514
+ name: "TransitionInput",
1515
+ description: "Input for transitioning a workflow",
1516
+ fields: {
1517
+ instanceId: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
1518
+ action: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
1519
+ data: { type: ScalarTypeEnum7.JSON(), isOptional: true },
1520
+ comment: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true }
1521
+ }
1522
+ });
1523
+ var TransitionResultModel = defineSchemaModel7({
1524
+ name: "TransitionResult",
1525
+ description: "Result of a workflow transition",
1526
+ fields: {
1527
+ success: { type: ScalarTypeEnum7.Boolean(), isOptional: false },
1528
+ instance: { type: WorkflowInstanceModel, isOptional: false },
1529
+ previousStepKey: {
1530
+ type: ScalarTypeEnum7.String_unsecure(),
1531
+ isOptional: true
1532
+ },
1533
+ currentStepKey: {
1534
+ type: ScalarTypeEnum7.String_unsecure(),
1535
+ isOptional: true
1536
+ },
1537
+ message: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true }
1538
+ }
1539
+ });
1540
+
1541
+ // src/instance/instance.operations.ts
1542
+ import {
1543
+ defineCommand as defineCommand3,
1544
+ defineQuery as defineQuery3
1545
+ } from "@contractspec/lib.contracts/operations";
1546
+ import { defineSchemaModel as defineSchemaModel8, ScalarTypeEnum as ScalarTypeEnum8 } from "@contractspec/lib.schema";
1547
+ var OWNERS3 = ["@example.workflow-system"];
1548
+ var StartWorkflowContract = defineCommand3({
1549
+ meta: {
1550
+ key: "workflow.instance.start",
1551
+ version: "1.0.0",
1552
+ stability: "stable",
1553
+ owners: [...OWNERS3],
1554
+ tags: ["workflow", "instance", "start"],
1555
+ description: "Start a new workflow instance.",
1556
+ goal: "Initiate a workflow for a business process.",
1557
+ context: "Order creation, request submission, etc."
1558
+ },
1559
+ io: {
1560
+ input: StartWorkflowInputModel,
1561
+ output: WorkflowInstanceModel
1562
+ },
1563
+ policy: { auth: "user" },
1564
+ sideEffects: {
1565
+ emits: [
1566
+ {
1567
+ key: "workflow.instance.started",
1568
+ version: "1.0.0",
1569
+ when: "Workflow starts",
1570
+ payload: WorkflowInstanceModel
1571
+ },
1572
+ {
1573
+ key: "workflow.step.entered",
1574
+ version: "1.0.0",
1575
+ when: "First step entered",
1576
+ payload: WorkflowInstanceModel
1577
+ }
1578
+ ],
1579
+ audit: ["workflow.instance.started"]
1580
+ },
1581
+ acceptance: {
1582
+ scenarios: [
1583
+ {
1584
+ key: "start-workflow-happy-path",
1585
+ given: ["Workflow definition exists"],
1586
+ when: ["User starts workflow"],
1587
+ then: ["Instance is created and started"]
1588
+ }
1589
+ ],
1590
+ examples: [
1591
+ {
1592
+ key: "start-onboarding",
1593
+ input: {
1594
+ workflowKey: "onboarding-v1",
1595
+ context: { employeeId: "emp-123" }
1596
+ },
1597
+ output: { id: "inst-456", status: "running" }
1598
+ }
1599
+ ]
1600
+ }
1601
+ });
1602
+ var TransitionWorkflowContract = defineCommand3({
1603
+ meta: {
1604
+ key: "workflow.instance.transition",
1605
+ version: "1.0.0",
1606
+ stability: "stable",
1607
+ owners: [...OWNERS3],
1608
+ tags: ["workflow", "instance", "transition", "state-machine"],
1609
+ description: "Transition a workflow instance to the next step.",
1610
+ goal: "Move workflow forward based on action.",
1611
+ context: "Task completion, approval decisions."
1612
+ },
1613
+ io: {
1614
+ input: TransitionInputModel,
1615
+ output: TransitionResultModel
1616
+ },
1617
+ policy: { auth: "user" },
1618
+ sideEffects: {
1619
+ emits: [
1620
+ {
1621
+ key: "workflow.step.exited",
1622
+ version: "1.0.0",
1623
+ when: "Step is exited",
1624
+ payload: WorkflowInstanceModel
1625
+ },
1626
+ {
1627
+ key: "workflow.step.entered",
1628
+ version: "1.0.0",
1629
+ when: "New step is entered",
1630
+ payload: WorkflowInstanceModel
1631
+ },
1632
+ {
1633
+ key: "workflow.instance.completed",
1634
+ version: "1.0.0",
1635
+ when: "Workflow reaches end",
1636
+ payload: WorkflowInstanceModel
1637
+ }
1638
+ ],
1639
+ audit: ["workflow.instance.transitioned"]
1640
+ },
1641
+ acceptance: {
1642
+ scenarios: [
1643
+ {
1644
+ key: "transition-workflow-happy-path",
1645
+ given: ["Workflow instance is waiting at step"],
1646
+ when: ["User provides input"],
1647
+ then: ["Instance moves to next step"]
1648
+ }
1649
+ ],
1650
+ examples: [
1651
+ {
1652
+ key: "complete-task",
1653
+ input: {
1654
+ instanceId: "inst-456",
1655
+ action: "complete",
1656
+ data: { approved: true }
1657
+ },
1658
+ output: { success: true, nextStep: "notify-hr" }
1659
+ }
1660
+ ]
1661
+ }
1662
+ });
1663
+ var PauseWorkflowContract = defineCommand3({
1664
+ meta: {
1665
+ key: "workflow.instance.pause",
1666
+ version: "1.0.0",
1667
+ stability: "stable",
1668
+ owners: [...OWNERS3],
1669
+ tags: ["workflow", "instance", "pause"],
1670
+ description: "Pause a running workflow instance.",
1671
+ goal: "Temporarily halt workflow execution.",
1672
+ context: "Administrative action, emergency stop."
1673
+ },
1674
+ io: {
1675
+ input: defineSchemaModel8({
1676
+ name: "PauseResumeInput",
1677
+ fields: {
1678
+ instanceId: {
1679
+ type: ScalarTypeEnum8.String_unsecure(),
1680
+ isOptional: false
1681
+ },
1682
+ reason: { type: ScalarTypeEnum8.String_unsecure(), isOptional: true }
1683
+ }
1684
+ }),
1685
+ output: WorkflowInstanceModel
1686
+ },
1687
+ policy: { auth: "user" },
1688
+ sideEffects: {
1689
+ emits: [
1690
+ {
1691
+ key: "workflow.instance.paused",
1692
+ version: "1.0.0",
1693
+ when: "Workflow is paused",
1694
+ payload: WorkflowInstanceModel
1695
+ }
1696
+ ],
1697
+ audit: ["workflow.instance.paused"]
1698
+ },
1699
+ acceptance: {
1700
+ scenarios: [
1701
+ {
1702
+ key: "pause-workflow-happy-path",
1703
+ given: ["Workflow is running"],
1704
+ when: ["Admin pauses workflow"],
1705
+ then: ["Instance status becomes PAUSED"]
1706
+ }
1707
+ ],
1708
+ examples: [
1709
+ {
1710
+ key: "pause-maintenance",
1711
+ input: { instanceId: "inst-456", reason: "System maintenance" },
1712
+ output: { id: "inst-456", status: "paused" }
1713
+ }
1714
+ ]
1715
+ }
1716
+ });
1717
+ var ResumeWorkflowContract = defineCommand3({
1718
+ meta: {
1719
+ key: "workflow.instance.resume",
1720
+ version: "1.0.0",
1721
+ stability: "stable",
1722
+ owners: [...OWNERS3],
1723
+ tags: ["workflow", "instance", "resume"],
1724
+ description: "Resume a paused workflow instance.",
1725
+ goal: "Continue workflow execution.",
1726
+ context: "Administrative action."
1727
+ },
1728
+ io: {
1729
+ input: defineSchemaModel8({
1730
+ name: "PauseResumeInput",
1731
+ fields: {
1732
+ instanceId: {
1733
+ type: ScalarTypeEnum8.String_unsecure(),
1734
+ isOptional: false
1735
+ },
1736
+ reason: { type: ScalarTypeEnum8.String_unsecure(), isOptional: true }
1737
+ }
1738
+ }),
1739
+ output: WorkflowInstanceModel
1740
+ },
1741
+ policy: { auth: "user" },
1742
+ sideEffects: {
1743
+ emits: [
1744
+ {
1745
+ key: "workflow.instance.resumed",
1746
+ version: "1.0.0",
1747
+ when: "Workflow is resumed",
1748
+ payload: WorkflowInstanceModel
1749
+ }
1750
+ ],
1751
+ audit: ["workflow.instance.resumed"]
1752
+ },
1753
+ acceptance: {
1754
+ scenarios: [
1755
+ {
1756
+ key: "resume-workflow-happy-path",
1757
+ given: ["Workflow is paused"],
1758
+ when: ["Admin resumes workflow"],
1759
+ then: ["Instance status becomes RUNNING"]
1760
+ }
1761
+ ],
1762
+ examples: [
1763
+ {
1764
+ key: "resume-normal",
1765
+ input: { instanceId: "inst-456", reason: "Issue resolved" },
1766
+ output: { id: "inst-456", status: "running" }
1767
+ }
1768
+ ]
1769
+ }
1770
+ });
1771
+ var CancelWorkflowContract = defineCommand3({
1772
+ meta: {
1773
+ key: "workflow.instance.cancel",
1774
+ version: "1.0.0",
1775
+ stability: "stable",
1776
+ owners: [...OWNERS3],
1777
+ tags: ["workflow", "instance", "cancel"],
1778
+ description: "Cancel a workflow instance.",
1779
+ goal: "Terminate workflow without completion.",
1780
+ context: "User request, system cancellation."
1781
+ },
1782
+ io: {
1783
+ input: defineSchemaModel8({
1784
+ name: "CancelWorkflowInput",
1785
+ fields: {
1786
+ instanceId: {
1787
+ type: ScalarTypeEnum8.String_unsecure(),
1788
+ isOptional: false
1789
+ },
1790
+ reason: {
1791
+ type: ScalarTypeEnum8.String_unsecure(),
1792
+ isOptional: false
1793
+ }
1794
+ }
1795
+ }),
1796
+ output: WorkflowInstanceModel
1797
+ },
1798
+ policy: { auth: "user" },
1799
+ sideEffects: {
1800
+ emits: [
1801
+ {
1802
+ key: "workflow.instance.cancelled",
1803
+ version: "1.0.0",
1804
+ when: "Workflow is cancelled",
1805
+ payload: WorkflowInstanceModel
1806
+ }
1807
+ ],
1808
+ audit: ["workflow.instance.cancelled"]
1809
+ },
1810
+ acceptance: {
1811
+ scenarios: [
1812
+ {
1813
+ key: "cancel-workflow-happy-path",
1814
+ given: ["Workflow is running"],
1815
+ when: ["User cancels workflow"],
1816
+ then: ["Instance status becomes CANCELLED"]
1817
+ }
1818
+ ],
1819
+ examples: [
1820
+ {
1821
+ key: "cancel-mistake",
1822
+ input: { instanceId: "inst-456", reason: "Created by mistake" },
1823
+ output: { id: "inst-456", status: "cancelled" }
1824
+ }
1825
+ ]
1826
+ }
1827
+ });
1828
+ var ListInstancesContract = defineQuery3({
1829
+ meta: {
1830
+ key: "workflow.instance.list",
1831
+ version: "1.0.0",
1832
+ stability: "stable",
1833
+ owners: [...OWNERS3],
1834
+ tags: ["workflow", "instance", "list"],
1835
+ description: "List workflow instances with filtering.",
1836
+ goal: "Browse and search running workflows.",
1837
+ context: "Dashboard, monitoring."
1838
+ },
1839
+ io: {
1840
+ input: defineSchemaModel8({
1841
+ name: "ListInstancesInput",
1842
+ fields: {
1843
+ workflowKey: {
1844
+ type: ScalarTypeEnum8.String_unsecure(),
1845
+ isOptional: true
1846
+ },
1847
+ status: { type: InstanceStatusEnum, isOptional: true },
1848
+ referenceType: {
1849
+ type: ScalarTypeEnum8.String_unsecure(),
1850
+ isOptional: true
1851
+ },
1852
+ referenceId: {
1853
+ type: ScalarTypeEnum8.String_unsecure(),
1854
+ isOptional: true
1855
+ },
1856
+ triggeredBy: {
1857
+ type: ScalarTypeEnum8.String_unsecure(),
1858
+ isOptional: true
1859
+ },
1860
+ limit: {
1861
+ type: ScalarTypeEnum8.Int_unsecure(),
1862
+ isOptional: true,
1863
+ defaultValue: 20
1864
+ },
1865
+ offset: {
1866
+ type: ScalarTypeEnum8.Int_unsecure(),
1867
+ isOptional: true,
1868
+ defaultValue: 0
1869
+ }
1870
+ }
1871
+ }),
1872
+ output: defineSchemaModel8({
1873
+ name: "ListInstancesOutput",
1874
+ fields: {
1875
+ instances: {
1876
+ type: WorkflowInstanceModel,
1877
+ isArray: true,
1878
+ isOptional: false
1879
+ },
1880
+ total: { type: ScalarTypeEnum8.Int_unsecure(), isOptional: false }
1881
+ }
1882
+ })
1883
+ },
1884
+ policy: { auth: "user" },
1885
+ acceptance: {
1886
+ scenarios: [
1887
+ {
1888
+ key: "list-instances-happy-path",
1889
+ given: ["Workflow instances exist"],
1890
+ when: ["User lists instances"],
1891
+ then: ["List of instances is returned"]
1892
+ }
1893
+ ],
1894
+ examples: [
1895
+ {
1896
+ key: "list-running",
1897
+ input: { status: "running", limit: 10 },
1898
+ output: { instances: [], total: 5 }
1899
+ }
1900
+ ]
1901
+ }
1902
+ });
1903
+ var GetInstanceContract = defineQuery3({
1904
+ meta: {
1905
+ key: "workflow.instance.get",
1906
+ version: "1.0.0",
1907
+ stability: "stable",
1908
+ owners: [...OWNERS3],
1909
+ tags: ["workflow", "instance", "get"],
1910
+ description: "Get a workflow instance with details.",
1911
+ goal: "View workflow instance details.",
1912
+ context: "Instance detail view."
1913
+ },
1914
+ io: {
1915
+ input: defineSchemaModel8({
1916
+ name: "GetInstanceInput",
1917
+ fields: {
1918
+ instanceId: {
1919
+ type: ScalarTypeEnum8.String_unsecure(),
1920
+ isOptional: false
1921
+ }
1922
+ }
1923
+ }),
1924
+ output: WorkflowInstanceModel
1925
+ },
1926
+ policy: { auth: "user" },
1927
+ acceptance: {
1928
+ scenarios: [
1929
+ {
1930
+ key: "get-instance-happy-path",
1931
+ given: ["Instance exists"],
1932
+ when: ["User requests instance details"],
1933
+ then: ["Instance details are returned"]
1934
+ }
1935
+ ],
1936
+ examples: [
1937
+ {
1938
+ key: "get-details",
1939
+ input: { instanceId: "inst-456" },
1940
+ output: { id: "inst-456", workflowKey: "onboarding-v1" }
1941
+ }
1942
+ ]
1943
+ }
1944
+ });
1945
+
1946
+ // src/instance/instance.event.ts
1947
+ import { defineEvent as defineEvent3, defineSchemaModel as defineSchemaModel9 } from "@contractspec/lib.contracts";
1948
+ import { ScalarTypeEnum as ScalarTypeEnum9 } from "@contractspec/lib.schema";
1949
+ var InstanceEventPayload = defineSchemaModel9({
1950
+ name: "InstanceEventPayload",
1951
+ description: "Base payload for instance events",
1952
+ fields: {
1953
+ instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1954
+ workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1955
+ workflowKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1956
+ status: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1957
+ referenceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
1958
+ referenceType: {
1959
+ type: ScalarTypeEnum9.String_unsecure(),
1960
+ isOptional: true
1961
+ },
1962
+ triggeredBy: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1963
+ organizationId: {
1964
+ type: ScalarTypeEnum9.String_unsecure(),
1965
+ isOptional: false
1966
+ },
1967
+ timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
1968
+ }
1969
+ });
1970
+ var StepTransitionPayload = defineSchemaModel9({
1971
+ name: "StepTransitionEventPayload",
1972
+ description: "Payload for step transition events",
1973
+ fields: {
1974
+ instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1975
+ workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1976
+ fromStepKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
1977
+ toStepKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1978
+ action: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
1979
+ executedBy: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1980
+ timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
1981
+ }
1982
+ });
1983
+ var InstanceCompletedPayload = defineSchemaModel9({
1984
+ name: "InstanceCompletedEventPayload",
1985
+ description: "Payload when instance completes",
1986
+ fields: {
1987
+ instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1988
+ workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1989
+ workflowKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1990
+ outcome: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
1991
+ referenceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
1992
+ referenceType: {
1993
+ type: ScalarTypeEnum9.String_unsecure(),
1994
+ isOptional: true
1995
+ },
1996
+ duration: { type: ScalarTypeEnum9.Int_unsecure(), isOptional: false },
1997
+ timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
1998
+ }
1999
+ });
2000
+ var InstanceStartedEvent = defineEvent3({
2001
+ meta: {
2002
+ key: "workflow.instance.started",
2003
+ version: "1.0.0",
2004
+ description: "A new workflow instance has been started.",
2005
+ stability: "stable",
2006
+ owners: ["@workflow-team"],
2007
+ tags: ["workflow", "instance", "started"]
2008
+ },
2009
+ payload: InstanceEventPayload
2010
+ });
2011
+ var StepEnteredEvent = defineEvent3({
2012
+ meta: {
2013
+ key: "workflow.step.entered",
2014
+ version: "1.0.0",
2015
+ description: "A workflow instance has entered a new step.",
2016
+ stability: "stable",
2017
+ owners: ["@workflow-team"],
2018
+ tags: ["workflow", "step", "entered"]
2019
+ },
2020
+ payload: StepTransitionPayload
2021
+ });
2022
+ var StepExitedEvent = defineEvent3({
2023
+ meta: {
2024
+ key: "workflow.step.exited",
2025
+ version: "1.0.0",
2026
+ description: "A workflow instance has exited a step.",
2027
+ stability: "stable",
2028
+ owners: ["@workflow-team"],
2029
+ tags: ["workflow", "step", "exited"]
2030
+ },
2031
+ payload: StepTransitionPayload
2032
+ });
2033
+ var InstanceCompletedEvent = defineEvent3({
2034
+ meta: {
2035
+ key: "workflow.instance.completed",
2036
+ version: "1.0.0",
2037
+ description: "A workflow instance has completed.",
2038
+ stability: "stable",
2039
+ owners: ["@workflow-team"],
2040
+ tags: ["workflow", "instance", "completed"]
2041
+ },
2042
+ payload: InstanceCompletedPayload
2043
+ });
2044
+ var InstanceCancelledEvent = defineEvent3({
2045
+ meta: {
2046
+ key: "workflow.instance.cancelled",
2047
+ version: "1.0.0",
2048
+ description: "A workflow instance has been cancelled.",
2049
+ stability: "stable",
2050
+ owners: ["@workflow-team"],
2051
+ tags: ["workflow", "instance", "cancelled"]
2052
+ },
2053
+ payload: InstanceEventPayload
2054
+ });
2055
+ var InstancePausedEvent = defineEvent3({
2056
+ meta: {
2057
+ key: "workflow.instance.paused",
2058
+ version: "1.0.0",
2059
+ description: "A workflow instance has been paused.",
2060
+ stability: "stable",
2061
+ owners: ["@workflow-team"],
2062
+ tags: ["workflow", "instance", "paused"]
2063
+ },
2064
+ payload: InstanceEventPayload
2065
+ });
2066
+ var InstanceResumedEvent = defineEvent3({
2067
+ meta: {
2068
+ key: "workflow.instance.resumed",
2069
+ version: "1.0.0",
2070
+ description: "A workflow instance has been resumed.",
2071
+ stability: "stable",
2072
+ owners: ["@workflow-team"],
2073
+ tags: ["workflow", "instance", "resumed"]
2074
+ },
2075
+ payload: InstanceEventPayload
2076
+ });
2077
+ var InstanceFailedEvent = defineEvent3({
2078
+ meta: {
2079
+ key: "workflow.instance.failed",
2080
+ version: "1.0.0",
2081
+ description: "A workflow instance has failed.",
2082
+ stability: "stable",
2083
+ owners: ["@workflow-team"],
2084
+ tags: ["workflow", "instance", "failed"]
2085
+ },
2086
+ payload: InstanceEventPayload
2087
+ });
2088
+ var InstanceTimedOutEvent = defineEvent3({
2089
+ meta: {
2090
+ key: "workflow.instance.timedOut",
2091
+ version: "1.0.0",
2092
+ description: "A workflow instance has timed out.",
2093
+ stability: "stable",
2094
+ owners: ["@workflow-team"],
2095
+ tags: ["workflow", "instance", "timeout"]
2096
+ },
2097
+ payload: InstanceEventPayload
2098
+ });
2099
+ // src/presentations/index.ts
2100
+ import { definePresentation, StabilityEnum } from "@contractspec/lib.contracts";
2101
+ var WorkflowDesignerPresentation = definePresentation({
2102
+ meta: {
2103
+ key: "workflow.designer",
2104
+ version: "1.0.0",
2105
+ title: "Workflow Designer",
2106
+ description: "Visual workflow designer with drag-and-drop steps",
2107
+ domain: "workflow-system",
2108
+ owners: ["@workflow-team"],
2109
+ tags: ["workflow", "designer", "admin"],
2110
+ stability: StabilityEnum.Experimental,
2111
+ goal: "Building and modifying workflow definitions",
2112
+ context: "Workflow administration and setup"
2113
+ },
2114
+ source: {
2115
+ type: "component",
2116
+ framework: "react",
2117
+ componentKey: "WorkflowDesigner",
2118
+ props: WorkflowDefinitionModel
2119
+ },
2120
+ targets: ["react"],
2121
+ policy: {
2122
+ flags: ["workflow.designer.enabled"]
2123
+ }
2124
+ });
2125
+ var WorkflowListPresentation = definePresentation({
2126
+ meta: {
2127
+ key: "workflow.definition.viewList",
2128
+ version: "1.0.0",
2129
+ title: "Workflow List",
2130
+ description: "List of workflow definitions with status and actions",
2131
+ domain: "workflow-system",
2132
+ owners: ["@workflow-team"],
2133
+ tags: ["workflow", "list", "admin"],
2134
+ stability: StabilityEnum.Experimental,
2135
+ goal: "Overview of all defined workflows",
2136
+ context: "Workflow management dashboard"
2137
+ },
2138
+ source: {
2139
+ type: "component",
2140
+ framework: "react",
2141
+ componentKey: "WorkflowDefinitionList",
2142
+ props: WorkflowDefinitionModel
2143
+ },
2144
+ targets: ["react", "markdown"],
2145
+ policy: {
2146
+ flags: ["workflow.enabled"]
2147
+ }
2148
+ });
2149
+ var WorkflowDetailPresentation = definePresentation({
2150
+ meta: {
2151
+ key: "workflow.definition.detail",
2152
+ version: "1.0.0",
2153
+ title: "Workflow Details",
2154
+ description: "Detailed view of a workflow definition with steps",
2155
+ domain: "workflow-system",
2156
+ owners: ["@workflow-team"],
2157
+ tags: ["workflow", "detail"],
2158
+ stability: StabilityEnum.Experimental,
2159
+ goal: "Viewing technical details of a workflow definition",
2160
+ context: "Workflow inspection and debugging"
2161
+ },
2162
+ source: {
2163
+ type: "component",
2164
+ framework: "react",
2165
+ componentKey: "WorkflowDefinitionDetail",
2166
+ props: WorkflowDefinitionModel
2167
+ },
2168
+ targets: ["react", "markdown"],
2169
+ policy: {
2170
+ flags: ["workflow.enabled"]
2171
+ }
2172
+ });
2173
+ var InstanceListPresentation = definePresentation({
2174
+ meta: {
2175
+ key: "workflow.instance.viewList",
2176
+ version: "1.0.0",
2177
+ title: "Instance List",
2178
+ description: "List of workflow instances with status and progress",
2179
+ domain: "workflow-system",
2180
+ owners: ["@workflow-team"],
2181
+ tags: ["workflow", "instance", "list"],
2182
+ stability: StabilityEnum.Experimental,
2183
+ goal: "Monitoring active and past workflow executions",
2184
+ context: "Operations monitoring"
2185
+ },
2186
+ source: {
2187
+ type: "component",
2188
+ framework: "react",
2189
+ componentKey: "WorkflowInstanceList",
2190
+ props: WorkflowInstanceModel
2191
+ },
2192
+ targets: ["react", "markdown"],
2193
+ policy: {
2194
+ flags: ["workflow.enabled"]
2195
+ }
2196
+ });
2197
+ var InstanceDetailPresentation = definePresentation({
2198
+ meta: {
2199
+ key: "workflow.instance.detail",
2200
+ version: "1.0.0",
2201
+ title: "Instance Details",
2202
+ description: "Detailed view of a workflow instance with step timeline",
2203
+ domain: "workflow-system",
2204
+ owners: ["@workflow-team"],
2205
+ tags: ["workflow", "instance", "detail", "timeline"],
2206
+ stability: StabilityEnum.Experimental,
2207
+ goal: "Detailed inspection of a specific workflow instance",
2208
+ context: "Case management and troubleshooting"
2209
+ },
2210
+ source: {
2211
+ type: "component",
2212
+ framework: "react",
2213
+ componentKey: "WorkflowInstanceDetail",
2214
+ props: WorkflowInstanceModel
2215
+ },
2216
+ targets: ["react", "markdown"],
2217
+ policy: {
2218
+ flags: ["workflow.enabled"]
2219
+ }
2220
+ });
2221
+ var ProgressTrackerPresentation = definePresentation({
2222
+ meta: {
2223
+ key: "workflow.instance.progress",
2224
+ version: "1.0.0",
2225
+ title: "Progress Tracker",
2226
+ description: "Visual progress tracker showing current step in workflow",
2227
+ domain: "workflow-system",
2228
+ owners: ["@workflow-team"],
2229
+ tags: ["workflow", "progress", "widget"],
2230
+ stability: StabilityEnum.Experimental,
2231
+ goal: "Quick view of current progress for a workflow",
2232
+ context: "Embedded progress indicator in entity views"
2233
+ },
2234
+ source: {
2235
+ type: "component",
2236
+ framework: "react",
2237
+ componentKey: "WorkflowProgressTracker",
2238
+ props: WorkflowInstanceModel
2239
+ },
2240
+ targets: ["react"],
2241
+ policy: {
2242
+ flags: ["workflow.enabled"]
2243
+ }
2244
+ });
2245
+ var ApprovalInboxPresentation = definePresentation({
2246
+ meta: {
2247
+ key: "workflow.approval.inbox",
2248
+ version: "1.0.0",
2249
+ title: "Approval Inbox",
2250
+ description: "Inbox showing pending approval requests for current user",
2251
+ domain: "workflow-system",
2252
+ owners: ["@workflow-team"],
2253
+ tags: ["workflow", "approval", "inbox"],
2254
+ stability: StabilityEnum.Experimental,
2255
+ goal: "Managing personal workload of approval requests",
2256
+ context: "Personal task management"
2257
+ },
2258
+ source: {
2259
+ type: "component",
2260
+ framework: "react",
2261
+ componentKey: "ApprovalInbox",
2262
+ props: ApprovalRequestModel
2263
+ },
2264
+ targets: ["react", "markdown"],
2265
+ policy: {
2266
+ flags: ["workflow.approvals.enabled"]
2267
+ }
2268
+ });
2269
+ var ApprovalDetailPresentation = definePresentation({
2270
+ meta: {
2271
+ key: "workflow.approval.detail",
2272
+ version: "1.0.0",
2273
+ title: "Approval Details",
2274
+ description: "Detailed approval request view with context and actions",
2275
+ domain: "workflow-system",
2276
+ owners: ["@workflow-team"],
2277
+ tags: ["workflow", "approval", "detail"],
2278
+ stability: StabilityEnum.Experimental,
2279
+ goal: "Decision support for an approval request",
2280
+ context: "Specific approval action"
2281
+ },
2282
+ source: {
2283
+ type: "component",
2284
+ framework: "react",
2285
+ componentKey: "ApprovalRequestDetail",
2286
+ props: ApprovalRequestModel
2287
+ },
2288
+ targets: ["react", "markdown"],
2289
+ policy: {
2290
+ flags: ["workflow.approvals.enabled"]
2291
+ }
2292
+ });
2293
+ var ApprovalFormPresentation = definePresentation({
2294
+ meta: {
2295
+ key: "workflow.approval.form",
2296
+ version: "1.0.0",
2297
+ title: "Approval Form",
2298
+ description: "Form for submitting approval decisions",
2299
+ domain: "workflow-system",
2300
+ owners: ["@workflow-team"],
2301
+ tags: ["workflow", "approval", "form"],
2302
+ stability: StabilityEnum.Experimental,
2303
+ goal: "Submitting a decision on an approval request",
2304
+ context: "Approval decision dialog"
2305
+ },
2306
+ source: {
2307
+ type: "component",
2308
+ framework: "react",
2309
+ componentKey: "ApprovalDecisionForm"
2310
+ },
2311
+ targets: ["react"],
2312
+ policy: {
2313
+ flags: ["workflow.approvals.enabled"]
2314
+ }
2315
+ });
2316
+ var PendingApprovalsBadgePresentation = definePresentation({
2317
+ meta: {
2318
+ key: "workflow.approval.badge",
2319
+ version: "1.0.0",
2320
+ title: "Pending Approvals Badge",
2321
+ description: "Badge showing count of pending approvals",
2322
+ domain: "workflow-system",
2323
+ owners: ["@workflow-team"],
2324
+ tags: ["workflow", "approval", "badge", "widget"],
2325
+ stability: StabilityEnum.Experimental,
2326
+ goal: "Visual notification of pending approvals",
2327
+ context: "Global navigation or sidebar"
2328
+ },
2329
+ source: {
2330
+ type: "component",
2331
+ framework: "react",
2332
+ componentKey: "PendingApprovalsBadge"
2333
+ },
2334
+ targets: ["react"],
2335
+ policy: {
2336
+ flags: ["workflow.approvals.enabled"]
2337
+ }
2338
+ });
2339
+ var WorkflowMetricsPresentation = definePresentation({
2340
+ meta: {
2341
+ key: "workflow.metrics",
2342
+ version: "1.0.0",
2343
+ title: "Workflow Metrics",
2344
+ description: "Dashboard widget showing workflow metrics and statistics",
2345
+ domain: "workflow-system",
2346
+ owners: ["@workflow-team"],
2347
+ tags: ["workflow", "metrics", "dashboard"],
2348
+ stability: StabilityEnum.Experimental,
2349
+ goal: "Monitoring throughput and bottlenecks",
2350
+ context: "System performance dashboard"
2351
+ },
2352
+ source: {
2353
+ type: "component",
2354
+ framework: "react",
2355
+ componentKey: "WorkflowMetricsDashboard"
2356
+ },
2357
+ targets: ["react", "markdown"],
2358
+ policy: {
2359
+ flags: ["workflow.metrics.enabled"]
2360
+ }
2361
+ });
2362
+ var WorkflowSystemPresentations = {
2363
+ WorkflowDesignerPresentation,
2364
+ WorkflowListPresentation,
2365
+ WorkflowDetailPresentation,
2366
+ InstanceListPresentation,
2367
+ InstanceDetailPresentation,
2368
+ ProgressTrackerPresentation,
2369
+ ApprovalInboxPresentation,
2370
+ ApprovalDetailPresentation,
2371
+ ApprovalFormPresentation,
2372
+ PendingApprovalsBadgePresentation,
2373
+ WorkflowMetricsPresentation
2374
+ };
2375
+
2376
+ // src/workflow-system.feature.ts
2377
+ import { defineFeature } from "@contractspec/lib.contracts";
2378
+ var WorkflowSystemFeature = defineFeature({
2379
+ meta: {
2380
+ key: "workflow-system",
2381
+ title: "Workflow & Approval System",
2382
+ description: "State machine-based workflow engine with role-based approvals, delegation, and escalation",
2383
+ domain: "workflow",
2384
+ owners: ["@workflow-team"],
2385
+ tags: ["workflow", "approval", "state-machine", "automation"],
2386
+ stability: "experimental",
2387
+ version: "1.0.0"
2388
+ },
2389
+ operations: [
2390
+ { key: "workflow.definition.create", version: "1.0.0" },
2391
+ { key: "workflow.definition.update", version: "1.0.0" },
2392
+ { key: "workflow.step.add", version: "1.0.0" },
2393
+ { key: "workflow.definition.publish", version: "1.0.0" },
2394
+ { key: "workflow.definition.list", version: "1.0.0" },
2395
+ { key: "workflow.definition.get", version: "1.0.0" },
2396
+ { key: "workflow.instance.start", version: "1.0.0" },
2397
+ { key: "workflow.instance.transition", version: "1.0.0" },
2398
+ { key: "workflow.instance.pause", version: "1.0.0" },
2399
+ { key: "workflow.instance.resume", version: "1.0.0" },
2400
+ { key: "workflow.instance.cancel", version: "1.0.0" },
2401
+ { key: "workflow.instance.list", version: "1.0.0" },
2402
+ { key: "workflow.instance.get", version: "1.0.0" },
2403
+ { key: "workflow.approval.decide", version: "1.0.0" },
2404
+ { key: "workflow.approval.delegate", version: "1.0.0" },
2405
+ { key: "workflow.approval.comment.add", version: "1.0.0" },
2406
+ { key: "workflow.approval.list.mine", version: "1.0.0" },
2407
+ { key: "workflow.approval.get", version: "1.0.0" }
2408
+ ],
2409
+ events: [
2410
+ { key: "workflow.definition.created", version: "1.0.0" },
2411
+ { key: "workflow.definition.updated", version: "1.0.0" },
2412
+ { key: "workflow.definition.published", version: "1.0.0" },
2413
+ { key: "workflow.step.added", version: "1.0.0" },
2414
+ { key: "workflow.instance.started", version: "1.0.0" },
2415
+ { key: "workflow.step.entered", version: "1.0.0" },
2416
+ { key: "workflow.step.exited", version: "1.0.0" },
2417
+ { key: "workflow.instance.completed", version: "1.0.0" },
2418
+ { key: "workflow.instance.cancelled", version: "1.0.0" },
2419
+ { key: "workflow.instance.paused", version: "1.0.0" },
2420
+ { key: "workflow.instance.resumed", version: "1.0.0" },
2421
+ { key: "workflow.instance.failed", version: "1.0.0" },
2422
+ { key: "workflow.instance.timedOut", version: "1.0.0" },
2423
+ { key: "workflow.approval.requested", version: "1.0.0" },
2424
+ { key: "workflow.approval.decided", version: "1.0.0" },
2425
+ { key: "workflow.approval.delegated", version: "1.0.0" },
2426
+ { key: "workflow.approval.escalated", version: "1.0.0" }
2427
+ ],
2428
+ presentations: [
2429
+ { key: "workflow.designer", version: "1.0.0" },
2430
+ { key: "workflow.definition.viewList", version: "1.0.0" },
2431
+ { key: "workflow.definition.detail", version: "1.0.0" },
2432
+ { key: "workflow.instance.viewList", version: "1.0.0" },
2433
+ { key: "workflow.instance.detail", version: "1.0.0" },
2434
+ { key: "workflow.instance.progress", version: "1.0.0" },
2435
+ { key: "workflow.approval.inbox", version: "1.0.0" },
2436
+ { key: "workflow.approval.detail", version: "1.0.0" },
2437
+ { key: "workflow.approval.form", version: "1.0.0" },
2438
+ { key: "workflow.approval.badge", version: "1.0.0" },
2439
+ { key: "workflow.metrics", version: "1.0.0" }
2440
+ ],
2441
+ opToPresentation: [
2442
+ {
2443
+ op: { key: "workflow.definition.list", version: "1.0.0" },
2444
+ pres: { key: "workflow.definition.viewList", version: "1.0.0" }
2445
+ },
2446
+ {
2447
+ op: { key: "workflow.instance.list", version: "1.0.0" },
2448
+ pres: { key: "workflow.instance.viewList", version: "1.0.0" }
2449
+ },
2450
+ {
2451
+ op: { key: "workflow.approval.list.mine", version: "1.0.0" },
2452
+ pres: { key: "workflow.approval.inbox", version: "1.0.0" }
2453
+ },
2454
+ {
2455
+ op: { key: "workflow.approval.decide", version: "1.0.0" },
2456
+ pres: { key: "workflow.approval.form", version: "1.0.0" }
2457
+ }
2458
+ ],
2459
+ presentationsTargets: [
2460
+ { key: "workflow.designer", version: "1.0.0", targets: ["react"] },
2461
+ {
2462
+ key: "workflow.definition.viewList",
2463
+ version: "1.0.0",
2464
+ targets: ["react", "markdown"]
2465
+ },
2466
+ {
2467
+ key: "workflow.definition.detail",
2468
+ version: "1.0.0",
2469
+ targets: ["react", "markdown"]
2470
+ },
2471
+ {
2472
+ key: "workflow.instance.viewList",
2473
+ version: "1.0.0",
2474
+ targets: ["react", "markdown"]
2475
+ },
2476
+ {
2477
+ key: "workflow.instance.detail",
2478
+ version: "1.0.0",
2479
+ targets: ["react", "markdown"]
2480
+ },
2481
+ { key: "workflow.instance.progress", version: "1.0.0", targets: ["react"] },
2482
+ {
2483
+ key: "workflow.approval.inbox",
2484
+ version: "1.0.0",
2485
+ targets: ["react", "markdown"]
2486
+ },
2487
+ {
2488
+ key: "workflow.approval.detail",
2489
+ version: "1.0.0",
2490
+ targets: ["react", "markdown"]
2491
+ },
2492
+ {
2493
+ key: "workflow.metrics",
2494
+ version: "1.0.0",
2495
+ targets: ["react", "markdown"]
2496
+ }
2497
+ ],
2498
+ capabilities: {
2499
+ requires: [
2500
+ { key: "identity", version: "1.0.0" },
2501
+ { key: "audit-trail", version: "1.0.0" },
2502
+ { key: "notifications", version: "1.0.0" },
2503
+ { key: "feature-flags", version: "1.0.0" }
2504
+ ],
2505
+ provides: [
2506
+ { key: "workflow", version: "1.0.0" },
2507
+ { key: "approval", version: "1.0.0" },
2508
+ { key: "state-machine", version: "1.0.0" }
2509
+ ]
2510
+ }
2511
+ });
2512
+
2513
+ // src/ui/renderers/workflow.markdown.ts
2514
+ var mockWorkflowDefinitions = [
2515
+ {
2516
+ id: "wf-1",
2517
+ name: "Purchase Approval",
2518
+ type: "APPROVAL",
2519
+ steps: [
2520
+ {
2521
+ id: "s1",
2522
+ name: "Manager Review",
2523
+ order: 1,
2524
+ requiredRoles: ["manager"]
2525
+ },
2526
+ {
2527
+ id: "s2",
2528
+ name: "Finance Review",
2529
+ order: 2,
2530
+ requiredRoles: ["finance"]
2531
+ },
2532
+ { id: "s3", name: "Final Approval", order: 3, requiredRoles: ["admin"] }
2533
+ ],
2534
+ status: "ACTIVE"
2535
+ },
2536
+ {
2537
+ id: "wf-2",
2538
+ name: "Leave Request",
2539
+ type: "APPROVAL",
2540
+ steps: [
2541
+ {
2542
+ id: "s1",
2543
+ name: "Supervisor Approval",
2544
+ order: 1,
2545
+ requiredRoles: ["supervisor"]
2546
+ },
2547
+ { id: "s2", name: "HR Review", order: 2, requiredRoles: ["hr"] }
2548
+ ],
2549
+ status: "ACTIVE"
2550
+ },
2551
+ {
2552
+ id: "wf-3",
2553
+ name: "Document Review",
2554
+ type: "SEQUENTIAL",
2555
+ steps: [
2556
+ { id: "s1", name: "Author Review", order: 1, requiredRoles: ["author"] },
2557
+ { id: "s2", name: "Peer Review", order: 2, requiredRoles: ["reviewer"] },
2558
+ { id: "s3", name: "Publish", order: 3, requiredRoles: ["publisher"] }
2559
+ ],
2560
+ status: "DRAFT"
2561
+ }
2562
+ ];
2563
+ var mockWorkflowInstances = [
2564
+ {
2565
+ id: "inst-1",
2566
+ definitionId: "wf-1",
2567
+ definitionName: "Purchase Approval",
2568
+ status: "IN_PROGRESS",
2569
+ currentStepId: "s2",
2570
+ startedAt: "2024-01-15T10:00:00Z",
2571
+ requestedBy: "John Doe"
2572
+ },
2573
+ {
2574
+ id: "inst-2",
2575
+ definitionId: "wf-1",
2576
+ definitionName: "Purchase Approval",
2577
+ status: "COMPLETED",
2578
+ currentStepId: null,
2579
+ startedAt: "2024-01-10T09:00:00Z",
2580
+ completedAt: "2024-01-12T14:00:00Z",
2581
+ requestedBy: "Jane Smith"
2582
+ },
2583
+ {
2584
+ id: "inst-3",
2585
+ definitionId: "wf-2",
2586
+ definitionName: "Leave Request",
2587
+ status: "PENDING",
2588
+ currentStepId: "s1",
2589
+ startedAt: "2024-01-16T08:00:00Z",
2590
+ requestedBy: "Bob Wilson"
2591
+ }
2592
+ ];
2593
+ var workflowDashboardMarkdownRenderer = {
2594
+ target: "markdown",
2595
+ render: async (desc) => {
2596
+ if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDashboard") {
2597
+ throw new Error("workflowDashboardMarkdownRenderer: not WorkflowDashboard");
2598
+ }
2599
+ const definitions = mockWorkflowDefinitions;
2600
+ const instances = mockWorkflowInstances;
2601
+ const activeDefinitions = definitions.filter((d) => d.status === "ACTIVE");
2602
+ const pendingInstances = instances.filter((i) => i.status === "PENDING");
2603
+ const inProgressInstances = instances.filter((i) => i.status === "IN_PROGRESS");
2604
+ const completedInstances = instances.filter((i) => i.status === "COMPLETED");
2605
+ const lines = [
2606
+ "# Workflow Dashboard",
2607
+ "",
2608
+ "> Workflow and approval management overview",
2609
+ "",
2610
+ "## Summary",
2611
+ "",
2612
+ "| Metric | Value |",
2613
+ "|--------|-------|",
2614
+ `| Active Workflows | ${activeDefinitions.length} |`,
2615
+ `| Pending Approvals | ${pendingInstances.length} |`,
2616
+ `| In Progress | ${inProgressInstances.length} |`,
2617
+ `| Completed | ${completedInstances.length} |`,
2618
+ "",
2619
+ "## Active Workflow Definitions",
2620
+ ""
2621
+ ];
2622
+ if (activeDefinitions.length === 0) {
2623
+ lines.push("_No active workflow definitions._");
2624
+ } else {
2625
+ lines.push("| Name | Type | Steps | Status |");
2626
+ lines.push("|------|------|-------|--------|");
2627
+ for (const def of activeDefinitions) {
2628
+ lines.push(`| ${def.name} | ${def.type} | ${def.steps.length} | ${def.status} |`);
2629
+ }
2630
+ }
2631
+ lines.push("");
2632
+ lines.push("## Recent Instances");
2633
+ lines.push("");
2634
+ if (instances.length === 0) {
2635
+ lines.push("_No workflow instances._");
2636
+ } else {
2637
+ lines.push("| Workflow | Requested By | Status | Started |");
2638
+ lines.push("|----------|--------------|--------|---------|");
2639
+ for (const inst of instances.slice(0, 10)) {
2640
+ const startedDate = new Date(inst.startedAt).toLocaleDateString();
2641
+ lines.push(`| ${inst.definitionName} | ${inst.requestedBy} | ${inst.status} | ${startedDate} |`);
2642
+ }
2643
+ }
2644
+ return {
2645
+ mimeType: "text/markdown",
2646
+ body: lines.join(`
2647
+ `)
2648
+ };
2649
+ }
2650
+ };
2651
+ var workflowDefinitionListMarkdownRenderer = {
2652
+ target: "markdown",
2653
+ render: async (desc) => {
2654
+ if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDefinitionList") {
2655
+ throw new Error("workflowDefinitionListMarkdownRenderer: not WorkflowDefinitionList");
2656
+ }
2657
+ const definitions = mockWorkflowDefinitions;
2658
+ const lines = [
2659
+ "# Workflow Definitions",
2660
+ "",
2661
+ "> Configure automated approval and process workflows",
2662
+ ""
2663
+ ];
2664
+ for (const def of definitions) {
2665
+ lines.push(`## ${def.name}`);
2666
+ lines.push("");
2667
+ lines.push(`**Type:** ${def.type} | **Status:** ${def.status}`);
2668
+ lines.push("");
2669
+ lines.push("### Steps");
2670
+ lines.push("");
2671
+ for (const step of def.steps) {
2672
+ lines.push(`${step.order}. **${step.name}** - Roles: ${step.requiredRoles.join(", ")}`);
2673
+ }
2674
+ lines.push("");
2675
+ }
2676
+ return {
2677
+ mimeType: "text/markdown",
2678
+ body: lines.join(`
2679
+ `)
2680
+ };
2681
+ }
2682
+ };
2683
+ var workflowInstanceDetailMarkdownRenderer = {
2684
+ target: "markdown",
2685
+ render: async (desc) => {
2686
+ if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowInstanceDetail") {
2687
+ throw new Error("workflowInstanceDetailMarkdownRenderer: not WorkflowInstanceDetail");
2688
+ }
2689
+ const instance = mockWorkflowInstances[0];
2690
+ if (!instance) {
2691
+ return {
2692
+ mimeType: "text/markdown",
2693
+ body: `# No Workflow Instances
2694
+
2695
+ No workflow instances available.`
2696
+ };
2697
+ }
2698
+ const definition = mockWorkflowDefinitions.find((d) => d.id === instance.definitionId);
2699
+ const lines = [
2700
+ `# Workflow: ${instance.definitionName}`,
2701
+ "",
2702
+ `**Instance ID:** ${instance.id}`,
2703
+ `**Status:** ${instance.status}`,
2704
+ `**Requested By:** ${instance.requestedBy}`,
2705
+ `**Started:** ${new Date(instance.startedAt).toLocaleString()}`,
2706
+ "",
2707
+ "## Steps Progress",
2708
+ ""
2709
+ ];
2710
+ if (definition) {
2711
+ for (const step of definition.steps) {
2712
+ const isCurrent = step.id === instance.currentStepId;
2713
+ const isCompleted = definition.steps.indexOf(step) < definition.steps.findIndex((s) => s.id === instance.currentStepId);
2714
+ let status = "⬜ Pending";
2715
+ if (isCompleted)
2716
+ status = "✅ Completed";
2717
+ if (isCurrent)
2718
+ status = "\uD83D\uDD04 In Progress";
2719
+ lines.push(`- ${status} **${step.name}**`);
2720
+ }
2721
+ }
2722
+ lines.push("");
2723
+ lines.push("## Actions");
2724
+ lines.push("");
2725
+ lines.push("- **Approve** - Move to next step");
2726
+ lines.push("- **Reject** - Reject and return");
2727
+ lines.push("- **Delegate** - Assign to another approver");
2728
+ return {
2729
+ mimeType: "text/markdown",
2730
+ body: lines.join(`
2731
+ `)
2732
+ };
2733
+ }
2734
+ };
2735
+ // src/ui/hooks/useWorkflowList.ts
2736
+ import { useCallback, useEffect, useState } from "react";
2737
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
2738
+ "use client";
2739
+ function useWorkflowList(projectId = "local-project") {
2740
+ const { handlers } = useTemplateRuntime();
2741
+ const workflow = handlers.workflow;
2742
+ const [definitions, setDefinitions] = useState([]);
2743
+ const [instances, setInstances] = useState([]);
2744
+ const [loading, setLoading] = useState(true);
2745
+ const [error, setError] = useState(null);
2746
+ const fetchData = useCallback(async () => {
2747
+ try {
2748
+ setLoading(true);
2749
+ setError(null);
2750
+ const [defResult, instResult] = await Promise.all([
2751
+ workflow.listDefinitions({ projectId, limit: 100 }),
2752
+ workflow.listInstances({ projectId, limit: 100 })
2753
+ ]);
2754
+ setDefinitions(defResult.definitions);
2755
+ setInstances(instResult.instances);
2756
+ } catch (err) {
2757
+ setError(err instanceof Error ? err : new Error("Failed to load workflows"));
2758
+ } finally {
2759
+ setLoading(false);
2760
+ }
2761
+ }, [handlers, projectId]);
2762
+ useEffect(() => {
2763
+ fetchData();
2764
+ }, [fetchData]);
2765
+ const stats = {
2766
+ totalDefinitions: definitions.length,
2767
+ activeDefinitions: definitions.filter((d) => d.status === "ACTIVE").length,
2768
+ totalInstances: instances.length,
2769
+ pendingInstances: instances.filter((i) => i.status === "PENDING").length,
2770
+ completedInstances: instances.filter((i) => i.status === "COMPLETED").length,
2771
+ rejectedInstances: instances.filter((i) => i.status === "REJECTED").length
2772
+ };
2773
+ return {
2774
+ definitions,
2775
+ instances,
2776
+ loading,
2777
+ error,
2778
+ stats,
2779
+ refetch: fetchData
2780
+ };
2781
+ }
2782
+
2783
+ // src/ui/WorkflowDashboard.tsx
2784
+ import { useState as useState2 } from "react";
2785
+ import {
2786
+ Button,
2787
+ ErrorState,
2788
+ LoaderBlock,
2789
+ StatCard,
2790
+ StatCardGroup
2791
+ } from "@contractspec/lib.design-system";
2792
+ import { jsxDEV } from "react/jsx-dev-runtime";
2793
+ "use client";
2794
+ var STATUS_COLORS = {
2795
+ ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
2796
+ DRAFT: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
2797
+ ARCHIVED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
2798
+ PENDING: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
2799
+ IN_PROGRESS: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400",
2800
+ COMPLETED: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
2801
+ REJECTED: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
2802
+ CANCELLED: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400"
2803
+ };
2804
+ function WorkflowDashboard() {
2805
+ const [activeTab, setActiveTab] = useState2("definitions");
2806
+ const { definitions, instances, loading, error, stats, refetch } = useWorkflowList();
2807
+ const tabs = [
2808
+ { id: "definitions", label: "Definitions", icon: "\uD83D\uDCCB" },
2809
+ { id: "instances", label: "Instances", icon: "\uD83D\uDD04" }
2810
+ ];
2811
+ if (loading) {
2812
+ return /* @__PURE__ */ jsxDEV(LoaderBlock, {
2813
+ label: "Loading Workflows..."
2814
+ }, undefined, false, undefined, this);
2815
+ }
2816
+ if (error) {
2817
+ return /* @__PURE__ */ jsxDEV(ErrorState, {
2818
+ title: "Failed to load Workflows",
2819
+ description: error.message,
2820
+ onRetry: refetch,
2821
+ retryLabel: "Retry"
2822
+ }, undefined, false, undefined, this);
2823
+ }
2824
+ return /* @__PURE__ */ jsxDEV("div", {
2825
+ className: "space-y-6",
2826
+ children: [
2827
+ /* @__PURE__ */ jsxDEV("div", {
2828
+ className: "flex items-center justify-between",
2829
+ children: [
2830
+ /* @__PURE__ */ jsxDEV("h2", {
2831
+ className: "text-2xl font-bold",
2832
+ children: "Workflow System"
2833
+ }, undefined, false, undefined, this),
2834
+ /* @__PURE__ */ jsxDEV(Button, {
2835
+ onClick: () => alert("Create workflow modal"),
2836
+ children: [
2837
+ /* @__PURE__ */ jsxDEV("span", {
2838
+ className: "mr-2",
2839
+ children: "+"
2840
+ }, undefined, false, undefined, this),
2841
+ " New Workflow"
2842
+ ]
2843
+ }, undefined, true, undefined, this)
2844
+ ]
2845
+ }, undefined, true, undefined, this),
2846
+ /* @__PURE__ */ jsxDEV(StatCardGroup, {
2847
+ children: [
2848
+ /* @__PURE__ */ jsxDEV(StatCard, {
2849
+ label: "Workflows",
2850
+ value: stats.totalDefinitions,
2851
+ hint: `${stats.activeDefinitions} active`
2852
+ }, undefined, false, undefined, this),
2853
+ /* @__PURE__ */ jsxDEV(StatCard, {
2854
+ label: "Instances",
2855
+ value: stats.totalInstances,
2856
+ hint: "total runs"
2857
+ }, undefined, false, undefined, this),
2858
+ /* @__PURE__ */ jsxDEV(StatCard, {
2859
+ label: "Pending",
2860
+ value: stats.pendingInstances,
2861
+ hint: "awaiting action"
2862
+ }, undefined, false, undefined, this),
2863
+ /* @__PURE__ */ jsxDEV(StatCard, {
2864
+ label: "Completed",
2865
+ value: stats.completedInstances,
2866
+ hint: "finished"
2867
+ }, undefined, false, undefined, this)
2868
+ ]
2869
+ }, undefined, true, undefined, this),
2870
+ /* @__PURE__ */ jsxDEV("nav", {
2871
+ className: "bg-muted flex gap-1 rounded-lg p-1",
2872
+ role: "tablist",
2873
+ children: tabs.map((tab) => /* @__PURE__ */ jsxDEV(Button, {
2874
+ type: "button",
2875
+ role: "tab",
2876
+ "aria-selected": activeTab === tab.id,
2877
+ onClick: () => setActiveTab(tab.id),
2878
+ className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
2879
+ children: [
2880
+ /* @__PURE__ */ jsxDEV("span", {
2881
+ children: tab.icon
2882
+ }, undefined, false, undefined, this),
2883
+ tab.label
2884
+ ]
2885
+ }, tab.id, true, undefined, this))
2886
+ }, undefined, false, undefined, this),
2887
+ /* @__PURE__ */ jsxDEV("div", {
2888
+ className: "min-h-[400px]",
2889
+ role: "tabpanel",
2890
+ children: [
2891
+ activeTab === "definitions" && /* @__PURE__ */ jsxDEV("div", {
2892
+ className: "border-border rounded-lg border",
2893
+ children: /* @__PURE__ */ jsxDEV("table", {
2894
+ className: "w-full",
2895
+ children: [
2896
+ /* @__PURE__ */ jsxDEV("thead", {
2897
+ className: "border-border bg-muted/30 border-b",
2898
+ children: /* @__PURE__ */ jsxDEV("tr", {
2899
+ children: [
2900
+ /* @__PURE__ */ jsxDEV("th", {
2901
+ className: "px-4 py-3 text-left text-sm font-medium",
2902
+ children: "Name"
2903
+ }, undefined, false, undefined, this),
2904
+ /* @__PURE__ */ jsxDEV("th", {
2905
+ className: "px-4 py-3 text-left text-sm font-medium",
2906
+ children: "Type"
2907
+ }, undefined, false, undefined, this),
2908
+ /* @__PURE__ */ jsxDEV("th", {
2909
+ className: "px-4 py-3 text-left text-sm font-medium",
2910
+ children: "Status"
2911
+ }, undefined, false, undefined, this),
2912
+ /* @__PURE__ */ jsxDEV("th", {
2913
+ className: "px-4 py-3 text-left text-sm font-medium",
2914
+ children: "Created"
2915
+ }, undefined, false, undefined, this)
2916
+ ]
2917
+ }, undefined, true, undefined, this)
2918
+ }, undefined, false, undefined, this),
2919
+ /* @__PURE__ */ jsxDEV("tbody", {
2920
+ className: "divide-border divide-y",
2921
+ children: [
2922
+ definitions.map((def) => /* @__PURE__ */ jsxDEV("tr", {
2923
+ className: "hover:bg-muted/50",
2924
+ children: [
2925
+ /* @__PURE__ */ jsxDEV("td", {
2926
+ className: "px-4 py-3",
2927
+ children: [
2928
+ /* @__PURE__ */ jsxDEV("div", {
2929
+ className: "font-medium",
2930
+ children: def.name
2931
+ }, undefined, false, undefined, this),
2932
+ /* @__PURE__ */ jsxDEV("div", {
2933
+ className: "text-muted-foreground text-sm",
2934
+ children: def.description
2935
+ }, undefined, false, undefined, this)
2936
+ ]
2937
+ }, undefined, true, undefined, this),
2938
+ /* @__PURE__ */ jsxDEV("td", {
2939
+ className: "px-4 py-3 font-mono text-sm",
2940
+ children: def.type
2941
+ }, undefined, false, undefined, this),
2942
+ /* @__PURE__ */ jsxDEV("td", {
2943
+ className: "px-4 py-3",
2944
+ children: /* @__PURE__ */ jsxDEV("span", {
2945
+ className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[def.status] ?? ""}`,
2946
+ children: def.status
2947
+ }, undefined, false, undefined, this)
2948
+ }, undefined, false, undefined, this),
2949
+ /* @__PURE__ */ jsxDEV("td", {
2950
+ className: "text-muted-foreground px-4 py-3 text-sm",
2951
+ children: def.createdAt.toLocaleDateString()
2952
+ }, undefined, false, undefined, this)
2953
+ ]
2954
+ }, def.id, true, undefined, this)),
2955
+ definitions.length === 0 && /* @__PURE__ */ jsxDEV("tr", {
2956
+ children: /* @__PURE__ */ jsxDEV("td", {
2957
+ colSpan: 4,
2958
+ className: "text-muted-foreground px-4 py-8 text-center",
2959
+ children: "No workflow definitions found"
2960
+ }, undefined, false, undefined, this)
2961
+ }, undefined, false, undefined, this)
2962
+ ]
2963
+ }, undefined, true, undefined, this)
2964
+ ]
2965
+ }, undefined, true, undefined, this)
2966
+ }, undefined, false, undefined, this),
2967
+ activeTab === "instances" && /* @__PURE__ */ jsxDEV("div", {
2968
+ className: "border-border rounded-lg border",
2969
+ children: /* @__PURE__ */ jsxDEV("table", {
2970
+ className: "w-full",
2971
+ children: [
2972
+ /* @__PURE__ */ jsxDEV("thead", {
2973
+ className: "border-border bg-muted/30 border-b",
2974
+ children: /* @__PURE__ */ jsxDEV("tr", {
2975
+ children: [
2976
+ /* @__PURE__ */ jsxDEV("th", {
2977
+ className: "px-4 py-3 text-left text-sm font-medium",
2978
+ children: "Instance ID"
2979
+ }, undefined, false, undefined, this),
2980
+ /* @__PURE__ */ jsxDEV("th", {
2981
+ className: "px-4 py-3 text-left text-sm font-medium",
2982
+ children: "Status"
2983
+ }, undefined, false, undefined, this),
2984
+ /* @__PURE__ */ jsxDEV("th", {
2985
+ className: "px-4 py-3 text-left text-sm font-medium",
2986
+ children: "Requested By"
2987
+ }, undefined, false, undefined, this),
2988
+ /* @__PURE__ */ jsxDEV("th", {
2989
+ className: "px-4 py-3 text-left text-sm font-medium",
2990
+ children: "Started"
2991
+ }, undefined, false, undefined, this)
2992
+ ]
2993
+ }, undefined, true, undefined, this)
2994
+ }, undefined, false, undefined, this),
2995
+ /* @__PURE__ */ jsxDEV("tbody", {
2996
+ className: "divide-border divide-y",
2997
+ children: [
2998
+ instances.map((inst) => /* @__PURE__ */ jsxDEV("tr", {
2999
+ className: "hover:bg-muted/50",
3000
+ children: [
3001
+ /* @__PURE__ */ jsxDEV("td", {
3002
+ className: "px-4 py-3 font-mono text-sm",
3003
+ children: inst.id
3004
+ }, undefined, false, undefined, this),
3005
+ /* @__PURE__ */ jsxDEV("td", {
3006
+ className: "px-4 py-3",
3007
+ children: /* @__PURE__ */ jsxDEV("span", {
3008
+ className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[inst.status] ?? ""}`,
3009
+ children: inst.status
3010
+ }, undefined, false, undefined, this)
3011
+ }, undefined, false, undefined, this),
3012
+ /* @__PURE__ */ jsxDEV("td", {
3013
+ className: "px-4 py-3 text-sm",
3014
+ children: inst.requestedBy
3015
+ }, undefined, false, undefined, this),
3016
+ /* @__PURE__ */ jsxDEV("td", {
3017
+ className: "text-muted-foreground px-4 py-3 text-sm",
3018
+ children: inst.startedAt.toLocaleDateString()
3019
+ }, undefined, false, undefined, this)
3020
+ ]
3021
+ }, inst.id, true, undefined, this)),
3022
+ instances.length === 0 && /* @__PURE__ */ jsxDEV("tr", {
3023
+ children: /* @__PURE__ */ jsxDEV("td", {
3024
+ colSpan: 4,
3025
+ className: "text-muted-foreground px-4 py-8 text-center",
3026
+ children: "No workflow instances found"
3027
+ }, undefined, false, undefined, this)
3028
+ }, undefined, false, undefined, this)
3029
+ ]
3030
+ }, undefined, true, undefined, this)
3031
+ ]
3032
+ }, undefined, true, undefined, this)
3033
+ }, undefined, false, undefined, this)
3034
+ ]
3035
+ }, undefined, true, undefined, this)
3036
+ ]
3037
+ }, undefined, true, undefined, this);
3038
+ }
3039
+
3040
+ // src/ui/hooks/index.ts
3041
+ "use client";
3042
+ export {
3043
+ workflowInstanceDetailMarkdownRenderer,
3044
+ workflowDefinitionListMarkdownRenderer,
3045
+ workflowDashboardMarkdownRenderer,
3046
+ useWorkflowList,
3047
+ mockDataStore,
3048
+ createWorkflowHandlers,
3049
+ createStateMachineEngine,
3050
+ createInitialState,
3051
+ buildStateMachineDefinition,
3052
+ WorkflowUpdatedEvent,
3053
+ WorkflowSystemPresentations,
3054
+ WorkflowSystemFeature,
3055
+ WorkflowStepModel,
3056
+ WorkflowStatusEnum,
3057
+ WorkflowPublishedEvent,
3058
+ WorkflowMetricsPresentation,
3059
+ WorkflowListPresentation,
3060
+ WorkflowInstanceModel,
3061
+ WorkflowDetailPresentation,
3062
+ WorkflowDesignerPresentation,
3063
+ WorkflowDefinitionModel,
3064
+ WorkflowDashboard,
3065
+ WorkflowCreatedEvent,
3066
+ UpdateWorkflowInputModel,
3067
+ UpdateWorkflowContract,
3068
+ TriggerTypeEnum,
3069
+ TransitionWorkflowContract,
3070
+ TransitionResultModel,
3071
+ TransitionInputModel,
3072
+ SubmitDecisionContract,
3073
+ StepTypeEnum,
3074
+ StepExitedEvent,
3075
+ StepEnteredEvent,
3076
+ StepAddedEvent,
3077
+ StartWorkflowInputModel,
3078
+ StartWorkflowContract,
3079
+ ResumeWorkflowContract,
3080
+ PublishWorkflowContract,
3081
+ ProgressTrackerPresentation,
3082
+ PendingApprovalsBadgePresentation,
3083
+ PauseWorkflowContract,
3084
+ ListWorkflowsContract,
3085
+ ListMyApprovalsContract,
3086
+ ListInstancesContract,
3087
+ InstanceTimedOutEvent,
3088
+ InstanceStatusEnum,
3089
+ InstanceStartedEvent,
3090
+ InstanceResumedEvent,
3091
+ InstancePausedEvent,
3092
+ InstanceListPresentation,
3093
+ InstanceFailedEvent,
3094
+ InstanceDetailPresentation,
3095
+ InstanceCompletedEvent,
3096
+ InstanceCancelledEvent,
3097
+ GetWorkflowContract,
3098
+ GetInstanceContract,
3099
+ GetApprovalContract,
3100
+ DelegateApprovalContract,
3101
+ CreateWorkflowInputModel,
3102
+ CreateWorkflowContract,
3103
+ CancelWorkflowContract,
3104
+ BasicStateMachineEngine,
3105
+ ApprovalStatusEnum,
3106
+ ApprovalRequestedEvent,
3107
+ ApprovalRequestModel,
3108
+ ApprovalModeEnum,
3109
+ ApprovalInboxPresentation,
3110
+ ApprovalFormPresentation,
3111
+ ApprovalEscalatedEvent,
3112
+ ApprovalDetailPresentation,
3113
+ ApprovalDelegatedEvent,
3114
+ ApprovalDecisionEnum,
3115
+ ApprovalDecidedEvent,
3116
+ ApprovalCommentModel,
3117
+ AddStepInputModel,
3118
+ AddStepContract,
3119
+ AddApprovalCommentContract
3120
+ };