@eventmodelers/cli 0.0.1

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 (220) hide show
  1. package/README.md +175 -0
  2. package/cli.js +676 -0
  3. package/package.json +35 -0
  4. package/shared/build-kit/code-export.mjs +560 -0
  5. package/shared/build-kit/lib/ollama-agent.js +147 -0
  6. package/shared/build-kit/package.json +11 -0
  7. package/shared/build-kit/ralph-ollama.js +39 -0
  8. package/shared/build-kit/realtime-agent.js +18 -0
  9. package/stacks/axon/templates/.claude/skills/build-automation/SKILL.md +407 -0
  10. package/stacks/axon/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +114 -0
  11. package/stacks/axon/templates/.claude/skills/build-automation-workflow/SKILL.md +496 -0
  12. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/axon-workflow-api.md +279 -0
  13. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/feature-flag-patterns.md +114 -0
  14. package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +396 -0
  15. package/stacks/axon/templates/.claude/skills/build-state-change/references/axon-test-fixture-patterns.md +162 -0
  16. package/stacks/axon/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +56 -0
  17. package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +115 -0
  18. package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +282 -0
  19. package/stacks/axon/templates/.claude/skills/connect/SKILL.md +178 -0
  20. package/stacks/axon/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +611 -0
  21. package/stacks/axon/templates/.claude/skills/load-slice/SKILL.md +141 -0
  22. package/stacks/axon/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  23. package/stacks/axon/templates/build-kit/lib/AGENT.md +47 -0
  24. package/stacks/axon/templates/build-kit/lib/agent.sh +20 -0
  25. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +158 -0
  26. package/stacks/axon/templates/build-kit/lib/prompt.md +126 -0
  27. package/stacks/axon/templates/build-kit/lib/ralph.js +369 -0
  28. package/stacks/axon/templates/build-kit/ralph-claude.js +44 -0
  29. package/stacks/axon/templates/build-kit/ralph.sh +98 -0
  30. package/stacks/axon/templates/root/.env.example +5 -0
  31. package/stacks/axon/templates/root/CLAUDE.md +60 -0
  32. package/stacks/axon/templates/root/README.md +44 -0
  33. package/stacks/axon/templates/root/docker-compose.yml +64 -0
  34. package/stacks/axon/templates/root/mvnw +259 -0
  35. package/stacks/axon/templates/root/mvnw.cmd +149 -0
  36. package/stacks/axon/templates/root/pom.xml +125 -0
  37. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java +128 -0
  38. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/config/WebConfig.java +155 -0
  39. package/stacks/axon/templates/root/src/main/resources/application.properties +2 -0
  40. package/stacks/axon/templates/root/src/main/resources/static/bg-body.png +0 -0
  41. package/stacks/axon/templates/root/src/main/resources/static/bg-header.png +0 -0
  42. package/stacks/axon/templates/root/src/main/resources/static/index.html +596 -0
  43. package/stacks/cratis-csharp/templates/.claude/skills/_shared/cratis-conventions.md +251 -0
  44. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/SKILL.md +99 -0
  45. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/references/patterns.md +115 -0
  46. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/SKILL.md +163 -0
  47. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/references/patterns.md +234 -0
  48. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/SKILL.md +120 -0
  49. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/references/patterns.md +166 -0
  50. package/stacks/cratis-csharp/templates/.claude/skills/connect/SKILL.md +169 -0
  51. package/stacks/cratis-csharp/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +609 -0
  52. package/stacks/cratis-csharp/templates/.claude/skills/load-slice/SKILL.md +141 -0
  53. package/stacks/cratis-csharp/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  54. package/stacks/cratis-csharp/templates/build-kit/lib/AGENT.md +58 -0
  55. package/stacks/cratis-csharp/templates/build-kit/lib/agent.sh +20 -0
  56. package/stacks/cratis-csharp/templates/build-kit/lib/backend-prompt.md +129 -0
  57. package/stacks/cratis-csharp/templates/build-kit/lib/prompt.md +124 -0
  58. package/stacks/cratis-csharp/templates/build-kit/lib/ralph.js +302 -0
  59. package/stacks/cratis-csharp/templates/build-kit/ralph-claude.js +37 -0
  60. package/stacks/cratis-csharp/templates/build-kit/ralph.sh +98 -0
  61. package/stacks/cratis-csharp/templates/root/.frontend/index.css +29 -0
  62. package/stacks/cratis-csharp/templates/root/.frontend/index.html +17 -0
  63. package/stacks/cratis-csharp/templates/root/.frontend/main.tsx +18 -0
  64. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.json +42 -0
  65. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.node.json +11 -0
  66. package/stacks/cratis-csharp/templates/root/.frontend/vite.config.ts +56 -0
  67. package/stacks/cratis-csharp/templates/root/App.tsx +23 -0
  68. package/stacks/cratis-csharp/templates/root/CLAUDE.md +62 -0
  69. package/stacks/cratis-csharp/templates/root/CratisApp.csproj +25 -0
  70. package/stacks/cratis-csharp/templates/root/CratisApp.sln +18 -0
  71. package/stacks/cratis-csharp/templates/root/GlobalUsings.cs +3 -0
  72. package/stacks/cratis-csharp/templates/root/Home.tsx +102 -0
  73. package/stacks/cratis-csharp/templates/root/Program.cs +26 -0
  74. package/stacks/cratis-csharp/templates/root/README.md +192 -0
  75. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/AllListings.ts +47 -0
  76. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.cs +11 -0
  77. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.ts +12 -0
  78. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/ListingDataTable.tsx +17 -0
  79. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/index.ts +1 -0
  80. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Register.ts +51 -0
  81. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/RegisterDialog.tsx +18 -0
  82. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Registration.cs +27 -0
  83. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/index.ts +1 -0
  84. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeFeature.tsx +22 -0
  85. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeName.cs +3 -0
  86. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/index.ts +1 -0
  87. package/stacks/cratis-csharp/templates/root/appsettings.Development.json +9 -0
  88. package/stacks/cratis-csharp/templates/root/appsettings.json +26 -0
  89. package/stacks/cratis-csharp/templates/root/docker-compose.yml +23 -0
  90. package/stacks/cratis-csharp/templates/root/package.json +33 -0
  91. package/stacks/cratis-csharp/templates/root/tsconfig.json +3 -0
  92. package/stacks/modeling-kit/templates/.claude/settings.local.json +13 -0
  93. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +215 -0
  94. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +176 -0
  95. package/stacks/modeling-kit/templates/.claude/skills/connect/SKILL.md +182 -0
  96. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +383 -0
  97. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +465 -0
  98. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +587 -0
  99. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/facilitating-event-modeling-workshops.md +626 -0
  100. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +542 -0
  101. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +497 -0
  102. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +783 -0
  103. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +604 -0
  104. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +699 -0
  105. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +674 -0
  106. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +231 -0
  107. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +150 -0
  108. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +329 -0
  109. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +204 -0
  110. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +352 -0
  111. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/project-planning-with-event-modeling.md +341 -0
  112. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +153 -0
  113. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +136 -0
  114. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +78 -0
  115. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +85 -0
  116. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +655 -0
  117. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +479 -0
  118. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +234 -0
  119. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +353 -0
  120. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +200 -0
  121. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +94 -0
  122. package/stacks/modeling-kit/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +441 -0
  123. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +290 -0
  124. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +212 -0
  125. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +123 -0
  126. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +353 -0
  127. package/stacks/modeling-kit/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  128. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +134 -0
  129. package/stacks/modeling-kit/templates/kit/lib/agent.sh +20 -0
  130. package/stacks/modeling-kit/templates/kit/lib/ollama-agent.js +147 -0
  131. package/stacks/modeling-kit/templates/kit/lib/ralph.js +286 -0
  132. package/stacks/modeling-kit/templates/kit/package.json +12 -0
  133. package/stacks/modeling-kit/templates/kit/ralph-claude.js +50 -0
  134. package/stacks/modeling-kit/templates/kit/ralph-ollama.js +38 -0
  135. package/stacks/modeling-kit/templates/kit/ralph.sh +61 -0
  136. package/stacks/modeling-kit/templates/kit/realtime-agent.js +18 -0
  137. package/stacks/modeling-kit/templates/root/CLAUDE.md +56 -0
  138. package/stacks/node/templates/.claude/skills/build-automation/SKILL.md +266 -0
  139. package/stacks/node/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  140. package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +412 -0
  141. package/stacks/node/templates/.claude/skills/connect/SKILL.md +178 -0
  142. package/stacks/node/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  143. package/stacks/node/templates/.claude/skills/load-slice/SKILL.md +143 -0
  144. package/stacks/node/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  145. package/stacks/node/templates/build-kit/README.md +86 -0
  146. package/stacks/node/templates/build-kit/lib/AGENT.md +47 -0
  147. package/stacks/node/templates/build-kit/lib/agent.sh +20 -0
  148. package/stacks/node/templates/build-kit/lib/backend-prompt.md +152 -0
  149. package/stacks/node/templates/build-kit/lib/prompt.md +122 -0
  150. package/stacks/node/templates/build-kit/lib/ralph.js +369 -0
  151. package/stacks/node/templates/build-kit/ralph-claude.js +44 -0
  152. package/stacks/node/templates/build-kit/ralph.sh +98 -0
  153. package/stacks/node/templates/root/.env.example +15 -0
  154. package/stacks/node/templates/root/CLAUDE.md +60 -0
  155. package/stacks/node/templates/root/docker-compose.yml +15 -0
  156. package/stacks/node/templates/root/flyway.conf +17 -0
  157. package/stacks/node/templates/root/migrations/V1__schema.sql.example +12 -0
  158. package/stacks/node/templates/root/package.json +50 -0
  159. package/stacks/node/templates/root/server.ts +130 -0
  160. package/stacks/node/templates/root/setup-env.sh +53 -0
  161. package/stacks/node/templates/root/src/common/assertions.ts +6 -0
  162. package/stacks/node/templates/root/src/common/db.ts +32 -0
  163. package/stacks/node/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  164. package/stacks/node/templates/root/src/common/parseEndpoint.ts +51 -0
  165. package/stacks/node/templates/root/src/common/processorDlq.ts +28 -0
  166. package/stacks/node/templates/root/src/common/realtimeBroadcast.ts +12 -0
  167. package/stacks/node/templates/root/src/common/replay.ts +16 -0
  168. package/stacks/node/templates/root/src/common/routes.ts +19 -0
  169. package/stacks/node/templates/root/src/common/testHelpers.ts +44 -0
  170. package/stacks/node/templates/root/src/swagger.ts +34 -0
  171. package/stacks/node/templates/root/src/util/assertions.ts +6 -0
  172. package/stacks/node/templates/root/src/util/hash.ts +9 -0
  173. package/stacks/node/templates/root/src/util/sanitize.ts +23 -0
  174. package/stacks/node/templates/root/tsconfig.json +32 -0
  175. package/stacks/node/templates/root/vercel.json +8 -0
  176. package/stacks/supabase/templates/.claude/skills/build-automation/SKILL.md +266 -0
  177. package/stacks/supabase/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  178. package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +390 -0
  179. package/stacks/supabase/templates/.claude/skills/build-webhook/SKILL.md +303 -0
  180. package/stacks/supabase/templates/.claude/skills/connect/SKILL.md +178 -0
  181. package/stacks/supabase/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  182. package/stacks/supabase/templates/.claude/skills/load-slice/SKILL.md +143 -0
  183. package/stacks/supabase/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  184. package/stacks/supabase/templates/build-kit/README.md +86 -0
  185. package/stacks/supabase/templates/build-kit/lib/AGENT.md +47 -0
  186. package/stacks/supabase/templates/build-kit/lib/agent.sh +20 -0
  187. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +152 -0
  188. package/stacks/supabase/templates/build-kit/lib/prompt.md +123 -0
  189. package/stacks/supabase/templates/build-kit/lib/ralph.js +369 -0
  190. package/stacks/supabase/templates/build-kit/ralph-claude.js +44 -0
  191. package/stacks/supabase/templates/build-kit/ralph.sh +98 -0
  192. package/stacks/supabase/templates/root/.env.example +22 -0
  193. package/stacks/supabase/templates/root/CLAUDE.md +61 -0
  194. package/stacks/supabase/templates/root/flyway.conf +17 -0
  195. package/stacks/supabase/templates/root/package.json +52 -0
  196. package/stacks/supabase/templates/root/server.ts +177 -0
  197. package/stacks/supabase/templates/root/setup-env.sh +53 -0
  198. package/stacks/supabase/templates/root/src/common/assertions.ts +6 -0
  199. package/stacks/supabase/templates/root/src/common/db.ts +32 -0
  200. package/stacks/supabase/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  201. package/stacks/supabase/templates/root/src/common/parseEndpoint.ts +51 -0
  202. package/stacks/supabase/templates/root/src/common/processorDlq.ts +28 -0
  203. package/stacks/supabase/templates/root/src/common/realtimeBroadcast.ts +19 -0
  204. package/stacks/supabase/templates/root/src/common/replay.ts +16 -0
  205. package/stacks/supabase/templates/root/src/common/routes.ts +23 -0
  206. package/stacks/supabase/templates/root/src/common/testHelpers.ts +54 -0
  207. package/stacks/supabase/templates/root/src/supabase/README.md +141 -0
  208. package/stacks/supabase/templates/root/src/supabase/api.ts +56 -0
  209. package/stacks/supabase/templates/root/src/supabase/requireOrgaAdmin.ts +32 -0
  210. package/stacks/supabase/templates/root/src/supabase/requireSysUser.ts +40 -0
  211. package/stacks/supabase/templates/root/src/supabase/requireUser.ts +72 -0
  212. package/stacks/supabase/templates/root/src/swagger.ts +34 -0
  213. package/stacks/supabase/templates/root/src/util/assertions.ts +6 -0
  214. package/stacks/supabase/templates/root/src/util/hash.ts +9 -0
  215. package/stacks/supabase/templates/root/src/util/sanitize.ts +23 -0
  216. package/stacks/supabase/templates/root/supabase/config.toml +295 -0
  217. package/stacks/supabase/templates/root/supabase/migrations/V1__schema.sql.example +12 -0
  218. package/stacks/supabase/templates/root/supabase/seed.sql +1 -0
  219. package/stacks/supabase/templates/root/tsconfig.json +32 -0
  220. package/stacks/supabase/templates/root/vercel.json +8 -0
@@ -0,0 +1,479 @@
1
+ ---
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: modernizing legacy systems using the side-car pattern (use eventmodeling-integrating-legacy-systems) or designing command handlers for the translated events (use eventmodeling-designing-event-models)."
4
+ allowed-tools:
5
+ - AskUserQuestion
6
+ - Write
7
+ - Bash
8
+ ---
9
+
10
+ # Translating External Events
11
+
12
+ > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
13
+
14
+ ## Interview Phase (Optional)
15
+
16
+ **When to Interview**: Skip if the user has specified: external systems involved, webhook/API formats, and domain mapping. Interview when external systems haven't been fully cataloged or translation rules are unclear.
17
+
18
+ **Interview Strategy**: Catalog all external systems and understand their event formats before defining translation rules. Missing correlation strategies — how external IDs map back to domain entities — are the most common source of integration failures, so surface them early.
19
+
20
+ ### Critical Questions
21
+
22
+ 1. **External System Details** (Impact: Determines what translation rules to create)
23
+ - Question: "Which external systems send events? For each: (A) System name, (B) Event types, (C) Data format (JSON/XML), (D) Authentication needed?"
24
+ - Why it matters: Translation rules depend entirely on what the external system sends
25
+ - Follow-up triggers: For each system → ask "Does their payload include your internal entity ID, or do you need a correlation reference table?"
26
+
27
+ 2. **Domain Mapping Complexity** (Impact: Determines if translation is straightforward or complex)
28
+ - Question: "For the most complex integration: Does the external event data: (A) Map directly to domain concept, (B) Need aggregation/multiple events, (C) Need data from another system to map?"
29
+ - Why it matters: Simple 1-to-1 mappings vs. complex multi-source translations affect design
30
+ - Follow-up triggers: If (B) or (C) → ask "What data must you look up from your own system to complete the translation? How do you handle arrival before that data exists?"
31
+
32
+ ### Interview Flow
33
+
34
+ **Conditional Entry**:
35
+ ```
36
+ If user has provided:
37
+ - Full list of external systems with event types
38
+ - AND sample payload formats for each event type
39
+ - AND correlation strategy (how to link external IDs to domain entity IDs)
40
+
41
+ Then: Skip interview, proceed directly to translation rule design
42
+
43
+ Else: Conduct interview
44
+ ```
45
+
46
+ **Phase 1: External System Catalog** (Question 1)
47
+ - Enumerate all systems that send events into the domain
48
+ - Document event types and payload formats for each
49
+ - Identify authentication and delivery mechanisms (webhook, polling, streaming)
50
+
51
+ **Phase 2: Mapping Complexity Assessment** (Question 2)
52
+ - Identify which integrations require enrichment from domain data
53
+ - Surface correlation gaps (external ID ≠ domain ID)
54
+ - Flag multi-source aggregations for deeper design attention
55
+
56
+ ### Capturing Interview Findings
57
+
58
+ Append findings to the project's event modeling file:
59
+
60
+ **File**: `.trogonai/interviews/[project-name]/EVENTMODELING.md`
61
+
62
+ Use Write tool to add/update this section:
63
+
64
+ ```markdown
65
+ ## Translating External Events (eventmodeling-translating-external-events)
66
+
67
+ ### External Systems Catalog
68
+ [From Q1: System names, event types, formats, auth mechanisms]
69
+
70
+ ### Mapping Complexity
71
+ [From Q2: Direct mappings vs. complex enrichment needs, correlation gaps]
72
+
73
+ ### Correlation Strategies
74
+ - [System A]: correlates via [reference field / lookup table]
75
+ - [System B]: correlates via [metadata in external payload]
76
+
77
+ ### High-Risk Integrations
78
+ - [System needing multi-source data]: [risk description]
79
+ ```
80
+
81
+ Update Interview Trail:
82
+ ```markdown
83
+ | Ext. Events | eventmodeling-translating-external-events | Done | External systems cataloged, correlation strategies defined |
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Workflow
89
+
90
+ ### 1. Identify External Event Sources
91
+
92
+ Document each external system and what it sends:
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
+ ```
129
+
130
+ ### 2. Analyze Technical Representation
131
+
132
+ Understand the raw data from external system:
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
+ ```
152
+
153
+ ### 3. Define Domain Translation Rules
154
+
155
+ Map technical data to domain concepts:
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
+ ```
182
+
183
+ ### 4. Handle Correlation
184
+
185
+ External systems often don't include your IDs. Establish correlation:
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
+ ```
205
+
206
+ ### 5. Define Translation Scenarios
207
+
208
+ Specify translation logic for each external event:
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
+ ```
239
+
240
+ ### 6. Handle Duplicates and Ordering
241
+
242
+ External systems may send duplicate webhooks:
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
+ ```
265
+
266
+ ### 7. Handle Partial or Missing Information
267
+
268
+ External systems may not provide complete data:
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
+ ```
301
+
302
+ ## Output Format
303
+
304
+ After completing the translation analysis, **place each translated domain event on the board** using the `place-element` skill:
305
+
306
+ | Parameter | Value |
307
+ |-----------|-------|
308
+ | `elementType` | `EVENT` |
309
+ | `title` | `<DomainEventName>` (translated name, not the external event name) |
310
+ | `boardId` | `BOARD_ID` |
311
+ | `timelineId` | the existing chapter/timeline |
312
+
313
+ Then present the full translation rules as text to the user.
314
+
315
+ ---
316
+
317
+ For reference, the full markdown structure is:
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
+ ````
419
+
420
+ ## Quality Checklist
421
+
422
+ - [ ] Every external event type has translation rules
423
+ - [ ] Correlation mechanism defined (how to link back to domain entities)
424
+ - [ ] External IDs captured for deduplication
425
+ - [ ] Missing data handled (enrichment from our system)
426
+ - [ ] Duplicate webhook handling implemented (idempotent)
427
+ - [ ] Failure scenarios documented
428
+ - [ ] Manual review process for unhandled cases
429
+ - [ ] No raw external IDs leak into domain model
430
+ - [ ] All external data validated before translation
431
+ - [ ] Timestamp handling is consistent
432
+ - [ ] Sensitive data from external systems handled properly
433
+
434
+ ## Common Translation Patterns
435
+
436
+ ### Pattern 1: Webhook to Event (Simple Mapping)
437
+ ```
438
+ External webhook → Validate → Map fields → Create domain event
439
+ Example: Payment gateway → PaymentAuthorized
440
+ ```
441
+
442
+ ### Pattern 2: Webhook with Correlation Lookup
443
+ ```
444
+ External webhook → Extract correlation ID → Look up our entity →
445
+ Enrich data → Create domain event
446
+ Example: GPS location + guestId → Look up guest room → GuestLeftHotel
447
+ ```
448
+
449
+ ### Pattern 3: API Polling (Scheduled Fetch)
450
+ ```
451
+ Scheduled job → Call external API → Extract events →
452
+ Translate → Create domain events
453
+ Example: Inventory availability check every 5 minutes
454
+ ```
455
+
456
+ ### Pattern 4: Webhook with Missing Context
457
+ ```
458
+ External webhook (partial data) → Extract what we have →
459
+ Query our system for missing context → Enrich → Create domain event
460
+ Example: Order confirmation from third-party fulfillment with only order ID
461
+ ```
462
+
463
+ ## Key Principles
464
+
465
+ 1. **Correlation First**: Always establish how to link external events to domain entities
466
+ 2. **No Leakage**: Don't expose external IDs/data structures in your event model
467
+ 3. **Translate Intent**: Translate the business meaning, not just map fields
468
+ 4. **Idempotent**: Always handle duplicate external events gracefully
469
+ 5. **Validate Always**: Verify external data before trusting it
470
+ 6. **Enrich from Source**: Look up context from your system, not external system
471
+ 7. **Default Gracefully**: Handle missing data with sensible defaults or explicit failure
472
+
473
+ ## Integration Patterns to Avoid
474
+
475
+ **Direct External IDs**: Using Stripe charge ID as our primary ID
476
+ **No Correlation**: Translating events without way to correlate back
477
+ **Schema Leakage**: Exposing external JSON structure in domain events
478
+ **Unvalidated Data**: Trusting external data without verification
479
+ **Duplicate Processing**: No idempotent check, processes same webhook twice