@rashidee/co2 1.2.5

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 (190) hide show
  1. package/dist/index.js +25449 -0
  2. package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
  3. package/drizzle/0001_wise_wolf_cub.sql +13 -0
  4. package/drizzle/0002_secret_spyke.sql +16 -0
  5. package/drizzle/0003_workspace_config_singleton.sql +16 -0
  6. package/drizzle/0004_terminal_claim_v120.sql +11 -0
  7. package/drizzle/0005_brainstorm_v124.sql +10 -0
  8. package/drizzle/0006_project_v140.sql +6 -0
  9. package/drizzle/0007_prd_wizard_v124.sql +14 -0
  10. package/drizzle/0008_workflow_artifact_v126.sql +24 -0
  11. package/drizzle/0009_project_import_v150.sql +7 -0
  12. package/drizzle/0010_quality_v151.sql +3 -0
  13. package/drizzle/meta/0000_snapshot.json +1335 -0
  14. package/drizzle/meta/0001_snapshot.json +1416 -0
  15. package/drizzle/meta/0002_snapshot.json +1510 -0
  16. package/drizzle/meta/_journal.json +83 -0
  17. package/package.json +41 -0
  18. package/plugin/.claude-plugin/marketplace.json +36 -0
  19. package/plugin/.claude-plugin/plugin.json +22 -0
  20. package/plugin/README.md +625 -0
  21. package/plugin/SKILLS.md +350 -0
  22. package/plugin/co2.svg +5 -0
  23. package/plugin/commands/brainstorm-loop.md +129 -0
  24. package/plugin/skills/conductor-defect/SKILL.md +898 -0
  25. package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
  26. package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
  27. package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
  28. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
  29. package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
  30. package/plugin/skills/depgen-k8s/SKILL.md +468 -0
  31. package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
  32. package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
  33. package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
  34. package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
  35. package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
  36. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
  37. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
  38. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
  39. package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
  40. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
  41. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
  42. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
  43. package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
  44. package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
  45. package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
  46. package/plugin/skills/modelgen-relational/SKILL.md +707 -0
  47. package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
  48. package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
  49. package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
  50. package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
  51. package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
  52. package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
  53. package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
  54. package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
  55. package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
  56. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
  57. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
  58. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
  59. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
  60. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
  61. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
  62. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
  63. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
  64. package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
  65. package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
  66. package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
  67. package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
  68. package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
  69. package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
  70. package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
  71. package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
  72. package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
  73. package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
  74. package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
  75. package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
  76. package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
  77. package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
  78. package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
  79. package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
  80. package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
  81. package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
  82. package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
  83. package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
  84. package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
  85. package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
  86. package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
  87. package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
  88. package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
  89. package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
  90. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
  91. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
  92. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
  93. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
  94. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
  95. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
  96. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
  97. package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
  98. package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
  99. package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
  100. package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
  101. package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
  102. package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
  103. package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
  104. package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
  105. package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
  106. package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
  107. package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
  108. package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
  109. package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
  110. package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
  111. package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
  112. package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
  113. package/plugin/skills/testgen-functional/SKILL.md +1381 -0
  114. package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
  115. package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
  116. package/plugin/skills/util-projectinit/SKILL.md +307 -0
  117. package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
  118. package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
  119. package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
  120. package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
  121. package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
  122. package/plugin/skills/util-projectsync/SKILL.md +501 -0
  123. package/plugin/skills/util-updprd/SKILL.md +324 -0
  124. package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
  125. package/plugin/skills/util-ustagger/SKILL.md +154 -0
  126. package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
  127. package/static/assets/arc-DRKw7sjs.js +1 -0
  128. package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
  129. package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
  130. package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
  131. package/static/assets/channel-C2nVbuwv.js +1 -0
  132. package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
  133. package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
  134. package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
  135. package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
  136. package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
  137. package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
  138. package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
  139. package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
  140. package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
  141. package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
  142. package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
  143. package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
  144. package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
  145. package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
  146. package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
  147. package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  148. package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
  149. package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  150. package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
  151. package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
  152. package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
  153. package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
  154. package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
  155. package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
  156. package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
  157. package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
  158. package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
  159. package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
  160. package/static/assets/graph-C9eacEi8.js +1 -0
  161. package/static/assets/index-LZSQkLE2.css +41 -0
  162. package/static/assets/index-y7XDSgMG.js +495 -0
  163. package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
  164. package/static/assets/init-Gi6I4Gst.js +1 -0
  165. package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
  166. package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
  167. package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
  168. package/static/assets/katex-C5jXJg4s.js +257 -0
  169. package/static/assets/layout-DEXfKzaS.js +1 -0
  170. package/static/assets/linear-CLO--ryk.js +1 -0
  171. package/static/assets/map-Czzmt4hB.js +1 -0
  172. package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
  173. package/static/assets/ordinal-Cboi1Yqb.js +1 -0
  174. package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
  175. package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
  176. package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
  177. package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
  178. package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
  179. package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
  180. package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
  181. package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
  182. package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
  183. package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
  184. package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
  185. package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
  186. package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
  187. package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
  188. package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
  189. package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
  190. package/static/index.html +24 -0
@@ -0,0 +1,461 @@
1
+ # Laravel Modules Patterns — Module Structure & Event Architecture
2
+
3
+ This reference describes the nwidart/laravel-modules conventions used in the spec. Include
4
+ this content in Sections 5 and 19 of the generated specification.
5
+
6
+ ---
7
+
8
+ ## Module Boundary Rules
9
+
10
+ nwidart/laravel-modules enforces modular boundaries by treating each module as an
11
+ independent package with its own namespace, routes, views, migrations, and service
12
+ providers. This spec uses a strict encapsulation model: public API via contracts and
13
+ DTOs, all implementation internal to the module.
14
+
15
+ ### What constitutes a module
16
+
17
+ ```
18
+ app/
19
+ ├── Http/Middleware/ ← NOT a module (shared middleware)
20
+ ├── Services/ ← NOT a module (shared services)
21
+ ├── Models/ ← NOT a module (shared base models like User)
22
+ ├── Traits/ ← NOT a module (shared traits)
23
+ ├── Constants/ ← NOT a module (shared constants)
24
+ ├── Exceptions/ ← NOT a module (shared exceptions)
25
+ └── Providers/ ← NOT a module (shared service providers)
26
+
27
+ Modules/
28
+ ├── Order/ ← MODULE: Order bounded context
29
+ ├── Inventory/ ← MODULE: Inventory bounded context
30
+ ├── Scheduling/ ← MODULE: Scheduling bounded context
31
+ └── ...
32
+ ```
33
+
34
+ Each module is generated via `php artisan module:make <ModuleName>` and follows the
35
+ nwidart/laravel-modules directory convention.
36
+
37
+ ### Visibility rules — Public API vs Internal Implementation
38
+
39
+ Each module has a strict two-layer structure:
40
+
41
+ ```
42
+ Modules/Order/ ← MODULE ROOT
43
+ ├── Contracts/ ← PUBLIC API (visible to other modules)
44
+ │ └── OrderServiceInterface.php ← Service interface
45
+ ├── DTOs/ ← PUBLIC API
46
+ │ └── OrderData.php ← spatie/laravel-data DTO
47
+ ├── Events/ ← PUBLIC API
48
+ │ └── OrderCreatedEvent.php ← Domain event
49
+ ├── Exceptions/ ← PUBLIC API
50
+ │ └── OrderException.php ← Module-specific exception
51
+
52
+ ├── Services/ ← INTERNAL
53
+ │ └── OrderService.php ← Implements OrderServiceInterface
54
+ ├── Models/ ← INTERNAL
55
+ │ └── Order.php ← Eloquent model
56
+ ├── Repositories/ ← INTERNAL (optional)
57
+ │ └── OrderRepository.php ← Query abstraction
58
+ ├── Http/ ← INTERNAL
59
+ │ ├── Controllers/
60
+ │ │ ├── OrderPageController.php ← Page controller (full HTML)
61
+ │ │ └── OrderFragmentController.php ← Fragment controller (htmx)
62
+ │ └── Requests/
63
+ │ ├── StoreOrderRequest.php ← Form validation
64
+ │ └── UpdateOrderRequest.php
65
+ ├── ViewModels/ ← INTERNAL
66
+ │ ├── OrderListViewModel.php ← List page view model
67
+ │ └── OrderDetailViewModel.php ← Detail page view model
68
+ ├── database/
69
+ │ └── migrations/ ← INTERNAL
70
+ │ └── 2024_01_01_000000_create_orders_table.php
71
+ ├── resources/
72
+ │ └── views/ ← INTERNAL
73
+ │ ├── pages/
74
+ │ │ ├── index.blade.php ← List page
75
+ │ │ ├── show.blade.php ← Detail page
76
+ │ │ ├── create.blade.php ← Create form
77
+ │ │ └── edit.blade.php ← Edit form
78
+ │ └── fragments/
79
+ │ ├── order-row.blade.php ← Table row fragment
80
+ │ └── search-results.blade.php ← Search results fragment
81
+ ├── routes/
82
+ │ └── web.php ← Module routes
83
+ ├── Config/
84
+ │ └── config.php ← Module config
85
+ ├── Providers/
86
+ │ └── OrderServiceProvider.php ← Module service provider
87
+ └── Tests/
88
+ ├── Feature/
89
+ └── Unit/
90
+ ```
91
+
92
+ **Public API (Contracts, DTOs, Events, Exceptions)** — only these types are visible to
93
+ other modules:
94
+ - `OrderServiceInterface` — Interface. The sole programmatic entry point for other modules.
95
+ Other modules inject this interface; Laravel wires the internal `OrderService` via the
96
+ module's service provider.
97
+ - `OrderData` — The data contract. When `OrderServiceInterface` returns data, it returns
98
+ this DTO, never the internal `Order` Eloquent model. This prevents leaking persistence
99
+ details.
100
+ - `OrderException` — Callers can catch module-specific failures.
101
+ - `OrderCreatedEvent` — Domain events must be in the public namespace so listeners in
102
+ other modules can reference the event type.
103
+
104
+ **Internal implementation** — invisible to other modules by convention:
105
+ - `OrderService` — Contains all business logic, Eloquent queries, event dispatching.
106
+ - `Order` — The Eloquent model is internal. It may have casts, relationships, or scopes
107
+ that are irrelevant to consumers.
108
+ - `OrderRepository` — Data access abstraction (optional — some teams query directly in
109
+ the service).
110
+ - `OrderPageController` — The controller is an **inbound adapter**. Other modules never
111
+ call controllers.
112
+ - `OrderListViewModel` — View models are internal to the module.
113
+
114
+ ### Module Service Provider Binding
115
+
116
+ Each module's service provider binds the interface to the implementation:
117
+
118
+ ```php
119
+ namespace Modules\Order\Providers;
120
+
121
+ use Illuminate\Support\ServiceProvider;
122
+ use Modules\Order\Contracts\OrderServiceInterface;
123
+ use Modules\Order\Services\OrderService;
124
+
125
+ class OrderServiceProvider extends ServiceProvider
126
+ {
127
+ public function register(): void
128
+ {
129
+ $this->app->bind(OrderServiceInterface::class, OrderService::class);
130
+ }
131
+
132
+ public function boot(): void
133
+ {
134
+ $this->loadMigrationsFrom(module_path('Order', 'database/migrations'));
135
+ $this->loadViewsFrom(module_path('Order', 'resources/views'), 'order');
136
+ $this->loadRoutesFrom(module_path('Order', 'routes/web.php'));
137
+ }
138
+ }
139
+ ```
140
+
141
+ ### Inter-module dependency direction
142
+
143
+ ```
144
+ OrderPageController (internal) → OrderServiceInterface (public contract)
145
+
146
+ InventoryService (another module) → OrderServiceInterface (public contract)
147
+ ```
148
+
149
+ Both the internal controller and external modules depend on the same public interface.
150
+ The `OrderService` implementation is wired by Laravel's service container but never
151
+ directly referenced.
152
+
153
+ ### What modules must NOT do
154
+
155
+ - Never inject a Service class from another module — use the Contract interface
156
+ - Never reference another module's `Models/`, `Services/`, or `Http/` namespace
157
+ - Never reference another module's Eloquent Model directly
158
+ - Never create circular dependencies between modules
159
+ - Never bypass the service interface by calling another module's controller
160
+
161
+ ---
162
+
163
+ ## Inter-Module Communication via Events
164
+
165
+ When one module needs to notify others about a domain event (e.g., an order was created
166
+ and inventory needs to adjust), use Laravel's event system.
167
+
168
+ ### Event Class Convention
169
+
170
+ Events are plain PHP classes, immutable, and carry only the data the listener needs.
171
+
172
+ Naming: `<AggregateRoot><PastTenseVerb>Event`
173
+
174
+ ```php
175
+ // In Modules/Order/Events/ (module public — visible to other modules)
176
+ namespace Modules\Order\Events;
177
+
178
+ use Illuminate\Foundation\Events\Dispatchable;
179
+ use Illuminate\Queue\SerializesModels;
180
+
181
+ class OrderCreatedEvent
182
+ {
183
+ use Dispatchable, SerializesModels;
184
+
185
+ public function __construct(
186
+ public readonly string $orderId,
187
+ public readonly string $customerId,
188
+ public readonly \DateTimeImmutable $occurredAt,
189
+ ) {}
190
+ }
191
+ ```
192
+
193
+ Why readonly properties: they're immutable and make the event's contract explicit.
194
+ Using `DateTimeImmutable` establishes when the event happened.
195
+
196
+ ### Publishing Events
197
+
198
+ The service implementation (internal) publishes events using Laravel's `event()` helper
199
+ or `Event` facade:
200
+
201
+ ```php
202
+ // In Modules/Order/Services/ (INTERNAL)
203
+ namespace Modules\Order\Services;
204
+
205
+ use Modules\Order\Contracts\OrderServiceInterface;
206
+ use Modules\Order\DTOs\OrderData;
207
+ use Modules\Order\Events\OrderCreatedEvent;
208
+ use Modules\Order\Models\Order;
209
+
210
+ class OrderService implements OrderServiceInterface
211
+ {
212
+ public function create(array $data): OrderData
213
+ {
214
+ $order = Order::create($data);
215
+
216
+ event(new OrderCreatedEvent(
217
+ orderId: $order->id,
218
+ customerId: $order->customer_id,
219
+ occurredAt: new \DateTimeImmutable(),
220
+ ));
221
+
222
+ return OrderData::from($order);
223
+ }
224
+ }
225
+ ```
226
+
227
+ ### Listening to Events
228
+
229
+ Other modules listen using Laravel listeners in their service provider:
230
+
231
+ ```php
232
+ // In Modules/Inventory/Listeners/ (INTERNAL)
233
+ namespace Modules\Inventory\Listeners;
234
+
235
+ use Illuminate\Contracts\Queue\ShouldQueue;
236
+ use Modules\Order\Events\OrderCreatedEvent;
237
+
238
+ class AdjustInventoryOnOrderCreated implements ShouldQueue
239
+ {
240
+ public bool $afterCommit = true;
241
+
242
+ public function handle(OrderCreatedEvent $event): void
243
+ {
244
+ // Business logic to reserve inventory
245
+ logger()->info("Adjusting inventory for order: {$event->orderId}");
246
+ }
247
+ }
248
+ ```
249
+
250
+ Register in the module's `EventServiceProvider` or `boot()`:
251
+ ```php
252
+ // In Modules/Inventory/Providers/InventoryServiceProvider.php
253
+ use Illuminate\Support\Facades\Event;
254
+ use Modules\Inventory\Listeners\AdjustInventoryOnOrderCreated;
255
+ use Modules\Order\Events\OrderCreatedEvent;
256
+
257
+ public function boot(): void
258
+ {
259
+ Event::listen(OrderCreatedEvent::class, AdjustInventoryOnOrderCreated::class);
260
+ }
261
+ ```
262
+
263
+ The listener references `OrderCreatedEvent` which is in the `Order` module's public
264
+ `Events/` namespace, so this cross-module reference is valid. The listener implementation
265
+ itself is internal to the `Inventory` module.
266
+
267
+ `ShouldQueue` + `$afterCommit = true` means:
268
+ - The listener runs in a separate queue job
269
+ - It executes after the publishing transaction commits
270
+ - Failures in the listener do not roll back the publisher
271
+
272
+ ### Event Publication Persistence
273
+
274
+ For at-least-once delivery semantics, consider:
275
+ 1. Using Laravel's queue system with database driver (failed jobs are retried)
276
+ 2. Implementing a custom `event_publications` table for tracking delivery status
277
+ 3. Using `spatie/laravel-event-sourcing` for full event sourcing
278
+
279
+ Configuration in `config/queue.php`:
280
+ ```php
281
+ 'connections' => [
282
+ 'database' => [
283
+ 'driver' => 'database',
284
+ 'table' => 'jobs',
285
+ 'queue' => 'default',
286
+ 'retry_after' => 90,
287
+ 'after_commit' => true,
288
+ ],
289
+ ],
290
+ ```
291
+
292
+ ---
293
+
294
+ ## Module Verification
295
+
296
+ To verify module boundaries are respected, use `phpat/phpat` architecture tests:
297
+
298
+ ```php
299
+ namespace Tests\Architecture;
300
+
301
+ use PHPat\Selector\Selector;
302
+ use PHPat\Test\Builder\Rule;
303
+ use PHPat\Test\PHPat;
304
+
305
+ class ModuleBoundaryTest
306
+ {
307
+ public function test_modules_only_depend_on_public_api(): Rule
308
+ {
309
+ return PHPat::rule()
310
+ ->classes(Selector::inNamespace('Modules\Inventory'))
311
+ ->canOnlyDependOn()
312
+ ->classes(
313
+ Selector::inNamespace('Modules\Order\Contracts'),
314
+ Selector::inNamespace('Modules\Order\DTOs'),
315
+ Selector::inNamespace('Modules\Order\Events'),
316
+ Selector::inNamespace('Modules\Order\Exceptions'),
317
+ // ... other public namespaces
318
+ Selector::inNamespace('Illuminate'),
319
+ Selector::inNamespace('App'),
320
+ );
321
+ }
322
+ }
323
+ ```
324
+
325
+ This test catches:
326
+ - Direct dependencies between modules that bypass contracts
327
+ - Circular module dependencies
328
+ - References to another module's internal types (Models, Services, Http)
329
+
330
+ Include this test in the Testing Strategy section of the spec. It should run as part
331
+ of CI to enforce architectural integrity continuously.
332
+
333
+ ---
334
+
335
+ ## Web Application Module Adaptations
336
+
337
+ For server-rendered web applications, each module includes `pages/` and `fragments/`
338
+ view directories, page and fragment controllers, and view models.
339
+
340
+ ### Key Patterns
341
+
342
+ 1. **No REST controllers**: Web modules use standard `Controller` returning Blade views,
343
+ not JSON API responses.
344
+
345
+ 2. **Direct data ownership**: Each module owns its Eloquent models and migrations.
346
+ The service layer queries the database directly via Eloquent.
347
+
348
+ 3. **View models**: Each page has a dedicated view model class (`spatie/laravel-view-models`)
349
+ that encapsulates all data needed by the Blade template. View models are internal.
350
+
351
+ 4. **Page vs Fragment separation**: `pages/` holds Blade views for full page renders;
352
+ `fragments/` holds Blade views that return partial HTML for htmx requests.
353
+
354
+ 5. **Form Requests**: Controllers use Form Request classes for validation. Validation
355
+ rules are defined per-action (Store, Update, etc.).
356
+
357
+ ### Web Page Controller Pattern
358
+
359
+ ```php
360
+ namespace Modules\Order\Http\Controllers;
361
+
362
+ use Illuminate\Http\Request;
363
+ use Illuminate\View\View;
364
+ use Modules\Order\Contracts\OrderServiceInterface;
365
+ use Modules\Order\ViewModels\OrderListViewModel;
366
+ use Modules\Order\ViewModels\OrderDetailViewModel;
367
+
368
+ class OrderPageController extends Controller
369
+ {
370
+ public function __construct(
371
+ private readonly OrderServiceInterface $orderService,
372
+ ) {}
373
+
374
+ public function index(Request $request): View
375
+ {
376
+ $items = $this->orderService->list(
377
+ page: $request->integer('page', 1),
378
+ perPage: 20,
379
+ );
380
+
381
+ return (new OrderListViewModel(
382
+ items: $items,
383
+ theme: $request->cookie('theme', 'light'),
384
+ user: auth()->user(),
385
+ ))->view('order::pages.index');
386
+ }
387
+
388
+ public function show(string $id, Request $request): View
389
+ {
390
+ $order = $this->orderService->get($id);
391
+
392
+ return (new OrderDetailViewModel(
393
+ order: $order,
394
+ theme: $request->cookie('theme', 'light'),
395
+ user: auth()->user(),
396
+ ))->view('order::pages.show');
397
+ }
398
+ }
399
+ ```
400
+
401
+ ### Web Fragment Controller Pattern
402
+
403
+ ```php
404
+ namespace Modules\Order\Http\Controllers;
405
+
406
+ use Illuminate\Http\Request;
407
+ use Illuminate\Http\Response;
408
+ use Illuminate\View\View;
409
+ use Modules\Order\Contracts\OrderServiceInterface;
410
+
411
+ class OrderFragmentController extends Controller
412
+ {
413
+ public function __construct(
414
+ private readonly OrderServiceInterface $orderService,
415
+ ) {}
416
+
417
+ public function row(string $id): View
418
+ {
419
+ $order = $this->orderService->get($id);
420
+ return view('order::fragments.order-row', ['item' => $order]);
421
+ }
422
+
423
+ public function search(Request $request): View
424
+ {
425
+ $results = $this->orderService->search($request->input('q', ''));
426
+ return view('order::fragments.search-results', ['items' => $results]);
427
+ }
428
+
429
+ public function destroy(string $id): Response
430
+ {
431
+ $this->orderService->delete($id);
432
+ return response('', 200);
433
+ }
434
+ }
435
+ ```
436
+
437
+ ### Module Route File
438
+
439
+ ```php
440
+ // Modules/Order/routes/web.php
441
+ use Illuminate\Support\Facades\Route;
442
+ use Modules\Order\Http\Controllers\OrderPageController;
443
+ use Modules\Order\Http\Controllers\OrderFragmentController;
444
+
445
+ Route::middleware(['auth', 'role:HUB_ADMINISTRATOR|HUB_OPERATION_SUPPORT'])
446
+ ->group(function () {
447
+ // Page routes
448
+ Route::get('/orders', [OrderPageController::class, 'index'])->name('order.index');
449
+ Route::get('/orders/create', [OrderPageController::class, 'create'])->name('order.create');
450
+ Route::post('/orders', [OrderPageController::class, 'store'])->name('order.store');
451
+ Route::get('/orders/{id}', [OrderPageController::class, 'show'])->name('order.show');
452
+ Route::get('/orders/{id}/edit', [OrderPageController::class, 'edit'])->name('order.edit');
453
+ Route::put('/orders/{id}', [OrderPageController::class, 'update'])->name('order.update');
454
+ Route::delete('/orders/{id}', [OrderPageController::class, 'destroy'])->name('order.destroy');
455
+
456
+ // Fragment routes (htmx)
457
+ Route::get('/orders/fragments/search', [OrderFragmentController::class, 'search'])->name('order.fragments.search');
458
+ Route::get('/orders/fragments/row/{id}', [OrderFragmentController::class, 'row'])->name('order.fragments.row');
459
+ Route::delete('/orders/fragments/{id}', [OrderFragmentController::class, 'destroy'])->name('order.fragments.destroy');
460
+ });
461
+ ```