create-ailk 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +55 -8
  2. package/component-catalog.json +336 -27
  3. package/component-catalog.md +25 -12
  4. package/dist/cli.js +54 -5
  5. package/dist/copy.d.ts +14 -0
  6. package/dist/copy.js +38 -1
  7. package/dist/lib/api-boot-assertion.d.ts +46 -0
  8. package/dist/lib/api-boot-assertion.js +70 -0
  9. package/dist/lib/extract-module-bundle.d.ts +20 -1
  10. package/dist/lib/extract-module-bundle.js +64 -5
  11. package/dist/lib/import-graph.d.ts +29 -0
  12. package/dist/lib/import-graph.js +140 -0
  13. package/dist/lib/module-license-gate.d.ts +6 -1
  14. package/dist/lib/module-license-gate.js +6 -1
  15. package/dist/lib/pro-callout.js +1 -1
  16. package/dist/module-architecture.d.ts +1 -0
  17. package/dist/module-architecture.js +253 -127
  18. package/dist/modules/commerce/0.6.0.tar.gz +0 -0
  19. package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
  20. package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
  21. package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
  22. package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
  23. package/dist/modules/workspace/0.6.0.tar.gz +0 -0
  24. package/dist/programmatic.js +14 -10
  25. package/dist/surfaces.js +105 -7
  26. package/dist/template-manifest.d.ts +33 -0
  27. package/dist/template-manifest.js +99 -16
  28. package/dist/template-names.d.ts +1 -1
  29. package/dist/template-names.js +1 -0
  30. package/package.json +3 -2
  31. package/site-templates/marketing-site/DESIGN.md +148 -0
  32. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +22 -2
  33. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +9 -2
  34. package/site-templates/marketing-site/ailk-template.json +1 -1
  35. package/site-templates/marketing-site-free/DESIGN.md +148 -0
  36. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +2 -2
  37. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +1 -0
  38. package/site-templates/minimalism-site/DESIGN.md +148 -0
  39. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +10 -2
  40. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +47 -35
  41. package/site-templates/minimalism-site/ailk-template.json +2 -1
  42. package/site-templates/minimalism-site/assets/wordmark-placeholder.svg +28 -0
  43. package/site-templates/minimalism-site/content/en/HomePage/home.mdx +49 -19
  44. package/site-templates/saas-product/DESIGN.md +148 -0
  45. package/site-templates/simple-service/DESIGN.md +148 -0
  46. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +240 -0
  47. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +278 -0
  48. package/site-templates/simple-service/ailk-template.json +10 -0
  49. package/site-templates/simple-service/content/en/AboutPage/about.mdx +38 -0
  50. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +67 -0
  51. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +56 -0
  52. package/site-templates/simple-service/content/en/HomePage/home.mdx +85 -0
  53. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +40 -0
  54. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +40 -0
  55. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +40 -0
  56. package/site-templates/simple-service/content/en/ServicesList/services.mdx +72 -0
  57. package/site-templates/simple-service/provenance.json +4 -0
  58. package/templates/.env.example +72 -7
  59. package/templates/CLAUDE.md +2 -3
  60. package/templates/DESIGN.md +155 -0
  61. package/templates/README.md +42 -8
  62. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +8 -0
  63. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +12 -0
  64. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +12 -0
  65. package/templates/apps/api/.env.example +13 -0
  66. package/templates/apps/api/CLAUDE.md +26 -2
  67. package/templates/apps/api/jest.config.cjs +3 -0
  68. package/templates/apps/api/package.json +1 -0
  69. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +407 -0
  70. package/templates/apps/api/src/__tests__/module-exclusion.test.ts +83 -7
  71. package/templates/apps/api/src/__tests__/server.test.ts +471 -0
  72. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +45 -0
  73. package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +2 -0
  74. package/templates/apps/api/src/config/index.ts +62 -0
  75. package/templates/apps/api/src/config/modules.ts +7 -3
  76. package/templates/apps/api/src/lib/__mocks__/prisma.ts +238 -2
  77. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +143 -0
  78. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +23 -0
  79. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +125 -0
  80. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +20 -0
  81. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +317 -0
  82. package/templates/apps/api/src/lib/__tests__/site.test.ts +238 -0
  83. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +75 -0
  84. package/templates/apps/api/src/lib/auth-email-budget.ts +160 -0
  85. package/templates/apps/api/src/lib/content-adapter.ts +57 -31
  86. package/templates/apps/api/src/lib/deliverable-asset-store.ts +76 -0
  87. package/templates/apps/api/src/lib/error-serializer.ts +23 -3
  88. package/templates/apps/api/src/lib/outbound-http.ts +7 -2
  89. package/templates/apps/api/src/lib/require-commerce-claim.ts +250 -0
  90. package/templates/apps/api/src/lib/site.ts +208 -9
  91. package/templates/apps/api/src/lib/stripe.ts +66 -0
  92. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +182 -0
  93. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +42 -0
  94. package/templates/apps/api/src/middleware/rate-limit.ts +7 -1
  95. package/templates/apps/api/src/openapi/spec.ts +543 -2
  96. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +48 -0
  97. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +309 -0
  98. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +123 -0
  99. package/templates/apps/api/src/routes/auth/transactional-email.ts +273 -0
  100. package/templates/apps/api/src/routes/auth/user.ts +61 -0
  101. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +434 -0
  102. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +888 -0
  103. package/templates/apps/api/src/routes/checkout/index.ts +34 -0
  104. package/templates/apps/api/src/routes/checkout/session.ts +139 -0
  105. package/templates/apps/api/src/routes/checkout/sessions.ts +197 -0
  106. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +554 -0
  107. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +108 -0
  108. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +450 -0
  109. package/templates/apps/api/src/routes/content/get-page.ts +94 -12
  110. package/templates/apps/api/src/routes/content/index.ts +13 -73
  111. package/templates/apps/api/src/routes/content/list-pages.ts +15 -3
  112. package/templates/apps/api/src/routes/content/rate-limit.ts +15 -6
  113. package/templates/apps/api/src/routes/content/search.ts +129 -0
  114. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +447 -31
  115. package/templates/apps/api/src/routes/leads/index.ts +100 -13
  116. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +51 -0
  117. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +351 -0
  118. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +51 -0
  119. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -2
  120. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +4 -1
  121. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +58 -0
  122. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +107 -6
  123. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +87 -2
  124. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +51 -0
  125. package/templates/apps/api/src/routes/project-listings/start.ts +5 -1
  126. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +686 -0
  127. package/templates/apps/api/src/routes/requests/confirm.ts +601 -0
  128. package/templates/apps/api/src/routes/requests/index.ts +54 -0
  129. package/templates/apps/api/src/routes/webhooks/README.md +265 -0
  130. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +749 -0
  131. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +330 -0
  132. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +262 -0
  133. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +285 -0
  134. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +213 -0
  135. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +301 -0
  136. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +648 -0
  137. package/templates/apps/api/src/routes/webhooks/index.ts +89 -0
  138. package/templates/apps/api/src/routes/webhooks/stripe.ts +1399 -0
  139. package/templates/apps/api/src/server.ts +439 -49
  140. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +39 -0
  141. package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +217 -40
  142. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +620 -0
  143. package/templates/apps/api/src/services/__tests__/consent.test.ts +2 -0
  144. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +300 -5
  145. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +20 -0
  146. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +368 -0
  147. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +160 -0
  148. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +166 -0
  149. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +154 -0
  150. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +137 -0
  151. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +444 -0
  152. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +238 -0
  153. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +78 -0
  154. package/templates/apps/api/src/services/abandon-email.ts +8 -2
  155. package/templates/apps/api/src/services/aeo-score.ts +49 -12
  156. package/templates/apps/api/src/services/audit-log.ts +668 -0
  157. package/templates/apps/api/src/services/consent.ts +18 -0
  158. package/templates/apps/api/src/services/default-tenant.ts +70 -31
  159. package/templates/apps/api/src/services/deliverable-fulfillment.ts +141 -13
  160. package/templates/apps/api/src/services/dunning-policy.ts +294 -0
  161. package/templates/apps/api/src/services/entitlements.ts +80 -0
  162. package/templates/apps/api/src/services/lead-promotion.ts +13 -14
  163. package/templates/apps/api/src/services/lead-routing.ts +161 -2
  164. package/templates/apps/api/src/services/leads-inbox.ts +23 -2
  165. package/templates/apps/api/src/services/listing-config.ts +27 -9
  166. package/templates/apps/api/src/services/project-listings.ts +201 -6
  167. package/templates/apps/api/src/services/public-site-resolver.ts +106 -0
  168. package/templates/apps/api/src/services/request-confirm.ts +646 -0
  169. package/templates/apps/api/src/services/revalidation.ts +173 -0
  170. package/templates/apps/api/src/services/verified-email.ts +71 -0
  171. package/templates/apps/api/src/vercel-handler.ts +75 -35
  172. package/templates/apps/mcp/.env.example +17 -0
  173. package/templates/apps/mcp/CLAUDE.md +57 -24
  174. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +6 -0
  175. package/templates/apps/mcp/__tests__/audit.test.ts +137 -8
  176. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +79 -36
  177. package/templates/apps/mcp/__tests__/get_offerings.test.ts +111 -2
  178. package/templates/apps/mcp/__tests__/get_pricing.test.ts +82 -2
  179. package/templates/apps/mcp/__tests__/http-transport.test.ts +541 -2
  180. package/templates/apps/mcp/__tests__/index.test.ts +39 -0
  181. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +143 -0
  182. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +111 -0
  183. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +65 -0
  184. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +188 -0
  185. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +165 -0
  186. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +124 -0
  187. package/templates/apps/mcp/__tests__/list_pages.test.ts +116 -0
  188. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +7 -1
  189. package/templates/apps/mcp/__tests__/parity.test.ts +10 -7
  190. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +89 -22
  191. package/templates/apps/mcp/__tests__/read_content.test.ts +322 -1
  192. package/templates/apps/mcp/__tests__/search_content.test.ts +105 -2
  193. package/templates/apps/mcp/__tests__/server.test.ts +67 -14
  194. package/templates/apps/mcp/__tests__/start_purchase.test.ts +252 -0
  195. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +300 -123
  196. package/templates/apps/mcp/jest.config.cjs +13 -0
  197. package/templates/apps/mcp/package.json +2 -0
  198. package/templates/apps/mcp/src/abuse/index.ts +159 -24
  199. package/templates/apps/mcp/src/config/modules.ts +10 -5
  200. package/templates/apps/mcp/src/http-transport.ts +102 -29
  201. package/templates/apps/mcp/src/index.ts +73 -11
  202. package/templates/apps/mcp/src/lib/audit-single-page.ts +90 -3
  203. package/templates/apps/mcp/src/lib/commerce-claim.ts +94 -0
  204. package/templates/apps/mcp/src/lib/content-adapter.ts +113 -0
  205. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +139 -0
  206. package/templates/apps/mcp/src/lib/prisma.ts +39 -0
  207. package/templates/apps/mcp/src/lib/public-workspace.ts +133 -0
  208. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +59 -0
  209. package/templates/apps/mcp/src/server.ts +59 -35
  210. package/templates/apps/mcp/src/tools/audit.ts +26 -2
  211. package/templates/apps/mcp/src/tools/get_business_hours.ts +4 -3
  212. package/templates/apps/mcp/src/tools/get_faq.ts +4 -3
  213. package/templates/apps/mcp/src/tools/get_locations.ts +5 -3
  214. package/templates/apps/mcp/src/tools/get_offerings.ts +16 -4
  215. package/templates/apps/mcp/src/tools/get_pricing.ts +25 -6
  216. package/templates/apps/mcp/src/tools/get_site_info.ts +4 -3
  217. package/templates/apps/mcp/src/tools/index.ts +6 -4
  218. package/templates/apps/mcp/src/tools/list_pages.ts +4 -3
  219. package/templates/apps/mcp/src/tools/purchase.ts +128 -45
  220. package/templates/apps/mcp/src/tools/read_content.ts +20 -6
  221. package/templates/apps/mcp/src/tools/search_content.ts +11 -4
  222. package/templates/apps/web/.env.example +71 -5
  223. package/templates/apps/web/CLAUDE.md +44 -0
  224. package/templates/apps/web/PRODUCT.md +86 -0
  225. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +18 -2
  226. package/templates/apps/web/app/.well-known/mcp.json/route.ts +11 -3
  227. package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +282 -0
  228. package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +515 -0
  229. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +89 -0
  230. package/templates/apps/web/app/[locale]/(auth)/forgot-password/page.tsx +109 -0
  231. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +92 -0
  232. package/templates/apps/web/app/[locale]/(auth)/reset-password/page.tsx +135 -0
  233. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +109 -0
  234. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/page.test.tsx +48 -2
  235. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/page.tsx +20 -6
  236. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +125 -0
  237. package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +96 -0
  238. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +101 -0
  239. package/templates/apps/web/app/[locale]/(auth)/use-auth-card-flow.ts +102 -0
  240. package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +87 -0
  241. package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +20 -10
  242. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +84 -0
  243. package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +58 -0
  244. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +63 -8
  245. package/templates/apps/web/app/[locale]/(authed)/layout.tsx +18 -1
  246. package/templates/apps/web/app/[locale]/cancellation/page.tsx +44 -0
  247. package/templates/apps/web/app/[locale]/layout.tsx +133 -87
  248. package/templates/apps/web/app/[locale]/purchase/__tests__/cancel.test.tsx +162 -0
  249. package/templates/apps/web/app/[locale]/purchase/__tests__/module-scope.test.ts +68 -0
  250. package/templates/apps/web/app/[locale]/purchase/__tests__/success.test.tsx +361 -0
  251. package/templates/apps/web/app/[locale]/purchase/cancel/page.tsx +115 -0
  252. package/templates/apps/web/app/[locale]/purchase/success/page.tsx +307 -0
  253. package/templates/apps/web/app/[locale]/returns/page.tsx +44 -0
  254. package/templates/apps/web/app/[locale]/shipping/page.tsx +44 -0
  255. package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +670 -0
  256. package/templates/apps/web/app/api/revalidate/route.ts +194 -0
  257. package/templates/apps/web/auth.ts +407 -8
  258. package/templates/apps/web/jest.config.cjs +8 -4
  259. package/templates/apps/web/lib/__tests__/auth-email.test.ts +214 -0
  260. package/templates/apps/web/lib/__tests__/auth-routes.test.ts +74 -0
  261. package/templates/apps/web/lib/__tests__/meeting-slugs.test.ts +72 -0
  262. package/templates/apps/web/lib/__tests__/site-theme.test.ts +135 -20
  263. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +18 -1
  264. package/templates/apps/web/lib/auth-email.ts +318 -0
  265. package/templates/apps/web/lib/auth-env.ts +85 -0
  266. package/templates/apps/web/lib/auth-routes.ts +55 -0
  267. package/templates/apps/web/lib/meeting-slugs.ts +53 -0
  268. package/templates/apps/web/lib/site-brand.tsx +4 -8
  269. package/templates/apps/web/lib/telemetry-scrub.ts +5 -1
  270. package/templates/apps/web/messages/en.json +187 -0
  271. package/templates/apps/web/middleware.ts +1 -1
  272. package/templates/apps/web/package.json +2 -1
  273. package/templates/apps/web/src/lib/commerce-claim.ts +33 -0
  274. package/templates/apps/web/src/lib/commerce-sections.ts +93 -0
  275. package/templates/content/_site.mdx +18 -3
  276. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +108 -0
  277. package/templates/content/en/ReturnsPolicyPage/returns.mdx +108 -0
  278. package/templates/content/en/ShippingPolicyPage/shipping.mdx +108 -0
  279. package/templates/database/CHANGELOG.md +149 -0
  280. package/templates/database/README.md +10 -3
  281. package/templates/database/__tests__/appointment.db.test.ts +106 -0
  282. package/templates/database/__tests__/artifact-content-store.db.test.ts +316 -0
  283. package/templates/database/__tests__/composite-fence.db.test.ts +206 -0
  284. package/templates/database/__tests__/fence-fan-out.db.test.ts +711 -0
  285. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +79 -0
  286. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +100 -0
  287. package/templates/database/__tests__/flow-workspace-key.db.test.ts +263 -0
  288. package/templates/database/__tests__/prefixed-ids.db.test.ts +85 -9
  289. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +111 -0
  290. package/templates/database/__tests__/tenancy.test.ts +141 -0
  291. package/templates/database/config/schema.prisma +79 -2
  292. package/templates/database/content/schema.prisma +87 -11
  293. package/templates/database/inbox/schema.prisma +452 -9
  294. package/templates/database/jest.config.cjs +5 -3
  295. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +15 -0
  296. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +158 -0
  297. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +40 -0
  298. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +67 -0
  299. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +70 -0
  300. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +181 -0
  301. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +172 -0
  302. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +41 -0
  303. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +185 -0
  304. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +70 -0
  305. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +57 -0
  306. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +68 -0
  307. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +1067 -0
  308. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +210 -0
  309. package/templates/database/package.json +3 -2
  310. package/templates/database/tenancy.ts +86 -1
  311. package/templates/database/tsconfig.json +1 -0
  312. package/versions.json +34 -34
  313. package/templates/apps/api/src/routes/content/__tests__/create.test.ts +0 -253
  314. package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +0 -215
  315. package/templates/apps/api/src/routes/content/__tests__/update.test.ts +0 -266
  316. package/templates/apps/api/src/routes/content/create.ts +0 -115
  317. package/templates/apps/api/src/routes/content/delete.ts +0 -82
  318. package/templates/apps/api/src/routes/content/update.ts +0 -112
  319. package/templates/apps/mcp/__tests__/create_page.test.ts +0 -202
  320. package/templates/apps/mcp/__tests__/delete_page.test.ts +0 -177
  321. package/templates/apps/mcp/__tests__/update_page.test.ts +0 -196
  322. package/templates/apps/mcp/src/tools/create_page.ts +0 -96
  323. package/templates/apps/mcp/src/tools/delete_page.ts +0 -74
  324. package/templates/apps/mcp/src/tools/update_page.ts +0 -92
  325. package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +0 -123
  326. package/templates/apps/web/public/logo-dark.svg +0 -21
  327. package/templates/apps/web/public/logo-light.svg +0 -21
  328. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/next-path.test.ts +0 -0
  329. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/next-path.ts +0 -0
@@ -83,8 +83,10 @@ import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
83
83
  import { pipeline } from "node:stream/promises";
84
84
  import { createGunzip } from "node:zlib";
85
85
  import * as tar from "tar";
86
+ import { isTextFile } from "../copy.js";
86
87
  import { coOwnedModuleDestinations, } from "../module-architecture.js";
87
88
  import { validateTemplateLayout, } from "../site-chrome.js";
89
+ import { substituteMarkers, } from "../substitute.js";
88
90
  import { computeModulePatches, writeModulePatches } from "./apply-module-patches.js";
89
91
  /** Soft limits to prevent decompression-bomb / zip-bomb attacks. Same values as extractBundle. */
90
92
  const MAX_ENTRIES = 1000;
@@ -446,6 +448,7 @@ export async function extractModuleBundle(options) {
446
448
  : {}),
447
449
  ...(options.ownership !== undefined ? { ownership: options.ownership } : {}),
448
450
  ...(options.versions !== undefined ? { versions: options.versions } : {}),
451
+ ...(options.markers !== undefined ? { markers: options.markers } : {}),
449
452
  });
450
453
  }
451
454
  finally {
@@ -463,7 +466,7 @@ export async function extractModuleBundle(options) {
463
466
  * rejected tree leaves `targetDir` exactly as it was.
464
467
  */
465
468
  export function installBundleTree(options) {
466
- const { sourceRoot, name, templateRequires, templateExtends, ownership } = options;
469
+ const { sourceRoot, name, templateRequires, templateExtends, ownership, markers } = options;
467
470
  const targetAbs = resolve(options.targetDir);
468
471
  const isTemplate = templateRequires !== undefined;
469
472
  const subject = isTemplate ? `template "${name}"` : `module "${name}"`;
@@ -526,6 +529,17 @@ export function installBundleTree(options) {
526
529
  // installMap destination) is read from the STAGED tree here, since
527
530
  // targetDir would not have it yet at this point.
528
531
  const installMapDestinationToSource = new Map(Object.entries(installMap).map(([source, destination]) => [destination, source]));
532
+ // #6460 — a patch target is read RAW from the staged tree here, while
533
+ // `copyTree` below writes the same path SUBSTITUTED, and
534
+ // `writeModulePatches` runs after `copyTree`. So a file a bundle both
535
+ // delivers as plain content AND patches would end up carrying unsubstituted
536
+ // markers. Unreachable today and asserted as such rather than guarded: the
537
+ // only patch targets any slice declares are `apps/web/package.json`,
538
+ // `next.config.mjs` and `jest.config.cjs`, all three delivered by the base
539
+ // `templates/` snapshot rather than by a bundle — so this reader falls
540
+ // through to the `targetAbs` branch and reads already-substituted bytes —
541
+ // and a template is refused `patches` outright above. A bundle that starts
542
+ // delivering one of its own patch targets must substitute here too.
529
543
  const readPatchTarget = (target) => {
530
544
  const mappedSource = installMapDestinationToSource.get(target);
531
545
  if (mappedSource !== undefined) {
@@ -550,11 +564,18 @@ export function installBundleTree(options) {
550
564
  // every installMap source are excluded from the whole-tree copy — the
551
565
  // manifest never lands in the scaffold, and a mapped source lands ONLY
552
566
  // at its mapped destination, never also at its original path.
553
- copyTree(sourceRoot, targetAbs, excluded);
567
+ copyTree(sourceRoot, targetAbs, excluded, markers);
554
568
  for (const [source, destination] of Object.entries(installMap)) {
555
569
  const destAbs = resolve(targetAbs, destination);
556
570
  mkdirSync(join(destAbs, ".."), { recursive: true });
557
- copyFileSync(resolve(sourceRoot, source), destAbs);
571
+ // BOTH ends decide text-ness (#6460), because an installMap entry is free
572
+ // to rename across the boundary and the two mismatches are not
573
+ // symmetric: a text source landing at a binary name merely misses a
574
+ // substitution, while a BINARY source landing at a text name would be
575
+ // read as utf8 and rewritten, turning every invalid byte sequence into
576
+ // U+FFFD — silent, unrecoverable corruption. Requiring both makes the
577
+ // safe direction structural rather than a property of today's manifests.
578
+ writeOneFile(resolve(sourceRoot, source), destAbs, [source, destination], markers);
558
579
  }
559
580
  // patches write AFTER every file the tree brought is in place (D5) —
560
581
  // after installMap, before postInstall — so a patch can never race a
@@ -589,8 +610,11 @@ export function installBundleTree(options) {
589
610
  * `safeExtractTarGz` has validated every entry, so no additional
590
611
  * path-safety check is needed here — `srcRoot` is our own staging tree, not
591
612
  * attacker-controlled input.
613
+ *
614
+ * `markers`, when given, is substituted into every TEXT file on the way
615
+ * through (#6460) — see `InstallBundleTreeOptions.markers`.
592
616
  */
593
- function copyTree(srcRoot, destRoot, excluded = new Set()) {
617
+ function copyTree(srcRoot, destRoot, excluded = new Set(), markers) {
594
618
  const stack = [srcRoot];
595
619
  while (stack.length > 0) {
596
620
  const dir = stack.pop();
@@ -608,12 +632,47 @@ function copyTree(srcRoot, destRoot, excluded = new Set()) {
608
632
  if (excluded.has(rel.split(sep).join("/")))
609
633
  continue;
610
634
  mkdirSync(join(destPath, ".."), { recursive: true });
611
- copyFileSync(srcPath, destPath);
635
+ writeOneFile(srcPath, destPath, [rel], markers);
612
636
  }
613
637
  // symlinks: never present — safeExtractTarGz rejects them outright.
614
638
  }
615
639
  }
616
640
  }
641
+ /**
642
+ * Land one file at `destAbs`, substituting `markers` into it when EVERY path
643
+ * in `relsForType` is text by `copy.ts`'s own `isTextFile` (#6460) — the
644
+ * source's relative path alone for a plain-content copy, source AND
645
+ * destination for an installMap entry, which may rename across the
646
+ * text/binary boundary. Unanimity rather than either-or, so binary content is
647
+ * never round-tripped through a utf8 string by construction; see the
648
+ * installMap loop for why the two mismatch directions are not symmetric.
649
+ *
650
+ * With no `markers`, or with any non-text path, this is exactly the
651
+ * `copyFileSync` it replaced.
652
+ *
653
+ * `isTextFile` is an allowlist of extensions, NOT "anything that parses as
654
+ * text": `.css`, `.html`, `.svg`, `.sh`, `.toml` and `.sql` are outside it, so
655
+ * a marker authored in one of those survives verbatim. That is pre-existing
656
+ * `copyTemplate` behaviour, deliberately shared rather than forked here.
657
+ *
658
+ * The source's mode rides along, because `copyFileSync` preserves it and
659
+ * `writeFileSync` does not: no tree this installs carries an executable file
660
+ * today, but a module slice is free to ship one, and a substituted `.mjs`
661
+ * silently losing its `+x` surfaces as "the scaffold builds but the hook never
662
+ * runs". Masked to the permission bits — `statSync().mode` carries the
663
+ * `S_IFREG` type bits too, which `open(2)` ignores but which have no business
664
+ * being passed. Like `copyFileSync`, this only sets the mode when the file is
665
+ * CREATED: an overwrite (the layer-over-layer case) keeps the existing one.
666
+ */
667
+ function writeOneFile(srcAbs, destAbs, relsForType, markers) {
668
+ if (markers === undefined || !relsForType.every(isTextFile)) {
669
+ copyFileSync(srcAbs, destAbs);
670
+ return;
671
+ }
672
+ writeFileSync(destAbs, substituteMarkers(readFileSync(srcAbs, "utf8"), markers), {
673
+ mode: statSync(srcAbs).mode & 0o777,
674
+ });
675
+ }
617
676
  /**
618
677
  * `extractBundle`'s validating-filter tar extraction, ported verbatim (see
619
678
  * file doc for why this is a port and not an import). Extracts `tarGzPath`
@@ -0,0 +1,29 @@
1
+ export declare const SOURCE_EXTS: string[];
2
+ /** Every source file under the given repo-relative roots, as "/"-joined paths. */
3
+ export declare function listFilesUnder(repoRoot: string, roots: string[]): Set<string>;
4
+ /** The relative import specifiers a source file names (static imports + re-exports). */
5
+ export declare function relativeImportsOf(absPath: string): string[];
6
+ /**
7
+ * Resolve a relative specifier against the candidate set. TypeScript ESM writes
8
+ * `./x.js` for `./x.ts`, so the `.js` → `.ts`/`.tsx` rewrite is the common case.
9
+ */
10
+ export declare function resolveRelativeImport(fromFile: string, spec: string, candidates: Set<string>): string | undefined;
11
+ /**
12
+ * The companion closure of `seeds` under `roots`: the seeds themselves plus
13
+ * every source file under `roots` that reaches one transitively through a
14
+ * relative import, to a fixed point.
15
+ *
16
+ * This is the shape both consumers need, and the reason the walk is shared
17
+ * rather than copied. `paidModuleTemplateExclusions()` seeds it with every
18
+ * paid module's `ownedFiles` to get the files a keyless starter must not
19
+ * carry; `tools/lint-slice-registration.ts` seeds it with the same set to
20
+ * derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
21
+ *
22
+ * Never a filename-stem rule (#5182 D7), which misses eleven files and
23
+ * over-marks three.
24
+ *
25
+ * @param repoRoot absolute path to the tree being walked.
26
+ * @param roots repo-relative roots the walk is confined to.
27
+ * @param seeds repo-relative, "/"-separated files the closure starts from.
28
+ */
29
+ export declare function importClosure(repoRoot: string, roots: readonly string[], seeds: Iterable<string>): Set<string>;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The relative-import graph walker over a repo-relative source tree.
3
+ *
4
+ * Extracted from `module-architecture.ts` (#5701) so the two consumers that
5
+ * need this resolution share ONE implementation rather than two that can
6
+ * disagree:
7
+ *
8
+ * - `paidModuleTemplateExclusions()` (module-architecture.ts) walks it to take
9
+ * the companion closure of every paid module's `ownedFiles` — the files that
10
+ * would ship dangling into a keyless starter.
11
+ * - `tools/lint-slice-registration.ts` walks it to close over the specifiers an
12
+ * `isModuleEnabled("X")` branch in `apps/api/src/server.ts` loads, and to
13
+ * check every reached file against what module X's slice delivers.
14
+ *
15
+ * Both questions are "which files does this one reach through relative
16
+ * imports", and the answer must be the same function in both mouths: a lint
17
+ * that resolved specifiers differently from the exclusion set it checks
18
+ * against would pass on a tree the scaffold cannot boot.
19
+ *
20
+ * The resolution is deliberately TEXTUAL — a regex over import/export
21
+ * specifiers plus a candidate-set lookup, no type-checker and no bundler — so
22
+ * it runs inside `pnpm preflight`'s memory budget.
23
+ */
24
+ import { readFileSync, readdirSync } from "node:fs";
25
+ import { dirname, join, sep } from "node:path";
26
+ export const SOURCE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
27
+ /** Every source file under the given repo-relative roots, as "/"-joined paths. */
28
+ export function listFilesUnder(repoRoot, roots) {
29
+ const out = new Set();
30
+ const skip = new Set(["node_modules", ".next", "dist", ".turbo", ".source"]);
31
+ const stack = roots.map((r) => r);
32
+ while (stack.length > 0) {
33
+ const rel = stack.pop();
34
+ const abs = join(repoRoot, rel);
35
+ let entries;
36
+ try {
37
+ entries = readdirSync(abs, { withFileTypes: true });
38
+ }
39
+ catch {
40
+ continue;
41
+ }
42
+ for (const entry of entries) {
43
+ if (skip.has(entry.name))
44
+ continue;
45
+ const childRel = `${rel}/${entry.name}`;
46
+ if (entry.isDirectory())
47
+ stack.push(childRel);
48
+ else if (SOURCE_EXTS.some((e) => entry.name.endsWith(e)))
49
+ out.add(childRel);
50
+ }
51
+ }
52
+ return out;
53
+ }
54
+ /** The relative import specifiers a source file names (static imports + re-exports). */
55
+ export function relativeImportsOf(absPath) {
56
+ let src;
57
+ try {
58
+ src = readFileSync(absPath, "utf8");
59
+ }
60
+ catch {
61
+ return [];
62
+ }
63
+ const out = [];
64
+ for (const m of src.matchAll(/(?:^|\n)\s*(?:import|export)[\s\S]{0,400}?from\s*["'](\.[^"']*)["']/g))
65
+ out.push(m[1]);
66
+ for (const m of src.matchAll(/\bimport\s*\(\s*["'](\.[^"']*)["']\s*\)/g))
67
+ out.push(m[1]);
68
+ return out;
69
+ }
70
+ /**
71
+ * Resolve a relative specifier against the candidate set. TypeScript ESM writes
72
+ * `./x.js` for `./x.ts`, so the `.js` → `.ts`/`.tsx` rewrite is the common case.
73
+ */
74
+ export function resolveRelativeImport(fromFile, spec, candidates) {
75
+ const base = posixJoin(dirname(fromFile.split("/").join(sep)), spec);
76
+ const stem = base.replace(/\.(js|jsx|mjs|cjs)$/, "");
77
+ for (const cand of [
78
+ base,
79
+ ...SOURCE_EXTS.map((e) => stem + e),
80
+ ...SOURCE_EXTS.map((e) => `${stem}/index${e}`),
81
+ ])
82
+ if (candidates.has(cand))
83
+ return cand;
84
+ return undefined;
85
+ }
86
+ /** Join and normalize a "/"-separated path, resolving `.` and `..` segments. */
87
+ function posixJoin(dir, spec) {
88
+ const parts = `${dir.split(sep).join("/")}/${spec}`.split("/");
89
+ const out = [];
90
+ for (const part of parts) {
91
+ if (part === "" || part === ".")
92
+ continue;
93
+ if (part === "..")
94
+ out.pop();
95
+ else
96
+ out.push(part);
97
+ }
98
+ return out.join("/");
99
+ }
100
+ /**
101
+ * The companion closure of `seeds` under `roots`: the seeds themselves plus
102
+ * every source file under `roots` that reaches one transitively through a
103
+ * relative import, to a fixed point.
104
+ *
105
+ * This is the shape both consumers need, and the reason the walk is shared
106
+ * rather than copied. `paidModuleTemplateExclusions()` seeds it with every
107
+ * paid module's `ownedFiles` to get the files a keyless starter must not
108
+ * carry; `tools/lint-slice-registration.ts` seeds it with the same set to
109
+ * derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
110
+ *
111
+ * Never a filename-stem rule (#5182 D7), which misses eleven files and
112
+ * over-marks three.
113
+ *
114
+ * @param repoRoot absolute path to the tree being walked.
115
+ * @param roots repo-relative roots the walk is confined to.
116
+ * @param seeds repo-relative, "/"-separated files the closure starts from.
117
+ */
118
+ export function importClosure(repoRoot, roots, seeds) {
119
+ const closed = new Set(seeds);
120
+ const candidates = listFilesUnder(repoRoot, [...roots]);
121
+ for (;;) {
122
+ let grew = false;
123
+ for (const file of candidates) {
124
+ if (closed.has(file))
125
+ continue;
126
+ const imports = relativeImportsOf(join(repoRoot, file));
127
+ for (const spec of imports) {
128
+ const target = resolveRelativeImport(file, spec, candidates);
129
+ if (target !== undefined && closed.has(target)) {
130
+ closed.add(file);
131
+ grew = true;
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ if (!grew)
137
+ break;
138
+ }
139
+ return closed;
140
+ }
@@ -18,7 +18,12 @@
18
18
  * gate (K1's regression floor).
19
19
  */
20
20
  import type { ModuleName } from "../parse-args.js";
21
- export declare const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pro";
21
+ /**
22
+ * Where a refused run sends the buyer. `/pricing`, not `/pro`: there is no
23
+ * `/pro` route and there will not be one (#6439, operator decision OD-2) —
24
+ * pricing is where every level and the commerce add-on are actually listed.
25
+ */
26
+ export declare const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pricing";
22
27
  /**
23
28
  * Thrown for both honest-denial states (no key, and an invalid/lapsed key).
24
29
  * The CLI does not distinguish them in its exit code — both are "this run
@@ -1,5 +1,10 @@
1
1
  import { FetchModuleError, fetchModule } from "./fetch-module.js";
2
- export const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pro";
2
+ /**
3
+ * Where a refused run sends the buyer. `/pricing`, not `/pro`: there is no
4
+ * `/pro` route and there will not be one (#6439, operator decision OD-2) —
5
+ * pricing is where every level and the commerce add-on are actually listed.
6
+ */
7
+ export const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pricing";
3
8
  /**
4
9
  * Thrown for both honest-denial states (no key, and an invalid/lapsed key).
5
10
  * The CLI does not distinguish them in its exit code — both are "this run
@@ -15,6 +15,6 @@ export function proCallout() {
15
15
  "your business, generates a vertical-aware page plan, configures",
16
16
  "Stripe / auth / lead routing / analytics, and sets up your",
17
17
  "GitHub→Vercel deploy — all in one orchestrated flow. Or invoke the",
18
- "free scaffolders one at a time → ailaunchkit.ai/pro",
18
+ "free scaffolders one at a time → ailaunchkit.ai/pricing",
19
19
  ].join("\n");
20
20
  }
@@ -397,4 +397,5 @@ export declare function normalizeModules(modules: string[]): ModuleName[];
397
397
  * whole invariant.
398
398
  */
399
399
  export declare function coOwnedModuleDestinations(): ReadonlySet<string>;
400
+ export declare const EXCLUDE_TEMPLATE_DIRS: readonly string[];
400
401
  export declare function paidModuleTemplateExclusions(snapshotRoots: readonly string[], repoRoot: string): string[];