@c0x12c/ai-toolkit 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +439 -0
  4. package/VERSION +1 -0
  5. package/agents/design-critic.md +127 -0
  6. package/agents/idea-killer.md +72 -0
  7. package/agents/infrastructure-expert.md +49 -0
  8. package/agents/micronaut-backend-expert.md +45 -0
  9. package/agents/phase-reviewer.md +150 -0
  10. package/agents/research-planner.md +70 -0
  11. package/agents/solution-architect-cto.md +49 -0
  12. package/agents/sre-architect.md +49 -0
  13. package/agents/team-coordinator.md +111 -0
  14. package/bin/cli.js +780 -0
  15. package/claude-md/00-header.md +39 -0
  16. package/claude-md/01-core.md +105 -0
  17. package/claude-md/05-database.md +20 -0
  18. package/claude-md/11-backend-micronaut.md +19 -0
  19. package/claude-md/20-frontend-react.md +44 -0
  20. package/claude-md/25-ux-design.md +56 -0
  21. package/claude-md/30-infrastructure.md +24 -0
  22. package/claude-md/30-project-mgmt.md +119 -0
  23. package/claude-md/40-product.md +39 -0
  24. package/claude-md/50-ops.md +34 -0
  25. package/claude-md/60-research.md +27 -0
  26. package/claude-md/90-footer.md +21 -0
  27. package/commands/spartan/brainstorm.md +134 -0
  28. package/commands/spartan/brownfield.md +157 -0
  29. package/commands/spartan/build.md +435 -0
  30. package/commands/spartan/careful.md +94 -0
  31. package/commands/spartan/commit-message.md +112 -0
  32. package/commands/spartan/content.md +17 -0
  33. package/commands/spartan/context-save.md +161 -0
  34. package/commands/spartan/contribute.md +140 -0
  35. package/commands/spartan/daily.md +42 -0
  36. package/commands/spartan/debug.md +308 -0
  37. package/commands/spartan/deep-dive.md +55 -0
  38. package/commands/spartan/deploy.md +207 -0
  39. package/commands/spartan/e2e.md +264 -0
  40. package/commands/spartan/env-setup.md +166 -0
  41. package/commands/spartan/epic.md +199 -0
  42. package/commands/spartan/fe-review.md +181 -0
  43. package/commands/spartan/figma-to-code.md +260 -0
  44. package/commands/spartan/forensics.md +46 -0
  45. package/commands/spartan/freeze.md +84 -0
  46. package/commands/spartan/fundraise.md +53 -0
  47. package/commands/spartan/gate-review.md +229 -0
  48. package/commands/spartan/gsd-upgrade.md +376 -0
  49. package/commands/spartan/guard.md +42 -0
  50. package/commands/spartan/init-project.md +178 -0
  51. package/commands/spartan/init-rules.md +298 -0
  52. package/commands/spartan/interview.md +154 -0
  53. package/commands/spartan/kickoff.md +73 -0
  54. package/commands/spartan/kotlin-service.md +109 -0
  55. package/commands/spartan/lean-canvas.md +222 -0
  56. package/commands/spartan/lint-rules.md +122 -0
  57. package/commands/spartan/map-codebase.md +124 -0
  58. package/commands/spartan/migration.md +82 -0
  59. package/commands/spartan/next-app.md +317 -0
  60. package/commands/spartan/next-feature.md +212 -0
  61. package/commands/spartan/onboard.md +326 -0
  62. package/commands/spartan/outreach.md +16 -0
  63. package/commands/spartan/phase.md +142 -0
  64. package/commands/spartan/pitch.md +18 -0
  65. package/commands/spartan/plan.md +210 -0
  66. package/commands/spartan/pr-ready.md +202 -0
  67. package/commands/spartan/project.md +106 -0
  68. package/commands/spartan/qa.md +222 -0
  69. package/commands/spartan/research.md +254 -0
  70. package/commands/spartan/review.md +132 -0
  71. package/commands/spartan/scan-rules.md +173 -0
  72. package/commands/spartan/sessions.md +143 -0
  73. package/commands/spartan/spec.md +131 -0
  74. package/commands/spartan/startup.md +257 -0
  75. package/commands/spartan/team.md +570 -0
  76. package/commands/spartan/teardown.md +161 -0
  77. package/commands/spartan/testcontainer.md +97 -0
  78. package/commands/spartan/tf-cost.md +123 -0
  79. package/commands/spartan/tf-deploy.md +116 -0
  80. package/commands/spartan/tf-drift.md +100 -0
  81. package/commands/spartan/tf-import.md +107 -0
  82. package/commands/spartan/tf-module.md +121 -0
  83. package/commands/spartan/tf-plan.md +100 -0
  84. package/commands/spartan/tf-review.md +106 -0
  85. package/commands/spartan/tf-scaffold.md +109 -0
  86. package/commands/spartan/tf-security.md +147 -0
  87. package/commands/spartan/think.md +221 -0
  88. package/commands/spartan/unfreeze.md +13 -0
  89. package/commands/spartan/update.md +134 -0
  90. package/commands/spartan/ux.md +1233 -0
  91. package/commands/spartan/validate.md +193 -0
  92. package/commands/spartan/web-to-prd.md +706 -0
  93. package/commands/spartan/workstreams.md +109 -0
  94. package/commands/spartan/write.md +16 -0
  95. package/commands/spartan.md +386 -0
  96. package/frameworks/00-framework-comparison-guide.md +317 -0
  97. package/frameworks/01-lean-canvas.md +196 -0
  98. package/frameworks/02-design-sprint.md +304 -0
  99. package/frameworks/03-foundation-sprint.md +337 -0
  100. package/frameworks/04-business-model-canvas.md +391 -0
  101. package/frameworks/05-customer-development.md +426 -0
  102. package/frameworks/06-jobs-to-be-done.md +358 -0
  103. package/frameworks/07-mom-test.md +392 -0
  104. package/frameworks/08-value-proposition-canvas.md +488 -0
  105. package/frameworks/09-javelin-board.md +428 -0
  106. package/frameworks/10-build-measure-learn.md +467 -0
  107. package/frameworks/11-mvp-approaches.md +533 -0
  108. package/frameworks/think-before-build.md +593 -0
  109. package/lib/assembler.js +197 -0
  110. package/lib/assembler.test.js +159 -0
  111. package/lib/detector.js +166 -0
  112. package/lib/detector.test.js +221 -0
  113. package/lib/packs.js +16 -0
  114. package/lib/resolver.js +272 -0
  115. package/lib/resolver.test.js +298 -0
  116. package/lib/worktree.sh +104 -0
  117. package/package.json +50 -0
  118. package/packs/backend-micronaut.yaml +35 -0
  119. package/packs/backend-nodejs.yaml +15 -0
  120. package/packs/backend-python.yaml +15 -0
  121. package/packs/core.yaml +37 -0
  122. package/packs/database.yaml +21 -0
  123. package/packs/frontend-react.yaml +24 -0
  124. package/packs/infrastructure.yaml +40 -0
  125. package/packs/ops.yaml +16 -0
  126. package/packs/packs.compiled.json +371 -0
  127. package/packs/product.yaml +22 -0
  128. package/packs/project-mgmt.yaml +24 -0
  129. package/packs/research.yaml +39 -0
  130. package/packs/shared-backend.yaml +14 -0
  131. package/packs/ux-design.yaml +21 -0
  132. package/rules/backend-micronaut/API_DESIGN.md +313 -0
  133. package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
  134. package/rules/backend-micronaut/CONTROLLERS.md +388 -0
  135. package/rules/backend-micronaut/KOTLIN.md +414 -0
  136. package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
  137. package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
  138. package/rules/core/NAMING_CONVENTIONS.md +208 -0
  139. package/rules/core/SKILL_AUTHORING.md +174 -0
  140. package/rules/core/TIMEZONE.md +316 -0
  141. package/rules/database/ORM_AND_REPO.md +289 -0
  142. package/rules/database/SCHEMA.md +146 -0
  143. package/rules/database/TRANSACTIONS.md +311 -0
  144. package/rules/frontend-react/FRONTEND.md +344 -0
  145. package/rules/infrastructure/MODULES.md +260 -0
  146. package/rules/infrastructure/NAMING.md +196 -0
  147. package/rules/infrastructure/PROVIDERS.md +309 -0
  148. package/rules/infrastructure/SECURITY.md +310 -0
  149. package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
  150. package/rules/infrastructure/STRUCTURE.md +234 -0
  151. package/rules/infrastructure/VARIABLES.md +285 -0
  152. package/rules/shared-backend/ARCHITECTURE.md +46 -0
  153. package/rules/ux-design/DESIGN_PROCESS.md +176 -0
  154. package/skills/api-endpoint-creator/SKILL.md +455 -0
  155. package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
  156. package/skills/api-endpoint-creator/examples.md +522 -0
  157. package/skills/api-endpoint-creator/testing-patterns.md +302 -0
  158. package/skills/article-writing/SKILL.md +109 -0
  159. package/skills/article-writing/examples.md +59 -0
  160. package/skills/backend-api-design/SKILL.md +84 -0
  161. package/skills/backend-api-design/code-patterns.md +138 -0
  162. package/skills/brainstorm/SKILL.md +95 -0
  163. package/skills/browser-qa/SKILL.md +87 -0
  164. package/skills/browser-qa/playwright-snippets.md +110 -0
  165. package/skills/ci-cd-patterns/SKILL.md +108 -0
  166. package/skills/ci-cd-patterns/workflows.md +149 -0
  167. package/skills/competitive-teardown/SKILL.md +93 -0
  168. package/skills/competitive-teardown/example-analysis.md +50 -0
  169. package/skills/content-engine/SKILL.md +131 -0
  170. package/skills/content-engine/examples.md +72 -0
  171. package/skills/database-patterns/SKILL.md +72 -0
  172. package/skills/database-patterns/code-templates.md +114 -0
  173. package/skills/database-table-creator/SKILL.md +141 -0
  174. package/skills/database-table-creator/examples.md +552 -0
  175. package/skills/database-table-creator/kotlin-templates.md +400 -0
  176. package/skills/database-table-creator/migration-template.sql +68 -0
  177. package/skills/database-table-creator/validation-checklist.md +337 -0
  178. package/skills/deep-research/SKILL.md +80 -0
  179. package/skills/design-intelligence/SKILL.md +268 -0
  180. package/skills/design-workflow/SKILL.md +127 -0
  181. package/skills/design-workflow/checklists.md +45 -0
  182. package/skills/idea-validation/SKILL.md +129 -0
  183. package/skills/idea-validation/example-report.md +50 -0
  184. package/skills/investor-materials/SKILL.md +122 -0
  185. package/skills/investor-materials/example-outline.md +70 -0
  186. package/skills/investor-outreach/SKILL.md +112 -0
  187. package/skills/investor-outreach/examples.md +76 -0
  188. package/skills/kotlin-best-practices/SKILL.md +58 -0
  189. package/skills/kotlin-best-practices/code-patterns.md +132 -0
  190. package/skills/market-research/SKILL.md +99 -0
  191. package/skills/security-checklist/SKILL.md +65 -0
  192. package/skills/security-checklist/audit-reference.md +95 -0
  193. package/skills/service-debugging/SKILL.md +116 -0
  194. package/skills/service-debugging/common-issues.md +65 -0
  195. package/skills/startup-pipeline/SKILL.md +152 -0
  196. package/skills/terraform-best-practices/SKILL.md +244 -0
  197. package/skills/terraform-module-creator/SKILL.md +284 -0
  198. package/skills/terraform-review/SKILL.md +222 -0
  199. package/skills/terraform-security-audit/SKILL.md +280 -0
  200. package/skills/terraform-service-scaffold/SKILL.md +574 -0
  201. package/skills/testing-strategies/SKILL.md +116 -0
  202. package/skills/testing-strategies/examples.md +103 -0
  203. package/skills/testing-strategies/integration-test-setup.md +71 -0
  204. package/skills/ui-ux-pro-max/SKILL.md +238 -0
  205. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  206. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  207. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  208. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  209. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  210. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  211. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  212. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  213. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  214. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  215. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  216. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  217. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  218. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  219. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  220. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  221. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  222. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  223. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  224. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  225. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  226. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  227. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  228. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  229. package/skills/ui-ux-pro-max/python-setup.md +146 -0
  230. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  231. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  232. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  233. package/skills/web-to-prd/SKILL.md +478 -0
  234. package/templates/build-config.yaml +44 -0
  235. package/templates/commands-config.yaml +55 -0
  236. package/templates/competitor-analysis.md +60 -0
  237. package/templates/content/AGENT_TEMPLATE.md +47 -0
  238. package/templates/content/COMMAND_TEMPLATE.md +27 -0
  239. package/templates/content/RULE_TEMPLATE.md +40 -0
  240. package/templates/content/SKILL_TEMPLATE.md +41 -0
  241. package/templates/design-config.md +105 -0
  242. package/templates/design-doc.md +207 -0
  243. package/templates/epic.md +100 -0
  244. package/templates/feature-spec.md +181 -0
  245. package/templates/idea-canvas.md +47 -0
  246. package/templates/implementation-plan.md +159 -0
  247. package/templates/prd-template.md +86 -0
  248. package/templates/preamble.md +89 -0
  249. package/templates/project-readme.md +35 -0
  250. package/templates/quality-gates.md +230 -0
  251. package/templates/spartan-config.yaml +164 -0
  252. package/templates/user-interview.md +69 -0
  253. package/templates/validation-checklist.md +108 -0
  254. package/templates/workflow-backend-micronaut.md +409 -0
  255. package/templates/workflow-frontend-react.md +233 -0
@@ -0,0 +1,146 @@
1
+ # Database Schema Rules
2
+
3
+ > Full guide: use /database-patterns or /database-table-creator skill
4
+
5
+ ## Core Principles
6
+ 1. **Simplicity First** — Keep it simple, avoid over-engineering
7
+ 2. **No Foreign Keys** — Handle relationships at application level
8
+ 3. **No CASCADE** — Handle deletions in application
9
+ 4. **Consistent Data Types** — Use TEXT instead of VARCHAR
10
+
11
+ ## Schema Rules
12
+
13
+ ### Table Design
14
+ - **No REFERENCES** — Never use foreign key constraints
15
+ - **No ON DELETE CASCADE** — Handle deletions in application
16
+ - **TEXT not VARCHAR** — Always use TEXT for strings
17
+ - **UUID primary keys** — `uuid_generate_v4()`
18
+ - **Soft delete** — Use `deleted_at TIMESTAMPTZ`, never hard delete records
19
+ - Standard columns: `id`, `created_at`, `updated_at`, `deleted_at`
20
+
21
+ ### Data Type Standards
22
+ - Strings: TEXT (not VARCHAR)
23
+ - IDs: UUID
24
+ - Dates: TIMESTAMPTZ (all timestamps are UTC, see `TIMEZONE.md`)
25
+ - Booleans: BOOLEAN
26
+ - Flexible data: JSONB
27
+ - IP addresses: INET
28
+
29
+ ### Naming Conventions
30
+ - Tables: plural, snake_case (users, user_sessions)
31
+ - Columns: snake_case (user_id, created_at)
32
+ - Indexes: idx_tablename_column (idx_users_email)
33
+ - Unique indexes: idx_tablename_column_unique
34
+
35
+ ### Required Features
36
+ - Add indexes for frequently queried columns
37
+ - Add indexes for foreign key columns (even without constraints)
38
+ - Use triggers for updated_at automation
39
+ - Keep migrations simple and focused
40
+
41
+ ### What NOT to Include
42
+ - No audit logs unless specifically asked
43
+ - No 2FA unless specifically asked
44
+ - No complex features unless needed
45
+ - No foreign key constraints
46
+ - No cascading deletes
47
+
48
+ ### Application-Level Handling
49
+ Since we don't use database constraints, the application must:
50
+ - Validate foreign key relationships
51
+ - Handle cascading deletes
52
+ - Make sure data stays consistent
53
+ - Manage transactions properly
54
+
55
+ ---
56
+
57
+ ## Kotlin Code Synchronization Rules
58
+
59
+ ### When Adding a New Table
60
+ You MUST create:
61
+ 1. **SQL migration** in `migrations/sql/`
62
+ 2. **Table object** in `module-repository/src/main/kotlin/com/yourcompany/postgresql/table/`
63
+ - Extend `SoftDeleteTable`
64
+ - Use `text()` for strings (not varchar)
65
+ - Don't re-declare `createdAt`, `updatedAt`, `deletedAt` (inherited)
66
+ 3. **Entity data class** in `module-repository/src/main/kotlin/com/yourcompany/postgresql/entity/`
67
+ - Implement `Entity<Instant>` interface
68
+ - Match all table columns
69
+ - Use proper Kotlin types (String for TEXT, UUID for ids, Instant for timestamps)
70
+ 4. **Constants/Enums** in `module-repository/src/main/kotlin/com/yourcompany/postgresql/constant/` if needed
71
+ - Create enums for status fields
72
+ - Create constants for roles/types
73
+ 5. **Repository** in `module-repository/repository/` with soft delete support
74
+
75
+ ### When Modifying a Table
76
+ You MUST update:
77
+ 1. **Table object** — Add/remove/modify column definitions
78
+ 2. **Entity data class** — Add/remove/modify properties to match
79
+ 3. **Constants/Enums** — Update if column values changed
80
+
81
+ ### When Deleting a Table
82
+ You MUST delete:
83
+ 1. **Table object** file
84
+ 2. **Entity data class** file
85
+ 3. **Related constants/enums** if no longer used
86
+
87
+ ### File Naming Conventions
88
+ - Tables: `{TableName}Table.kt` (e.g., `UsersTable.kt`)
89
+ - Entities: `{TableName}Entity.kt` (e.g., `UserEntity.kt`)
90
+ - Constants: `{FieldName}.kt` (e.g., `UserStatus.kt`, `UserRole.kt`)
91
+
92
+ ### Package Structure
93
+ ```
94
+ module-repository/src/main/kotlin/
95
+ ├── com/yourcompany/postgresql/
96
+ │ ├── table/ # Exposed table definitions
97
+ │ ├── entity/ # Data class entities
98
+ │ └── constant/ # Enums and constants
99
+ └── spartan/exposed/codegen/
100
+ └── Entity.kt # Base Entity interface
101
+ ```
102
+
103
+ ### Example Synchronization
104
+ When SQL migration adds:
105
+ ```sql
106
+ CREATE TABLE products (
107
+ id UUID PRIMARY KEY,
108
+ name TEXT NOT NULL,
109
+ status TEXT DEFAULT 'active',
110
+ created_at TIMESTAMPTZ DEFAULT NOW(),
111
+ updated_at TIMESTAMPTZ,
112
+ deleted_at TIMESTAMPTZ
113
+ );
114
+ ```
115
+
116
+ You MUST create:
117
+ 1. `ProductsTable.kt` with all columns
118
+ 2. `ProductEntity.kt` implementing Entity<Instant>
119
+ 3. `ProductStatus.kt` enum for status values
120
+ 4. `ProductRepository.kt` with CRUD operations
121
+
122
+ ---
123
+
124
+ ## Additional Standards (merged from DATABASE_DESIGN.md)
125
+
126
+ ### UUID Generation
127
+ - **Always use `uuid_generate_v4()`** — NOT `gen_random_uuid()`
128
+ - Ensure consistency across all migrations
129
+
130
+ ### Trigger Functions
131
+ - **Reuse existing `update_updated_at()` function** from `000-init.sql`
132
+ - Do NOT create duplicate trigger functions in each migration
133
+
134
+ ### Index Strategy for Soft Deletes
135
+ - Create **partial indexes** for active record queries:
136
+ ```sql
137
+ CREATE INDEX idx_table_active ON table_name(column) WHERE deleted_at IS NULL;
138
+ ```
139
+ - Create **separate index** for cleanup queries:
140
+ ```sql
141
+ CREATE INDEX idx_table_deleted ON table_name(deleted_at) WHERE deleted_at IS NOT NULL;
142
+ ```
143
+
144
+ ### Exposed ORM Compatibility
145
+ - Use `TEXT` for flexible data fields (contains JSON) — Exposed reads as String
146
+ - JSONB columns use `text()` in Exposed Table definition, serialize/deserialize in Entity
@@ -0,0 +1,311 @@
1
+ # Transaction Rules
2
+
3
+ ## CRITICAL: Multi-Table Operations Must Use Transactions
4
+
5
+ ### 1. Always Use Transactions for Multi-Table Operations
6
+ **Any operation that modifies data in 2 or more tables MUST be wrapped in a transaction.**
7
+
8
+ #### Why This Is Critical
9
+ - Ensures data consistency and integrity
10
+ - Prevents partial updates if one operation fails
11
+ - Allows rollback of all changes if any error occurs
12
+ - Maintains referential integrity between related tables
13
+ - Prevents orphaned records
14
+
15
+ ### 2. Transaction Pattern for Managers
16
+
17
+ **Required pattern for multi-table operations:**
18
+
19
+ ```kotlin
20
+ class DefaultSomeManager(
21
+ private val db: DatabaseContext, // MUST have DatabaseContext
22
+ private val repository1: Repository1,
23
+ private val repository2: Repository2
24
+ ) : SomeManager {
25
+
26
+ override suspend fun multiTableOperation(
27
+ params: Params
28
+ ): Either<ClientException, Result> {
29
+ return transaction(db.primary) {
30
+ try {
31
+ // Operation 1 on table 1
32
+ val result1 = repository1.insert(entity1)
33
+
34
+ // Operation 2 on table 2
35
+ val result2 = repository2.insert(entity2)
36
+
37
+ // Return success
38
+ Result.right()
39
+ } catch (e: Exception) {
40
+ rollback()
41
+ ClientError.SOME_ERROR.asException().left()
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### 3. Examples of Operations That MUST Use Transactions
49
+
50
+ #### Creating Related Entities
51
+ ```kotlin
52
+ // BAD - No transaction
53
+ override suspend fun createProject(request: CreateProjectRequest): Either<ClientException, Project> {
54
+ val project = projectRepository.insert(projectEntity)
55
+ val idea = projectIdeasRepository.insert(ideaEntity) // Could fail, leaving orphaned project
56
+ return toProject(project, idea).right()
57
+ }
58
+
59
+ // GOOD - With transaction
60
+ override suspend fun createProject(request: CreateProjectRequest): Either<ClientException, Project> {
61
+ return transaction(db.primary) {
62
+ try {
63
+ val project = projectRepository.insert(projectEntity)
64
+ val idea = projectIdeasRepository.insert(ideaEntity)
65
+ toProject(project, idea).right()
66
+ } catch (e: Exception) {
67
+ rollback()
68
+ ClientError.USER_NOT_FOUND.asException().left()
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ #### Updating Related Entities
75
+ ```kotlin
76
+ // BAD - No transaction
77
+ override suspend fun submitIdea(projectId: UUID, request: SubmitIdeaRequest): Either<ClientException, Project> {
78
+ val idea = projectIdeasRepository.insert(ideaEntity)
79
+ projectRepository.update(projectId, status = ProjectStatus.VALIDATING) // Could fail
80
+ return project.right()
81
+ }
82
+
83
+ // GOOD - With transaction
84
+ override suspend fun submitIdea(projectId: UUID, request: SubmitIdeaRequest): Either<ClientException, Project> {
85
+ return transaction(db.primary) {
86
+ try {
87
+ val idea = projectIdeasRepository.insert(ideaEntity)
88
+ projectRepository.update(projectId, status = ProjectStatus.VALIDATING)
89
+ project.right()
90
+ } catch (e: Exception) {
91
+ rollback()
92
+ ClientError.USER_NOT_FOUND.asException().left()
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ #### Deleting Related Entities
99
+ ```kotlin
100
+ // BAD - No transaction
101
+ override suspend fun deleteProject(projectId: UUID): Either<ClientException, Boolean> {
102
+ projectRepository.deleteById(projectId)
103
+ projectIdeasRepository.deleteByProjectId(projectId) // Could fail, leaving orphaned ideas
104
+ validationSessionsRepository.deleteByProjectId(projectId) // Could fail
105
+ return true.right()
106
+ }
107
+
108
+ // GOOD - With transaction
109
+ override suspend fun deleteProject(projectId: UUID): Either<ClientException, Boolean> {
110
+ return transaction(db.primary) {
111
+ try {
112
+ // Delete in correct order (children first)
113
+ validationSessionsRepository.deleteByProjectId(projectId)
114
+ projectIdeasRepository.deleteByProjectId(projectId)
115
+ projectRepository.deleteById(projectId)
116
+ true.right()
117
+ } catch (e: Exception) {
118
+ rollback()
119
+ ClientError.USER_NOT_FOUND.asException().left()
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### 4. Manager Constructor Requirements
126
+
127
+ **When a manager needs to perform multi-table operations:**
128
+
129
+ ```kotlin
130
+ // Manager Factory must provide DatabaseContext
131
+ @Singleton
132
+ fun provideProjectManager(
133
+ databaseContext: DatabaseContext, // REQUIRED for transactions
134
+ projectRepository: ProjectRepository,
135
+ projectIdeasRepository: ProjectIdeasRepository,
136
+ validationSessionsRepository: ValidationSessionsRepository
137
+ ): ProjectManager = DefaultProjectManager(
138
+ db = databaseContext,
139
+ projectRepository = projectRepository,
140
+ projectIdeasRepository = projectIdeasRepository,
141
+ validationSessionsRepository = validationSessionsRepository
142
+ )
143
+ ```
144
+
145
+ ### 5. Single Table Operations
146
+
147
+ **Single table operations DON'T need explicit transactions** (repositories handle them internally):
148
+
149
+ ```kotlin
150
+ // OK - Single table operation
151
+ override suspend fun getProject(projectId: UUID): Either<ClientException, Project> {
152
+ val project = projectRepository.byId(projectId)
153
+ ?: return ClientError.USER_NOT_FOUND.asException().left()
154
+ return project.right()
155
+ }
156
+ ```
157
+
158
+ ### 6. Common Scenarios Requiring Transactions
159
+
160
+ 1. **Creating parent-child relationships**
161
+ - Project + ProjectIdea
162
+ - User + UserCredentials
163
+ - Order + OrderItems
164
+
165
+ 2. **Updating status across tables**
166
+ - Updating project status when idea is submitted
167
+ - Updating user status when subscription changes
168
+
169
+ 3. **Cascading deletes**
170
+ - Deleting project and all related data
171
+ - Deleting user and all related records
172
+
173
+ 4. **Complex business operations**
174
+ - Processing payments (update multiple records)
175
+ - Starting validation (create session + update project)
176
+
177
+ ### 7. Transaction Checklist
178
+
179
+ Before implementing any manager method, ask:
180
+ - [ ] Does this operation touch more than one table?
181
+ - [ ] Could partial failure leave the database inconsistent?
182
+ - [ ] Are there parent-child relationships involved?
183
+ - [ ] Does the operation need to be atomic?
184
+
185
+ If ANY answer is YES → **USE A TRANSACTION**
186
+
187
+ ### 8. Error Handling in Transactions
188
+
189
+ ```kotlin
190
+ return transaction(db.primary) {
191
+ try {
192
+ // Your operations here
193
+ successResult.right()
194
+ } catch (e: Exception) {
195
+ rollback() // Always rollback on error
196
+ // Log the actual error for debugging
197
+ logger.error("Transaction failed", e)
198
+ // Return appropriate client error
199
+ ClientError.APPROPRIATE_ERROR.asException().left()
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### 9. Testing Transactions
205
+
206
+ Always test transaction rollback scenarios:
207
+ - Simulate failures in the second operation
208
+ - Verify first operation is rolled back
209
+ - Ensure no partial data remains
210
+
211
+ ### Remember:
212
+ **When in doubt, use a transaction. It's better to have an unnecessary transaction than risk data inconsistency.**
213
+
214
+ ---
215
+
216
+ ## CRITICAL: Atomic Operations for Balance Updates
217
+
218
+ ### 10. Race Condition Prevention with Atomic Operations
219
+
220
+ **Any operation that updates a numeric balance (points, allowance, count) for multiple records MUST use atomic SQL operations.**
221
+
222
+ #### Why This Is Critical
223
+ - Prevents race conditions when updating multiple records in a loop
224
+ - Avoids stale data issues from read-modify-write pattern
225
+ - Ensures accurate calculations even with concurrent requests
226
+
227
+ #### Bad Pattern (Race Condition Risk)
228
+ ```kotlin
229
+ // BAD - Fetches data first, then uses stale values in loop
230
+ val receivers = userRepository.findByIds(receiverIds) // Fetched at T=0
231
+
232
+ receivers.forEach { receiver ->
233
+ userRepository.update(
234
+ id = receiver.id,
235
+ pointsBalance = receiver.pointsBalance + points // Uses T=0 value, not current!
236
+ )
237
+ }
238
+ ```
239
+
240
+ **Problem**: If `receiver.pointsBalance` was 100 at fetch time, and another request updated it to 120 before this loop runs, this code will set it to 100 + 10 = 110 instead of 120 + 10 = 130.
241
+
242
+ #### Good Pattern (Atomic SQL Operations)
243
+ ```kotlin
244
+ // GOOD - Uses SQL-level increment, always reads current value
245
+ receivers.forEach { receiver ->
246
+ userRepository.incrementPointsBalance(receiver.id, points)
247
+ }
248
+ ```
249
+
250
+ **Implementation in Repository:**
251
+ ```kotlin
252
+ import org.jetbrains.exposed.sql.SqlExpressionBuilder.plus
253
+ import org.jetbrains.exposed.sql.SqlExpressionBuilder.minus
254
+
255
+ override fun incrementPointsBalance(id: UUID, amount: Int): UserEntity? {
256
+ return transaction(db.primary) {
257
+ val updated = UsersTable.update({
258
+ (UsersTable.id eq id) and (UsersTable.deletedAt.isNull())
259
+ }) {
260
+ it[pointsBalance] = pointsBalance + amount // SQL: points_balance = points_balance + ?
261
+ it[updatedAt] = Instant.now()
262
+ }
263
+ if (updated > 0) {
264
+ UsersTable.selectAll()
265
+ .where { UsersTable.id eq id }
266
+ .singleOrNull()
267
+ ?.let { convert(it) }
268
+ } else null
269
+ }
270
+ }
271
+
272
+ override fun decrementAllowanceBalance(id: UUID, amount: Int): UserEntity? {
273
+ return transaction(db.primary) {
274
+ val updated = UsersTable.update({
275
+ (UsersTable.id eq id) and (UsersTable.deletedAt.isNull())
276
+ }) {
277
+ it[allowanceBalance] = allowanceBalance - amount // SQL: allowance_balance = allowance_balance - ?
278
+ it[updatedAt] = Instant.now()
279
+ }
280
+ if (updated > 0) {
281
+ UsersTable.selectAll()
282
+ .where { UsersTable.id eq id }
283
+ .singleOrNull()
284
+ ?.let { convert(it) }
285
+ } else null
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### 11. Common Scenarios Requiring Atomic Operations
291
+
292
+ 1. **Recognition points distribution**
293
+ - Incrementing receiver's points balance
294
+ - Decrementing giver's allowance balance
295
+
296
+ 2. **Redemption processing**
297
+ - Deducting user's points on redeem
298
+ - Refunding points on reject/cancel
299
+
300
+ 3. **Any counter increment/decrement**
301
+ - View counts, like counts, comment counts
302
+ - Stock quantities, inventory levels
303
+
304
+ ### 12. Atomic Operations Checklist
305
+
306
+ Before implementing any balance update, ask:
307
+ - [ ] Am I updating a numeric value that could be modified by concurrent requests?
308
+ - [ ] Am I using a value fetched earlier in the same method?
309
+ - [ ] Am I updating multiple records in a loop?
310
+
311
+ If ANY answer is YES → **USE ATOMIC SQL OPERATIONS**