create-ailk 0.23.0 → 0.25.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 (604) hide show
  1. package/README.md +68 -33
  2. package/component-catalog.json +3 -3
  3. package/component-catalog.md +3 -3
  4. package/dist/add-module.js +10 -3
  5. package/dist/add-route.d.ts +12 -1
  6. package/dist/add-route.js +38 -4
  7. package/dist/cli.js +12 -7
  8. package/dist/derive-architecture.d.ts +3 -4
  9. package/dist/derive-architecture.js +75 -22
  10. package/dist/lib/design-checks.d.ts +9 -4
  11. package/dist/lib/design-checks.js +13 -7
  12. package/dist/lib/extract-module-bundle.js +29 -2
  13. package/dist/lib/fetch-template-snapshot.d.ts +1 -1
  14. package/dist/lib/fetch-template-snapshot.js +7 -3
  15. package/dist/lib/import-graph.d.ts +1 -1
  16. package/dist/lib/import-graph.js +4 -4
  17. package/dist/lib/module-license-gate.d.ts +12 -1
  18. package/dist/lib/module-license-gate.js +34 -12
  19. package/dist/lib/scaffold-render-sweep.d.ts +33 -0
  20. package/dist/lib/scaffold-render-sweep.js +45 -0
  21. package/dist/module-architecture.d.ts +20 -3
  22. package/dist/module-architecture.js +122 -538
  23. package/dist/paid-sections.d.ts +25 -1
  24. package/dist/paid-sections.js +88 -3
  25. package/dist/surfaces.js +10 -2
  26. package/dist/sync-routes.d.ts +30 -4
  27. package/dist/sync-routes.js +271 -18
  28. package/dist/template-record.d.ts +14 -4
  29. package/dist/template-record.js +23 -5
  30. package/dist/topology.d.ts +16 -3
  31. package/dist/topology.js +31 -19
  32. package/dist/update.d.ts +10 -1
  33. package/dist/update.js +540 -16
  34. package/package.json +3 -3
  35. package/release-scope.json +1 -1
  36. package/templates/.claude/cloudparity-repo-hooks.json +5 -0
  37. package/templates/.claude/hooks/template-guard.sh +137 -0
  38. package/templates/.claude/rules/extending.md +106 -0
  39. package/templates/.claude/rules/loop-contract.md +2 -2
  40. package/templates/.claude/settings.json +11 -0
  41. package/templates/.env.example +9 -5
  42. package/templates/.github/workflows/ci.yml +7 -4
  43. package/templates/CLAUDE.md +15 -3
  44. package/templates/CONVENTIONS.md +8 -10
  45. package/templates/README.md +14 -13
  46. package/templates/apps/api/.env.example +9 -2
  47. package/templates/apps/api/CLAUDE.md +122 -82
  48. package/templates/apps/api/jest.config.cjs +15 -5
  49. package/templates/apps/api/package.json +16 -20
  50. package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
  51. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
  52. package/templates/apps/api/src/index.ts +1 -1
  53. package/templates/apps/api/src/lib/__mocks__/prisma.ts +7 -4
  54. package/templates/apps/api/src/modules/commerce.ts +10 -0
  55. package/templates/apps/api/src/modules/content-write.ts +10 -0
  56. package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
  57. package/templates/apps/api/src/modules/scheduling.ts +10 -0
  58. package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
  59. package/templates/apps/api/src/modules/workspace.ts +10 -0
  60. package/templates/apps/api/src/server.ts +117 -1857
  61. package/templates/apps/api/vercel.json +2 -2
  62. package/templates/apps/mcp/CLAUDE.md +77 -24
  63. package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
  64. package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
  65. package/templates/apps/mcp/jest.config.cjs +6 -1
  66. package/templates/apps/mcp/package.json +5 -12
  67. package/templates/apps/mcp/src/app.ts +8 -7
  68. package/templates/apps/mcp/src/index.ts +6 -34
  69. package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
  70. package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
  71. package/templates/apps/mcp/src/site.ts +12 -0
  72. package/templates/apps/web/.env.example +1 -1
  73. package/templates/apps/web/CLAUDE.md +21 -5
  74. package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
  75. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +1 -1
  76. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +14 -4
  77. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
  78. package/templates/apps/web/app/[locale]/contact/intake-script.ts +1 -1
  79. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
  80. package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +28 -7
  81. package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
  82. package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
  83. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
  84. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
  85. package/templates/apps/web/app/api/revalidate/route.ts +3 -3
  86. package/templates/apps/web/auth.ts +2 -2
  87. package/templates/apps/web/jest.config.cjs +1 -0
  88. package/templates/apps/web/lib/__tests__/magnet-routes.test.ts +7 -0
  89. package/templates/apps/web/lib/auth-email.ts +1 -1
  90. package/templates/apps/web/lib/magnet-routes.ts +3 -1
  91. package/templates/apps/web/lib/newsletter.actions.ts +9 -6
  92. package/templates/apps/web/lib/relay.ts +2 -2
  93. package/templates/apps/web/lib/release-scope.ts +47 -0
  94. package/templates/apps/web/lib/server-api.ts +1 -1
  95. package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
  96. package/templates/customizations.yaml +37 -0
  97. package/templates/database/prisma.config.ts +10 -14
  98. package/templates/database/seed-test.ts +2 -2
  99. package/templates/database/seed.ts +32 -5
  100. package/templates/package.json +12 -6
  101. package/templates/pnpm-workspace.yaml +0 -1
  102. package/templates/project.yaml +16 -8
  103. package/templates/tools/jest/reporters.cjs +65 -0
  104. package/templates/tools/lint-architecture.ts +757 -7
  105. package/templates/tsconfig.json +1 -2
  106. package/versions.json +48 -35
  107. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
  108. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
  109. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
  110. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
  111. package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
  112. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
  113. package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
  114. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
  115. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
  116. package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
  117. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
  118. package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
  119. package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
  120. package/templates/apps/api/src/bin/spokes.ts +0 -198
  121. package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
  122. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
  123. package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
  124. package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
  125. package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
  126. package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
  127. package/templates/apps/api/src/config/index.ts +0 -596
  128. package/templates/apps/api/src/config/modules.ts +0 -83
  129. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
  130. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
  131. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
  132. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
  133. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
  134. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
  135. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
  136. package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
  137. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
  138. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
  139. package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
  140. package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
  141. package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
  142. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
  143. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
  144. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
  145. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
  146. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
  147. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
  148. package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -292
  149. package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
  150. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
  151. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
  152. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
  153. package/templates/apps/api/src/lib/agent-store.ts +0 -613
  154. package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
  155. package/templates/apps/api/src/lib/consent-store.ts +0 -363
  156. package/templates/apps/api/src/lib/content-adapter.ts +0 -112
  157. package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
  158. package/templates/apps/api/src/lib/error-serializer.ts +0 -164
  159. package/templates/apps/api/src/lib/errors.ts +0 -95
  160. package/templates/apps/api/src/lib/file-fallback.ts +0 -87
  161. package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
  162. package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
  163. package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
  164. package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
  165. package/templates/apps/api/src/lib/license-key-store.ts +0 -45
  166. package/templates/apps/api/src/lib/locales.ts +0 -201
  167. package/templates/apps/api/src/lib/outbound-http.ts +0 -127
  168. package/templates/apps/api/src/lib/prisma.ts +0 -21
  169. package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
  170. package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
  171. package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
  172. package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
  173. package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
  174. package/templates/apps/api/src/lib/site.ts +0 -254
  175. package/templates/apps/api/src/lib/slice-load.ts +0 -90
  176. package/templates/apps/api/src/lib/spoke-store.ts +0 -180
  177. package/templates/apps/api/src/lib/stripe.ts +0 -318
  178. package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
  179. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
  180. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
  181. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
  182. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
  183. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
  184. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
  185. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
  186. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
  187. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
  188. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
  189. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
  190. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
  191. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
  192. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
  193. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
  194. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
  195. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
  196. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
  197. package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
  198. package/templates/apps/api/src/middleware/auth.ts +0 -864
  199. package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
  200. package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
  201. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -264
  202. package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
  203. package/templates/apps/api/src/openapi/index.ts +0 -18
  204. package/templates/apps/api/src/openapi/spec.ts +0 -1815
  205. package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
  206. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
  207. package/templates/apps/api/src/routes/aeo/index.ts +0 -107
  208. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
  209. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
  210. package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
  211. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
  212. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
  213. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
  214. package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
  215. package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
  216. package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
  217. package/templates/apps/api/src/routes/auth/user.ts +0 -305
  218. package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -325
  219. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
  220. package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1300
  221. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
  222. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
  223. package/templates/apps/api/src/routes/checkout/index.ts +0 -34
  224. package/templates/apps/api/src/routes/checkout/session.ts +0 -171
  225. package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
  226. package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
  227. package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
  228. package/templates/apps/api/src/routes/consent/account.ts +0 -268
  229. package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
  230. package/templates/apps/api/src/routes/consent/index.ts +0 -26
  231. package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
  232. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
  233. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
  234. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
  235. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
  236. package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
  237. package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
  238. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
  239. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
  240. package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
  241. package/templates/apps/api/src/routes/content/get-page.ts +0 -268
  242. package/templates/apps/api/src/routes/content/index.ts +0 -49
  243. package/templates/apps/api/src/routes/content/list-pages.ts +0 -95
  244. package/templates/apps/api/src/routes/content/list-types.ts +0 -19
  245. package/templates/apps/api/src/routes/content/offerings.ts +0 -184
  246. package/templates/apps/api/src/routes/content/pricing.ts +0 -176
  247. package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
  248. package/templates/apps/api/src/routes/content/search.ts +0 -129
  249. package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
  250. package/templates/apps/api/src/routes/content/slug.ts +0 -9
  251. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
  252. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
  253. package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
  254. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
  255. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
  256. package/templates/apps/api/src/routes/leads/index.ts +0 -573
  257. package/templates/apps/api/src/routes/leads/list.ts +0 -104
  258. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
  259. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
  260. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
  261. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -480
  262. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -465
  263. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
  264. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
  265. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
  266. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
  267. package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
  268. package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
  269. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
  270. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
  271. package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
  272. package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
  273. package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
  274. package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
  275. package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
  276. package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
  277. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
  278. package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
  279. package/templates/apps/api/src/routes/requests/index.ts +0 -54
  280. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
  281. package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
  282. package/templates/apps/api/src/routes/webhooks/README.md +0 -398
  283. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
  284. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
  285. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -448
  286. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
  287. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
  288. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
  289. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
  290. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
  291. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
  292. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
  293. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
  294. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -808
  295. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
  296. package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
  297. package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
  298. package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2026
  299. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -528
  300. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
  301. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
  302. package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
  303. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
  304. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
  305. package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
  306. package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
  307. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -867
  308. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
  309. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
  310. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
  311. package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
  312. package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
  313. package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
  314. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
  315. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
  316. package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
  317. package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1176
  318. package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -444
  319. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -154
  320. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
  321. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
  322. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
  323. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
  324. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
  325. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
  326. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
  327. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
  328. package/templates/apps/api/src/services/abandon-email.ts +0 -313
  329. package/templates/apps/api/src/services/aeo-score.ts +0 -325
  330. package/templates/apps/api/src/services/answer-distributions.ts +0 -138
  331. package/templates/apps/api/src/services/audit-log.ts +0 -961
  332. package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
  333. package/templates/apps/api/src/services/consent.ts +0 -834
  334. package/templates/apps/api/src/services/default-tenant.ts +0 -416
  335. package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -755
  336. package/templates/apps/api/src/services/dunning-policy.ts +0 -294
  337. package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
  338. package/templates/apps/api/src/services/entitlements.ts +0 -338
  339. package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
  340. package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
  341. package/templates/apps/api/src/services/lead-promotion.ts +0 -160
  342. package/templates/apps/api/src/services/lead-routing.ts +0 -1372
  343. package/templates/apps/api/src/services/leads-inbox.ts +0 -312
  344. package/templates/apps/api/src/services/listing-config.ts +0 -178
  345. package/templates/apps/api/src/services/magnet-completion.ts +0 -242
  346. package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -295
  347. package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
  348. package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -868
  349. package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
  350. package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -396
  351. package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -681
  352. package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
  353. package/templates/apps/api/src/services/offerings/catalog.ts +0 -308
  354. package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -385
  355. package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
  356. package/templates/apps/api/src/services/offerings/connection.ts +0 -1003
  357. package/templates/apps/api/src/services/offerings/index.ts +0 -614
  358. package/templates/apps/api/src/services/offerings/source.ts +0 -140
  359. package/templates/apps/api/src/services/offerings/store.ts +0 -150
  360. package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
  361. package/templates/apps/api/src/services/person.ts +0 -1188
  362. package/templates/apps/api/src/services/plan-offerings.ts +0 -125
  363. package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
  364. package/templates/apps/api/src/services/project-listings.ts +0 -2073
  365. package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
  366. package/templates/apps/api/src/services/request-confirm.ts +0 -698
  367. package/templates/apps/api/src/services/revalidation.ts +0 -235
  368. package/templates/apps/api/src/services/slack-notify.ts +0 -291
  369. package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
  370. package/templates/apps/api/src/services/usage-credits.ts +0 -340
  371. package/templates/apps/api/src/services/verified-email.ts +0 -71
  372. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
  373. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
  374. package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
  375. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
  376. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
  377. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
  378. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
  379. package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
  380. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
  381. package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
  382. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
  383. package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
  384. package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
  385. package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
  386. package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
  387. package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
  388. package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1151
  389. package/templates/apps/mcp/__tests__/index.test.ts +0 -195
  390. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
  391. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
  392. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -65
  393. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -187
  394. package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
  395. package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
  396. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -165
  397. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
  398. package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -228
  399. package/templates/apps/mcp/__tests__/locale.test.ts +0 -135
  400. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
  401. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
  402. package/templates/apps/mcp/__tests__/read_content.test.ts +0 -474
  403. package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -225
  404. package/templates/apps/mcp/__tests__/search_content.test.ts +0 -256
  405. package/templates/apps/mcp/__tests__/server.test.ts +0 -388
  406. package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
  407. package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -307
  408. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -223
  409. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
  410. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
  411. package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
  412. package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
  413. package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
  414. package/templates/apps/mcp/src/abuse/index.ts +0 -342
  415. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
  416. package/templates/apps/mcp/src/boot.ts +0 -167
  417. package/templates/apps/mcp/src/config/modules.ts +0 -43
  418. package/templates/apps/mcp/src/http-transport.ts +0 -526
  419. package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
  420. package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
  421. package/templates/apps/mcp/src/lib/content-adapter.ts +0 -142
  422. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -139
  423. package/templates/apps/mcp/src/lib/errors.ts +0 -61
  424. package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
  425. package/templates/apps/mcp/src/lib/locales.ts +0 -171
  426. package/templates/apps/mcp/src/lib/prisma.ts +0 -39
  427. package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
  428. package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
  429. package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
  430. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
  431. package/templates/apps/mcp/src/request-context.ts +0 -52
  432. package/templates/apps/mcp/src/server.ts +0 -343
  433. package/templates/apps/mcp/src/serverless-app.ts +0 -88
  434. package/templates/apps/mcp/src/tools/audit.ts +0 -127
  435. package/templates/apps/mcp/src/tools/capture_lead.ts +0 -64
  436. package/templates/apps/mcp/src/tools/create_project.ts +0 -134
  437. package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
  438. package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
  439. package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
  440. package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
  441. package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
  442. package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
  443. package/templates/apps/mcp/src/tools/index.ts +0 -137
  444. package/templates/apps/mcp/src/tools/list_pages.ts +0 -74
  445. package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
  446. package/templates/apps/mcp/src/tools/proposals.ts +0 -27
  447. package/templates/apps/mcp/src/tools/purchase.ts +0 -205
  448. package/templates/apps/mcp/src/tools/read_content.ts +0 -75
  449. package/templates/apps/mcp/src/tools/request_callback.ts +0 -59
  450. package/templates/apps/mcp/src/tools/search_content.ts +0 -67
  451. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -57
  452. package/templates/apps/mcp/src/workspace-server.ts +0 -224
  453. package/templates/database/CHANGELOG.md +0 -961
  454. package/templates/database/LICENSE +0 -202
  455. package/templates/database/NOTICE +0 -2
  456. package/templates/database/README.md +0 -243
  457. package/templates/database/__tests__/agents.db.test.ts +0 -320
  458. package/templates/database/__tests__/appointment.db.test.ts +0 -106
  459. package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
  460. package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
  461. package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
  462. package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
  463. package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
  464. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
  465. package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
  466. package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
  467. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
  468. package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
  469. package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
  470. package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
  471. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
  472. package/templates/database/__tests__/flows-presets.test.ts +0 -173
  473. package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
  474. package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
  475. package/templates/database/__tests__/member-area.db.test.ts +0 -257
  476. package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
  477. package/templates/database/__tests__/member-contract.db.test.ts +0 -413
  478. package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
  479. package/templates/database/__tests__/offerings-migration.test.ts +0 -197
  480. package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
  481. package/templates/database/__tests__/offerings.db.test.ts +0 -303
  482. package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
  483. package/templates/database/__tests__/person-contact.db.test.ts +0 -563
  484. package/templates/database/__tests__/person-notes.db.test.ts +0 -249
  485. package/templates/database/__tests__/person.db.test.ts +0 -586
  486. package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
  487. package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
  488. package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
  489. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
  490. package/templates/database/__tests__/seed.test.ts +0 -240
  491. package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
  492. package/templates/database/__tests__/tenancy.test.ts +0 -141
  493. package/templates/database/__tests__/user-cascade.test.ts +0 -140
  494. package/templates/database/_gitignore +0 -8
  495. package/templates/database/auth/.gitkeep +0 -0
  496. package/templates/database/auth/schema.prisma +0 -641
  497. package/templates/database/config/.gitkeep +0 -0
  498. package/templates/database/config/schema.prisma +0 -441
  499. package/templates/database/content/.gitkeep +0 -0
  500. package/templates/database/content/schema.prisma +0 -339
  501. package/templates/database/eslint.config.mjs +0 -69
  502. package/templates/database/flows/listing-diagnostic.ts +0 -182
  503. package/templates/database/flows/presets.ts +0 -315
  504. package/templates/database/inbox/.gitkeep +0 -0
  505. package/templates/database/inbox/README.md +0 -3
  506. package/templates/database/inbox/__tests__/schema.test.ts +0 -44
  507. package/templates/database/inbox/schema.prisma +0 -1447
  508. package/templates/database/jest.config.cjs +0 -36
  509. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
  510. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
  511. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
  512. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
  513. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
  514. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
  515. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
  516. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
  517. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
  518. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
  519. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
  520. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
  521. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
  522. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
  523. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
  524. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
  525. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
  526. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
  527. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
  528. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
  529. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
  530. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
  531. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
  532. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
  533. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
  534. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
  535. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
  536. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
  537. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
  538. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
  539. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
  540. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
  541. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
  542. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
  543. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
  544. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
  545. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
  546. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
  547. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
  548. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
  549. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
  550. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
  551. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
  552. package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
  553. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
  554. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
  555. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
  556. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
  557. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
  558. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
  559. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
  560. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
  561. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
  562. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
  563. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
  564. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
  565. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
  566. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
  567. package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
  568. package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
  569. package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
  570. package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
  571. package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
  572. package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
  573. package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
  574. package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
  575. package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
  576. package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
  577. package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
  578. package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
  579. package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
  580. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
  581. package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
  582. package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
  583. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
  584. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
  585. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
  586. package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
  587. package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
  588. package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
  589. package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
  590. package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
  591. package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
  592. package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
  593. package/templates/database/migrations/migration_lock.toml +0 -3
  594. package/templates/database/ops/.gitkeep +0 -0
  595. package/templates/database/ops/schema.prisma +0 -43
  596. package/templates/database/package.json +0 -89
  597. package/templates/database/schema.prisma +0 -71
  598. package/templates/database/scripts/db-generate-locked.sh +0 -80
  599. package/templates/database/scripts/person-backfill.sql +0 -132
  600. package/templates/database/tenancy.ts +0 -183
  601. package/templates/database/tsconfig.build.json +0 -16
  602. package/templates/database/tsconfig.flows.json +0 -15
  603. package/templates/database/tsconfig.json +0 -16
  604. package/templates/database/tsconfig.tenancy.json +0 -14
@@ -1,210 +0,0 @@
1
- -- #6314 — ProjectListing gains `captured_by_flow_id`: the listicle-kind
2
- -- FlowDefinition that CAPTURED the application, so a magnet's own
3
- -- Applications list can be scoped to its own submissions rather than to the
4
- -- whole workspace. Nothing constrains a workspace to one listicle magnet
5
- -- ("flow_definitions" carries a (site_id, slug) unique and no
6
- -- (site_id, kind) one), so workspace-only scoping would silently conflate
7
- -- two listicle magnets' applications.
8
- --
9
- -- A NEW MIGRATION DIRECTORY, not an amendment of the already-merged
10
- -- 20260922120000_tenancy_fence (spec D8). #6254 AC-1's one-migration-per-
11
- -- milestone rule names #6314 by number in that migration's own header, so
12
- -- this is a DEPARTURE taken deliberately and with the operator's
13
- -- confirmation (2026-09-20), not a gap that rule failed to cover. Two
14
- -- reasons, in order of weight:
15
- -- 1. Prisma records a per-migration CHECKSUM. `prisma migrate deploy`
16
- -- refuses a migration whose file no longer matches `_prisma_migrations`,
17
- -- so a database that already applied the fence directory would never
18
- -- receive this column or its index while the new code assumes both.
19
- -- "Editing it in place is a silent no-op" is true of the SQL; it is not
20
- -- true of the checksum.
21
- -- 2. apps/api/CLAUDE.md: "Never edit a shipped migration — add a new one."
22
- -- Where a spec's convenience and an in-repo rule disagree, the rule wins.
23
- --
24
- -- PURELY ADDITIVE: one nullable column, one index. NO UPDATE, NO backfill,
25
- -- and NO foreign key.
26
- --
27
- -- NO BACKFILL, deliberately (spec § 3.5 / AC-3, operator ruling 2026-09-19).
28
- -- No existing row carries evidence naming the magnet that captured it — no
29
- -- referrer, no session link, no slug. A backfill would have to guess "the
30
- -- workspace's only listicle magnet", which is exactly the conflation this
31
- -- column exists to remove, made permanent and unauditable. Every row written
32
- -- before this migration therefore reads NULL for the life of the row:
33
- -- unattributed, excluded from every per-magnet list (NULL never equals a
34
- -- magnet id, so the exclusion is a property of the query, not a filter that
35
- -- can be forgotten), and UNCHANGED in the workspace Inbox — no operator loses
36
- -- access to any application. This is the same discipline the founder-name
37
- -- parts (#5407), the address parts (#5279) and `owner_user_id` (#5295) each
38
- -- follow: a value that can only be guessed must not be asserted.
39
- --
40
- -- NO foreign key, deliberately (spec § 3.2, operator decision 2026-09-20,
41
- -- which withdrew the 2026-09-19 ruling's "on-delete set-null" clause). Both
42
- -- models live in the `inbox` namespace, so ADR 0009 invariant #1 (which bans
43
- -- CROSS-namespace relations) does not reach this column — permission was
44
- -- never the question. The convention is: of the 24 foreign-key constraints
45
- -- under database/migrations/**, every one targets the `auth` namespace
46
- -- ("users"); the intra-inbox columns listing_id, lead_id, grant_id and
47
- -- flow_session_id carry none. The composite (workspace_id, …) shape was
48
- -- itself offered and declined on "listing_csv_sends" the day before this
49
- -- spec's pin. Integrity rests on the server-side resolve in
50
- -- `startProjectListingDraft` (site_id + workspace_id + kind = 'listicle')
51
- -- and on the read carrying the injected workspace_id alongside the magnet id
52
- -- — so a dangling or foreign value yields no rows, never another workspace's.
53
- -- Nothing deletes a flow_definitions row either (routes/magnets D5: "No
54
- -- DELETE"), so ON DELETE SET NULL would have described no live code path.
55
- --
56
- -- RE-RUNNABLE: IF NOT EXISTS on both DDL statements, the census temp table is
57
- -- dropped-if-exists before it is built, and post-assertion 2 is skipped on a
58
- -- re-apply (it proves this file grew no backfill, which only the first
59
- -- application can show — see its own comment). So re-applying this directory
60
- -- against a database that already has the column is inert rather than an abort
61
- -- that would wedge the ledger.
62
- --
63
- -- ORDER-SAFE: the index references "workspace_id", added by
64
- -- 20260919140000_inbox_workspace_key and made NOT NULL by
65
- -- 20260922120000_tenancy_fence — both of which this migration sorts strictly
66
- -- after. The guard below is therefore a formality in the normal case, kept
67
- -- for the reason 20260920130000_lead_workspace_source_index keeps one: IF NOT
68
- -- EXISTS guards the INDEX's own name, not the column it references, so an
69
- -- unguarded CREATE INDEX would abort inside prisma migrate's per-migration
70
- -- transaction and wedge the ledger for the whole deployment if that earlier
71
- -- migration were ever skipped, renamed, or rolled back on a given database.
72
- --
73
- -- CREATE INDEX is NOT CONCURRENT, and cannot be: CONCURRENTLY may not run
74
- -- inside prisma migrate's per-migration transaction. It therefore takes a
75
- -- lock on "project_listings" for its duration — the same accepted risk
76
- -- 20260920130000_lead_workspace_source_index names. A deployment with a large
77
- -- project_listings table should create this index out-of-band with
78
- -- CONCURRENTLY first; the IF NOT EXISTS guard then makes the statement a
79
- -- no-op.
80
- --
81
- -- Rollback:
82
- -- DROP INDEX "project_listings_workspace_id_captured_by_flow_id_idx";
83
- -- ALTER TABLE "project_listings" DROP COLUMN "captured_by_flow_id";
84
- -- Safe at any point: the column is nullable and unconstrained, and no row's
85
- -- correctness depends on it beyond per-magnet attribution.
86
-
87
- -- A census, so the post-assertions below can prove nothing moved.
88
- --
89
- -- `column_preexisted` is captured HERE, before the ALTER, and it is what keeps
90
- -- assertion 2 honest on a RE-APPLY. That assertion proves a property of THIS
91
- -- FILE (it performs no backfill), which is only observable on the application
92
- -- that first adds the column: once the application has written even one real
93
- -- attribution, "no row is attributed" is false for reasons this migration had
94
- -- nothing to do with. Asserting it unconditionally would abort inside prisma
95
- -- migrate's per-migration transaction and wedge the ledger for every later
96
- -- migration on that database — on a restored snapshot, a `migrate resolve
97
- -- --rolled-back` redeploy, or a branch of production.
98
- -- `pg_temp.`-qualified: DROP TABLE does not distinguish temporary from
99
- -- permanent relations, and at this point the session holds no temp table, so
100
- -- an unqualified name would resolve through search_path to `public` and drop
101
- -- a same-named PERMANENT table — inside the transaction prisma commits.
102
- DROP TABLE IF EXISTS pg_temp."_6314_capture_census";
103
- CREATE TEMP TABLE "_6314_capture_census" AS
104
- SELECT
105
- count(*) AS p,
106
- EXISTS (
107
- SELECT 1 FROM information_schema.columns
108
- -- `table_schema = current_schema()` is load-bearing, not tidiness:
109
- -- `information_schema.columns` spans EVERY schema in the database, so
110
- -- without it the probe answers "does any table anywhere named
111
- -- project_listings carry this column" rather than "does the table this
112
- -- migration is about to alter carry it". A pre-migration snapshot in a
113
- -- side schema (`CREATE TABLE backup.project_listings AS SELECT ...`, a
114
- -- `pg_dump -n` restore) would then make a genuine FIRST apply take the
115
- -- skip branch below and wave a real backfill through unchecked — the
116
- -- exact AC-8 property assertion 2 exists to prove.
117
- WHERE table_schema = current_schema()
118
- AND table_name = 'project_listings'
119
- AND column_name = 'captured_by_flow_id'
120
- ) AS column_preexisted
121
- FROM "project_listings";
122
-
123
- -- AlterTable — the capturing magnet's id. Nullable and unconstrained, so a
124
- -- row predating this migration reads NULL and nothing here can reject it.
125
- ALTER TABLE "project_listings" ADD COLUMN IF NOT EXISTS "captured_by_flow_id" TEXT;
126
-
127
- -- CreateIndex — the read is workspace_id = $1 AND captured_by_flow_id = $2,
128
- -- ordered by created_at desc. A two-column (workspace_id, captured_by_flow_id)
129
- -- index serves it directly. With no foreign key there is no cascade, so no
130
- -- referencing-side index is owed beyond this one.
131
- DO $$ BEGIN
132
- IF EXISTS (
133
- SELECT 1 FROM information_schema.columns
134
- -- `table_schema = current_schema()` for the same reason the census probe
135
- -- above carries it, and the failure direction here is WORSE. A decoy
136
- -- `project_listings` in another schema makes this EXISTS spuriously true;
137
- -- the CREATE INDEX below then runs against the table search_path actually
138
- -- resolves, hits `column "workspace_id" does not exist`, and aborts the
139
- -- whole migration transaction — a wedged ledger, where the census probe's
140
- -- equivalent merely skips an assertion. The guard must ask about the table
141
- -- the statement it protects will really touch.
142
- WHERE table_schema = current_schema()
143
- AND table_name = 'project_listings'
144
- AND column_name = 'workspace_id'
145
- ) THEN
146
- CREATE INDEX IF NOT EXISTS "project_listings_workspace_id_captured_by_flow_id_idx"
147
- ON "project_listings"("workspace_id", "captured_by_flow_id");
148
- ELSE
149
- RAISE NOTICE '#6314: project_listings.workspace_id absent — index skipped. 20260919140000_inbox_workspace_key has not run against this database; the per-magnet Applications read cannot be served efficiently until it does.';
150
- END IF;
151
- END $$;
152
-
153
- -- Post-assertions, in 20260922120000_tenancy_fence's own idiom.
154
- DO $$
155
- DECLARE
156
- before_p bigint;
157
- after_p bigint;
158
- attributed bigint;
159
- preexisted boolean;
160
- BEGIN
161
- SELECT p, column_preexisted INTO before_p, preexisted FROM "_6314_capture_census";
162
- SELECT count(*) INTO after_p FROM "project_listings";
163
-
164
- -- 1. Nothing LOST. Deliberately `<`, not `<>`.
165
- --
166
- -- An equality test here has no true-positive mode and one guaranteed
167
- -- false-positive mode, which is the worst shape a guard can have. No
168
- -- statement in this file modifies a row of "project_listings" (the whole
169
- -- file is five statements; read them), so the two counts can only diverge
170
- -- through a write committed by ANOTHER session between them. The census
171
- -- takes ACCESS SHARE; the ALTER takes ACCESS EXCLUSIVE, and until it does,
172
- -- the table stays open to writers. "project_listings" is written by an
173
- -- ANONYMOUS, unauthenticated route, so on a live deploy one application
174
- -- started mid-migration aborts the migration — and the retry meets the
175
- -- same race. That is a wedged ledger caused by the system working
176
- -- normally.
177
- --
178
- -- `<` keeps the property the assertion is actually for — this migration
179
- -- must never destroy a row — while letting a concurrent INSERT through.
180
- -- A DELETE or TRUNCATE creeping into this file still trips it.
181
- IF after_p < before_p THEN
182
- RAISE EXCEPTION
183
- '#6314 post-assertion: project_listings LOST row(s) across a purely additive migration (% -> %)',
184
- before_p, after_p;
185
- END IF;
186
-
187
- -- 2. Nothing guessed (AC-8): every PRE-EXISTING row reads NULL. This
188
- -- migration performs no UPDATE, so a non-NULL row on the application that
189
- -- first adds the column would mean the file grew a backfill the ruling
190
- -- refused.
191
- --
192
- -- Skipped when the column already existed: on a re-apply, attributed rows
193
- -- are the APPLICATION's own writes, not a backfill, and failing on them
194
- -- would wedge the migration ledger (see the census above). The assertion
195
- -- still fires where it can mean anything — the first application, which is
196
- -- the only run that can introduce a backfill.
197
- IF preexisted THEN
198
- RAISE NOTICE '#6314 post-assertion 2 skipped: captured_by_flow_id already existed, so this is a re-apply and any attributed row is an application write rather than a backfill.';
199
- ELSE
200
- SELECT count(*) INTO attributed
201
- FROM "project_listings" WHERE "captured_by_flow_id" IS NOT NULL;
202
- IF attributed <> 0 THEN
203
- RAISE EXCEPTION
204
- '#6314 post-assertion: % project_listings row(s) carry a captured_by_flow_id after a migration that performs no UPDATE — existing rows must stay unattributed (no backfill by guess)',
205
- attributed;
206
- END IF;
207
- END IF;
208
- END $$;
209
-
210
- DROP TABLE pg_temp."_6314_capture_census";
@@ -1,80 +0,0 @@
1
- -- #7532 — the hub's spoke registry and the booking-origin record (spec
2
- -- docs/specs/7532-a-spoke-s-public-reads-spec.md D1, D5).
3
- --
4
- -- spokes (auth) — one row per separately deployed site that
5
- -- calls this hub, bound to ONE workspace. It
6
- -- stores the SHA-256 digest of the spoke's
7
- -- hub-minted key, never the key. Deleting a
8
- -- workspace deletes its spokes (the FK below).
9
- -- appointment_origins (inbox) — (provider, booking uid) → workspace, written
10
- -- when a spoke's booking is created so the
11
- -- deployment-wide Cal.com webhook stores the
12
- -- booking in the spoke's workspace. One origin
13
- -- per booking uid. No foreign key and no
14
- -- relation (ADR 0009): workspace_id and
15
- -- spoke_id are plain columns with format CHECKs.
16
- --
17
- -- PURELY ADDITIVE: two new tables, their indexes and one FK to "workspaces".
18
- -- No statement touches an existing table's rows or columns, so there is no
19
- -- pre-assertion block — this migration cannot lose a row.
20
- --
21
- -- Rollback: DROP TABLE "appointment_origins"; DROP TABLE "spokes". Safe while
22
- -- nothing but #7532's own code reads them.
23
-
24
- -- CreateTable
25
- CREATE TABLE "spokes" (
26
- "id" TEXT NOT NULL DEFAULT ('spoke_'::text || (uuidv7())::text),
27
- "workspace_id" TEXT NOT NULL,
28
- "name" VARCHAR(120) NOT NULL,
29
- "credential_hash" CHAR(64) NOT NULL,
30
- "credential_prefix" VARCHAR(24) NOT NULL,
31
- "revoked_at" TIMESTAMP(3),
32
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
33
- "updated_at" TIMESTAMP(3) NOT NULL,
34
-
35
- CONSTRAINT "spokes_pkey" PRIMARY KEY ("id")
36
- );
37
-
38
- -- CreateTable
39
- CREATE TABLE "appointment_origins" (
40
- "id" TEXT NOT NULL DEFAULT ('apptorg_'::text || (uuidv7())::text),
41
- "provider" VARCHAR(32) NOT NULL DEFAULT 'cal',
42
- "provider_booking_uid" VARCHAR(200) NOT NULL,
43
- "workspace_id" TEXT NOT NULL,
44
- "spoke_id" TEXT NOT NULL,
45
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
46
-
47
- CONSTRAINT "appointment_origins_pkey" PRIMARY KEY ("id")
48
- );
49
-
50
- -- CreateIndex
51
- -- The lookup a spoke's every request makes (`findSpokeByKeyHash`).
52
- CREATE UNIQUE INDEX "spokes_credential_hash_key" ON "spokes"("credential_hash");
53
-
54
- -- CreateIndex
55
- CREATE INDEX "spokes_workspace_id_idx" ON "spokes"("workspace_id");
56
-
57
- -- CreateIndex
58
- CREATE INDEX "appointment_origins_workspace_id_idx" ON "appointment_origins"("workspace_id");
59
-
60
- -- CreateIndex
61
- -- One origin per booking uid (spec D5). The bind inserts with
62
- -- ON CONFLICT DO NOTHING against this key.
63
- CREATE UNIQUE INDEX "appointment_origins_provider_provider_booking_uid_key" ON "appointment_origins"("provider", "provider_booking_uid");
64
-
65
- -- AddForeignKey
66
- ALTER TABLE "spokes" ADD CONSTRAINT "spokes_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
67
-
68
- -- ADR-0031 rule 3 — spokes: spoke_, appointment_origins: apptorg_ (registered
69
- -- in packages/ids/src/registry.ts; this migration's path is added to
70
- -- migration-sync.test.ts's PK_CHECK_MIGRATIONS).
71
- ALTER TABLE "spokes" ALTER COLUMN "id" TYPE text COLLATE "C";
72
- ALTER TABLE "spokes" ALTER COLUMN "id" SET DEFAULT ('spoke_'::text || (uuidv7())::text);
73
- ALTER TABLE "spokes" ADD CONSTRAINT "spokes_id_format" CHECK ("id" ~ '^spoke_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
74
- ALTER TABLE "spokes" ADD CONSTRAINT "spokes_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
75
-
76
- ALTER TABLE "appointment_origins" ALTER COLUMN "id" TYPE text COLLATE "C";
77
- ALTER TABLE "appointment_origins" ALTER COLUMN "id" SET DEFAULT ('apptorg_'::text || (uuidv7())::text);
78
- ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_id_format" CHECK ("id" ~ '^apptorg_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
79
- ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_spoke_id_format" CHECK ("spoke_id" ~ '^spoke_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
80
- ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
@@ -1,49 +0,0 @@
1
- -- #7533 — the SchedulingConnection model: a workspace's own scheduling
2
- -- provider account (spec docs/specs/7533-a-scheduling-connection-per-workspace-spec.md
3
- -- D1). One row per workspace, keyed `@unique(workspace_id)` like its config
4
- -- sibling workspace_meetings; the credential and webhook secret columns hold
5
- -- AES-256-GCM ciphertext written only by apps/api's
6
- -- services/scheduling/connections.ts. `webhook_token` is the per-connection
7
- -- webhook entry point's routing id, unique so a delivery resolves at most
8
- -- one row.
9
- --
10
- -- One new table, two unique indexes, in the house style of
11
- -- 20260919130000_workspace_meetings (CreateTable + CreateIndex immediately
12
- -- followed by the ADR-0031 rule-3 id-format completion, in ONE migration
13
- -- since the table is new and needs no retrofit). No `workspace_id_format`
14
- -- CHECK and no `provider` CHECK, matching that same precedent (the API
15
- -- accepts only the provider ids its factory table knows).
16
- --
17
- -- No backfill, no constraint relaxed, no existing table touched.
18
- --
19
- -- Rollback: DROP TABLE "scheduling_connections". Every stored connection is
20
- -- lost; each workspace returns to the unconfigured state (or, on a
21
- -- one-workspace deployment, to the CAL_API_KEY env fallback).
22
-
23
- -- CreateTable
24
- CREATE TABLE "scheduling_connections" (
25
- "id" TEXT NOT NULL DEFAULT ('schconn_'::text || (uuidv7())::text),
26
- "workspace_id" TEXT NOT NULL,
27
- "provider" VARCHAR(32) NOT NULL,
28
- "credential_ciphertext" TEXT NOT NULL,
29
- "webhook_token" VARCHAR(64) NOT NULL,
30
- "webhook_secret_ciphertext" TEXT NOT NULL,
31
- "base_url" TEXT,
32
- "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
33
- "updated_at" TIMESTAMPTZ NOT NULL,
34
-
35
- CONSTRAINT "scheduling_connections_pkey" PRIMARY KEY ("id")
36
- );
37
-
38
- -- CreateIndex
39
- CREATE UNIQUE INDEX "scheduling_connections_workspace_id_key" ON "scheduling_connections"("workspace_id");
40
-
41
- -- CreateIndex
42
- CREATE UNIQUE INDEX "scheduling_connections_webhook_token_key" ON "scheduling_connections"("webhook_token");
43
-
44
- -- ADR-0031 rule 3 — scheduling_connections: schconn_ (registered in
45
- -- packages/ids/src/registry.ts ENTITY_PREFIX.schedulingConnection; this
46
- -- migration's path is added to migration-sync.test.ts's PK_CHECK_MIGRATIONS).
47
- ALTER TABLE "scheduling_connections" ALTER COLUMN "id" TYPE text COLLATE "C";
48
- ALTER TABLE "scheduling_connections" ALTER COLUMN "id" SET DEFAULT ('schconn_'::text || (uuidv7())::text);
49
- ALTER TABLE "scheduling_connections" ADD CONSTRAINT "scheduling_connections_id_format" CHECK ("id" ~ '^schconn_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
@@ -1,84 +0,0 @@
1
- -- #3591 — the agent seat, step A (spec
2
- -- docs/specs/3591-tenant-scoped-agent-auth-secure-spec.md D1).
3
- --
4
- -- agents (auth) — one row per agent: a stored delegate of ONE person (its
5
- -- responsible Membership), bound to ONE workspace. It stores
6
- -- the SHA-256 digest of the agent's key, never the key.
7
- -- Deleting the organization, the workspace or the person's
8
- -- membership deletes the agent; deleting the membership of
9
- -- the person who was last shown its key sets
10
- -- key_issued_to_membership_id null, which the guard refuses
11
- -- until the agent is re-keyed. created_by_user_id is a plain
12
- -- column with no foreign key, so deleting the creator does
13
- -- not delete the agents they made for someone else.
14
- --
15
- -- PURELY ADDITIVE: one new enum, one new table, its indexes and four FKs (to
16
- -- "organizations", "workspaces" and twice to "memberships"). No statement
17
- -- touches an existing table's rows or columns, so there is no pre-assertion
18
- -- block — this migration cannot lose a row.
19
- --
20
- -- Rollback: DROP TABLE "agents"; DROP TYPE "AgentPermissionLevel". Safe while
21
- -- nothing but #3591's own code reads them.
22
-
23
- -- CreateEnum
24
- CREATE TYPE "AgentPermissionLevel" AS ENUM ('member');
25
-
26
- -- CreateTable
27
- CREATE TABLE "agents" (
28
- "id" TEXT NOT NULL DEFAULT ('agent_'::text || (uuidv7())::text),
29
- "organization_id" TEXT NOT NULL,
30
- "workspace_id" TEXT NOT NULL,
31
- "responsible_membership_id" TEXT NOT NULL,
32
- "name" VARCHAR(80) NOT NULL,
33
- "permission_level" "AgentPermissionLevel" NOT NULL DEFAULT 'member',
34
- "enabled" BOOLEAN NOT NULL DEFAULT true,
35
- "credential_hash" CHAR(64) NOT NULL,
36
- "credential_prefix" VARCHAR(24) NOT NULL,
37
- "last_active_at" TIMESTAMP(3),
38
- "created_by_user_id" TEXT NOT NULL,
39
- "key_issued_to_membership_id" TEXT,
40
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
41
- "updated_at" TIMESTAMP(3) NOT NULL,
42
-
43
- CONSTRAINT "agents_pkey" PRIMARY KEY ("id")
44
- );
45
-
46
- -- CreateIndex
47
- -- The lookup an agent's every request makes (`findAgentByKeyHash`).
48
- CREATE UNIQUE INDEX "agents_credential_hash_key" ON "agents"("credential_hash");
49
-
50
- -- CreateIndex
51
- CREATE INDEX "agents_organization_id_idx" ON "agents"("organization_id");
52
-
53
- -- CreateIndex
54
- CREATE INDEX "agents_workspace_id_idx" ON "agents"("workspace_id");
55
-
56
- -- CreateIndex
57
- CREATE INDEX "agents_responsible_membership_id_idx" ON "agents"("responsible_membership_id");
58
-
59
- -- AddForeignKey
60
- ALTER TABLE "agents" ADD CONSTRAINT "agents_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
61
-
62
- -- AddForeignKey
63
- ALTER TABLE "agents" ADD CONSTRAINT "agents_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
64
-
65
- -- AddForeignKey
66
- -- Leaving stops the agent: removing the person's membership deletes it.
67
- ALTER TABLE "agents" ADD CONSTRAINT "agents_responsible_membership_id_fkey" FOREIGN KEY ("responsible_membership_id") REFERENCES "memberships"("id") ON DELETE CASCADE ON UPDATE CASCADE;
68
-
69
- -- AddForeignKey
70
- -- A key dies with the person who received it: SET NULL, which the guard refuses.
71
- ALTER TABLE "agents" ADD CONSTRAINT "agents_key_issued_to_membership_id_fkey" FOREIGN KEY ("key_issued_to_membership_id") REFERENCES "memberships"("id") ON DELETE SET NULL ON UPDATE CASCADE;
72
-
73
- -- ADR-0031 rule 3 — agents: agent_ (registered in packages/ids/src/registry.ts;
74
- -- this migration's path is added to migration-sync.test.ts's
75
- -- PK_CHECK_MIGRATIONS). Each reference column carries the format CHECK of the
76
- -- entity it names, in the exact pattern the spoke migration uses.
77
- ALTER TABLE "agents" ALTER COLUMN "id" TYPE text COLLATE "C";
78
- ALTER TABLE "agents" ALTER COLUMN "id" SET DEFAULT ('agent_'::text || (uuidv7())::text);
79
- ALTER TABLE "agents" ADD CONSTRAINT "agents_id_format" CHECK ("id" ~ '^agent_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
80
- ALTER TABLE "agents" ADD CONSTRAINT "agents_organization_id_format" CHECK ("organization_id" ~ '^org_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
81
- ALTER TABLE "agents" ADD CONSTRAINT "agents_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
82
- ALTER TABLE "agents" ADD CONSTRAINT "agents_responsible_membership_id_format" CHECK ("responsible_membership_id" ~ '^member_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
83
- ALTER TABLE "agents" ADD CONSTRAINT "agents_key_issued_to_membership_id_format" CHECK ("key_issued_to_membership_id" ~ '^member_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
84
- ALTER TABLE "agents" ADD CONSTRAINT "agents_created_by_user_id_format" CHECK ("created_by_user_id" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
@@ -1,35 +0,0 @@
1
- -- #7803 — sign-in lands in the user's last workspace (spec
2
- -- docs/specs/7803-sign-in-last-workspace-spec.md D1).
3
- --
4
- -- users.last_workspace_id (auth) — the workspace this person last activated.
5
- -- Written only by activateWorkspace after its membership
6
- -- grant; read only by listTenancy, which reports it only
7
- -- when the workspace is in the caller's own listing
8
- -- (apps/api/src/services/tenant-context.ts). Deleting the
9
- -- workspace sets it null.
10
- --
11
- -- PURELY ADDITIVE: one nullable column with no default, its index, one FK to
12
- -- "workspaces" and the ADR-0031 format CHECK on the new reference column. No
13
- -- backfill runs and no existing row changes, so there is no pre-assertion
14
- -- block — this migration cannot lose a row. A NULL passes the CHECK.
15
- --
16
- -- Rollout: deploy this migration BEFORE the API code that reads the column
17
- -- (SEC-7803-3). Being nullable, it is safe to apply ahead of the code.
18
- --
19
- -- Rollback: ALTER TABLE "users" DROP COLUMN "last_workspace_id"; (this drops
20
- -- the index, the FK and the CHECK with it). Safe while nothing but #7803's own
21
- -- code reads it.
22
-
23
- -- AlterTable
24
- ALTER TABLE "users" ADD COLUMN "last_workspace_id" TEXT;
25
-
26
- -- CreateIndex
27
- CREATE INDEX "users_last_workspace_id_idx" ON "users"("last_workspace_id");
28
-
29
- -- AddForeignKey
30
- -- A deleted workspace clears every pointer to it.
31
- ALTER TABLE "users" ADD CONSTRAINT "users_last_workspace_id_fkey" FOREIGN KEY ("last_workspace_id") REFERENCES "workspaces"("id") ON DELETE SET NULL ON UPDATE CASCADE;
32
-
33
- -- ADR-0031 rule 3 — the reference column carries the format CHECK of the
34
- -- entity it names (wksp_), in the exact pattern the agents migration uses.
35
- ALTER TABLE "users" ADD CONSTRAINT "users_last_workspace_id_format" CHECK ("last_workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
@@ -1,20 +0,0 @@
1
- -- #7869 (spoke-pattern roadmap Phase 1, D5) — Lead idempotency key: the
2
- -- caller's optional `Idempotency-Key` header on POST /v1/leads/submit, so a
3
- -- retried lead write (a client retry, a spoke's fulfilment replay) finds the
4
- -- first lead instead of writing a second. Mirrors the column-add shape of
5
- -- 20260906000000_add_flow_checkout_idempotency (one AlterTable, one unique
6
- -- index under the Prisma section headers).
7
- --
8
- -- The column is nullable with no default, so no pre-existing row needs a
9
- -- backfill and none collides on the new unique — Postgres treats NULLs as
10
- -- distinct. The unique is scoped by workspace_id: one key in two workspaces
11
- -- is two leads.
12
- --
13
- -- Rollback: ALTER TABLE "leads" DROP COLUMN "idempotency_key"; (the index
14
- -- goes with it).
15
-
16
- -- AlterTable
17
- ALTER TABLE "leads" ADD COLUMN "idempotency_key" TEXT;
18
-
19
- -- CreateIndex
20
- CREATE UNIQUE INDEX "leads_workspace_id_idempotency_key_key" ON "leads"("workspace_id", "idempotency_key");
@@ -1,33 +0,0 @@
1
- -- #7864 — grant an agent key five named abilities (spec
2
- -- docs/specs/7864-agent-key-grants-spec.md D2).
3
- --
4
- -- agents.grants (auth) — the permissions an owner or admin granted this
5
- -- agent one by one. Written only by setServedAgentGrants
6
- -- (apps/api/src/lib/agent-store.ts, the PUT
7
- -- …/agents/:agentId/grants route); read by the auth
8
- -- preHandler's key lookup and the agent list. The tenant
9
- -- guards hold an agent to the grants its person's own role
10
- -- also holds, so a stored grant never outranks the person.
11
- --
12
- -- The CHECK names the same five permissions as @working-theory/validation's
13
- -- AGENT_GRANTABLE_PERMISSIONS; database/__tests__/agents.db.test.ts reads
14
- -- this file and fails if the two lists differ (SEC-7864-G).
15
- --
16
- -- PURELY ADDITIVE: one NOT NULL column with an empty-array default and its
17
- -- CHECK. No backfill runs: every existing agent takes the default, no
18
- -- grants, and so behaves exactly as before. No existing row changes beyond
19
- -- the default fill, so there is no pre-assertion block.
20
- --
21
- -- Rollout: deploy this migration BEFORE the API code that reads the column.
22
- -- Code without the column fails closed — its key lookup errors and every
23
- -- agent is answered 401 (SEC-7864-F).
24
- --
25
- -- Rollback: ALTER TABLE "agents" DROP COLUMN "grants"; (this drops the CHECK
26
- -- with it). Safe while nothing but #7864's own code reads it.
27
-
28
- -- AlterTable
29
- ALTER TABLE "agents" ADD COLUMN "grants" TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[];
30
-
31
- -- Only the five grantable permissions may be stored.
32
- ALTER TABLE "agents" ADD CONSTRAINT "agents_grants_allowed"
33
- CHECK ("grants" <@ ARRAY['content-edit','content-publish','assets-write','magnets-manage','meeting-types-manage']::TEXT[]);
@@ -1,106 +0,0 @@
1
- -- #852 — Person, the per-workspace client record (spec
2
- -- docs/specs/852-person-the-per-workspace-client-spec.md D1, D2).
3
- --
4
- -- people (inbox) — one client of one workspace, keyed on a lowercased,
5
- -- trimmed email unique per workspace. Created only by
6
- -- apps/api/src/services/person.ts's findOrCreatePerson.
7
- -- workspace_id and user_id are plain columns with no
8
- -- foreign key (ADR 0009): they name auth-namespace rows.
9
- -- leads.person_id, appointments.person_id — the Person each row belongs
10
- -- to, stamped at creation by the intake paths.
11
- --
12
- -- PURELY ADDITIVE, DDL ONLY: one new table with its indexes and CHECKs, and
13
- -- one nullable column with no default on each of "leads" and "appointments",
14
- -- so Postgres changes only the catalog for those two. No existing row's
15
- -- values change here — the backfill is the next migration,
16
- -- 20261010121000_person_backfill, split out so its row updates never run
17
- -- under the exclusive locks these ALTER TABLEs take (SEC-852-E). Prisma runs
18
- -- this file as one transaction, so each ALTER TABLE's ACCESS EXCLUSIVE lock
19
- -- is held until the file commits — through the plain CREATE INDEX on the new
20
- -- column — blocking reads AND writes of "leads" and "appointments" (lead
21
- -- capture included) for one heap scan of each. Accepted: the scan is short
22
- -- next to the backfill it is split from.
23
- --
24
- -- Rollout: deploy this migration (and the backfill) BEFORE the API code that
25
- -- writes person_id; code without the column fails every lead write.
26
- --
27
- -- Rollback: ALTER TABLE "leads" DROP COLUMN "person_id"; ALTER TABLE
28
- -- "appointments" DROP COLUMN "person_id"; DROP TABLE "people"; (the indexes
29
- -- and CHECKs go with them). Safe while nothing but #852's own code reads them.
30
-
31
- -- AlterTable
32
- ALTER TABLE "appointments" ADD COLUMN "person_id" TEXT;
33
-
34
- -- AlterTable
35
- ALTER TABLE "leads" ADD COLUMN "person_id" TEXT;
36
-
37
- -- CreateTable
38
- CREATE TABLE "people" (
39
- "id" TEXT NOT NULL DEFAULT ('person_'::text || (uuidv7())::text),
40
- "workspace_id" TEXT NOT NULL,
41
- "email" VARCHAR(254) NOT NULL,
42
- "name" VARCHAR(200),
43
- "user_id" TEXT,
44
- "billing_provider" VARCHAR(32),
45
- "billing_customer_id" VARCHAR(255),
46
- "plan_offering" VARCHAR(100),
47
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
48
- "updated_at" TIMESTAMP(3) NOT NULL,
49
-
50
- CONSTRAINT "people_pkey" PRIMARY KEY ("id")
51
- );
52
-
53
- -- CreateIndex
54
- -- The webhook's first match: a customer id within one workspace (D3 step 2).
55
- -- NOT unique — the spokes share one Stripe account.
56
- CREATE INDEX "people_workspace_id_billing_customer_id_idx" ON "people"("workspace_id", "billing_customer_id");
57
-
58
- -- CreateIndex
59
- -- The People list: workspace_id = $1 ORDER BY created_at DESC (D7).
60
- CREATE INDEX "people_workspace_id_created_at_idx" ON "people"("workspace_id", "created_at");
61
-
62
- -- CreateIndex
63
- -- One Person per address per workspace — what findOrCreatePerson's
64
- -- INSERT … ON CONFLICT DO NOTHING absorbs a concurrent duplicate on.
65
- CREATE UNIQUE INDEX "people_workspace_id_email_key" ON "people"("workspace_id", "email");
66
-
67
- -- CreateIndex
68
- -- One Person per User per workspace. NULLs are distinct, so any number of
69
- -- unlinked Persons fit.
70
- CREATE UNIQUE INDEX "people_workspace_id_user_id_key" ON "people"("workspace_id", "user_id");
71
-
72
- -- CreateIndex
73
- CREATE INDEX "appointments_person_id_idx" ON "appointments"("person_id");
74
-
75
- -- CreateIndex
76
- CREATE INDEX "leads_person_id_idx" ON "leads"("person_id");
77
-
78
- -- ADR-0031 rule 3 — people: person_ (registered in packages/ids/src/registry.ts;
79
- -- this migration's path is added to migration-sync.test.ts's
80
- -- PK_CHECK_MIGRATIONS). Each reference column carries the format CHECK of the
81
- -- entity it names, in the agents-migration shape.
82
- ALTER TABLE "people" ALTER COLUMN "id" TYPE text COLLATE "C";
83
- ALTER TABLE "people" ALTER COLUMN "id" SET DEFAULT ('person_'::text || (uuidv7())::text);
84
- ALTER TABLE "people" ADD CONSTRAINT "people_id_format" CHECK ("id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
85
- ALTER TABLE "people" ADD CONSTRAINT "people_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
86
- ALTER TABLE "people" ADD CONSTRAINT "people_user_id_format" CHECK ("user_id" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
87
-
88
- -- The stored address is already normalized: printable ASCII only (no
89
- -- whitespace, no control or invisible character), exactly one @ with a
90
- -- non-empty side each, lower case. findOrCreatePerson's
91
- -- isStorablePersonEmail applies the same rule before any write (D3).
92
- ALTER TABLE "people" ADD CONSTRAINT "people_email_normalized"
93
- CHECK ("email" = lower("email" COLLATE "C") AND "email" ~ '^[!-?A-~]+@[!-?A-~]+$');
94
-
95
- -- A provider and its customer id are written together or not at all — the
96
- -- same provider-agnostic pair User and Organization carry.
97
- ALTER TABLE "people" ADD CONSTRAINT "people_billing_pair"
98
- CHECK (("billing_provider" IS NULL) = ("billing_customer_id" IS NULL));
99
-
100
- -- The two new reference columns carry the person_ format CHECK, added NOT
101
- -- VALID and then validated: the file runs as one transaction, so the ALTER
102
- -- TABLE's lock is still held, and the scan is of an all-NULL column.
103
- ALTER TABLE "leads" ADD CONSTRAINT "leads_person_id_format" CHECK ("person_id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') NOT VALID;
104
- ALTER TABLE "leads" VALIDATE CONSTRAINT "leads_person_id_format";
105
- ALTER TABLE "appointments" ADD CONSTRAINT "appointments_person_id_format" CHECK ("person_id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') NOT VALID;
106
- ALTER TABLE "appointments" VALIDATE CONSTRAINT "appointments_person_id_format";