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,184 @@
1
+ /**
2
+ * Paid-module-bundle tar.gz extract, with path-traversal protection (K1,
3
+ * #5089 — Flavor 3).
4
+ *
5
+ * Security posture is a line-for-line port of
6
+ * `packages/cli/src/lib/extract-bundle.ts` (`extractBundle`) — fail-closed on
7
+ * every unsafe entry:
8
+ * - Reject entries whose normalized path escapes the staging root (any
9
+ * `..` segment, absolute paths, or any path that resolves outside).
10
+ * - Reject ANY symlink / hardlink entry.
11
+ * - Cap extracted-entry count + cumulative size to prevent zip-bomb-style
12
+ * denial-of-service.
13
+ * - Strip setuid/setgid mode bits.
14
+ *
15
+ * NOT a straight import of `extractBundle` — see `fetch-module.ts`'s file
16
+ * doc for why `create-ailk` (the one publicly-published package in this
17
+ * monorepo) cannot take a runtime dependency on anything in
18
+ * `packages/cli/src/lib/`, which is `publishConfig.access: "restricted"`.
19
+ * This is a deliberate, named duplication of the guard logic, not a
20
+ * reimplementation of a different one.
21
+ *
22
+ * ONE difference from `extractBundle`, required by the caller's shape:
23
+ * `extractBundle` extracts into an EMPTY staging dir that then swap-renames
24
+ * over the (possibly pre-existing) install target — appropriate for a single
25
+ * self-contained skill directory. A fetched module's files are scattered
26
+ * across an ALREADY-SCAFFOLDED tree (`apps/api/src/routes/...`,
27
+ * `apps/web/app/...`), so there is no single directory to rename over.
28
+ * `extractModuleBundle` therefore extracts into a throwaway temp dir first
29
+ * (same validation, same guards), and ONLY on full success copies each
30
+ * validated file into its place under `targetDir` — so a rejected or
31
+ * partially-decompressed bundle never touches the scaffold at all.
32
+ */
33
+ import { copyFileSync, createReadStream, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync, } from "node:fs";
34
+ import { tmpdir } from "node:os";
35
+ import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
36
+ import { pipeline } from "node:stream/promises";
37
+ import { createGunzip } from "node:zlib";
38
+ import * as tar from "tar";
39
+ /** Soft limits to prevent decompression-bomb / zip-bomb attacks. Same values as extractBundle. */
40
+ const MAX_ENTRIES = 1000;
41
+ const MAX_TOTAL_SIZE_BYTES = 50 * 1024 * 1024; // 50 MiB
42
+ /**
43
+ * Extract a fetched module bundle into `targetDir`, merging its files onto
44
+ * the tree `copyTemplate` already wrote. Throws on any unsafe entry,
45
+ * decompress error, or limit overrun — `targetDir` is left untouched on
46
+ * failure (validation completes in a throwaway staging dir before any file
47
+ * is copied into place).
48
+ */
49
+ export async function extractModuleBundle(options) {
50
+ const { bytes, targetDir, moduleName } = options;
51
+ const targetAbs = resolve(targetDir);
52
+ if (!existsSync(targetAbs)) {
53
+ throw new Error(`extractModuleBundle: target directory does not exist: ${targetAbs}`);
54
+ }
55
+ const stagingDir = mkdtempSync(join(tmpdir(), `ailk-module-${moduleName}-`));
56
+ const stagingTar = join(stagingDir, "bundle.tar.gz");
57
+ try {
58
+ writeFileSync(stagingTar, bytes);
59
+ const extractedRoot = join(stagingDir, "extracted");
60
+ mkdirSync(extractedRoot, { recursive: true });
61
+ await safeExtractTarGz(stagingTar, extractedRoot, moduleName);
62
+ // Full validation passed — merge into targetDir. Copies only (never
63
+ // deletes anything): a fetched module's files ADD to the free scaffold,
64
+ // they never remove what the free copy already wrote.
65
+ copyTree(extractedRoot, targetAbs);
66
+ }
67
+ finally {
68
+ rmSync(stagingDir, { recursive: true, force: true });
69
+ }
70
+ }
71
+ /**
72
+ * Recursively copy every file from `srcRoot` into `destRoot`, creating parent
73
+ * directories as needed. Runs ONLY after `safeExtractTarGz` has validated
74
+ * every entry, so no additional path-safety check is needed here — `srcRoot`
75
+ * is our own staging tree, not attacker-controlled input.
76
+ */
77
+ function copyTree(srcRoot, destRoot) {
78
+ const stack = [srcRoot];
79
+ while (stack.length > 0) {
80
+ const dir = stack.pop();
81
+ if (dir === undefined)
82
+ break;
83
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
84
+ const srcPath = join(dir, entry.name);
85
+ const rel = relative(srcRoot, srcPath);
86
+ const destPath = join(destRoot, rel);
87
+ if (entry.isDirectory()) {
88
+ mkdirSync(destPath, { recursive: true });
89
+ stack.push(srcPath);
90
+ }
91
+ else if (entry.isFile()) {
92
+ mkdirSync(join(destPath, ".."), { recursive: true });
93
+ copyFileSync(srcPath, destPath);
94
+ }
95
+ // symlinks: never present — safeExtractTarGz rejects them outright.
96
+ }
97
+ }
98
+ }
99
+ /**
100
+ * `extractBundle`'s validating-filter tar extraction, ported verbatim (see
101
+ * file doc for why this is a port and not an import). Extracts `tarGzPath`
102
+ * into `targetDir`, which the caller guarantees is empty.
103
+ */
104
+ async function safeExtractTarGz(tarGzPath, targetDir, moduleName) {
105
+ const resolvedTarget = resolve(targetDir);
106
+ let entryCount = 0;
107
+ let totalSize = 0;
108
+ const captured = { error: null };
109
+ const reject = (msg) => {
110
+ if (captured.error === null) {
111
+ captured.error = new Error(`module "${moduleName}": ${msg}`);
112
+ }
113
+ return false;
114
+ };
115
+ const validate = (entryPath, rawEntry) => {
116
+ if (captured.error !== null)
117
+ return false;
118
+ entryCount += 1;
119
+ if (entryCount > MAX_ENTRIES) {
120
+ return reject(`unsafe bundle: entry count exceeds ${MAX_ENTRIES}`);
121
+ }
122
+ const declaredSize = typeof rawEntry.size === "number" ? rawEntry.size : 0;
123
+ totalSize += declaredSize;
124
+ if (totalSize > MAX_TOTAL_SIZE_BYTES) {
125
+ return reject(`unsafe bundle: cumulative size exceeds ${MAX_TOTAL_SIZE_BYTES} bytes`);
126
+ }
127
+ if (typeof entryPath !== "string" || entryPath.length === 0) {
128
+ return reject("unsafe path: bundle entry has empty path");
129
+ }
130
+ if (isAbsolute(entryPath)) {
131
+ return reject(`unsafe path: bundle entry uses absolute path "${entryPath}"`);
132
+ }
133
+ const normalized = normalize(entryPath);
134
+ if (normalized === ".." ||
135
+ normalized.startsWith(`..${sep}`) ||
136
+ normalized.split(sep).includes("..")) {
137
+ return reject(`unsafe path: bundle entry "${entryPath}" contains path traversal`);
138
+ }
139
+ const fullPath = resolve(resolvedTarget, entryPath);
140
+ if (!isPathInside(resolvedTarget, fullPath)) {
141
+ return reject(`unsafe path: bundle entry "${entryPath}" resolves outside target`);
142
+ }
143
+ const entryType = rawEntry.type;
144
+ if (entryType === "SymbolicLink" ||
145
+ entryType === "Link" ||
146
+ entryType === "symlink" ||
147
+ entryType === "link") {
148
+ return reject(`unsafe link: bundle entry "${entryPath}" is a ${entryType} (rejected)`);
149
+ }
150
+ return true;
151
+ };
152
+ const extractStream = tar.x({
153
+ cwd: resolvedTarget,
154
+ strict: true,
155
+ filter: validate,
156
+ onentry: (entry) => {
157
+ if (typeof entry.mode === "number") {
158
+ entry.mode = entry.mode & 0o777;
159
+ }
160
+ },
161
+ });
162
+ try {
163
+ await pipeline(createReadStream(tarGzPath), createGunzip(), extractStream);
164
+ }
165
+ catch (err) {
166
+ if (captured.error !== null)
167
+ throw captured.error;
168
+ throw err;
169
+ }
170
+ if (captured.error !== null) {
171
+ throw captured.error;
172
+ }
173
+ }
174
+ /** True iff `child` is the same path as `parent` or a descendant of it. */
175
+ function isPathInside(parent, child) {
176
+ const rel = relative(parent, child);
177
+ if (rel === "")
178
+ return true;
179
+ if (rel.startsWith(".."))
180
+ return false;
181
+ if (isAbsolute(rel))
182
+ return false;
183
+ return true;
184
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Authenticated paid-module-bundle fetch (K1, #5089 — Flavor 3).
3
+ *
4
+ * Posture lifted verbatim from `packages/cli/src/lib/fetch-bundle.ts`
5
+ * (`fetchBundle`, the skill-registry twin of this function):
6
+ * - Bearer-JWT auth on every request.
7
+ * - `redirect: "error"` so a maliciously redirected response can't drop us
8
+ * onto an unintended host — the CLI must hit the configured module
9
+ * distribution only.
10
+ * - Empty-token guard before any network call (defense in depth — the
11
+ * caller should already have gated on an empty/absent key).
12
+ * - Status-code mapping: 401 → license invalid/revoked/lapsed, 404 →
13
+ * module content not yet available, other 4xx/5xx → upstream body.
14
+ *
15
+ * Deliberately DOES NOT depend on `@working-theory/license` or
16
+ * `@working-theory/cli` — both are `publishConfig.access: "restricted"` and
17
+ * `create-ailk` is the one package in this monorepo published to PUBLIC npm
18
+ * (Apache-2.0, A1 disposed it `oss`). A runtime dependency on a restricted
19
+ * package would break `pnpm install` for every free-tier consumer, not just
20
+ * gate the paid modules — so this file re-states fetchBundle's POSTURE
21
+ * rather than importing it. Named in the K1 PR body as the public-package
22
+ * boundary this card had to draw.
23
+ *
24
+ * Also deliberately skips fetchBundle's caller-side `checkLicense()` local
25
+ * JWT pre-check (install-skill.ts's step 2): that local verification lives
26
+ * in `@working-theory/license`, which for the same publish-boundary reason
27
+ * above cannot be a runtime dependency here. Instead the module distribution
28
+ * endpoint's own 401 response IS the license verdict — exactly the signal
29
+ * `fetchBundle` already surfaces via `isLicenseError`. This trades one local,
30
+ * no-network check for one authoritative, server-verified one; the caller-
31
+ * visible contract (present-but-invalid key ⟹ the honest "does not cover
32
+ * this" message) is unchanged.
33
+ *
34
+ * Returns the response body bytes on 200; throws a descriptive
35
+ * `FetchModuleError` on any failure path so the caller can map to an honest
36
+ * exit uniformly.
37
+ */
38
+ export declare const DEFAULT_AILK_MODULE_REGISTRY_URL = "https://ailaunchkit.ai/api/modules";
39
+ export interface FetchModuleOptions {
40
+ moduleName: string;
41
+ /** JWT used as `Authorization: Bearer <token>`. Must be non-empty. */
42
+ token: string;
43
+ /** Registry root; the module name is appended as a single path segment. */
44
+ registryUrl?: string;
45
+ /** Override for tests; defaults to `globalThis.fetch`. Never a live call in CI. */
46
+ fetchImpl?: typeof fetch;
47
+ }
48
+ export declare class FetchModuleError extends Error {
49
+ /** True iff the failure was a license-gating signal (HTTP 401). */
50
+ readonly isLicenseError: boolean;
51
+ constructor(message: string,
52
+ /** True iff the failure was a license-gating signal (HTTP 401). */
53
+ isLicenseError?: boolean);
54
+ }
55
+ export declare function fetchModule(options: FetchModuleOptions): Promise<Uint8Array>;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Authenticated paid-module-bundle fetch (K1, #5089 — Flavor 3).
3
+ *
4
+ * Posture lifted verbatim from `packages/cli/src/lib/fetch-bundle.ts`
5
+ * (`fetchBundle`, the skill-registry twin of this function):
6
+ * - Bearer-JWT auth on every request.
7
+ * - `redirect: "error"` so a maliciously redirected response can't drop us
8
+ * onto an unintended host — the CLI must hit the configured module
9
+ * distribution only.
10
+ * - Empty-token guard before any network call (defense in depth — the
11
+ * caller should already have gated on an empty/absent key).
12
+ * - Status-code mapping: 401 → license invalid/revoked/lapsed, 404 →
13
+ * module content not yet available, other 4xx/5xx → upstream body.
14
+ *
15
+ * Deliberately DOES NOT depend on `@working-theory/license` or
16
+ * `@working-theory/cli` — both are `publishConfig.access: "restricted"` and
17
+ * `create-ailk` is the one package in this monorepo published to PUBLIC npm
18
+ * (Apache-2.0, A1 disposed it `oss`). A runtime dependency on a restricted
19
+ * package would break `pnpm install` for every free-tier consumer, not just
20
+ * gate the paid modules — so this file re-states fetchBundle's POSTURE
21
+ * rather than importing it. Named in the K1 PR body as the public-package
22
+ * boundary this card had to draw.
23
+ *
24
+ * Also deliberately skips fetchBundle's caller-side `checkLicense()` local
25
+ * JWT pre-check (install-skill.ts's step 2): that local verification lives
26
+ * in `@working-theory/license`, which for the same publish-boundary reason
27
+ * above cannot be a runtime dependency here. Instead the module distribution
28
+ * endpoint's own 401 response IS the license verdict — exactly the signal
29
+ * `fetchBundle` already surfaces via `isLicenseError`. This trades one local,
30
+ * no-network check for one authoritative, server-verified one; the caller-
31
+ * visible contract (present-but-invalid key ⟹ the honest "does not cover
32
+ * this" message) is unchanged.
33
+ *
34
+ * Returns the response body bytes on 200; throws a descriptive
35
+ * `FetchModuleError` on any failure path so the caller can map to an honest
36
+ * exit uniformly.
37
+ */
38
+ export const DEFAULT_AILK_MODULE_REGISTRY_URL = "https://ailaunchkit.ai/api/modules";
39
+ export class FetchModuleError extends Error {
40
+ isLicenseError;
41
+ constructor(message,
42
+ /** True iff the failure was a license-gating signal (HTTP 401). */
43
+ isLicenseError = false) {
44
+ super(message);
45
+ this.isLicenseError = isLicenseError;
46
+ this.name = "FetchModuleError";
47
+ }
48
+ }
49
+ /**
50
+ * Build the fetch URL by joining `registryUrl` with `moduleName` as a single
51
+ * trailing path segment. `encodeURIComponent` on the module name is defense
52
+ * in depth — `parse-args.ts`'s `parseModules` already restricts the value to
53
+ * `RECOGNIZED_MODULES`, but a hostile value can never smuggle a path
54
+ * separator or query string here regardless.
55
+ */
56
+ function buildUrl(registryUrl, moduleName) {
57
+ const trimmed = registryUrl.replace(/\/+$/, "");
58
+ return `${trimmed}/${encodeURIComponent(moduleName)}`;
59
+ }
60
+ export async function fetchModule(options) {
61
+ const { moduleName, token } = options;
62
+ if (token.length === 0) {
63
+ throw new FetchModuleError("internal error: fetchModule called without a token");
64
+ }
65
+ const registryUrl = options.registryUrl ??
66
+ process.env["AILK_MODULE_REGISTRY_URL"] ??
67
+ DEFAULT_AILK_MODULE_REGISTRY_URL;
68
+ const url = buildUrl(registryUrl, moduleName);
69
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
70
+ let response;
71
+ try {
72
+ response = await fetchImpl(url, {
73
+ method: "GET",
74
+ headers: {
75
+ Authorization: `Bearer ${token}`,
76
+ Accept: "application/gzip, application/octet-stream",
77
+ },
78
+ redirect: "error",
79
+ });
80
+ }
81
+ catch (err) {
82
+ const detail = err instanceof Error ? err.message : String(err);
83
+ throw new FetchModuleError(`module registry unreachable: ${detail}`);
84
+ }
85
+ if (response.status === 401) {
86
+ throw new FetchModuleError(`your licence does not cover the "${moduleName}" module (invalid, revoked, or lapsed)`,
87
+ /* isLicenseError */ true);
88
+ }
89
+ if (response.status === 404) {
90
+ throw new FetchModuleError(`"${moduleName}" module content not yet available — ping us at hello@ailaunchkit.ai`);
91
+ }
92
+ if (!response.ok) {
93
+ const body = await safeReadBody(response);
94
+ throw new FetchModuleError(`module registry returned ${response.status} for "${moduleName}": ${body}`);
95
+ }
96
+ const buf = await response.arrayBuffer();
97
+ return new Uint8Array(buf);
98
+ }
99
+ /**
100
+ * Best-effort error body extraction. Tries JSON first (registry uses
101
+ * `{ error: "..." }` shapes), falls back to text, swallows any read failure
102
+ * so the caller's error message remains useful. Verbatim copy of
103
+ * `fetch-bundle.ts`'s helper of the same name.
104
+ */
105
+ async function safeReadBody(response) {
106
+ try {
107
+ const text = await response.text();
108
+ try {
109
+ const parsed = JSON.parse(text);
110
+ if (parsed !== null &&
111
+ typeof parsed === "object" &&
112
+ "error" in parsed &&
113
+ typeof parsed.error === "string") {
114
+ return parsed.error;
115
+ }
116
+ }
117
+ catch {
118
+ /* not JSON — fall through to raw text */
119
+ }
120
+ return text || response.statusText;
121
+ }
122
+ catch {
123
+ return response.statusText;
124
+ }
125
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Paid-module license gate (K1, #5089 — Flavor 3). Orchestrates
3
+ * `module-tier.ts`'s classification + `fetch-module.ts`'s authenticated
4
+ * fetch into the three honest states the CLI must surface:
5
+ *
6
+ * (a) no key + a paid module requested → conversion hint, non-zero, ZERO
7
+ * network (mirrors `install-skill.ts`'s free-tier short-circuit).
8
+ * (b) a lapsed/invalid key + a paid module → "your licence does not cover
9
+ * this", non-zero (the module distribution's own 401 — see
10
+ * `fetch-module.ts`'s file doc for why there is no local JWT
11
+ * pre-check here).
12
+ * (c) a valid key → every requested paid module's bundle bytes, ready for
13
+ * `extract-module-bundle.ts` to merge into the scaffold.
14
+ *
15
+ * A Free-only request (no paid modules) never reaches the key check at all —
16
+ * `resolvePaidModules` returns immediately, before touching `process.env` or
17
+ * the network, so a bare/all-Free scaffold is provably unaffected by this
18
+ * gate (K1's regression floor).
19
+ */
20
+ import type { ModuleName } from "../parse-args.js";
21
+ export declare const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pro";
22
+ /**
23
+ * Thrown for both honest-denial states (no key, and an invalid/lapsed key).
24
+ * The CLI does not distinguish them in its exit code — both are "this run
25
+ * cannot proceed without a paid module you don't have entitlement to" — but
26
+ * the MESSAGE always says which state it is, per the honest-state contract.
27
+ */
28
+ export declare class LicenseRequiredError extends Error {
29
+ constructor(message: string);
30
+ }
31
+ export interface ResolvePaidModulesOptions {
32
+ /** The requested module set's paid subset (see `module-tier.ts`). */
33
+ paidModules: ModuleName[];
34
+ /** Defaults to `process.env["AILK_LICENSE_KEY"]`. Injectable for tests. */
35
+ licenseKey?: string | undefined;
36
+ /** Forwarded to `fetchModule`; defaults to `AILK_MODULE_REGISTRY_URL` / the built-in default. */
37
+ registryUrl?: string;
38
+ /** Forwarded to `fetchModule`; defaults to `globalThis.fetch`. Never a live call in tests. */
39
+ fetchImpl?: typeof fetch;
40
+ }
41
+ /**
42
+ * Resolve every requested paid module to its fetched bundle bytes, or throw
43
+ * `LicenseRequiredError` naming exactly why the run cannot proceed. Never
44
+ * partially resolves: on the first denial or failure, no further modules are
45
+ * fetched and the caller has written nothing to disk yet (the gate runs
46
+ * BEFORE the scaffold copy — see `programmatic.ts`'s `scaffold()`).
47
+ */
48
+ export declare function resolvePaidModules(options: ResolvePaidModulesOptions): Promise<Map<ModuleName, Uint8Array>>;
@@ -0,0 +1,67 @@
1
+ import { FetchModuleError, fetchModule } from "./fetch-module.js";
2
+ export const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pro";
3
+ /**
4
+ * Thrown for both honest-denial states (no key, and an invalid/lapsed key).
5
+ * The CLI does not distinguish them in its exit code — both are "this run
6
+ * cannot proceed without a paid module you don't have entitlement to" — but
7
+ * the MESSAGE always says which state it is, per the honest-state contract.
8
+ */
9
+ export class LicenseRequiredError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = "LicenseRequiredError";
13
+ }
14
+ }
15
+ /**
16
+ * Resolve every requested paid module to its fetched bundle bytes, or throw
17
+ * `LicenseRequiredError` naming exactly why the run cannot proceed. Never
18
+ * partially resolves: on the first denial or failure, no further modules are
19
+ * fetched and the caller has written nothing to disk yet (the gate runs
20
+ * BEFORE the scaffold copy — see `programmatic.ts`'s `scaffold()`).
21
+ */
22
+ export async function resolvePaidModules(options) {
23
+ const { paidModules } = options;
24
+ if (paidModules.length === 0) {
25
+ // Regression floor: zero key reads, zero network, for any request that
26
+ // names no paid module.
27
+ return new Map();
28
+ }
29
+ const token = options.licenseKey ?? process.env["AILK_LICENSE_KEY"];
30
+ if (token === undefined || token.length === 0) {
31
+ throw new LicenseRequiredError(conversionHint(paidModules));
32
+ }
33
+ const bundles = new Map();
34
+ for (const moduleName of paidModules) {
35
+ try {
36
+ const bytes = await fetchModule({
37
+ moduleName,
38
+ token,
39
+ ...(options.registryUrl !== undefined
40
+ ? { registryUrl: options.registryUrl }
41
+ : {}),
42
+ ...(options.fetchImpl !== undefined
43
+ ? { fetchImpl: options.fetchImpl }
44
+ : {}),
45
+ });
46
+ bundles.set(moduleName, bytes);
47
+ }
48
+ catch (err) {
49
+ if (err instanceof FetchModuleError) {
50
+ if (err.isLicenseError) {
51
+ throw new LicenseRequiredError(`${err.message} → ${CONVERSION_HINT_URL}`);
52
+ }
53
+ // Not a license-gating signal (e.g. 404 "not yet available", or the
54
+ // registry unreachable) — a generic failure, not the honest-denial
55
+ // state. Re-thrown as-is; the CLI's top-level catch still turns this
56
+ // into a `[create-ailk] <message>` stderr write + non-zero exit.
57
+ throw err;
58
+ }
59
+ throw err;
60
+ }
61
+ }
62
+ return bundles;
63
+ }
64
+ function conversionHint(paidModules) {
65
+ const list = paidModules.join(", ");
66
+ return `Pro module(s) requested (${list}) — set AILK_LICENSE_KEY first → ${CONVERSION_HINT_URL}`;
67
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Free vs paid module classification (K1, #5089 — REL-015.3 "AI Launch Kit —
3
+ * Commercial line", D-17 "Flavor 3").
4
+ *
5
+ * The commercial line is decided: the paid modules do NOT ship on public npm
6
+ * — delivery itself is the gate. `create-ailk` scaffolds Free's modules from
7
+ * `templates/` with no key (today's path, unchanged); a paid module is
8
+ * FETCHED from the internal module distribution when `AILK_LICENSE_KEY`
9
+ * verifies (see `fetch-module.ts` + `module-license-gate.ts`).
10
+ *
11
+ * `FREE_MODULES` is the one hand-authored list (today just `marketing`, the
12
+ * always-available default). `PAID_MODULES` is derived from it — every other
13
+ * `RECOGNIZED_MODULES` entry — so adding a new module to the vocabulary
14
+ * (`parse-args.ts`) defaults it to "paid" until someone deliberately adds it
15
+ * to `FREE_MODULES`, rather than silently shipping it free.
16
+ */
17
+ import { type ModuleName } from "../parse-args.js";
18
+ /** Modules scaffolded from `templates/` with no license — today's free path. */
19
+ export declare const FREE_MODULES: readonly ModuleName[];
20
+ /**
21
+ * Modules requiring a verified `AILK_LICENSE_KEY` — delivered via the paid
22
+ * module fetch path rather than bundled in the published `create-ailk` npm
23
+ * package. Derived (not hand-listed) so the free/paid split can never drift
24
+ * from `RECOGNIZED_MODULES` silently.
25
+ */
26
+ export declare const PAID_MODULES: readonly ModuleName[];
27
+ export interface ModuleClassification {
28
+ free: ModuleName[];
29
+ paid: ModuleName[];
30
+ }
31
+ /**
32
+ * Split a requested (already-validated, `ModuleName`) module set into its
33
+ * free and paid subsets, each preserving the input's relative order.
34
+ */
35
+ export declare function classifyModules(modules: ModuleName[]): ModuleClassification;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Free vs paid module classification (K1, #5089 — REL-015.3 "AI Launch Kit —
3
+ * Commercial line", D-17 "Flavor 3").
4
+ *
5
+ * The commercial line is decided: the paid modules do NOT ship on public npm
6
+ * — delivery itself is the gate. `create-ailk` scaffolds Free's modules from
7
+ * `templates/` with no key (today's path, unchanged); a paid module is
8
+ * FETCHED from the internal module distribution when `AILK_LICENSE_KEY`
9
+ * verifies (see `fetch-module.ts` + `module-license-gate.ts`).
10
+ *
11
+ * `FREE_MODULES` is the one hand-authored list (today just `marketing`, the
12
+ * always-available default). `PAID_MODULES` is derived from it — every other
13
+ * `RECOGNIZED_MODULES` entry — so adding a new module to the vocabulary
14
+ * (`parse-args.ts`) defaults it to "paid" until someone deliberately adds it
15
+ * to `FREE_MODULES`, rather than silently shipping it free.
16
+ */
17
+ import { RECOGNIZED_MODULES } from "../parse-args.js";
18
+ /** Modules scaffolded from `templates/` with no license — today's free path. */
19
+ export const FREE_MODULES = ["marketing"];
20
+ /**
21
+ * Modules requiring a verified `AILK_LICENSE_KEY` — delivered via the paid
22
+ * module fetch path rather than bundled in the published `create-ailk` npm
23
+ * package. Derived (not hand-listed) so the free/paid split can never drift
24
+ * from `RECOGNIZED_MODULES` silently.
25
+ */
26
+ export const PAID_MODULES = RECOGNIZED_MODULES.filter((m) => !FREE_MODULES.includes(m));
27
+ /**
28
+ * Split a requested (already-validated, `ModuleName`) module set into its
29
+ * free and paid subsets, each preserving the input's relative order.
30
+ */
31
+ export function classifyModules(modules) {
32
+ const paidSet = new Set(PAID_MODULES);
33
+ return {
34
+ free: modules.filter((m) => !paidSet.has(m)),
35
+ paid: modules.filter((m) => paidSet.has(m)),
36
+ };
37
+ }