create-ailk 0.23.0 → 0.25.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 (604) hide show
  1. package/README.md +68 -33
  2. package/component-catalog.json +3 -3
  3. package/component-catalog.md +3 -3
  4. package/dist/add-module.js +10 -3
  5. package/dist/add-route.d.ts +12 -1
  6. package/dist/add-route.js +38 -4
  7. package/dist/cli.js +12 -7
  8. package/dist/derive-architecture.d.ts +3 -4
  9. package/dist/derive-architecture.js +75 -22
  10. package/dist/lib/design-checks.d.ts +9 -4
  11. package/dist/lib/design-checks.js +13 -7
  12. package/dist/lib/extract-module-bundle.js +29 -2
  13. package/dist/lib/fetch-template-snapshot.d.ts +1 -1
  14. package/dist/lib/fetch-template-snapshot.js +7 -3
  15. package/dist/lib/import-graph.d.ts +1 -1
  16. package/dist/lib/import-graph.js +4 -4
  17. package/dist/lib/module-license-gate.d.ts +12 -1
  18. package/dist/lib/module-license-gate.js +34 -12
  19. package/dist/lib/scaffold-render-sweep.d.ts +33 -0
  20. package/dist/lib/scaffold-render-sweep.js +45 -0
  21. package/dist/module-architecture.d.ts +20 -3
  22. package/dist/module-architecture.js +122 -538
  23. package/dist/paid-sections.d.ts +25 -1
  24. package/dist/paid-sections.js +88 -3
  25. package/dist/surfaces.js +10 -2
  26. package/dist/sync-routes.d.ts +30 -4
  27. package/dist/sync-routes.js +271 -18
  28. package/dist/template-record.d.ts +14 -4
  29. package/dist/template-record.js +23 -5
  30. package/dist/topology.d.ts +16 -3
  31. package/dist/topology.js +31 -19
  32. package/dist/update.d.ts +10 -1
  33. package/dist/update.js +540 -16
  34. package/package.json +3 -3
  35. package/release-scope.json +1 -1
  36. package/templates/.claude/cloudparity-repo-hooks.json +5 -0
  37. package/templates/.claude/hooks/template-guard.sh +137 -0
  38. package/templates/.claude/rules/extending.md +106 -0
  39. package/templates/.claude/rules/loop-contract.md +2 -2
  40. package/templates/.claude/settings.json +11 -0
  41. package/templates/.env.example +9 -5
  42. package/templates/.github/workflows/ci.yml +7 -4
  43. package/templates/CLAUDE.md +15 -3
  44. package/templates/CONVENTIONS.md +8 -10
  45. package/templates/README.md +14 -13
  46. package/templates/apps/api/.env.example +9 -2
  47. package/templates/apps/api/CLAUDE.md +122 -82
  48. package/templates/apps/api/jest.config.cjs +15 -5
  49. package/templates/apps/api/package.json +16 -20
  50. package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
  51. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
  52. package/templates/apps/api/src/index.ts +1 -1
  53. package/templates/apps/api/src/lib/__mocks__/prisma.ts +7 -4
  54. package/templates/apps/api/src/modules/commerce.ts +10 -0
  55. package/templates/apps/api/src/modules/content-write.ts +10 -0
  56. package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
  57. package/templates/apps/api/src/modules/scheduling.ts +10 -0
  58. package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
  59. package/templates/apps/api/src/modules/workspace.ts +10 -0
  60. package/templates/apps/api/src/server.ts +117 -1857
  61. package/templates/apps/api/vercel.json +2 -2
  62. package/templates/apps/mcp/CLAUDE.md +77 -24
  63. package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
  64. package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
  65. package/templates/apps/mcp/jest.config.cjs +6 -1
  66. package/templates/apps/mcp/package.json +5 -12
  67. package/templates/apps/mcp/src/app.ts +8 -7
  68. package/templates/apps/mcp/src/index.ts +6 -34
  69. package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
  70. package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
  71. package/templates/apps/mcp/src/site.ts +12 -0
  72. package/templates/apps/web/.env.example +1 -1
  73. package/templates/apps/web/CLAUDE.md +21 -5
  74. package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
  75. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +1 -1
  76. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +14 -4
  77. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
  78. package/templates/apps/web/app/[locale]/contact/intake-script.ts +1 -1
  79. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
  80. package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +28 -7
  81. package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
  82. package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
  83. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
  84. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
  85. package/templates/apps/web/app/api/revalidate/route.ts +3 -3
  86. package/templates/apps/web/auth.ts +2 -2
  87. package/templates/apps/web/jest.config.cjs +1 -0
  88. package/templates/apps/web/lib/__tests__/magnet-routes.test.ts +7 -0
  89. package/templates/apps/web/lib/auth-email.ts +1 -1
  90. package/templates/apps/web/lib/magnet-routes.ts +3 -1
  91. package/templates/apps/web/lib/newsletter.actions.ts +9 -6
  92. package/templates/apps/web/lib/relay.ts +2 -2
  93. package/templates/apps/web/lib/release-scope.ts +47 -0
  94. package/templates/apps/web/lib/server-api.ts +1 -1
  95. package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
  96. package/templates/customizations.yaml +37 -0
  97. package/templates/database/prisma.config.ts +10 -14
  98. package/templates/database/seed-test.ts +2 -2
  99. package/templates/database/seed.ts +32 -5
  100. package/templates/package.json +12 -6
  101. package/templates/pnpm-workspace.yaml +0 -1
  102. package/templates/project.yaml +16 -8
  103. package/templates/tools/jest/reporters.cjs +65 -0
  104. package/templates/tools/lint-architecture.ts +757 -7
  105. package/templates/tsconfig.json +1 -2
  106. package/versions.json +48 -35
  107. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
  108. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
  109. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
  110. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
  111. package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
  112. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
  113. package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
  114. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
  115. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
  116. package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
  117. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
  118. package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
  119. package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
  120. package/templates/apps/api/src/bin/spokes.ts +0 -198
  121. package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
  122. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
  123. package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
  124. package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
  125. package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
  126. package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
  127. package/templates/apps/api/src/config/index.ts +0 -596
  128. package/templates/apps/api/src/config/modules.ts +0 -83
  129. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
  130. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
  131. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
  132. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
  133. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
  134. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
  135. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
  136. package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
  137. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
  138. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
  139. package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
  140. package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
  141. package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
  142. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
  143. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
  144. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
  145. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
  146. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
  147. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
  148. package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -292
  149. package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
  150. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
  151. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
  152. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
  153. package/templates/apps/api/src/lib/agent-store.ts +0 -613
  154. package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
  155. package/templates/apps/api/src/lib/consent-store.ts +0 -363
  156. package/templates/apps/api/src/lib/content-adapter.ts +0 -112
  157. package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
  158. package/templates/apps/api/src/lib/error-serializer.ts +0 -164
  159. package/templates/apps/api/src/lib/errors.ts +0 -95
  160. package/templates/apps/api/src/lib/file-fallback.ts +0 -87
  161. package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
  162. package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
  163. package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
  164. package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
  165. package/templates/apps/api/src/lib/license-key-store.ts +0 -45
  166. package/templates/apps/api/src/lib/locales.ts +0 -201
  167. package/templates/apps/api/src/lib/outbound-http.ts +0 -127
  168. package/templates/apps/api/src/lib/prisma.ts +0 -21
  169. package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
  170. package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
  171. package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
  172. package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
  173. package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
  174. package/templates/apps/api/src/lib/site.ts +0 -254
  175. package/templates/apps/api/src/lib/slice-load.ts +0 -90
  176. package/templates/apps/api/src/lib/spoke-store.ts +0 -180
  177. package/templates/apps/api/src/lib/stripe.ts +0 -318
  178. package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
  179. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
  180. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
  181. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
  182. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
  183. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
  184. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
  185. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
  186. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
  187. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
  188. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
  189. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
  190. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
  191. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
  192. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
  193. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
  194. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
  195. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
  196. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
  197. package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
  198. package/templates/apps/api/src/middleware/auth.ts +0 -864
  199. package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
  200. package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
  201. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -264
  202. package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
  203. package/templates/apps/api/src/openapi/index.ts +0 -18
  204. package/templates/apps/api/src/openapi/spec.ts +0 -1815
  205. package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
  206. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
  207. package/templates/apps/api/src/routes/aeo/index.ts +0 -107
  208. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
  209. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
  210. package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
  211. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
  212. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
  213. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
  214. package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
  215. package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
  216. package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
  217. package/templates/apps/api/src/routes/auth/user.ts +0 -305
  218. package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -325
  219. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
  220. package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1300
  221. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
  222. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
  223. package/templates/apps/api/src/routes/checkout/index.ts +0 -34
  224. package/templates/apps/api/src/routes/checkout/session.ts +0 -171
  225. package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
  226. package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
  227. package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
  228. package/templates/apps/api/src/routes/consent/account.ts +0 -268
  229. package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
  230. package/templates/apps/api/src/routes/consent/index.ts +0 -26
  231. package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
  232. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
  233. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
  234. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
  235. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
  236. package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
  237. package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
  238. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
  239. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
  240. package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
  241. package/templates/apps/api/src/routes/content/get-page.ts +0 -268
  242. package/templates/apps/api/src/routes/content/index.ts +0 -49
  243. package/templates/apps/api/src/routes/content/list-pages.ts +0 -95
  244. package/templates/apps/api/src/routes/content/list-types.ts +0 -19
  245. package/templates/apps/api/src/routes/content/offerings.ts +0 -184
  246. package/templates/apps/api/src/routes/content/pricing.ts +0 -176
  247. package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
  248. package/templates/apps/api/src/routes/content/search.ts +0 -129
  249. package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
  250. package/templates/apps/api/src/routes/content/slug.ts +0 -9
  251. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
  252. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
  253. package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
  254. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
  255. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
  256. package/templates/apps/api/src/routes/leads/index.ts +0 -573
  257. package/templates/apps/api/src/routes/leads/list.ts +0 -104
  258. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
  259. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
  260. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
  261. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -480
  262. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -465
  263. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
  264. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
  265. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
  266. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
  267. package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
  268. package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
  269. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
  270. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
  271. package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
  272. package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
  273. package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
  274. package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
  275. package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
  276. package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
  277. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
  278. package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
  279. package/templates/apps/api/src/routes/requests/index.ts +0 -54
  280. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
  281. package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
  282. package/templates/apps/api/src/routes/webhooks/README.md +0 -398
  283. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
  284. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
  285. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -448
  286. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
  287. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
  288. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
  289. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
  290. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
  291. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
  292. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
  293. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
  294. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -808
  295. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
  296. package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
  297. package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
  298. package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2026
  299. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -528
  300. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
  301. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
  302. package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
  303. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
  304. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
  305. package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
  306. package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
  307. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -867
  308. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
  309. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
  310. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
  311. package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
  312. package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
  313. package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
  314. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
  315. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
  316. package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
  317. package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1176
  318. package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -444
  319. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -154
  320. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
  321. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
  322. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
  323. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
  324. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
  325. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
  326. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
  327. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
  328. package/templates/apps/api/src/services/abandon-email.ts +0 -313
  329. package/templates/apps/api/src/services/aeo-score.ts +0 -325
  330. package/templates/apps/api/src/services/answer-distributions.ts +0 -138
  331. package/templates/apps/api/src/services/audit-log.ts +0 -961
  332. package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
  333. package/templates/apps/api/src/services/consent.ts +0 -834
  334. package/templates/apps/api/src/services/default-tenant.ts +0 -416
  335. package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -755
  336. package/templates/apps/api/src/services/dunning-policy.ts +0 -294
  337. package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
  338. package/templates/apps/api/src/services/entitlements.ts +0 -338
  339. package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
  340. package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
  341. package/templates/apps/api/src/services/lead-promotion.ts +0 -160
  342. package/templates/apps/api/src/services/lead-routing.ts +0 -1372
  343. package/templates/apps/api/src/services/leads-inbox.ts +0 -312
  344. package/templates/apps/api/src/services/listing-config.ts +0 -178
  345. package/templates/apps/api/src/services/magnet-completion.ts +0 -242
  346. package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -295
  347. package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
  348. package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -868
  349. package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
  350. package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -396
  351. package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -681
  352. package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
  353. package/templates/apps/api/src/services/offerings/catalog.ts +0 -308
  354. package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -385
  355. package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
  356. package/templates/apps/api/src/services/offerings/connection.ts +0 -1003
  357. package/templates/apps/api/src/services/offerings/index.ts +0 -614
  358. package/templates/apps/api/src/services/offerings/source.ts +0 -140
  359. package/templates/apps/api/src/services/offerings/store.ts +0 -150
  360. package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
  361. package/templates/apps/api/src/services/person.ts +0 -1188
  362. package/templates/apps/api/src/services/plan-offerings.ts +0 -125
  363. package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
  364. package/templates/apps/api/src/services/project-listings.ts +0 -2073
  365. package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
  366. package/templates/apps/api/src/services/request-confirm.ts +0 -698
  367. package/templates/apps/api/src/services/revalidation.ts +0 -235
  368. package/templates/apps/api/src/services/slack-notify.ts +0 -291
  369. package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
  370. package/templates/apps/api/src/services/usage-credits.ts +0 -340
  371. package/templates/apps/api/src/services/verified-email.ts +0 -71
  372. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
  373. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
  374. package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
  375. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
  376. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
  377. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
  378. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
  379. package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
  380. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
  381. package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
  382. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
  383. package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
  384. package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
  385. package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
  386. package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
  387. package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
  388. package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1151
  389. package/templates/apps/mcp/__tests__/index.test.ts +0 -195
  390. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
  391. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
  392. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -65
  393. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -187
  394. package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
  395. package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
  396. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -165
  397. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
  398. package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -228
  399. package/templates/apps/mcp/__tests__/locale.test.ts +0 -135
  400. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
  401. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
  402. package/templates/apps/mcp/__tests__/read_content.test.ts +0 -474
  403. package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -225
  404. package/templates/apps/mcp/__tests__/search_content.test.ts +0 -256
  405. package/templates/apps/mcp/__tests__/server.test.ts +0 -388
  406. package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
  407. package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -307
  408. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -223
  409. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
  410. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
  411. package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
  412. package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
  413. package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
  414. package/templates/apps/mcp/src/abuse/index.ts +0 -342
  415. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
  416. package/templates/apps/mcp/src/boot.ts +0 -167
  417. package/templates/apps/mcp/src/config/modules.ts +0 -43
  418. package/templates/apps/mcp/src/http-transport.ts +0 -526
  419. package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
  420. package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
  421. package/templates/apps/mcp/src/lib/content-adapter.ts +0 -142
  422. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -139
  423. package/templates/apps/mcp/src/lib/errors.ts +0 -61
  424. package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
  425. package/templates/apps/mcp/src/lib/locales.ts +0 -171
  426. package/templates/apps/mcp/src/lib/prisma.ts +0 -39
  427. package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
  428. package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
  429. package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
  430. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
  431. package/templates/apps/mcp/src/request-context.ts +0 -52
  432. package/templates/apps/mcp/src/server.ts +0 -343
  433. package/templates/apps/mcp/src/serverless-app.ts +0 -88
  434. package/templates/apps/mcp/src/tools/audit.ts +0 -127
  435. package/templates/apps/mcp/src/tools/capture_lead.ts +0 -64
  436. package/templates/apps/mcp/src/tools/create_project.ts +0 -134
  437. package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
  438. package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
  439. package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
  440. package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
  441. package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
  442. package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
  443. package/templates/apps/mcp/src/tools/index.ts +0 -137
  444. package/templates/apps/mcp/src/tools/list_pages.ts +0 -74
  445. package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
  446. package/templates/apps/mcp/src/tools/proposals.ts +0 -27
  447. package/templates/apps/mcp/src/tools/purchase.ts +0 -205
  448. package/templates/apps/mcp/src/tools/read_content.ts +0 -75
  449. package/templates/apps/mcp/src/tools/request_callback.ts +0 -59
  450. package/templates/apps/mcp/src/tools/search_content.ts +0 -67
  451. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -57
  452. package/templates/apps/mcp/src/workspace-server.ts +0 -224
  453. package/templates/database/CHANGELOG.md +0 -961
  454. package/templates/database/LICENSE +0 -202
  455. package/templates/database/NOTICE +0 -2
  456. package/templates/database/README.md +0 -243
  457. package/templates/database/__tests__/agents.db.test.ts +0 -320
  458. package/templates/database/__tests__/appointment.db.test.ts +0 -106
  459. package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
  460. package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
  461. package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
  462. package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
  463. package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
  464. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
  465. package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
  466. package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
  467. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
  468. package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
  469. package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
  470. package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
  471. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
  472. package/templates/database/__tests__/flows-presets.test.ts +0 -173
  473. package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
  474. package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
  475. package/templates/database/__tests__/member-area.db.test.ts +0 -257
  476. package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
  477. package/templates/database/__tests__/member-contract.db.test.ts +0 -413
  478. package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
  479. package/templates/database/__tests__/offerings-migration.test.ts +0 -197
  480. package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
  481. package/templates/database/__tests__/offerings.db.test.ts +0 -303
  482. package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
  483. package/templates/database/__tests__/person-contact.db.test.ts +0 -563
  484. package/templates/database/__tests__/person-notes.db.test.ts +0 -249
  485. package/templates/database/__tests__/person.db.test.ts +0 -586
  486. package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
  487. package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
  488. package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
  489. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
  490. package/templates/database/__tests__/seed.test.ts +0 -240
  491. package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
  492. package/templates/database/__tests__/tenancy.test.ts +0 -141
  493. package/templates/database/__tests__/user-cascade.test.ts +0 -140
  494. package/templates/database/_gitignore +0 -8
  495. package/templates/database/auth/.gitkeep +0 -0
  496. package/templates/database/auth/schema.prisma +0 -641
  497. package/templates/database/config/.gitkeep +0 -0
  498. package/templates/database/config/schema.prisma +0 -441
  499. package/templates/database/content/.gitkeep +0 -0
  500. package/templates/database/content/schema.prisma +0 -339
  501. package/templates/database/eslint.config.mjs +0 -69
  502. package/templates/database/flows/listing-diagnostic.ts +0 -182
  503. package/templates/database/flows/presets.ts +0 -315
  504. package/templates/database/inbox/.gitkeep +0 -0
  505. package/templates/database/inbox/README.md +0 -3
  506. package/templates/database/inbox/__tests__/schema.test.ts +0 -44
  507. package/templates/database/inbox/schema.prisma +0 -1447
  508. package/templates/database/jest.config.cjs +0 -36
  509. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
  510. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
  511. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
  512. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
  513. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
  514. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
  515. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
  516. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
  517. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
  518. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
  519. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
  520. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
  521. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
  522. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
  523. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
  524. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
  525. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
  526. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
  527. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
  528. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
  529. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
  530. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
  531. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
  532. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
  533. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
  534. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
  535. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
  536. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
  537. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
  538. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
  539. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
  540. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
  541. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
  542. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
  543. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
  544. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
  545. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
  546. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
  547. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
  548. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
  549. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
  550. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
  551. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
  552. package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
  553. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
  554. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
  555. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
  556. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
  557. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
  558. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
  559. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
  560. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
  561. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
  562. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
  563. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
  564. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
  565. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
  566. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
  567. package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
  568. package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
  569. package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
  570. package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
  571. package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
  572. package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
  573. package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
  574. package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
  575. package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
  576. package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
  577. package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
  578. package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
  579. package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
  580. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
  581. package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
  582. package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
  583. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
  584. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
  585. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
  586. package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
  587. package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
  588. package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
  589. package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
  590. package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
  591. package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
  592. package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
  593. package/templates/database/migrations/migration_lock.toml +0 -3
  594. package/templates/database/ops/.gitkeep +0 -0
  595. package/templates/database/ops/schema.prisma +0 -43
  596. package/templates/database/package.json +0 -89
  597. package/templates/database/schema.prisma +0 -71
  598. package/templates/database/scripts/db-generate-locked.sh +0 -80
  599. package/templates/database/scripts/person-backfill.sql +0 -132
  600. package/templates/database/tenancy.ts +0 -183
  601. package/templates/database/tsconfig.build.json +0 -16
  602. package/templates/database/tsconfig.flows.json +0 -15
  603. package/templates/database/tsconfig.json +0 -16
  604. package/templates/database/tsconfig.tenancy.json +0 -14
package/README.md CHANGED
@@ -17,9 +17,13 @@ Compose the site from modules with `--modules`. The recognized vocabulary is
17
17
  `RECOGNIZED_MODULES` in `src/parse-args.ts` — `marketing`, `docs-blog`,
18
18
  `multi-tenant`, `workspace`, `scheduling`, `signal-collectors`, `commerce` —
19
19
  and `--modules` TRIMS or ADDS relative to the level your licence key unlocks
20
- (#6759), never replaces it: with no key the level is Free (`marketing`
21
- alone); a Pro key switches on `docs-blog`, `scheduling` and
22
- `signal-collectors` too; Pro Plus adds `multi-tenant`. Naming modules here
20
+ (#6759), never replaces it: Free is `marketing` alone; a Pro key switches
21
+ on `docs-blog`, `scheduling` and `signal-collectors` too; Pro Plus adds
22
+ `multi-tenant`. A run with no key is a Free run, and Free is held for now
23
+ (`release-scope.json` marks `levels.free` `deferred`, #6484): the CLI refuses
24
+ it before its first write, naming `https://ailaunchkit.ai/pricing` and the
25
+ two ways to pass a key (`--license <key>` or `AILK_LICENSE_KEY`). The Free
26
+ template and level stay defined; only the keyless path is held. Naming modules here
23
27
  keeps exactly those, trimming the level's default; naming only `commerce`
24
28
  (a per-site add-on) or `workspace` (included at Pro, opt-in) adds it on top
25
29
  of the level's default without trimming. The level is always DERIVED from
@@ -42,24 +46,27 @@ vocabulary is `RECOGNIZED_SHAPES` in `src/parse-args.ts` — `organization-produ
42
46
  `organization-service`, `local-business-service`, `person-service` (the README
43
47
  already lists `RECOGNIZED_MODULES` the same way); `local-business-product` is
44
48
  refused as not available yet. A terminal run with no `--shape` asks; a
45
- non-interactive one stops. The level comes only from your license key: no key
46
- is Free, and a key switches on its level's modules (`LEVEL_MODULES`) —
47
- `--modules` trims or adds relative to that set, as above. A keyed example:
49
+ non-interactive one stops. The level comes only from your license key: a key
50
+ switches on its level's modules (`LEVEL_MODULES`) — `--modules` trims or adds
51
+ relative to that set, as above — and no key is the Free level, which is held
52
+ (above), so the run is refused before the shape prompt. A keyed example:
48
53
 
49
54
  ```bash
50
55
  pnpm create ailk@latest my-site --shape organization-service --license <key>
51
56
  ```
52
57
 
53
58
  `--design minimalism` picks the other look and needs a Pro or Pro Plus key;
54
- `standard` (the default) needs none. `--template <alias>` scaffolds one of the
59
+ `standard` (the default) needs none of its own (the run itself still needs a
60
+ key while Free is held, above). `--template <alias>` scaffolds one of the
55
61
  three named aliases (`marketing-site-free`, `marketing-site`, `saas-product`) —
56
62
  each fixes a shape, a design and its own module list — and cannot be combined
57
- with `--shape` or `--design`.
63
+ with `--shape` or `--design`; `marketing-site-free` with no key is refused the
64
+ same way while Free is held.
58
65
 
59
66
  ### Add a purchased module to an existing site
60
67
 
61
- A site scaffolded without a paid module (a Free site whose owner then buys
62
- Pro, say) gets it with `add-module` — alias `upgrade` — run against the site
68
+ A site scaffolded without a paid module (a site scaffolded with `--modules
69
+ marketing` whose owner then adds `docs-blog`, say) gets it with `add-module` — alias `upgrade` — run against the site
63
70
  itself, with `AILK_LICENSE_KEY` covering the module:
64
71
 
65
72
  ```bash
@@ -214,9 +221,9 @@ as-is, they never fail the check, and `--apply` never overwrites them.
214
221
 
215
222
  `--apply` only creates route directories that are absent, through the same
216
223
  copier a fresh scaffold uses (so the copied files are byte-identical to a fresh
217
- scaffold's). It never rewrites or deletes an existing file, never writes
218
- outside `apps/web/app/[locale]/`, runs no install, and a second run is a
219
- no-op. `--apply` exits 0 on success.
224
+ scaffold's). It never rewrites or deletes an existing file, writes nothing
225
+ outside `apps/web/app/[locale]/` except the local modules those routes import
226
+ (below), runs no install, and a second run is a no-op. `--apply` exits 0 on success.
220
227
 
221
228
  **Scope.** Every core route (`about`, `contact`, `faq`, `thanks/[slug]`,
222
229
  `sign-in`) is always checked, and so is the `(authed)` route GROUP —
@@ -232,17 +239,30 @@ gated off at scaffold time is listed as skipped, not missing — its absence is
232
239
  deliberate, not drift. Add a surface with `--sync-architecture` and the
233
240
  `add-page` skill, not with `sync-routes`.
234
241
 
235
- **The lib-and-messages dependency contract (#5014).** Some routes import
236
- files OUTSIDE their own route directory — `sign-in/page.tsx` imports
237
- `apps/web/lib/auth-env.ts` and `lib/site-brand.tsx`; the `(authed)` group's
238
- `layout.tsx` imports `apps/web/auth.ts`; `(authed)/account/page.tsx` imports
239
- `lib/account-config.ts`, `lib/server-api.ts`, and two files from its
240
- `(authed)/waitlist` sibling (`components/ForbiddenState.tsx`, `format.ts`).
241
- Copying a route's directory alone would leave those imports dangling in an
242
- older consumer that never had them. `ROUTE_DEPENDENCIES` in `src/surfaces.ts`
243
- declares them per route; `sync-routes` copies each one `--apply` finds
244
- missing (never overwriting — the same rule routes themselves follow) and
245
- reports it in check mode under an `Also required` heading. `ROUTE_MESSAGE_NAMESPACES`
242
+ **The local-module dependency contract (#5014, #9406).** Some routes import
243
+ files OUTSIDE their own route directory — `purchase/success/page.tsx` imports
244
+ `apps/web/src/lib/commerce-claim.ts`; the `(authed)` group's `layout.tsx`
245
+ imports `apps/web/auth.ts`. Copying a route's directory alone would leave those
246
+ imports dangling in an older consumer that never had them. So `sync-routes`
247
+ resolves every relative import (`./`, `../`) of every file the route would
248
+ copy, and of every helper that brings in turn, against the site first and then
249
+ the template. `ROUTE_DEPENDENCIES` in `src/surfaces.ts` is a declared
250
+ supplement, unioned with what the resolver finds. Each imported module has one
251
+ of three outcomes:
252
+
253
+ - **Copied** — the site lacks it and the template has it: `--apply` copies it
254
+ (never overwriting) and check mode lists it under `copies:` and `Also
255
+ required`.
256
+ - **Left as-is** — the site has it and its copy differs from the template's:
257
+ it is named under `left as-is (differs from the template)` and never
258
+ written. The route is still copied; run your type-check afterwards.
259
+ - **Refused** — the import resolves to no file in the site or the template,
260
+ only to a spoke-excluded file, or to a surface the site does not carry: the
261
+ route is listed under `cannot resolve:` and `--apply` does not write it, nor
262
+ its sub-routes, nor a route that imports from it. Its ancestor route is still
263
+ copied without the refused sub-tree.
264
+
265
+ `ROUTE_MESSAGE_NAMESPACES`
246
266
  does the same for the i18n namespaces a route's copy needs
247
267
  (`signIn`, `account`, `waitlistDashboard.gate`) — but CHECK-ONLY: a
248
268
  consumer's `apps/web/messages/<locale>.json` already exists and may carry
@@ -483,6 +503,17 @@ from the module distribution's own 401/403 (`src/lib/fetch-module.ts`). The
483
503
  gate runs before anything is copied (`scaffold()` in `src/programmatic.ts`), so
484
504
  a refused run leaves no partial scaffold behind.
485
505
 
506
+ While the Free level is held (`release-scope.json` `levels.free: "deferred"`,
507
+ #6484), a request that names no paid module needs a key as well: with none,
508
+ `resolvePaidModules` and `cli.ts` call `assertKeyedOrFreeReleased`, which
509
+ refuses the run with `level "free" is not available yet. No licence key, so
510
+ this would be a Free scaffold — pass --license <key> or set AILK_LICENSE_KEY
511
+ with a Pro key → https://ailaunchkit.ai/pricing`, before any prompt, fetch or
512
+ write. The key is read on that path but never validated or sent — an all-Free
513
+ request still makes no request — and a keyed run proceeds exactly as before.
514
+ `AILK_RELEASE_SCOPE=ignore` is the test-only bypass (this package's jest
515
+ setup); a published CLI never sets it.
516
+
486
517
  `AILK_MODULE_REGISTRY_URL` is optional: `fetchModule` uses an explicitly passed
487
518
  `registryUrl`, then that variable, then `https://api.ailaunchkit.ai/v1/modules`
488
519
  (`DEFAULT_AILK_MODULE_REGISTRY_URL`, `src/lib/fetch-module.ts`).
@@ -493,7 +524,10 @@ explicitly passed `registryUrl`, then that variable, then
493
524
  either registry fails the fetch before any second request is sent.
494
525
 
495
526
  ```bash
496
- # free-only — no key read, no network call
527
+ # all-Free — the key is read (Free is held), never validated or sent; no network call
528
+ AILK_LICENSE_KEY=... pnpm create ailk@latest my-site --shape organization-product --modules marketing
529
+
530
+ # the same run with no key is refused before its first write (exit 1)
497
531
  pnpm create ailk@latest my-site --shape organization-product --modules marketing
498
532
 
499
533
  # paid — the key is read from the environment
@@ -502,9 +536,10 @@ AILK_LICENSE_KEY=... pnpm create ailk@latest my-site --shape organization-produc
502
536
 
503
537
  The network invariant (#6759 D6), in full:
504
538
 
505
- - **No key** → no request at all. A request that names no paid module never
506
- reaches the key check either: `resolvePaidModules` returns an empty map on
507
- its first branch, before touching `process.env` or the network.
539
+ - **No key** → no request at all. A request that names no paid module reads
540
+ the key (#6484) but never validates or sends it: `resolvePaidModules` runs
541
+ `assertKeyedOrFreeReleased` — refusing a keyless run while Free is held —
542
+ and returns an empty map on its first branch, before the network.
508
543
  - **A key with no `--modules`** → the level probe (`deriveLevel`): 3-4
509
544
  requests, to find out what the key unlocks.
510
545
  - **An explicit `--modules` list** → requests only for the paid modules it
@@ -513,7 +548,7 @@ The network invariant (#6759 D6), in full:
513
548
  ## What it does
514
549
 
515
550
  1. Validates the target directory does not exist OR is empty.
516
- 2. Copies the curated template tree (`apps/{web,api,mcp}` + `database/` + `content/` + root config files) from the package's `templates/` directory.
551
+ 2. Copies the curated template tree (`apps/{web,api,mcp}` + the thin `database/` — `prisma.config.ts` over the installed `@working-theory/database`, plus the two seeds — + `content/` + root config files) from the package's `templates/` directory.
517
552
  3. Substitutes `workspace:*` references in every `package.json` with the matching `@working-theory/*` semver from npm — versions are pinned at npm-publish time.
518
553
  4. Substitutes `{{PROJECT_NAME}}`, `{{COMPANY_NAME}}`, `{{COMPANY_DOMAIN}}` markers in `templates/README.md` from the target directory name (and CLI flags / interactive prompts in future versions).
519
554
  5. Derives and writes `architecture.yaml` (the site's code-boundary config) from the selected module set — see below.
@@ -544,10 +579,10 @@ declares a slice for every recognized module.
544
579
  ## Templates are snapshotted at build time
545
580
 
546
581
  The `prepublishOnly` script (`scripts/build-templates.mjs`) reads the canonical
547
- sources from this monorepo (`apps/`, `database/`, `content/`, root config) and
548
- populates `templates/`. The npm tarball ships the populated templates via the
549
- `files` field. A free-only scaffold performs no network access at scaffold
550
- time; only `pnpm install` (run by the user after scaffolding) hits the npm
582
+ sources from this monorepo (`apps/`, the two `database/` seeds, `content/`, root
583
+ config) and populates `templates/`. The npm tarball ships the populated templates via the
584
+ `files` field. An all-Free scaffold (a key plus `--modules marketing`)
585
+ performs no network access at scaffold time; only `pnpm install` (run by the user after scaffolding) hits the npm
551
586
  registry. A run naming a paid module fetches that module's bundle — see
552
587
  [Paid modules require `AILK_LICENSE_KEY`](#paid-modules-require-ailk_license_key).
553
588
 
@@ -1283,7 +1283,7 @@
1283
1283
  "sourcePath": "packages/ui/src/blocks/ListRow.tsx",
1284
1284
  "importPath": "@working-theory/ui/blocks",
1285
1285
  "exported": true,
1286
- "description": "The PHONE form of one admin list item. The reference is `apps-paid/admin/design/demos/first-steps/demo.html:475` (`rowDoc`), which lays the row out as: a leading type glyph, a two-line text column with the MUTED META LINE FIRST and the item's name second (every phone screen in the demo agrees), an optional trailing control, and a chevron.",
1286
+ "description": "The PHONE form of one admin list item. The reference is `packages-paid/admin/design/demos/first-steps/demo.html:475` (`rowDoc`), which lays the row out as: a leading type glyph, a two-line text column with the MUTED META LINE FIRST and the item's name second (every phone screen in the demo agrees), an optional trailing control, and a chevron.",
1287
1287
  "descriptionSource": "doc-comment",
1288
1288
  "descriptionGrade": "strong",
1289
1289
  "sectionType": null
@@ -1294,7 +1294,7 @@
1294
1294
  "sourcePath": "packages/ui/src/blocks/ListTable.tsx",
1295
1295
  "importPath": "@working-theory/ui/blocks",
1296
1296
  "exported": true,
1297
- "description": "The desktop form: a fixed-layout list table that never wraps, with the shared Tags and Live cells. The reference is `apps-paid/admin/design/demos/first-steps/demo.html`'s `.tbl`: `table-layout:fixed` on the table and `white-space:nowrap;overflow:hidden;text-overflow:ellipsis` on every cell. BOTH are load-bearing — `table-fixed` alone lets the cell wrap, `truncate` alone lets the browser widen the column to fit.",
1297
+ "description": "The desktop form: a fixed-layout list table that never wraps, with the shared Tags and Live cells. The reference is `packages-paid/admin/design/demos/first-steps/demo.html`'s `.tbl`: `table-layout:fixed` on the table and `white-space:nowrap;overflow:hidden;text-overflow:ellipsis` on every cell. BOTH are load-bearing — `table-fixed` alone lets the cell wrap, `truncate` alone lets the browser widen the column to fit.",
1298
1298
  "descriptionSource": "barrel",
1299
1299
  "descriptionGrade": "strong",
1300
1300
  "sectionType": null
@@ -1646,7 +1646,7 @@
1646
1646
  "sourcePath": "packages/ui/src/blocks/RowGroup.tsx",
1647
1647
  "importPath": "@working-theory/ui/blocks",
1648
1648
  "exported": true,
1649
- "description": "The bordered box that groups ListRows with hairline dividers. The reference is `apps-paid/admin/design/demos/first-steps/demo.html`'s `.box` (`background:var(--bg);border:1px solid var(--border); border-radius:6px;overflow:hidden`) with `.row{border-top:…}` and `.row:first-child{border-top:0}` — i.e. hairlines BETWEEN rows, none above the first.",
1649
+ "description": "The bordered box that groups ListRows with hairline dividers. The reference is `packages-paid/admin/design/demos/first-steps/demo.html`'s `.box` (`background:var(--bg);border:1px solid var(--border); border-radius:6px;overflow:hidden`) with `.row{border-top:…}` and `.row:first-child{border-top:0}` — i.e. hairlines BETWEEN rows, none above the first.",
1650
1650
  "descriptionSource": "barrel",
1651
1651
  "descriptionGrade": "strong",
1652
1652
  "sectionType": null
@@ -177,8 +177,8 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
177
177
  | `LeadCaptureForm` | The one contact form every template renders. Submits ONLY through the `action` prop — a Server Action the page binds — so there is no fetch, no URL and no browser-side JSON here. | `import { LeadCaptureForm } from "@working-theory/ui/blocks"` |
178
178
  | `LinkCard` | A whole-tile link card: the entire tile IS the anchor (Claude-docs link-card anatomy). Optional leading icon, a title heading, and an optional description paragraph. Hover fill + chrome are intrinsic to the block — never props. | `import { LinkCard } from "@working-theory/ui/blocks"` |
179
179
  | `LinkListItem` | Hub-page spoke list row: prose Link + optional description, enlarged to the 44px touch-target floor. Fix: the enlarged-hit-area pattern (same idiom as ShortcutTrigger, SegmentedControl's touchTargetFloor) — `min-h-(control-height-big)` clamps the anchor's clickable box to 44px while `inline-flex items-center` keeps the visible text at its normal prose size. | `import { LinkListItem } from "@working-theory/ui/blocks"` |
180
- | `ListRow` | The PHONE form of one admin list item. The reference is `apps-paid/admin/design/demos/first-steps/demo.html:475` (`rowDoc`), which lays the row out as: a leading type glyph, a two-line text column with the MUTED META LINE FIRST and the item's name second (every phone screen in the demo agrees), an optional trailing control, and a chevron. | `import { ListRow } from "@working-theory/ui/blocks"` |
181
- | `ListTable` | The desktop form: a fixed-layout list table that never wraps, with the shared Tags and Live cells. The reference is `apps-paid/admin/design/demos/first-steps/demo.html`'s `.tbl`: `table-layout:fixed` on the table and `white-space:nowrap;overflow:hidden;text-overflow:ellipsis` on every cell. BOTH are load-bearing — `table-fixed` alone lets the cell wrap, `truncate` alone lets the browser widen the column to fit. | `import { ListTable } from "@working-theory/ui/blocks"` |
180
+ | `ListRow` | The PHONE form of one admin list item. The reference is `packages-paid/admin/design/demos/first-steps/demo.html:475` (`rowDoc`), which lays the row out as: a leading type glyph, a two-line text column with the MUTED META LINE FIRST and the item's name second (every phone screen in the demo agrees), an optional trailing control, and a chevron. | `import { ListRow } from "@working-theory/ui/blocks"` |
181
+ | `ListTable` | The desktop form: a fixed-layout list table that never wraps, with the shared Tags and Live cells. The reference is `packages-paid/admin/design/demos/first-steps/demo.html`'s `.tbl`: `table-layout:fixed` on the table and `white-space:nowrap;overflow:hidden;text-overflow:ellipsis` on every cell. BOTH are load-bearing — `table-fixed` alone lets the cell wrap, `truncate` alone lets the browser widen the column to fit. | `import { ListTable } from "@working-theory/ui/blocks"` |
182
182
  | `LocaleSwitcher` | Compact globe + locale dropdown. Extracts the "🌐 English ▾" affordance that lived as an inline node in the chrome Footer story into a reusable block. Composes the `Select` primitive (NOT a raw &lt;select>): a leading globe icon, the current locale label (via SelectValue), and the trigger's built-in chevron. | `import { LocaleSwitcher } from "@working-theory/ui/blocks"` |
183
183
  | `LocaleSwitcherNav` | Composes the controlled `LocaleSwitcher` block and owns the navigation side-effect that block deliberately leaves to its consumer: on a locale change it writes the `NEXT_LOCALE` cookie and navigates to the as-needed prefixed path (default locale unprefixed, every other locale `/&lt;code>` + path — mirroring `apps/web/middleware.ts`'s `localePrefix: "as-needed"`). | `import { LocaleSwitcherNav } from "@working-theory/ui/blocks"` |
184
184
  | `LogoRow` | The ONE logo-strip implementation; bounded layout/treatment/logoSize plus an opt-in motion-safe marquee; composed by the LogoCloud section and the Hero logoStrip opt-in. | `import { LogoRow } from "@working-theory/ui/blocks"` |
@@ -210,7 +210,7 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
210
210
  | `Prose` | The single typography wrapper both the docs route and blog render their compiled-MDX body inside. It styles every RAW markdown element a compiled document emits — h2–h6, p, ul/ol/li, blockquote, table parts, hr, a, inline code, pre, img, kbd, strong/em — via `@working-theory/theme` semantic tokens and type roles. No raw color or spacing literals; dark mode rides the semantic tokens (no `dark:` variants needed). | `import { Prose } from "@working-theory/ui/blocks"` |
211
211
  | `RecommendationCard` | "For you" proactive-recommendation tile: status + title + description + "Why this?" disclosure + context chip + action + dismiss (ploy-capture recomposition). The "For you" proactive-recommendation card captured off ploy.ai's Overview page (behavior spec: -2, — `overview-page` "For you" feed / rebuild-triage row "For you" recommendation card"). | `import { RecommendationCard } from "@working-theory/ui/blocks"` |
212
212
  | `ResponsiveSheet` | ONE component, TWO forms, ONE open pair. Renders its `children` as a Radix Dialog at `md` (768px, --breakpoint-md) and up, and as a full-screen Radix Sheet below it — never both at once. | `import { ResponsiveSheet } from "@working-theory/ui/blocks"` |
213
- | `RowGroup` | The bordered box that groups ListRows with hairline dividers. The reference is `apps-paid/admin/design/demos/first-steps/demo.html`'s `.box` (`background:var(--bg);border:1px solid var(--border); border-radius:6px;overflow:hidden`) with `.row{border-top:…}` and `.row:first-child{border-top:0}` — i.e. hairlines BETWEEN rows, none above the first. | `import { RowGroup } from "@working-theory/ui/blocks"` |
213
+ | `RowGroup` | The bordered box that groups ListRows with hairline dividers. The reference is `packages-paid/admin/design/demos/first-steps/demo.html`'s `.box` (`background:var(--bg);border:1px solid var(--border); border-radius:6px;overflow:hidden`) with `.row{border-top:…}` and `.row:first-child{border-top:0}` — i.e. hairlines BETWEEN rows, none above the first. | `import { RowGroup } from "@working-theory/ui/blocks"` |
214
214
  | `SchedulerEmbed` | A declarative third-party booking iframe. Renders a full-width, border-0, lazy-loaded &lt;iframe> at `src` with a graceful loading skeleton (shown until the iframe's own `load` event fires) and a timeout-gated plain-link fallback beneath it — for environments that block third-party frames (ad blockers, a strict CSP `frame-src`) where the iframe may load blank or never load at all. | `import { SchedulerEmbed } from "@working-theory/ui/blocks"` · `packages/ui/src/blocks/SchedulerEmbed.tsx` |
215
215
  | `SectionActionRow` | The bottom-anchored, centered action row a section places BENEATH its own content, at the 44×44px target-size floor. It is the block form of the placement established for `stair-steps`: a bounded 1-2 action list rendered after the section body rather than inside the section header. | `import { SectionActionRow } from "@working-theory/ui/blocks"` |
216
216
  | `SectionHeader` | Alignment-parameterized section header (eyebrow/subtitle/description/supportLink). The same component serves two ranks (headingLevel="section" \| "subsection") and three alignments (align="start" \| "center" \| "end"). It knows nothing about columns/splits/carousels — it is width-flexible and fills whatever container the section places it in. | `import { SectionHeader } from "@working-theory/ui/blocks"` |
@@ -35,7 +35,7 @@ import { writeAuthSecretFile } from "./lib/auth-secret-file.js";
35
35
  import { appendEnvRows } from "./lib/declared-env.js";
36
36
  import { diffTwoStrings, extractModuleBundle, } from "./lib/extract-module-bundle.js";
37
37
  import { normalizeModules } from "./module-architecture.js";
38
- import { MODULE_FLAGS_PATH, PAID_SECTIONS_PATH, writePaidSections } from "./paid-sections.js";
38
+ import { MODULE_FLAGS_PATH, PAID_MCP_TOOLS_PATH, PAID_SECTIONS_PATH, writePaidSections, } from "./paid-sections.js";
39
39
  import { ParseError, parseModules } from "./parse-args.js";
40
40
  import { writeSpokeFlowsReadme } from "./seed-flows.js";
41
41
  import { SITE_ROSTER_PATH, moduleRosterRows, planRosterAppend, readSiteRoster, siteRosterProblems, } from "./site-roster.js";
@@ -211,7 +211,9 @@ export async function applyModuleToScaffold(opts) {
211
211
  // overwritten, like `architecture.yaml` above.
212
212
  // #8843 D10 — its module-presence flags follow the same file, and are
213
213
  // reported the same way when a module turns one on.
214
- const generated = [PAID_SECTIONS_PATH, MODULE_FLAGS_PATH].map((path) => {
214
+ // #9460 DD6 — the paid MCP tool registry follows `apps/mcp/package.json`
215
+ // the same way.
216
+ const generated = [PAID_SECTIONS_PATH, MODULE_FLAGS_PATH, PAID_MCP_TOOLS_PATH].map((path) => {
215
217
  const abs = join(targetAbs, path);
216
218
  return { path, abs, before: existsSync(abs) ? readFileSync(abs, "utf8") : undefined };
217
219
  });
@@ -351,7 +353,9 @@ export function formatAddModuleReport(result, moduleName) {
351
353
  const lines = [
352
354
  `[create-ailk] add-module ${moduleName} → ${result.targetDir}`,
353
355
  ];
354
- if (result.report.length === 0 && result.routes.applied.length === 0) {
356
+ if (result.report.length === 0 &&
357
+ result.routes.applied.length === 0 &&
358
+ result.routes.refused.length === 0) {
355
359
  lines.push(`Nothing to add — the site already carries everything ${moduleName} brings.`);
356
360
  }
357
361
  if (written.length > 0) {
@@ -387,6 +391,9 @@ export function formatAddModuleReport(result, moduleName) {
387
391
  lines.push(`Also copied ${routes.appliedDependencies.length} file(s) those routes import:`);
388
392
  lines.push(...routes.appliedDependencies.map((dep) => ` ${dep}`));
389
393
  }
394
+ if (routes.refused.length > 0) {
395
+ lines.push(`Routes not copied (${routes.refused.length}) — an import does not resolve (run create-ailk sync-routes for the paths): ${routes.refused.join(", ")}`);
396
+ }
390
397
  if (routes.missingMessageNamespaces.length > 0) {
391
398
  lines.push("Also required — message namespace(s) not found in apps/web/messages/en.json (add manually, not auto-merged):");
392
399
  lines.push(...routes.missingMessageNamespaces.map((ns) => ` ${ns}`));
@@ -72,6 +72,11 @@ export interface AddMagnetResult {
72
72
  flow: string;
73
73
  /** The landing's row, then the walk's. */
74
74
  report: MagnetReportRow[];
75
+ /**
76
+ * The `customizations.yaml` entry mapping both pages, indented to append
77
+ * under `customizations:` as `--seed-customizations` prints entries.
78
+ */
79
+ entry: string;
75
80
  }
76
81
  /**
77
82
  * Write a magnet page pair — `apps/web/app/[locale]/<path>/page.tsx` (the
@@ -83,6 +88,12 @@ export interface AddMagnetResult {
83
88
  * that already exists is never overwritten: a second run reports both
84
89
  * `skipped`. No `architecture.yaml`, nav or seed changes — the pair is the
85
90
  * site's own, with no `ROUTE_SINCE` key or routes-map row (D13).
91
+ *
92
+ * Being the site's own, the pair is no template-record row either: `update`
93
+ * deletes an untouched recorded file the template does not carry. So the
94
+ * site lint's R5a reads both pages as site-authored, and the result carries
95
+ * the `customizations.yaml` entry that maps them, a site-kept decision the
96
+ * report prints ready to paste (#9553).
86
97
  */
87
98
  export declare function addMagnetToScaffold(opts: AddMagnetOptions): AddMagnetResult;
88
99
  /** The report `add-route magnet` prints. */
@@ -98,7 +109,7 @@ export interface AddRouteArgs {
98
109
  /** `--flow`, the magnet mode's flow slug — set only with `magnet`. */
99
110
  flow?: string;
100
111
  }
101
- export declare const ADD_ROUTE_HELP = "create-ailk add-route \u2014 add a route family to an existing site.\n\nUsage:\n create-ailk add-route <route> [<target-dir>]\n create-ailk add-route magnet --path <path> --flow <slug> [<target-dir>]\n\nArguments:\n <route> One route family, named as --surfaces names it,\n e.g. pricing.\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nOptions:\n --path <path> magnet only: the site path the landing serves,\n one to three kebab-case segments, e.g. /diagnostic.\n --flow <slug> magnet only: the flow slug the pages are bound to.\n --help, -h Print this message.\n\nCopies the route's pages, writes its seed content, declares it in\narchitecture.yaml and adds its link to the generated nav \u2014 the site a fresh\nscaffold with --surfaces <route> would have been. A file the site already has\nis never overwritten: one whose content differs, a hand-edited nav included,\nis left as-is and listed for manual review with the change the route wanted.\nLike add-module, it also restores any other page route the site carries but\nlacks. A route a module delivers (blog and docs come with docs-blog) is\nrefused; add that module with create-ailk add-module. Running it again changes\nnothing.\n\nadd-route magnet writes a magnet page pair bound to one flow: a landing at\napps/web/app/[locale]/<path>/page.tsx and a full-screen walk at\n<path>/start/page.tsx, each a few lines over the standard magnet pages, so the\ncopy, consent and ending come from the flow's record. It needs the\nsignal-collectors module, and refuses (nothing written) a path the site already\nserves, a one-segment path a LandingPage seed of the same slug owns, a path\nending in start or apply, a reserved first segment (api, v1, flows, account,\nadmin, the sign-in routes, a locale) and a slug the flow API would refuse. A\npage that exists is never overwritten: running it again skips both. It changes\nno architecture.yaml, nav or seed.\n";
112
+ export declare const ADD_ROUTE_HELP = "create-ailk add-route \u2014 add a route family to an existing site.\n\nUsage:\n create-ailk add-route <route> [<target-dir>]\n create-ailk add-route magnet --path <path> --flow <slug> [<target-dir>]\n\nArguments:\n <route> One route family, named as --surfaces names it,\n e.g. pricing.\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nOptions:\n --path <path> magnet only: the site path the landing serves,\n one to three kebab-case segments, e.g. /diagnostic.\n --flow <slug> magnet only: the flow slug the pages are bound to.\n --help, -h Print this message.\n\nCopies the route's pages, writes its seed content, declares it in\narchitecture.yaml and adds its link to the generated nav \u2014 the site a fresh\nscaffold with --surfaces <route> would have been. A file the site already has\nis never overwritten: one whose content differs, a hand-edited nav included,\nis left as-is and listed for manual review with the change the route wanted.\nLike add-module, it also restores any other page route the site carries but\nlacks. A route a module delivers (blog and docs come with docs-blog) is\nrefused; add that module with create-ailk add-module. Running it again changes\nnothing.\n\nadd-route magnet writes a magnet page pair bound to one flow: a landing at\napps/web/app/[locale]/<path>/page.tsx and a full-screen walk at\n<path>/start/page.tsx, each a few lines over the standard magnet pages, so the\ncopy, consent and ending come from the flow's record. It needs the\nsignal-collectors module, and refuses (nothing written) a path the site already\nserves, a one-segment path a LandingPage seed of the same slug owns, a path\nending in start or apply, a reserved first segment (api, v1, flows, account,\nadmin, the sign-in routes, a locale) and a slug the flow API would refuse. A\npage that exists is never overwritten: running it again skips both. It changes\nno architecture.yaml, nav or seed; it prints the customizations.yaml entry\nthat maps the two pages, for pnpm architecture.\n";
102
113
  /**
103
114
  * Parse the argv AFTER the `add-route` word. Strict `node:util` parseArgs,
104
115
  * like `parseAddModuleArgs`; the route itself is validated by
package/dist/add-route.js CHANGED
@@ -226,13 +226,16 @@ export function formatAddRouteReport(result) {
226
226
  const skipped = result.report.filter((row) => row.action === "skipped");
227
227
  const routes = result.routes ?? {
228
228
  applied: [],
229
+ refused: [],
229
230
  appliedDependencies: [],
230
231
  missingMessageNamespaces: [],
231
232
  };
232
233
  const lines = [
233
234
  `[create-ailk] add-route ${result.route} → ${result.targetDir}`,
234
235
  ];
235
- if (result.report.length === 0 && routes.applied.length === 0) {
236
+ if (result.report.length === 0 &&
237
+ routes.applied.length === 0 &&
238
+ routes.refused.length === 0) {
236
239
  lines.push(`Nothing to add — the site already carries the ${result.route} route.`);
237
240
  }
238
241
  if (routes.applied.length > 0) {
@@ -243,6 +246,9 @@ export function formatAddRouteReport(result) {
243
246
  lines.push(`Also copied ${routes.appliedDependencies.length} file(s) those routes import:`);
244
247
  lines.push(...routes.appliedDependencies.map((dep) => ` ${dep}`));
245
248
  }
249
+ if (routes.refused.length > 0) {
250
+ lines.push(`Routes not copied (${routes.refused.length}) — an import does not resolve (run create-ailk sync-routes for the paths): ${routes.refused.join(", ")}`);
251
+ }
246
252
  if (written.length > 0) {
247
253
  lines.push(`Written (${written.length}):`);
248
254
  lines.push(...written.map((row) => ` ${row.path}`));
@@ -308,6 +314,11 @@ const RESERVED_FIRST_SEGMENTS = new Set([
308
314
  const LOCALE_SHAPED_RE = /^[a-z]{2}(-[a-z]{2})?$/;
309
315
  /** Template-relative root every page directory sits under. */
310
316
  const WEB_ROUTE_ROOT = "apps/web/app/[locale]";
317
+ /**
318
+ * The `request` a pair's `customizations.yaml` entry names (#9553): the AILK
319
+ * issue that made the pair the site's own page (#8840 C1).
320
+ */
321
+ const MAGNET_REQUEST = "working-theory-labs/ai-launch-kit-internal#8840";
311
322
  /** Whether `slug` passes `flowSlugSchema`'s rule. */
312
323
  export function isMagnetFlowSlug(slug) {
313
324
  return slug.length <= FLOW_SLUG_MAX && FLOW_SLUG_RE.test(slug);
@@ -322,6 +333,12 @@ export function isMagnetFlowSlug(slug) {
322
333
  * that already exists is never overwritten: a second run reports both
323
334
  * `skipped`. No `architecture.yaml`, nav or seed changes — the pair is the
324
335
  * site's own, with no `ROUTE_SINCE` key or routes-map row (D13).
336
+ *
337
+ * Being the site's own, the pair is no template-record row either: `update`
338
+ * deletes an untouched recorded file the template does not carry. So the
339
+ * site lint's R5a reads both pages as site-authored, and the result carries
340
+ * the `customizations.yaml` entry that maps them, a site-kept decision the
341
+ * report prints ready to paste (#9553).
325
342
  */
326
343
  export function addMagnetToScaffold(opts) {
327
344
  const targetAbs = resolve(opts.targetDir);
@@ -376,7 +393,23 @@ export function addMagnetToScaffold(opts) {
376
393
  writeFileSync(dest, text);
377
394
  report.push({ path, action: "written" });
378
395
  }
379
- return { targetDir: targetAbs, path: opts.path, flow: opts.flow, report };
396
+ // Segments join on `--`, which no kebab segment carries, so `/a-b` and
397
+ // `/a/b` never share an id.
398
+ const today = new Date().toISOString().slice(0, 10);
399
+ const entry = [
400
+ ` - id: ${JSON.stringify(`magnet-${segments.join("--")}`)}`,
401
+ " paths:",
402
+ ...pages.map(([path]) => ` - ${JSON.stringify(path)}`),
403
+ ` request: ${JSON.stringify(MAGNET_REQUEST)}`,
404
+ ` decision: ${JSON.stringify(`build-in: site — ailk#8840, ${today}, a magnet pair is the site's own page over AILK's standard renderers`)}`,
405
+ ].join("\n");
406
+ return {
407
+ targetDir: targetAbs,
408
+ path: opts.path,
409
+ flow: opts.flow,
410
+ report,
411
+ entry,
412
+ };
380
413
  }
381
414
  /** `--path`'s segments, refusing a path a pair may not take (SEC-8840-J). */
382
415
  function magnetPathSegments(path) {
@@ -501,7 +534,7 @@ export function formatAddMagnetReport(result) {
501
534
  lines.push(...skipped.map((row) => ` ${row.path}`));
502
535
  }
503
536
  if (written.length > 0) {
504
- lines.push(`Next: pnpm build, then open ${result.path}. The page's copy comes from the ${result.flow} flow's record.`);
537
+ lines.push(`Next: append this entry to customizations.yaml unless it is there already (an empty \`customizations: []\` becomes \`customizations:\` first), then pnpm build and open ${result.path}. The page's copy comes from the ${result.flow} flow's record.`, result.entry);
505
538
  }
506
539
  return lines.join("\n") + "\n";
507
540
  }
@@ -542,7 +575,8 @@ serves, a one-segment path a LandingPage seed of the same slug owns, a path
542
575
  ending in start or apply, a reserved first segment (api, v1, flows, account,
543
576
  admin, the sign-in routes, a locale) and a slug the flow API would refuse. A
544
577
  page that exists is never overwritten: running it again skips both. It changes
545
- no architecture.yaml, nav or seed.
578
+ no architecture.yaml, nav or seed; it prints the customizations.yaml entry
579
+ that maps the two pages, for pnpm architecture.
546
580
  `;
547
581
  /**
548
582
  * Parse the argv AFTER the `add-route` word. Strict `node:util` parseArgs,
package/dist/cli.js CHANGED
@@ -55,7 +55,7 @@ import { ADOPT_HELP, AdoptRefusedError, adoptSite, formatAdoptReport, parseAdopt
55
55
  import { APPLY_DESIGN_HELP, applyDesign, formatApplyDesignReport, parseApplyDesignArgs, } from "./apply-design.js";
56
56
  import { CLAUDE_MD_CHECK_PATH } from "./claude-md.js";
57
57
  import { buildScaffoldMarkers } from "./copy.js";
58
- import { assertReleased } from "./lib/module-license-gate.js";
58
+ import { assertKeyedOrFreeReleased, assertReleased } from "./lib/module-license-gate.js";
59
59
  import { withNpmTokenUserConfig } from "./lib/npm-auth.js";
60
60
  import { FREE_PREREQUISITES_NOTE, LICENSED_PREREQUISITES_NOTE, isLicensedInstall, proCallout, } from "./lib/pro-callout.js";
61
61
  import { LICENSE_SET_HELP, runLicenseSet } from "./license-set.js";
@@ -309,6 +309,7 @@ async function main() {
309
309
  targetDir: args.target ?? process.cwd(),
310
310
  templatesDir: resolve(PKG_ROOT, "templates"),
311
311
  version: readPackageVersion(),
312
+ versions: readVersionMap(),
312
313
  });
313
314
  process.stdout.write(formatUpdateReport(result));
314
315
  }
@@ -328,6 +329,8 @@ async function main() {
328
329
  if (parsed.needsShapePrompt && !parsed.help && !parsed.version) {
329
330
  assertReleased("designs", [parsed.design]);
330
331
  assertReleased("modules", parsed.modules ?? []);
332
+ // #6484 — and a keyless run, which is the Free level the scope defers.
333
+ assertKeyedOrFreeReleased(parsed.license);
331
334
  }
332
335
  const opts = await resolveCliShape(parsed, {
333
336
  input: process.stdin,
@@ -433,10 +436,12 @@ async function main() {
433
436
  // rejection (caught at top level below). The network invariant (#6759 D6):
434
437
  // no key → no request at all; a key with no --modules → the D4 level probe
435
438
  // (3-4 requests); an explicit --modules list → requests only for the paid
436
- // modules it names, exactly as before this card. `--template
437
- // marketing-site-free` still rides the no-key case (record D11): its
438
- // `requires` is all-free, so it installs from the shipped
439
- // `site-templates/` tree with no key and no request.
439
+ // modules it names, exactly as before this card. A keyless run — `--template
440
+ // marketing-site-free` included, whose all-free `requires` once rode the
441
+ // no-key case (record D11) — is refused by the licence gate inside
442
+ // scaffold() (#6484, REL-034.1: Free is a deferred level,
443
+ // `release-scope.json`), after its scope-name refusals and before its first
444
+ // write, naming the pricing page. With a key, every branch is as before.
440
445
  const { targetDir: targetAbs, surfaces, starter, modules: effectiveModules, droppedModules, hubOrigin, hubSignInOrigin, } = await scaffold(toScaffoldOptions(opts));
441
446
  const isSpoke = opts.topology === "spoke";
442
447
  // The starter scaffold() resolved — from --template, or from --shape (#6754 D4).
@@ -491,7 +496,7 @@ async function main() {
491
496
  " AILK_HUB_CLIENT_SECRET # issued by the hub; never written here",
492
497
  "",
493
498
  "On the hub, issue the client id and secret with:",
494
- " pnpm --filter @working-theory/api spokes sign-in-client --id <spoke_id> --redirect-uri <this site's origin>/api/hub-session/callback",
499
+ " pnpm --filter @working-theory/app-api spokes sign-in-client --id <spoke_id> --redirect-uri <this site's origin>/api/hub-session/callback",
495
500
  ]
496
501
  : []),
497
502
  ]
@@ -500,7 +505,7 @@ async function main() {
500
505
  ];
501
506
  // Prerequisites (#6440 AC4) — every one the scaffold enforces, and nothing
502
507
  // it does not. A starter reaches `pnpm dev` AND `pnpm build` on a toolchain
503
- // alone: the Prisma client is generated by `database`'s own `postinstall`,
508
+ // alone: the Prisma client ships prebuilt in `@working-theory/database`,
504
509
  // so there is no generator step to remember, and no database or vendor API
505
510
  // key gates either command (a free install also says no licence key does;
506
511
  // a licensed one, #6480, does not). Saying so is the point — the previous
@@ -14,7 +14,7 @@
14
14
  * fixed document shape this module produces — no `yaml`/`js-yaml` dependency.
15
15
  */
16
16
  import { type ForbiddenPattern } from "./module-architecture.js";
17
- import type { Topology } from "./topology.js";
17
+ import { type Topology } from "./topology.js";
18
18
  /** The topology a document is derived for (#7426 D8). */
19
19
  export interface DeriveArchitectureOptions {
20
20
  /** `"hub"` (the default) or `"spoke"`. */
@@ -51,9 +51,8 @@ export declare const SPOKE_MCP_FORBIDDEN_PATTERNS: readonly ForbiddenPattern[];
51
51
  * modules gets exactly what the modules imply.
52
52
  * @param options the topology (#7426 D8). Absent or `"hub"` ⟹ the output is
53
53
  * byte-identical to the two-argument form. `"spoke"` ⟹ only the spoke's own
54
- * apps (`web`, and `mcp` unless `mcp: false`), no `namespaces`, no
55
- * `database` root, a top-level `topology: spoke` and the hub-facing
56
- * composition tiers.
54
+ * apps (`web`, and `mcp` unless `mcp: false`), no `database` root, a
55
+ * top-level `topology: spoke` and the hub-facing composition tiers.
57
56
  * @returns the complete `architecture.yaml` file content (a deterministic
58
57
  * function of the module SET, the surface SET and the topology).
59
58
  * @throws Error on an unrecognized module (defensive; parse-args rejects first).