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
@@ -0,0 +1,307 @@
1
+ // oss: false
2
+ /**
3
+ * /[locale]/purchase/success — the order-confirmation return page (#6084).
4
+ *
5
+ * NOTE on `// oss: false` — a DELIBERATE correction to the spec's NFR-4,
6
+ * which assumed this page could ship unmarked like the base-tree checkout
7
+ * API primitives (`routes/checkout/sessions.ts`, `tools/purchase.ts`). Those
8
+ * import only OSS `@working-theory/stripe-client`; THIS page renders
9
+ * `payment-receipt` via `registerCommerceSections()` from the PAID
10
+ * `@working-theory/ui-commerce` package (D5) — the same shape `/meet`
11
+ * already has for `@working-theory/ui-scheduling`. The architecture lint's
12
+ * OSS→paid boundary rule (`architecture.yaml` forbidden_patterns) requires
13
+ * either no marker + no paid import, or a `paths_excluded` entry PLUS this
14
+ * marker (the `meet/**` precedent) — never no-marker-with-a-paid-import.
15
+ * `create-ailk`'s scaffold is UNAFFECTED: `CORE_ROUTE_DIRS`
16
+ * (`packages/create-ailk/src/surfaces.ts`) governs what a scaffold carries,
17
+ * not this marker, so AC-4/FR-8 still hold — every scaffold gets this file
18
+ * regardless. Only the ai-launch-kit-internal → ai-launch-kit PUBLIC-REPO
19
+ * split (a different mechanism) reads this marker.
20
+ *
21
+ * READS the Checkout Session the Stripe webhook already granted (spec §1.2)
22
+ * — this page never writes: no Prisma call, no Stripe write, no grant, no
23
+ * stamp (AC-1, FR-3). It is reachable by anyone holding a `cs_…` id, with
24
+ * no credential at all (D8) — the design below is built around that fact.
25
+ *
26
+ * D6 — the paid render is not forgeable. `outcome: "success"` is Stripe's
27
+ * proof-of-payment status (a green chip, `data-outcome="success"`, and a
28
+ * schema.org `PaymentComplete` node — `PaymentResult.tsx`), so the
29
+ * `payment-receipt` section is constructed ONLY on a 2xx read with
30
+ * `paymentStatus === "paid"`. Every other reachable state — no
31
+ * `session_id`, an API failure, or a 2xx read that is not yet paid —
32
+ * renders a DIFFERENT chassis (`content-block` → `cta`, not a
33
+ * `CheckoutDeliveryPage`) with no badge, no `data-outcome` and no
34
+ * `PaymentComplete` string anywhere in the DOM (AC-8).
35
+ *
36
+ * D12 — base tree, request-time gate. This page ships unconditionally in
37
+ * every scaffold; whether it SERVES is decided per request by the
38
+ * `commerce` licence claim (`../../../../src/lib/commerce-claim.ts`,
39
+ * extracted from `.well-known/mcp.json`'s own check). `notFound()` on no
40
+ * claim is indistinguishable from a build without the module — before any
41
+ * API call, before any render.
42
+ *
43
+ * The `ui-commerce` package itself is registered LAZILY
44
+ * (`../../../../src/lib/commerce-sections.ts`), never via a top-level
45
+ * static import — a keyless scaffold carries no dependency on it by design
46
+ * (#5581 U6/D5), and a static import would fail every keyless build
47
+ * regardless of the request-time gate above. When the module genuinely is
48
+ * not installed, `paidSections()` below falls back to an OSS
49
+ * `content-block` carrying the same confirmation copy, rather than the bare
50
+ * `payment-receipt` section `SectionRenderer` would otherwise silently
51
+ * render as nothing (`ModuleAbsent` in production).
52
+ *
53
+ * `noindex`: reachable only by finishing (or trying) a Checkout, never a
54
+ * page a crawler should list.
55
+ */
56
+ import { checkout } from "@working-theory/api-client";
57
+ import type { CheckoutSessionReadResponse } from "@working-theory/api-client";
58
+ import { SectionRenderer } from "@working-theory/ui/sections";
59
+ import type { PageSection } from "@working-theory/validation";
60
+ import { formatMoney } from "@working-theory/web-i18n";
61
+ import type { Metadata } from "next";
62
+ import { headers } from "next/headers";
63
+ import { notFound } from "next/navigation";
64
+ import { getTranslations } from "next-intl/server";
65
+ import type { ReactElement } from "react";
66
+
67
+ import { resolveCommerceClaim } from "../../../../src/lib/commerce-claim";
68
+ import { ensureCommerceSectionsRegistered } from "../../../../src/lib/commerce-sections";
69
+
70
+ // The success page reads `searchParams` (dynamic by construction); paired
71
+ // with the cancel page's explicit `force-dynamic` so a site that buys
72
+ // commerce after its last deploy is not stuck serving a prerendered 404
73
+ // (D12).
74
+ export const dynamic = "force-dynamic";
75
+
76
+ /**
77
+ * `next-intl`'s `getTranslations()` return type, so it can be passed
78
+ * between the section builders below (this repo has no other precedent
79
+ * typing it explicitly, since no other page passes `t` across functions).
80
+ */
81
+ type PurchaseT = Awaited<ReturnType<typeof getTranslations>>;
82
+
83
+ interface Props {
84
+ params: Promise<{ locale: string }>;
85
+ searchParams?: Promise<{ session_id?: string | string[] }>;
86
+ }
87
+
88
+ /** First value only — a repeated query param must not become an array here. */
89
+ function firstValue(raw: string | string[] | undefined): string | undefined {
90
+ if (Array.isArray(raw)) return raw[0];
91
+ return raw;
92
+ }
93
+
94
+ /**
95
+ * Reads the visitor's real IP from THIS page's own incoming request —
96
+ * never from the query string — preferring `x-forwarded-for` and falling
97
+ * back to `x-real-ip`. Returns `undefined` rather than throwing on any
98
+ * failure. A local copy of `flows/[slug]/checkout.actions.ts`'s identical
99
+ * helper (#4730) — every RSC-to-API caller carries its own copy rather than
100
+ * a shared import, since this one crosses the OSS/paid boundary the other
101
+ * doesn't. Without it, `apps/api`'s rate limiter
102
+ * (`middleware/rate-limit.ts`) sees the Next server's own egress IP for
103
+ * every buyer, collapsing them into one shared bucket (security-review
104
+ * finding on this issue's PR — #6084).
105
+ */
106
+ async function resolveVisitorIpInit(): Promise<
107
+ { headers: Record<string, string> } | undefined
108
+ > {
109
+ try {
110
+ const incoming = await headers();
111
+ const visitorIp =
112
+ incoming.get("x-forwarded-for") ?? incoming.get("x-real-ip");
113
+ return visitorIp
114
+ ? { headers: { "x-forwarded-for": visitorIp } }
115
+ : undefined;
116
+ } catch {
117
+ return undefined;
118
+ }
119
+ }
120
+
121
+ /** The onward `cta` section every one of D6's five rows carries (AC-7 — never a dead end). */
122
+ function ctaSection(t: PurchaseT): PageSection {
123
+ return {
124
+ id: "purchase-success-cta",
125
+ type: "cta",
126
+ data: {
127
+ headline: t("success.ctaHeadline"),
128
+ description: t("success.ctaDescription"),
129
+ primaryCta: { label: t("success.ctaLabel"), href: "/services" },
130
+ },
131
+ };
132
+ }
133
+
134
+ /** One card per paid line item — the D5 seam: `items`, not `payment-receipt`, carries the lines. */
135
+ function itemsSection(
136
+ lineItems: CheckoutSessionReadResponse["lineItems"],
137
+ t: PurchaseT,
138
+ locale: string,
139
+ ): PageSection {
140
+ return {
141
+ id: "purchase-success-items",
142
+ type: "items",
143
+ data: {
144
+ items: lineItems.map((line) => ({
145
+ title: line.description,
146
+ description: t("success.lineItem", {
147
+ quantity: line.quantity,
148
+ amount: formatMoney(line.amountTotal, line.currency, locale),
149
+ }),
150
+ })),
151
+ },
152
+ };
153
+ }
154
+
155
+ /**
156
+ * D6's degraded-state row: no `session_id`, a shape-gate reject, an API
157
+ * 404/non-2xx, or a session that isn't yet paid — all render honestly
158
+ * rather than claiming a payment. `content-block` → `cta`; no
159
+ * `payment-receipt`, so no badge and no schema.org node exists to be read.
160
+ */
161
+ function unknownSections(t: PurchaseT): PageSection[] {
162
+ return [
163
+ {
164
+ id: "purchase-success-unknown",
165
+ type: "content-block",
166
+ data: {
167
+ headline: t("success.unknownHeadline"),
168
+ body: t("success.unknownBody"),
169
+ },
170
+ },
171
+ ctaSection(t),
172
+ ];
173
+ }
174
+
175
+ /** 2xx, `paymentStatus` is `"unpaid"` or `"no_payment_required"` — D6 row 2. */
176
+ function pendingSections(
177
+ session: CheckoutSessionReadResponse,
178
+ t: PurchaseT,
179
+ locale: string,
180
+ ): PageSection[] {
181
+ return [
182
+ {
183
+ id: "purchase-success-pending",
184
+ type: "content-block",
185
+ data: {
186
+ headline: t("success.pendingHeadline"),
187
+ body: t("success.pendingBody"),
188
+ },
189
+ },
190
+ itemsSection(session.lineItems, t, locale),
191
+ ctaSection(t),
192
+ ];
193
+ }
194
+
195
+ /**
196
+ * The OSS degrade for `paidSections()` — carries the same title/message/
197
+ * status copy as `payment-receipt`, minus its badge/schema.org markers, for
198
+ * a deployment where `@working-theory/ui-commerce` is genuinely not
199
+ * installed (a keyless scaffold with a `commerce` licence claim but no
200
+ * redeploy since buying it — `ensureCommerceSectionsRegistered()`'s own
201
+ * doc comment).
202
+ */
203
+ function paidFallbackSection(t: PurchaseT): PageSection {
204
+ return {
205
+ id: "purchase-success-receipt-fallback",
206
+ type: "content-block",
207
+ data: {
208
+ headline: t("success.title"),
209
+ body: `${t("success.message")} ${t("success.statusLabel")}`,
210
+ },
211
+ };
212
+ }
213
+
214
+ /** 2xx AND `paymentStatus === "paid"` — the ONLY row that constructs `payment-receipt` (D6). */
215
+ async function paidSections(
216
+ session: CheckoutSessionReadResponse,
217
+ t: PurchaseT,
218
+ locale: string,
219
+ ): Promise<PageSection[]> {
220
+ const commerceSectionsAvailable = await ensureCommerceSectionsRegistered();
221
+ const receipt: PageSection = commerceSectionsAvailable
222
+ ? {
223
+ id: "purchase-success-receipt",
224
+ type: "payment-receipt",
225
+ data: {
226
+ outcome: "success",
227
+ title: t("success.title"),
228
+ message: t("success.message"),
229
+ statusLabel: t("success.statusLabel"),
230
+ amount: {
231
+ amountMinor: session.amountTotal ?? 0,
232
+ currency: session.currency,
233
+ },
234
+ locale,
235
+ sessionId: session.id,
236
+ sessionIdLabel: t("success.sessionIdLabel"),
237
+ },
238
+ }
239
+ : paidFallbackSection(t);
240
+ return [receipt, itemsSection(session.lineItems, t, locale), ctaSection(t)];
241
+ }
242
+
243
+ /** D6's five-row table, collapsed to the three code paths that produce distinct output. */
244
+ async function sectionsFor(
245
+ sessionId: string | undefined,
246
+ t: PurchaseT,
247
+ locale: string,
248
+ ): Promise<PageSection[]> {
249
+ if (!sessionId) return unknownSections(t);
250
+
251
+ // A malformed/oversized id (D8's shape gate) or an unknown session both
252
+ // answer non-2xx here — the API's failure is logged server-side and never
253
+ // surfaced to the buyer (spec §3 D6 table). `checkout.getSession()` calls
254
+ // `fetch()` directly with no try/catch of its own
255
+ // (`packages/api-client/src/http.ts`), so a network-level failure (the API
256
+ // unreachable, DNS, a dropped connection) REJECTS rather than resolving
257
+ // `{ ok: false }` — caught here so it degrades identically to a non-2xx
258
+ // response instead of crashing the page (AC-7's "never a dead end",
259
+ // code-review finding on this issue's PR).
260
+ let res: Awaited<ReturnType<typeof checkout.getSession>>;
261
+ try {
262
+ res = await checkout.getSession(sessionId, await resolveVisitorIpInit());
263
+ } catch {
264
+ return unknownSections(t);
265
+ }
266
+ if (!res.ok) return unknownSections(t);
267
+
268
+ if (res.body.paymentStatus !== "paid") {
269
+ return pendingSections(res.body, t, locale);
270
+ }
271
+
272
+ return await paidSections(res.body, t, locale);
273
+ }
274
+
275
+ export async function generateMetadata({ params }: Props): Promise<Metadata> {
276
+ const { locale } = await params;
277
+ const t = await getTranslations({ locale, namespace: "purchase" });
278
+ return {
279
+ title: t("success.title"),
280
+ description: t("success.message"),
281
+ robots: { index: false, follow: true },
282
+ };
283
+ }
284
+
285
+ export default async function Page({
286
+ params,
287
+ searchParams,
288
+ }: Props): Promise<ReactElement> {
289
+ const { locale } = await params;
290
+ const t: PurchaseT = await getTranslations({ locale, namespace: "purchase" });
291
+
292
+ // D12 — request-time gate, before any API call and before any render.
293
+ if (!(await resolveCommerceClaim())) {
294
+ notFound();
295
+ }
296
+
297
+ const query = searchParams ? await searchParams : {};
298
+ const sessionId = firstValue(query.session_id);
299
+
300
+ const sections = await sectionsFor(sessionId, t, locale);
301
+
302
+ return (
303
+ <main>
304
+ <SectionRenderer sections={sections} locale={locale} />
305
+ </main>
306
+ );
307
+ }
@@ -0,0 +1,44 @@
1
+ // ReturnsPolicyPage route (#5947). Reads the ReturnsPolicyPage MDX frontmatter, renders sections via
2
+ // SectionRenderer, and emits a JSON-LD <script>.
3
+ import type {
4
+ getMdxSource as defaultGetMdxSource,
5
+ getPageSections as defaultGetPageSections} from "@working-theory/page-renderer";
6
+ import {
7
+ renderPage,
8
+ renderPageMetadata
9
+ } from "@working-theory/page-renderer";
10
+ import type { Metadata } from "next";
11
+ import type { ReactElement } from "react";
12
+
13
+ interface Props {
14
+ params: Promise<{ locale: string }>;
15
+ getMdxSource?: typeof defaultGetMdxSource;
16
+ getPageSections?: typeof defaultGetPageSections;
17
+ }
18
+
19
+ export async function generateMetadata({
20
+ params,
21
+ }: Pick<Props, "params">): Promise<Metadata> {
22
+ const { locale } = await params;
23
+ return renderPageMetadata({ type: "ReturnsPolicyPage", slug: "returns", locale });
24
+ }
25
+
26
+ export default async function Page({
27
+ params,
28
+ getMdxSource,
29
+ getPageSections,
30
+ }: Props): Promise<ReactElement> {
31
+ const { locale } = await params;
32
+ return renderPage({
33
+ type: "ReturnsPolicyPage",
34
+ slug: "returns",
35
+ locale,
36
+ // Without a namespace `renderPage` 404s on a missing seed — and a scaffold
37
+ // IS a missing-seed environment, since `build-templates.mjs` snapshots
38
+ // `apps/` but deliberately not `content/`. The namespace makes this route
39
+ // render the #4154 authoring empty state at 200, exactly as /terms does.
40
+ translationsNamespace: "returns",
41
+ ...(getMdxSource !== undefined && { getMdxSource }),
42
+ ...(getPageSections !== undefined && { getPageSections }),
43
+ });
44
+ }
@@ -0,0 +1,44 @@
1
+ // ShippingPolicyPage route (#5947). Reads the ShippingPolicyPage MDX frontmatter, renders sections via
2
+ // SectionRenderer, and emits a JSON-LD <script>.
3
+ import type {
4
+ getMdxSource as defaultGetMdxSource,
5
+ getPageSections as defaultGetPageSections} from "@working-theory/page-renderer";
6
+ import {
7
+ renderPage,
8
+ renderPageMetadata
9
+ } from "@working-theory/page-renderer";
10
+ import type { Metadata } from "next";
11
+ import type { ReactElement } from "react";
12
+
13
+ interface Props {
14
+ params: Promise<{ locale: string }>;
15
+ getMdxSource?: typeof defaultGetMdxSource;
16
+ getPageSections?: typeof defaultGetPageSections;
17
+ }
18
+
19
+ export async function generateMetadata({
20
+ params,
21
+ }: Pick<Props, "params">): Promise<Metadata> {
22
+ const { locale } = await params;
23
+ return renderPageMetadata({ type: "ShippingPolicyPage", slug: "shipping", locale });
24
+ }
25
+
26
+ export default async function Page({
27
+ params,
28
+ getMdxSource,
29
+ getPageSections,
30
+ }: Props): Promise<ReactElement> {
31
+ const { locale } = await params;
32
+ return renderPage({
33
+ type: "ShippingPolicyPage",
34
+ slug: "shipping",
35
+ locale,
36
+ // Without a namespace `renderPage` 404s on a missing seed — and a scaffold
37
+ // IS a missing-seed environment, since `build-templates.mjs` snapshots
38
+ // `apps/` but deliberately not `content/`. The namespace makes this route
39
+ // render the #4154 authoring empty state at 200, exactly as /terms does.
40
+ translationsNamespace: "shipping",
41
+ ...(getMdxSource !== undefined && { getMdxSource }),
42
+ ...(getPageSections !== undefined && { getPageSections }),
43
+ });
44
+ }