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,521 @@
1
+ // auth namespace — tenancy models (Organization, Workspace, Membership, Invitation)
2
+ //
3
+ // The multi-tenant module's Organization → Workspace → Membership layer
4
+ // (FEAT-042). Per ADR 0009, the auth namespace's charter is identity + tenancy
5
+ // membership, so these live beside User/Session — @relation to User is allowed
6
+ // here (same namespace).
7
+ //
8
+ // Organization is the tenant boundary (members, billing, security key on
9
+ // organizationId). Workspace is the working context (operational config + all
10
+ // domain content key on workspaceId). Membership is org-level; workspace
11
+ // visibility follows org membership (per-workspace ACL is a future additive
12
+ // concern — do not add a workspace-member table without a new design pass).
13
+ //
14
+ // Organization / Membership / Invitation are managed by the Better Auth
15
+ // organization plugin (apps/workspace auth config maps member → Membership via
16
+ // modelName). Workspace is AILK's own model: the plugin's teams feature was
17
+ // evaluated and rejected because setActiveTeam requires per-team membership
18
+ // rows, contradicting org-level membership (see
19
+ // docs/research/ploy-capture/lessons/better-auth-teams-rejected-for-workspaces.md).
20
+ //
21
+ // Generator + datasource blocks live in database/schema.prisma (the root schema
22
+ // file). This file holds only model definitions for the auth-namespace tenancy
23
+ // tables; the same models are registered in the root schema for generation.
24
+
25
+ /// Role — membership role within an Organization. Hierarchy: owner > admin > member.
26
+ /// Values are lowercase to match the Better Auth organization plugin's role
27
+ /// strings ("owner" | "admin" | "member") so plugin writes pass Prisma enum
28
+ /// validation unmapped. Distinct from User.role (a per-deployment String).
29
+ enum Role {
30
+ owner
31
+ admin
32
+ member
33
+ }
34
+
35
+ /// Organization — the tenant boundary. Owns membership, billing, security.
36
+ model Organization {
37
+ id String @id @default(dbgenerated("('org_'::text || (uuidv7())::text)")) @db.Text
38
+ name String
39
+ slug String @unique
40
+ logo String?
41
+ metadata String?
42
+ createdAt DateTime @default(now()) @map("created_at")
43
+ updatedAt DateTime @updatedAt @map("updated_at")
44
+
45
+ // Org-level billing identity + tier/subscription projection (org-scoped
46
+ // billing, #3601). Mirrors the User billing shape (see User L134-144) at the
47
+ // Organization level: in a multi-tenant deployment the Organization is the
48
+ // billing entity (individuals are billed as orgs-of-one on their sentinel
49
+ // default Organization). The Stripe webhook is the only writer (see
50
+ // apps/api/src/routes/webhooks/stripe.ts, keyed on checkout
51
+ // metadata.organizationId). Single-tenant deployments keep User-scoped
52
+ // billing (User fields above) and never touch these.
53
+ billingProvider String? @map("billing_provider") // "stripe"; provider-agnostic
54
+ billingCustomerId String? @map("billing_customer_id") // cus_xxx or equivalent
55
+ tier String @default("free") // "free" | "pro" | "pro_plus" | "enterprise"
56
+ hasCarePlan Boolean @default(false) @map("has_care_plan")
57
+ seatCount Int @default(1) @map("seat_count")
58
+
59
+ // Usage-billing balance counters — the Company-counter live on-demand
60
+ // credit model (FEAT-047 P1.S2, #3710 — capture D6, NOT a CreditUsagePeriod
61
+ // ledger table). Same-namespace additions to the existing billing identity
62
+ // fields above — no new relation. Read/written by the credit waterfall
63
+ // (apps/api/src/services/usage-credits.ts, #3716, the sanctioned
64
+ // tenant-scope exception) and the entitlement resolver (P1.S3).
65
+ usageBillingEnabled Boolean @default(false) @map("usage_billing_enabled")
66
+ stripeUsageMeterItemId String? @map("stripe_usage_meter_item_id")
67
+ includedCreditsCents Int @default(0) @map("included_credits_cents")
68
+ includedCreditsUsedCents Int @default(0) @map("included_credits_used_cents")
69
+ onDemandLimitCents Int? @map("on_demand_limit_cents")
70
+ onDemandUsedCents Int @default(0) @map("on_demand_used_cents")
71
+ onDemandPrechargedCents Int @default(0) @map("on_demand_precharged_cents")
72
+ /// Carry-forward credit balance. DB CHECK `>= 0`
73
+ /// (`organizations_on_demand_credit_balance_non_negative`, migration
74
+ /// 20260714030000) — Prisma cannot model CHECK, so the migration is the
75
+ /// source of truth. Debited only via the credit waterfall's compare-and-swap
76
+ /// (apps/api/src/services/usage-credits.ts, #3730); a negative balance would
77
+ /// INVERT the debit and hand out free credits.
78
+ onDemandCreditBalanceCents Int @default(0) @map("on_demand_credit_balance_cents")
79
+ creditsCycleEnd DateTime? @map("credits_cycle_end")
80
+ limitAllocationMode String @default("COMPANY_WIDE") @map("limit_allocation_mode") // "COMPANY_WIDE" | "INDIVIDUAL"
81
+
82
+ memberships Membership[]
83
+ invitations Invitation[]
84
+ workspaces Workspace[]
85
+
86
+ @@unique([billingProvider, billingCustomerId])
87
+ @@map("organizations")
88
+ }
89
+
90
+ /// Workspace — working context under an Organization. URL scope for all
91
+ /// domain content; operational config keys on workspaceId. Flat (org →
92
+ /// workspaces): no nesting — a future positioning-entity tree is a separate
93
+ /// feature and must not require tenancy rework.
94
+ model Workspace {
95
+ id String @id @default(dbgenerated("('wksp_'::text || (uuidv7())::text)")) @db.Text
96
+ organizationId String @map("organization_id")
97
+ name String
98
+ slug String
99
+ createdAt DateTime @default(now()) @map("created_at")
100
+ updatedAt DateTime @updatedAt @map("updated_at")
101
+
102
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
103
+
104
+ @@unique([organizationId, slug])
105
+ @@index([organizationId])
106
+ @@map("workspaces")
107
+ }
108
+
109
+ /// Membership — User ↔ Organization with a Role. Managed by the Better Auth
110
+ /// organization plugin (modelName "membership"). Org-level: grants visibility
111
+ /// into every workspace of the organization.
112
+ model Membership {
113
+ id String @id @default(dbgenerated("('member_'::text || (uuidv7())::text)")) @db.Text
114
+ organizationId String @map("organization_id")
115
+ userId String @map("user_id")
116
+ role Role @default(member)
117
+ createdAt DateTime @default(now()) @map("created_at")
118
+
119
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
120
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
121
+
122
+ @@unique([organizationId, userId])
123
+ @@index([userId])
124
+ @@index([organizationId])
125
+ @@map("memberships")
126
+ }
127
+
128
+ /// Invitation — pending invite of an email address into an Organization.
129
+ /// Managed by the Better Auth organization plugin. status:
130
+ /// "pending" | "accepted" | "rejected" | "canceled".
131
+ model Invitation {
132
+ id String @id @default(dbgenerated("('invite_'::text || (uuidv7())::text)")) @db.Text
133
+ organizationId String @map("organization_id")
134
+ email String
135
+ role Role @default(member)
136
+ status String @default("pending")
137
+ expiresAt DateTime? @map("expires_at")
138
+ inviterId String @map("inviter_id")
139
+ createdAt DateTime @default(now()) @map("created_at")
140
+
141
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
142
+ inviter User @relation("sent_invitations", fields: [inviterId], references: [id], onDelete: Cascade)
143
+
144
+ @@index([organizationId])
145
+ @@index([email])
146
+ @@map("invitations")
147
+ }
148
+
149
+ // ============================================================================
150
+ // Usage-billing balances/subscription/plan (FEAT-047 P1.S2, #3710 — Epic
151
+ // #3704). Per ADR 0009 D2 (roadmap §4), billing balances/subscription/plan
152
+ // live in `auth` (identity+tenancy charter); pricing/markup/model config
153
+ // lives in `config` (see database/config/schema.prisma). organizationId is a
154
+ // plain String stable-id — no @relation to Organization, even though both
155
+ // live in this namespace (spec D4: cross-namespace assembly + billing writes
156
+ // are keyed on explicit id, not relation traversal — mirrors the sanctioned
157
+ // usage-credits.ts / entitlements.ts / webhooks/stripe.ts read/write shape).
158
+ // Field roster ported from docs/research/wt-billing-capture/schema.md.
159
+ // ============================================================================
160
+
161
+ /// Subscription — one per Organization; the plan link + Stripe subscription
162
+ /// identity + enterprise contract terms. contractType/paymentMode are
163
+ /// nullable — "enterprise contract fields" only apply to sales-assisted /
164
+ /// enterprise deals; a self-serve subscription leaves them unset (no
165
+ /// business default invented — see spec §5.3).
166
+ model Subscription {
167
+ id String @id @default(dbgenerated("('orgsub_'::text || (uuidv7())::text)")) @db.Text
168
+ organizationId String @unique @map("organization_id")
169
+ planId String @map("plan_id")
170
+
171
+ stripeSubscriptionId String? @map("stripe_subscription_id")
172
+ stripePriceId String? @map("stripe_price_id")
173
+ stripeCustomerId String? @map("stripe_customer_id")
174
+
175
+ contractType ContractType? @map("contract_type")
176
+ netTermsDays Int? @map("net_terms_days")
177
+ contractValueCents Int? @map("contract_value_cents")
178
+ paymentMode SubscriptionPaymentMode? @map("payment_mode")
179
+
180
+ createdAt DateTime @default(now()) @map("created_at")
181
+ updatedAt DateTime @updatedAt @map("updated_at")
182
+
183
+ @@map("subscriptions")
184
+ }
185
+
186
+ /// Plan — the plan catalog (allowances, limits, Stripe price). Global
187
+ /// (not org-scoped) — the definitions a Subscription.planId references by
188
+ /// stable id, no @relation (spec D4).
189
+ model Plan {
190
+ id String @id @default(dbgenerated("('plan_'::text || (uuidv7())::text)")) @db.Text
191
+ slug String @unique
192
+ tier Int
193
+
194
+ baseTokens Int @map("base_tokens")
195
+ // Decimal, never Float: usageMultiplier scales a money amount. DOUBLE
196
+ // PRECISION admits NaN/Infinity, and NaN compares false against every
197
+ // spend-limit comparison — a float here fails OPEN past the limit gate.
198
+ // Matches the sibling money-multiplier convention (LlmModel.
199
+ // consumptionMultiplier, database/config/schema.prisma).
200
+ usageMultiplier Decimal @map("usage_multiplier") @db.Decimal(5, 2)
201
+ isPooled Boolean @map("is_pooled")
202
+ monthlyDollarCreditCents Int @map("monthly_dollar_credit_cents")
203
+
204
+ features Json
205
+ limits Json
206
+
207
+ stripePriceId String? @map("stripe_price_id")
208
+
209
+ createdAt DateTime @default(now()) @map("created_at")
210
+ updatedAt DateTime @updatedAt @map("updated_at")
211
+
212
+ @@map("plans")
213
+ }
214
+
215
+ /// UsageSettings — one per Organization; the usage-based-billing opt-in +
216
+ /// monthly spend-limit gate (read by the spend-limit check, P2).
217
+ model UsageSettings {
218
+ id String @id @default(dbgenerated("('usgset_'::text || (uuidv7())::text)")) @db.Text
219
+ organizationId String @unique @map("organization_id")
220
+
221
+ usageBasedBillingEnabled Boolean @default(false) @map("usage_based_billing_enabled")
222
+ monthlySpendLimitCents Int? @map("monthly_spend_limit_cents")
223
+
224
+ createdAt DateTime @default(now()) @map("created_at")
225
+ updatedAt DateTime @updatedAt @map("updated_at")
226
+
227
+ @@map("usage_settings")
228
+ }
229
+
230
+
231
+ // === Relocated from root schema.prisma (ADR-0009 D4 Phase 2, #3607) ===
232
+
233
+ /// User - Dashboard users (site owners, admins, end-users)
234
+ ///
235
+ /// emailVerified is a Boolean per Better Auth's contract (NextAuth previously
236
+ /// stored the verification timestamp as DateTime?). The five custom relations
237
+ /// — ApiToken, RefreshToken, OAuthAuthorization, PushToken, UserData — keep
238
+ /// their onDelete: Cascade semantics so user removal cleanly tears down all
239
+ /// dependent rows.
240
+ model User {
241
+ id String @id @default(dbgenerated("('user_'::text || (uuidv7())::text)")) @db.Text
242
+ email String @unique
243
+ name String?
244
+ image String?
245
+ emailVerified Boolean @default(false) @map("email_verified")
246
+
247
+ // Profile extensions
248
+ role String @default("user") // "user", "admin", "owner"
249
+
250
+ // Billing identity — provider-agnostic so Stripe is v1 value, not baked-in name.
251
+ // Webhook is the only writer (see apps/api/src/routes/webhooks/stripe.ts).
252
+ // #771 self-serve dashboard reads billingCustomerId for Stripe customer-portal URL.
253
+ billingProvider String? @map("billing_provider") // "stripe"; future: "lemonsqueezy", "paddle"
254
+ billingCustomerId String? @map("billing_customer_id") // cus_xxx (Stripe) or equivalent
255
+
256
+ // Subscription tier projection — derived from the Stripe webhook's product-aware
257
+ // routing (#898). Defaults to "free" until a customer.subscription.created event
258
+ // fires; flips to "pro" / "pro_plus" / etc. based on the line item's product.
259
+ // hasCarePlan is true only for pro_plus today; seatCount mirrors the line item
260
+ // quantity from Stripe's adjustable-quantity widget (1–50).
261
+ tier String @default("free") // "free" | "pro" | "pro_plus" | "enterprise" (retired "agency"/"commercial" rows migrated to "enterprise" — #3516)
262
+ hasCarePlan Boolean @default(false) @map("has_care_plan")
263
+ seatCount Int @default(1) @map("seat_count")
264
+
265
+ createdAt DateTime @default(now()) @map("created_at")
266
+ updatedAt DateTime @updatedAt @map("updated_at")
267
+
268
+ // Better Auth relations
269
+ sessions Session[]
270
+ accounts Account[]
271
+
272
+ // API & OAuth
273
+ apiTokens ApiToken[]
274
+ refreshTokens RefreshToken[]
275
+ oauthAuthorizations OAuthAuthorization[]
276
+ pushTokens PushToken[]
277
+
278
+ // Extensions
279
+ userData UserData[]
280
+
281
+ // Tenancy (multi-tenant module — database/auth/schema.prisma)
282
+ memberships Membership[]
283
+ sentInvitations Invitation[] @relation("sent_invitations")
284
+
285
+ @@unique([billingProvider, billingCustomerId])
286
+ @@map("users")
287
+ }
288
+
289
+ /// Session - Active user sessions (Better Auth schema)
290
+ ///
291
+ /// Session.token is the opaque cookie value the dual-mode preHandler reads.
292
+ /// Deleting a row revokes the session; deleting the parent User cascades.
293
+ model Session {
294
+ id String @id @default(dbgenerated("('sess_'::text || (uuidv7())::text)")) @db.Text
295
+ expiresAt DateTime @map("expires_at")
296
+ token String @unique
297
+ createdAt DateTime @default(now()) @map("created_at")
298
+ updatedAt DateTime @updatedAt @map("updated_at")
299
+ ipAddress String? @map("ip_address")
300
+ userAgent String? @map("user_agent")
301
+ userId String @map("user_id")
302
+
303
+ // Active tenant context (multi-tenant module). activeOrganizationId is the
304
+ // Better Auth organization plugin's session field; activeWorkspaceId is
305
+ // AILK's thin session extension (session.additionalFields in the
306
+ // apps/workspace auth config). Null in single-tenant deployments.
307
+ activeOrganizationId String? @map("active_organization_id")
308
+ activeWorkspaceId String? @map("active_workspace_id")
309
+
310
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
311
+
312
+ @@index([userId])
313
+ @@index([token])
314
+ @@map("sessions")
315
+ }
316
+
317
+ /// Account - OAuth provider connections (Google, GitHub, etc.)
318
+ ///
319
+ /// Better Auth's account shape: one row per (providerId, accountId) pair.
320
+ /// Cascade on User removal keeps OAuth links from orphaning.
321
+ model Account {
322
+ id String @id @default(dbgenerated("('acct_'::text || (uuidv7())::text)")) @db.Text
323
+ accountId String @map("account_id")
324
+ providerId String @map("provider_id")
325
+ userId String @map("user_id")
326
+ accessToken String? @map("access_token") @db.Text
327
+ refreshToken String? @map("refresh_token") @db.Text
328
+ idToken String? @map("id_token") @db.Text
329
+ accessTokenExpiresAt DateTime? @map("access_token_expires_at")
330
+ refreshTokenExpiresAt DateTime? @map("refresh_token_expires_at")
331
+ scope String?
332
+ password String?
333
+ createdAt DateTime @default(now()) @map("created_at")
334
+ updatedAt DateTime @updatedAt @map("updated_at")
335
+
336
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
337
+
338
+ @@unique([providerId, accountId])
339
+ @@index([userId])
340
+ @@map("accounts")
341
+ }
342
+
343
+ /// Verification - Email / magic-link verification tokens (Better Auth schema)
344
+ model Verification {
345
+ id String @id @default(dbgenerated("('verify_'::text || (uuidv7())::text)")) @db.Text
346
+ identifier String
347
+ value String
348
+ expiresAt DateTime @map("expires_at")
349
+ createdAt DateTime @default(now()) @map("created_at")
350
+ updatedAt DateTime @updatedAt @map("updated_at")
351
+
352
+ @@index([identifier])
353
+ @@map("verifications")
354
+ }
355
+
356
+ /// ApiToken - Bearer tokens for non-web clients (mobile apps, API integrations)
357
+ model ApiToken {
358
+ id String @id @default(dbgenerated("('apitok_'::text || (uuidv7())::text)")) @db.Text
359
+ userId String @map("user_id")
360
+
361
+ // Token identification
362
+ name String // "iPhone", "Android App", "API Integration"
363
+ token String @unique // Hashed token
364
+ tokenPrefix String @map("token_prefix") // First 8 chars for identification
365
+
366
+ // Client info
367
+ clientType String @default("api") @map("client_type") // "mobile", "api", "cli"
368
+ deviceInfo String? @map("device_info") // "iPhone 15 Pro", "Android 14"
369
+
370
+ // Permissions
371
+ scopes String[] @default([]) // ["read:profile", "write:data"]
372
+
373
+ // Lifecycle
374
+ expiresAt DateTime? @map("expires_at")
375
+ lastUsedAt DateTime? @map("last_used_at")
376
+ lastUsedIp String? @map("last_used_ip")
377
+ revokedAt DateTime? @map("revoked_at")
378
+
379
+ createdAt DateTime @default(now()) @map("created_at")
380
+
381
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
382
+ refreshTokens RefreshToken[]
383
+
384
+ @@index([userId])
385
+ @@index([token])
386
+ @@index([tokenPrefix])
387
+ @@map("api_tokens")
388
+ }
389
+
390
+ /// RefreshToken - Long-lived tokens for mobile session refresh
391
+ model RefreshToken {
392
+ id String @id @default(dbgenerated("('reftok_'::text || (uuidv7())::text)")) @db.Text
393
+ userId String @map("user_id")
394
+ apiTokenId String @map("api_token_id")
395
+
396
+ token String @unique // Hashed
397
+
398
+ // Lifecycle
399
+ expiresAt DateTime @map("expires_at")
400
+ usedAt DateTime? @map("used_at") // Last time used to get new access token
401
+ revokedAt DateTime? @map("revoked_at")
402
+
403
+ createdAt DateTime @default(now()) @map("created_at")
404
+
405
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
406
+ apiToken ApiToken @relation(fields: [apiTokenId], references: [id], onDelete: Cascade)
407
+
408
+ @@index([userId])
409
+ @@index([apiTokenId])
410
+ @@index([token])
411
+ @@map("refresh_tokens")
412
+ }
413
+
414
+ /// OAuthClient - Registered OAuth applications (ChatGPT, Slack, etc.)
415
+ model OAuthClient {
416
+ id String @id @default(dbgenerated("('oauthc_'::text || (uuidv7())::text)")) @db.Text
417
+
418
+ // Client identification
419
+ name String // "ChatGPT Plugin", "Slack Bot"
420
+ description String?
421
+ logoUrl String? @map("logo_url")
422
+
423
+ // OAuth credentials
424
+ clientId String @unique @map("client_id") // Public identifier
425
+ clientSecret String @map("client_secret") // Hashed secret
426
+
427
+ // OAuth config
428
+ redirectUris String[] @map("redirect_uris") // Allowed callback URLs
429
+ scopes String[] @default([]) // Allowed scopes
430
+
431
+ // Settings
432
+ enabled Boolean @default(true)
433
+ trusted Boolean @default(false) // Skip consent screen
434
+
435
+ createdAt DateTime @default(now()) @map("created_at")
436
+ updatedAt DateTime @updatedAt @map("updated_at")
437
+
438
+ authorizations OAuthAuthorization[]
439
+
440
+ @@map("oauth_clients")
441
+ }
442
+
443
+ /// OAuthAuthorization - User grants to OAuth clients
444
+ model OAuthAuthorization {
445
+ id String @id @default(dbgenerated("('oautha_'::text || (uuidv7())::text)")) @db.Text
446
+ userId String @map("user_id")
447
+ clientId String @map("client_id")
448
+
449
+ // Granted scopes (may be subset of client's allowed scopes)
450
+ scopes String[]
451
+
452
+ // Tokens
453
+ accessToken String @unique @map("access_token") // Hashed
454
+ refreshToken String? @unique @map("refresh_token") // Hashed
455
+
456
+ // Lifecycle
457
+ expiresAt DateTime @map("expires_at")
458
+ revokedAt DateTime? @map("revoked_at")
459
+
460
+ createdAt DateTime @default(now()) @map("created_at")
461
+ updatedAt DateTime @updatedAt @map("updated_at")
462
+
463
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
464
+ client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
465
+
466
+ @@unique([userId, clientId])
467
+ @@index([userId])
468
+ @@index([clientId])
469
+ @@index([accessToken])
470
+ @@map("oauth_authorizations")
471
+ }
472
+
473
+ /// PushToken - Device tokens for push notifications
474
+ model PushToken {
475
+ id String @id @default(dbgenerated("('pushtok_'::text || (uuidv7())::text)")) @db.Text
476
+ userId String @map("user_id")
477
+
478
+ // Token details
479
+ token String @unique // FCM or APNs token
480
+ platform String // "ios", "android", "web"
481
+
482
+ // Device info
483
+ deviceId String? @map("device_id") // Unique device identifier
484
+ deviceName String? @map("device_name") // "iPhone 15 Pro"
485
+ appVersion String? @map("app_version") // "1.2.3"
486
+
487
+ // Status
488
+ enabled Boolean @default(true)
489
+ failedAt DateTime? @map("failed_at") // Last delivery failure
490
+ failCount Int @default(0) @map("fail_count")
491
+
492
+ createdAt DateTime @default(now()) @map("created_at")
493
+ updatedAt DateTime @updatedAt @map("updated_at")
494
+
495
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
496
+
497
+ @@index([userId])
498
+ @@index([platform])
499
+ @@map("push_tokens")
500
+ }
501
+
502
+ /// UserData - Flexible key-value storage for customer extensions
503
+ /// Use this for: preferences, saved items, custom fields, feature flags
504
+ model UserData {
505
+ id String @id @default(dbgenerated("('userd_'::text || (uuidv7())::text)")) @db.Text
506
+ userId String @map("user_id")
507
+
508
+ // Key-value storage
509
+ key String // "preferences", "saved_products", "notification_settings"
510
+ value Json // Flexible JSON storage
511
+
512
+ createdAt DateTime @default(now()) @map("created_at")
513
+ updatedAt DateTime @updatedAt @map("updated_at")
514
+
515
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
516
+
517
+ @@unique([userId, key])
518
+ @@index([userId])
519
+ @@index([key])
520
+ @@map("user_data")
521
+ }