@eventmodelers/cli 1.0.36 → 1.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +12 -10
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +2 -23
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/references/api-fallback.md +11 -0
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +6 -57
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/references/api-fallback.md +68 -0
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +4 -61
- package/stacks/modeling-kit/templates/.claude/skills/attributes/references/api-fallback.md +39 -0
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +9 -53
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/references/api-fallback.md +63 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +9 -319
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/references/examples.md +329 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +23 -199
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/api-fallback.md +97 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/examples.md +35 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +13 -410
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/api-fallback.md +22 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/examples.md +397 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/SKILL.md +132 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/references/api-fallback.md +21 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +9 -236
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +257 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +28 -302
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/api-fallback.md +31 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/examples.md +216 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +30 -343
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/api-fallback.md +79 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/examples.md +282 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +51 -400
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/api-fallback.md +67 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/examples.md +273 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +45 -152
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +49 -90
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +64 -137
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +74 -65
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/api-fallback.md +51 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +1 -5
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/references/api-fallback.md +10 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +19 -36
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/api-fallback.md +41 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +12 -9
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +1 -10
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +26 -332
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/api-fallback.md +77 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/examples.md +271 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +9 -294
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/references/examples.md +306 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +12 -11
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +6 -36
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +3 -110
- package/stacks/modeling-kit/templates/.claude/skills/examples/references/api-fallback.md +118 -0
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +5 -25
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/references/api-fallback.md +35 -0
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +9 -44
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/references/api-fallback.md +51 -0
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +23 -183
- package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +193 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +14 -81
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/references/api-fallback.md +74 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +4 -45
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/references/api-fallback.md +44 -0
- package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +19 -88
- package/stacks/modeling-kit/templates/.claude/skills/timeline/references/api-fallback.md +91 -0
- package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +1 -9
- package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +0 -674
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +0 -204
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Storyboarding Events — Worked Examples
|
|
2
|
+
|
|
3
|
+
These are conceptual worked examples (Order domain) illustrating the storyboard-design reasoning this step applies — useful for understanding the reasoning, but the actual mechanics live in the "Board Integration", "Mandatory Field Definitions", "Mandatory Screen Rendering", and "Timeline Placement Rules" sections of the main SKILL.md (rendering and placing screen nodes via the API), not in writing a document like this.
|
|
4
|
+
|
|
5
|
+
## 1. Identify UI Screens/Views — mockup example
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Screen 1: Order Creation Form
|
|
9
|
+
|
|
10
|
+
Place Your Order
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
Customer ID: [____________]
|
|
14
|
+
|
|
15
|
+
Items:
|
|
16
|
+
Product 1 Qty: [_] Price: $_
|
|
17
|
+
Product 2 Qty: [_] Price: $_
|
|
18
|
+
Product 3 Qty: [_] Price: $_
|
|
19
|
+
|
|
20
|
+
Total: $___
|
|
21
|
+
|
|
22
|
+
Shipping Address:
|
|
23
|
+
[_____________________]
|
|
24
|
+
[_____________________]
|
|
25
|
+
|
|
26
|
+
[ Create Order ]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Trigger: CreateOrder command
|
|
30
|
+
Result Events: OrderCreated
|
|
31
|
+
Data captured from UI:
|
|
32
|
+
- customerId
|
|
33
|
+
- items (products + quantities)
|
|
34
|
+
- total
|
|
35
|
+
- shippingAddress
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 2. Show State Transitions Between Screens — worked example
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Screen 2: Order Confirmation
|
|
42
|
+
(After OrderCreated event)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Order Confirmation
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Order ID: #12345
|
|
49
|
+
Status: Draft
|
|
50
|
+
|
|
51
|
+
Items: 3 products
|
|
52
|
+
Total: $150.00
|
|
53
|
+
|
|
54
|
+
Shipping: 123 Main St
|
|
55
|
+
|
|
56
|
+
Payment Options:
|
|
57
|
+
Credit Card
|
|
58
|
+
Bank Transfer
|
|
59
|
+
|
|
60
|
+
[ Confirm Order ]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
Trigger: ConfirmOrder command
|
|
64
|
+
Result Events: OrderConfirmed
|
|
65
|
+
Data from UI:
|
|
66
|
+
- orderId (from OrderCreated)
|
|
67
|
+
- paymentMethod
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 3. Document All Data Fields — worked example
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Screen: Order Status View
|
|
74
|
+
|
|
75
|
+
Your Order Status
|
|
76
|
+
|
|
77
|
+
Order ID: #12345 (from OrderCreated)
|
|
78
|
+
Status: Confirmed (from OrderConfirmed)
|
|
79
|
+
Confirmed at: 2024-12-31 10:00 (from OrderConfirmed)
|
|
80
|
+
|
|
81
|
+
Payment: Authorized (from PaymentAuthorized)
|
|
82
|
+
Auth Code: AUTH-789 (from PaymentAuthorized)
|
|
83
|
+
|
|
84
|
+
Inventory: Reserved (from InventoryReserved)
|
|
85
|
+
Expected Ship: 2025-01-02 (from InventoryReserved)
|
|
86
|
+
|
|
87
|
+
Shipped: Pending (awaiting OrderShipped)
|
|
88
|
+
Tracking: -- (waiting for shipment)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
Fields and their origins:
|
|
92
|
+
orderId → OrderCreated event
|
|
93
|
+
status → OrderConfirmed event
|
|
94
|
+
confirmedAt → OrderConfirmed event
|
|
95
|
+
paymentStatus → PaymentAuthorized event
|
|
96
|
+
authCode → PaymentAuthorized event
|
|
97
|
+
inventoryStatus → InventoryReserved event
|
|
98
|
+
expectedShip → InventoryReserved event
|
|
99
|
+
tracking → OrderShipped event (when available)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 4. Show Data Flow Through Screens — worked example
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Order Entry UI
|
|
106
|
+
(user inputs)
|
|
107
|
+
customerId
|
|
108
|
+
items[]
|
|
109
|
+
total
|
|
110
|
+
shippingAddress
|
|
111
|
+
↓
|
|
112
|
+
Command: CreateOrder
|
|
113
|
+
↓
|
|
114
|
+
Event: OrderCreated
|
|
115
|
+
↓
|
|
116
|
+
Order Status UI (displays)
|
|
117
|
+
orderId (from event)
|
|
118
|
+
items (from event)
|
|
119
|
+
total (from event)
|
|
120
|
+
shippingAddress (from event)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 5. Organize Screens by Swimlane — worked example
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Swimlane: Customer (Human Role)
|
|
127
|
+
Screen 1: Order Entry Form
|
|
128
|
+
Screen 2: Order Confirmation
|
|
129
|
+
Screen 3: Order Status View
|
|
130
|
+
Screen 4: Tracking View
|
|
131
|
+
|
|
132
|
+
Swimlane: Seller (Human Role)
|
|
133
|
+
Screen 1: Order Fulfillment Dashboard
|
|
134
|
+
Screen 2: Review Response Form
|
|
135
|
+
Screen 3: Product Management
|
|
136
|
+
|
|
137
|
+
Swimlane: Support Agent (Human Role)
|
|
138
|
+
Screen 1: Escalation Queue
|
|
139
|
+
Screen 2: Manual Override Panel
|
|
140
|
+
|
|
141
|
+
Swimlane: Payment Processor (System Actor)
|
|
142
|
+
Screen 1: Payment Verification (automated)
|
|
143
|
+
Screen 2: Authorization Confirmation
|
|
144
|
+
|
|
145
|
+
Swimlane: Inventory System (System Actor)
|
|
146
|
+
Screen 1: Reservation Todo List (internal)
|
|
147
|
+
Screen 2: Availability Check
|
|
148
|
+
|
|
149
|
+
Swimlane: Fulfillment System (System Actor)
|
|
150
|
+
Screen 1: Shipment Creation Todo
|
|
151
|
+
Screen 2: Shipping Confirmation
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 6. Show Processor "Todo List" Pattern — worked example
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Processor: InventoryReserver
|
|
158
|
+
|
|
159
|
+
Internal "Todo List" (based on received events):
|
|
160
|
+
|
|
161
|
+
Inventory Reservation Todos
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
Order-123: Reserve 2x Prod-1 (triggered by PaymentAuthorized)
|
|
165
|
+
Order-124: Reserve 3x Prod-2 (triggered by PaymentAuthorized)
|
|
166
|
+
Order-125: Reserve 1x Prod-3 (triggered by PaymentAuthorized)
|
|
167
|
+
|
|
168
|
+
Processor checks todo items:
|
|
169
|
+
For each: Check availability
|
|
170
|
+
If available: Mark done
|
|
171
|
+
Reserve inventory
|
|
172
|
+
Produce event
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
This todo list is driven by:
|
|
177
|
+
Events received → Items added to todo
|
|
178
|
+
Processor logic → Items processed
|
|
179
|
+
Success → InventoryReserved event produced + todo marked done
|
|
180
|
+
Failure → InventoryFailed event produced + todo marked failed
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Output Format — full worked example
|
|
184
|
+
|
|
185
|
+
```markdown
|
|
186
|
+
# Storyboard: [Domain Name]
|
|
187
|
+
|
|
188
|
+
## Swimlane Organization (from Role Catalog)
|
|
189
|
+
|
|
190
|
+
### Human Role Swimlanes
|
|
191
|
+
|
|
192
|
+
#### Customer Swimlane
|
|
193
|
+
- Screen 1: Order Entry Form
|
|
194
|
+
- Screen 2: Order Confirmation
|
|
195
|
+
- Screen 3: Order Status View
|
|
196
|
+
|
|
197
|
+
#### [Other Human Role Swimlanes — one per role in the catalog]
|
|
198
|
+
|
|
199
|
+
### System Actor Swimlanes
|
|
200
|
+
|
|
201
|
+
_(Narrative grouping only — these are not physical board lanes. Every automation below renders in the chapter's shared default actor lane; see "Placing Automations".)_
|
|
202
|
+
|
|
203
|
+
#### Payment Processor Swimlane
|
|
204
|
+
- Screen 1: Payment Verification (automated)
|
|
205
|
+
- [Shows what UI/views the processor interacts with]
|
|
206
|
+
|
|
207
|
+
#### [Other System Actor Swimlanes]
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Screen 1: [Screen Name]
|
|
212
|
+
|
|
213
|
+
### Mockup
|
|
214
|
+
```
|
|
215
|
+
[ASCII art mockup or description]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Data Displayed
|
|
219
|
+
- Field 1: Description, source event
|
|
220
|
+
- Field 2: Description, source event
|
|
221
|
+
|
|
222
|
+
### User Actions (Commands)
|
|
223
|
+
- Action: [Action], produces: [Event]
|
|
224
|
+
|
|
225
|
+
### Business Rules
|
|
226
|
+
- Rule about what can/cannot be done on this screen
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Screen 2: [Screen Name]
|
|
231
|
+
|
|
232
|
+
[Repeat for each screen]
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Processor Todo Lists
|
|
237
|
+
|
|
238
|
+
### Processor: [Processor Name]
|
|
239
|
+
|
|
240
|
+
Internal "Todo List" pattern:
|
|
241
|
+
```
|
|
242
|
+
Triggered by: [Event type]
|
|
243
|
+
Todo action: [What needs to be done]
|
|
244
|
+
Success produces: [Event]
|
|
245
|
+
Failure produces: [Event]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
[Repeat for each processor]
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Data Flow Diagram
|
|
253
|
+
|
|
254
|
+
[Show how data enters from UI and returns via events]
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Field Traceability Matrix
|
|
259
|
+
|
|
260
|
+
| Field | Screen | Source Event | Status |
|
|
261
|
+
|-------|--------|-------------|--------|
|
|
262
|
+
| orderId | Status View | OrderCreated | |
|
|
263
|
+
| shipmentId | Status View | OrderShipped | |
|
|
264
|
+
| customerId | All | OrderCreated | |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Missing Data Analysis
|
|
269
|
+
|
|
270
|
+
[Any fields without clear source or destination]
|
|
271
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eventmodeling-translating-external-events
|
|
3
|
-
description: "Translate external system events (webhooks, APIs, IoT) into domain events. Map technical data to business concepts. Use when integrating with external systems that emit events your domain needs to react to. Do not use for:
|
|
3
|
+
description: "Translate external system events (webhooks, APIs, IoT) into domain events. Map technical data to business concepts. Use when integrating with external systems that emit events your domain needs to react to. Do not use for: designing command handlers for the translated events (use eventmodeling-designing-event-models)."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- AskUserQuestion
|
|
6
6
|
- Write
|
|
@@ -89,215 +89,31 @@ Update Interview Trail:
|
|
|
89
89
|
|
|
90
90
|
### 1. Identify External Event Sources
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
External System: Payment Gateway (Stripe)
|
|
96
|
-
|
|
97
|
-
Events received:
|
|
98
|
-
- charge.succeeded
|
|
99
|
-
- charge.failed
|
|
100
|
-
- charge.refunded
|
|
101
|
-
- charge.dispute.created
|
|
102
|
-
|
|
103
|
-
Example payload: charge.succeeded
|
|
104
|
-
{
|
|
105
|
-
"id": "ch_1234567890",
|
|
106
|
-
"amount": 15000,
|
|
107
|
-
"currency": "usd",
|
|
108
|
-
"customer": "cus_9876543210",
|
|
109
|
-
"status": "succeeded",
|
|
110
|
-
"created": 1640995200
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
External System: GPS Location Service (Google Maps)
|
|
114
|
-
|
|
115
|
-
Events received:
|
|
116
|
-
- location_update
|
|
117
|
-
- geofence_enter
|
|
118
|
-
- geofence_exit
|
|
119
|
-
|
|
120
|
-
Example payload: geofence_exit
|
|
121
|
-
{
|
|
122
|
-
"userId": "user-123",
|
|
123
|
-
"geoFenceId": "hotel-front-entrance",
|
|
124
|
-
"timestamp": 1640995200,
|
|
125
|
-
"latitude": 40.7128,
|
|
126
|
-
"longitude": -74.0060
|
|
127
|
-
}
|
|
128
|
-
```
|
|
92
|
+
For each external system, document its name, the events it sends, and a sample payload for each event type. Do this for every system your domain integrates with before moving on. A full worked example (Stripe payment webhooks, GPS geofence events) is in `references/examples.md`.
|
|
129
93
|
|
|
130
94
|
### 2. Analyze Technical Representation
|
|
131
95
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
External Event: charge.succeeded (Stripe)
|
|
136
|
-
|
|
137
|
-
Technical fields:
|
|
138
|
-
- id: UUID of charge in Stripe (not meaningful to us)
|
|
139
|
-
- amount: Integer cents (15000 = $150.00)
|
|
140
|
-
- currency: ISO code ("usd")
|
|
141
|
-
- customer: Stripe customer ID (not our customer ID)
|
|
142
|
-
- status: String indicating success
|
|
143
|
-
- created: Unix timestamp
|
|
144
|
-
|
|
145
|
-
Problems with using directly:
|
|
146
|
-
We don't use Stripe customer IDs (we have our own customer IDs)
|
|
147
|
-
Currency and amount require interpretation
|
|
148
|
-
Status is one field in their model, we care about the fact it succeeded
|
|
149
|
-
Stripe charge ID isn't the same as our order ID
|
|
150
|
-
We need to correlate back to our Order stream
|
|
151
|
-
```
|
|
96
|
+
For each external event, list its raw technical fields and call out what's wrong with using them directly: opaque IDs that mean nothing to your domain, values needing unit/format conversion, a single technical field standing in for a business fact, and — critically — IDs that don't match your own entity IDs and therefore need correlation. A full worked example (Stripe `charge.succeeded`) is in `references/examples.md`.
|
|
152
97
|
|
|
153
98
|
### 3. Define Domain Translation Rules
|
|
154
99
|
|
|
155
|
-
Map technical
|
|
156
|
-
|
|
157
|
-
```
|
|
158
|
-
Translation: External charge.succeeded → Domain PaymentAuthorized
|
|
159
|
-
|
|
160
|
-
Mapping rules:
|
|
161
|
-
charge.id (Stripe) → paymentGatewayRef (store for reconciliation, don't use as primary)
|
|
162
|
-
charge.customer (Stripe) → Look up: Which of OUR customers has this Stripe ID?
|
|
163
|
-
charge.amount → paymentAmount (convert from cents)
|
|
164
|
-
charge.currency → paymentCurrency
|
|
165
|
-
created → timestamp
|
|
166
|
-
[NEED TO FIND] → orderId (Stripe doesn't tell us! This is critical—how do we know which order?)
|
|
167
|
-
|
|
168
|
-
Problem identified:
|
|
169
|
-
Stripe webhook comes with charge details but NOT our order ID.
|
|
170
|
-
|
|
171
|
-
Solutions:
|
|
172
|
-
A. Store Stripe charge ID in our Order when we initiate payment
|
|
173
|
-
When webhook arrives: charge.id → Look up in OrderPaymentReference
|
|
174
|
-
Find orderId → Create PaymentAuthorized event
|
|
175
|
-
|
|
176
|
-
B. Store custom metadata in Stripe charge
|
|
177
|
-
When creating charge: Include our orderId in metadata
|
|
178
|
-
When webhook arrives: Extract orderId from metadata
|
|
179
|
-
|
|
180
|
-
Choose A or B based on Stripe integration approach.
|
|
181
|
-
```
|
|
100
|
+
Map each technical field to the domain concept it should become, and flag any domain field the external payload doesn't supply at all. When a required field (like your own internal ID) is missing, decide how to obtain it — typically either by storing a reference to the external ID when you initiate the external action, or by embedding your own ID as metadata that the external system echoes back. A full worked example (Stripe charge → `PaymentAuthorized`) is in `references/examples.md`.
|
|
182
101
|
|
|
183
102
|
### 4. Handle Correlation
|
|
184
103
|
|
|
185
|
-
External systems
|
|
186
|
-
|
|
187
|
-
```
|
|
188
|
-
Pattern: Correlation via Reference Tracking
|
|
189
|
-
|
|
190
|
-
Our system flow:
|
|
191
|
-
1. Order created in our system: order-123
|
|
192
|
-
2. We initiate payment with Stripe:
|
|
193
|
-
- Send amount, customer info
|
|
194
|
-
- Receive charge ID: ch_1234567890
|
|
195
|
-
- Store reference: OrderPaymentReference { orderId: order-123, stripeChargeId: ch_1234567890 }
|
|
196
|
-
|
|
197
|
-
When webhook arrives:
|
|
198
|
-
1. Webhook: charge.succeeded { id: ch_1234567890, amount: 15000, ... }
|
|
199
|
-
2. Look up: Find OrderPaymentReference where stripeChargeId = ch_1234567890
|
|
200
|
-
3. Get orderId from reference
|
|
201
|
-
4. Create PaymentAuthorized event: { orderId: order-123, amount: 150.00, ... }
|
|
202
|
-
|
|
203
|
-
Key insight: You must create the correlation bridge when initiating external action.
|
|
204
|
-
```
|
|
104
|
+
External systems rarely include your own entity IDs, so the correlation bridge must be created on **your** side, at the moment you initiate the external action — store a reference record mapping your entity ID to the external ID you receive back. When the external event later arrives, look up that reference to recover your entity ID before creating the domain event. A full worked example (Order ↔ Stripe charge reference tracking) is in `references/examples.md`.
|
|
205
105
|
|
|
206
106
|
### 5. Define Translation Scenarios
|
|
207
107
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
External Event: charge.succeeded
|
|
212
|
-
Trigger: Stripe webhook arrives with charge details
|
|
213
|
-
Precondition: OrderPaymentReference exists for this charge ID
|
|
214
|
-
Translation logic:
|
|
215
|
-
1. Extract charge.id from webhook
|
|
216
|
-
2. Look up OrderPaymentReference.orderId
|
|
217
|
-
3. Validate order exists and is in Confirmed state
|
|
218
|
-
4. Create domain event: PaymentAuthorized { orderId, amount, timestamp, ... }
|
|
219
|
-
Success: Domain event produced
|
|
220
|
-
Failure scenarios:
|
|
221
|
-
- Charge ID not found in references → Log error, don't produce event (manual review)
|
|
222
|
-
- Order not in Confirmed state → Log error, don't produce event
|
|
223
|
-
- Duplicate webhook → Idempotent handling (check if event already exists)
|
|
224
|
-
|
|
225
|
-
--- External Event: geofence_exit
|
|
226
|
-
Trigger: Guest leaves hotel area (GPS geofence)
|
|
227
|
-
Precondition: Guest has opted in to location tracking
|
|
228
|
-
Translation logic:
|
|
229
|
-
1. Extract userId and geoFenceId from webhook
|
|
230
|
-
2. Validate guest is currently in hotel
|
|
231
|
-
3. Check geofence_exit is "hotel-front-entrance" (not just any geofence)
|
|
232
|
-
4. Create domain event: GuestLeftHotel { guestId: userId, timestamp, ... }
|
|
233
|
-
Success: Domain event produced
|
|
234
|
-
Failure scenarios:
|
|
235
|
-
- Guest hasn't opted in → Don't produce event (respect privacy)
|
|
236
|
-
- Guest not checked in → Don't produce event (shouldn't be in geofence)
|
|
237
|
-
- Unknown geofence → Log error, don't produce event
|
|
238
|
-
```
|
|
108
|
+
For each external event, specify: its trigger, any precondition that must hold, the translation logic as an ordered list of steps, what a success looks like, and every failure scenario (e.g. missing correlation, invalid state, duplicate delivery) with its handling. A full worked example (Stripe `charge.succeeded`, GPS `geofence_exit`) is in `references/examples.md`.
|
|
239
109
|
|
|
240
110
|
### 6. Handle Duplicates and Ordering
|
|
241
111
|
|
|
242
|
-
External systems
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
Problem: Stripe retries charge.succeeded webhook
|
|
246
|
-
Webhook 1: charge.succeeded { id: ch_123 } → Arrives at 10:00 AM
|
|
247
|
-
Webhook 2: charge.succeeded { id: ch_123 } → Arrives at 10:05 AM (retry)
|
|
248
|
-
|
|
249
|
-
Solution: Idempotent translation
|
|
250
|
-
|
|
251
|
-
Check before creating event:
|
|
252
|
-
1. Extract external ID: ch_123
|
|
253
|
-
2. Query: Does PaymentAuthorized event exist with paymentGatewayRef = ch_123?
|
|
254
|
-
3. If yes: Do nothing (already processed)
|
|
255
|
-
4. If no: Create event
|
|
256
|
-
|
|
257
|
-
This requires storing the external ID in the event:
|
|
258
|
-
PaymentAuthorized event {
|
|
259
|
-
orderId: order-123,
|
|
260
|
-
amount: 150.00,
|
|
261
|
-
paymentGatewayRef: ch_123, ← Store external ID for deduplication
|
|
262
|
-
...
|
|
263
|
-
}
|
|
264
|
-
```
|
|
112
|
+
External systems commonly redeliver the same event (e.g. webhook retries). Translation must be idempotent: before creating a domain event, check whether one already exists for that external ID, and only create it if not. This requires storing the external ID on the resulting domain event so the check has something to query against. A full worked example (duplicate Stripe webhook delivery) is in `references/examples.md`.
|
|
265
113
|
|
|
266
114
|
### 7. Handle Partial or Missing Information
|
|
267
115
|
|
|
268
|
-
External
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
External Event: geofence_exit
|
|
272
|
-
|
|
273
|
-
Available data:
|
|
274
|
-
- userId
|
|
275
|
-
- geoFenceId
|
|
276
|
-
- timestamp
|
|
277
|
-
- latitude, longitude (raw GPS)
|
|
278
|
-
|
|
279
|
-
Missing data:
|
|
280
|
-
- Guest name (not in webhook payload)
|
|
281
|
-
- Reason for leaving (not tracked)
|
|
282
|
-
- Expected return time (not available)
|
|
283
|
-
|
|
284
|
-
Handling strategy:
|
|
285
|
-
A. Translation enriches from our system:
|
|
286
|
-
Domain event: GuestLeftHotel {
|
|
287
|
-
guestId: userId, ← From webhook
|
|
288
|
-
timestamp: ..., ← From webhook
|
|
289
|
-
guestName: "John Smith", ← Looked up from guest stream
|
|
290
|
-
roomNumber: "502", ← Looked up from guest stream
|
|
291
|
-
geoFenceId: "front-entrance" ← From webhook
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
B. Some data we don't need:
|
|
295
|
-
We ignore: latitude, longitude (we just care that guest left)
|
|
296
|
-
|
|
297
|
-
C. Some data we can infer:
|
|
298
|
-
We can assume: Guest is now outside hotel
|
|
299
|
-
Cleaning crew can visit room
|
|
300
|
-
```
|
|
116
|
+
External payloads are often incomplete. For each field the domain event needs, classify it as: enrich (look it up from your own system), ignore (not needed for this domain), or infer (a safe assumption follows from the event itself). Document the classification explicitly rather than leaving a field's source implicit. A full worked example (GPS `geofence_exit` enrichment) is in `references/examples.md`.
|
|
301
117
|
|
|
302
118
|
## Output Format
|
|
303
119
|
|
|
@@ -314,108 +130,7 @@ Then present the full translation rules as text to the user.
|
|
|
314
130
|
|
|
315
131
|
---
|
|
316
132
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
````markdown
|
|
320
|
-
# External Event Translation: [Domain Name]
|
|
321
|
-
|
|
322
|
-
## External Systems & Events
|
|
323
|
-
|
|
324
|
-
### System: [External System Name]
|
|
325
|
-
|
|
326
|
-
**Connection Type**: [Webhook/API polling/WebSocket/Streaming]
|
|
327
|
-
|
|
328
|
-
**Events Received**:
|
|
329
|
-
- event1_name
|
|
330
|
-
- event2_name
|
|
331
|
-
- event3_name
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
## Translation Rules
|
|
336
|
-
|
|
337
|
-
### External Event: [Event Name]
|
|
338
|
-
|
|
339
|
-
**Source System**: [System name]
|
|
340
|
-
|
|
341
|
-
**Technical Representation**:
|
|
342
|
-
```json
|
|
343
|
-
{
|
|
344
|
-
"field1": "value",
|
|
345
|
-
"field2": "value"
|
|
346
|
-
}
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
**Domain Translation**:
|
|
350
|
-
| External Field | Our Field | Mapping | Notes |
|
|
351
|
-
|---|---|---|---|
|
|
352
|
-
| externalId | n/a | Stored for deduplication | Reference only |
|
|
353
|
-
| customer | [lookup] | Look up our customer ID | Must correlate |
|
|
354
|
-
|
|
355
|
-
**Correlation Method**:
|
|
356
|
-
[How do we link back to our domain entities?]
|
|
357
|
-
|
|
358
|
-
**Domain Event Produced**:
|
|
359
|
-
- Event Name: [EventName]
|
|
360
|
-
- Fields: [List with sources]
|
|
361
|
-
|
|
362
|
-
**Translation Logic**:
|
|
363
|
-
```
|
|
364
|
-
1. Extract from webhook
|
|
365
|
-
2. Validate preconditions
|
|
366
|
-
3. Enrich from our system
|
|
367
|
-
4. Create domain event
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
**Success Scenario**:
|
|
371
|
-
[What success looks like]
|
|
372
|
-
|
|
373
|
-
**Failure Scenarios**:
|
|
374
|
-
- Scenario 1: Consequence
|
|
375
|
-
- Scenario 2: Consequence
|
|
376
|
-
|
|
377
|
-
**Duplicate Handling**: [Idempotent strategy]
|
|
378
|
-
|
|
379
|
-
--- [Repeat for each external event]
|
|
380
|
-
|
|
381
|
-
---
|
|
382
|
-
|
|
383
|
-
## Correlation Reference
|
|
384
|
-
|
|
385
|
-
Track how external IDs map to our domain:
|
|
386
|
-
|
|
387
|
-
| Our Entity | External System | External ID Field | Storage | Lookup |
|
|
388
|
-
|---|---|---|---|---|
|
|
389
|
-
| Order | Stripe | charge.id | OrderPaymentReference | By charge ID |
|
|
390
|
-
| Guest | GPS Service | userId | Guest stream | By userId |
|
|
391
|
-
|
|
392
|
-
---
|
|
393
|
-
|
|
394
|
-
## Failure & Recovery
|
|
395
|
-
|
|
396
|
-
### Webhook Arrives for Non-existent Order
|
|
397
|
-
**Symptom**: Stripe sends charge.succeeded for unknown order
|
|
398
|
-
**Cause**: Race condition or data inconsistency
|
|
399
|
-
**Detection**: OrderPaymentReference lookup returns nothing
|
|
400
|
-
**Recovery**: Log error, queue for manual review
|
|
401
|
-
|
|
402
|
-
### Duplicate Webhooks
|
|
403
|
-
**Symptom**: Same webhook received multiple times
|
|
404
|
-
**Cause**: Stripe retry mechanism or network duplication
|
|
405
|
-
**Detection**: Domain event already exists with same externalRef
|
|
406
|
-
**Recovery**: Idempotent check prevents duplicate event creation
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
## Testing Recommendations
|
|
411
|
-
|
|
412
|
-
- [ ] Test happy path: External event → Correct domain event
|
|
413
|
-
- [ ] Test missing correlation: External event arrives before our order created
|
|
414
|
-
- [ ] Test duplicate: Same webhook processed twice
|
|
415
|
-
- [ ] Test invalid data: Webhook with missing required fields
|
|
416
|
-
- [ ] Test partial data: Webhook with some fields missing
|
|
417
|
-
- [ ] Test ordering: Multiple webhooks arrive out of order
|
|
418
|
-
````
|
|
133
|
+
Older versions of this skill wrote the translation rules as a standalone markdown document rather than placing translated events on the board; that legacy format is kept in `references/examples.md` for reference only — it is not the actual output mechanism (see "Output Format" above).
|
|
419
134
|
|
|
420
135
|
## Quality Checklist
|
|
421
136
|
|