create-ailk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (620) hide show
  1. package/README.md +124 -3
  2. package/component-catalog.md +456 -0
  3. package/dist/cli.js +92 -16
  4. package/dist/component-catalog.d.ts +11 -0
  5. package/dist/component-catalog.js +39 -0
  6. package/dist/copy.d.ts +7 -0
  7. package/dist/copy.js +24 -0
  8. package/dist/derive-architecture.d.ts +13 -0
  9. package/dist/derive-architecture.js +238 -0
  10. package/dist/index.d.ts +7 -2
  11. package/dist/index.js +19 -2
  12. package/dist/lib/extract-module-bundle.d.ts +16 -0
  13. package/dist/lib/extract-module-bundle.js +184 -0
  14. package/dist/lib/fetch-module.d.ts +55 -0
  15. package/dist/lib/fetch-module.js +125 -0
  16. package/dist/lib/module-license-gate.d.ts +48 -0
  17. package/dist/lib/module-license-gate.js +67 -0
  18. package/dist/lib/module-tier.d.ts +35 -0
  19. package/dist/lib/module-tier.js +37 -0
  20. package/dist/module-architecture.d.ts +175 -0
  21. package/dist/module-architecture.js +663 -0
  22. package/dist/parse-args.d.ts +47 -1
  23. package/dist/parse-args.js +143 -2
  24. package/dist/programmatic.d.ts +160 -3
  25. package/dist/programmatic.js +196 -7
  26. package/dist/surfaces.d.ts +211 -0
  27. package/dist/surfaces.js +532 -0
  28. package/dist/sync-routes.d.ts +92 -0
  29. package/dist/sync-routes.js +350 -0
  30. package/package.json +12 -5
  31. package/templates/.claude/rules/architecture.md +6 -2
  32. package/templates/.claude/skills/README.md +9 -9
  33. package/templates/.claude/skills/add-schema/SKILL.md +14 -7
  34. package/templates/.claude/skills/add-schema/references/schema-types.md +109 -6
  35. package/templates/.claude/skills/provision-config/SKILL.md +1 -1
  36. package/templates/.claude/skills/scaffold-commerce/SKILL.md +498 -1
  37. package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +370 -0
  38. package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +376 -0
  39. package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +471 -0
  40. package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +365 -0
  41. package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +60 -0
  42. package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +446 -0
  43. package/templates/.claude/skills/suggest-site-pages/references/categories.md +4 -4
  44. package/templates/.env.example +126 -2
  45. package/templates/CLAUDE.md +11 -5
  46. package/templates/README.md +1 -1
  47. package/templates/apps/api/.env.example +38 -0
  48. package/templates/apps/api/CLAUDE.md +78 -1
  49. package/templates/apps/api/LICENSE +201 -0
  50. package/templates/apps/api/api/index.ts +6 -141
  51. package/templates/apps/api/jest.config.cjs +16 -0
  52. package/templates/apps/api/package.json +22 -6
  53. package/templates/apps/api/src/__tests__/module-exclusion.test.ts +141 -0
  54. package/templates/apps/api/src/__tests__/server.test.ts +46 -0
  55. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +211 -0
  56. package/templates/apps/api/src/bin/abandon-sweep.ts +42 -0
  57. package/templates/apps/api/src/bin/deliverable-resend.ts +144 -0
  58. package/templates/apps/api/src/bin/deliverable-upload.ts +114 -0
  59. package/templates/apps/api/src/bin/followup-sweep.ts +44 -0
  60. package/templates/apps/api/src/bin/listing-csv-sweep.ts +46 -0
  61. package/templates/apps/api/src/bin/seed-presets.ts +58 -0
  62. package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +104 -0
  63. package/templates/apps/api/src/bin/session-retention-sweep.ts +46 -0
  64. package/templates/apps/api/src/cli.ts +5 -11
  65. package/templates/apps/api/src/config/index.ts +35 -0
  66. package/templates/apps/api/src/config/modules.ts +43 -0
  67. package/templates/apps/api/src/lib/__mocks__/prisma-client.js +11 -0
  68. package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -0
  69. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +2 -2
  70. package/templates/apps/api/src/lib/site.ts +16 -0
  71. package/templates/apps/api/src/lib/stripe.ts +22 -0
  72. package/templates/apps/api/src/lib/tenant-db.ts +225 -0
  73. package/templates/apps/api/src/lib/ws-token.ts +91 -0
  74. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +7 -1
  75. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +7 -1
  76. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +91 -4
  77. package/templates/apps/api/src/middleware/auth.ts +43 -8
  78. package/templates/apps/api/src/middleware/rate-limit.ts +78 -3
  79. package/templates/apps/api/src/middleware/tenant.ts +99 -0
  80. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +92 -0
  81. package/templates/apps/api/src/openapi/spec.ts +312 -3
  82. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +175 -0
  83. package/templates/apps/api/src/routes/aeo/index.ts +107 -0
  84. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +5 -2
  85. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +22 -3
  86. package/templates/apps/api/src/routes/auth/tokens.ts +13 -1
  87. package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +450 -0
  88. package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +262 -0
  89. package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +436 -0
  90. package/templates/apps/api/src/routes/billing/index.ts +36 -0
  91. package/templates/apps/api/src/routes/billing/portal.ts +182 -0
  92. package/templates/apps/api/src/routes/billing/read.ts +75 -0
  93. package/templates/apps/api/src/routes/billing/usage.ts +153 -0
  94. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +99 -0
  95. package/templates/apps/api/src/routes/checkout/sessions.ts +20 -8
  96. package/templates/apps/api/src/routes/content/create.ts +1 -0
  97. package/templates/apps/api/src/routes/content/delete.ts +1 -0
  98. package/templates/apps/api/src/routes/content/index.ts +42 -6
  99. package/templates/apps/api/src/routes/content/update.ts +1 -0
  100. package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +393 -0
  101. package/templates/apps/api/src/routes/deliverables/index.ts +200 -0
  102. package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +443 -0
  103. package/templates/apps/api/src/routes/flow-checkouts/index.ts +82 -0
  104. package/templates/apps/api/src/routes/flows/README.md +147 -0
  105. package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +752 -0
  106. package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +671 -0
  107. package/templates/apps/api/src/routes/flows/index.ts +202 -0
  108. package/templates/apps/api/src/routes/flows/recommender.ts +443 -0
  109. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +438 -31
  110. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +10 -10
  111. package/templates/apps/api/src/routes/leads/index.ts +43 -9
  112. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +558 -0
  113. package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +815 -0
  114. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +869 -0
  115. package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +221 -0
  116. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +468 -0
  117. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +424 -0
  118. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +707 -0
  119. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +375 -0
  120. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +467 -0
  121. package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +566 -0
  122. package/templates/apps/api/src/routes/project-listings/get.ts +70 -0
  123. package/templates/apps/api/src/routes/project-listings/index.ts +120 -0
  124. package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
  125. package/templates/apps/api/src/routes/project-listings/me.ts +76 -0
  126. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +222 -0
  127. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +97 -0
  128. package/templates/apps/api/src/routes/project-listings/patch.ts +136 -0
  129. package/templates/apps/api/src/routes/project-listings/public.ts +52 -0
  130. package/templates/apps/api/src/routes/project-listings/respond.ts +37 -0
  131. package/templates/apps/api/src/routes/project-listings/resume-token.ts +22 -0
  132. package/templates/apps/api/src/routes/project-listings/start.ts +106 -0
  133. package/templates/apps/api/src/routes/project-listings/submit.ts +122 -0
  134. package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +490 -0
  135. package/templates/apps/api/src/routes/schedule/index.ts +249 -0
  136. package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +385 -0
  137. package/templates/apps/api/src/routes/slack/actions.ts +177 -0
  138. package/templates/apps/api/src/routes/slack/index.ts +38 -0
  139. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +16 -6
  140. package/templates/apps/api/src/routes/test/auth/session.ts +8 -6
  141. package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +577 -0
  142. package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +78 -0
  143. package/templates/apps/api/src/routes/waitlist-experiments/index.ts +41 -0
  144. package/templates/apps/api/src/routes/waitlist-experiments/list.ts +64 -0
  145. package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +42 -0
  146. package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +84 -0
  147. package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +119 -0
  148. package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +238 -0
  149. package/templates/apps/api/src/routes/waitlist-signups/index.ts +101 -0
  150. package/templates/apps/api/src/routes/webhooks/README.md +35 -12
  151. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +315 -0
  152. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +270 -0
  153. package/templates/apps/api/src/routes/webhooks/stripe.ts +248 -20
  154. package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +356 -0
  155. package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +671 -0
  156. package/templates/apps/api/src/routes/workspaces/config.ts +125 -0
  157. package/templates/apps/api/src/routes/workspaces/index.ts +194 -0
  158. package/templates/apps/api/src/routes/workspaces/sessions.ts +218 -0
  159. package/templates/apps/api/src/server.ts +307 -7
  160. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +489 -0
  161. package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +475 -0
  162. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +132 -0
  163. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +65 -0
  164. package/templates/apps/api/src/services/__tests__/consent.test.ts +282 -0
  165. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +523 -0
  166. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +359 -0
  167. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +142 -0
  168. package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +425 -0
  169. package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +2840 -0
  170. package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +393 -0
  171. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +8 -8
  172. package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +560 -0
  173. package/templates/apps/api/src/services/__tests__/listing-promotion.test.ts +684 -0
  174. package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +406 -0
  175. package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +290 -0
  176. package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +736 -0
  177. package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +475 -0
  178. package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +340 -0
  179. package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +983 -0
  180. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +278 -0
  181. package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +71 -0
  182. package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +379 -0
  183. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +941 -0
  184. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +588 -0
  185. package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +768 -0
  186. package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +1314 -0
  187. package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +341 -0
  188. package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +567 -0
  189. package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +474 -0
  190. package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +354 -0
  191. package/templates/apps/api/src/services/abandon-email.ts +307 -0
  192. package/templates/apps/api/src/services/aeo-score.ts +288 -0
  193. package/templates/apps/api/src/services/answer-distributions.ts +138 -0
  194. package/templates/apps/api/src/services/consent.ts +236 -0
  195. package/templates/apps/api/src/services/deliverable-fulfillment.ts +523 -0
  196. package/templates/apps/api/src/services/entitlements.ts +102 -0
  197. package/templates/apps/api/src/services/flow-aggregate.ts +232 -0
  198. package/templates/apps/api/src/services/flow-checkouts.ts +123 -0
  199. package/templates/apps/api/src/services/flow-engine.ts +1296 -0
  200. package/templates/apps/api/src/services/lead-promotion.ts +176 -0
  201. package/templates/apps/api/src/services/lead-routing.ts +3 -3
  202. package/templates/apps/api/src/services/listing-config.ts +102 -0
  203. package/templates/apps/api/src/services/listing-csv-sweep.ts +455 -0
  204. package/templates/apps/api/src/services/listing-promotion.ts +342 -0
  205. package/templates/apps/api/src/services/playbook-compile.ts +398 -0
  206. package/templates/apps/api/src/services/playbook-render.ts +263 -0
  207. package/templates/apps/api/src/services/project-listing-decision.ts +510 -0
  208. package/templates/apps/api/src/services/project-listing-flow.ts +426 -0
  209. package/templates/apps/api/src/services/project-listing-issue.ts +251 -0
  210. package/templates/apps/api/src/services/project-listings.ts +1472 -0
  211. package/templates/apps/api/src/services/recommender-capture.ts +835 -0
  212. package/templates/apps/api/src/services/scheduling/cal-provider.ts +392 -0
  213. package/templates/apps/api/src/services/scheduling/index.ts +63 -0
  214. package/templates/apps/api/src/services/scheduling/types.ts +88 -0
  215. package/templates/apps/api/src/services/slack-notify.ts +240 -0
  216. package/templates/apps/api/src/services/tenant-context.ts +451 -0
  217. package/templates/apps/api/src/services/usage-aggregation.ts +516 -0
  218. package/templates/apps/api/src/services/usage-credits.ts +340 -0
  219. package/templates/apps/api/src/services/usage-metering.ts +699 -0
  220. package/templates/apps/api/src/services/waitlist-dashboard.ts +947 -0
  221. package/templates/apps/api/src/services/waitlist-experiments.ts +213 -0
  222. package/templates/apps/api/src/services/waitlist-followup.ts +486 -0
  223. package/templates/apps/api/src/services/waitlist-scoring.ts +166 -0
  224. package/templates/apps/api/src/services/waitlist-signups.ts +165 -0
  225. package/templates/apps/api/src/vercel-handler.ts +165 -0
  226. package/templates/apps/api/tsconfig.json +0 -12
  227. package/templates/apps/mcp/CLAUDE.md +19 -9
  228. package/templates/apps/mcp/LICENSE +201 -0
  229. package/templates/apps/mcp/__tests__/create_page.test.ts +1 -0
  230. package/templates/apps/mcp/__tests__/delete_page.test.ts +1 -0
  231. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +105 -0
  232. package/templates/apps/mcp/__tests__/parity.test.ts +70 -6
  233. package/templates/apps/mcp/__tests__/request_callback.test.ts +4 -4
  234. package/templates/apps/mcp/__tests__/schedule_tools.test.ts +242 -0
  235. package/templates/apps/mcp/__tests__/submit_lead.test.ts +4 -4
  236. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +4 -4
  237. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +47 -0
  238. package/templates/apps/mcp/__tests__/update_page.test.ts +1 -0
  239. package/templates/apps/mcp/package.json +6 -4
  240. package/templates/apps/mcp/src/config/modules.ts +37 -0
  241. package/templates/apps/mcp/src/server.ts +109 -18
  242. package/templates/apps/mcp/src/tools/capture_lead.ts +1 -1
  243. package/templates/apps/mcp/src/tools/create_booking.ts +58 -0
  244. package/templates/apps/mcp/src/tools/create_page.ts +1 -0
  245. package/templates/apps/mcp/src/tools/delete_page.ts +1 -0
  246. package/templates/apps/mcp/src/tools/get_event_meta.ts +55 -0
  247. package/templates/apps/mcp/src/tools/get_flow.ts +61 -0
  248. package/templates/apps/mcp/src/tools/index.ts +25 -0
  249. package/templates/apps/mcp/src/tools/list_availability.ts +67 -0
  250. package/templates/apps/mcp/src/tools/purchase.ts +3 -0
  251. package/templates/apps/mcp/src/tools/submit_flow_step.ts +83 -0
  252. package/templates/apps/mcp/src/tools/update_page.ts +1 -0
  253. package/templates/apps/mcp/tsconfig.json +1 -9
  254. package/templates/apps/web/.env.example +44 -0
  255. package/templates/apps/web/CLAUDE.md +28 -0
  256. package/templates/apps/web/LICENSE +201 -0
  257. package/templates/apps/web/__tests__/__mocks__/code-highlight.jest-stub.ts +24 -0
  258. package/templates/apps/web/__tests__/__mocks__/next-intl-server.ts +33 -0
  259. package/templates/apps/web/__tests__/__mocks__/next-intl.ts +18 -0
  260. package/templates/apps/web/__tests__/__mocks__/server-only.ts +13 -0
  261. package/templates/apps/web/__tests__/__mocks__/style-mock.js +4 -0
  262. package/templates/apps/web/__tests__/__mocks__/vercel-analytics-server.ts +9 -0
  263. package/templates/apps/web/__tests__/jest-support/import-meta-transformer.cjs +90 -0
  264. package/templates/apps/web/__tests__/setup.ts +22 -32
  265. package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +6 -3
  266. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +8 -2
  267. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +260 -0
  268. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +263 -0
  269. package/templates/apps/web/app/[locale]/(authed)/account/sign-out-button.tsx +39 -0
  270. package/templates/apps/web/app/[locale]/(authed)/layout.tsx +54 -0
  271. package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +96 -0
  272. package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +309 -0
  273. package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +149 -0
  274. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +273 -0
  275. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/gate.test.tsx +172 -0
  276. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +171 -0
  277. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +179 -0
  278. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +116 -0
  279. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ForbiddenState.tsx +24 -0
  280. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +66 -0
  281. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +61 -0
  282. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +114 -0
  283. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +139 -0
  284. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +85 -0
  285. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +67 -0
  286. package/templates/apps/web/app/[locale]/(authed)/waitlist/format.ts +111 -0
  287. package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +179 -0
  288. package/templates/apps/web/app/[locale]/about/page.tsx +10 -1
  289. package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +6 -1
  290. package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +9 -0
  291. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
  292. package/templates/apps/web/app/[locale]/careers/page.tsx +9 -1
  293. package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +9 -0
  294. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
  295. package/templates/apps/web/app/[locale]/case-studies/page.tsx +13 -1
  296. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +11 -1
  297. package/templates/apps/web/app/[locale]/clients/page.tsx +9 -1
  298. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +21 -1
  299. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +188 -0
  300. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +242 -0
  301. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +29 -0
  302. package/templates/apps/web/app/[locale]/contact/__tests__/intake-analytics.test.ts +51 -0
  303. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +39 -15
  304. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +21 -3
  305. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +49 -0
  306. package/templates/apps/web/app/[locale]/contact/intake-script.ts +66 -0
  307. package/templates/apps/web/app/[locale]/contact/page.tsx +14 -4
  308. package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +13 -1
  309. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
  310. package/templates/apps/web/app/[locale]/courses/page.tsx +9 -1
  311. package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +1 -0
  312. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +11 -1
  313. package/templates/apps/web/app/[locale]/downloads/page.tsx +13 -1
  314. package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +9 -0
  315. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +12 -2
  316. package/templates/apps/web/app/[locale]/events/page.tsx +9 -1
  317. package/templates/apps/web/app/[locale]/faq/page.tsx +10 -1
  318. package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +265 -0
  319. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +445 -0
  320. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +341 -0
  321. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +287 -0
  322. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +302 -0
  323. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +128 -0
  324. package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +254 -0
  325. package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +144 -0
  326. package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +108 -0
  327. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +532 -0
  328. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +121 -0
  329. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +457 -0
  330. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +396 -0
  331. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +114 -0
  332. package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +52 -0
  333. package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +13 -1
  334. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
  335. package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +9 -0
  336. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
  337. package/templates/apps/web/app/[locale]/integrations/page.tsx +13 -1
  338. package/templates/apps/web/app/[locale]/launch-service/page.tsx +14 -1
  339. package/templates/apps/web/app/[locale]/layout.tsx +127 -16
  340. package/templates/apps/web/app/[locale]/page.tsx +10 -1
  341. package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +9 -0
  342. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
  343. package/templates/apps/web/app/[locale]/partners/page.tsx +9 -1
  344. package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +9 -0
  345. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
  346. package/templates/apps/web/app/[locale]/products/page.tsx +9 -1
  347. package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +13 -1
  348. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +10 -0
  349. package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +110 -0
  350. package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +96 -0
  351. package/templates/apps/web/app/[locale]/projects/page.tsx +13 -1
  352. package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +9 -0
  353. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +12 -2
  354. package/templates/apps/web/app/[locale]/resources/page.tsx +13 -1
  355. package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +117 -0
  356. package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +96 -0
  357. package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +92 -0
  358. package/templates/apps/web/app/[locale]/schedule/page.tsx +82 -0
  359. package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +9 -0
  360. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
  361. package/templates/apps/web/app/[locale]/services/page.tsx +9 -1
  362. package/templates/apps/web/app/[locale]/sign-in/__tests__/next-path.test.ts +31 -0
  363. package/templates/apps/web/app/[locale]/sign-in/__tests__/page.test.tsx +152 -0
  364. package/templates/apps/web/app/[locale]/sign-in/next-path.ts +0 -0
  365. package/templates/apps/web/app/[locale]/sign-in/page.tsx +83 -0
  366. package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +123 -0
  367. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +13 -1
  368. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
  369. package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +13 -1
  370. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
  371. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +11 -1
  372. package/templates/apps/web/app/[locale]/testimonials/page.tsx +13 -1
  373. package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +93 -0
  374. package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +48 -0
  375. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +11 -1
  376. package/templates/apps/web/app/[locale]/use-cases/page.tsx +13 -1
  377. package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +13 -1
  378. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
  379. package/templates/apps/web/app/globals.css +35 -0
  380. package/templates/apps/web/app/llms.txt/route.ts +2 -1
  381. package/templates/apps/web/app/og/route.tsx +10 -2
  382. package/templates/apps/web/auth.ts +8 -0
  383. package/templates/apps/web/components/sign-out-trigger.tsx +42 -0
  384. package/templates/apps/web/content/en/blog/README.txt +25 -0
  385. package/templates/apps/web/content/en/docs/index.mdx +28 -0
  386. package/templates/apps/web/jest.config.cjs +90 -27
  387. package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
  388. package/templates/apps/web/lib/__tests__/site-theme.test.ts +112 -0
  389. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +499 -0
  390. package/templates/apps/web/lib/account-config.ts +13 -0
  391. package/templates/apps/web/lib/server-api.ts +85 -0
  392. package/templates/apps/web/lib/site-brand.tsx +121 -0
  393. package/templates/apps/web/lib/site-theme.ts +74 -0
  394. package/templates/apps/web/messages/en.json +275 -7
  395. package/templates/apps/web/middleware.ts +11 -3
  396. package/templates/apps/web/next.config.mjs +8 -2
  397. package/templates/apps/web/package.json +17 -7
  398. package/templates/apps/web/postcss.config.mjs +23 -0
  399. package/templates/apps/web/public/.well-known/security.txt +3 -3
  400. package/templates/apps/web/src/lib/routes.ts +15 -2
  401. package/templates/apps/web/tsconfig.json +1 -16
  402. package/templates/content/_site.mdx +36 -25
  403. package/templates/content/en/AboutPage/about.mdx +24 -14
  404. package/templates/content/en/ContactPage/contact.mdx +23 -14
  405. package/templates/content/en/FAQPage/faq.mdx +10 -392
  406. package/templates/content/en/HomePage/home.mdx +14 -285
  407. package/templates/database/CHANGELOG.md +443 -0
  408. package/templates/database/LICENSE +201 -0
  409. package/templates/database/README.md +3 -1
  410. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +392 -0
  411. package/templates/database/__tests__/flows-presets.test.ts +173 -0
  412. package/templates/database/__tests__/prefixed-ids.db.test.ts +146 -0
  413. package/templates/database/__tests__/seed.test.ts +88 -0
  414. package/templates/database/__tests__/user-cascade.test.ts +19 -4
  415. package/templates/database/auth/schema.prisma +521 -0
  416. package/templates/database/config/schema.prisma +234 -0
  417. package/templates/database/content/schema.prisma +263 -0
  418. package/templates/database/flows/listing-diagnostic.ts +182 -0
  419. package/templates/database/flows/presets.ts +315 -0
  420. package/templates/database/inbox/__tests__/schema.test.ts +4 -0
  421. package/templates/database/inbox/schema.prisma +574 -3
  422. package/templates/database/jest.config.cjs +8 -0
  423. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +201 -0
  424. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +67 -0
  425. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +46 -0
  426. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +25 -0
  427. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +49 -0
  428. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +197 -0
  429. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +32 -0
  430. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +22 -0
  431. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +151 -0
  432. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +223 -0
  433. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +22 -0
  434. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +32 -0
  435. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +40 -0
  436. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +4 -0
  437. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +2 -0
  438. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +2 -0
  439. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +29 -0
  440. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +6 -0
  441. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +39 -0
  442. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +24 -0
  443. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +3 -0
  444. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +33 -0
  445. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +30 -0
  446. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +47 -0
  447. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +16 -0
  448. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +47 -0
  449. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +10 -0
  450. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +26 -0
  451. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +90 -0
  452. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +174 -0
  453. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +14 -0
  454. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +25 -0
  455. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +32 -0
  456. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +71 -0
  457. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +30 -0
  458. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +49 -0
  459. package/templates/database/ops/schema.prisma +27 -0
  460. package/templates/database/package.json +42 -4
  461. package/templates/database/prisma.config.ts +1 -1
  462. package/templates/database/schema.prisma +19 -435
  463. package/templates/database/seed-test.ts +14 -4
  464. package/templates/database/seed.ts +148 -0
  465. package/templates/database/tenancy.ts +45 -0
  466. package/templates/database/tsconfig.flows.json +15 -0
  467. package/templates/database/tsconfig.json +7 -1
  468. package/templates/database/tsconfig.tenancy.json +14 -0
  469. package/templates/package.json +30 -55
  470. package/templates/pnpm-workspace.yaml +0 -3
  471. package/templates/project.yaml +1 -1
  472. package/templates/tsconfig.json +1 -37
  473. package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +0 -94
  474. package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +0 -75
  475. package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +0 -82
  476. package/templates/apps/web/__tests__/auth/env-helpers.test.ts +0 -168
  477. package/templates/apps/web/__tests__/authority-list-routes.test.tsx +0 -208
  478. package/templates/apps/web/__tests__/better-stack.test.ts +0 -66
  479. package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +0 -87
  480. package/templates/apps/web/__tests__/blog-source-populated.test.ts +0 -130
  481. package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +0 -60
  482. package/templates/apps/web/__tests__/google-analytics.test.tsx +0 -104
  483. package/templates/apps/web/__tests__/i18n/middleware.test.ts +0 -119
  484. package/templates/apps/web/__tests__/i18n/routing.test.ts +0 -114
  485. package/templates/apps/web/__tests__/i18n/translations.test.ts +0 -191
  486. package/templates/apps/web/__tests__/json-ld.test.ts +0 -98
  487. package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +0 -580
  488. package/templates/apps/web/__tests__/layout-stealth.test.ts +0 -39
  489. package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +0 -103
  490. package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +0 -114
  491. package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +0 -94
  492. package/templates/apps/web/__tests__/page.test.tsx +0 -230
  493. package/templates/apps/web/__tests__/products-services-phase1.test.tsx +0 -321
  494. package/templates/apps/web/__tests__/projects-routes.test.tsx +0 -392
  495. package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +0 -475
  496. package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +0 -53
  497. package/templates/apps/web/__tests__/routes/blog-route.test.tsx +0 -191
  498. package/templates/apps/web/__tests__/routes/llms-txt.test.ts +0 -123
  499. package/templates/apps/web/__tests__/routes/robots-txt.test.ts +0 -52
  500. package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +0 -78
  501. package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +0 -203
  502. package/templates/apps/web/__tests__/section-routes.test.tsx +0 -693
  503. package/templates/apps/web/__tests__/security-headers.test.ts +0 -201
  504. package/templates/apps/web/__tests__/sentry-config.test.ts +0 -116
  505. package/templates/apps/web/__tests__/sitemap-locales.test.ts +0 -415
  506. package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +0 -844
  507. package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +0 -120
  508. package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +0 -202
  509. package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +0 -152
  510. package/templates/apps/web/content/en/blog/index.mdx +0 -15
  511. package/templates/apps/web/content/en/blog/launching-ailk.mdx +0 -20
  512. package/templates/apps/web/content/en/docs/getting-started.mdx +0 -30
  513. package/templates/content/.gitkeep +0 -0
  514. package/templates/content/CLAUDE.md +0 -85
  515. package/templates/content/ar/HomePage/home.mdx +0 -123
  516. package/templates/content/ar/_site.mdx +0 -35
  517. package/templates/content/de/_site.mdx +0 -29
  518. package/templates/content/en/.gitkeep +0 -0
  519. package/templates/content/en/AboutPage/about.schema.json +0 -82
  520. package/templates/content/en/BookCall/book-call.mdx +0 -19
  521. package/templates/content/en/BookCall/book-call.schema.json +0 -121
  522. package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +0 -20
  523. package/templates/content/en/CareersList/careers.mdx +0 -24
  524. package/templates/content/en/CaseStudiesList/case-studies.mdx +0 -22
  525. package/templates/content/en/CaseStudiesList/showcase.mdx +0 -8
  526. package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +0 -32
  527. package/templates/content/en/CaseStudy/schema-builder-migration.mdx +0 -41
  528. package/templates/content/en/ClientsList/clients.mdx +0 -38
  529. package/templates/content/en/ContactPage/contact.schema.json +0 -100
  530. package/templates/content/en/ContactPoint/primary.mdx +0 -14
  531. package/templates/content/en/Course/aeo-fundamentals.mdx +0 -37
  532. package/templates/content/en/Course/schema-builder-workshop.mdx +0 -62
  533. package/templates/content/en/CoursesList/courses.mdx +0 -22
  534. package/templates/content/en/DownloadsList/downloads.mdx +0 -22
  535. package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +0 -39
  536. package/templates/content/en/Event/ailk-launch-day-2026.mdx +0 -35
  537. package/templates/content/en/EventsList/events.mdx +0 -26
  538. package/templates/content/en/FAQPage/faq.schema.json +0 -231
  539. package/templates/content/en/GlossaryList/glossary.mdx +0 -19
  540. package/templates/content/en/GlossaryList/glossary.schema.json +0 -300
  541. package/templates/content/en/HomePage/home.schema.json +0 -88
  542. package/templates/content/en/HomePage/launch-service.mdx +0 -475
  543. package/templates/content/en/HomePage/launch-service.schema.json +0 -138
  544. package/templates/content/en/HowTo/add-mdx-content.mdx +0 -38
  545. package/templates/content/en/HowTo/configure-aeo-scoring.mdx +0 -35
  546. package/templates/content/en/HowTo/set-up-json-ld.mdx +0 -36
  547. package/templates/content/en/Integration/github-actions.mdx +0 -31
  548. package/templates/content/en/Integration/openai-api.mdx +0 -26
  549. package/templates/content/en/Integration/vercel.mdx +0 -32
  550. package/templates/content/en/IntegrationsList/integrations.mdx +0 -22
  551. package/templates/content/en/JobPosting/content-strategist.mdx +0 -46
  552. package/templates/content/en/JobPosting/developer-advocate.mdx +0 -47
  553. package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +0 -57
  554. package/templates/content/en/LandingPage/aeo-audit.mdx +0 -19
  555. package/templates/content/en/LandingPage/aeo-audit.schema.json +0 -92
  556. package/templates/content/en/LandingPage/agency-waitlist.mdx +0 -340
  557. package/templates/content/en/LandingPage/agency-waitlist.schema.json +0 -152
  558. package/templates/content/en/LandingPage/developers.mdx +0 -19
  559. package/templates/content/en/LandingPage/developers.schema.json +0 -109
  560. package/templates/content/en/LandingPage/for-agencies.mdx +0 -390
  561. package/templates/content/en/LandingPage/for-agencies.schema.json +0 -107
  562. package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +0 -417
  563. package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +0 -105
  564. package/templates/content/en/LandingPage/for-businesses.mdx +0 -19
  565. package/templates/content/en/LandingPage/for-businesses.schema.json +0 -96
  566. package/templates/content/en/LandingPage/platform.mdx +0 -369
  567. package/templates/content/en/LandingPage/platform.schema.json +0 -166
  568. package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +0 -19
  569. package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +0 -102
  570. package/templates/content/en/LandingPage/vs-wordpress.mdx +0 -19
  571. package/templates/content/en/LandingPage/vs-wordpress.schema.json +0 -53
  572. package/templates/content/en/NewsletterSignup/newsletter.mdx +0 -236
  573. package/templates/content/en/NewsletterSignup/newsletter.schema.json +0 -91
  574. package/templates/content/en/Organization/site-owner.mdx +0 -16
  575. package/templates/content/en/Partner/prisma.mdx +0 -31
  576. package/templates/content/en/Partner/supabase.mdx +0 -30
  577. package/templates/content/en/Partner/vercel.mdx +0 -28
  578. package/templates/content/en/PartnersList/partners.mdx +0 -22
  579. package/templates/content/en/Person/founder.mdx +0 -18
  580. package/templates/content/en/Pricing/pricing.mdx +0 -538
  581. package/templates/content/en/Pricing/pricing.schema.json +0 -209
  582. package/templates/content/en/PrivacyPage/privacy.mdx +0 -165
  583. package/templates/content/en/PrivacyPage/privacy.schema.json +0 -64
  584. package/templates/content/en/Product/ailk.mdx +0 -19
  585. package/templates/content/en/Product/ailk.schema.json +0 -94
  586. package/templates/content/en/Product/api-launch-kit.mdx +0 -26
  587. package/templates/content/en/Product/launch-kit.mdx +0 -28
  588. package/templates/content/en/ProductsList/products.mdx +0 -26
  589. package/templates/content/en/Project/ailk-phase-2.mdx +0 -54
  590. package/templates/content/en/ProjectsList/projects.mdx +0 -25
  591. package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +0 -27
  592. package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +0 -28
  593. package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +0 -39
  594. package/templates/content/en/ResourcesHub/resources.mdx +0 -22
  595. package/templates/content/en/Service/consulting.mdx +0 -22
  596. package/templates/content/en/Service/implementation.mdx +0 -30
  597. package/templates/content/en/Service/launch-service.mdx +0 -232
  598. package/templates/content/en/Service/launch.mdx +0 -228
  599. package/templates/content/en/ServicesList/services.mdx +0 -84
  600. package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +0 -44
  601. package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +0 -47
  602. package/templates/content/en/SoftwareProduct/ailk-schema.mdx +0 -49
  603. package/templates/content/en/TeamList/team.mdx +0 -63
  604. package/templates/content/en/TeamMember/founder.mdx +0 -72
  605. package/templates/content/en/TermsPage/terms.mdx +0 -19
  606. package/templates/content/en/TermsPage/terms.schema.json +0 -99
  607. package/templates/content/en/TestimonialsList/testimonials.mdx +0 -44
  608. package/templates/content/en/UseCasesList/use-cases.mdx +0 -30
  609. package/templates/content/en/Whitepaper/ax-first-product-development.mdx +0 -27
  610. package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +0 -27
  611. package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +0 -31
  612. package/templates/content/en-XA/AboutPage/about.mdx +0 -8
  613. package/templates/content/en-XA/FAQPage/faq.mdx +0 -8
  614. package/templates/content/en-XA/HomePage/home.mdx +0 -8
  615. package/templates/content/es/_site.mdx +0 -30
  616. package/templates/content/fr/_site.mdx +0 -30
  617. package/templates/content/ja/_site.mdx +0 -30
  618. package/templates/content/pt-BR/AboutPage/about.mdx +0 -8
  619. package/templates/content/pt-BR/FAQPage/faq.mdx +0 -8
  620. package/templates/content/pt-BR/HomePage/home.mdx +0 -23
@@ -0,0 +1,49 @@
1
+ -- The verified owner link on `project_listings` (#5295).
2
+ --
3
+ -- A listing carried `founder_email` and `lead_id` and no user link, so there
4
+ -- was no query for "the listings belonging to this signed-in person". The only
5
+ -- join available was a session's email against `founder_email` — and
6
+ -- `founder_email` is an UNVERIFIED string typed into an anonymous form, so that
7
+ -- join hands a stranger someone else's submission the first time two people
8
+ -- type the same address. These two columns are the ownership claim instead.
9
+ --
10
+ -- Plain scalars, no foreign key into `users`: ADR 0009 invariant #1 forbids a
11
+ -- relation across the namespace boundary, and `leads.promoted_user_id` /
12
+ -- `promoted_at` (20260714000000_add_lead_promotion_fields) are the same shape
13
+ -- for the same reason. The join is stable-id matching in the service layer.
14
+ --
15
+ -- `apps/api/src/services/listing-promotion.ts` is the sole writer, and it sets
16
+ -- the pair only when all three of these hold:
17
+ -- 1. the reconciling user's OWN email is verified (`users.email_verified`) —
18
+ -- never a claimed or session-asserted address;
19
+ -- 2. that verified address matches the row's `founder_email`;
20
+ -- 3. the row's `site_id` is one of that user's own tenant workspaces.
21
+ -- Any one failing writes nothing.
22
+ --
23
+ -- NO BACKFILL, deliberately and permanently. Every existing row predates
24
+ -- verification, so deriving `owner_user_id` from `founder_email` here would
25
+ -- assert exactly the link nobody proved — the bug the column exists to remove.
26
+ -- Existing rows stay null, and a listing submitted by someone who never signs
27
+ -- in stays null for the life of the row: that is a legitimate resting state,
28
+ -- not a backlog to clean up.
29
+ --
30
+ -- The index backs the self-scoped read's whole WHERE clause
31
+ -- (`GET /v1/project-listings/me` — `owner_user_id = $1`, and nothing else: the
32
+ -- owner link IS the scope, so no site term joins it). Single-column by design —
33
+ -- the promotion match (`founder_email` + `site_id` + a null owner) is already
34
+ -- served by the existing (site_id, founder_email) index.
35
+ --
36
+ -- Forward-additive only: both columns are nullable with no default, so every
37
+ -- existing read and write is unaffected.
38
+ --
39
+ -- Rollback:
40
+ -- DROP INDEX "project_listings_owner_user_id_idx";
41
+ -- ALTER TABLE "project_listings" DROP COLUMN "owner_linked_at";
42
+ -- ALTER TABLE "project_listings" DROP COLUMN "owner_user_id";
43
+
44
+ -- AlterTable
45
+ ALTER TABLE "project_listings" ADD COLUMN "owner_user_id" TEXT,
46
+ ADD COLUMN "owner_linked_at" TIMESTAMP(3);
47
+
48
+ -- CreateIndex
49
+ CREATE INDEX "project_listings_owner_user_id_idx" ON "project_listings"("owner_user_id");
@@ -0,0 +1,27 @@
1
+ // ops namespace — AEO scores, audit log, analytics/telemetry (ADR-0009).
2
+ //
3
+ // Generator + datasource live in database/schema.prisma (the folder's single
4
+ // config file); this file holds only model definitions.
5
+ //
6
+ // TelemetryRecord (vendor seat-usage telemetry) moved out of this namespace to
7
+ // apps-paid/license-issuer/prisma/schema.prisma — the vendor service is the
8
+ // table's sole writer and nothing in the product schema reads it, so it is a
9
+ // vendor-owned concern rather than a product-schema model. See
10
+ // docs/internal/proposals/agentic-services-control-plane-proposal.md.
11
+
12
+ /// AuditLog — workspace-scoped "who did what, when" audit trail (queryable + retained).
13
+ model AuditLog {
14
+ id String @id @default(dbgenerated("('audit_'::text || (uuidv7())::text)")) @db.Text
15
+ workspaceId String @map("workspace_id") // tenant scope — stable-id ref, NO @relation (ADR-0009)
16
+ actorId String @map("actor_id") // who acted (a User / agent / system id) — stable-id ref
17
+ actorType String @map("actor_type") // "user" | "agent" | "system"
18
+ action String // e.g. "workspace.settings.updated", "lead.deleted"
19
+ targetType String? @map("target_type") // what was acted on: "workspace" | "lead" | "user" | …
20
+ targetId String? @map("target_id") // stable-id ref to the target (nullable)
21
+ metadata Json? // structured detail (before/after, request context)
22
+ createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
23
+
24
+ @@index([workspaceId, createdAt(sort: Desc)])
25
+ @@index([workspaceId, targetType, targetId])
26
+ @@map("audit_logs")
27
+ }
@@ -1,6 +1,23 @@
1
1
  {
2
2
  "name": "@working-theory/database",
3
- "version": "0.1.2",
3
+ "version": "0.20.0",
4
+ "license": "Apache-2.0",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "schema.prisma",
11
+ "migrations",
12
+ "config",
13
+ "content",
14
+ "flows",
15
+ "auth",
16
+ "inbox",
17
+ "ops",
18
+ "tenancy.ts",
19
+ "prisma.config.ts"
20
+ ],
4
21
  "description": "AI Launch Kit database schema (single-tenant Prisma)",
5
22
  "type": "module",
6
23
  "main": "./dist/client/client.js",
@@ -15,28 +32,49 @@
15
32
  "types": "./dist/client/client.d.ts",
16
33
  "import": "./dist/client/client.js",
17
34
  "default": "./dist/client/client.js"
35
+ },
36
+ "./tenancy": {
37
+ "types": "./dist/tenancy.d.ts",
38
+ "import": "./dist/tenancy.js",
39
+ "default": "./dist/tenancy.js"
40
+ },
41
+ "./flows/presets": {
42
+ "types": "./dist/flows/presets.d.ts",
43
+ "import": "./dist/flows/presets.js",
44
+ "default": "./dist/flows/presets.js"
45
+ },
46
+ "./flows/listing-diagnostic": {
47
+ "types": "./dist/flows/listing-diagnostic.d.ts",
48
+ "import": "./dist/flows/listing-diagnostic.js",
49
+ "default": "./dist/flows/listing-diagnostic.js"
18
50
  }
19
51
  },
20
52
  "scripts": {
21
- "build": "tsc -b tsconfig.build.json",
53
+ "lint": "tsx ../scripts/lint-package.ts",
54
+ "build": "tsc -b tsconfig.build.json && tsc -b tsconfig.tenancy.json && tsc -b tsconfig.flows.json",
22
55
  "db:generate": "prisma generate && pnpm run build",
23
56
  "db:migrate": "prisma migrate dev",
24
57
  "db:migrate:deploy": "prisma migrate deploy",
25
58
  "db:push": "prisma db push",
26
- "db:seed": "prisma db seed",
59
+ "db:seed": "tsx seed.ts",
27
60
  "db:seed:test": "tsx seed-test.ts",
28
61
  "db:studio": "prisma studio",
29
62
  "test": "jest --config jest.config.cjs",
30
63
  "test:watch": "jest --config jest.config.cjs --watch"
31
64
  },
32
65
  "dependencies": {
33
- "@prisma/client": "^7.8.0"
66
+ "@prisma/adapter-pg": "^7.8.0",
67
+ "@prisma/client": "^7.8.0",
68
+ "@working-theory/ids": "workspace:*",
69
+ "@working-theory/validation": "workspace:*"
34
70
  },
35
71
  "devDependencies": {
36
72
  "@types/jest": "^30.0.0",
37
73
  "@types/node": "^22.20.0",
74
+ "@types/pg": "^8.20.0",
38
75
  "dotenv": "^17.4.2",
39
76
  "jest": "^30.4.2",
77
+ "pg": "^8.22.0",
40
78
  "prisma": "^7.8.0",
41
79
  "ts-jest": "^29.4.11",
42
80
  "tsx": "^4.22.4",
@@ -13,7 +13,7 @@ import "dotenv/config";
13
13
  import { defineConfig } from "prisma/config";
14
14
 
15
15
  export default defineConfig({
16
- schema: "./schema.prisma",
16
+ schema: ".",
17
17
  datasource: {
18
18
  url: process.env.DATABASE_URL_NON_POOLED,
19
19
  },
@@ -3,19 +3,12 @@
3
3
  // MINIMAL BUT EXTENSIBLE - Only stores auth and customer extensions
4
4
  // All business data (leads, orders, analytics) lives on the Platform
5
5
  //
6
- // Tables (14 total 11 auth/config + 3 inbox added in B1):
7
- // - Better Auth (4): User, Session, Account, Verification (post-#587)
8
- // - API Auth (2): ApiToken, RefreshToken
9
- // - OAuth (2): OAuthClient, OAuthAuthorization
10
- // - Push (1): PushToken
11
- // - Extensions (2): UserData, SiteSetting
12
- // - Inbox (3): Lead, Subscriber, Callback [namespace: database/inbox/]
13
- //
14
- // Aggregation strategy: Namespace-local schema files (e.g. database/inbox/schema.prisma)
15
- // define models canonically for lint and documentation. Those same models are
16
- // registered here so Prisma can generate from the single root schema.prisma.
17
- // Phase 2 (ADR 0009 D4) will migrate to prismaSchemaFolder once multi-file
18
- // generation is adopted repo-wide.
6
+ // Schema layout: prismaSchemaFolder (ADR 0009 D4 Phase 2, #3607). Prisma reads
7
+ // the whole database/ folder each model is defined ONCE in its namespace file
8
+ // (database/{auth,config,ops,inbox,content}/schema.prisma). This file holds ONLY
9
+ // the single generator + datasource blocks — it is model-free (#3607 AC-1). The
10
+ // former per-User site-config models (TenantTheme/TenantSiteIdentity/TenantSEO)
11
+ // were re-anchored to the config namespace keyed on workspaceId (#3641).
19
12
 
20
13
  generator client {
21
14
  provider = "prisma-client"
@@ -27,327 +20,26 @@ datasource db {
27
20
  provider = "postgresql"
28
21
  }
29
22
 
30
- // ============================================================================
31
- // Better Auth Models (Web Dashboard Authentication — #587)
32
- // ============================================================================
33
-
34
- /// User - Dashboard users (site owners, admins, end-users)
35
- ///
36
- /// emailVerified is a Boolean per Better Auth's contract (NextAuth previously
37
- /// stored the verification timestamp as DateTime?). The five custom relations
38
- /// — ApiToken, RefreshToken, OAuthAuthorization, PushToken, UserData — keep
39
- /// their onDelete: Cascade semantics so user removal cleanly tears down all
40
- /// dependent rows.
41
- model User {
42
- id String @id @default(cuid())
43
- email String @unique
44
- name String?
45
- image String?
46
- emailVerified Boolean @default(false) @map("email_verified")
47
-
48
- // Profile extensions
49
- role String @default("user") // "user", "admin", "owner"
50
-
51
- // Billing identity — provider-agnostic so Stripe is v1 value, not baked-in name.
52
- // Webhook is the only writer (see apps/api/src/routes/webhooks/stripe.ts).
53
- // #771 self-serve dashboard reads billingCustomerId for Stripe customer-portal URL.
54
- billingProvider String? @map("billing_provider") // "stripe"; future: "lemonsqueezy", "paddle"
55
- billingCustomerId String? @map("billing_customer_id") // cus_xxx (Stripe) or equivalent
56
-
57
- // Subscription tier projection — derived from the Stripe webhook's product-aware
58
- // routing (#898). Defaults to "free" until a customer.subscription.created event
59
- // fires; flips to "pro" / "pro_plus" / etc. based on the line item's product.
60
- // hasCarePlan is true only for pro_plus today; seatCount mirrors the line item
61
- // quantity from Stripe's adjustable-quantity widget (1–50).
62
- tier String @default("free") // "free" | "pro" | "pro_plus" | "enterprise" (retired "agency"/"commercial" rows migrated to "enterprise" — #3516)
63
- hasCarePlan Boolean @default(false) @map("has_care_plan")
64
- seatCount Int @default(1) @map("seat_count")
65
-
66
- createdAt DateTime @default(now()) @map("created_at")
67
- updatedAt DateTime @updatedAt @map("updated_at")
68
-
69
- // Better Auth relations
70
- sessions Session[]
71
- accounts Account[]
72
-
73
- // API & OAuth
74
- apiTokens ApiToken[]
75
- refreshTokens RefreshToken[]
76
- oauthAuthorizations OAuthAuthorization[]
77
- pushTokens PushToken[]
78
-
79
- // Extensions
80
- userData UserData[]
81
-
82
- // Theme Wiring (TWP3-MAT #1359)
83
- tenantTheme TenantTheme?
84
- tenantSiteIdentity TenantSiteIdentity?
85
- tenantSeo TenantSEO?
86
-
87
- @@unique([billingProvider, billingCustomerId])
88
- @@map("users")
89
- }
90
-
91
- /// Session - Active user sessions (Better Auth schema)
92
- ///
93
- /// Session.token is the opaque cookie value the dual-mode preHandler reads.
94
- /// Deleting a row revokes the session; deleting the parent User cascades.
95
- model Session {
96
- id String @id
97
- expiresAt DateTime @map("expires_at")
98
- token String @unique
99
- createdAt DateTime @default(now()) @map("created_at")
100
- updatedAt DateTime @updatedAt @map("updated_at")
101
- ipAddress String? @map("ip_address")
102
- userAgent String? @map("user_agent")
103
- userId String @map("user_id")
104
-
105
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
106
-
107
- @@index([userId])
108
- @@index([token])
109
- @@map("sessions")
110
- }
111
-
112
- /// Account - OAuth provider connections (Google, GitHub, etc.)
113
- ///
114
- /// Better Auth's account shape: one row per (providerId, accountId) pair.
115
- /// Cascade on User removal keeps OAuth links from orphaning.
116
- model Account {
117
- id String @id
118
- accountId String @map("account_id")
119
- providerId String @map("provider_id")
120
- userId String @map("user_id")
121
- accessToken String? @map("access_token") @db.Text
122
- refreshToken String? @map("refresh_token") @db.Text
123
- idToken String? @map("id_token") @db.Text
124
- accessTokenExpiresAt DateTime? @map("access_token_expires_at")
125
- refreshTokenExpiresAt DateTime? @map("refresh_token_expires_at")
126
- scope String?
127
- password String?
128
- createdAt DateTime @default(now()) @map("created_at")
129
- updatedAt DateTime @updatedAt @map("updated_at")
130
-
131
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
132
-
133
- @@unique([providerId, accountId])
134
- @@index([userId])
135
- @@map("accounts")
136
- }
137
-
138
- /// Verification - Email / magic-link verification tokens (Better Auth schema)
139
- model Verification {
140
- id String @id
141
- identifier String
142
- value String
143
- expiresAt DateTime @map("expires_at")
144
- createdAt DateTime @default(now()) @map("created_at")
145
- updatedAt DateTime @updatedAt @map("updated_at")
146
-
147
- @@index([identifier])
148
- @@map("verifications")
149
- }
150
-
151
23
  // ============================================================================
152
24
  // API Token Authentication (Mobile Apps, CLI, External Clients)
153
25
  // ============================================================================
154
26
 
155
- /// ApiToken - Bearer tokens for non-web clients (mobile apps, API integrations)
156
- model ApiToken {
157
- id String @id @default(cuid())
158
- userId String @map("user_id")
159
-
160
- // Token identification
161
- name String // "iPhone", "Android App", "API Integration"
162
- token String @unique // Hashed token
163
- tokenPrefix String @map("token_prefix") // First 8 chars for identification
164
-
165
- // Client info
166
- clientType String @default("api") @map("client_type") // "mobile", "api", "cli"
167
- deviceInfo String? @map("device_info") // "iPhone 15 Pro", "Android 14"
168
-
169
- // Permissions
170
- scopes String[] @default([]) // ["read:profile", "write:data"]
171
-
172
- // Lifecycle
173
- expiresAt DateTime? @map("expires_at")
174
- lastUsedAt DateTime? @map("last_used_at")
175
- lastUsedIp String? @map("last_used_ip")
176
- revokedAt DateTime? @map("revoked_at")
177
-
178
- createdAt DateTime @default(now()) @map("created_at")
179
-
180
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
181
- refreshTokens RefreshToken[]
182
-
183
- @@index([userId])
184
- @@index([token])
185
- @@index([tokenPrefix])
186
- @@map("api_tokens")
187
- }
188
-
189
- /// RefreshToken - Long-lived tokens for mobile session refresh
190
- model RefreshToken {
191
- id String @id @default(cuid())
192
- userId String @map("user_id")
193
- apiTokenId String @map("api_token_id")
194
-
195
- token String @unique // Hashed
196
-
197
- // Lifecycle
198
- expiresAt DateTime @map("expires_at")
199
- usedAt DateTime? @map("used_at") // Last time used to get new access token
200
- revokedAt DateTime? @map("revoked_at")
201
-
202
- createdAt DateTime @default(now()) @map("created_at")
203
-
204
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
205
- apiToken ApiToken @relation(fields: [apiTokenId], references: [id], onDelete: Cascade)
206
-
207
- @@index([userId])
208
- @@index([apiTokenId])
209
- @@index([token])
210
- @@map("refresh_tokens")
211
- }
212
-
213
27
  // ============================================================================
214
28
  // OAuth 2.0 (ChatGPT Plugin, Slack Bot, External Integrations)
215
29
  // ============================================================================
216
30
 
217
- /// OAuthClient - Registered OAuth applications (ChatGPT, Slack, etc.)
218
- model OAuthClient {
219
- id String @id @default(cuid())
220
-
221
- // Client identification
222
- name String // "ChatGPT Plugin", "Slack Bot"
223
- description String?
224
- logoUrl String? @map("logo_url")
225
-
226
- // OAuth credentials
227
- clientId String @unique @map("client_id") // Public identifier
228
- clientSecret String @map("client_secret") // Hashed secret
229
-
230
- // OAuth config
231
- redirectUris String[] @map("redirect_uris") // Allowed callback URLs
232
- scopes String[] @default([]) // Allowed scopes
233
-
234
- // Settings
235
- enabled Boolean @default(true)
236
- trusted Boolean @default(false) // Skip consent screen
237
-
238
- createdAt DateTime @default(now()) @map("created_at")
239
- updatedAt DateTime @updatedAt @map("updated_at")
240
-
241
- authorizations OAuthAuthorization[]
242
-
243
- @@map("oauth_clients")
244
- }
245
-
246
- /// OAuthAuthorization - User grants to OAuth clients
247
- model OAuthAuthorization {
248
- id String @id @default(cuid())
249
- userId String @map("user_id")
250
- clientId String @map("client_id")
251
-
252
- // Granted scopes (may be subset of client's allowed scopes)
253
- scopes String[]
254
-
255
- // Tokens
256
- accessToken String @unique @map("access_token") // Hashed
257
- refreshToken String? @unique @map("refresh_token") // Hashed
258
-
259
- // Lifecycle
260
- expiresAt DateTime @map("expires_at")
261
- revokedAt DateTime? @map("revoked_at")
262
-
263
- createdAt DateTime @default(now()) @map("created_at")
264
- updatedAt DateTime @updatedAt @map("updated_at")
265
-
266
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
267
- client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
268
-
269
- @@unique([userId, clientId])
270
- @@index([userId])
271
- @@index([clientId])
272
- @@index([accessToken])
273
- @@map("oauth_authorizations")
274
- }
275
-
276
31
  // ============================================================================
277
32
  // Push Notifications (Mobile Apps, Web Push)
278
33
  // ============================================================================
279
34
 
280
- /// PushToken - Device tokens for push notifications
281
- model PushToken {
282
- id String @id @default(cuid())
283
- userId String @map("user_id")
284
-
285
- // Token details
286
- token String @unique // FCM or APNs token
287
- platform String // "ios", "android", "web"
288
-
289
- // Device info
290
- deviceId String? @map("device_id") // Unique device identifier
291
- deviceName String? @map("device_name") // "iPhone 15 Pro"
292
- appVersion String? @map("app_version") // "1.2.3"
293
-
294
- // Status
295
- enabled Boolean @default(true)
296
- failedAt DateTime? @map("failed_at") // Last delivery failure
297
- failCount Int @default(0) @map("fail_count")
298
-
299
- createdAt DateTime @default(now()) @map("created_at")
300
- updatedAt DateTime @updatedAt @map("updated_at")
301
-
302
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
303
-
304
- @@index([userId])
305
- @@index([platform])
306
- @@map("push_tokens")
307
- }
308
-
309
35
  // ============================================================================
310
36
  // User Data Extensions (Customer Customizations)
311
37
  // ============================================================================
312
38
 
313
- /// UserData - Flexible key-value storage for customer extensions
314
- /// Use this for: preferences, saved items, custom fields, feature flags
315
- model UserData {
316
- id String @id @default(cuid())
317
- userId String @map("user_id")
318
-
319
- // Key-value storage
320
- key String // "preferences", "saved_products", "notification_settings"
321
- value Json // Flexible JSON storage
322
-
323
- createdAt DateTime @default(now()) @map("created_at")
324
- updatedAt DateTime @updatedAt @map("updated_at")
325
-
326
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
327
-
328
- @@unique([userId, key])
329
- @@index([userId])
330
- @@index([key])
331
- @@map("user_data")
332
- }
333
-
334
39
  // ============================================================================
335
40
  // Site Settings (Site-wide Configuration)
336
41
  // ============================================================================
337
42
 
338
- /// SiteSetting - Key-value settings for the customer site
339
- /// Use for: feature flags, custom config, cached Platform data
340
- model SiteSetting {
341
- id String @id @default(cuid())
342
- key String @unique // "feature_flags", "cached_config", "custom_theme"
343
- value Json
344
-
345
- createdAt DateTime @default(now()) @map("created_at")
346
- updatedAt DateTime @updatedAt @map("updated_at")
347
-
348
- @@map("site_settings")
349
- }
350
-
351
43
  // ============================================================================
352
44
  // Inbox Namespace (database/inbox/schema.prisma — B1)
353
45
  //
@@ -356,132 +48,24 @@ model SiteSetting {
356
48
  // through apps/api/src/services/ (D3).
357
49
  // ============================================================================
358
50
 
359
- /// Lead - anonymous lead submission (Phase B submit_lead tool / B6 route)
360
- model Lead {
361
- id String @id @default(cuid())
362
- siteId String @map("site_id")
363
- source String
364
- email String
365
- payload Json
366
- createdAt DateTime @default(now()) @map("created_at")
367
-
368
- @@index([siteId])
369
- @@index([createdAt])
370
- @@map("leads")
371
- }
372
-
373
- /// Subscriber - newsletter subscription (Phase B subscribe_newsletter tool / B6 route)
374
- model Subscriber {
375
- id String @id @default(cuid())
376
- siteId String @map("site_id")
377
- email String
378
- source String
379
- createdAt DateTime @default(now()) @map("created_at")
380
-
381
- @@unique([siteId, email])
382
- @@index([siteId])
383
- @@map("subscribers")
384
- }
385
-
386
- /// Callback - callback request (Phase B request_callback tool / B6 route)
387
- model Callback {
388
- id String @id @default(cuid())
389
- siteId String @map("site_id")
390
- name String
391
- phone String
392
- preferredTime String? @map("preferred_time")
393
- payload Json
394
- createdAt DateTime @default(now()) @map("created_at")
395
-
396
- @@index([siteId])
397
- @@index([createdAt])
398
- @@map("callbacks")
399
- }
400
-
401
51
  // ============================================================================
402
- // License Telemetry (apps-paid/license-issuerS2 #1031)
52
+ // Tenancy multi-tenant module (database/auth/schema.prismaFEAT-042)
403
53
  //
404
- // Time-series records of opt-in seat-usage telemetry from customer deployments.
405
- // Written by POST /telemetry on the license-issuer when AILK_TELEMETRY=1.
406
- // Enables queries computing the distribution of active_user_count / seat_count
407
- // across the customer base over a time window (S2 trigger condition monitoring).
408
- //
409
- // No PII beyond customer_id (Stripe customer ID — pseudo-anonymous).
54
+ // Organization Workspace Membership. Same-namespace @relation to User is
55
+ // allowed (auth namespace: identity + tenancy membership per ADR 0009).
56
+ // Organization/Membership/Invitation are managed by the Better Auth
57
+ // organization plugin (apps/workspace auth config); Workspace is AILK's own
58
+ // model (plugin teams feature rejected — per-team membership contradicts
59
+ // org-level membership; see docs/research/ploy-capture/lessons/).
410
60
  // ============================================================================
411
61
 
412
- /// TelemetryRecord - opt-in seat-usage telemetry from customer deployments.
413
- ///
414
- /// timestamp is the client-side observation time (from the telemetry payload).
415
- /// recordedAt is the server-side receipt time (default now()).
416
- /// The (customerId, recordedAt DESC) index supports "latest record per customer"
417
- /// queries; the recordedAt DESC index supports time-window aggregate queries.
418
- model TelemetryRecord {
419
- id String @id @default(cuid())
420
- customerId String @map("customer_id")
421
- activeUserCount Int @map("active_user_count")
422
- seatCount Int @map("seat_count")
423
- timestamp DateTime
424
- recordedAt DateTime @default(now()) @map("recorded_at")
425
-
426
- @@index([customerId, recordedAt(sort: Desc)])
427
- @@index([recordedAt(sort: Desc)])
428
- @@map("telemetry_records")
429
- }
430
-
431
62
  // ============================================================================
432
- // Theme Wiring — Per-tenant design system persistence (TWP3-MAT #1359)
433
- //
434
- // Three tables, one per @working-theory/site-config schema. Each row stores the
435
- // Zod-validated JSON blob for a single tenant (identified by userId from the
436
- // Better Auth session). Validation is enforced at the API layer; the DB stores
437
- // the already-validated blob in a Json column.
63
+ // Chat/Artifact substrate (database/content/schema.prisma)
438
64
  //
439
- // Design decisions (spec §3):
440
- // - One table per schema (not a polymorphic config table) — different update
441
- // cadences + consumer access patterns.
442
- // - Json column for the blob schema evolves without DB migration on change;
443
- // Zod validates at API boundary.
444
- // - userId is the Better Auth User id — plain String FK; onDelete Cascade
445
- // ensures rows are removed when the user account is deleted.
446
- // - @@unique([userId]) enforces one active record per tenant per config type
447
- // (upsert semantics at the API layer).
65
+ // Event-sourced conversation transport + artifact persistence per
66
+ // docs/research/ploy-capture/BACKEND-REQUIREMENTS.md. Every table carries a
67
+ // non-null workspaceId tenant scope as a plain String — no cross-namespace
68
+ // FK into auth (ADR 0009 invariant 1). Cross-namespace assembly (tenant
69
+ // guard, unread counts per user) routes through apps/api/src/services/.
448
70
  // ============================================================================
449
71
 
450
- /// TenantTheme — per-tenant ThemeSchema blob (TWP3-MAT #1359)
451
- model TenantTheme {
452
- id String @id @default(cuid())
453
- userId String @unique @map("user_id")
454
- data Json
455
- createdAt DateTime @default(now()) @map("created_at")
456
- updatedAt DateTime @updatedAt @map("updated_at")
457
-
458
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
459
-
460
- @@map("tenant_themes")
461
- }
462
-
463
- /// TenantSiteIdentity — per-tenant SiteIdentitySchema blob (TWP3-MAT #1359)
464
- model TenantSiteIdentity {
465
- id String @id @default(cuid())
466
- userId String @unique @map("user_id")
467
- data Json
468
- createdAt DateTime @default(now()) @map("created_at")
469
- updatedAt DateTime @updatedAt @map("updated_at")
470
-
471
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
472
-
473
- @@map("tenant_site_identities")
474
- }
475
-
476
- /// TenantSEO — per-tenant SEOSchema blob (TWP3-MAT #1359)
477
- model TenantSEO {
478
- id String @id @default(cuid())
479
- userId String @unique @map("user_id")
480
- data Json
481
- createdAt DateTime @default(now()) @map("created_at")
482
- updatedAt DateTime @updatedAt @map("updated_at")
483
-
484
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
485
-
486
- @@map("tenant_seos")
487
- }