create-ailk 0.23.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/README.md +68 -33
  2. package/component-catalog.json +3 -3
  3. package/component-catalog.md +3 -3
  4. package/dist/add-module.js +10 -3
  5. package/dist/add-route.d.ts +12 -1
  6. package/dist/add-route.js +38 -4
  7. package/dist/cli.js +12 -7
  8. package/dist/derive-architecture.d.ts +3 -4
  9. package/dist/derive-architecture.js +75 -22
  10. package/dist/lib/design-checks.d.ts +9 -4
  11. package/dist/lib/design-checks.js +13 -7
  12. package/dist/lib/extract-module-bundle.js +29 -2
  13. package/dist/lib/fetch-template-snapshot.d.ts +1 -1
  14. package/dist/lib/fetch-template-snapshot.js +7 -3
  15. package/dist/lib/import-graph.d.ts +1 -1
  16. package/dist/lib/import-graph.js +4 -4
  17. package/dist/lib/module-license-gate.d.ts +12 -1
  18. package/dist/lib/module-license-gate.js +34 -12
  19. package/dist/lib/scaffold-render-sweep.d.ts +33 -0
  20. package/dist/lib/scaffold-render-sweep.js +45 -0
  21. package/dist/module-architecture.d.ts +20 -3
  22. package/dist/module-architecture.js +122 -538
  23. package/dist/paid-sections.d.ts +25 -1
  24. package/dist/paid-sections.js +88 -3
  25. package/dist/surfaces.js +10 -2
  26. package/dist/sync-routes.d.ts +30 -4
  27. package/dist/sync-routes.js +271 -18
  28. package/dist/template-record.d.ts +14 -4
  29. package/dist/template-record.js +23 -5
  30. package/dist/topology.d.ts +16 -3
  31. package/dist/topology.js +31 -19
  32. package/dist/update.d.ts +10 -1
  33. package/dist/update.js +540 -16
  34. package/package.json +3 -3
  35. package/release-scope.json +1 -1
  36. package/templates/.claude/cloudparity-repo-hooks.json +5 -0
  37. package/templates/.claude/hooks/template-guard.sh +137 -0
  38. package/templates/.claude/rules/extending.md +106 -0
  39. package/templates/.claude/rules/loop-contract.md +2 -2
  40. package/templates/.claude/settings.json +11 -0
  41. package/templates/.env.example +9 -5
  42. package/templates/.github/workflows/ci.yml +7 -4
  43. package/templates/CLAUDE.md +15 -3
  44. package/templates/CONVENTIONS.md +8 -10
  45. package/templates/README.md +14 -13
  46. package/templates/apps/api/.env.example +9 -2
  47. package/templates/apps/api/CLAUDE.md +122 -82
  48. package/templates/apps/api/jest.config.cjs +15 -5
  49. package/templates/apps/api/package.json +16 -20
  50. package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
  51. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
  52. package/templates/apps/api/src/index.ts +1 -1
  53. package/templates/apps/api/src/lib/__mocks__/prisma.ts +7 -4
  54. package/templates/apps/api/src/modules/commerce.ts +10 -0
  55. package/templates/apps/api/src/modules/content-write.ts +10 -0
  56. package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
  57. package/templates/apps/api/src/modules/scheduling.ts +10 -0
  58. package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
  59. package/templates/apps/api/src/modules/workspace.ts +10 -0
  60. package/templates/apps/api/src/server.ts +117 -1857
  61. package/templates/apps/api/vercel.json +2 -2
  62. package/templates/apps/mcp/CLAUDE.md +77 -24
  63. package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
  64. package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
  65. package/templates/apps/mcp/jest.config.cjs +6 -1
  66. package/templates/apps/mcp/package.json +5 -12
  67. package/templates/apps/mcp/src/app.ts +8 -7
  68. package/templates/apps/mcp/src/index.ts +6 -34
  69. package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
  70. package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
  71. package/templates/apps/mcp/src/site.ts +12 -0
  72. package/templates/apps/web/.env.example +1 -1
  73. package/templates/apps/web/CLAUDE.md +21 -5
  74. package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
  75. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +1 -1
  76. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +14 -4
  77. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
  78. package/templates/apps/web/app/[locale]/contact/intake-script.ts +1 -1
  79. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
  80. package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +28 -7
  81. package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
  82. package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
  83. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
  84. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
  85. package/templates/apps/web/app/api/revalidate/route.ts +3 -3
  86. package/templates/apps/web/auth.ts +2 -2
  87. package/templates/apps/web/jest.config.cjs +1 -0
  88. package/templates/apps/web/lib/__tests__/magnet-routes.test.ts +7 -0
  89. package/templates/apps/web/lib/auth-email.ts +1 -1
  90. package/templates/apps/web/lib/magnet-routes.ts +3 -1
  91. package/templates/apps/web/lib/newsletter.actions.ts +9 -6
  92. package/templates/apps/web/lib/relay.ts +2 -2
  93. package/templates/apps/web/lib/release-scope.ts +47 -0
  94. package/templates/apps/web/lib/server-api.ts +1 -1
  95. package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
  96. package/templates/customizations.yaml +37 -0
  97. package/templates/database/prisma.config.ts +10 -14
  98. package/templates/database/seed-test.ts +2 -2
  99. package/templates/database/seed.ts +32 -5
  100. package/templates/package.json +12 -6
  101. package/templates/pnpm-workspace.yaml +0 -1
  102. package/templates/project.yaml +16 -8
  103. package/templates/tools/jest/reporters.cjs +65 -0
  104. package/templates/tools/lint-architecture.ts +757 -7
  105. package/templates/tsconfig.json +1 -2
  106. package/versions.json +48 -35
  107. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
  108. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
  109. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
  110. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
  111. package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
  112. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
  113. package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
  114. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
  115. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
  116. package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
  117. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
  118. package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
  119. package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
  120. package/templates/apps/api/src/bin/spokes.ts +0 -198
  121. package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
  122. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
  123. package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
  124. package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
  125. package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
  126. package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
  127. package/templates/apps/api/src/config/index.ts +0 -596
  128. package/templates/apps/api/src/config/modules.ts +0 -83
  129. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
  130. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
  131. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
  132. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
  133. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
  134. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
  135. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
  136. package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
  137. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
  138. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
  139. package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
  140. package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
  141. package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
  142. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
  143. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
  144. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
  145. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
  146. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
  147. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
  148. package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -292
  149. package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
  150. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
  151. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
  152. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
  153. package/templates/apps/api/src/lib/agent-store.ts +0 -613
  154. package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
  155. package/templates/apps/api/src/lib/consent-store.ts +0 -363
  156. package/templates/apps/api/src/lib/content-adapter.ts +0 -112
  157. package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
  158. package/templates/apps/api/src/lib/error-serializer.ts +0 -164
  159. package/templates/apps/api/src/lib/errors.ts +0 -95
  160. package/templates/apps/api/src/lib/file-fallback.ts +0 -87
  161. package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
  162. package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
  163. package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
  164. package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
  165. package/templates/apps/api/src/lib/license-key-store.ts +0 -45
  166. package/templates/apps/api/src/lib/locales.ts +0 -201
  167. package/templates/apps/api/src/lib/outbound-http.ts +0 -127
  168. package/templates/apps/api/src/lib/prisma.ts +0 -21
  169. package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
  170. package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
  171. package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
  172. package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
  173. package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
  174. package/templates/apps/api/src/lib/site.ts +0 -254
  175. package/templates/apps/api/src/lib/slice-load.ts +0 -90
  176. package/templates/apps/api/src/lib/spoke-store.ts +0 -180
  177. package/templates/apps/api/src/lib/stripe.ts +0 -318
  178. package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
  179. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
  180. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
  181. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
  182. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
  183. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
  184. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
  185. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
  186. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
  187. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
  188. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
  189. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
  190. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
  191. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
  192. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
  193. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
  194. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
  195. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
  196. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
  197. package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
  198. package/templates/apps/api/src/middleware/auth.ts +0 -864
  199. package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
  200. package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
  201. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -264
  202. package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
  203. package/templates/apps/api/src/openapi/index.ts +0 -18
  204. package/templates/apps/api/src/openapi/spec.ts +0 -1815
  205. package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
  206. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
  207. package/templates/apps/api/src/routes/aeo/index.ts +0 -107
  208. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
  209. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
  210. package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
  211. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
  212. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
  213. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
  214. package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
  215. package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
  216. package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
  217. package/templates/apps/api/src/routes/auth/user.ts +0 -305
  218. package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -325
  219. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
  220. package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1300
  221. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
  222. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
  223. package/templates/apps/api/src/routes/checkout/index.ts +0 -34
  224. package/templates/apps/api/src/routes/checkout/session.ts +0 -171
  225. package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
  226. package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
  227. package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
  228. package/templates/apps/api/src/routes/consent/account.ts +0 -268
  229. package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
  230. package/templates/apps/api/src/routes/consent/index.ts +0 -26
  231. package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
  232. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
  233. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
  234. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
  235. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
  236. package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
  237. package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
  238. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
  239. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
  240. package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
  241. package/templates/apps/api/src/routes/content/get-page.ts +0 -268
  242. package/templates/apps/api/src/routes/content/index.ts +0 -49
  243. package/templates/apps/api/src/routes/content/list-pages.ts +0 -95
  244. package/templates/apps/api/src/routes/content/list-types.ts +0 -19
  245. package/templates/apps/api/src/routes/content/offerings.ts +0 -184
  246. package/templates/apps/api/src/routes/content/pricing.ts +0 -176
  247. package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
  248. package/templates/apps/api/src/routes/content/search.ts +0 -129
  249. package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
  250. package/templates/apps/api/src/routes/content/slug.ts +0 -9
  251. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
  252. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
  253. package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
  254. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
  255. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
  256. package/templates/apps/api/src/routes/leads/index.ts +0 -573
  257. package/templates/apps/api/src/routes/leads/list.ts +0 -104
  258. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
  259. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
  260. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
  261. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -480
  262. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -465
  263. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
  264. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
  265. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
  266. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
  267. package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
  268. package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
  269. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
  270. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
  271. package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
  272. package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
  273. package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
  274. package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
  275. package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
  276. package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
  277. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
  278. package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
  279. package/templates/apps/api/src/routes/requests/index.ts +0 -54
  280. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
  281. package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
  282. package/templates/apps/api/src/routes/webhooks/README.md +0 -398
  283. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
  284. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
  285. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -448
  286. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
  287. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
  288. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
  289. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
  290. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
  291. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
  292. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
  293. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
  294. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -808
  295. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
  296. package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
  297. package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
  298. package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2026
  299. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -528
  300. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
  301. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
  302. package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
  303. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
  304. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
  305. package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
  306. package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
  307. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -867
  308. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
  309. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
  310. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
  311. package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
  312. package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
  313. package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
  314. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
  315. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
  316. package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
  317. package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1176
  318. package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -444
  319. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -154
  320. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
  321. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
  322. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
  323. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
  324. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
  325. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
  326. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
  327. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
  328. package/templates/apps/api/src/services/abandon-email.ts +0 -313
  329. package/templates/apps/api/src/services/aeo-score.ts +0 -325
  330. package/templates/apps/api/src/services/answer-distributions.ts +0 -138
  331. package/templates/apps/api/src/services/audit-log.ts +0 -961
  332. package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
  333. package/templates/apps/api/src/services/consent.ts +0 -834
  334. package/templates/apps/api/src/services/default-tenant.ts +0 -416
  335. package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -755
  336. package/templates/apps/api/src/services/dunning-policy.ts +0 -294
  337. package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
  338. package/templates/apps/api/src/services/entitlements.ts +0 -338
  339. package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
  340. package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
  341. package/templates/apps/api/src/services/lead-promotion.ts +0 -160
  342. package/templates/apps/api/src/services/lead-routing.ts +0 -1372
  343. package/templates/apps/api/src/services/leads-inbox.ts +0 -312
  344. package/templates/apps/api/src/services/listing-config.ts +0 -178
  345. package/templates/apps/api/src/services/magnet-completion.ts +0 -242
  346. package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -295
  347. package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
  348. package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -868
  349. package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
  350. package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -396
  351. package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -681
  352. package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
  353. package/templates/apps/api/src/services/offerings/catalog.ts +0 -308
  354. package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -385
  355. package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
  356. package/templates/apps/api/src/services/offerings/connection.ts +0 -1003
  357. package/templates/apps/api/src/services/offerings/index.ts +0 -614
  358. package/templates/apps/api/src/services/offerings/source.ts +0 -140
  359. package/templates/apps/api/src/services/offerings/store.ts +0 -150
  360. package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
  361. package/templates/apps/api/src/services/person.ts +0 -1188
  362. package/templates/apps/api/src/services/plan-offerings.ts +0 -125
  363. package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
  364. package/templates/apps/api/src/services/project-listings.ts +0 -2073
  365. package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
  366. package/templates/apps/api/src/services/request-confirm.ts +0 -698
  367. package/templates/apps/api/src/services/revalidation.ts +0 -235
  368. package/templates/apps/api/src/services/slack-notify.ts +0 -291
  369. package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
  370. package/templates/apps/api/src/services/usage-credits.ts +0 -340
  371. package/templates/apps/api/src/services/verified-email.ts +0 -71
  372. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
  373. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
  374. package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
  375. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
  376. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
  377. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
  378. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
  379. package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
  380. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
  381. package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
  382. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
  383. package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
  384. package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
  385. package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
  386. package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
  387. package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
  388. package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1151
  389. package/templates/apps/mcp/__tests__/index.test.ts +0 -195
  390. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
  391. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
  392. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -65
  393. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -187
  394. package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
  395. package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
  396. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -165
  397. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
  398. package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -228
  399. package/templates/apps/mcp/__tests__/locale.test.ts +0 -135
  400. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
  401. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
  402. package/templates/apps/mcp/__tests__/read_content.test.ts +0 -474
  403. package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -225
  404. package/templates/apps/mcp/__tests__/search_content.test.ts +0 -256
  405. package/templates/apps/mcp/__tests__/server.test.ts +0 -388
  406. package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
  407. package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -307
  408. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -223
  409. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
  410. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
  411. package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
  412. package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
  413. package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
  414. package/templates/apps/mcp/src/abuse/index.ts +0 -342
  415. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
  416. package/templates/apps/mcp/src/boot.ts +0 -167
  417. package/templates/apps/mcp/src/config/modules.ts +0 -43
  418. package/templates/apps/mcp/src/http-transport.ts +0 -526
  419. package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
  420. package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
  421. package/templates/apps/mcp/src/lib/content-adapter.ts +0 -142
  422. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -139
  423. package/templates/apps/mcp/src/lib/errors.ts +0 -61
  424. package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
  425. package/templates/apps/mcp/src/lib/locales.ts +0 -171
  426. package/templates/apps/mcp/src/lib/prisma.ts +0 -39
  427. package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
  428. package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
  429. package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
  430. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
  431. package/templates/apps/mcp/src/request-context.ts +0 -52
  432. package/templates/apps/mcp/src/server.ts +0 -343
  433. package/templates/apps/mcp/src/serverless-app.ts +0 -88
  434. package/templates/apps/mcp/src/tools/audit.ts +0 -127
  435. package/templates/apps/mcp/src/tools/capture_lead.ts +0 -64
  436. package/templates/apps/mcp/src/tools/create_project.ts +0 -134
  437. package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
  438. package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
  439. package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
  440. package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
  441. package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
  442. package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
  443. package/templates/apps/mcp/src/tools/index.ts +0 -137
  444. package/templates/apps/mcp/src/tools/list_pages.ts +0 -74
  445. package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
  446. package/templates/apps/mcp/src/tools/proposals.ts +0 -27
  447. package/templates/apps/mcp/src/tools/purchase.ts +0 -205
  448. package/templates/apps/mcp/src/tools/read_content.ts +0 -75
  449. package/templates/apps/mcp/src/tools/request_callback.ts +0 -59
  450. package/templates/apps/mcp/src/tools/search_content.ts +0 -67
  451. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -57
  452. package/templates/apps/mcp/src/workspace-server.ts +0 -224
  453. package/templates/database/CHANGELOG.md +0 -961
  454. package/templates/database/LICENSE +0 -202
  455. package/templates/database/NOTICE +0 -2
  456. package/templates/database/README.md +0 -243
  457. package/templates/database/__tests__/agents.db.test.ts +0 -320
  458. package/templates/database/__tests__/appointment.db.test.ts +0 -106
  459. package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
  460. package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
  461. package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
  462. package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
  463. package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
  464. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
  465. package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
  466. package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
  467. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
  468. package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
  469. package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
  470. package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
  471. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
  472. package/templates/database/__tests__/flows-presets.test.ts +0 -173
  473. package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
  474. package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
  475. package/templates/database/__tests__/member-area.db.test.ts +0 -257
  476. package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
  477. package/templates/database/__tests__/member-contract.db.test.ts +0 -413
  478. package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
  479. package/templates/database/__tests__/offerings-migration.test.ts +0 -197
  480. package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
  481. package/templates/database/__tests__/offerings.db.test.ts +0 -303
  482. package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
  483. package/templates/database/__tests__/person-contact.db.test.ts +0 -563
  484. package/templates/database/__tests__/person-notes.db.test.ts +0 -249
  485. package/templates/database/__tests__/person.db.test.ts +0 -586
  486. package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
  487. package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
  488. package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
  489. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
  490. package/templates/database/__tests__/seed.test.ts +0 -240
  491. package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
  492. package/templates/database/__tests__/tenancy.test.ts +0 -141
  493. package/templates/database/__tests__/user-cascade.test.ts +0 -140
  494. package/templates/database/_gitignore +0 -8
  495. package/templates/database/auth/.gitkeep +0 -0
  496. package/templates/database/auth/schema.prisma +0 -641
  497. package/templates/database/config/.gitkeep +0 -0
  498. package/templates/database/config/schema.prisma +0 -441
  499. package/templates/database/content/.gitkeep +0 -0
  500. package/templates/database/content/schema.prisma +0 -339
  501. package/templates/database/eslint.config.mjs +0 -69
  502. package/templates/database/flows/listing-diagnostic.ts +0 -182
  503. package/templates/database/flows/presets.ts +0 -315
  504. package/templates/database/inbox/.gitkeep +0 -0
  505. package/templates/database/inbox/README.md +0 -3
  506. package/templates/database/inbox/__tests__/schema.test.ts +0 -44
  507. package/templates/database/inbox/schema.prisma +0 -1447
  508. package/templates/database/jest.config.cjs +0 -36
  509. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
  510. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
  511. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
  512. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
  513. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
  514. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
  515. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
  516. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
  517. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
  518. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
  519. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
  520. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
  521. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
  522. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
  523. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
  524. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
  525. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
  526. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
  527. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
  528. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
  529. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
  530. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
  531. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
  532. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
  533. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
  534. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
  535. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
  536. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
  537. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
  538. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
  539. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
  540. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
  541. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
  542. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
  543. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
  544. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
  545. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
  546. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
  547. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
  548. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
  549. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
  550. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
  551. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
  552. package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
  553. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
  554. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
  555. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
  556. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
  557. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
  558. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
  559. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
  560. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
  561. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
  562. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
  563. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
  564. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
  565. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
  566. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
  567. package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
  568. package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
  569. package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
  570. package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
  571. package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
  572. package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
  573. package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
  574. package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
  575. package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
  576. package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
  577. package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
  578. package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
  579. package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
  580. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
  581. package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
  582. package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
  583. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
  584. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
  585. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
  586. package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
  587. package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
  588. package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
  589. package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
  590. package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
  591. package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
  592. package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
  593. package/templates/database/migrations/migration_lock.toml +0 -3
  594. package/templates/database/ops/.gitkeep +0 -0
  595. package/templates/database/ops/schema.prisma +0 -43
  596. package/templates/database/package.json +0 -89
  597. package/templates/database/schema.prisma +0 -71
  598. package/templates/database/scripts/db-generate-locked.sh +0 -80
  599. package/templates/database/scripts/person-backfill.sql +0 -132
  600. package/templates/database/tenancy.ts +0 -183
  601. package/templates/database/tsconfig.build.json +0 -16
  602. package/templates/database/tsconfig.flows.json +0 -15
  603. package/templates/database/tsconfig.json +0 -16
  604. package/templates/database/tsconfig.tenancy.json +0 -14
@@ -1,339 +0,0 @@
1
- // content namespace — chat + artifact substrate (AgentSession, ConversationEvent,
2
- // SessionReadReceipt, Artifact, ArtifactVersion, Asset)
3
- //
4
- // Backs the event-sourced conversation transport + artifact persistence in
5
- // docs/research/ploy-capture/BACKEND-REQUIREMENTS.md (§1 transport R-T1..R-T7,
6
- // §2 event envelope, §3 endpoints). Workspaces own all domain content, so every
7
- // table here carries a non-null `workspaceId` tenant scope.
8
- //
9
- // Per ADR 0009 invariant 1: workspaceId / userId are plain String stable IDs —
10
- // NO @relation into the auth namespace (Workspace/User live in database/auth/).
11
- // Relations WITHIN this namespace (event → session, version → artifact) are
12
- // real FKs. Cross-namespace assembly (e.g. tenant guard resolving a session's
13
- // workspace) routes through apps/api/src/services/ (invariant 4).
14
- //
15
- // Generator + datasource blocks live in database/schema.prisma (the root schema
16
- // file). This file holds only model definitions for the content namespace.
17
-
18
- /// AgentSession — one agent conversation ("session"/captured "ploy") within a
19
- /// workspace. lastSeq is the append watermark for the event log (R-T1).
20
- model AgentSession {
21
- id String @id @default(dbgenerated("('agsess_'::text || (uuidv7())::text)")) @db.Text
22
- workspaceId String @map("workspace_id")
23
- title String?
24
- status String @default("idle")
25
- lastSeq Int @default(0) @map("last_seq")
26
- lastMessageAt DateTime? @map("last_message_at")
27
- draftMessage String? @map("draft_message")
28
- createdAt DateTime @default(now()) @map("created_at")
29
- updatedAt DateTime @updatedAt @map("updated_at")
30
-
31
- events ConversationEvent[]
32
- artifacts Artifact[]
33
- readReceipts SessionReadReceipt[]
34
-
35
- @@index([workspaceId, lastMessageAt(sort: Desc)])
36
- @@map("agent_sessions")
37
- }
38
-
39
- /// ConversationEvent — append-only, seq-ordered event log entry (R-T1/R-T4).
40
- /// Envelope: { agentId, seq, type, turnId, payload, createdAt } (§2).
41
- /// workspaceId is denormalized so the scope layer filters events without a
42
- /// join through agent_sessions.
43
- model ConversationEvent {
44
- id String @id @default(dbgenerated("('convev_'::text || (uuidv7())::text)")) @db.Text
45
- sessionId String @map("session_id")
46
- workspaceId String @map("workspace_id")
47
- agentId String @map("agent_id")
48
- seq Int
49
- type String
50
- turnId String? @map("turn_id")
51
- payload Json
52
- createdAt DateTime @default(now()) @map("created_at")
53
-
54
- session AgentSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
55
-
56
- @@unique([sessionId, seq])
57
- @@index([workspaceId])
58
- @@map("conversation_events")
59
- }
60
-
61
- /// SessionReadReceipt — per-user read position for a session (R-T7 mark-read;
62
- /// drives unread badges). userId is a stable auth-namespace ID — no FK.
63
- model SessionReadReceipt {
64
- id String @id @default(dbgenerated("('receipt_'::text || (uuidv7())::text)")) @db.Text
65
- sessionId String @map("session_id")
66
- workspaceId String @map("workspace_id")
67
- userId String @map("user_id")
68
- lastReadSeq Int @default(0) @map("last_read_seq")
69
- updatedAt DateTime @updatedAt @map("updated_at")
70
-
71
- session AgentSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
72
-
73
- @@unique([sessionId, userId])
74
- @@index([workspaceId])
75
- @@map("session_read_receipts")
76
- }
77
-
78
- /// Artifact — a piece of the WORKSPACE's versioned content (#3846, generalized
79
- /// by #5800 / roadmap D1). Originally "a session's produced output"; a session
80
- /// is now PROVENANCE, not ownership — `sessionId` is optional and `SetNull`, so
81
- /// deleting the conversation that produced a page leaves the page standing.
82
- ///
83
- /// `contentType` is the discriminator the content store reads: `text/page` is
84
- /// what the editor writes, `text/document` the legacy chat artifact. A page's
85
- /// public identity is `(workspaceId, contentType, locale, slug)`; `slug` stays
86
- /// NULL until publish, and NULLs never collide in a Postgres unique index, so a
87
- /// workspace may hold any number of unpublished drafts.
88
- ///
89
- /// `publishedVersionId` is a plain pointer at the ArtifactVersion the public
90
- /// read serves — deliberately NOT a relation (a FK back into `versions` would
91
- /// make the delete order of an artifact's own history circular), and
92
- /// deliberately NOT `ArtifactVersion.isCurrent`, which is the DRAFT TIP and is
93
- /// never the publish mechanism. Saving a draft moves `isCurrent`; only publish
94
- /// moves this pointer.
95
- ///
96
- /// `type` is the LEGACY discriminator. It predates `contentType` and is still
97
- /// read by apps/api/src/routes/workspaces/sessions.ts (the session-artifacts
98
- /// route, a hard-floor surface), so #5800 added `contentType` beside it and
99
- /// backfilled it from `type` rather than renaming the column out from under a
100
- /// live consumer. New code reads `contentType`; retiring `type` belongs to the
101
- /// card that moves that route.
102
- model Artifact {
103
- id String @id @default(dbgenerated("('artif_'::text || (uuidv7())::text)")) @db.Text
104
- sessionId String? @map("session_id")
105
- workspaceId String @map("workspace_id")
106
- type String @default("text/document")
107
- contentType String @default("text/document") @map("content_type")
108
- locale String @default("en")
109
- slug String?
110
- title String
111
- publishedVersionId String? @map("published_version_id")
112
- createdAt DateTime @default(now()) @map("created_at")
113
- updatedAt DateTime @updatedAt @map("updated_at")
114
-
115
- session AgentSession? @relation(fields: [sessionId], references: [id], onDelete: SetNull)
116
- versions ArtifactVersion[]
117
-
118
- @@unique([workspaceId, contentType, locale, slug])
119
- @@index([sessionId])
120
- @@index([workspaceId])
121
- @@index([workspaceId, contentType, updatedAt])
122
- @@map("artifacts")
123
- }
124
-
125
- /// ArtifactVersion — auto-saved version history; exactly one isCurrent per
126
- /// artifact (enforced at the service layer on save/restore).
127
- model ArtifactVersion {
128
- id String @id @default(dbgenerated("('artiv_'::text || (uuidv7())::text)")) @db.Text
129
- artifactId String @map("artifact_id")
130
- workspaceId String @map("workspace_id")
131
- content Json
132
- isCurrent Boolean @default(true) @map("is_current")
133
- savedAt DateTime @default(now()) @map("saved_at")
134
-
135
- artifact Artifact @relation(fields: [artifactId], references: [id], onDelete: Cascade)
136
-
137
- @@index([artifactId, savedAt(sort: Desc)])
138
- @@index([workspaceId])
139
- @@map("artifact_versions")
140
- }
141
-
142
- /// Asset — a workspace's uploaded binary (#5800 / roadmap D7), following the
143
- /// `DeliverableAsset` precedent in the inbox namespace: the bytes live in the
144
- /// row, not in object storage. That precedent was deliberate — no new
145
- /// infrastructure — and only the resolver changes if blob storage arrives later.
146
- ///
147
- /// `workspaceId` is a plain String stable id with no @relation (ADR 0009
148
- /// invariant 1), and `(workspaceId, key)` is the addressable identity. Ids are
149
- /// UUIDv7 (ADR 0031), so a re-upload is a NEW id and a served asset can be
150
- /// cached immutably. The upload route itself is #5802's scope, not this model's.
151
- ///
152
- /// Since #6310: this is also the store a magnet's `deliverables.assets[].assetKey`
153
- /// resolves against FIRST (by `(workspaceId, key)`), ahead of the legacy
154
- /// `DeliverableAsset` fallback (database/inbox/schema.prisma) — read through
155
- /// the scoped boundary in apps/api/src/lib/deliverable-asset-store.ts, never
156
- /// a raw query.
157
- model Asset {
158
- id String @id @default(dbgenerated("('asset_'::text || (uuidv7())::text)")) @db.Text
159
- workspaceId String @map("workspace_id")
160
- /// The caller-chosen name an artifact's content references the asset by.
161
- key String
162
- /// Download filename (Content-Disposition). Stored RAW; sanitize at SERVE
163
- /// time, exactly as the DeliverableAsset download route does.
164
- filename String
165
- contentType String @map("content_type")
166
- bytes Bytes
167
- size Int
168
- /// Owner-authored display name, shown above the filename in the lightbox
169
- /// (#6092, S4/D10). NULL means the owner has not written one — distinct from
170
- /// an empty string, which means they cleared it. Never backfilled from
171
- /// `filename`: the two are different facts (demo.html:782 renders both).
172
- title String?
173
- /// Owner-authored longer description. Same NULL-vs-empty contract as `title`.
174
- description String?
175
- /// Owner-controlled tag SLUGS (`ad-creative`, `workspace-memory`, …), never
176
- /// the human labels — the label is presentation, resolved by the surface from
177
- /// its own vocabulary (demo.html:358 `ATAGS`, :794 the Docs set). Free-form
178
- /// by design: the asset vocabulary and the document vocabulary (D8/D9) ride
179
- /// this one column, and the "fixed set" of D10 is a UI affordance, not a
180
- /// database constraint (#6092, D2 of the spec).
181
- tags String[] @default([])
182
- createdAt DateTime @default(now()) @map("created_at")
183
-
184
- @@unique([workspaceId, key])
185
- @@index([workspaceId])
186
- @@map("assets")
187
- }
188
-
189
- // ============================================================================
190
- // Usage-billing metering (FEAT-047 P1.S1, #3709 — Epic #3704)
191
- //
192
- // The metering event + its org-level aggregates. Per ADR 0009 D2 (roadmap §4),
193
- // the metering event + UsagePeriod + UsageBillingReport live in `content`;
194
- // balances/plans (S2) live in auth/config. organizationId/workspaceId/userId
195
- // are plain String stable-ids — no @relation into auth (ADR 0009 invariant 1).
196
- // Field roster ported from docs/research/wt-billing-capture/schema.md, modeled
197
- // on WT's TraceLog billing columns (spec D1), with workspaceId/userId added to
198
- // the event grain (spec D2). Cross-namespace assembly (e.g. resolving an
199
- // event's owning Workspace) routes through apps/api/src/services/.
200
- // ============================================================================
201
-
202
- /// ModelTier — the pricing tier at event time. BASE is unlimited/free-ish;
203
- /// PREMIUM/FRONTIER consume credits. Defined here (S1, the dependency root)
204
- /// per spec OQ-1 — S2's LlmModel references the same enum through the merged
205
- /// prismaSchemaFolder (one logical schema; an enum reference needs no
206
- /// @relation, so this is not a cross-namespace FK).
207
- enum ModelTier {
208
- BASE
209
- PREMIUM
210
- FRONTIER
211
- }
212
-
213
- /// UsageBillingStatus — UsageBillingReport lifecycle: PENDING → REPORTED →
214
- /// INVOICED → PAID, or FAILED.
215
- enum UsageBillingStatus {
216
- PENDING
217
- REPORTED
218
- INVOICED
219
- PAID
220
- FAILED
221
- }
222
-
223
- /// UsageEvent — one row per billable AI call (the metering event; modeled on
224
- /// WT's TraceLog billing columns, spec D1). org+workspace+user grain (spec
225
- /// D2); all three scope ids are plain String stable-ids — no cross-namespace
226
- /// @relation (ADR 0009 invariant 1, spec D3). The three attribution portion
227
- /// columns are the load-bearing billing split; only onDemandPortionCents is
228
- /// ever reported to Stripe (P4, spec D4). completionStatus 'success' rows
229
- /// drive billing — aggregation (P2) filters on it.
230
- model UsageEvent {
231
- id String @id @default(dbgenerated("('usagev_'::text || (uuidv7())::text)")) @db.Text
232
- organizationId String @map("organization_id")
233
- workspaceId String @map("workspace_id")
234
- userId String @map("user_id")
235
-
236
- provider String
237
- model String
238
-
239
- // Cache-aware token breakdown.
240
- inputTokensCacheWrite Int @map("input_tokens_cache_write")
241
- inputTokensNoCacheWrite Int @map("input_tokens_no_cache_write")
242
- cacheReadTokens Int @map("cache_read_tokens")
243
- outputTokens Int @map("output_tokens")
244
- thinkingTokens Int @map("thinking_tokens")
245
- totalTokens Int @map("total_tokens")
246
-
247
- providerCostUsd Decimal @map("provider_cost_usd") @db.Decimal(10, 6)
248
- billedCostUsd Decimal @map("billed_cost_usd") @db.Decimal(10, 6)
249
- markupPercent Decimal @map("markup_percent") @db.Decimal(5, 2)
250
-
251
- modelTier ModelTier @default(BASE) @map("model_tier")
252
- wasAutoModel Boolean @map("was_auto_model")
253
-
254
- // Attribution split — billedCostUsd apportioned across the three buckets;
255
- // only onDemandPortionCents is ever Stripe-metered (P4, spec D4).
256
- includedPortionCents Int @default(0) @map("included_portion_cents")
257
- creditBalancePortionCents Int @default(0) @map("credit_balance_portion_cents")
258
- onDemandPortionCents Int @default(0) @map("on_demand_portion_cents")
259
-
260
- completionStatus String @map("completion_status")
261
- createdAt DateTime @default(now()) @map("created_at")
262
-
263
- @@index([organizationId, createdAt])
264
- @@index([workspaceId, createdAt])
265
- @@index([userId, createdAt])
266
- @@index([provider, model])
267
- @@index([modelTier, wasAutoModel])
268
- @@map("usage_events")
269
- }
270
-
271
- /// UsagePeriod — one row per (organizationId, periodStart); the org-scoped
272
- /// spend/tier rollup the P2 write path upserts as UsageEvent rows land.
273
- /// Carries the event-grain roll-up support for the Org → Workspace → User
274
- /// aggregation (spec D2) — whether this model itself gains per-workspace
275
- /// sub-rows is a P2 decision, not a P1 schema requirement (spec OQ-2).
276
- model UsagePeriod {
277
- id String @id @default(dbgenerated("('usagper_'::text || (uuidv7())::text)")) @db.Text
278
- organizationId String @map("organization_id")
279
-
280
- periodStart DateTime @map("period_start")
281
- periodEnd DateTime @map("period_end")
282
-
283
- tokensConsumed BigInt @default(0) @map("tokens_consumed")
284
- baseTokensConsumed BigInt @default(0) @map("base_tokens_consumed")
285
- premiumTokensConsumed BigInt @default(0) @map("premium_tokens_consumed")
286
- frontierTokensConsumed BigInt @default(0) @map("frontier_tokens_consumed")
287
-
288
- usageSpendCents Int @default(0) @map("usage_spend_cents")
289
-
290
- @@unique([organizationId, periodStart])
291
- @@index([baseTokensConsumed, premiumTokensConsumed, frontierTokensConsumed], map: "usage_periods_tier_tracking_idx")
292
- @@map("usage_periods")
293
- }
294
-
295
- /// UsageBillingReport — one per (organizationId, periodStart, periodEnd); the
296
- /// Stripe-reporting unit rolled up from UsageEvent by P2 aggregation. Only
297
- /// onDemandCents is ever reported to Stripe (P4, spec D4) — includedCents/
298
- /// creditBalanceCents are informational attribution, never metered.
299
- model UsageBillingReport {
300
- id String @id @default(dbgenerated("('usagrept_'::text || (uuidv7())::text)")) @db.Text
301
- organizationId String @map("organization_id")
302
-
303
- periodStart DateTime @map("period_start")
304
- periodEnd DateTime @map("period_end")
305
-
306
- // AGGREGATE precision (#3738 H2) — these hold a MONTH of events, not one
307
- // event, so they must NOT reuse UsageEvent's per-event widths. At the
308
- // original Decimal(10,6)/Int, an org whose month crossed $9,999.999999 (or
309
- // 2.15B tokens) overflowed the column, the upsert threw, and the report was
310
- // never written on ANY subsequent run — silently stalling revenue for the
311
- // largest customers, worsening monotonically. Decimal(20,6) ≈ $1e14 and int8
312
- // give headroom far above the service's own MAX_TOTAL_USD / token caps, so
313
- // the service's loud `aggregate_overflow` assertion is always the gate and a
314
- // silent DB overflow is unreachable. See usage-aggregation.ts § Bounds.
315
- totalProviderCost Decimal @map("total_provider_cost") @db.Decimal(20, 6)
316
- totalMarkupAmount Decimal @map("total_markup_amount") @db.Decimal(20, 6)
317
- totalBilledAmount Decimal @map("total_billed_amount") @db.Decimal(20, 6)
318
-
319
- totalTokens BigInt @map("total_tokens")
320
- eventCount Int @map("event_count")
321
-
322
- // Attribution split — only onDemandCents is ever Stripe-metered (P4, spec D4).
323
- includedCents Int @default(0) @map("included_cents")
324
- creditBalanceCents Int @default(0) @map("credit_balance_cents")
325
- onDemandCents Int @default(0) @map("on_demand_cents")
326
-
327
- stripeUsageRecordId String? @map("stripe_usage_record_id")
328
- reportedToStripeAt DateTime? @map("reported_to_stripe_at")
329
- stripeInvoiceId String? @map("stripe_invoice_id")
330
-
331
- status UsageBillingStatus @default(PENDING)
332
- errorMessage String? @map("error_message")
333
-
334
- @@unique([organizationId, periodStart, periodEnd], map: "usage_billing_reports_period_key")
335
- @@index([organizationId, status])
336
- @@index([status])
337
- @@index([periodStart])
338
- @@map("usage_billing_reports")
339
- }
@@ -1,69 +0,0 @@
1
- // Self-contained ESLint flat config for this scaffolded package.
2
- //
3
- // It deliberately does NOT depend on @working-theory/eslint-config — that
4
- // package is internal to the AI Launch Kit monorepo and is not published, so
5
- // it cannot be a dependency of a scaffolded starter. Everything below comes
6
- // from public npm packages already pinned as devDependencies (see
7
- // package.json): @eslint/js, globals and typescript-eslint.
8
- //
9
- // Source file name (#5556): this file is checked in as `_eslint.config.mjs`,
10
- // not `eslint.config.mjs` — build-templates.mjs renames it at snapshot time
11
- // (renameScaffoldLintConfigs()). A file literally named `eslint.config.mjs`
12
- // anywhere under this monorepo (even one this repo's own root eslint.config.ts
13
- // lists in its `ignores`) is auto-discovered by ESLint's flat-config nested
14
- // resolution as a competing config root, which breaks the monorepo's own
15
- // lint runs (verified live: typescript-eslint's "multiple candidate
16
- // TSConfigRootDirs" parser error across unrelated packages/create-ailk
17
- // files). The underscore prefix keeps it invisible to that discovery while
18
- // it lives in this checkout; only the snapshot in templates/ — which ships
19
- // to the customer, not this repo — gets the real filename.
20
- import js from "@eslint/js";
21
- import globals from "globals";
22
- import tseslint from "typescript-eslint";
23
-
24
- export default tseslint.config(
25
- {
26
- ignores: [
27
- "**/.next/**",
28
- "**/dist/**",
29
- "**/generated/**",
30
- "**/node_modules/**",
31
- ],
32
- },
33
- js.configs.recommended,
34
- ...tseslint.configs.recommended,
35
- {
36
- languageOptions: {
37
- globals: {
38
- ...globals.node,
39
- ...globals.browser,
40
- ...globals.jest,
41
- },
42
- // Explicit, self-contained root — this scaffold config is never meant
43
- // to combine with any sibling scaffold package's config (each ships
44
- // standalone), and leaving it unset makes typescript-eslint's
45
- // candidate-root disambiguation ambiguous the moment more than one
46
- // scaffold package's config resolves in the same ESLint process (e.g.
47
- // this monorepo's own `templates/` build, where all four exist
48
- // side by side; a real customer scaffold never has that problem,
49
- // since it only ever ships and lints ONE of these four at a time).
50
- parserOptions: {
51
- tsconfigRootDir: import.meta.dirname,
52
- },
53
- },
54
- rules: {
55
- // Downgraded rather than off, so both stay visible without failing a
56
- // fresh scaffold's lint:
57
- // - unused-vars: most of the source follows the underscore-prefix
58
- // convention for intentionally-unused bindings, which this rule's
59
- // default options don't recognize; a handful of test fixtures also
60
- // carry genuinely-unused locals this minimal config doesn't try to
61
- // triage file-by-file.
62
- // - require-imports: CommonJS require() is the correct form in Jest
63
- // config/mock files and in a few test-only dynamic re-require
64
- // patterns.
65
- "@typescript-eslint/no-unused-vars": "warn",
66
- "@typescript-eslint/no-require-imports": "warn",
67
- },
68
- },
69
- );
@@ -1,182 +0,0 @@
1
- /**
2
- * @file listing-diagnostic.ts
3
- * @description The ONE scoring RULE every project-listing diagnostic shares
4
- * (#5001, reworked by #5036 D4) — the template's Q3–Q6 resolved by option
5
- * VALUE, never by option position.
6
- *
7
- * The mechanism (#5036 D4, "scoring by value, not position"): the generated
8
- * flow emits each scored option under the FOUNDER'S OWN `option.value`, and
9
- * the register's `optionWeights` map is keyed on those same values. Q3/Q4 are
10
- * founder-authored, so their weights map is built PER LISTING from that
11
- * listing's own options — the WEIGHT still comes from the founder's declared
12
- * order via `listingOptionPoints(index, arity)`, but it is stored against the
13
- * value rather than an index. Q5/Q6 carry fixed values
14
- * (`projectListingQuestionsSchema`, #4998), so their weights are declared once
15
- * here, shared by every listing.
16
- *
17
- * What that buys, and why the old `q{n}:{i}of{k}` encoding had to go: meaning
18
- * now travels with the value. A register may reorder or insert options and an
19
- * already-stored answer keeps scoring what it always meant, so the subset a
20
- * surface renders no longer has to be a prefix of the register's list — which
21
- * is what unblocks the shared team-composition value set (#5036 D3). It also
22
- * dissolves the "shared register needs a shared value universe" problem
23
- * (docs/lessons/2026-09-07-…): the generated experiment's `questionSet` now
24
- * declares the listing's OWN options, so
25
- * `waitlistExperimentConfigSchema`'s "every weights key must be a declared
26
- * option" cross-validation is satisfied by construction rather than by
27
- * declaring a finite universe of positional tokens.
28
- *
29
- * What is shared is therefore the RULE and the shape — same point names, same
30
- * `total` sum, same tier floors, same 0–12 range — not a single frozen
31
- * constant. Two listings' registers differ only in the Q3/Q4 KEYS, which are
32
- * the founders' own option values.
33
- *
34
- * Q5 runs STRONGEST-FIRST, deliberately. `projectListingQuestionsSchema` pins
35
- * Q5's values as `urgent | planning | exploring`, which is urgency descending,
36
- * while the positional rule scores index 0 lowest — so the old positional
37
- * encoding scored `urgent` 0 and `exploring` 3, backwards, a standing defect
38
- * recorded in docs/lessons/2026-09-07-q5-fixed-order-is-strongest-first.md.
39
- * Scoring by value is exactly the mechanism that resolves it: the weights
40
- * below name `urgent` 3 and `exploring` 0 explicitly, with no reordering of
41
- * the founder's rendered options and no per-question special case hidden
42
- * inside a positional formula. That lesson's open question is closed here.
43
- * Q6 (`low → critical`) is genuinely weakest-first and keeps 0 → 3.
44
- *
45
- * Q1 (contact), Q2 (segment), Q7 (free text) and the extras carry no points —
46
- * they are absent from `points` entirely, so they contribute 0 by
47
- * construction rather than by a zero weight that could drift.
48
- *
49
- * This module is data + the pure functions that generate it — it imports only
50
- * TYPES from `@working-theory/validation` and introduces no dependency from
51
- * `database/` toward `apps/*` (architecture.yaml's import boundary), exactly
52
- * like `presets.ts` beside it. The rule lives here and only here; the
53
- * projection (`apps/api/src/services/project-listing-flow.ts`) calls
54
- * `buildListingDiagnosticScoring` rather than re-deriving weights, so the
55
- * register and the flow can never disagree about what an answer is worth.
56
- */
57
-
58
- import type {
59
- ProjectListingQuestions,
60
- WaitlistScoring,
61
- } from "@working-theory/validation";
62
-
63
- /** The four scored template questions, in template order. */
64
- export const LISTING_DIAGNOSTIC_SCORED_QUESTIONS = ["q3", "q4", "q5", "q6"] as const;
65
- export type ListingDiagnosticScoredQuestion =
66
- (typeof LISTING_DIAGNOSTIC_SCORED_QUESTIONS)[number];
67
-
68
- /** The highest score any one question can contribute. */
69
- export const LISTING_DIAGNOSTIC_MAX_QUESTION_POINTS = 3;
70
-
71
- /**
72
- * The weight of option `index` (zero-based) of `arity` options —
73
- * `round(3·i/(k−1))`, so the founder's first option always scores 0 and their
74
- * last always scores 3, whatever the arity. This is still how a
75
- * founder-authored question's weights are DERIVED (the founder orders their
76
- * options weakest→strongest); what changed in #5036 D4 is where the result is
77
- * STORED — against the option's value, not its index.
78
- *
79
- * A single-option question (`arity <= 1`) has no spread to score and yields 0;
80
- * the template never produces one, and this guard exists so the expression can
81
- * never divide by zero.
82
- */
83
- export function listingOptionPoints(index: number, arity: number): number {
84
- if (arity <= 1) return 0;
85
- return Math.round((LISTING_DIAGNOSTIC_MAX_QUESTION_POINTS * index) / (arity - 1));
86
- }
87
-
88
- /**
89
- * `optionWeights` for one founder-authored question (Q3/Q4), keyed by the
90
- * founder's own option values and weighted by their declared order.
91
- */
92
- export function listingDiagnosticOptionWeights(
93
- options: readonly { value: string }[],
94
- ): Record<string, number> {
95
- const weights: Record<string, number> = {};
96
- options.forEach((option, index) => {
97
- weights[option.value] = listingOptionPoints(index, options.length);
98
- });
99
- return weights;
100
- }
101
-
102
- /**
103
- * Q5's fixed urgency weights — STRONGEST FIRST, against the positional rule
104
- * and deliberately so (see the file header). `urgent` is the strongest buying
105
- * signal the question can carry and scores 3; `exploring` is the weakest and
106
- * scores 0. The three weights are the same multiset a 3-option positional
107
- * question produces (`{0, 2, 3}`), so the 0–12 total range is unchanged.
108
- */
109
- export const LISTING_DIAGNOSTIC_Q5_WEIGHTS: Readonly<Record<string, number>> = {
110
- urgent: 3,
111
- planning: 2,
112
- exploring: 0,
113
- };
114
-
115
- /**
116
- * Q6's fixed band weights — weakest first, matching the schema's own
117
- * `low → critical` low→high ordering, so these are exactly what the positional
118
- * rule produced for a 4-option question.
119
- */
120
- export const LISTING_DIAGNOSTIC_Q6_WEIGHTS: Readonly<Record<string, number>> = {
121
- low: 0,
122
- medium: 1,
123
- high: 2,
124
- critical: 3,
125
- };
126
-
127
- /** The four tier keys, strongest first — the order `tiers` is evaluated in. */
128
- export const LISTING_DIAGNOSTIC_TIERS = ["now", "soon", "later", "curious"] as const;
129
-
130
- /**
131
- * The inclusive lower bound of each tier over the 0–12 total (4 questions ×
132
- * 3 points): `now` 10–12, `soon` 7–9, `later` 4–6, `curious` 0–3. Ordered
133
- * strongest-first because `evaluateWaitlistScoring` takes the FIRST matching
134
- * tier, so a `gte` ladder read top-down is total and unambiguous.
135
- */
136
- const TIER_FLOORS: Readonly<Record<(typeof LISTING_DIAGNOSTIC_TIERS)[number], number>> = {
137
- now: 10,
138
- soon: 7,
139
- later: 4,
140
- curious: 0,
141
- };
142
-
143
- /**
144
- * Build one listing's register from its own `questions` block. Embedded
145
- * verbatim into that listing's generated `WaitlistExperiment.config` —
146
- * `waitlistExperimentConfigSchema` carries the scoring block by value and
147
- * offers no by-reference slot.
148
- *
149
- * Every listing gets the same point names, the same `total` sum, the same
150
- * tier ladder and the same 0–12 range; only the Q3/Q4 weight KEYS differ,
151
- * because those keys are the founder's own option values (#5036 D4).
152
- */
153
- export function buildListingDiagnosticScoring(
154
- questions: ProjectListingQuestions,
155
- ): WaitlistScoring {
156
- const weights: Record<ListingDiagnosticScoredQuestion, Record<string, number>> = {
157
- q3: listingDiagnosticOptionWeights(questions.q3.options),
158
- q4: listingDiagnosticOptionWeights(questions.q4.options),
159
- q5: { ...LISTING_DIAGNOSTIC_Q5_WEIGHTS },
160
- q6: { ...LISTING_DIAGNOSTIC_Q6_WEIGHTS },
161
- };
162
-
163
- return {
164
- version: 1,
165
- points: LISTING_DIAGNOSTIC_SCORED_QUESTIONS.map((question) => ({
166
- name: `${question}_points`,
167
- question,
168
- kind: "optionWeights" as const,
169
- weights: weights[question],
170
- })),
171
- scores: {
172
- total: {
173
- sum: LISTING_DIAGNOSTIC_SCORED_QUESTIONS.map((q) => `${q}_points`),
174
- },
175
- },
176
- tiers: LISTING_DIAGNOSTIC_TIERS.map((key) => ({
177
- key,
178
- when: { score: "total", gte: TIER_FLOORS[key] },
179
- })),
180
- default: "curious",
181
- };
182
- }