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,48 +0,0 @@
1
- /**
2
- * NOT marked `oss: false` (D-48/#5366 escalation, reversing this pass's
3
- * own D6 read — see `./me.ts`'s header comment): `sendValidated` is imported
4
- * by `./me.ts`, `./patch-draft.ts` and `./public.ts`, each of which must ship
5
- * unconditionally because `./index.ts`'s multi-tenant literal `import()`
6
- * forces it. A file imported by an always-shipping file cannot itself be
7
- * excluded — this is the ORIGINAL multi-tenant/#5088 card's own conclusion
8
- * about this exact file (module-architecture.ts lines 569-571), which D6's
9
- * "every other consumer is Pro Plus" premise doesn't override: two of its
10
- * three non-tenant consumers are these three always-shipping files, not a
11
- * gated one.
12
- *
13
- * Response-schema validation for the project-listings routes (#4998),
14
- * mirroring `waitlist-experiments/respond.ts`'s discipline: response schemas
15
- * are contract-only unless re-parsed against their own `.strict()` schema
16
- * before the value leaves the process. A shape drift here is a genuine
17
- * internal error (the service layer already guards every field), never a
18
- * client-facing 4xx.
19
- */
20
- import { logger } from "@working-theory/observability";
21
- import type { FastifyReply } from "fastify";
22
- import type { z } from "zod";
23
-
24
- /**
25
- * Parse `data` against `schema`; on success send the ORIGINAL `data` object
26
- * (not the parsed clone) at `200`, matching the waitlist-experiments
27
- * envelope. On failure, log the zod issues (never the raw `data`, which may
28
- * carry founder PII) and reply `500`.
29
- */
30
- export function sendValidated<T>(
31
- reply: FastifyReply,
32
- schema: z.ZodType<T>,
33
- data: T,
34
- routeName: string,
35
- ): FastifyReply {
36
- const parsed = schema.safeParse(data);
37
- if (!parsed.success) {
38
- logger.error(
39
- { route: routeName, issues: parsed.error.issues },
40
- "[project-listings] response failed its own contract schema",
41
- );
42
- return reply.status(500).send({
43
- ok: false,
44
- error: { code: "internal_error", message: "Response failed contract validation" },
45
- });
46
- }
47
- return reply.status(200).send({ ok: true, data });
48
- }
@@ -1,27 +0,0 @@
1
- /**
2
- * NOT marked `oss: false` — see `./me.ts`'s header comment (D-48/#5366
3
- * escalation): imported only by `./patch-draft.ts` and `./submit.ts`, both
4
- * of which ship unconditionally (`./index.ts`'s multi-tenant literal
5
- * `import()`), so this file cannot be excluded either.
6
- *
7
- * The resume token's transport (#5036 D1).
8
- *
9
- * `start` hands the client an opaque token; `patch` and `submit` present it
10
- * back. It travels in the `Authorization: Bearer` header rather than in the
11
- * body or the query string for two reasons that matter on an anonymous
12
- * surface: a query parameter lands in access logs, proxy logs and
13
- * `Referer` headers, and a body field cannot be sent on a future GET. The
14
- * header is where a credential belongs, and these routes sit in `leadsScope`
15
- * where no auth preHandler runs, so nothing else in the stack reads it.
16
- */
17
- import type { FastifyRequest } from "fastify";
18
-
19
- const BEARER = /^Bearer (.+)$/;
20
-
21
- /** The presented token, or null when the header is absent or malformed. */
22
- export function resumeTokenFrom(request: FastifyRequest): string | null {
23
- const header = request.headers.authorization;
24
- if (typeof header !== "string") return null;
25
- const match = BEARER.exec(header.trim());
26
- return match ? match[1]! : null;
27
- }
@@ -1,140 +0,0 @@
1
- /**
2
- * NOT marked `oss: false` — see `./me.ts`'s header comment (D-48/#5366
3
- * escalation: `./index.ts` is a mixed barrel multi-tenant's `server.ts`
4
- * reaches by a literal, always-resolved `import()`; this file ships
5
- * unconditionally, registration stays gated).
6
- *
7
- * POST /v1/project-listings
8
- *
9
- * `start` — step one of the application (#5036 D1). Anonymous, registered in
10
- * the same rate-limited `leadsScope` as `/v1/leads/*`. Validates with
11
- * `projectListingStartSchema` (the founder's name, email and consent, and
12
- * optionally a requested window) and writes the `ProjectListing` row at
13
- * `status: "draft"`. Returns 201 `{ ok: true, data: { id, resumeToken } }`.
14
- *
15
- * NO Lead is written here. The founder's contact details are already captured
16
- * on the listing row itself at step one, so a Lead would add no capture — and
17
- * `routeLead` sends an operator notification, which on an anonymous route
18
- * means a stranger could mail the operator by opening a draft they never
19
- * finish (PR #5042 security review, finding 4). `submit` writes the Lead.
20
- *
21
- * This route REPLACES the single anonymous create. The application became a
22
- * ten-step form that saves on every advance, so the create had to split into
23
- * start / patch / submit; validation moved with it, from write-time to
24
- * submit-time. Nothing here asserts the application is complete, because at
25
- * step one it never is.
26
- *
27
- * The response body is the ONLY place the resume token is ever readable: the
28
- * server stores a digest of it. A client that loses it has lost the draft.
29
- *
30
- * NO `siteId` (#5048 D2). The payload names the site by its PUBLIC KEY and
31
- * this route resolves the id through `siteIdForPublicKey` — a body-supplied
32
- * tenant identifier is exactly what the consuming site's proxy route existed
33
- * to prevent, and the resolution moving here is what lets that route go away.
34
- * An unknown key is a 400; it never falls back to the deployment's own site.
35
- *
36
- * NO `slug`, and no site config values (#5033 D1/D2): the slug is derived from
37
- * `name` at submit, and the site's window bounds are read server-side. The
38
- * applicant may REQUEST a window; the server clamps it rather than rejecting
39
- * the application, because a founder who could post their own bound could post
40
- * an unbounded one.
41
- *
42
- * PII-safe logging (mirrors `routes/leads/index.ts`): routing metadata only —
43
- * never founderEmail, founderName, or the resume token.
44
- *
45
- * SENDS THE RESUME EMAIL (#5406), fire-and-forget, after the row exists. The
46
- * 201 below is never delayed or failed by it: `sendListingResumeLink` returns
47
- * `void` and swallows everything, exactly as `sendListingDecisionEmail`'s
48
- * `fileIssueOnApprove` does on the approve path. The email is OPT-IN — a site
49
- * whose `SiteListingConfig` carries no `resumeEmail.fromAddress` gets none, so
50
- * a site sending its own today does not start sending two — and the request
51
- * and response shapes of this hard-floor route are unchanged.
52
- *
53
- * THE EMAIL IS ALSO THE ONLY CARRIER OF THE VERIFICATION NONCE (#5407).
54
- * `startProjectListingDraft` mints it, stores only its digest, and returns it
55
- * as a SIBLING of the result — never inside the value parsed below, because
56
- * `projectListingStartResponseSchema` is this route's hard-floor contract and
57
- * carries `id` and `resumeToken` and nothing else. The nonce reaches
58
- * `sendListingResumeLink` from a local variable and goes nowhere else: not
59
- * into the response, not into the log line above it. That is precisely what
60
- * makes `email_verified_at` mean something the resume token alone could not
61
- * prove — see `verifyProjectListingDraftEmail`.
62
- *
63
- * The response uses the API's own `{ ok, data }` / `{ ok, error }` envelope
64
- * (`apps/api/CLAUDE.md`) on BOTH the success and the failure path — the
65
- * anonymous create it replaces answered bare on success and enveloped on
66
- * failure, so a client branching on `body.ok` read a success as a failure.
67
- */
68
- import {
69
- projectListingStartResponseSchema,
70
- projectListingStartSchema,
71
- } from "@working-theory/validation";
72
- import type { FastifyPluginAsync } from "fastify";
73
-
74
- import { siteIdForPublicKey } from "../../services/listing-config.js";
75
- import { sendListingResumeLink } from "../../services/project-listing-resume-email.js";
76
- import { startProjectListingDraft } from "../../services/project-listings.js";
77
-
78
- export const startProjectListingRoute: FastifyPluginAsync = async (fastify) => {
79
- fastify.post("/v1/project-listings", async (request, reply) => {
80
- const parsed = projectListingStartSchema.safeParse(request.body);
81
- if (!parsed.success) {
82
- return reply.status(400).send({
83
- ok: false,
84
- error: {
85
- code: "invalid_input",
86
- message: parsed.error.issues[0]?.message ?? "invalid input",
87
- },
88
- });
89
- }
90
-
91
- // #5048 D2 — the site is resolved SERVER-SIDE from the payload's public
92
- // key. The body never carries a `siteId`, and `projectListingStartSchema`
93
- // is `.strict()`, so a body that still does is the 400 above naming the
94
- // unrecognised key rather than a silently-honoured tenant override. This
95
- // is the one property the consuming site's proxy route existed to
96
- // guarantee, and resolving it here is what lets that route go away.
97
- //
98
- // An unknown key is a 400 and never falls back to the deployment's own
99
- // site: a typo would otherwise file one site's applications against
100
- // another with nothing to notice it.
101
- const siteId = await siteIdForPublicKey(parsed.data.siteKey);
102
- if (siteId === null) {
103
- return reply.status(400).send({
104
- ok: false,
105
- error: { code: "unknown_site_key", message: "Unknown site key" },
106
- });
107
- }
108
-
109
- const result = await startProjectListingDraft(siteId, parsed.data);
110
- // #5275 — a `consents` map declining a REQUIRED purpose contradicts the
111
- // body's own `consent: true`; no row was created.
112
- if (!result.ok) {
113
- // #6203 — `tenant_unresolved` is a server-side tenancy
114
- // misconfiguration (the resolved `siteId` names no workspace this
115
- // database holds), not a client input problem — 503, never 400.
116
- const status = result.error.kind === "tenant_unresolved" ? 503 : 400;
117
- return reply.status(status).send({
118
- ok: false,
119
- error: { code: result.error.kind, message: result.error.message },
120
- });
121
- }
122
-
123
- request.log.info(
124
- { siteId, listingId: result.id, ip: request.ip },
125
- "project listing draft started",
126
- );
127
-
128
- // #5406 — the founder's way back to this draft. NOT awaited: the 201 must
129
- // not wait on Resend, and must not fail if Resend does. Both credentials
130
- // are handed over here and neither is ever logged — they ride the link
131
- // inside the email, and the #5407 nonce rides NOTHING ELSE anywhere.
132
- sendListingResumeLink(result.id, result.resumeToken, result.verifyNonce);
133
-
134
- const body = projectListingStartResponseSchema.parse({
135
- id: result.id,
136
- resumeToken: result.resumeToken,
137
- });
138
- return reply.status(201).send({ ok: true, data: body });
139
- });
140
- };
@@ -1,130 +0,0 @@
1
- /**
2
- * NOT marked `oss: false` — see `./me.ts`'s header comment (D-48/#5366
3
- * escalation: `./index.ts` is a mixed barrel multi-tenant's `server.ts`
4
- * reaches by a literal, always-resolved `import()`; this file ships
5
- * unconditionally, registration stays gated).
6
- *
7
- * POST /v1/project-listings/drafts/:id/submit
8
- *
9
- * `submit` — the moment an application stops being a draft (#5036 D1).
10
- * Anonymous, token-gated, registered in the rate-limited `leadsScope`.
11
- *
12
- * It carries NO body. Everything it validates is already on the row, put
13
- * there by ten steps of `patch`, and the server assembles and validates it
14
- * against `projectListingSubmitSchema`. An incomplete draft comes back `422`
15
- * with the offending fields NAMED, so the form can send the founder back to
16
- * the step that owns each one rather than saying "something is missing".
17
- *
18
- * Three server-side rules bind here and only here: completeness; the
19
- * concurrent-listing limit (`409 listing_limit_reached` — at most two
20
- * non-terminal listings per founder, drafts included, #5036 D7); and the
21
- * slug, derived from `name` at last (#5033 D2) and returned in the response,
22
- * which is the only place a caller learns it.
23
- *
24
- * The Lead write also happens here rather than at step one, via `routeLead` —
25
- * so an anonymous stranger cannot cause an operator notification by opening a
26
- * draft they never finish (PR #5042 security review, finding 4). The Slack
27
- * notification fires AFTER the transition, never before, and never fails a
28
- * submit that already succeeded (`postListingApplication` never throws). Both
29
- * moved here from the old create route because this — not step one — is the
30
- * moment an operator has an application worth looking at.
31
- *
32
- * Every response uses the API's own `{ ok, data }` / `{ ok, error }` envelope
33
- * (`apps/api/CLAUDE.md`), success included.
34
- */
35
- import { zProjectListingId } from "@working-theory/ids";
36
- import { projectListingSubmitResponseSchema } from "@working-theory/validation";
37
- import type { FastifyPluginAsync } from "fastify";
38
- import { z } from "zod";
39
-
40
- import { submitProjectListingDraft } from "../../services/project-listings.js";
41
- import { postListingApplication } from "../../services/slack-notify.js";
42
-
43
- import { resumeTokenFrom } from "./resume-token.js";
44
-
45
- const paramsSchema = z.object({ id: zProjectListingId });
46
-
47
- export const submitProjectListingRoute: FastifyPluginAsync = async (fastify) => {
48
- fastify.post("/v1/project-listings/drafts/:id/submit", async (request, reply) => {
49
- const parsedParams = paramsSchema.safeParse(request.params);
50
- if (!parsedParams.success) {
51
- return reply.status(400).send({
52
- ok: false,
53
- error: { code: "validation_failed", message: "Invalid project listing id" },
54
- });
55
- }
56
-
57
- const resumeToken = resumeTokenFrom(request);
58
- if (resumeToken === null) {
59
- return reply.status(401).send({
60
- ok: false,
61
- error: { code: "unauthorized", message: "A resume token is required" },
62
- });
63
- }
64
-
65
- const sourceMeta = {
66
- ip: request.ip,
67
- userAgent: request.headers["user-agent"],
68
- receivedAt: new Date().toISOString(),
69
- };
70
-
71
- const result = await submitProjectListingDraft(
72
- parsedParams.data.id,
73
- resumeToken,
74
- sourceMeta,
75
- );
76
-
77
- if (!result.ok) {
78
- if (result.error.kind === "not_found") {
79
- return reply.status(404).send({
80
- ok: false,
81
- error: { code: "not_found", message: "Draft not found" },
82
- });
83
- }
84
- if (result.error.kind === "incomplete") {
85
- return reply.status(422).send({
86
- ok: false,
87
- error: {
88
- code: "incomplete_application",
89
- message: result.error.message,
90
- missingFields: result.error.missingFields,
91
- },
92
- });
93
- }
94
- if (result.error.kind === "listing_limit_reached") {
95
- return reply.status(409).send({
96
- ok: false,
97
- error: { code: "listing_limit_reached", message: result.error.message },
98
- });
99
- }
100
- return reply.status(409).send({
101
- ok: false,
102
- error: { code: "slug_taken", message: result.error.message },
103
- });
104
- }
105
-
106
- request.log.info(
107
- { siteId: result.listing.siteId, slug: result.slug, ip: request.ip },
108
- "project listing applied",
109
- );
110
-
111
- // Awaited (not fire-and-forget) so it can't be killed mid-flight by a
112
- // serverless runtime tearing down after the response.
113
- await postListingApplication({
114
- id: result.listing.id,
115
- name: result.listing.name,
116
- oneLiner: result.listing.oneLiner,
117
- problem: result.listing.problem,
118
- url: result.listing.url,
119
- product: result.listing.product,
120
- founderName: result.listing.founderName,
121
- founderCompany: result.listing.founderCompany,
122
- // #7522 D5 — the actions block names the listing's workspace; `siteId`
123
- // IS the workspace id (the `project_listings_workspace_site_agree` CHECK).
124
- workspaceId: result.listing.siteId,
125
- });
126
-
127
- const body = projectListingSubmitResponseSchema.parse({ id: result.id, slug: result.slug });
128
- return reply.status(200).send({ ok: true, data: body });
129
- });
130
- };
@@ -1,150 +0,0 @@
1
- /**
2
- * POST /v1/project-listings/drafts/:id/verify-email
3
- *
4
- * Records that the founder proved control of `founderEmail`, by opening the
5
- * resume link emailed at step one (#5407). Anonymous, credential-gated,
6
- * registered in the same rate-limited `leadsScope` as the other three
7
- * anonymous listing routes.
8
- *
9
- * WHY THE ROUTE EXISTS. The resume email (#5406) tells the founder to "verify
10
- * your email and continue", and until this route nothing made that sentence
11
- * true: `ListingApplicationFlow` rehydrated from `?draft=&token=` entirely in
12
- * the browser and touched the server only on the NEXT advance — so a founder
13
- * who opened the link and closed the tab left no record, and the operator had
14
- * no way to tell a proved address from a typed one at review (samhenry spec
15
- * 316 D6b).
16
- *
17
- * WHAT IT PROVES. That somebody who can read mail at `founderEmail` opened
18
- * this link — evidence about the ADDRESS, not about who is driving the draft
19
- * (`verifyProjectListingDraftEmail` carries the full note). It takes
20
- * TWO credentials and only the second carries that: the `Authorization:
21
- * Bearer` resume token says "you opened this draft" (it is in `start`'s own
22
- * 201 body, so anyone who posted the form has it), and the `verifyNonce` in
23
- * the body says "you read the email" — it is minted at `start`, digested onto
24
- * the row, and handed to nothing but the resume-email builder, reaching the
25
- * outside world only as the `?verify=` parameter inside the message. Keying
26
- * this route on the resume token ALONE was the first design and was
27
- * forgeable in two HTTP calls; `verifyProjectListingDraftEmail` carries the
28
- * full note.
29
- *
30
- * It still says nothing about WHO the founder is. `ownerUserId` (#5295) is
31
- * the column that carries an identity claim.
32
- *
33
- * A SITE THAT SENDS NO RESUME EMAIL CAN NEVER VERIFY, and that is correct:
34
- * the nonce is minted on every draft but delivered only by the email, so
35
- * where `SiteListingConfig` carries no `resumeEmail` the column stays null
36
- * forever — nobody has read anything at that address.
37
- *
38
- * IDEMPOTENT, AND WRITE-ONCE. The service stamps by compare-and-swap on
39
- * `emailVerifiedAt: null`, so a founder who opens the link five times is
40
- * stamped once and every call answers with that FIRST stamp.
41
- *
42
- * THE ERROR SURFACE IS `patch`'s AND `submit`'s, deliberately unchanged: a
43
- * malformed id or a body that is not `{ verifyNonce }` is `400
44
- * validation_failed`, a missing or malformed `Authorization: Bearer` is `401
45
- * unauthorized`, and a WRONG token, a WRONG nonce, a credential bound to
46
- * another listing, an unknown id and an already-submitted row are all one
47
- * `404 not_found`. The 400s describe the REQUEST's shape and reveal nothing
48
- * about any row; everything that depends on a row is the single 404. An
49
- * anonymous surface must not distinguish "exists but not yours" from "does
50
- * not exist", and this route least of all — a distinguishable answer would
51
- * make it both an oracle for which drafts exist and a guessing channel for
52
- * the nonce.
53
- *
54
- * THE NONCE TRAVELS IN THE BODY, not the query string, for the reason
55
- * `resume-token.ts` gives about the resume token: a query parameter lands in
56
- * access logs, proxy logs and `Referer` headers. The claim is about THIS hop
57
- * only, and it is worth being exact about that — the nonce's DELIVERY hop is
58
- * itself a query parameter on the consuming site's URL, so it lands in that
59
- * site's own access logs exactly as the resume token does. What the body
60
- * placement buys is that the API's logs and any proxy between the browser and
61
- * this server never see it. The resume token keeps its `Authorization:
62
- * Bearer` header. Neither credential is ever logged and neither is ever
63
- * returned.
64
- */
65
- import { zProjectListingId } from "@working-theory/ids";
66
- import { projectListingVerifyEmailResponseSchema } from "@working-theory/validation";
67
- import type { FastifyPluginAsync } from "fastify";
68
- import { z } from "zod";
69
-
70
- import { verifyProjectListingDraftEmail } from "../../services/project-listings.js";
71
-
72
- import { sendValidated } from "./respond.js";
73
- import { resumeTokenFrom } from "./resume-token.js";
74
-
75
- const paramsSchema = z.object({ id: zProjectListingId });
76
-
77
- /**
78
- * The nonce, as the emailed link carried it. Bounded so an oversized body is
79
- * refused before any digest is computed; the value is 256 bits of CSPRNG
80
- * output in base64url, which is 43 characters.
81
- */
82
- const bodySchema = z.object({ verifyNonce: z.string().min(1).max(256) }).strict();
83
-
84
- export const verifyProjectListingDraftEmailRoute: FastifyPluginAsync = async (
85
- fastify,
86
- ) => {
87
- fastify.post(
88
- "/v1/project-listings/drafts/:id/verify-email",
89
- async (request, reply) => {
90
- const parsedParams = paramsSchema.safeParse(request.params);
91
- if (!parsedParams.success) {
92
- return reply.status(400).send({
93
- ok: false,
94
- error: { code: "validation_failed", message: "Invalid project listing id" },
95
- });
96
- }
97
-
98
- const resumeToken = resumeTokenFrom(request);
99
- if (resumeToken === null) {
100
- return reply.status(401).send({
101
- ok: false,
102
- error: { code: "unauthorized", message: "A resume token is required" },
103
- });
104
- }
105
-
106
- // The message names the FIELD, never whether the value would have
107
- // matched — that distinction is the 404's, below.
108
- const parsedBody = bodySchema.safeParse(request.body);
109
- if (!parsedBody.success) {
110
- return reply.status(400).send({
111
- ok: false,
112
- error: {
113
- code: "validation_failed",
114
- message: "A verification nonce is required",
115
- },
116
- });
117
- }
118
-
119
- const result = await verifyProjectListingDraftEmail(
120
- parsedParams.data.id,
121
- resumeToken,
122
- parsedBody.data.verifyNonce,
123
- );
124
- if (!result.ok) {
125
- return reply.status(404).send({
126
- ok: false,
127
- error: { code: "not_found", message: "Draft not found" },
128
- });
129
- }
130
-
131
- // Routing metadata only, the same PII boundary `start` documents: the
132
- // listing id and the caller's ip, never the founder's email and never
133
- // the token.
134
- request.log.info(
135
- { listingId: result.value.id, ip: request.ip },
136
- "project listing draft email verified",
137
- );
138
-
139
- return sendValidated(
140
- reply,
141
- projectListingVerifyEmailResponseSchema,
142
- {
143
- id: result.value.id,
144
- emailVerifiedAt: result.value.emailVerifiedAt.toISOString(),
145
- },
146
- "verify-email",
147
- );
148
- },
149
- );
150
- };