@contractspec/example.crm-pipeline 3.7.6 → 3.7.10

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 (130) hide show
  1. package/.turbo/turbo-build.log +45 -42
  2. package/AGENTS.md +51 -33
  3. package/CHANGELOG.md +36 -0
  4. package/README.md +67 -148
  5. package/dist/browser/docs/crm-pipeline.docblock.js +1 -1
  6. package/dist/browser/docs/index.js +1 -1
  7. package/dist/browser/events/contact.event.js +1 -1
  8. package/dist/browser/events/deal.event.js +1 -1
  9. package/dist/browser/events/index.js +3 -3
  10. package/dist/browser/events/task.event.js +1 -1
  11. package/dist/browser/handlers/crm.handlers.js +13 -2
  12. package/dist/browser/handlers/index.js +13 -2
  13. package/dist/browser/index.js +680 -447
  14. package/dist/browser/ui/CrmDashboard.js +574 -352
  15. package/dist/browser/ui/CrmDealCard.js +5 -5
  16. package/dist/browser/ui/CrmPipelineBoard.js +13 -13
  17. package/dist/browser/ui/hooks/index.js +21 -10
  18. package/dist/browser/ui/hooks/useDealList.js +20 -9
  19. package/dist/browser/ui/hooks/useDealMutations.js +1 -1
  20. package/dist/browser/ui/index.js +683 -450
  21. package/dist/browser/ui/modals/CreateDealModal.js +12 -12
  22. package/dist/browser/ui/modals/DealActionsModal.js +21 -21
  23. package/dist/browser/ui/modals/index.js +33 -33
  24. package/dist/browser/ui/renderers/index.js +140 -118
  25. package/dist/browser/ui/renderers/pipeline.markdown.js +13 -2
  26. package/dist/browser/ui/renderers/pipeline.renderer.js +108 -97
  27. package/dist/browser/ui/tables/DealListTab.js +390 -0
  28. package/dist/deal/index.d.ts +2 -2
  29. package/dist/docs/crm-pipeline.docblock.js +1 -1
  30. package/dist/docs/index.js +1 -1
  31. package/dist/events/contact.event.js +1 -1
  32. package/dist/events/deal.event.js +1 -1
  33. package/dist/events/index.js +3 -3
  34. package/dist/events/task.event.js +1 -1
  35. package/dist/handlers/crm.handlers.d.ts +2 -0
  36. package/dist/handlers/crm.handlers.js +13 -2
  37. package/dist/handlers/index.d.ts +2 -2
  38. package/dist/handlers/index.js +13 -2
  39. package/dist/index.d.ts +3 -3
  40. package/dist/index.js +680 -447
  41. package/dist/node/docs/crm-pipeline.docblock.js +1 -1
  42. package/dist/node/docs/index.js +1 -1
  43. package/dist/node/events/contact.event.js +1 -1
  44. package/dist/node/events/deal.event.js +1 -1
  45. package/dist/node/events/index.js +3 -3
  46. package/dist/node/events/task.event.js +1 -1
  47. package/dist/node/handlers/crm.handlers.js +13 -2
  48. package/dist/node/handlers/index.js +13 -2
  49. package/dist/node/index.js +680 -447
  50. package/dist/node/ui/CrmDashboard.js +574 -352
  51. package/dist/node/ui/CrmDealCard.js +5 -5
  52. package/dist/node/ui/CrmPipelineBoard.js +13 -13
  53. package/dist/node/ui/hooks/index.js +21 -10
  54. package/dist/node/ui/hooks/useDealList.js +20 -9
  55. package/dist/node/ui/hooks/useDealMutations.js +1 -1
  56. package/dist/node/ui/index.js +683 -450
  57. package/dist/node/ui/modals/CreateDealModal.js +12 -12
  58. package/dist/node/ui/modals/DealActionsModal.js +21 -21
  59. package/dist/node/ui/modals/index.js +33 -33
  60. package/dist/node/ui/renderers/index.js +140 -118
  61. package/dist/node/ui/renderers/pipeline.markdown.js +13 -2
  62. package/dist/node/ui/renderers/pipeline.renderer.js +108 -97
  63. package/dist/node/ui/tables/DealListTab.js +390 -0
  64. package/dist/operations/index.d.ts +1 -1
  65. package/dist/ui/CrmDashboard.js +574 -352
  66. package/dist/ui/CrmDealCard.js +5 -5
  67. package/dist/ui/CrmPipelineBoard.js +13 -13
  68. package/dist/ui/hooks/index.d.ts +2 -2
  69. package/dist/ui/hooks/index.js +21 -10
  70. package/dist/ui/hooks/useDealList.d.ts +8 -2
  71. package/dist/ui/hooks/useDealList.js +20 -9
  72. package/dist/ui/hooks/useDealMutations.d.ts +9 -0
  73. package/dist/ui/hooks/useDealMutations.js +1 -1
  74. package/dist/ui/index.d.ts +3 -3
  75. package/dist/ui/index.js +683 -450
  76. package/dist/ui/modals/CreateDealModal.js +12 -12
  77. package/dist/ui/modals/DealActionsModal.js +21 -21
  78. package/dist/ui/modals/index.js +33 -33
  79. package/dist/ui/renderers/index.d.ts +1 -1
  80. package/dist/ui/renderers/index.js +140 -118
  81. package/dist/ui/renderers/pipeline.markdown.js +13 -2
  82. package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
  83. package/dist/ui/renderers/pipeline.renderer.js +108 -97
  84. package/dist/ui/tables/DealListTab.d.ts +20 -0
  85. package/dist/ui/tables/DealListTab.js +391 -0
  86. package/dist/ui/tables/DealListTab.smoke.test.d.ts +1 -0
  87. package/package.json +29 -14
  88. package/src/crm-pipeline.feature.ts +86 -86
  89. package/src/deal/deal.enum.ts +8 -8
  90. package/src/deal/deal.operation.ts +255 -255
  91. package/src/deal/deal.schema.ts +92 -92
  92. package/src/deal/deal.test-spec.ts +48 -48
  93. package/src/deal/index.ts +17 -19
  94. package/src/docs/crm-pipeline.docblock.ts +44 -44
  95. package/src/entities/company.entity.ts +52 -52
  96. package/src/entities/contact.entity.ts +67 -67
  97. package/src/entities/deal.entity.ts +134 -134
  98. package/src/entities/index.ts +27 -27
  99. package/src/entities/task.entity.ts +105 -105
  100. package/src/events/contact.event.ts +22 -22
  101. package/src/events/deal.event.ts +77 -77
  102. package/src/events/task.event.ts +19 -19
  103. package/src/example.ts +32 -32
  104. package/src/handlers/crm.handlers.ts +375 -357
  105. package/src/handlers/deal.handlers.ts +179 -179
  106. package/src/handlers/index.ts +18 -19
  107. package/src/handlers/mock-data.ts +167 -167
  108. package/src/index.ts +11 -11
  109. package/src/operations/index.ts +16 -16
  110. package/src/presentations/dashboard.presentation.ts +45 -45
  111. package/src/presentations/pipeline.presentation.ts +90 -90
  112. package/src/seeders/index.ts +26 -26
  113. package/src/shared/overlay-types.ts +23 -23
  114. package/src/ui/CrmDashboard.tsx +210 -279
  115. package/src/ui/CrmDealCard.tsx +64 -64
  116. package/src/ui/CrmPipelineBoard.tsx +105 -105
  117. package/src/ui/hooks/index.ts +3 -3
  118. package/src/ui/hooks/useDealList.ts +113 -85
  119. package/src/ui/hooks/useDealMutations.ts +151 -150
  120. package/src/ui/index.ts +5 -10
  121. package/src/ui/modals/CreateDealModal.tsx +217 -217
  122. package/src/ui/modals/DealActionsModal.tsx +390 -390
  123. package/src/ui/overlays/demo-overlays.ts +43 -43
  124. package/src/ui/renderers/index.ts +4 -3
  125. package/src/ui/renderers/pipeline.markdown.ts +165 -165
  126. package/src/ui/renderers/pipeline.renderer.tsx +17 -16
  127. package/src/ui/tables/DealListTab.smoke.test.tsx +149 -0
  128. package/src/ui/tables/DealListTab.tsx +276 -0
  129. package/tsconfig.json +7 -8
  130. package/tsdown.config.js +7 -3
@@ -4,18 +4,18 @@ import { defineEnum } from '@contractspec/lib.schema';
4
4
  * Deal status enum.
5
5
  */
6
6
  export const DealStatusEnum = defineEnum('DealStatus', [
7
- 'OPEN',
8
- 'WON',
9
- 'LOST',
10
- 'STALE',
7
+ 'OPEN',
8
+ 'WON',
9
+ 'LOST',
10
+ 'STALE',
11
11
  ]);
12
12
 
13
13
  /**
14
14
  * Deal status filter enum.
15
15
  */
16
16
  export const DealStatusFilterEnum = defineEnum('DealStatusFilter', [
17
- 'OPEN',
18
- 'WON',
19
- 'LOST',
20
- 'all',
17
+ 'OPEN',
18
+ 'WON',
19
+ 'LOST',
20
+ 'all',
21
21
  ]);
@@ -1,18 +1,18 @@
1
1
  import {
2
- defineCommand,
3
- defineQuery,
2
+ defineCommand,
3
+ defineQuery,
4
4
  } from '@contractspec/lib.contracts-spec/operations';
5
5
  import {
6
- DealModel,
7
- CreateDealInputModel,
8
- MoveDealInputModel,
9
- DealMovedPayloadModel,
10
- WinDealInputModel,
11
- DealWonPayloadModel,
12
- LoseDealInputModel,
13
- DealLostPayloadModel,
14
- ListDealsInputModel,
15
- ListDealsOutputModel,
6
+ CreateDealInputModel,
7
+ DealLostPayloadModel,
8
+ DealModel,
9
+ DealMovedPayloadModel,
10
+ DealWonPayloadModel,
11
+ ListDealsInputModel,
12
+ ListDealsOutputModel,
13
+ LoseDealInputModel,
14
+ MoveDealInputModel,
15
+ WinDealInputModel,
16
16
  } from './deal.schema';
17
17
 
18
18
  const OWNERS = ['@example.crm-pipeline'] as const;
@@ -21,271 +21,271 @@ const OWNERS = ['@example.crm-pipeline'] as const;
21
21
  * Create a new deal.
22
22
  */
23
23
  export const CreateDealContract = defineCommand({
24
- meta: {
25
- key: 'crm.deal.create',
26
- version: '1.0.0',
27
- stability: 'stable',
28
- owners: [...OWNERS],
29
- tags: ['crm', 'deal', 'create'],
30
- description: 'Create a new deal in the pipeline.',
31
- goal: 'Allow sales reps to create new opportunities.',
32
- context: 'Deal creation UI, quick add.',
33
- },
34
- io: {
35
- input: CreateDealInputModel,
36
- output: DealModel,
37
- },
38
- policy: {
39
- auth: 'user',
40
- },
41
- sideEffects: {
42
- emits: [
43
- {
44
- key: 'deal.created',
45
- version: '1.0.0',
46
- when: 'Deal is created',
47
- payload: DealModel,
48
- },
49
- ],
50
- audit: ['deal.created'],
51
- },
52
- acceptance: {
53
- scenarios: [
54
- {
55
- key: 'create-deal-happy-path',
56
- given: ['User is authenticated'],
57
- when: ['User creates a deal with valid data'],
58
- then: ['Deal is created', 'DealCreated event is emitted'],
59
- },
60
- ],
61
- examples: [
62
- {
63
- key: 'create-basic-deal',
64
- input: {
65
- title: 'Big Corp Q3 License',
66
- stageId: 'stage-lead',
67
- value: 50000,
68
- companyId: 'comp-123',
69
- },
70
- output: {
71
- id: 'deal-789',
72
- title: 'Big Corp Q3 License',
73
- status: 'open',
74
- },
75
- },
76
- ],
77
- },
24
+ meta: {
25
+ key: 'crm.deal.create',
26
+ version: '1.0.0',
27
+ stability: 'stable',
28
+ owners: [...OWNERS],
29
+ tags: ['crm', 'deal', 'create'],
30
+ description: 'Create a new deal in the pipeline.',
31
+ goal: 'Allow sales reps to create new opportunities.',
32
+ context: 'Deal creation UI, quick add.',
33
+ },
34
+ io: {
35
+ input: CreateDealInputModel,
36
+ output: DealModel,
37
+ },
38
+ policy: {
39
+ auth: 'user',
40
+ },
41
+ sideEffects: {
42
+ emits: [
43
+ {
44
+ key: 'deal.created',
45
+ version: '1.0.0',
46
+ when: 'Deal is created',
47
+ payload: DealModel,
48
+ },
49
+ ],
50
+ audit: ['deal.created'],
51
+ },
52
+ acceptance: {
53
+ scenarios: [
54
+ {
55
+ key: 'create-deal-happy-path',
56
+ given: ['User is authenticated'],
57
+ when: ['User creates a deal with valid data'],
58
+ then: ['Deal is created', 'DealCreated event is emitted'],
59
+ },
60
+ ],
61
+ examples: [
62
+ {
63
+ key: 'create-basic-deal',
64
+ input: {
65
+ title: 'Big Corp Q3 License',
66
+ stageId: 'stage-lead',
67
+ value: 50000,
68
+ companyId: 'comp-123',
69
+ },
70
+ output: {
71
+ id: 'deal-789',
72
+ title: 'Big Corp Q3 License',
73
+ status: 'open',
74
+ },
75
+ },
76
+ ],
77
+ },
78
78
  });
79
79
 
80
80
  /**
81
81
  * Move deal to a different stage.
82
82
  */
83
83
  export const MoveDealContract = defineCommand({
84
- meta: {
85
- key: 'crm.deal.move',
86
- version: '1.0.0',
87
- stability: 'stable',
88
- owners: [...OWNERS],
89
- tags: ['crm', 'deal', 'move', 'kanban'],
90
- description: 'Move a deal to a different stage.',
91
- goal: 'Allow drag-and-drop stage movement in Kanban.',
92
- context: 'Pipeline Kanban view.',
93
- },
94
- io: {
95
- input: MoveDealInputModel,
96
- output: DealModel,
97
- },
98
- policy: {
99
- auth: 'user',
100
- },
101
- sideEffects: {
102
- emits: [
103
- {
104
- key: 'deal.moved',
105
- version: '1.0.0',
106
- when: 'Deal stage changed',
107
- payload: DealMovedPayloadModel,
108
- },
109
- ],
110
- audit: ['deal.moved'],
111
- },
112
- acceptance: {
113
- scenarios: [
114
- {
115
- key: 'move-deal-happy-path',
116
- given: ['Deal exists in stage A'],
117
- when: ['User moves deal to stage B'],
118
- then: ['Deal stage is updated', 'DealMoved event is emitted'],
119
- },
120
- ],
121
- examples: [
122
- {
123
- key: 'move-to-negotiation',
124
- input: { dealId: 'deal-789', targetStageId: 'stage-negotiation' },
125
- output: {
126
- id: 'deal-789',
127
- stageId: 'stage-negotiation',
128
- movedAt: '2025-01-15T10:00:00Z',
129
- },
130
- },
131
- ],
132
- },
84
+ meta: {
85
+ key: 'crm.deal.move',
86
+ version: '1.0.0',
87
+ stability: 'stable',
88
+ owners: [...OWNERS],
89
+ tags: ['crm', 'deal', 'move', 'kanban'],
90
+ description: 'Move a deal to a different stage.',
91
+ goal: 'Allow drag-and-drop stage movement in Kanban.',
92
+ context: 'Pipeline Kanban view.',
93
+ },
94
+ io: {
95
+ input: MoveDealInputModel,
96
+ output: DealModel,
97
+ },
98
+ policy: {
99
+ auth: 'user',
100
+ },
101
+ sideEffects: {
102
+ emits: [
103
+ {
104
+ key: 'deal.moved',
105
+ version: '1.0.0',
106
+ when: 'Deal stage changed',
107
+ payload: DealMovedPayloadModel,
108
+ },
109
+ ],
110
+ audit: ['deal.moved'],
111
+ },
112
+ acceptance: {
113
+ scenarios: [
114
+ {
115
+ key: 'move-deal-happy-path',
116
+ given: ['Deal exists in stage A'],
117
+ when: ['User moves deal to stage B'],
118
+ then: ['Deal stage is updated', 'DealMoved event is emitted'],
119
+ },
120
+ ],
121
+ examples: [
122
+ {
123
+ key: 'move-to-negotiation',
124
+ input: { dealId: 'deal-789', targetStageId: 'stage-negotiation' },
125
+ output: {
126
+ id: 'deal-789',
127
+ stageId: 'stage-negotiation',
128
+ movedAt: '2025-01-15T10:00:00Z',
129
+ },
130
+ },
131
+ ],
132
+ },
133
133
  });
134
134
 
135
135
  /**
136
136
  * Mark deal as won.
137
137
  */
138
138
  export const WinDealContract = defineCommand({
139
- meta: {
140
- key: 'crm.deal.win',
141
- version: '1.0.0',
142
- stability: 'stable',
143
- owners: [...OWNERS],
144
- tags: ['crm', 'deal', 'won'],
145
- description: 'Mark a deal as won.',
146
- goal: 'Close a deal as successful.',
147
- context: 'Deal closing flow.',
148
- },
149
- io: {
150
- input: WinDealInputModel,
151
- output: DealModel,
152
- },
153
- policy: {
154
- auth: 'user',
155
- },
156
- sideEffects: {
157
- emits: [
158
- {
159
- key: 'deal.won',
160
- version: '1.0.0',
161
- when: 'Deal is won',
162
- payload: DealWonPayloadModel,
163
- },
164
- ],
165
- audit: ['deal.won'],
166
- },
167
- acceptance: {
168
- scenarios: [
169
- {
170
- key: 'win-deal-happy-path',
171
- given: ['Deal is open'],
172
- when: ['User marks deal as won'],
173
- then: ['Deal status becomes WON', 'DealWon event is emitted'],
174
- },
175
- ],
176
- examples: [
177
- {
178
- key: 'mark-won',
179
- input: {
180
- dealId: 'deal-789',
181
- actualValue: 52000,
182
- note: 'Signed contract attached',
183
- },
184
- output: {
185
- id: 'deal-789',
186
- status: 'won',
187
- closedAt: '2025-01-20T14:30:00Z',
188
- },
189
- },
190
- ],
191
- },
139
+ meta: {
140
+ key: 'crm.deal.win',
141
+ version: '1.0.0',
142
+ stability: 'stable',
143
+ owners: [...OWNERS],
144
+ tags: ['crm', 'deal', 'won'],
145
+ description: 'Mark a deal as won.',
146
+ goal: 'Close a deal as successful.',
147
+ context: 'Deal closing flow.',
148
+ },
149
+ io: {
150
+ input: WinDealInputModel,
151
+ output: DealModel,
152
+ },
153
+ policy: {
154
+ auth: 'user',
155
+ },
156
+ sideEffects: {
157
+ emits: [
158
+ {
159
+ key: 'deal.won',
160
+ version: '1.0.0',
161
+ when: 'Deal is won',
162
+ payload: DealWonPayloadModel,
163
+ },
164
+ ],
165
+ audit: ['deal.won'],
166
+ },
167
+ acceptance: {
168
+ scenarios: [
169
+ {
170
+ key: 'win-deal-happy-path',
171
+ given: ['Deal is open'],
172
+ when: ['User marks deal as won'],
173
+ then: ['Deal status becomes WON', 'DealWon event is emitted'],
174
+ },
175
+ ],
176
+ examples: [
177
+ {
178
+ key: 'mark-won',
179
+ input: {
180
+ dealId: 'deal-789',
181
+ actualValue: 52000,
182
+ note: 'Signed contract attached',
183
+ },
184
+ output: {
185
+ id: 'deal-789',
186
+ status: 'won',
187
+ closedAt: '2025-01-20T14:30:00Z',
188
+ },
189
+ },
190
+ ],
191
+ },
192
192
  });
193
193
 
194
194
  /**
195
195
  * Mark deal as lost.
196
196
  */
197
197
  export const LoseDealContract = defineCommand({
198
- meta: {
199
- key: 'crm.deal.lose',
200
- version: '1.0.0',
201
- stability: 'stable',
202
- owners: [...OWNERS],
203
- tags: ['crm', 'deal', 'lost'],
204
- description: 'Mark a deal as lost.',
205
- goal: 'Close a deal as unsuccessful.',
206
- context: 'Deal closing flow.',
207
- },
208
- io: {
209
- input: LoseDealInputModel,
210
- output: DealModel,
211
- },
212
- policy: {
213
- auth: 'user',
214
- },
215
- sideEffects: {
216
- emits: [
217
- {
218
- key: 'deal.lost',
219
- version: '1.0.0',
220
- when: 'Deal is lost',
221
- payload: DealLostPayloadModel,
222
- },
223
- ],
224
- audit: ['deal.lost'],
225
- },
226
- acceptance: {
227
- scenarios: [
228
- {
229
- key: 'lose-deal-happy-path',
230
- given: ['Deal is open'],
231
- when: ['User marks deal as lost'],
232
- then: ['Deal status becomes LOST', 'DealLost event is emitted'],
233
- },
234
- ],
235
- examples: [
236
- {
237
- key: 'mark-lost',
238
- input: {
239
- dealId: 'deal-789',
240
- reason: 'competitor',
241
- note: 'Went with cheaper option',
242
- },
243
- output: {
244
- id: 'deal-789',
245
- status: 'lost',
246
- closedAt: '2025-01-21T09:00:00Z',
247
- },
248
- },
249
- ],
250
- },
198
+ meta: {
199
+ key: 'crm.deal.lose',
200
+ version: '1.0.0',
201
+ stability: 'stable',
202
+ owners: [...OWNERS],
203
+ tags: ['crm', 'deal', 'lost'],
204
+ description: 'Mark a deal as lost.',
205
+ goal: 'Close a deal as unsuccessful.',
206
+ context: 'Deal closing flow.',
207
+ },
208
+ io: {
209
+ input: LoseDealInputModel,
210
+ output: DealModel,
211
+ },
212
+ policy: {
213
+ auth: 'user',
214
+ },
215
+ sideEffects: {
216
+ emits: [
217
+ {
218
+ key: 'deal.lost',
219
+ version: '1.0.0',
220
+ when: 'Deal is lost',
221
+ payload: DealLostPayloadModel,
222
+ },
223
+ ],
224
+ audit: ['deal.lost'],
225
+ },
226
+ acceptance: {
227
+ scenarios: [
228
+ {
229
+ key: 'lose-deal-happy-path',
230
+ given: ['Deal is open'],
231
+ when: ['User marks deal as lost'],
232
+ then: ['Deal status becomes LOST', 'DealLost event is emitted'],
233
+ },
234
+ ],
235
+ examples: [
236
+ {
237
+ key: 'mark-lost',
238
+ input: {
239
+ dealId: 'deal-789',
240
+ reason: 'competitor',
241
+ note: 'Went with cheaper option',
242
+ },
243
+ output: {
244
+ id: 'deal-789',
245
+ status: 'lost',
246
+ closedAt: '2025-01-21T09:00:00Z',
247
+ },
248
+ },
249
+ ],
250
+ },
251
251
  });
252
252
 
253
253
  /**
254
254
  * List deals in pipeline.
255
255
  */
256
256
  export const ListDealsContract = defineQuery({
257
- meta: {
258
- key: 'crm.deal.list',
259
- version: '1.0.0',
260
- stability: 'stable',
261
- owners: [...OWNERS],
262
- tags: ['crm', 'deal', 'list'],
263
- description: 'List deals with filters.',
264
- goal: 'Show pipeline, deal lists, dashboards.',
265
- context: 'Pipeline view, deal list.',
266
- },
267
- io: {
268
- input: ListDealsInputModel,
269
- output: ListDealsOutputModel,
270
- },
271
- policy: {
272
- auth: 'user',
273
- },
274
- acceptance: {
275
- scenarios: [
276
- {
277
- key: 'list-deals-happy-path',
278
- given: ['User has access to deals'],
279
- when: ['User lists deals'],
280
- then: ['List of deals is returned'],
281
- },
282
- ],
283
- examples: [
284
- {
285
- key: 'list-filter-stage',
286
- input: { stageId: 'stage-lead', limit: 20 },
287
- output: { items: [], total: 5, hasMore: false },
288
- },
289
- ],
290
- },
257
+ meta: {
258
+ key: 'crm.deal.list',
259
+ version: '1.0.0',
260
+ stability: 'stable',
261
+ owners: [...OWNERS],
262
+ tags: ['crm', 'deal', 'list'],
263
+ description: 'List deals with filters.',
264
+ goal: 'Show pipeline, deal lists, dashboards.',
265
+ context: 'Pipeline view, deal list.',
266
+ },
267
+ io: {
268
+ input: ListDealsInputModel,
269
+ output: ListDealsOutputModel,
270
+ },
271
+ policy: {
272
+ auth: 'user',
273
+ },
274
+ acceptance: {
275
+ scenarios: [
276
+ {
277
+ key: 'list-deals-happy-path',
278
+ given: ['User has access to deals'],
279
+ when: ['User lists deals'],
280
+ then: ['List of deals is returned'],
281
+ },
282
+ ],
283
+ examples: [
284
+ {
285
+ key: 'list-filter-stage',
286
+ input: { stageId: 'stage-lead', limit: 20 },
287
+ output: { items: [], total: 5, hasMore: false },
288
+ },
289
+ ],
290
+ },
291
291
  });