create-ailk 0.24.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 (599) hide show
  1. package/README.md +42 -20
  2. package/component-catalog.json +3 -3
  3. package/component-catalog.md +3 -3
  4. package/dist/add-module.js +4 -2
  5. package/dist/add-route.d.ts +12 -1
  6. package/dist/add-route.js +31 -3
  7. package/dist/cli.js +12 -7
  8. package/dist/derive-architecture.d.ts +3 -4
  9. package/dist/derive-architecture.js +65 -29
  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/module-architecture.d.ts +20 -3
  20. package/dist/module-architecture.js +117 -550
  21. package/dist/paid-sections.d.ts +25 -1
  22. package/dist/paid-sections.js +88 -3
  23. package/dist/surfaces.js +10 -2
  24. package/dist/template-record.d.ts +14 -4
  25. package/dist/template-record.js +23 -5
  26. package/dist/topology.d.ts +16 -3
  27. package/dist/topology.js +31 -19
  28. package/dist/update.d.ts +10 -1
  29. package/dist/update.js +540 -16
  30. package/package.json +3 -3
  31. package/release-scope.json +1 -1
  32. package/templates/.claude/cloudparity-repo-hooks.json +5 -0
  33. package/templates/.claude/hooks/template-guard.sh +137 -0
  34. package/templates/.claude/rules/extending.md +106 -0
  35. package/templates/.claude/rules/loop-contract.md +2 -2
  36. package/templates/.claude/settings.json +11 -0
  37. package/templates/.env.example +5 -5
  38. package/templates/.github/workflows/ci.yml +7 -4
  39. package/templates/CLAUDE.md +11 -1
  40. package/templates/CONVENTIONS.md +8 -10
  41. package/templates/README.md +14 -13
  42. package/templates/apps/api/.env.example +2 -2
  43. package/templates/apps/api/CLAUDE.md +102 -76
  44. package/templates/apps/api/jest.config.cjs +15 -5
  45. package/templates/apps/api/package.json +16 -20
  46. package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
  47. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
  48. package/templates/apps/api/src/index.ts +1 -1
  49. package/templates/apps/api/src/lib/__mocks__/prisma.ts +3 -3
  50. package/templates/apps/api/src/modules/commerce.ts +10 -0
  51. package/templates/apps/api/src/modules/content-write.ts +10 -0
  52. package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
  53. package/templates/apps/api/src/modules/scheduling.ts +10 -0
  54. package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
  55. package/templates/apps/api/src/modules/workspace.ts +10 -0
  56. package/templates/apps/api/src/server.ts +117 -1882
  57. package/templates/apps/api/vercel.json +2 -2
  58. package/templates/apps/mcp/CLAUDE.md +67 -20
  59. package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
  60. package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
  61. package/templates/apps/mcp/jest.config.cjs +6 -1
  62. package/templates/apps/mcp/package.json +5 -13
  63. package/templates/apps/mcp/src/app.ts +8 -7
  64. package/templates/apps/mcp/src/index.ts +6 -34
  65. package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
  66. package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
  67. package/templates/apps/mcp/src/site.ts +12 -0
  68. package/templates/apps/web/.env.example +1 -1
  69. package/templates/apps/web/CLAUDE.md +10 -3
  70. package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
  71. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
  72. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
  73. package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +7 -3
  74. package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
  75. package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
  76. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
  77. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
  78. package/templates/apps/web/app/api/revalidate/route.ts +3 -3
  79. package/templates/apps/web/auth.ts +2 -2
  80. package/templates/apps/web/jest.config.cjs +1 -0
  81. package/templates/apps/web/lib/auth-email.ts +1 -1
  82. package/templates/apps/web/lib/relay.ts +2 -2
  83. package/templates/apps/web/lib/release-scope.ts +47 -0
  84. package/templates/apps/web/lib/server-api.ts +1 -1
  85. package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
  86. package/templates/customizations.yaml +37 -0
  87. package/templates/database/prisma.config.ts +10 -14
  88. package/templates/database/seed-test.ts +2 -2
  89. package/templates/database/seed.ts +5 -5
  90. package/templates/package.json +12 -6
  91. package/templates/pnpm-workspace.yaml +0 -1
  92. package/templates/project.yaml +16 -8
  93. package/templates/tools/jest/reporters.cjs +65 -0
  94. package/templates/tools/lint-architecture.ts +553 -7
  95. package/templates/tsconfig.json +1 -2
  96. package/versions.json +48 -35
  97. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
  98. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
  99. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
  100. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
  101. package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
  102. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
  103. package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
  104. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
  105. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
  106. package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
  107. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
  108. package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
  109. package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
  110. package/templates/apps/api/src/bin/spokes.ts +0 -198
  111. package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
  112. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
  113. package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
  114. package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
  115. package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
  116. package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
  117. package/templates/apps/api/src/config/index.ts +0 -596
  118. package/templates/apps/api/src/config/modules.ts +0 -83
  119. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
  120. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
  121. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
  122. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
  123. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
  124. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
  125. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
  126. package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
  127. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
  128. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
  129. package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
  130. package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
  131. package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
  132. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
  133. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
  134. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
  135. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
  136. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
  137. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
  138. package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -308
  139. package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
  140. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
  141. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
  142. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
  143. package/templates/apps/api/src/lib/agent-store.ts +0 -613
  144. package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
  145. package/templates/apps/api/src/lib/consent-store.ts +0 -363
  146. package/templates/apps/api/src/lib/content-adapter.ts +0 -112
  147. package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
  148. package/templates/apps/api/src/lib/error-serializer.ts +0 -164
  149. package/templates/apps/api/src/lib/errors.ts +0 -95
  150. package/templates/apps/api/src/lib/file-fallback.ts +0 -87
  151. package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
  152. package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
  153. package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
  154. package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
  155. package/templates/apps/api/src/lib/license-key-store.ts +0 -45
  156. package/templates/apps/api/src/lib/locales.ts +0 -201
  157. package/templates/apps/api/src/lib/outbound-http.ts +0 -127
  158. package/templates/apps/api/src/lib/prisma.ts +0 -21
  159. package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
  160. package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
  161. package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
  162. package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
  163. package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
  164. package/templates/apps/api/src/lib/site.ts +0 -257
  165. package/templates/apps/api/src/lib/slice-load.ts +0 -90
  166. package/templates/apps/api/src/lib/spoke-store.ts +0 -180
  167. package/templates/apps/api/src/lib/stripe.ts +0 -321
  168. package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
  169. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
  170. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
  171. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
  172. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
  173. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
  174. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
  175. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
  176. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
  177. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
  178. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
  179. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
  180. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
  181. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
  182. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
  183. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
  184. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
  185. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
  186. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
  187. package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
  188. package/templates/apps/api/src/middleware/auth.ts +0 -864
  189. package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
  190. package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
  191. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -391
  192. package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
  193. package/templates/apps/api/src/openapi/index.ts +0 -18
  194. package/templates/apps/api/src/openapi/spec.ts +0 -2148
  195. package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
  196. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
  197. package/templates/apps/api/src/routes/aeo/index.ts +0 -107
  198. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
  199. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
  200. package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
  201. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
  202. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
  203. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
  204. package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
  205. package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
  206. package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
  207. package/templates/apps/api/src/routes/auth/user.ts +0 -305
  208. package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -332
  209. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
  210. package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1426
  211. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
  212. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
  213. package/templates/apps/api/src/routes/checkout/index.ts +0 -34
  214. package/templates/apps/api/src/routes/checkout/session.ts +0 -171
  215. package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
  216. package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
  217. package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
  218. package/templates/apps/api/src/routes/consent/account.ts +0 -268
  219. package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
  220. package/templates/apps/api/src/routes/consent/index.ts +0 -26
  221. package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
  222. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
  223. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
  224. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
  225. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
  226. package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
  227. package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
  228. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
  229. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
  230. package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
  231. package/templates/apps/api/src/routes/content/get-page.ts +0 -183
  232. package/templates/apps/api/src/routes/content/index.ts +0 -49
  233. package/templates/apps/api/src/routes/content/list-pages.ts +0 -74
  234. package/templates/apps/api/src/routes/content/list-types.ts +0 -19
  235. package/templates/apps/api/src/routes/content/offerings.ts +0 -184
  236. package/templates/apps/api/src/routes/content/pricing.ts +0 -176
  237. package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
  238. package/templates/apps/api/src/routes/content/search.ts +0 -100
  239. package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
  240. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
  241. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
  242. package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
  243. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
  244. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
  245. package/templates/apps/api/src/routes/leads/index.ts +0 -639
  246. package/templates/apps/api/src/routes/leads/list.ts +0 -104
  247. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
  248. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
  249. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
  250. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -491
  251. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -476
  252. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
  253. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
  254. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
  255. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
  256. package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
  257. package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
  258. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
  259. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
  260. package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
  261. package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
  262. package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
  263. package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
  264. package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
  265. package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
  266. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
  267. package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
  268. package/templates/apps/api/src/routes/requests/index.ts +0 -54
  269. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
  270. package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
  271. package/templates/apps/api/src/routes/webhooks/README.md +0 -398
  272. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
  273. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
  274. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -449
  275. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
  276. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
  277. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
  278. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
  279. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
  280. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
  281. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
  282. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
  283. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -809
  284. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
  285. package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
  286. package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
  287. package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2028
  288. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -645
  289. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
  290. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
  291. package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
  292. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
  293. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
  294. package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
  295. package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
  296. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -877
  297. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
  298. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
  299. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
  300. package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
  301. package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
  302. package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
  303. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
  304. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
  305. package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
  306. package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1204
  307. package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -450
  308. package/templates/apps/api/src/services/__tests__/project-listings.counts.test.ts +0 -202
  309. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -151
  310. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
  311. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
  312. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
  313. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
  314. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
  315. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
  316. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
  317. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
  318. package/templates/apps/api/src/services/abandon-email.ts +0 -336
  319. package/templates/apps/api/src/services/aeo-score.ts +0 -325
  320. package/templates/apps/api/src/services/answer-distributions.ts +0 -138
  321. package/templates/apps/api/src/services/audit-log.ts +0 -961
  322. package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
  323. package/templates/apps/api/src/services/consent.ts +0 -834
  324. package/templates/apps/api/src/services/default-tenant.ts +0 -416
  325. package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -750
  326. package/templates/apps/api/src/services/dunning-policy.ts +0 -294
  327. package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
  328. package/templates/apps/api/src/services/entitlements.ts +0 -338
  329. package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
  330. package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
  331. package/templates/apps/api/src/services/lead-promotion.ts +0 -160
  332. package/templates/apps/api/src/services/lead-routing.ts +0 -1372
  333. package/templates/apps/api/src/services/leads-inbox.ts +0 -312
  334. package/templates/apps/api/src/services/listing-config.ts +0 -178
  335. package/templates/apps/api/src/services/magnet-completion.ts +0 -242
  336. package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -348
  337. package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
  338. package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -975
  339. package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
  340. package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -400
  341. package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -685
  342. package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
  343. package/templates/apps/api/src/services/offerings/catalog.ts +0 -318
  344. package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -403
  345. package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
  346. package/templates/apps/api/src/services/offerings/connection.ts +0 -1083
  347. package/templates/apps/api/src/services/offerings/index.ts +0 -614
  348. package/templates/apps/api/src/services/offerings/source.ts +0 -140
  349. package/templates/apps/api/src/services/offerings/store.ts +0 -150
  350. package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
  351. package/templates/apps/api/src/services/person.ts +0 -1211
  352. package/templates/apps/api/src/services/plan-offerings.ts +0 -125
  353. package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
  354. package/templates/apps/api/src/services/project-listings.ts +0 -2085
  355. package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
  356. package/templates/apps/api/src/services/request-confirm.ts +0 -698
  357. package/templates/apps/api/src/services/revalidation.ts +0 -235
  358. package/templates/apps/api/src/services/slack-notify.ts +0 -291
  359. package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
  360. package/templates/apps/api/src/services/usage-credits.ts +0 -340
  361. package/templates/apps/api/src/services/verified-email.ts +0 -71
  362. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
  363. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
  364. package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
  365. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
  366. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
  367. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
  368. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
  369. package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
  370. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
  371. package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
  372. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
  373. package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
  374. package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
  375. package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
  376. package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
  377. package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
  378. package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1232
  379. package/templates/apps/mcp/__tests__/index.test.ts +0 -195
  380. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
  381. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
  382. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -70
  383. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -162
  384. package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
  385. package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
  386. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -180
  387. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
  388. package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -268
  389. package/templates/apps/mcp/__tests__/locale.test.ts +0 -120
  390. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
  391. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
  392. package/templates/apps/mcp/__tests__/rate-limit-write.test.ts +0 -189
  393. package/templates/apps/mcp/__tests__/read_content.test.ts +0 -511
  394. package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -160
  395. package/templates/apps/mcp/__tests__/search_content.test.ts +0 -271
  396. package/templates/apps/mcp/__tests__/server.test.ts +0 -388
  397. package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
  398. package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -222
  399. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -152
  400. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
  401. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
  402. package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
  403. package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
  404. package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
  405. package/templates/apps/mcp/src/abuse/index.ts +0 -349
  406. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
  407. package/templates/apps/mcp/src/boot.ts +0 -167
  408. package/templates/apps/mcp/src/config/modules.ts +0 -43
  409. package/templates/apps/mcp/src/http-transport.ts +0 -564
  410. package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
  411. package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
  412. package/templates/apps/mcp/src/lib/content-adapter.ts +0 -116
  413. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -140
  414. package/templates/apps/mcp/src/lib/errors.ts +0 -61
  415. package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
  416. package/templates/apps/mcp/src/lib/locales.ts +0 -171
  417. package/templates/apps/mcp/src/lib/prisma.ts +0 -39
  418. package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
  419. package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
  420. package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
  421. package/templates/apps/mcp/src/lib/site-config.ts +0 -53
  422. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
  423. package/templates/apps/mcp/src/request-context.ts +0 -52
  424. package/templates/apps/mcp/src/server.ts +0 -343
  425. package/templates/apps/mcp/src/serverless-app.ts +0 -88
  426. package/templates/apps/mcp/src/tools/audit.ts +0 -127
  427. package/templates/apps/mcp/src/tools/capture_lead.ts +0 -66
  428. package/templates/apps/mcp/src/tools/create_project.ts +0 -134
  429. package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
  430. package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
  431. package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
  432. package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
  433. package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
  434. package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
  435. package/templates/apps/mcp/src/tools/index.ts +0 -138
  436. package/templates/apps/mcp/src/tools/list_pages.ts +0 -68
  437. package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
  438. package/templates/apps/mcp/src/tools/proposals.ts +0 -27
  439. package/templates/apps/mcp/src/tools/purchase.ts +0 -205
  440. package/templates/apps/mcp/src/tools/read_content.ts +0 -81
  441. package/templates/apps/mcp/src/tools/request_callback.ts +0 -52
  442. package/templates/apps/mcp/src/tools/search_content.ts +0 -63
  443. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -54
  444. package/templates/apps/mcp/src/workspace-server.ts +0 -224
  445. package/templates/database/CHANGELOG.md +0 -981
  446. package/templates/database/LICENSE +0 -202
  447. package/templates/database/NOTICE +0 -2
  448. package/templates/database/README.md +0 -243
  449. package/templates/database/__tests__/agents.db.test.ts +0 -320
  450. package/templates/database/__tests__/appointment.db.test.ts +0 -106
  451. package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
  452. package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
  453. package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
  454. package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
  455. package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
  456. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
  457. package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
  458. package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
  459. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
  460. package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
  461. package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
  462. package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
  463. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
  464. package/templates/database/__tests__/flows-presets.test.ts +0 -173
  465. package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
  466. package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
  467. package/templates/database/__tests__/member-area.db.test.ts +0 -257
  468. package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
  469. package/templates/database/__tests__/member-contract.db.test.ts +0 -413
  470. package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
  471. package/templates/database/__tests__/offerings-migration.test.ts +0 -197
  472. package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
  473. package/templates/database/__tests__/offerings.db.test.ts +0 -303
  474. package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
  475. package/templates/database/__tests__/person-contact.db.test.ts +0 -563
  476. package/templates/database/__tests__/person-notes.db.test.ts +0 -249
  477. package/templates/database/__tests__/person.db.test.ts +0 -586
  478. package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
  479. package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
  480. package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
  481. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
  482. package/templates/database/__tests__/seed.test.ts +0 -272
  483. package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
  484. package/templates/database/__tests__/tenancy.test.ts +0 -141
  485. package/templates/database/__tests__/trial-magnet-migration.test.ts +0 -186
  486. package/templates/database/__tests__/user-cascade.test.ts +0 -140
  487. package/templates/database/_gitignore +0 -8
  488. package/templates/database/auth/.gitkeep +0 -0
  489. package/templates/database/auth/schema.prisma +0 -641
  490. package/templates/database/config/.gitkeep +0 -0
  491. package/templates/database/config/schema.prisma +0 -441
  492. package/templates/database/content/.gitkeep +0 -0
  493. package/templates/database/content/schema.prisma +0 -339
  494. package/templates/database/eslint.config.mjs +0 -69
  495. package/templates/database/flows/listing-diagnostic.ts +0 -182
  496. package/templates/database/flows/presets.ts +0 -315
  497. package/templates/database/inbox/.gitkeep +0 -0
  498. package/templates/database/inbox/README.md +0 -3
  499. package/templates/database/inbox/__tests__/schema.test.ts +0 -44
  500. package/templates/database/inbox/schema.prisma +0 -1447
  501. package/templates/database/jest.config.cjs +0 -36
  502. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
  503. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
  504. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
  505. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
  506. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
  507. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
  508. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
  509. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
  510. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
  511. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
  512. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
  513. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
  514. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
  515. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
  516. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
  517. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
  518. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
  519. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
  520. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
  521. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
  522. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
  523. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
  524. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
  525. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
  526. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
  527. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
  528. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
  529. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
  530. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
  531. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
  532. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
  533. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
  534. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
  535. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
  536. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
  537. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
  538. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
  539. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
  540. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
  541. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
  542. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
  543. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
  544. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
  545. package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
  546. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
  547. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
  548. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
  549. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
  550. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
  551. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
  552. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
  553. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
  554. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
  555. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
  556. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
  557. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
  558. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
  559. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
  560. package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
  561. package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
  562. package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
  563. package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
  564. package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
  565. package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
  566. package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
  567. package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
  568. package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
  569. package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
  570. package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
  571. package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
  572. package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
  573. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
  574. package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
  575. package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
  576. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
  577. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
  578. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
  579. package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
  580. package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
  581. package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
  582. package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
  583. package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
  584. package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
  585. package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
  586. package/templates/database/migrations/20261025120000_trial_magnet/migration.sql +0 -28
  587. package/templates/database/migrations/20261026120000_trial_magnet_proof_line/migration.sql +0 -23
  588. package/templates/database/migrations/migration_lock.toml +0 -3
  589. package/templates/database/ops/.gitkeep +0 -0
  590. package/templates/database/ops/schema.prisma +0 -43
  591. package/templates/database/package.json +0 -89
  592. package/templates/database/schema.prisma +0 -71
  593. package/templates/database/scripts/db-generate-locked.sh +0 -80
  594. package/templates/database/scripts/person-backfill.sql +0 -132
  595. package/templates/database/tenancy.ts +0 -183
  596. package/templates/database/tsconfig.build.json +0 -16
  597. package/templates/database/tsconfig.flows.json +0 -15
  598. package/templates/database/tsconfig.json +0 -16
  599. package/templates/database/tsconfig.tenancy.json +0 -14
@@ -1,132 +0,0 @@
1
- -- #852 — the Person backfill (spec
2
- -- docs/specs/852-person-the-per-workspace-client-spec.md D2, D4).
3
- --
4
- -- Fills "people" from the rows the hub already holds and stamps
5
- -- leads.person_id and appointments.person_id, so the People list is not
6
- -- empty on the day it ships. Set-based and idempotent: every insert is
7
- -- ON CONFLICT DO NOTHING and every update is guarded by IS NULL, so running
8
- -- this text twice changes nothing the first run wrote.
9
- --
10
- -- THE SAME TEXT, byte for byte, is database/scripts/person-backfill.sql. The
11
- -- previous deployment keeps writing leads and appointments without a
12
- -- person_id between this migration and the cutover to the new code; run
13
- -- that script ONCE against the hub database after the cutover to stamp them.
14
- -- database/__tests__/person.db.test.ts asserts the two files are identical
15
- -- and that a second run changes no row.
16
- --
17
- -- Normalization — the SQL twin of apps/api/src/services/person.ts's
18
- -- normalizePersonEmail / isStorablePersonEmail:
19
- -- N(x) = lower(btrim(x, E' \t\n\r\f\x0B') COLLATE "C")
20
- -- (\x0B is vertical tab; an E-string has no \v escape — E'\v'
21
- -- is the letter v, which would strip the v of every .dev)
22
- -- VALID(e) = e ~ '^[!-?A-~]+@[!-?A-~]+$' AND length(e) <= 254
23
- -- NAME(x) = C0/C1 controls and bidi controls removed, trimmed, cut to
24
- -- 200 characters; empty → NULL
25
- -- A row whose email is not VALID makes no Person and keeps person_id NULL.
26
- --
27
- -- Sources, in order: leads (oldest first), then completed hub FlowCheckouts
28
- -- through their lead (the customer id, first writer wins), then appointments
29
- -- by attendee email. Subscriber is NOT a source; FlowSession, ProjectListing
30
- -- and DeliverableGrant reach a Person through their lead at read time.
31
- -- The join to "users" reads the auth namespace inside this one-off
32
- -- statement only; it adds no foreign key (ADR 0009 invariant 1).
33
- --
34
- -- Rollback: nothing to undo on its own — dropping 20261010120000_person's
35
- -- table and columns removes everything this wrote.
36
-
37
- -- 1. Leads, oldest first: one Person per (workspace, normalized email). The
38
- -- name is the oldest lead's payload.name when it is a JSON string.
39
- INSERT INTO "people" ("workspace_id", "email", "name", "created_at", "updated_at")
40
- SELECT DISTINCT ON (l."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"))
41
- l."workspace_id",
42
- lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"),
43
- CASE WHEN jsonb_typeof(l."payload" -> 'name') = 'string'
44
- THEN NULLIF(left(btrim(regexp_replace(l."payload" ->> 'name', '[\x01-\x1F\x7F-\x9F\u200E\u200F\u202A-\u202E\u2066-\u2069]', '', 'g')), 200), '')
45
- END,
46
- l."created_at",
47
- now()
48
- FROM "leads" l
49
- WHERE lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C") ~ '^[!-?A-~]+@[!-?A-~]+$'
50
- AND length(lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C")) <= 254
51
- ORDER BY l."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"), l."created_at" ASC, l."id" ASC
52
- ON CONFLICT ("workspace_id", "email") DO NOTHING;
53
-
54
- -- 2. Hub FlowCheckouts, through their lead (same workspace): the oldest
55
- -- completed checkout with a customer id writes it onto a Person that has
56
- -- none. First writer wins — oldest by completed_at, then created_at, then id.
57
- UPDATE "people" p
58
- SET "billing_provider" = 'stripe',
59
- "billing_customer_id" = c."stripe_customer_id",
60
- "updated_at" = now()
61
- FROM (
62
- SELECT DISTINCT ON (fc."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"))
63
- fc."workspace_id",
64
- lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C") AS "email",
65
- fc."stripe_customer_id"
66
- FROM "flow_checkouts" fc
67
- JOIN "leads" l ON l."id" = fc."lead_id" AND l."workspace_id" = fc."workspace_id"
68
- WHERE fc."status" = 'completed'
69
- AND fc."stripe_customer_id" IS NOT NULL
70
- AND fc."stripe_customer_id" <> ''
71
- AND length(fc."stripe_customer_id") <= 255
72
- ORDER BY fc."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"),
73
- fc."completed_at" ASC NULLS LAST, fc."created_at" ASC, fc."id" ASC
74
- ) c
75
- WHERE p."workspace_id" = c."workspace_id"
76
- AND p."email" = c."email"
77
- AND p."billing_customer_id" IS NULL;
78
-
79
- -- 3. Appointments, by attendee email: a Person a lead already made keeps its
80
- -- lead-derived name and created_at (ON CONFLICT DO NOTHING).
81
- INSERT INTO "people" ("workspace_id", "email", "name", "created_at", "updated_at")
82
- SELECT DISTINCT ON (a."workspace_id", lower(btrim(a."attendee_email", E' \t\n\r\f\x0B') COLLATE "C"))
83
- a."workspace_id",
84
- lower(btrim(a."attendee_email", E' \t\n\r\f\x0B') COLLATE "C"),
85
- NULLIF(left(btrim(regexp_replace(a."attendee_name", '[\x01-\x1F\x7F-\x9F\u200E\u200F\u202A-\u202E\u2066-\u2069]', '', 'g')), 200), ''),
86
- a."created_at",
87
- now()
88
- FROM "appointments" a
89
- WHERE lower(btrim(a."attendee_email", E' \t\n\r\f\x0B') COLLATE "C") ~ '^[!-?A-~]+@[!-?A-~]+$'
90
- AND length(lower(btrim(a."attendee_email", E' \t\n\r\f\x0B') COLLATE "C")) <= 254
91
- ORDER BY a."workspace_id", lower(btrim(a."attendee_email", E' \t\n\r\f\x0B') COLLATE "C"), a."created_at" ASC, a."id" ASC
92
- ON CONFLICT ("workspace_id", "email") DO NOTHING;
93
-
94
- -- 4. Stamps: every lead and appointment with a storable email points at its
95
- -- workspace's Person; a row already stamped is left alone.
96
- UPDATE "leads"
97
- SET "person_id" = p."id"
98
- FROM "people" p
99
- WHERE "leads"."person_id" IS NULL
100
- AND p."workspace_id" = "leads"."workspace_id"
101
- AND p."email" = lower(btrim("leads"."email", E' \t\n\r\f\x0B') COLLATE "C");
102
-
103
- UPDATE "appointments"
104
- SET "person_id" = p."id"
105
- FROM "people" p
106
- WHERE "appointments"."person_id" IS NULL
107
- AND p."workspace_id" = "appointments"."workspace_id"
108
- AND p."email" = lower(btrim("appointments"."attendee_email", E' \t\n\r\f\x0B') COLLATE "C");
109
-
110
- -- 5. user_id, verified only: the oldest promoted lead (by promoted_at, then
111
- -- created_at, then id) whose user is email-verified and whose verified
112
- -- address normalizes to the Person's. An unverified or differing user is
113
- -- never copied — the rule stampPersonUser applies to new rows.
114
- UPDATE "people" p
115
- SET "user_id" = c."user_id",
116
- "updated_at" = now()
117
- FROM (
118
- SELECT DISTINCT ON (l."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"))
119
- l."workspace_id",
120
- lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C") AS "email",
121
- l."promoted_user_id" AS "user_id"
122
- FROM "leads" l
123
- JOIN "users" u ON u."id" = l."promoted_user_id"
124
- WHERE l."promoted_user_id" IS NOT NULL
125
- AND u."email_verified" = true
126
- AND lower(btrim(u."email", E' \t\n\r\f\x0B') COLLATE "C") = lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C")
127
- ORDER BY l."workspace_id", lower(btrim(l."email", E' \t\n\r\f\x0B') COLLATE "C"),
128
- l."promoted_at" ASC NULLS LAST, l."created_at" ASC, l."id" ASC
129
- ) c
130
- WHERE p."workspace_id" = c."workspace_id"
131
- AND p."email" = c."email"
132
- AND p."user_id" IS NULL;
@@ -1,20 +0,0 @@
1
- -- #852 — an agent key may be granted people-read (spec
2
- -- docs/specs/852-person-the-per-workspace-client-spec.md D9).
3
- --
4
- -- Widens the agents_grants_allowed CHECK from the five #7864 permissions to
5
- -- six. The CHECK names the same six as @working-theory/validation's
6
- -- AGENT_GRANTABLE_PERMISSIONS; database/__tests__/agents.db.test.ts reads
7
- -- this file and fails if the two lists differ (SEC-7864-G).
8
- --
9
- -- PURELY ADDITIVE in effect: the new CHECK admits every row the old one
10
- -- admitted, so re-adding it cannot fail on existing data. No row changes.
11
- --
12
- -- Rollback: ALTER TABLE "agents" DROP CONSTRAINT "agents_grants_allowed";
13
- -- then re-add the five-id CHECK from 20261009120000_agent_grants. That
14
- -- re-add FAILS while any row holds people-read — remove those grants first.
15
-
16
- ALTER TABLE "agents" DROP CONSTRAINT "agents_grants_allowed";
17
-
18
- -- Only the six grantable permissions may be stored.
19
- ALTER TABLE "agents" ADD CONSTRAINT "agents_grants_allowed"
20
- CHECK ("grants" <@ ARRAY['content-edit','content-publish','assets-write','magnets-manage','meeting-types-manage','people-read']::TEXT[]);
@@ -1,158 +0,0 @@
1
- -- #7877 — the member area contract (spec
2
- -- docs/specs/7877-the-member-area-contract-a-spec.md D1, D2, D3).
3
- --
4
- -- pieces (inbox) — one deliverable for one client: a title, a stage
5
- -- drawn from the workspace's declared list, a
6
- -- needs-client flag. Written only through
7
- -- apps/api's tenantDb(tenant).memberArea.
8
- -- interactions (inbox) — one outbound message on the 'member' channel to
9
- -- one client, optionally carrying a workspace
10
- -- library asset. The original CRM spec's
11
- -- Interaction table cut to one channel and one
12
- -- direction; an inbound reply is a later second
13
- -- direction value on this table.
14
- -- workspace_piece_stages (config) — a workspace's declared piece stages,
15
- -- in order, one row per workspace. No row means the
16
- -- product default, which lives in apps/api only.
17
- -- people_id_workspace_id_key — a unique index over a pair the PK already
18
- -- makes unique: the target of the composite
19
- -- (person_id, workspace_id) foreign keys, so "a
20
- -- Person of the same workspace" is a database fact.
21
- --
22
- -- Both foreign keys stay inside the inbox namespace (ADR 0009 invariant 1).
23
- -- workspace_id, asset_id, created_by and updated_by name rows of other
24
- -- namespaces: plain columns with format CHECKs, no foreign key. Neither new
25
- -- inbox table carries an email.
26
- --
27
- -- PURELY ADDITIVE, DDL ONLY: three new tables and one unique index on
28
- -- "people". No existing row changes. The unique index builds under the
29
- -- file's transaction, holding a SHARE lock on "people" (writes wait, reads do
30
- -- not) for one scan of a table that is one row per client.
31
- --
32
- -- Rollout: deploy this migration BEFORE the API code that reads or writes
33
- -- these tables; code without them fails every member-area read and write.
34
- --
35
- -- Rollback: DROP TABLE "interactions"; DROP TABLE "pieces"; DROP TABLE
36
- -- "workspace_piece_stages"; DROP INDEX "people_id_workspace_id_key"; (the
37
- -- indexes, foreign keys and CHECKs go with them). Safe while nothing but
38
- -- #7877's own code reads them.
39
-
40
- -- CreateTable
41
- CREATE TABLE "workspace_piece_stages" (
42
- "id" TEXT NOT NULL DEFAULT ('pstages_'::text || (uuidv7())::text),
43
- "workspace_id" TEXT NOT NULL,
44
- "stages" TEXT[],
45
- "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
46
- "updated_at" TIMESTAMPTZ NOT NULL,
47
-
48
- CONSTRAINT "workspace_piece_stages_pkey" PRIMARY KEY ("id")
49
- );
50
-
51
- -- CreateTable
52
- CREATE TABLE "pieces" (
53
- "id" TEXT NOT NULL DEFAULT ('piece_'::text || (uuidv7())::text),
54
- "workspace_id" TEXT NOT NULL,
55
- "person_id" TEXT NOT NULL,
56
- "title" VARCHAR(200) NOT NULL,
57
- "stage" VARCHAR(40) NOT NULL,
58
- "needs_client" BOOLEAN NOT NULL DEFAULT false,
59
- "updated_by" TEXT NOT NULL,
60
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
61
- "updated_at" TIMESTAMP(3) NOT NULL,
62
-
63
- CONSTRAINT "pieces_pkey" PRIMARY KEY ("id")
64
- );
65
-
66
- -- CreateTable
67
- CREATE TABLE "interactions" (
68
- "id" TEXT NOT NULL DEFAULT ('intx_'::text || (uuidv7())::text),
69
- "workspace_id" TEXT NOT NULL,
70
- "person_id" TEXT NOT NULL,
71
- "channel" VARCHAR(16) NOT NULL,
72
- "direction" VARCHAR(16) NOT NULL,
73
- "subject" VARCHAR(200) NOT NULL,
74
- "body" TEXT NOT NULL,
75
- "asset_id" TEXT,
76
- "created_by" TEXT NOT NULL,
77
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
78
- "read_at" TIMESTAMP(3),
79
-
80
- CONSTRAINT "interactions_pkey" PRIMARY KEY ("id")
81
- );
82
-
83
- -- CreateIndex
84
- -- One stage list per workspace — the WorkspaceMeetings shape.
85
- CREATE UNIQUE INDEX "workspace_piece_stages_workspace_id_key" ON "workspace_piece_stages"("workspace_id");
86
-
87
- -- CreateIndex
88
- -- A client's pieces: workspace_id = $1 AND person_id = $2 ORDER BY created_at DESC.
89
- CREATE INDEX "pieces_workspace_id_person_id_created_at_idx" ON "pieces"("workspace_id", "person_id", "created_at");
90
-
91
- -- CreateIndex
92
- -- A client's messages, the same read shape as pieces.
93
- CREATE INDEX "interactions_workspace_id_person_id_created_at_idx" ON "interactions"("workspace_id", "person_id", "created_at");
94
-
95
- -- CreateIndex
96
- -- The public asset read's "is this asset attached to any message" count (D18).
97
- CREATE INDEX "interactions_asset_id_idx" ON "interactions"("asset_id");
98
-
99
- -- CreateIndex
100
- -- Redundant with the PK; the composite foreign keys below need it as their target.
101
- CREATE UNIQUE INDEX "people_id_workspace_id_key" ON "people"("id", "workspace_id");
102
-
103
- -- AddForeignKey
104
- -- A piece names a Person of ITS OWN workspace; deleting a Person with a piece is refused.
105
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_person_fk" FOREIGN KEY ("person_id", "workspace_id") REFERENCES "people"("id", "workspace_id") ON DELETE RESTRICT ON UPDATE CASCADE;
106
-
107
- -- AddForeignKey
108
- -- The same rule for a message.
109
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_person_fk" FOREIGN KEY ("person_id", "workspace_id") REFERENCES "people"("id", "workspace_id") ON DELETE RESTRICT ON UPDATE CASCADE;
110
-
111
- -- ADR-0031 rule 3 — pieces: piece_, interactions: intx_,
112
- -- workspace_piece_stages: pstages_ (registered in
113
- -- packages/ids/src/registry.ts; this migration's path is added to
114
- -- migration-sync.test.ts's PK_CHECK_MIGRATIONS). Each reference column
115
- -- carries the format CHECK of the entity it names, in the person-migration
116
- -- shape.
117
- ALTER TABLE "pieces" ALTER COLUMN "id" TYPE text COLLATE "C";
118
- ALTER TABLE "pieces" ALTER COLUMN "id" SET DEFAULT ('piece_'::text || (uuidv7())::text);
119
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_id_format" CHECK ("id" ~ '^piece_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
120
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_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}$');
121
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_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}$');
122
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_updated_by_format" CHECK ("updated_by" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
123
-
124
- ALTER TABLE "interactions" ALTER COLUMN "id" TYPE text COLLATE "C";
125
- ALTER TABLE "interactions" ALTER COLUMN "id" SET DEFAULT ('intx_'::text || (uuidv7())::text);
126
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_id_format" CHECK ("id" ~ '^intx_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
127
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_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}$');
128
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_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}$');
129
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_created_by_format" CHECK ("created_by" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
130
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_asset_id_format" CHECK ("asset_id" ~ '^asset_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
131
-
132
- ALTER TABLE "workspace_piece_stages" ALTER COLUMN "id" TYPE text COLLATE "C";
133
- ALTER TABLE "workspace_piece_stages" ALTER COLUMN "id" SET DEFAULT ('pstages_'::text || (uuidv7())::text);
134
- ALTER TABLE "workspace_piece_stages" ADD CONSTRAINT "workspace_piece_stages_id_format" CHECK ("id" ~ '^pstages_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
135
- ALTER TABLE "workspace_piece_stages" ADD CONSTRAINT "workspace_piece_stages_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}$');
136
-
137
- -- A piece's title is 1–200 characters once trimmed; a stage is a slug. Which
138
- -- slugs a workspace accepts is its declared list, checked at write time by
139
- -- the API — never an enum here or in packages/validation.
140
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_title_length"
141
- CHECK (char_length(btrim("title")) BETWEEN 1 AND 200);
142
- ALTER TABLE "pieces" ADD CONSTRAINT "pieces_stage_format"
143
- CHECK ("stage" ~ '^[a-z0-9][a-z0-9-]{0,39}$');
144
-
145
- -- One channel and one direction in this slice. An inbound reply widens
146
- -- interactions_direction_allowed in its own migration.
147
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_channel_allowed"
148
- CHECK ("channel" = 'member');
149
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_direction_allowed"
150
- CHECK ("direction" = 'outbound');
151
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_subject_length"
152
- CHECK (char_length(btrim("subject")) BETWEEN 1 AND 200);
153
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_body_length"
154
- CHECK (char_length(btrim("body")) BETWEEN 1 AND 10000);
155
-
156
- -- A declared list holds 1–20 stages (never NULL: no row is the default).
157
- ALTER TABLE "workspace_piece_stages" ADD CONSTRAINT "workspace_piece_stages_count"
158
- CHECK ("stages" IS NOT NULL AND cardinality("stages") BETWEEN 1 AND 20);
@@ -1,21 +0,0 @@
1
- -- #7878 — an agent key may be granted member-pieces-manage: a client's
2
- -- pieces, plan and outbound messages (#7877's operator writes).
3
- --
4
- -- Widens the agents_grants_allowed CHECK from the six #852 permissions to
5
- -- seven. The CHECK names the same seven as @working-theory/validation's
6
- -- AGENT_GRANTABLE_PERMISSIONS; database/__tests__/agents.db.test.ts reads
7
- -- this file and fails if the two lists differ (SEC-7864-G).
8
- --
9
- -- PURELY ADDITIVE in effect: the new CHECK admits every row the old one
10
- -- admitted, so re-adding it cannot fail on existing data. No row changes.
11
- --
12
- -- Rollback: ALTER TABLE "agents" DROP CONSTRAINT "agents_grants_allowed";
13
- -- then re-add the six-id CHECK from 20261010130000_agent_grants_people_read.
14
- -- That re-add FAILS while any row holds member-pieces-manage — remove those
15
- -- grants first.
16
-
17
- ALTER TABLE "agents" DROP CONSTRAINT "agents_grants_allowed";
18
-
19
- -- Only the seven grantable permissions may be stored.
20
- ALTER TABLE "agents" ADD CONSTRAINT "agents_grants_allowed"
21
- CHECK ("grants" <@ ARRAY['content-edit','content-publish','assets-write','magnets-manage','meeting-types-manage','people-read','member-pieces-manage']::TEXT[]);
@@ -1,192 +0,0 @@
1
- -- #8168 — the member area data model (spec
2
- -- docs/specs/8168-member-area-data-model-spec.md D1–D3, D5, D7–D9, D12).
3
- --
4
- -- piece_versions (inbox) — one delivery of a piece to its client:
5
- -- a private library file OR an https
6
- -- link, numbered from 1 per piece, with
7
- -- the client's review recorded on it.
8
- -- NO round count, limit or remaining
9
- -- column (#8140 disposition 3).
10
- -- pieces.approved_at — set with an `approved` review; freezes
11
- -- review (D5).
12
- -- pieces_id_person_id_workspace_id_key — a unique index over a triple the
13
- -- PK already makes unique: the target of
14
- -- piece_versions_piece_fk, so "a piece of
15
- -- THIS Person in THIS workspace" is one
16
- -- database fact (D1).
17
- -- interactions.kind / .payload — `message` · `quote` · `review`, and the
18
- -- stored payload of a quote or review;
19
- -- `inbound` joins `outbound` (D3). An
20
- -- outbound row stays a payload-free
21
- -- `message` — #7877's rows, unchanged.
22
- -- flow_definitions.customers_enabled — whether a signed-in client may submit
23
- -- the magnet from the member area (D7).
24
- -- the `request-quote` magnet — one draft `contact` magnet with
25
- -- customers_enabled = true, backfilled
26
- -- into EVERY existing workspace (D8).
27
- --
28
- -- The only new foreign key stays inside the inbox namespace (ADR 0009
29
- -- invariant 1). asset_id and delivered_by name rows of other namespaces:
30
- -- plain columns with format CHECKs, no foreign key. The backfill reads
31
- -- "workspaces" (auth namespace) in SQL only — no relation.
32
- --
33
- -- ADDITIVE: every ADD COLUMN is nullable or carries a constant default, so no
34
- -- existing row fails a new CHECK — every existing interaction is an outbound
35
- -- `message` with no payload, which the replaced and added CHECKs admit
36
- -- (interactions_body_length keeps its 1–10000 rule for a `message`). The
37
- -- unique index on "pieces" builds under the file's transaction, holding a
38
- -- SHARE lock on "pieces" for one scan of a table that is a few rows per
39
- -- client. The backfill inserts one row per workspace and NEVER overwrites a
40
- -- workspace's existing (site_id, slug) row (ON CONFLICT DO NOTHING) —
41
- -- re-running the block adds nothing.
42
- --
43
- -- Rollout: deploy this migration BEFORE any code that writes piece_versions,
44
- -- pieces.approved_at, an inbound interaction, interactions.kind/payload or
45
- -- flow_definitions.customers_enabled. Code written before it never names the
46
- -- new columns, so it keeps working against the migrated database.
47
- --
48
- -- Rollback (safe while nothing but #8168's siblings use the new surface):
49
- -- DELETE FROM "flow_definitions" WHERE "slug" = 'request-quote' AND "status" = 'draft' AND "customers_enabled";
50
- -- ALTER TABLE "flow_definitions" DROP COLUMN "customers_enabled";
51
- -- DELETE FROM "interactions" WHERE "direction" = 'inbound';
52
- -- ALTER TABLE "interactions" DROP CONSTRAINT "interactions_kind_allowed",
53
- -- DROP CONSTRAINT "interactions_outbound_shape", DROP CONSTRAINT "interactions_payload_by_kind",
54
- -- DROP CONSTRAINT "interactions_payload_size", DROP CONSTRAINT "interactions_body_length",
55
- -- DROP CONSTRAINT "interactions_direction_allowed";
56
- -- ALTER TABLE "interactions" DROP COLUMN "kind", DROP COLUMN "payload";
57
- -- then re-add #7877's interactions_direction_allowed (direction = 'outbound')
58
- -- and interactions_body_length (1–10000 once trimmed) from
59
- -- 20261011120000_member_area;
60
- -- DROP TABLE "piece_versions"; DROP INDEX "pieces_id_person_id_workspace_id_key";
61
- -- ALTER TABLE "pieces" DROP COLUMN "approved_at";
62
- -- The first DELETE also removes an operator's own edits to a still-draft
63
- -- seeded magnet; check for those before rolling back.
64
-
65
- -- AlterTable
66
- ALTER TABLE "flow_definitions" ADD COLUMN "customers_enabled" BOOLEAN NOT NULL DEFAULT false;
67
-
68
- -- AlterTable
69
- -- Existing rows and #7877's writer (which names no kind) stay `message`.
70
- ALTER TABLE "interactions" ADD COLUMN "kind" VARCHAR(16) NOT NULL DEFAULT 'message',
71
- ADD COLUMN "payload" JSONB;
72
-
73
- -- AlterTable
74
- ALTER TABLE "pieces" ADD COLUMN "approved_at" TIMESTAMP(3);
75
-
76
- -- CreateTable
77
- CREATE TABLE "piece_versions" (
78
- "id" TEXT NOT NULL DEFAULT ('pver_'::text || (uuidv7())::text),
79
- "workspace_id" TEXT NOT NULL,
80
- "person_id" TEXT NOT NULL,
81
- "piece_id" TEXT NOT NULL,
82
- "version" INTEGER NOT NULL,
83
- "asset_id" TEXT,
84
- "link" VARCHAR(2048),
85
- "note" TEXT,
86
- "delivered_by" TEXT NOT NULL,
87
- "delivered_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
88
- "review" VARCHAR(24),
89
- "review_comment" TEXT,
90
- "reviewed_at" TIMESTAMP(3),
91
-
92
- CONSTRAINT "piece_versions_pkey" PRIMARY KEY ("id")
93
- );
94
-
95
- -- CreateIndex
96
- -- A client's artifacts: workspace_id = $1 AND person_id = $2 ORDER BY delivered_at DESC.
97
- CREATE INDEX "piece_versions_workspace_id_person_id_delivered_at_idx" ON "piece_versions"("workspace_id", "person_id", "delivered_at");
98
-
99
- -- CreateIndex
100
- -- The public asset read's "is this asset a version file" check (AC-MAA-21).
101
- CREATE INDEX "piece_versions_asset_id_idx" ON "piece_versions"("asset_id");
102
-
103
- -- CreateIndex
104
- -- A version number is a fact per piece; the writer numbers, this is the backstop.
105
- CREATE UNIQUE INDEX "piece_versions_piece_id_version_key" ON "piece_versions"("piece_id", "version");
106
-
107
- -- CreateIndex
108
- -- Redundant with the PK; piece_versions_piece_fk needs it as its target.
109
- CREATE UNIQUE INDEX "pieces_id_person_id_workspace_id_key" ON "pieces"("id", "person_id", "workspace_id");
110
-
111
- -- AddForeignKey
112
- -- A version names a piece of THIS Person in THIS workspace (the piece's own
113
- -- FK already ties it to a Person of its workspace); deleting a piece with a
114
- -- version is refused.
115
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_piece_fk" FOREIGN KEY ("piece_id", "person_id", "workspace_id") REFERENCES "pieces"("id", "person_id", "workspace_id") ON DELETE RESTRICT ON UPDATE CASCADE;
116
-
117
- -- ADR-0031 rule 3 — piece_versions: pver_ (registered in
118
- -- packages/ids/src/registry.ts; this migration's path is added to
119
- -- migration-sync.test.ts's PK_CHECK_MIGRATIONS). Each reference column
120
- -- carries the format CHECK of the entity it names, in the #7877 shape.
121
- ALTER TABLE "piece_versions" ALTER COLUMN "id" TYPE text COLLATE "C";
122
- ALTER TABLE "piece_versions" ALTER COLUMN "id" SET DEFAULT ('pver_'::text || (uuidv7())::text);
123
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_id_format" CHECK ("id" ~ '^pver_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
124
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_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}$');
125
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_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}$');
126
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_piece_id_format" CHECK ("piece_id" ~ '^piece_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
127
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_asset_id_format" CHECK ("asset_id" ~ '^asset_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
128
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_delivered_by_format" CHECK ("delivered_by" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
129
-
130
- -- D2 — a version's shape is held here, not by the writer alone.
131
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_version_positive"
132
- CHECK ("version" >= 1);
133
- -- A delivery is a file or a link: exactly one.
134
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_one_target"
135
- CHECK (("asset_id" IS NULL) <> ("link" IS NULL));
136
- -- An https scheme, a host with no userinfo, no whitespace anywhere — the
137
- -- database floor under packages/validation's isHttpsLink (SEC-8168-5).
138
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_link_https"
139
- CHECK ("link" IS NULL OR ("link" ~ '^https://[^[:space:]/?#@]+([/?#][^[:space:]]*)?$' AND char_length("link") <= 2048));
140
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_note_length"
141
- CHECK ("note" IS NULL OR char_length(btrim("note")) BETWEEN 1 AND 2000);
142
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_review_allowed"
143
- CHECK ("review" IS NULL OR "review" IN ('approved', 'changes-requested'));
144
- -- A review and its timestamp are set together or not at all.
145
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_review_stamped"
146
- CHECK (("review" IS NULL) = ("reviewed_at" IS NULL));
147
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_comment_needs_review"
148
- CHECK ("review_comment" IS NULL OR "review" IS NOT NULL);
149
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_changes_need_comment"
150
- CHECK ("review" IS DISTINCT FROM 'changes-requested' OR char_length(btrim(coalesce("review_comment", ''))) >= 1);
151
- ALTER TABLE "piece_versions" ADD CONSTRAINT "piece_versions_comment_length"
152
- CHECK ("review_comment" IS NULL OR char_length("review_comment") <= 5000);
153
-
154
- -- D3 — the second direction and the kinds. Replaced IN PLACE under the same
155
- -- names, so #7877's tests keep naming the same constraints.
156
- ALTER TABLE "interactions" DROP CONSTRAINT "interactions_direction_allowed";
157
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_direction_allowed"
158
- CHECK ("direction" IN ('outbound', 'inbound'));
159
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_kind_allowed"
160
- CHECK ("kind" IN ('message', 'quote', 'review'));
161
- -- An outbound row is a payload-free `message` — #7877's rows, unchanged.
162
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_outbound_shape"
163
- CHECK ("direction" <> 'outbound' OR ("kind" = 'message' AND "payload" IS NULL));
164
- -- A quote or a review always carries its stored payload.
165
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_payload_by_kind"
166
- CHECK ("kind" = 'message' OR "payload" IS NOT NULL);
167
- -- 64 items of a 200-character label and a 2000-character value fit with room (SEC-8168-4).
168
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_payload_size"
169
- CHECK ("payload" IS NULL OR octet_length("payload"::text) <= 262144);
170
- -- A message body stays 1–10000 characters once trimmed; a quote or review
171
- -- body may be empty; no body exceeds 10000.
172
- ALTER TABLE "interactions" DROP CONSTRAINT "interactions_body_length";
173
- ALTER TABLE "interactions" ADD CONSTRAINT "interactions_body_length"
174
- CHECK (
175
- char_length("body") <= 10000
176
- AND ("kind" <> 'message' OR char_length(btrim("body")) BETWEEN 1 AND 10000)
177
- );
178
-
179
- -- D8/D9 — the request-quote magnet in every existing workspace. The config
180
- -- literal below is test-held to `requestQuoteFlowConfig`
181
- -- (packages/validation/src/schemas/flow.ts) by
182
- -- database/__tests__/member-contract-migration.test.ts, and the block is
183
- -- re-executed verbatim by member-contract.db.test.ts to prove it idempotent.
184
- -- Do not edit one without the other.
185
- -- BEGIN request-quote backfill
186
- INSERT INTO "flow_definitions" ("site_id", "workspace_id", "slug", "config", "kind", "title", "status", "customers_enabled", "updated_at")
187
- SELECT w."id", w."id", 'request-quote',
188
- '{"slug":"request-quote","defaultLocale":"en","steps":[{"key":"request","type":"field","copy":{"title":{"en":"Request a quote"}},"fields":[{"name":"need","inputType":"textarea","required":true,"copy":{"label":{"en":"What do you need?"}}},{"name":"timing","inputType":"text","copy":{"label":{"en":"When do you need it?"}}},{"name":"budget","inputType":"text","copy":{"label":{"en":"Budget range"},"help":{"en":"A rough range is fine."}}},{"name":"link","inputType":"url","copy":{"label":{"en":"Link"},"help":{"en":"A brief, a document or an example. Must start with https://."}}}]}]}'::jsonb,
189
- 'contact', 'Request a quote', 'draft', true, CURRENT_TIMESTAMP
190
- FROM "workspaces" w
191
- ON CONFLICT ("site_id", "slug") DO NOTHING;
192
- -- END request-quote backfill
@@ -1,20 +0,0 @@
1
- -- #8185 — record, at the moment the hub writes it, that a lead is a spoke's
2
- -- live paid checkout (spec docs/specs/8185-spoke-checkout-purchases-spec.md
3
- -- D1, D6, D10).
4
- --
5
- -- leads.spoke_checkout — set true by apps/api/src/services/lead-routing.ts
6
- -- only for a spoke-keyed, unrelayed submit passing
7
- -- the #7877 checkout plan rule's predicate. Written
8
- -- at creation, never updated. NOT NULL with a
9
- -- constant default, so existing rows read false and
10
- -- nothing is rewritten; they are deliberately NOT
11
- -- backfilled (D6: no stored fact proves an older
12
- -- lead's provenance).
13
- --
14
- -- Rollout order (D10): apply this migration to a deployment's database BEFORE
15
- -- deploying the API that writes the column. The old API is unaffected by it;
16
- -- the new API's marked create fails without it.
17
- --
18
- -- Rollback: ALTER TABLE "leads" DROP COLUMN "spoke_checkout";
19
-
20
- ALTER TABLE "leads" ADD COLUMN "spoke_checkout" BOOLEAN NOT NULL DEFAULT false;