create-ailk 0.6.1 → 0.8.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 (324) hide show
  1. package/README.md +87 -14
  2. package/component-catalog.json +735 -95
  3. package/component-catalog.md +13 -7
  4. package/dist/add-module-core.d.ts +22 -0
  5. package/dist/add-module-core.js +50 -0
  6. package/dist/add-module.d.ts +89 -0
  7. package/dist/add-module.js +334 -0
  8. package/dist/category-profile.d.ts +126 -0
  9. package/dist/category-profile.js +262 -0
  10. package/dist/cli.js +89 -29
  11. package/dist/index.d.ts +4 -2
  12. package/dist/index.js +6 -1
  13. package/dist/lib/extract-module-bundle.d.ts +56 -1
  14. package/dist/lib/extract-module-bundle.js +170 -14
  15. package/dist/lib/license-key-files.d.ts +15 -0
  16. package/dist/lib/license-key-files.js +102 -0
  17. package/dist/lib/module-license-gate.d.ts +79 -0
  18. package/dist/lib/module-license-gate.js +160 -12
  19. package/dist/lib/module-tier.d.ts +45 -16
  20. package/dist/lib/module-tier.js +76 -0
  21. package/dist/lib/pro-callout.d.ts +16 -10
  22. package/dist/lib/pro-callout.js +34 -3
  23. package/dist/license-set.d.ts +34 -0
  24. package/dist/license-set.js +194 -0
  25. package/dist/module-architecture.d.ts +20 -0
  26. package/dist/module-architecture.js +77 -19
  27. package/dist/modules/commerce/0.6.1.tar.gz +0 -0
  28. package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
  29. package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
  30. package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
  31. package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
  32. package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
  33. package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
  34. package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
  35. package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
  36. package/dist/modules/workspace/0.6.1.tar.gz +0 -0
  37. package/dist/parse-args.d.ts +85 -10
  38. package/dist/parse-args.js +227 -15
  39. package/dist/programmatic.d.ts +81 -5
  40. package/dist/programmatic.js +291 -32
  41. package/dist/site-chrome.d.ts +18 -7
  42. package/dist/site-chrome.js +32 -14
  43. package/dist/site-roster.d.ts +127 -0
  44. package/dist/site-roster.js +499 -0
  45. package/dist/starter-grid.d.ts +216 -0
  46. package/dist/starter-grid.js +449 -0
  47. package/dist/surfaces.d.ts +20 -7
  48. package/dist/surfaces.js +204 -24
  49. package/dist/sync-routes.d.ts +9 -0
  50. package/dist/sync-routes.js +2 -2
  51. package/dist/template-manifest.d.ts +94 -19
  52. package/dist/template-manifest.js +170 -289
  53. package/dist/template-names.d.ts +14 -12
  54. package/dist/template-names.js +13 -17
  55. package/package.json +6 -4
  56. package/site-templates/_base/content/en/BookCall/book-call.mdx +52 -0
  57. package/site-templates/_base/content/en/Feature/feature-1.mdx +69 -0
  58. package/site-templates/_base/content/en/Feature/feature-2.mdx +69 -0
  59. package/site-templates/_base/content/en/Feature/feature-3.mdx +69 -0
  60. package/site-templates/_base/content/en/FeaturesList/features.mdx +91 -0
  61. package/site-templates/_base/content/en/GlossaryList/glossary.mdx +65 -0
  62. package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +67 -0
  63. package/site-templates/_base/content/en/PortfolioItem/sample-four.mdx +105 -0
  64. package/site-templates/_base/content/en/PortfolioItem/sample-one.mdx +34 -0
  65. package/site-templates/_base/content/en/PortfolioItem/sample-three.mdx +94 -0
  66. package/site-templates/_base/content/en/PortfolioItem/sample-two.mdx +45 -0
  67. package/site-templates/_base/content/en/PortfolioList/portfolio.mdx +169 -0
  68. package/site-templates/_base/content/en/Pricing/pricing.mdx +71 -62
  69. package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +17 -3
  70. package/site-templates/_base/content/en/TermsPage/terms.mdx +2 -3
  71. package/site-templates/_base/content/en/UseCase/persona-1.mdx +69 -0
  72. package/site-templates/_base/content/en/UseCase/persona-2.mdx +69 -0
  73. package/site-templates/_base/content/en/UseCase/persona-3.mdx +69 -0
  74. package/site-templates/designs/minimalism/DESIGN.md +162 -0
  75. package/site-templates/designs/standard/DESIGN.md +167 -0
  76. package/site-templates/marketing-site/DESIGN.md +59 -40
  77. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +376 -57
  78. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +230 -90
  79. package/site-templates/marketing-site/ailk-template.json +1 -0
  80. package/site-templates/marketing-site-free/DESIGN.md +59 -40
  81. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +323 -63
  82. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +323 -113
  83. package/site-templates/marketing-site-free/ailk-template.json +3 -2
  84. package/site-templates/marketing-site-free/content/en/NewsletterSignup/newsletter.mdx +59 -0
  85. package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +199 -0
  86. package/site-templates/minimalism-site/DESIGN.md +54 -40
  87. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +246 -19
  88. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +173 -51
  89. package/site-templates/minimalism-site/ailk-template.json +3 -2
  90. package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +52 -0
  91. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +3 -37
  92. package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  93. package/site-templates/saas-product/DESIGN.md +59 -40
  94. package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
  95. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +369 -0
  96. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +302 -0
  97. package/site-templates/shapes/local-business-service/ailk-template.json +10 -0
  98. package/site-templates/{simple-service → shapes/local-business-service}/content/en/AboutPage/about.mdx +4 -4
  99. package/site-templates/shapes/local-business-service/content/en/HomePage/home.mdx +70 -0
  100. package/site-templates/shapes/local-business-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  101. package/site-templates/shapes/local-business-service/content/en/PortfolioList/portfolio.mdx +171 -0
  102. package/site-templates/shapes/local-business-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  103. package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +39 -0
  104. package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +39 -0
  105. package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +39 -0
  106. package/site-templates/shapes/local-business-service/content/en/ServicesList/services.mdx +61 -0
  107. package/site-templates/shapes/local-business-service/provenance.json +4 -0
  108. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +362 -0
  109. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +300 -0
  110. package/site-templates/shapes/organization-service/ailk-template.json +10 -0
  111. package/site-templates/shapes/organization-service/content/en/AboutPage/about.mdx +38 -0
  112. package/site-templates/shapes/organization-service/content/en/HomePage/home.mdx +85 -0
  113. package/site-templates/shapes/organization-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  114. package/site-templates/shapes/organization-service/content/en/PortfolioList/portfolio.mdx +171 -0
  115. package/site-templates/shapes/organization-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  116. package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +38 -0
  117. package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +38 -0
  118. package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +38 -0
  119. package/site-templates/shapes/organization-service/content/en/ServicesList/services.mdx +72 -0
  120. package/site-templates/shapes/organization-service/provenance.json +4 -0
  121. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +369 -0
  122. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +299 -0
  123. package/site-templates/shapes/person-service/ailk-template.json +10 -0
  124. package/site-templates/shapes/person-service/content/_site.mdx +85 -0
  125. package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +39 -0
  126. package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +97 -0
  127. package/site-templates/shapes/person-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  128. package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +169 -0
  129. package/site-templates/shapes/person-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  130. package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +38 -0
  131. package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +38 -0
  132. package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +38 -0
  133. package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx +16 -16
  134. package/site-templates/shapes/person-service/provenance.json +4 -0
  135. package/templates/.claude/settings.json +15 -0
  136. package/templates/.claude/skills/README.md +10 -9
  137. package/templates/.claude/skills/{scaffold-auth → add-auth}/SKILL.md +7 -7
  138. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/env-vars.md +2 -2
  139. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/oauth-app-setup.md +3 -3
  140. package/templates/.claude/skills/{scaffold-page → add-page}/SKILL.md +76 -62
  141. package/templates/.claude/skills/add-page/references/page-types.md +115 -0
  142. package/templates/.claude/skills/{scaffold-page → add-page}/templates/content.mdx.tmpl +4 -4
  143. package/templates/.claude/skills/{scaffold-page → add-page}/templates/route.tsx.tmpl +1 -1
  144. package/templates/.claude/skills/{audit-site → check-site}/SKILL.md +16 -17
  145. package/templates/.claude/skills/{audit-site → check-site}/references/common-errors.md +3 -3
  146. package/templates/.claude/skills/{audit-site → check-site}/references/findings-glossary.md +16 -14
  147. package/templates/.claude/skills/{audit-site → check-site}/references/severity-levels.md +1 -1
  148. package/templates/.claude/skills/fill-page/SKILL.md +180 -0
  149. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +80 -0
  150. package/templates/.claude/skills/fill-page/references/section-sources.md +41 -0
  151. package/templates/.claude/skills/setup-database/SKILL.md +156 -0
  152. package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +154 -0
  153. package/templates/.claude/skills/{provision-config → setup-deploy}/SKILL.md +73 -41
  154. package/templates/.claude/skills/{provision-config → setup-deploy}/references/env-vars-template.md +21 -30
  155. package/templates/.claude/skills/setup-deploy/references/runbook-template.md +204 -0
  156. package/templates/.claude/skills/{provision-config → setup-deploy}/references/vercel-json-template.md +1 -1
  157. package/templates/.claude/skills/upgrade-plan/SKILL.md +117 -0
  158. package/templates/.claude/skills/upgrade-plan/references/options.md +24 -0
  159. package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +527 -0
  160. package/templates/.github/workflows/ci.yml +5 -0
  161. package/templates/CLAUDE.md +8 -2
  162. package/templates/DESIGN.md +56 -44
  163. package/templates/README.md +116 -46
  164. package/templates/apps/api/.env.example +2 -1
  165. package/templates/apps/api/CLAUDE.md +3 -2
  166. package/templates/apps/api/package.json +1 -1
  167. package/templates/apps/api/src/config/__tests__/index.test.ts +146 -10
  168. package/templates/apps/api/src/config/index.ts +46 -14
  169. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +30 -0
  170. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +96 -0
  171. package/templates/apps/api/src/lib/lead-capture-store.ts +12 -0
  172. package/templates/apps/api/src/lib/lead-delivery.ts +52 -0
  173. package/templates/apps/api/src/lib/license-key-store.ts +45 -0
  174. package/templates/apps/api/src/lib/site.ts +5 -3
  175. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +97 -0
  176. package/templates/apps/api/src/middleware/auth.ts +9 -0
  177. package/templates/apps/api/src/openapi/spec.ts +63 -12
  178. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +127 -5
  179. package/templates/apps/api/src/routes/content/get-page.ts +86 -2
  180. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +88 -0
  181. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +100 -0
  182. package/templates/apps/api/src/routes/leads/index.ts +46 -1
  183. package/templates/apps/api/src/server.ts +13 -0
  184. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +194 -0
  185. package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +124 -0
  186. package/templates/apps/api/src/services/lead-routing.ts +140 -30
  187. package/templates/apps/api/src/services/leads-inbox.ts +48 -11
  188. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +75 -1
  189. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +57 -9
  190. package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
  191. package/templates/apps/mcp/package.json +2 -1
  192. package/templates/apps/mcp/src/index.ts +7 -0
  193. package/templates/apps/mcp/src/lib/audit-single-page.ts +36 -10
  194. package/templates/apps/mcp/src/lib/license-key-store.ts +45 -0
  195. package/templates/apps/mcp/src/tools/create_project.ts +21 -6
  196. package/templates/apps/web/__tests__/setup.ts +18 -0
  197. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +10 -2
  198. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +2 -2
  199. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +10 -4
  200. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +22 -14
  201. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +26 -18
  202. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +12 -4
  203. package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +35 -4
  204. package/templates/apps/web/app/[locale]/[slug]/page.tsx +49 -9
  205. package/templates/apps/web/app/[locale]/book-a-call/page.tsx +50 -0
  206. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
  207. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
  208. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +3 -4
  209. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +67 -29
  210. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +94 -11
  211. package/templates/apps/web/app/[locale]/contact/__tests__/contact-form-text.test.ts +32 -0
  212. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +129 -0
  213. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +228 -86
  214. package/templates/apps/web/app/[locale]/contact/contact-form-text.ts +50 -0
  215. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +73 -20
  216. package/templates/apps/web/app/[locale]/contact/page.tsx +115 -7
  217. package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
  218. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
  219. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +3 -4
  220. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +4 -5
  221. package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +64 -0
  222. package/templates/apps/web/app/[locale]/features/page.tsx +52 -0
  223. package/templates/apps/web/app/[locale]/glossary/page.tsx +50 -0
  224. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
  225. package/templates/apps/web/app/[locale]/how-to/page.tsx +25 -15
  226. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
  227. package/templates/apps/web/app/[locale]/layout.tsx +146 -52
  228. package/templates/apps/web/app/[locale]/newsletter/__tests__/newsletter.actions.test.ts +75 -0
  229. package/templates/apps/web/app/[locale]/newsletter/__tests__/page.test.tsx +163 -0
  230. package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +66 -0
  231. package/templates/apps/web/app/[locale]/newsletter/page.tsx +142 -0
  232. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
  233. package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
  234. package/templates/apps/web/app/[locale]/portfolio/page.tsx +49 -0
  235. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
  236. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -5
  237. package/templates/apps/web/app/[locale]/{cancellation → purchase-policy}/page.tsx +15 -10
  238. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +4 -5
  239. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
  240. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +14 -1
  241. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
  242. package/templates/apps/web/app/[locale]/software/page.tsx +25 -15
  243. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
  244. package/templates/apps/web/app/[locale]/tech-articles/page.tsx +25 -15
  245. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +3 -4
  246. package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +63 -0
  247. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +3 -4
  248. package/templates/apps/web/app/[locale]/use-cases/page.tsx +15 -2
  249. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
  250. package/templates/apps/web/app/[locale]/whitepapers/page.tsx +25 -15
  251. package/templates/apps/web/app/error-fallback.tsx +17 -45
  252. package/templates/apps/web/app/not-found.tsx +14 -38
  253. package/templates/apps/web/app/og/route.tsx +6 -0
  254. package/templates/apps/web/eslint.config.mjs +3 -0
  255. package/templates/apps/web/instrumentation.ts +14 -0
  256. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +38 -0
  257. package/templates/apps/web/lib/license-key-store.ts +52 -0
  258. package/templates/apps/web/lib/nav-config.ts +82 -18
  259. package/templates/apps/web/lib/prisma-for-auth.ts +9 -6
  260. package/templates/apps/web/lib/site-brand.tsx +1 -1
  261. package/templates/apps/web/lib/site-chrome.ts +3 -3
  262. package/templates/apps/web/lib/site-identity.ts +148 -0
  263. package/templates/apps/web/lib/site-theme.ts +11 -0
  264. package/templates/apps/web/messages/en.json +78 -37
  265. package/templates/apps/web/public/android-chrome-192x192.png +0 -0
  266. package/templates/apps/web/public/android-chrome-512x512.png +0 -0
  267. package/templates/apps/web/public/apple-touch-icon.png +0 -0
  268. package/templates/apps/web/public/favicon-16x16.png +0 -0
  269. package/templates/apps/web/public/favicon-32x32.png +0 -0
  270. package/templates/apps/web/public/favicon.ico +0 -0
  271. package/templates/apps/web/public/favicon.svg +3 -3
  272. package/templates/apps/web/public/logomark.svg +6 -3
  273. package/templates/apps/web/public/logos/ai-launch-kit-light.svg +4 -0
  274. package/templates/apps/web/public/logos/ai-launch-kit.svg +4 -0
  275. package/templates/apps/web/public/logos/atomic-agent-light.svg +4 -0
  276. package/templates/apps/web/public/logos/atomic-agent.svg +4 -0
  277. package/templates/apps/web/public/logos/salessmyth-light.svg +4 -0
  278. package/templates/apps/web/public/logos/salessmyth.svg +4 -0
  279. package/templates/apps/web/public/site.webmanifest +4 -4
  280. package/templates/apps/web/public/wordmark-light.svg +4 -0
  281. package/templates/apps/web/public/wordmark.svg +3 -3
  282. package/templates/apps/web/security-headers.config.ts +5 -1
  283. package/templates/content/_site.mdx +25 -0
  284. package/templates/content/en/AboutPage/about.mdx +150 -144
  285. package/templates/content/en/BlogList/blog.mdx +126 -0
  286. package/templates/content/en/ContactPage/contact.mdx +21 -92
  287. package/templates/content/en/FAQPage/faq.mdx +86 -57
  288. package/templates/content/en/HomePage/home.mdx +268 -217
  289. package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +181 -0
  290. package/templates/content/en/UseCasesList/use-cases.mdx +170 -0
  291. package/templates/database/CHANGELOG.md +14 -0
  292. package/templates/database/package.json +1 -1
  293. package/templates/package.json +3 -1
  294. package/templates/tools/lint-architecture.ts +315 -0
  295. package/templates/tools/tsconfig.json +14 -0
  296. package/versions.json +33 -33
  297. package/site-templates/simple-service/DESIGN.md +0 -148
  298. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +0 -240
  299. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -278
  300. package/site-templates/simple-service/ailk-template.json +0 -10
  301. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -67
  302. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +0 -56
  303. package/site-templates/simple-service/content/en/HomePage/home.mdx +0 -85
  304. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +0 -40
  305. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +0 -40
  306. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +0 -40
  307. package/site-templates/simple-service/provenance.json +0 -4
  308. package/templates/.claude/skills/add-schema/SKILL.md +0 -277
  309. package/templates/.claude/skills/add-schema/references/conflict-handling.md +0 -200
  310. package/templates/.claude/skills/add-schema/references/file-finding.md +0 -123
  311. package/templates/.claude/skills/add-schema/references/schema-types.md +0 -234
  312. package/templates/.claude/skills/provision-config/references/runbook-template.md +0 -248
  313. package/templates/.claude/skills/scaffold-page/references/page-types.md +0 -169
  314. package/templates/.claude/skills/suggest-site-pages/SKILL.md +0 -242
  315. package/templates/.claude/skills/suggest-site-pages/references/categories.md +0 -287
  316. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -150
  317. package/templates/apps/web/app/[locale]/returns/page.tsx +0 -44
  318. package/templates/apps/web/app/[locale]/shipping/page.tsx +0 -44
  319. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +0 -108
  320. package/templates/content/en/LandingPage/blog.mdx +0 -83
  321. package/templates/content/en/LandingPage/features.mdx +0 -103
  322. package/templates/content/en/LandingPage/how-it-works.mdx +0 -143
  323. package/templates/content/en/ReturnsPolicyPage/returns.mdx +0 -108
  324. package/templates/content/en/ShippingPolicyPage/shipping.mdx +0 -108
@@ -1,4 +1,6 @@
1
1
  import { FetchModuleError, fetchModule } from "./fetch-module.js";
2
+ import { assertLicenseKeyShape } from "./license-key-files.js";
3
+ import { ADD_ONS, LEVEL_LABEL, LEVEL_MODULES, OPT_IN_MODULES, PAID_MODULES, classifyModules, composeModuleSet, levelOf, } from "./module-tier.js";
2
4
  /**
3
5
  * Where a refused run sends the buyer. `/pricing`, not `/pro`: there is no
4
6
  * `/pro` route and there will not be one (#6439, operator decision OD-2) —
@@ -17,6 +19,53 @@ export class LicenseRequiredError extends Error {
17
19
  this.name = "LicenseRequiredError";
18
20
  }
19
21
  }
22
+ /** Designs every level renders (#6760 D1). Anything else in `STARTER_DESIGNS` is Pro and up. */
23
+ export const FREE_DESIGNS = ["standard"];
24
+ /** Levels that render any design (#6760 D1) — an allow-list: an unknown level is not in it. */
25
+ export const DESIGN_LEVELS = ["pro", "pro-plus"];
26
+ /**
27
+ * Refuse a non-`standard` design at a level below Pro (#6760 D1, D6). Pure
28
+ * and synchronous — takes the level `deriveLevel`/`resolveModuleSet` already
29
+ * resolved; never reads a key or derives a level itself (D2, fail-closed:
30
+ * both checks below are allow-lists, so an unrecognized `level` refuses
31
+ * rather than granting it).
32
+ */
33
+ export function assertDesignAllowed(design, level) {
34
+ if (design === undefined || FREE_DESIGNS.includes(design))
35
+ return;
36
+ if (DESIGN_LEVELS.includes(level))
37
+ return;
38
+ throw new LicenseRequiredError(`design "${design}" is a Pro feature — this run's licence level is ${LEVEL_LABEL[level]}; pass --license <key> or set AILK_LICENSE_KEY with a Pro or Pro Plus key → ${CONVERSION_HINT_URL}`);
39
+ }
40
+ /**
41
+ * The message phrase for one module (D5): what level includes it, or that it
42
+ * is an add-on. Pure — derived from `levelOf`, never from the current run's
43
+ * own derived level.
44
+ */
45
+ export function levelPhrase(m) {
46
+ const level = levelOf(m);
47
+ if (level === "add-on") {
48
+ return `"${m}" is an add-on, bought on top of Pro or Pro Plus`;
49
+ }
50
+ if (level === "free") {
51
+ return `"${m}" is included at ${LEVEL_LABEL.free}`;
52
+ }
53
+ return `"${m}" is included at ${LEVEL_LABEL[level]}`;
54
+ }
55
+ /** M1 / M1t (D5): the no-key refusal, with or without a named template. */
56
+ function noKeyMessage(paidModules, templateName) {
57
+ const phrases = paidModules.map((m) => levelPhrase(m)).join("; ");
58
+ const intro = templateName !== undefined
59
+ ? `template "${templateName}" needs a licence: ${phrases}`
60
+ : `no licence key, so this is a Free scaffold: ${phrases}`;
61
+ return `${intro} — set AILK_LICENSE_KEY first → ${CONVERSION_HINT_URL}`;
62
+ }
63
+ /** M2 (D5): a key the registry rejected for one module. */
64
+ function licenseErrorMessage(err, moduleName, templateName, level) {
65
+ const templateSuffix = templateName !== undefined ? ` (required by template "${templateName}")` : "";
66
+ const levelSuffix = level !== undefined ? ` — your licence is at ${LEVEL_LABEL[level]}` : "";
67
+ return `${err.message}; ${levelPhrase(moduleName)}${templateSuffix}${levelSuffix} → ${CONVERSION_HINT_URL}`;
68
+ }
20
69
  /**
21
70
  * Resolve every requested paid module to its fetched bundle bytes, or throw
22
71
  * `LicenseRequiredError` naming exactly why the run cannot proceed. Never
@@ -33,8 +82,11 @@ export async function resolvePaidModules(options) {
33
82
  }
34
83
  const token = options.licenseKey ?? process.env["AILK_LICENSE_KEY"];
35
84
  if (token === undefined || token.length === 0) {
36
- throw new LicenseRequiredError(conversionHint(paidModules, options.templateName));
85
+ throw new LicenseRequiredError(noKeyMessage(paidModules, options.templateName));
37
86
  }
87
+ // SEC-2 — the `--license` flag and the env var are validated alike,
88
+ // whichever source this token came from, before it reaches a request.
89
+ assertLicenseKeyShape(token);
38
90
  const bundles = new Map();
39
91
  for (const moduleName of paidModules) {
40
92
  try {
@@ -55,11 +107,9 @@ export async function resolvePaidModules(options) {
55
107
  if (err instanceof FetchModuleError) {
56
108
  if (err.isLicenseError) {
57
109
  // DD5 row 2: the mapped 401/403 already names the module the key
58
- // does not cover; the template is appended so the buyer can see
59
- // WHICH of the things they asked for needs it.
60
- throw new LicenseRequiredError(options.templateName !== undefined
61
- ? `${err.message}, required by template "${options.templateName}" → ${CONVERSION_HINT_URL}`
62
- : `${err.message} → ${CONVERSION_HINT_URL}`);
110
+ // does not cover; the template and level are appended so the buyer
111
+ // can see WHICH of the things they asked for needs it.
112
+ throw new LicenseRequiredError(licenseErrorMessage(err, moduleName, options.templateName, options.level));
63
113
  }
64
114
  // Not a license-gating signal (e.g. 404 "not yet available", or the
65
115
  // registry unreachable) — a generic failure, not the honest-denial
@@ -72,10 +122,108 @@ export async function resolvePaidModules(options) {
72
122
  }
73
123
  return bundles;
74
124
  }
75
- function conversionHint(paidModules, templateName) {
76
- const list = paidModules.join(", ");
77
- const requested = templateName !== undefined
78
- ? `template "${templateName}" requires Pro module(s) (${list})`
79
- : `Pro module(s) requested (${list})`;
80
- return `${requested} — set AILK_LICENSE_KEY first → ${CONVERSION_HINT_URL}`;
125
+ function forward(options) {
126
+ return {
127
+ ...(options.registryUrl !== undefined ? { registryUrl: options.registryUrl } : {}),
128
+ ...(options.version !== undefined ? { version: options.version } : {}),
129
+ ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),
130
+ };
131
+ }
132
+ /**
133
+ * Derive the key's level from what the registry actually answers (D4) — the
134
+ * level only chooses which modules to ASK FOR; every byte is still
135
+ * authorized by the registry per module. Nothing client-side is an
136
+ * entitlement claim: the JWT is never parsed here.
137
+ *
138
+ * No key ⟹ `"free"`, zero network. A present key is shape-checked first,
139
+ * whichever source it came from (SEC-2). Then: probe every paid member of
140
+ * `LEVEL_MODULES.pro`, in order — a licence error on any of them is refused
141
+ * (a key that does not unlock all of Pro is not silently downgraded); any
142
+ * other failure (404, 5xx, unreachable) is wrapped so the caller sees it
143
+ * could not determine the level, and is told the escape hatch (`--modules`).
144
+ * Then probe `multi-tenant` (what Pro Plus adds beyond Pro): a licence error
145
+ * there is the expected "this key is Pro, not Pro Plus" answer, not a
146
+ * refusal.
147
+ */
148
+ export async function deriveLevel(options) {
149
+ const token = options.licenseKey ?? process.env["AILK_LICENSE_KEY"];
150
+ if (token === undefined || token.length === 0) {
151
+ return { level: "free", bundles: new Map() };
152
+ }
153
+ assertLicenseKeyShape(token);
154
+ const bundles = new Map();
155
+ const proModules = LEVEL_MODULES.pro.filter((m) => PAID_MODULES.includes(m));
156
+ for (const moduleName of proModules) {
157
+ try {
158
+ const bytes = await fetchModule({ moduleName, token, ...forward(options) });
159
+ bundles.set(moduleName, bytes);
160
+ }
161
+ catch (err) {
162
+ if (err instanceof FetchModuleError) {
163
+ if (err.isLicenseError) {
164
+ throw new LicenseRequiredError(licenseErrorMessage(err, moduleName));
165
+ }
166
+ throw new FetchModuleError(`could not determine your licence level: ${err.message} — name the modules you want with --modules`);
167
+ }
168
+ throw err;
169
+ }
170
+ }
171
+ try {
172
+ const bytes = await fetchModule({
173
+ moduleName: "multi-tenant",
174
+ token,
175
+ ...forward(options),
176
+ });
177
+ bundles.set("multi-tenant", bytes);
178
+ return { level: "pro-plus", bundles };
179
+ }
180
+ catch (err) {
181
+ if (err instanceof FetchModuleError) {
182
+ if (err.isLicenseError) {
183
+ return { level: "pro", bundles };
184
+ }
185
+ throw new FetchModuleError(`could not determine your licence level: ${err.message} — name the modules you want with --modules`);
186
+ }
187
+ throw err;
188
+ }
189
+ }
190
+ /**
191
+ * The one entry point that turns `--modules` + the key into the effective
192
+ * module set and its resolved bundles (D5) — `programmatic.ts`'s `scaffold()`
193
+ * calls this for every run except a named `--template` alias (NFR-4).
194
+ *
195
+ * A named list with a non-addition (the KEEP branch, D2) resolves it exactly
196
+ * as today, with no level derived and no extra request (NFR-2). Otherwise the
197
+ * level is derived first, the set composed from it, and any named addition
198
+ * not already fetched during the level probe is resolved on top.
199
+ */
200
+ export async function resolveModuleSet(options) {
201
+ const namedList = options.named ?? [];
202
+ const additions = [...ADD_ONS, ...OPT_IN_MODULES];
203
+ const isKeep = namedList.some((m) => !additions.includes(m));
204
+ if (isKeep) {
205
+ const modules = composeModuleSet(namedList, "free");
206
+ const { paid } = classifyModules(modules);
207
+ const bundles = await resolvePaidModules({
208
+ paidModules: paid,
209
+ licenseKey: options.licenseKey,
210
+ ...forward(options),
211
+ });
212
+ return { modules, bundles };
213
+ }
214
+ const { level, bundles } = await deriveLevel(options);
215
+ const modules = composeModuleSet(namedList, level);
216
+ const { paid } = classifyModules(modules);
217
+ const missing = paid.filter((m) => !bundles.has(m));
218
+ if (missing.length > 0) {
219
+ const extra = await resolvePaidModules({
220
+ paidModules: missing,
221
+ licenseKey: options.licenseKey,
222
+ level,
223
+ ...forward(options),
224
+ });
225
+ for (const [k, v] of extra)
226
+ bundles.set(k, v);
227
+ }
228
+ return { modules, bundles, level };
81
229
  }
@@ -1,19 +1,3 @@
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
1
  import { type ModuleName } from "../parse-args.js";
18
2
  /** Modules scaffolded from `templates/` with no license — today's free path. */
19
3
  export declare const FREE_MODULES: readonly ModuleName[];
@@ -24,6 +8,51 @@ export declare const FREE_MODULES: readonly ModuleName[];
24
8
  * from `RECOGNIZED_MODULES` silently.
25
9
  */
26
10
  export declare const PAID_MODULES: readonly ModuleName[];
11
+ /**
12
+ * The levels a key can be at (#6759 D2). A value, never read from a flag, a
13
+ * manifest or a key claim — it is always DERIVED, by `deriveLevel`
14
+ * (`module-license-gate.ts`), from what the registry actually answers.
15
+ */
16
+ export declare const LEVELS: readonly ["free", "pro", "pro-plus"];
17
+ export type Level = (typeof LEVELS)[number];
18
+ export declare const LEVEL_LABEL: Readonly<Record<Level, string>>;
19
+ /**
20
+ * Bought per site on top of a paid level — never switched on BY a level
21
+ * (OFFERINGS §4a). Naming one in `--modules` adds it without trimming
22
+ * (`composeModuleSet`), and it is refused below Pro naming the level it is
23
+ * an add-on ON TOP of.
24
+ */
25
+ export declare const ADD_ONS: readonly ModuleName[];
26
+ /**
27
+ * Included at Pro and above (the licence manifest's `pro` tier), but not
28
+ * switched on by default at any level (D1) — an authed app surface
29
+ * contributing no PUBLIC page to a marketing site. Naming it in `--modules`
30
+ * adds it without trimming, exactly like an add-on.
31
+ */
32
+ export declare const OPT_IN_MODULES: readonly ModuleName[];
33
+ /**
34
+ * What a key at each level switches on with no `--modules` (D2). Derived —
35
+ * every list is `RECOGNIZED_MODULES.filter(...)`, so declaration order is
36
+ * preserved and a module added to the vocabulary later lands in `pro` by
37
+ * derivation (loud: `module-tier.test.ts`'s table test pins the exact sets).
38
+ */
39
+ export declare const LEVEL_MODULES: Readonly<Record<Level, readonly ModuleName[]>>;
40
+ /**
41
+ * Which level (or add-on status) a module belongs to (D2). `"free"` for
42
+ * `FREE_MODULES`, `"add-on"` for `ADD_ONS`, `"pro-plus"` for
43
+ * `PRO_PLUS_MODULES`, else `"pro"` (`workspace` included — D1). Pure.
44
+ */
45
+ export declare function levelOf(m: ModuleName): Level | "add-on";
46
+ /**
47
+ * The pure core of FR-2/FR-3 (D2): compose the effective module set from
48
+ * what `--modules` named and the key's derived level. Naming any module that
49
+ * is not an addition (`ADDITIONS`) is a KEEP — it names exactly the set,
50
+ * unchanged from today (NFR-2), and the level plays no part. Naming only
51
+ * additions (or nothing) takes the level's default plus those additions.
52
+ * Never refuses — refusals belong to the gate (`resolveModuleSet`), because
53
+ * whether a named module is covered is a registry answer, not a table lookup.
54
+ */
55
+ export declare function composeModuleSet(named: readonly ModuleName[] | undefined, level: Level): ModuleName[];
27
56
  export interface ModuleClassification {
28
57
  free: ModuleName[];
29
58
  paid: ModuleName[];
@@ -14,6 +14,7 @@
14
14
  * (`parse-args.ts`) defaults it to "paid" until someone deliberately adds it
15
15
  * to `FREE_MODULES`, rather than silently shipping it free.
16
16
  */
17
+ import { normalizeModules } from "../module-architecture.js";
17
18
  import { RECOGNIZED_MODULES } from "../parse-args.js";
18
19
  /** Modules scaffolded from `templates/` with no license — today's free path. */
19
20
  export const FREE_MODULES = ["marketing"];
@@ -24,6 +25,81 @@ export const FREE_MODULES = ["marketing"];
24
25
  * from `RECOGNIZED_MODULES` silently.
25
26
  */
26
27
  export const PAID_MODULES = RECOGNIZED_MODULES.filter((m) => !FREE_MODULES.includes(m));
28
+ /**
29
+ * The levels a key can be at (#6759 D2). A value, never read from a flag, a
30
+ * manifest or a key claim — it is always DERIVED, by `deriveLevel`
31
+ * (`module-license-gate.ts`), from what the registry actually answers.
32
+ */
33
+ export const LEVELS = ["free", "pro", "pro-plus"];
34
+ export const LEVEL_LABEL = {
35
+ free: "Free",
36
+ pro: "Pro",
37
+ "pro-plus": "Pro Plus",
38
+ };
39
+ /**
40
+ * Bought per site on top of a paid level — never switched on BY a level
41
+ * (OFFERINGS §4a). Naming one in `--modules` adds it without trimming
42
+ * (`composeModuleSet`), and it is refused below Pro naming the level it is
43
+ * an add-on ON TOP of.
44
+ */
45
+ export const ADD_ONS = ["commerce"];
46
+ /**
47
+ * Included at Pro and above (the licence manifest's `pro` tier), but not
48
+ * switched on by default at any level (D1) — an authed app surface
49
+ * contributing no PUBLIC page to a marketing site. Naming it in `--modules`
50
+ * adds it without trimming, exactly like an add-on.
51
+ */
52
+ export const OPT_IN_MODULES = ["workspace"];
53
+ /** The Pro Plus membership: what Pro Plus switches on beyond Pro. */
54
+ const PRO_PLUS_MODULES = ["multi-tenant"];
55
+ /** Named modules that never trim the level default when composing a set (D2). */
56
+ const ADDITIONS = [...ADD_ONS, ...OPT_IN_MODULES];
57
+ const PRO_EXCLUDED = new Set([...ADDITIONS, ...PRO_PLUS_MODULES]);
58
+ /**
59
+ * What a key at each level switches on with no `--modules` (D2). Derived —
60
+ * every list is `RECOGNIZED_MODULES.filter(...)`, so declaration order is
61
+ * preserved and a module added to the vocabulary later lands in `pro` by
62
+ * derivation (loud: `module-tier.test.ts`'s table test pins the exact sets).
63
+ */
64
+ export const LEVEL_MODULES = Object.freeze({
65
+ free: [...FREE_MODULES],
66
+ pro: RECOGNIZED_MODULES.filter((m) => FREE_MODULES.includes(m) ||
67
+ (PAID_MODULES.includes(m) && !PRO_EXCLUDED.has(m))),
68
+ "pro-plus": RECOGNIZED_MODULES.filter((m) => FREE_MODULES.includes(m) ||
69
+ (PAID_MODULES.includes(m) && !ADDITIONS.includes(m))),
70
+ });
71
+ /**
72
+ * Which level (or add-on status) a module belongs to (D2). `"free"` for
73
+ * `FREE_MODULES`, `"add-on"` for `ADD_ONS`, `"pro-plus"` for
74
+ * `PRO_PLUS_MODULES`, else `"pro"` (`workspace` included — D1). Pure.
75
+ */
76
+ export function levelOf(m) {
77
+ if (FREE_MODULES.includes(m))
78
+ return "free";
79
+ if (ADD_ONS.includes(m))
80
+ return "add-on";
81
+ if (PRO_PLUS_MODULES.includes(m))
82
+ return "pro-plus";
83
+ return "pro";
84
+ }
85
+ /**
86
+ * The pure core of FR-2/FR-3 (D2): compose the effective module set from
87
+ * what `--modules` named and the key's derived level. Naming any module that
88
+ * is not an addition (`ADDITIONS`) is a KEEP — it names exactly the set,
89
+ * unchanged from today (NFR-2), and the level plays no part. Naming only
90
+ * additions (or nothing) takes the level's default plus those additions.
91
+ * Never refuses — refusals belong to the gate (`resolveModuleSet`), because
92
+ * whether a named module is covered is a registry answer, not a table lookup.
93
+ */
94
+ export function composeModuleSet(named, level) {
95
+ const namedList = [...(named ?? [])];
96
+ const keep = namedList.filter((m) => !ADDITIONS.includes(m));
97
+ if (keep.length > 0) {
98
+ return normalizeModules(namedList);
99
+ }
100
+ const add = namedList.filter((m) => ADDITIONS.includes(m));
101
+ return normalizeModules([...LEVEL_MODULES[level], ...add]);
102
+ }
27
103
  /**
28
104
  * Split a requested (already-validated, `ModuleName`) module set into its
29
105
  * free and paid subsets, each preserving the input's relative order.
@@ -1,12 +1,18 @@
1
+ export declare function proCallout(): string;
2
+ /** The closing prerequisites note on a free install (#6440 AC4). */
3
+ export declare const FREE_PREREQUISITES_NOTE = "No database, no licence key and no vendor API key are needed to run or build this site.";
1
4
  /**
2
- * `proCallout()` — the AI-guided setup conversion message appended to
3
- * `pnpm create ailk-app`'s closing summary.
4
- *
5
- * Wording is locked in `docs/internal/specs/ailk-onboard-site-spec.md` §2.1 and
6
- * `docs/internal/specs/ailk-onboard-site-spec.md` §5.1 (Sam-verifiable AC).
7
- *
8
- * The message is always shown — no flags, no env gating. Free-tier users
9
- * see it as a discovery surface for Pro; Pro users see it as a reminder
10
- * of the `/onboard-site` skill they can install.
5
+ * The same note on a licensed install (#6480): it drops the licence-key claim,
6
+ * which would contradict the key the customer just installed with.
11
7
  */
12
- export declare function proCallout(): string;
8
+ export declare const LICENSED_PREREQUISITES_NOTE = "No database and no vendor API key are needed to run or build this site.";
9
+ /**
10
+ * Whether an install delivered paid content — any paid module in the effective
11
+ * module set, `union(template.requires, --modules)`, the same union
12
+ * `scaffold()` gates on. A paid template is covered by that union too:
13
+ * `templateDelivery` derives "paid" from `requires` alone.
14
+ */
15
+ export declare function isLicensedInstall(opts: {
16
+ template?: string;
17
+ modules?: string[];
18
+ }): boolean;
@@ -5,10 +5,12 @@
5
5
  * Wording is locked in `docs/internal/specs/ailk-onboard-site-spec.md` §2.1 and
6
6
  * `docs/internal/specs/ailk-onboard-site-spec.md` §5.1 (Sam-verifiable AC).
7
7
  *
8
- * The message is always shown — no flags, no env gating. Free-tier users
9
- * see it as a discovery surface for Pro; Pro users see it as a reminder
10
- * of the `/onboard-site` skill they can install.
8
+ * Shown on a free install only (#6480): it is a discovery surface for Pro,
9
+ * and a licensed install already owns the tier it pitches.
11
10
  */
11
+ import { normalizeModules } from "../module-architecture.js";
12
+ import { SHAPE_STARTERS, resolveTemplate } from "../template-manifest.js";
13
+ import { classifyModules } from "./module-tier.js";
12
14
  export function proCallout() {
13
15
  return [
14
16
  "Want AI-guided setup? Pro's `/onboard-site` interviews you about",
@@ -18,3 +20,32 @@ export function proCallout() {
18
20
  "free scaffolders one at a time → ailaunchkit.ai/pricing",
19
21
  ].join("\n");
20
22
  }
23
+ /** The closing prerequisites note on a free install (#6440 AC4). */
24
+ export const FREE_PREREQUISITES_NOTE = "No database, no licence key and no vendor API key are needed to run or build this site.";
25
+ /**
26
+ * The same note on a licensed install (#6480): it drops the licence-key claim,
27
+ * which would contradict the key the customer just installed with.
28
+ */
29
+ export const LICENSED_PREREQUISITES_NOTE = "No database and no vendor API key are needed to run or build this site.";
30
+ /**
31
+ * Whether an install delivered paid content — any paid module in the effective
32
+ * module set, `union(template.requires, --modules)`, the same union
33
+ * `scaffold()` gates on. A paid template is covered by that union too:
34
+ * `templateDelivery` derives "paid" from `requires` alone.
35
+ */
36
+ export function isLicensedInstall(opts) {
37
+ // #6757 D6 row 4 — a bare-shape starter's name (the shape itself, passed
38
+ // here after #6754 D4 item 3 resolves it) is looked up through
39
+ // SHAPE_STARTERS first; `resolveTemplate` alone throws `unknown template`
40
+ // for one (NFR-3).
41
+ const requires = opts.template !== undefined
42
+ ? Object.prototype.hasOwnProperty.call(SHAPE_STARTERS, opts.template)
43
+ ? SHAPE_STARTERS[opts.template].requires
44
+ : resolveTemplate(opts.template).requires
45
+ : [];
46
+ const modules = normalizeModules([
47
+ ...requires,
48
+ ...(opts.modules ?? ["marketing"]),
49
+ ]);
50
+ return classifyModules(modules).paid.length > 0;
51
+ }
@@ -0,0 +1,34 @@
1
+ export interface LicenseSetRunResult {
2
+ /** Exit status; null when the process never ran or was killed. */
3
+ status: number | null;
4
+ /** Set when the process could not be spawned (e.g. `ENOENT`). */
5
+ error?: NodeJS.ErrnoException;
6
+ }
7
+ /**
8
+ * Runs `vercel <args>`. The command itself is fixed — a runner is never
9
+ * handed one to run, per the package's hard-coded-command invariant
10
+ * (security.test.ts).
11
+ * `input`, when given, is written to the child's stdin.
12
+ */
13
+ export type LicenseSetRunner = (args: readonly string[], options: {
14
+ cwd: string;
15
+ input?: string;
16
+ }) => LicenseSetRunResult;
17
+ export interface LicenseSetIO {
18
+ /** Resolves a relative or absent `[dir]`. */
19
+ cwd: string;
20
+ stdout: (text: string) => void;
21
+ stderr: (text: string) => void;
22
+ /** Reads all of stdin — used only by the `-` form. */
23
+ readStdin: () => string;
24
+ /** Defaults to `spawnSync` with `shell: false` (see `defaultRunner`). */
25
+ runner?: LicenseSetRunner;
26
+ }
27
+ export declare const LICENSE_SET_HELP = "create-ailk license set \u2014 put your licence key into an existing site.\n\nUsage:\n pnpm create ailk@latest license set <key> [<target-dir>]\n pnpm create ailk@latest license set - [<target-dir>] < key.txt\n\nArguments:\n <key> Your licence key, or `-` to read it from stdin\n (keeps it out of your shell history).\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nWrites the key to ailk.key and apps/api/.env (owner-only, gitignored). When the\nsite (or apps/api, or apps/web) is linked to Vercel, it also replaces the\nproduction AILK_LICENSE_KEY variable and redeploys.\n";
28
+ /** `spawnSync`, never through a shell; stdin piped only when there is input. */
29
+ export declare const defaultRunner: LicenseSetRunner;
30
+ /**
31
+ * Run `license set` with `argv` = everything after the `license set` words.
32
+ * Returns the process exit code; never throws for an expected failure.
33
+ */
34
+ export declare function runLicenseSet(argv: string[], io: LicenseSetIO): number;