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
@@ -14,7 +14,19 @@
14
14
  * fixed document shape this module produces — no `yaml`/`js-yaml` dependency.
15
15
  */
16
16
  import { ARCHITECTURE_BASE, MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
17
- import { CORE_SURFACE_PATHS, RECOGNIZED_SURFACES, resolveSurfaces, } from "./surfaces.js";
17
+ import { MODULE_FLAGS_PATH, PAID_MCP_TOOLS_PATH, PAID_SECTIONS_PATH } from "./paid-sections.js";
18
+ import { SITE_CHROME_PATH } from "./site-chrome.js";
19
+ import { SITE_FONTS_PATH } from "./site-fonts.js";
20
+ import { SPOKE_CHECKOUT_CONFIG_PATH, SPOKE_CHECKOUT_TEMPLATE_PATHS, } from "./spoke-checkout.js";
21
+ import { CORE_SURFACE_PATHS, NAV_CONFIG_PATH, RECOGNIZED_SURFACES, resolveSurfaces, } from "./surfaces.js";
22
+ import { SPOKE_SEAM_FILES } from "./topology.js";
23
+ /** The npm scope a site consumes and never forks (#9191). */
24
+ const PACKAGE_SCOPE = "@working-theory/";
25
+ /** Apps whose `package.json` name is not `@working-theory/<dir>`, because the published package took it (#9564, #9570). */
26
+ const SHELL_PACKAGE_NAME = {
27
+ api: "app-api",
28
+ admin: "admin-shell",
29
+ };
18
30
  /** A spoke's composition tiers (#7426 D8): its data and API are the hub's. */
19
31
  const SPOKE_TIERS = {
20
32
  data: "none — the hub's database",
@@ -207,18 +219,6 @@ function appToYaml(app) {
207
219
  }
208
220
  return m;
209
221
  }
210
- function namespacesToYaml(ns) {
211
- const members = {};
212
- const sortedMembers = Object.entries(ns.members).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
213
- for (const [key, mem] of sortedMembers) {
214
- members[key] = { path: mem.path, description: mem.description };
215
- }
216
- return {
217
- description: ns.description,
218
- members,
219
- rules: [...ns.rules],
220
- };
221
- }
222
222
  /**
223
223
  * Derive the `architecture.yaml` document for a module set.
224
224
  *
@@ -229,9 +229,8 @@ function namespacesToYaml(ns) {
229
229
  * modules gets exactly what the modules imply.
230
230
  * @param options the topology (#7426 D8). Absent or `"hub"` ⟹ the output is
231
231
  * byte-identical to the two-argument form. `"spoke"` ⟹ only the spoke's own
232
- * apps (`web`, and `mcp` unless `mcp: false`), no `namespaces`, no
233
- * `database` root, a top-level `topology: spoke` and the hub-facing
234
- * composition tiers.
232
+ * apps (`web`, and `mcp` unless `mcp: false`), no `database` root, a
233
+ * top-level `topology: spoke` and the hub-facing composition tiers.
235
234
  * @returns the complete `architecture.yaml` file content (a deterministic
236
235
  * function of the module SET, the surface SET and the topology).
237
236
  * @throws Error on an unrecognized module (defensive; parse-args rejects first).
@@ -304,16 +303,69 @@ export function deriveArchitecture(modules = ["marketing"], surfaces, options =
304
303
  forbidden_patterns: mergeForbidden([...ARCHITECTURE_BASE.appForbiddenPatterns], [...(a.forbidden_patterns ?? []), ...extra]).map(scoped),
305
304
  });
306
305
  }
307
- // namespaces — present only if a data-tier module contributes one, and
308
- // never on a spoke, which has no database/ of its own.
309
- const nsSlice = spoke
310
- ? undefined
311
- : slices.find((s) => s.namespaces)?.namespaces;
306
+ // No `namespaces` block (#9569): a site's `database/` holds no schema — the
307
+ // namespace boundaries belong to `@working-theory/database`'s own source and
308
+ // this monorepo's lint, and a rule naming `database/<ns>` paths a scaffold
309
+ // lacks is what #6940 refuses.
312
310
  // forbidden_patterns — base floor first, then the selected modules' patterns.
313
311
  const extraForbidden = [];
314
312
  for (const s of slices)
315
313
  extraForbidden.push(...(s.forbiddenPatterns ?? []));
316
314
  const forbidden = mergeForbidden([...ARCHITECTURE_BASE.forbiddenPatterns], extraForbidden).map(scoped);
315
+ // The upgradeable-consumer rules (#9191): the workspaces this scaffold
316
+ // creates and the in-scope package names it gives them. The site lint
317
+ // reads this block to refuse a forked, patched or pinned-off package.
318
+ // A hub's `database/` is a plain folder, not a workspace (#9569): the
319
+ // package is an npm dependency the same-caret rule covers like any other.
320
+ const upgradeableConsumer = {
321
+ package_scope: PACKAGE_SCOPE,
322
+ workspaces: ["apps/*"],
323
+ // Every app the scaffold ships is named `@working-theory/<dir>`, except
324
+ // the two whose published package took the name: `@working-theory/api` is
325
+ // what the API app boots from (#9564), so the app is
326
+ // `@working-theory/app-api`; `@working-theory/admin` is what the Admin
327
+ // shell boots from (#9570), so the app is `@working-theory/admin-shell`.
328
+ scaffold_packages: Object.keys(apps)
329
+ .map((dir) => `${PACKAGE_SCOPE}${SHELL_PACKAGE_NAME[dir] ?? dir}`)
330
+ .sort(),
331
+ };
332
+ // The customizations manifest (#9223): the files under `apps/` the template
333
+ // record (`.ailk-template-files.json`) cannot see, so the site lint can tell
334
+ // a site-authored file from a scaffolded one by membership alone. (a) The
335
+ // generator outputs, on a hub and a spoke alike — an exempted path that is
336
+ // absent exempts nothing, and only a create-ailk generator writes each. The
337
+ // constants are composed here, never at module top level: `spoke-checkout`
338
+ // imports this module back, and `template-record`'s own list is deliberately
339
+ // not imported (it reads `spoke-checkout` at top level). (b) Each selected
340
+ // module's bundle-delivered and patched app files, scoped to the apps this
341
+ // derivation declares. (c) A commerce spoke's checkout slice, which
342
+ // `add-module` writes with no record row.
343
+ const generatorPaths = [
344
+ NAV_CONFIG_PATH,
345
+ SITE_CHROME_PATH,
346
+ SITE_FONTS_PATH,
347
+ PAID_SECTIONS_PATH,
348
+ MODULE_FLAGS_PATH,
349
+ PAID_MCP_TOOLS_PATH,
350
+ ...SPOKE_SEAM_FILES,
351
+ SPOKE_CHECKOUT_CONFIG_PATH,
352
+ SPOKE_BILLING_ACTION_PATH,
353
+ ];
354
+ const modulePaths = [];
355
+ for (const s of slices) {
356
+ modulePaths.push(...(s.ownedFiles ?? []));
357
+ modulePaths.push(...Object.values(s.installMap ?? {}));
358
+ if (s.installRoot)
359
+ modulePaths.push(`${s.installRoot.replace(/\/$/, "")}/**`);
360
+ modulePaths.push(...(s.patches ?? []).map((p) => p.target));
361
+ }
362
+ const checkoutPaths = spoke && selected.includes("commerce")
363
+ ? SPOKE_CHECKOUT_TEMPLATE_PATHS.map((p) => (/\.[^/]+$/.test(p) ? p : `${p}/**`))
364
+ : [];
365
+ const customizations = {
366
+ manifest: "customizations.yaml",
367
+ scaffold_paths: sortedUnion(generatorPaths, [...modulePaths, ...checkoutPaths].filter((p) => p.startsWith("apps/") && inScaffold(p))),
368
+ };
317
369
  const doc = {
318
370
  version: ARCHITECTURE_BASE.version,
319
371
  ...(spoke ? { topology: "spoke" } : {}),
@@ -328,8 +380,9 @@ export function deriveArchitecture(modules = ["marketing"], surfaces, options =
328
380
  available: [...RECOGNIZED_SURFACES],
329
381
  },
330
382
  apps,
331
- ...(nsSlice ? { namespaces: namespacesToYaml(nsSlice) } : {}),
332
383
  forbidden_patterns: forbidden.map(forbiddenToYaml),
384
+ upgradeable_consumer: upgradeableConsumer,
385
+ customizations,
333
386
  };
334
387
  const header = [
335
388
  "# Architecture Boundaries — AI Launch Kit site",
@@ -79,13 +79,18 @@ export interface MeasureApplyDesignDriftOptions {
79
79
  workDir: string;
80
80
  /** The loopback registry the CLI resolves modules and templates from. */
81
81
  registryUrl?: string;
82
- /** Written to the site's own `ailk.key`, which `apply-design` gates a non-Free design on. */
82
+ /**
83
+ * Scaffolds with `--license <key>` (#9650: a keyless run refuses while Free
84
+ * is held), which writes the site's own `ailk.key` — what `apply-design`
85
+ * gates a non-Free design on.
86
+ */
83
87
  licenseKey?: string;
84
88
  }
85
89
  /**
86
- * Scaffold a keyless `organization-product` site on `standard`, compose its
87
- * JSON-LD, run `apply-design <design>` on it, and compose again. A non-zero
88
- * exit at any step throws naming the step and the child's stderr.
90
+ * Scaffold an `organization-product` site on `standard` — keyed when
91
+ * `licenseKey` is given — compose its JSON-LD, run `apply-design <design>` on
92
+ * it, and compose again. A non-zero exit at any step throws naming the step
93
+ * and the child's stderr.
89
94
  */
90
95
  export declare function measureApplyDesignDrift(opts: MeasureApplyDesignDriftOptions): {
91
96
  before: ComposedPages;
@@ -25,7 +25,6 @@
25
25
  * (#8661 D11); `admitSeededContactPage` admits only those two fields.
26
26
  */
27
27
  import { execFileSync } from "node:child_process";
28
- import { writeFileSync } from "node:fs";
29
28
  import { join } from "node:path";
30
29
  import { isDeepStrictEqual } from "node:util";
31
30
  import { CONTACT_PAGE_PATH } from "../design-home.js";
@@ -189,9 +188,10 @@ export function assessJsonLdDrift(design, before, after) {
189
188
  };
190
189
  }
191
190
  /**
192
- * Scaffold a keyless `organization-product` site on `standard`, compose its
193
- * JSON-LD, run `apply-design <design>` on it, and compose again. A non-zero
194
- * exit at any step throws naming the step and the child's stderr.
191
+ * Scaffold an `organization-product` site on `standard` — keyed when
192
+ * `licenseKey` is given — compose its JSON-LD, run `apply-design <design>` on
193
+ * it, and compose again. A non-zero exit at any step throws naming the step
194
+ * and the child's stderr.
195
195
  */
196
196
  export function measureApplyDesignDrift(opts) {
197
197
  const baseEnv = { ...process.env };
@@ -223,9 +223,15 @@ export function measureApplyDesignDrift(opts) {
223
223
  throw new Error(`drift: ${label} printed no JSON: ${err.message}`, { cause: err });
224
224
  }
225
225
  };
226
- exec("scaffold organization-product on standard", process.execPath, [opts.cliPath, site, "--shape", "organization-product", "--design", "standard"], registryEnv);
227
- if (opts.licenseKey !== undefined)
228
- writeFileSync(join(site, "ailk.key"), `${opts.licenseKey}\n`);
226
+ exec("scaffold organization-product on standard", process.execPath, [
227
+ opts.cliPath,
228
+ site,
229
+ "--shape",
230
+ "organization-product",
231
+ "--design",
232
+ "standard",
233
+ ...(opts.licenseKey === undefined ? [] : ["--license", opts.licenseKey]),
234
+ ], registryEnv);
229
235
  const before = compose("compose JSON-LD before apply-design");
230
236
  const applyStdout = exec(`apply-design ${opts.design}`, process.execPath, [opts.cliPath, "apply-design", opts.design, "--target", site], opts.registryUrl === undefined ? {} : { AILK_MODULE_REGISTRY_URL: opts.registryUrl });
231
237
  const after = compose("compose JSON-LD after apply-design");
@@ -23,8 +23,8 @@
23
23
  * `extractBundle` extracts into an EMPTY staging dir that then swap-renames
24
24
  * over the (possibly pre-existing) install target — appropriate for a single
25
25
  * self-contained skill directory. A fetched module's files are scattered
26
- * across an ALREADY-SCAFFOLDED tree (`apps/api/src/routes/...`,
27
- * `apps/web/app/...`), so there is no single directory to rename over.
26
+ * across an ALREADY-SCAFFOLDED tree (`apps/web/app/...`,
27
+ * `apps/web/lib/...`), so there is no single directory to rename over.
28
28
  * `extractModuleBundle` therefore extracts into a throwaway temp dir first
29
29
  * (same validation, same guards), and ONLY on full success copies each
30
30
  * validated file into its place under `targetDir` — so a rejected or
@@ -386,6 +386,26 @@ function validateLayerOwnership(destinations, ownership, subject, isTemplate, pa
386
386
  }
387
387
  }
388
388
  /** Every regular file under `srcRoot`, as a `/`-separated relative path. */
389
+ const API_SOURCE_ROOT = "apps/api/";
390
+ /**
391
+ * #9565 D6 — refuse a tree that would write under `apps/api/`, naming the
392
+ * path. Checked BEFORE any write, beside `validateInstallMap` and
393
+ * `validatePatches`.
394
+ */
395
+ function refuseApiSource(sourceRoot, installMap, patches, subject) {
396
+ const toPosixRel = (p) => normalize(p).split(sep).join("/").replace(/^\.\//, "");
397
+ // Compared lower-cased: on a case-insensitive filesystem `Apps/API/...` lands
398
+ // in the same tree.
399
+ const underApi = (rel) => rel.toLowerCase().startsWith(API_SOURCE_ROOT);
400
+ const offenders = [
401
+ ...stagedFiles(sourceRoot).filter(underApi),
402
+ ...Object.values(installMap).map(toPosixRel).filter(underApi),
403
+ ...patches.map((patch) => toPosixRel(patch.target)).filter(underApi),
404
+ ];
405
+ if (offenders.length > 0) {
406
+ throw new Error(`${subject}: refuses to write ${offenders[0]} — API source ships in its @working-theory/api-<module> package, never in a bundle (#9565)`);
407
+ }
408
+ }
389
409
  function stagedFiles(srcRoot) {
390
410
  const out = [];
391
411
  const stack = [srcRoot];
@@ -545,6 +565,13 @@ export function installBundleTree(options) {
545
565
  // Every declared patch is validated, skipped or not (#7426 D4), exactly as
546
566
  // the installMap is above; only then are the skipped ones dropped.
547
567
  validatePatches(declaredPatches, targetAbs, subject);
568
+ // #9565 D6 — no bundle writes under apps/api/: a module's API source is its
569
+ // `@working-theory/api-<module>` package, installed from npm, never a copy
570
+ // in the site's tree. A staged file, a (remapped) installMap destination or
571
+ // a patch target under apps/api/ refuses the whole tree at this same
572
+ // fail-closed point, for module and template trees alike — which is what
573
+ // holds for a bundle built before this change and still at the store.
574
+ refuseApiSource(sourceRoot, remappedInstallMap, declaredPatches, subject);
548
575
  const patches = declaredPatches.filter((patch) => !isSkipped(patch.target));
549
576
  options.checkPatches?.(patches);
550
577
  // The exclusion set copyTree/the content-only guard both use — built from
@@ -12,7 +12,7 @@ export interface FetchTemplateSnapshotOptions {
12
12
  }
13
13
  /**
14
14
  * Fetch and re-materialise create-ailk `version`'s `templates/apps/{web,api,mcp}/`
15
- * tree from its published npm tarball.
15
+ * tree, plus its `templates/database/` boot files, from its published npm tarball.
16
16
  *
17
17
  * @throws FetchTemplateSnapshotError on an invalid version, an unreachable
18
18
  * or malformed registry response, an integrity mismatch, or a symlink /
@@ -21,6 +21,7 @@ import { createHash } from "node:crypto";
21
21
  import { gunzipSync } from "node:zlib";
22
22
  import * as tar from "tar";
23
23
  import { templateDestination } from "../copy.js";
24
+ import { DATABASE_BOOT_FILES } from "../template-record.js";
24
25
  import { MAX_TOTAL_SIZE_BYTES } from "./extract-module-bundle.js";
25
26
  import { assertContentLengthWithinLimit, assertHttpsRegistryUrl, fetchTimeoutSignal, } from "./fetch-guard.js";
26
27
  export const DEFAULT_AILK_NPM_REGISTRY_URL = "https://registry.npmjs.org";
@@ -29,6 +30,8 @@ const VERSION_PATTERN = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;
29
30
  /** The one tar path prefix a snapshot is read from, and the three app roots inside it. */
30
31
  const TAR_ROOT = "package/templates/";
31
32
  const APP_PREFIXES = ["apps/web/", "apps/api/", "apps/mcp/"];
33
+ /** The paths outside the app roots a snapshot keeps: a hub's three database boot files (#9569 DD8). */
34
+ const BOOT_FILES = new Set(DATABASE_BOOT_FILES);
32
35
  export class FetchTemplateSnapshotError extends Error {
33
36
  constructor(message) {
34
37
  super(message);
@@ -110,13 +113,14 @@ async function fetchTarball(tarballUrl, integrity, version, fetchImpl) {
110
113
  }
111
114
  return buf;
112
115
  }
113
- /** The app-relative path (no `package/templates/` prefix) for a tar entry path, or undefined outside the three app trees. */
116
+ /** The template-relative path (no `package/templates/` prefix) for a tar entry path, or undefined outside the three app trees and the database boot files. */
114
117
  function appRelativePath(tarPath) {
115
118
  if (!tarPath.startsWith(TAR_ROOT))
116
119
  return undefined;
117
120
  const rel = tarPath.slice(TAR_ROOT.length);
118
- if (!APP_PREFIXES.some((prefix) => rel.startsWith(prefix)))
121
+ if (!APP_PREFIXES.some((prefix) => rel.startsWith(prefix)) && !BOOT_FILES.has(rel)) {
119
122
  return undefined;
123
+ }
120
124
  if (rel.length === 0)
121
125
  return undefined;
122
126
  const segments = rel.split("/");
@@ -176,7 +180,7 @@ function parseSnapshot(gunzipped, version) {
176
180
  }
177
181
  /**
178
182
  * Fetch and re-materialise create-ailk `version`'s `templates/apps/{web,api,mcp}/`
179
- * tree from its published npm tarball.
183
+ * tree, plus its `templates/database/` boot files, from its published npm tarball.
180
184
  *
181
185
  * @throws FetchTemplateSnapshotError on an invalid version, an unreachable
182
186
  * or malformed registry response, an integrity mismatch, or a symlink /
@@ -16,7 +16,7 @@ export declare function resolveRelativeImport(fromFile: string, spec: string, ca
16
16
  * This is the shape both consumers need, and the reason the walk is shared
17
17
  * rather than copied. `paidModuleTemplateExclusions()` seeds it with every
18
18
  * paid module's `ownedFiles` to get the files a keyless starter must not
19
- * carry; `tools/lint-slice-registration.ts` seeds it with the same set to
19
+ * carry; the retired slice-registration lint seeded it with the same set to
20
20
  * derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
21
21
  *
22
22
  * Never a filename-stem rule (#5182 D7), which misses eleven files and
@@ -8,9 +8,9 @@
8
8
  * - `paidModuleTemplateExclusions()` (module-architecture.ts) walks it to take
9
9
  * the companion closure of every paid module's `ownedFiles` — the files that
10
10
  * would ship dangling into a keyless starter.
11
- * - `tools/lint-slice-registration.ts` walks it to close over the specifiers an
12
- * `isModuleEnabled("X")` branch in `apps/api/src/server.ts` loads, and to
13
- * check every reached file against what module X's slice delivers.
11
+ * - the slice-registration lint walked it (#5701, retired by #9565 D8 once
12
+ * no bundle delivered an API file) to close over the specifiers a module
13
+ * gate loaded and check each against what the slice delivered.
14
14
  *
15
15
  * Both questions are "which files does this one reach through relative
16
16
  * imports", and the answer must be the same function in both mouths: a lint
@@ -105,7 +105,7 @@ function posixJoin(dir, spec) {
105
105
  * This is the shape both consumers need, and the reason the walk is shared
106
106
  * rather than copied. `paidModuleTemplateExclusions()` seeds it with every
107
107
  * paid module's `ownedFiles` to get the files a keyless starter must not
108
- * carry; `tools/lint-slice-registration.ts` seeds it with the same set to
108
+ * carry; the retired slice-registration lint seeded it with the same set to
109
109
  * derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
110
110
  *
111
111
  * Never a filename-stem rule (#5182 D7), which misses eleven files and
@@ -17,7 +17,7 @@ export declare class LicenseRequiredError extends Error {
17
17
  }
18
18
  /** The five axes `release-scope.json` declares (spec 6977 D3). */
19
19
  export type ReleaseAxis = "templates" | "shapes" | "designs" | "modules" | "levels";
20
- /** `gated` and `deferred` are both refused; only a `gated` one gets negative checks. */
20
+ /** `gated` and `deferred` are both refused; only a `gated` one gets negative checks (the Free level excepted, #6484). */
21
21
  export type ReleaseStatus = "released" | "gated" | "deferred";
22
22
  export type ReleaseScope = Readonly<Record<ReleaseAxis, Readonly<Record<string, ReleaseStatus>>>>;
23
23
  /**
@@ -44,6 +44,17 @@ export declare class ReleaseScopeError extends Error {
44
44
  * gated module.
45
45
  */
46
46
  export declare function assertReleased(axis: ReleaseAxis, names: readonly (string | undefined)[], scope?: ReleaseScope): void;
47
+ /**
48
+ * A run with no key is a Free run, and `release-scope.json` says whether Free
49
+ * is available (#6484, REL-034.1: deferred — held). Refused before any prompt,
50
+ * fetch or write, with the level gate's message naming the pricing page; zero
51
+ * network. A keyed run passes through untouched — its level is the registry's
52
+ * answer (`deriveLevel`), never decided here. Called by `cli.ts` ahead of the
53
+ * shape prompt, and by `resolvePaidModules` for an all-Free request — the
54
+ * seam every `scaffold()` branch crosses (alias, keep and default alike),
55
+ * after the scope-name refusals and before the first write.
56
+ */
57
+ export declare function assertKeyedOrFreeReleased(licenseKey?: string | undefined): void;
47
58
  /**
48
59
  * Design names every level renders (#6760 D1). Anything else in
49
60
  * `STARTER_DESIGNS` is Pro and up. A path design's Free-ness is decided by
@@ -12,10 +12,11 @@
12
12
  * (c) a valid key → every requested paid module's bundle bytes, ready for
13
13
  * `extract-module-bundle.ts` to merge into the scaffold.
14
14
  *
15
- * A Free-only request (no paid modules) never reaches the key check at all —
16
- * `resolvePaidModules` returns immediately, before touching `process.env` or
17
- * the network, so a bare/all-Free scaffold is provably unaffected by this
18
- * gate (K1's regression floor).
15
+ * A Free-only request (no paid modules) never reaches the network — but since
16
+ * #6484 (REL-034.1) it does read the key: no key is the Free level, which
17
+ * `release-scope.json` defers, so `resolvePaidModules` refuses it through
18
+ * `assertKeyedOrFreeReleased` before returning its empty map. A keyed
19
+ * all-Free scaffold is unaffected (K1's regression floor, keyed).
19
20
  *
20
21
  * Also carries the design gate (#6760): `assertDesignAllowed` refuses a
21
22
  * non-`standard` design at the `free` level, naming the design and the
@@ -107,14 +108,32 @@ export function assertReleased(axis, names, scope = RELEASE_SCOPE) {
107
108
  continue;
108
109
  const released = Object.keys(statuses).filter((n) => statuses[n] === "released");
109
110
  // A level comes from the key, never a flag — so it points at what the run CAN choose.
110
- const choose = axis === "levels"
111
- ? `Your licence key's level is ${name}; name the modules you want with --modules (one of: ${Object.keys(scope.modules)
112
- .filter((m) => scope.modules[m] === "released")
113
- .join(", ")}).`
114
- : `Choose one of: ${released.join(", ")}.`;
111
+ // `free` is the keyless level (#6484): it points at the pricing page.
112
+ const choose = axis === "levels" && name === "free"
113
+ ? `No licence key, so this would be a Free scaffold — pass --license <key> or set AILK_LICENSE_KEY with a Pro key → ${CONVERSION_HINT_URL}`
114
+ : axis === "levels"
115
+ ? `Your licence key's level is ${name}; name the modules you want with --modules (one of: ${Object.keys(scope.modules)
116
+ .filter((m) => scope.modules[m] === "released")
117
+ .join(", ")}).`
118
+ : `Choose one of: ${released.join(", ")}.`;
115
119
  throw new ReleaseScopeError(`${AXIS_NOUN[axis]} "${name}" is not available yet. ${choose}`);
116
120
  }
117
121
  }
122
+ /**
123
+ * A run with no key is a Free run, and `release-scope.json` says whether Free
124
+ * is available (#6484, REL-034.1: deferred — held). Refused before any prompt,
125
+ * fetch or write, with the level gate's message naming the pricing page; zero
126
+ * network. A keyed run passes through untouched — its level is the registry's
127
+ * answer (`deriveLevel`), never decided here. Called by `cli.ts` ahead of the
128
+ * shape prompt, and by `resolvePaidModules` for an all-Free request — the
129
+ * seam every `scaffold()` branch crosses (alias, keep and default alike),
130
+ * after the scope-name refusals and before the first write.
131
+ */
132
+ export function assertKeyedOrFreeReleased(licenseKey = process.env["AILK_LICENSE_KEY"]) {
133
+ if (licenseKey === undefined || licenseKey.length === 0) {
134
+ assertReleased("levels", ["free"]);
135
+ }
136
+ }
118
137
  /**
119
138
  * Design names every level renders (#6760 D1). Anything else in
120
139
  * `STARTER_DESIGNS` is Pro and up. A path design's Free-ness is decided by
@@ -182,12 +201,15 @@ function licenseErrorMessage(err, moduleName, templateName, level) {
182
201
  */
183
202
  export async function resolvePaidModules(options) {
184
203
  const { paidModules } = options;
204
+ const token = options.licenseKey ?? process.env["AILK_LICENSE_KEY"];
185
205
  if (paidModules.length === 0) {
186
- // Regression floor: zero key reads, zero network, for any request that
187
- // names no paid module.
206
+ // Zero network for any request that names no paid module — but no
207
+ // longer zero key reads (#6484): a keyless all-Free request is the Free
208
+ // level, which `release-scope.json` holds, and is refused here, after
209
+ // `scaffold()`'s scope-name refusals and before its first write.
210
+ assertKeyedOrFreeReleased(token);
188
211
  return new Map();
189
212
  }
190
- const token = options.licenseKey ?? process.env["AILK_LICENSE_KEY"];
191
213
  if (token === undefined || token.length === 0) {
192
214
  throw new LicenseRequiredError(noKeyMessage(paidModules, options.templateName));
193
215
  }
@@ -21,6 +21,39 @@ export declare const MAX_REDIRECTS = 5;
21
21
  * so each entry must answer exactly 404. A 200 means the gate stopped gating.
22
22
  */
23
23
  export declare const CLAIM_GATED_ROUTES: Readonly<Record<string, string>>;
24
+ /**
25
+ * Routes whose answer depends on whether the site has a hub to ask (#9423),
26
+ * and the flow each one sells. With no API origin configured the flow read
27
+ * is `not-configured` and the route must answer exactly 404 — the no-hub
28
+ * 404 where the module that owns it is installed, Next's own 404 where it
29
+ * is not. With one configured it must render its own content.
30
+ */
31
+ export declare const HUB_GATED_ROUTES: Readonly<Record<string, string>>;
32
+ /**
33
+ * The API origin names `apps/web` reads, in step with `apiOriginConfigured()`
34
+ * in `apps/web/app/[locale]/flows/[slug]/magnet-page.tsx`.
35
+ */
36
+ export declare const HUB_ORIGIN_ENV_NAMES: readonly ["AILK_API_URL", "NEXT_PUBLIC_AILK_API_URL", "NEXT_PUBLIC_API_URL"];
37
+ /**
38
+ * Whether a served `apps/web` has an API origin: a non-empty value for one
39
+ * of `HUB_ORIGIN_ENV_NAMES` in the serve environment or assigned in one of
40
+ * the env files Next loads (`envFileTexts`).
41
+ */
42
+ export declare function hubOriginConfigured(env: Readonly<Record<string, string | undefined>>, envFileTexts: string[]): boolean;
43
+ /**
44
+ * A `HUB_GATED_ROUTES` entry. Hub configured: the page must render its own
45
+ * content (`assessPageRender`). No hub: exactly 404 with no redirect — a 200
46
+ * means the no-hub branch stopped running.
47
+ */
48
+ export declare function assessHubGatedRoute(input: {
49
+ route: string;
50
+ hubConfigured: boolean;
51
+ hops: RedirectHop[];
52
+ status: number | null;
53
+ contentType: string | null;
54
+ html: string;
55
+ locale: string;
56
+ }): SweepVerdict;
24
57
  /**
25
58
  * A route whose live page needs an env var the driver never sets (#6146).
26
59
  * While it is unset the route serves its Free placeholder seed instead
@@ -37,6 +37,51 @@ export const CLAIM_GATED_ROUTES = {
37
37
  "/purchase/success": "commerce",
38
38
  "/purchase/cancel": "commerce",
39
39
  };
40
+ /**
41
+ * Routes whose answer depends on whether the site has a hub to ask (#9423),
42
+ * and the flow each one sells. With no API origin configured the flow read
43
+ * is `not-configured` and the route must answer exactly 404 — the no-hub
44
+ * 404 where the module that owns it is installed, Next's own 404 where it
45
+ * is not. With one configured it must render its own content.
46
+ */
47
+ export const HUB_GATED_ROUTES = {
48
+ "/trial": "trial",
49
+ };
50
+ /**
51
+ * The API origin names `apps/web` reads, in step with `apiOriginConfigured()`
52
+ * in `apps/web/app/[locale]/flows/[slug]/magnet-page.tsx`.
53
+ */
54
+ export const HUB_ORIGIN_ENV_NAMES = ["AILK_API_URL", "NEXT_PUBLIC_AILK_API_URL", "NEXT_PUBLIC_API_URL"];
55
+ /**
56
+ * Whether a served `apps/web` has an API origin: a non-empty value for one
57
+ * of `HUB_ORIGIN_ENV_NAMES` in the serve environment or assigned in one of
58
+ * the env files Next loads (`envFileTexts`).
59
+ */
60
+ export function hubOriginConfigured(env, envFileTexts) {
61
+ if (HUB_ORIGIN_ENV_NAMES.some((name) => Boolean(env[name])))
62
+ return true;
63
+ return envFileTexts.some((text) => HUB_ORIGIN_ENV_NAMES.some((name) => new RegExp(`^\\s*(?:export\\s+)?${name}\\s*=\\s*["']?[^\\s"'#]`, "m").test(text)));
64
+ }
65
+ /**
66
+ * A `HUB_GATED_ROUTES` entry. Hub configured: the page must render its own
67
+ * content (`assessPageRender`). No hub: exactly 404 with no redirect — a 200
68
+ * means the no-hub branch stopped running.
69
+ */
70
+ export function assessHubGatedRoute(input) {
71
+ const { route, hubConfigured, hops, status, contentType, html, locale } = input;
72
+ const flow = HUB_GATED_ROUTES[route];
73
+ if (hubConfigured) {
74
+ const rendered = assessPageRender({ route, hops, status, contentType, html, locale });
75
+ return { ok: rendered.ok, reason: `${rendered.reason} (hub-gated: ${flow}, hub configured)` };
76
+ }
77
+ if (hops.length > 0 || status !== 404) {
78
+ const first = hops[0];
79
+ const seen = first ? `${first.status} redirect` : `status ${status}`;
80
+ const why = status === 200 ? "rendered with no hub to ask" : `expected 404, got ${seen}`;
81
+ return { ok: false, reason: `${route} -> ${why} (hub-gated: ${flow}, no hub)` };
82
+ }
83
+ return { ok: true, reason: `404 (hub-gated: ${flow}, no hub)` };
84
+ }
40
85
  /**
41
86
  * A route whose live page needs an env var the driver never sets (#6146).
42
87
  * While it is unset the route serves its Free placeholder seed instead
@@ -100,6 +100,15 @@ export interface ModuleSlice {
100
100
  * otherwise. Only a module with a BASE-tree consumer sets it.
101
101
  */
102
102
  paidSectionsPackage?: string;
103
+ /**
104
+ * The paid MCP tool packages base code loads through
105
+ * `apps/mcp/src/lib/paid-tools.generated.ts` (#9460 DD6). Each is one row
106
+ * in the generated registry: a bundled `import()` when the scaffold's
107
+ * `apps/mcp/package.json` declares the package, absent otherwise. A
108
+ * package two modules deliver (`mcp-workspace`) is listed by each and
109
+ * rendered once.
110
+ */
111
+ paidMcpToolPackages?: string[];
103
112
  /** Packages this module adds to apps/web.may_import_from (its presentation surface). */
104
113
  webImports?: string[];
105
114
  /** Apps this module declares (api, mcp replace the base block; admin is new). web is BASE, never here. */
@@ -124,7 +133,7 @@ export interface ModuleSlice {
124
133
  * *scaffolded customer site's* `architecture.yaml` — "apps/web MAY import
125
134
  * packages/fumadocs-schema." `ownedFiles` instead names, one literal path at
126
135
  * a time, which files in *this* monorepo physically belong to the module —
127
- * "apps/api/src/routes/schedule/index.ts IS the scheduling module." A
136
+ * "packages-paid/api-scheduling/src/routes/schedule/index.ts IS the scheduling module." A
128
137
  * package can appear in one view and not the other: `packages/fumadocs-schema`
129
138
  * is a `webImports` entry (a permission — a docs scaffold installs it) but
130
139
  * NOT an `ownedFiles` entry (it is `oss`-tiered; the strip keeps it).
@@ -154,7 +163,7 @@ export interface ModuleSlice {
154
163
  * `RECOGNIZED_MODULES`, so adding a `content-write` key would make
155
164
  * `create-ailk --modules content-write` a valid scaffold selection. It is
156
165
  * not one — content-write is a licence-tier line drawn inside a single
157
- * app, never a customer opt-in (see `apps/api/src/config/modules.ts`).
166
+ * app, never a customer opt-in (see `packages/api/src/config/modules.ts`).
158
167
  * - Two are this-list-only and the manifest simply never recorded them:
159
168
  * `apps/web/app/[locale]/docs/[[...slug]]/page.tsx` and
160
169
  * `apps/web/app/[locale]/meet/confirmed/page.tsx`.
@@ -164,6 +173,14 @@ export interface ModuleSlice {
164
173
  * are derived from the import graph — a test or story file carries
165
174
  * `oss: false` iff it imports a slice file — never from filename stems,
166
175
  * which miss eleven and over-mark three.
176
+ *
177
+ * Since REL-034.4 (#9565 D6) no entry names an `apps/api/` path: a module's
178
+ * API source is its `@working-theory/api-<module>` package under
179
+ * `packages-paid/`, dropped from the public tree wholesale and reached by a
180
+ * keyed scaffold through npm, never through a bundle. The producer
181
+ * (`scripts/build-module-bundles.mjs` `stageModule`) refuses to stage, and
182
+ * the extractor (`lib/extract-module-bundle.ts` `installBundleTree`) refuses
183
+ * to install, any path under `apps/api/`.
167
184
  */
168
185
  ownedFiles?: string[];
169
186
  /**
@@ -349,7 +366,7 @@ export declare const ARCHITECTURE_BASE: {
349
366
  readonly version: 1;
350
367
  readonly composition_model: {
351
368
  readonly tiers: {
352
- readonly data: "database/ — Prisma schema + migrations";
369
+ readonly data: "database/ — Prisma config + seed; schema and migrations ship in @working-theory/database";
353
370
  readonly api: "apps/api (public HTTP API) + apps/mcp (agent tools)";
354
371
  readonly presentation: "apps/web — frontend surfaces";
355
372
  };