create-ailk 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (638) hide show
  1. package/README.md +53 -22
  2. package/component-catalog.json +3 -3
  3. package/component-catalog.md +3 -3
  4. package/dist/add-module.js +4 -2
  5. package/dist/add-route.d.ts +12 -1
  6. package/dist/add-route.js +31 -3
  7. package/dist/cli.js +12 -7
  8. package/dist/derive-architecture.d.ts +3 -4
  9. package/dist/derive-architecture.js +65 -29
  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 +2 -1
  14. package/dist/lib/fetch-template-snapshot.js +8 -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 +36 -15
  19. package/dist/lib/module-tier.d.ts +2 -8
  20. package/dist/lib/module-tier.js +13 -12
  21. package/dist/module-architecture.d.ts +20 -3
  22. package/dist/module-architecture.js +129 -552
  23. package/dist/paid-sections.d.ts +25 -1
  24. package/dist/paid-sections.js +88 -3
  25. package/dist/starter-grid.d.ts +6 -6
  26. package/dist/starter-grid.js +12 -5
  27. package/dist/surfaces.js +39 -2
  28. package/dist/template-record.d.ts +21 -3
  29. package/dist/template-record.js +38 -7
  30. package/dist/topology.d.ts +16 -3
  31. package/dist/topology.js +54 -23
  32. package/dist/update.d.ts +10 -1
  33. package/dist/update.js +715 -21
  34. package/package.json +3 -3
  35. package/release-scope.json +2 -2
  36. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +8 -2
  37. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +2 -2
  38. package/site-templates/marketing-site/ailk-template.json +7 -1
  39. package/site-templates/marketing-site/provenance.json +7 -1
  40. package/site-templates/saas-product/ailk-template.json +2 -1
  41. package/site-templates/saas-product/provenance.json +1 -0
  42. package/templates/.claude/cloudparity-repo-hooks.json +5 -0
  43. package/templates/.claude/hooks/template-guard.sh +137 -0
  44. package/templates/.claude/rules/extending.md +106 -0
  45. package/templates/.claude/rules/loop-contract.md +2 -2
  46. package/templates/.claude/settings.json +11 -0
  47. package/templates/.env.example +20 -5
  48. package/templates/.github/workflows/ci.yml +7 -4
  49. package/templates/CLAUDE.md +11 -1
  50. package/templates/CONVENTIONS.md +8 -10
  51. package/templates/README.md +14 -13
  52. package/templates/apps/api/.env.example +23 -2
  53. package/templates/apps/api/CLAUDE.md +119 -83
  54. package/templates/apps/api/jest.config.cjs +15 -5
  55. package/templates/apps/api/package.json +16 -20
  56. package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
  57. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
  58. package/templates/apps/api/src/index.ts +1 -1
  59. package/templates/apps/api/src/lib/__mocks__/prisma-client.js +16 -0
  60. package/templates/apps/api/src/lib/__mocks__/prisma.ts +3 -3
  61. package/templates/apps/api/src/modules/commerce.ts +10 -0
  62. package/templates/apps/api/src/modules/content-write.ts +10 -0
  63. package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
  64. package/templates/apps/api/src/modules/scheduling.ts +10 -0
  65. package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
  66. package/templates/apps/api/src/modules/workspace.ts +10 -0
  67. package/templates/apps/api/src/server.ts +117 -1882
  68. package/templates/apps/api/vercel.json +2 -2
  69. package/templates/apps/mcp/CLAUDE.md +90 -26
  70. package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
  71. package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
  72. package/templates/apps/mcp/jest.config.cjs +6 -1
  73. package/templates/apps/mcp/package.json +5 -13
  74. package/templates/apps/mcp/src/app.ts +8 -7
  75. package/templates/apps/mcp/src/index.ts +6 -34
  76. package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
  77. package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
  78. package/templates/apps/mcp/src/site.ts +12 -0
  79. package/templates/apps/web/.env.example +1 -1
  80. package/templates/apps/web/CLAUDE.md +31 -3
  81. package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
  82. package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +43 -4
  83. package/templates/apps/web/app/[locale]/(auth)/legal-footnote.tsx +35 -0
  84. package/templates/apps/web/app/[locale]/(auth)/sign-in/__tests__/page.test.tsx +117 -8
  85. package/templates/apps/web/app/[locale]/(auth)/sign-in/page.tsx +14 -37
  86. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +6 -6
  87. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-text.ts +20 -35
  88. package/templates/apps/web/app/[locale]/(auth)/sign-up/__tests__/page.test.tsx +108 -0
  89. package/templates/apps/web/app/[locale]/(auth)/sign-up/__tests__/sign-up-card.test.tsx +111 -5
  90. package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +78 -16
  91. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +132 -12
  92. package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +53 -1
  93. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/billing.test.tsx +38 -0
  94. package/templates/apps/web/app/[locale]/(authed)/account/billing/page.tsx +4 -2
  95. package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +47 -24
  96. package/templates/apps/web/app/[locale]/(authed)/signed-out-gate.generated.tsx +23 -4
  97. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
  98. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
  99. package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +7 -3
  100. package/templates/apps/web/app/[locale]/layout.tsx +33 -13
  101. package/templates/apps/web/app/[locale]/meet/confirmed/BookingHandOff.tsx +128 -0
  102. package/templates/apps/web/app/[locale]/meet/confirmed/__tests__/BookingHandOff.test.tsx +126 -0
  103. package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
  104. package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
  105. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
  106. package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
  107. package/templates/apps/web/app/api/revalidate/route.ts +3 -3
  108. package/templates/apps/web/auth.ts +10 -6
  109. package/templates/apps/web/i18n/request.ts +49 -1
  110. package/templates/apps/web/jest.config.cjs +1 -0
  111. package/templates/apps/web/lib/__tests__/account-config.test.ts +7 -0
  112. package/templates/apps/web/lib/__tests__/auth-email.test.ts +276 -0
  113. package/templates/apps/web/lib/auth-email.ts +103 -21
  114. package/templates/apps/web/lib/hub-session/__tests__/sign-in-gate.test.tsx +72 -23
  115. package/templates/apps/web/lib/hub-session/sign-in-gate.tsx +94 -70
  116. package/templates/apps/web/lib/prisma-for-auth.ts +5 -2
  117. package/templates/apps/web/lib/relay.ts +2 -2
  118. package/templates/apps/web/lib/release-scope.ts +47 -0
  119. package/templates/apps/web/lib/server-api.ts +1 -1
  120. package/templates/apps/web/lib/sign-up-agreements.ts +291 -28
  121. package/templates/apps/web/lib/site-contributions.ts +18 -0
  122. package/templates/apps/web/messages/en.json +186 -20
  123. package/templates/apps/web/messages/site/en.json +1 -0
  124. package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
  125. package/templates/customizations.yaml +37 -0
  126. package/templates/database/prisma.config.ts +10 -14
  127. package/templates/database/seed-test.ts +2 -2
  128. package/templates/database/seed.ts +5 -5
  129. package/templates/package.json +12 -6
  130. package/templates/pnpm-workspace.yaml +0 -1
  131. package/templates/project.yaml +16 -8
  132. package/templates/tools/jest/reporters.cjs +65 -0
  133. package/templates/tools/lint-architecture.ts +553 -7
  134. package/templates/tsconfig.json +1 -2
  135. package/versions.json +49 -36
  136. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
  137. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
  138. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
  139. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
  140. package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
  141. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
  142. package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
  143. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
  144. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
  145. package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
  146. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
  147. package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
  148. package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
  149. package/templates/apps/api/src/bin/spokes.ts +0 -198
  150. package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
  151. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
  152. package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
  153. package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
  154. package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
  155. package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
  156. package/templates/apps/api/src/config/index.ts +0 -596
  157. package/templates/apps/api/src/config/modules.ts +0 -83
  158. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
  159. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
  160. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
  161. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
  162. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
  163. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
  164. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
  165. package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
  166. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
  167. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
  168. package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
  169. package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
  170. package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
  171. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
  172. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
  173. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
  174. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
  175. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
  176. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
  177. package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -308
  178. package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
  179. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
  180. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
  181. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
  182. package/templates/apps/api/src/lib/agent-store.ts +0 -613
  183. package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
  184. package/templates/apps/api/src/lib/consent-store.ts +0 -363
  185. package/templates/apps/api/src/lib/content-adapter.ts +0 -112
  186. package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
  187. package/templates/apps/api/src/lib/error-serializer.ts +0 -164
  188. package/templates/apps/api/src/lib/errors.ts +0 -95
  189. package/templates/apps/api/src/lib/file-fallback.ts +0 -87
  190. package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
  191. package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
  192. package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
  193. package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
  194. package/templates/apps/api/src/lib/license-key-store.ts +0 -45
  195. package/templates/apps/api/src/lib/locales.ts +0 -201
  196. package/templates/apps/api/src/lib/outbound-http.ts +0 -127
  197. package/templates/apps/api/src/lib/prisma.ts +0 -21
  198. package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
  199. package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
  200. package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
  201. package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
  202. package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
  203. package/templates/apps/api/src/lib/site.ts +0 -257
  204. package/templates/apps/api/src/lib/slice-load.ts +0 -90
  205. package/templates/apps/api/src/lib/spoke-store.ts +0 -180
  206. package/templates/apps/api/src/lib/stripe.ts +0 -321
  207. package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
  208. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
  209. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
  210. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
  211. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
  212. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
  213. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
  214. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
  215. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
  216. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
  217. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
  218. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
  219. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
  220. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
  221. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
  222. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
  223. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
  224. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
  225. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
  226. package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
  227. package/templates/apps/api/src/middleware/auth.ts +0 -864
  228. package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
  229. package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
  230. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -391
  231. package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
  232. package/templates/apps/api/src/openapi/index.ts +0 -18
  233. package/templates/apps/api/src/openapi/spec.ts +0 -2148
  234. package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
  235. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
  236. package/templates/apps/api/src/routes/aeo/index.ts +0 -107
  237. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
  238. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
  239. package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
  240. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
  241. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
  242. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
  243. package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
  244. package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
  245. package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
  246. package/templates/apps/api/src/routes/auth/user.ts +0 -305
  247. package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -332
  248. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
  249. package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1426
  250. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
  251. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
  252. package/templates/apps/api/src/routes/checkout/index.ts +0 -34
  253. package/templates/apps/api/src/routes/checkout/session.ts +0 -171
  254. package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
  255. package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
  256. package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
  257. package/templates/apps/api/src/routes/consent/account.ts +0 -268
  258. package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
  259. package/templates/apps/api/src/routes/consent/index.ts +0 -26
  260. package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
  261. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
  262. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
  263. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
  264. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
  265. package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
  266. package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
  267. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
  268. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
  269. package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
  270. package/templates/apps/api/src/routes/content/get-page.ts +0 -183
  271. package/templates/apps/api/src/routes/content/index.ts +0 -49
  272. package/templates/apps/api/src/routes/content/list-pages.ts +0 -74
  273. package/templates/apps/api/src/routes/content/list-types.ts +0 -19
  274. package/templates/apps/api/src/routes/content/offerings.ts +0 -184
  275. package/templates/apps/api/src/routes/content/pricing.ts +0 -176
  276. package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
  277. package/templates/apps/api/src/routes/content/search.ts +0 -100
  278. package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
  279. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
  280. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
  281. package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
  282. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
  283. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
  284. package/templates/apps/api/src/routes/leads/index.ts +0 -639
  285. package/templates/apps/api/src/routes/leads/list.ts +0 -104
  286. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
  287. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
  288. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
  289. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -491
  290. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -476
  291. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
  292. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
  293. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
  294. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
  295. package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
  296. package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
  297. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
  298. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
  299. package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
  300. package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
  301. package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
  302. package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
  303. package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
  304. package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
  305. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
  306. package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
  307. package/templates/apps/api/src/routes/requests/index.ts +0 -54
  308. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
  309. package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
  310. package/templates/apps/api/src/routes/webhooks/README.md +0 -398
  311. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
  312. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
  313. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -449
  314. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
  315. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
  316. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
  317. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
  318. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
  319. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
  320. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
  321. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
  322. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -809
  323. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
  324. package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
  325. package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
  326. package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2028
  327. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -645
  328. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
  329. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
  330. package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
  331. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
  332. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
  333. package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
  334. package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
  335. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -877
  336. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
  337. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
  338. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
  339. package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
  340. package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
  341. package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
  342. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
  343. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
  344. package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
  345. package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1204
  346. package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -450
  347. package/templates/apps/api/src/services/__tests__/project-listings.counts.test.ts +0 -202
  348. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -151
  349. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
  350. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
  351. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
  352. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
  353. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
  354. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
  355. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
  356. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
  357. package/templates/apps/api/src/services/abandon-email.ts +0 -336
  358. package/templates/apps/api/src/services/aeo-score.ts +0 -325
  359. package/templates/apps/api/src/services/answer-distributions.ts +0 -138
  360. package/templates/apps/api/src/services/audit-log.ts +0 -961
  361. package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
  362. package/templates/apps/api/src/services/consent.ts +0 -834
  363. package/templates/apps/api/src/services/default-tenant.ts +0 -416
  364. package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -750
  365. package/templates/apps/api/src/services/dunning-policy.ts +0 -294
  366. package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
  367. package/templates/apps/api/src/services/entitlements.ts +0 -338
  368. package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
  369. package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
  370. package/templates/apps/api/src/services/lead-promotion.ts +0 -160
  371. package/templates/apps/api/src/services/lead-routing.ts +0 -1372
  372. package/templates/apps/api/src/services/leads-inbox.ts +0 -312
  373. package/templates/apps/api/src/services/listing-config.ts +0 -178
  374. package/templates/apps/api/src/services/magnet-completion.ts +0 -242
  375. package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -348
  376. package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
  377. package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -975
  378. package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
  379. package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -400
  380. package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -685
  381. package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
  382. package/templates/apps/api/src/services/offerings/catalog.ts +0 -318
  383. package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -403
  384. package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
  385. package/templates/apps/api/src/services/offerings/connection.ts +0 -1083
  386. package/templates/apps/api/src/services/offerings/index.ts +0 -614
  387. package/templates/apps/api/src/services/offerings/source.ts +0 -140
  388. package/templates/apps/api/src/services/offerings/store.ts +0 -150
  389. package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
  390. package/templates/apps/api/src/services/person.ts +0 -1211
  391. package/templates/apps/api/src/services/plan-offerings.ts +0 -125
  392. package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
  393. package/templates/apps/api/src/services/project-listings.ts +0 -2085
  394. package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
  395. package/templates/apps/api/src/services/request-confirm.ts +0 -698
  396. package/templates/apps/api/src/services/revalidation.ts +0 -235
  397. package/templates/apps/api/src/services/slack-notify.ts +0 -291
  398. package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
  399. package/templates/apps/api/src/services/usage-credits.ts +0 -340
  400. package/templates/apps/api/src/services/verified-email.ts +0 -71
  401. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
  402. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
  403. package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
  404. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
  405. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
  406. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
  407. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
  408. package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
  409. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
  410. package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
  411. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
  412. package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
  413. package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
  414. package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
  415. package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
  416. package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
  417. package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1232
  418. package/templates/apps/mcp/__tests__/index.test.ts +0 -195
  419. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
  420. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
  421. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -70
  422. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -162
  423. package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
  424. package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
  425. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -180
  426. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
  427. package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -268
  428. package/templates/apps/mcp/__tests__/locale.test.ts +0 -120
  429. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
  430. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
  431. package/templates/apps/mcp/__tests__/rate-limit-write.test.ts +0 -189
  432. package/templates/apps/mcp/__tests__/read_content.test.ts +0 -511
  433. package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -160
  434. package/templates/apps/mcp/__tests__/search_content.test.ts +0 -271
  435. package/templates/apps/mcp/__tests__/server.test.ts +0 -388
  436. package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
  437. package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -222
  438. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -152
  439. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
  440. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
  441. package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
  442. package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
  443. package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
  444. package/templates/apps/mcp/src/abuse/index.ts +0 -349
  445. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
  446. package/templates/apps/mcp/src/boot.ts +0 -167
  447. package/templates/apps/mcp/src/config/modules.ts +0 -43
  448. package/templates/apps/mcp/src/http-transport.ts +0 -564
  449. package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
  450. package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
  451. package/templates/apps/mcp/src/lib/content-adapter.ts +0 -116
  452. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -140
  453. package/templates/apps/mcp/src/lib/errors.ts +0 -61
  454. package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
  455. package/templates/apps/mcp/src/lib/locales.ts +0 -171
  456. package/templates/apps/mcp/src/lib/prisma.ts +0 -39
  457. package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
  458. package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
  459. package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
  460. package/templates/apps/mcp/src/lib/site-config.ts +0 -53
  461. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
  462. package/templates/apps/mcp/src/request-context.ts +0 -52
  463. package/templates/apps/mcp/src/server.ts +0 -343
  464. package/templates/apps/mcp/src/serverless-app.ts +0 -88
  465. package/templates/apps/mcp/src/tools/audit.ts +0 -127
  466. package/templates/apps/mcp/src/tools/capture_lead.ts +0 -66
  467. package/templates/apps/mcp/src/tools/create_project.ts +0 -134
  468. package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
  469. package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
  470. package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
  471. package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
  472. package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
  473. package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
  474. package/templates/apps/mcp/src/tools/index.ts +0 -138
  475. package/templates/apps/mcp/src/tools/list_pages.ts +0 -68
  476. package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
  477. package/templates/apps/mcp/src/tools/proposals.ts +0 -27
  478. package/templates/apps/mcp/src/tools/purchase.ts +0 -205
  479. package/templates/apps/mcp/src/tools/read_content.ts +0 -81
  480. package/templates/apps/mcp/src/tools/request_callback.ts +0 -52
  481. package/templates/apps/mcp/src/tools/search_content.ts +0 -63
  482. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -54
  483. package/templates/apps/mcp/src/workspace-server.ts +0 -224
  484. package/templates/database/CHANGELOG.md +0 -981
  485. package/templates/database/LICENSE +0 -202
  486. package/templates/database/NOTICE +0 -2
  487. package/templates/database/README.md +0 -243
  488. package/templates/database/__tests__/agents.db.test.ts +0 -320
  489. package/templates/database/__tests__/appointment.db.test.ts +0 -106
  490. package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
  491. package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
  492. package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
  493. package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
  494. package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
  495. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
  496. package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
  497. package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
  498. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
  499. package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
  500. package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
  501. package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
  502. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
  503. package/templates/database/__tests__/flows-presets.test.ts +0 -173
  504. package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
  505. package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
  506. package/templates/database/__tests__/member-area.db.test.ts +0 -257
  507. package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
  508. package/templates/database/__tests__/member-contract.db.test.ts +0 -413
  509. package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
  510. package/templates/database/__tests__/offerings-migration.test.ts +0 -197
  511. package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
  512. package/templates/database/__tests__/offerings.db.test.ts +0 -303
  513. package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
  514. package/templates/database/__tests__/person-contact.db.test.ts +0 -563
  515. package/templates/database/__tests__/person-notes.db.test.ts +0 -249
  516. package/templates/database/__tests__/person.db.test.ts +0 -586
  517. package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
  518. package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
  519. package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
  520. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
  521. package/templates/database/__tests__/seed.test.ts +0 -272
  522. package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
  523. package/templates/database/__tests__/tenancy.test.ts +0 -141
  524. package/templates/database/__tests__/trial-magnet-migration.test.ts +0 -186
  525. package/templates/database/__tests__/user-cascade.test.ts +0 -140
  526. package/templates/database/_gitignore +0 -8
  527. package/templates/database/auth/.gitkeep +0 -0
  528. package/templates/database/auth/schema.prisma +0 -641
  529. package/templates/database/config/.gitkeep +0 -0
  530. package/templates/database/config/schema.prisma +0 -441
  531. package/templates/database/content/.gitkeep +0 -0
  532. package/templates/database/content/schema.prisma +0 -339
  533. package/templates/database/eslint.config.mjs +0 -69
  534. package/templates/database/flows/listing-diagnostic.ts +0 -182
  535. package/templates/database/flows/presets.ts +0 -315
  536. package/templates/database/inbox/.gitkeep +0 -0
  537. package/templates/database/inbox/README.md +0 -3
  538. package/templates/database/inbox/__tests__/schema.test.ts +0 -44
  539. package/templates/database/inbox/schema.prisma +0 -1447
  540. package/templates/database/jest.config.cjs +0 -36
  541. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
  542. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
  543. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
  544. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
  545. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
  546. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
  547. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
  548. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
  549. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
  550. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
  551. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
  552. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
  553. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
  554. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
  555. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
  556. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
  557. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
  558. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
  559. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
  560. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
  561. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
  562. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
  563. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
  564. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
  565. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
  566. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
  567. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
  568. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
  569. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
  570. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
  571. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
  572. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
  573. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
  574. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
  575. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
  576. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
  577. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
  578. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
  579. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
  580. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
  581. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
  582. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
  583. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
  584. package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
  585. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
  586. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
  587. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
  588. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
  589. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
  590. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
  591. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
  592. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
  593. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
  594. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
  595. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
  596. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
  597. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
  598. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
  599. package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
  600. package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
  601. package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
  602. package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
  603. package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
  604. package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
  605. package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
  606. package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
  607. package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
  608. package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
  609. package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
  610. package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
  611. package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
  612. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
  613. package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
  614. package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
  615. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
  616. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
  617. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
  618. package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
  619. package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
  620. package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
  621. package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
  622. package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
  623. package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
  624. package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
  625. package/templates/database/migrations/20261025120000_trial_magnet/migration.sql +0 -28
  626. package/templates/database/migrations/20261026120000_trial_magnet_proof_line/migration.sql +0 -23
  627. package/templates/database/migrations/migration_lock.toml +0 -3
  628. package/templates/database/ops/.gitkeep +0 -0
  629. package/templates/database/ops/schema.prisma +0 -43
  630. package/templates/database/package.json +0 -89
  631. package/templates/database/schema.prisma +0 -71
  632. package/templates/database/scripts/db-generate-locked.sh +0 -80
  633. package/templates/database/scripts/person-backfill.sql +0 -132
  634. package/templates/database/tenancy.ts +0 -183
  635. package/templates/database/tsconfig.build.json +0 -16
  636. package/templates/database/tsconfig.flows.json +0 -15
  637. package/templates/database/tsconfig.json +0 -16
  638. package/templates/database/tsconfig.tenancy.json +0 -14
@@ -1,981 +0,0 @@
1
- # @working-theory/database
2
-
3
- ## 0.45.0
4
-
5
- ### Patch Changes
6
-
7
- - [#9309](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/9309) [`42b37e2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/42b37e237d0f424573346b158290f0ecc4ae77a4) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Every workspace now holds a standard trial magnet at the fixed slug `trial` ([#9301](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/9301)).
8
-
9
- - **`@working-theory/validation`**: new exports `TRIAL_FLOW_SLUG`, `TRIAL_FLOW_TITLE`, `TRIAL_FLOW_LANDING_PAGE`, `TRIAL_TERMS_STATEMENT` and `trialFlowConfig` — one step asking for first name, last name, work email and the terms box, ending on "Thanks, {name}.", with a landing whose button reads "Request a free trial". `RESERVED_FLOW_SLUGS` gains `trial`, so no flow-engine write, spoke seed or new listing can take the slug (a new listing named "Trial" now derives `trial-2`).
10
- - **`@working-theory/database`**: the default workspace's seed writes the trial magnet (`diagnostic`, `live`, completion `lead`, landing page `/trial`), and the `20261025120000_trial_magnet` migration backfills it into every existing workspace, insert-only — a row already at `trial` is never changed.
11
- - **`create-ailk`**: the API seeds the trial magnet when it creates a workspace and from `seed-presets`, and the magnet PATCH refuses to rename the trial magnet or rename another magnet to `trial` (`409`). A completed walk is a `flow:trial` Inbox submission whose Person carries the given name, family name, email and, when a site adds a `company`-tagged field, the company.
12
-
13
- - [#9330](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/9330) [`569b348`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/569b348a95aa7b1b414ed62151d810e41877f238) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The trial magnet gets its page pair: `/trial` and `/trial/request` ([#9302](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/9302)).
14
-
15
- - **`create-ailk`**: a site with the `signal-collectors` module carries `/trial`, the indexable landing inside the site's Nav and Footer — the trial magnet's landing copy, one button ("Request a free trial") to `/trial/request`, and the `Assessment` JSON-LD — and `/trial/request`, the full-screen, `noindex, follow` walk of the trial magnet with a back arrow to `/trial`. When the trial flow is absent or the hub cannot answer, the walk shows the site's contact email under its own "Free trial" heading instead of a 404. The magnet landing renderer takes an optional `startPath` for a walk not at `<path>/start`.
16
- - **`@working-theory/validation`**: `trialFlowConfig.landing` gains its proof line, `meta`: "A person on our team reviews every request." It is true for every site, because only an operator starts a trial, from the Inbox.
17
- - **`@working-theory/database`**: the `20261026120000_trial_magnet_proof_line` migration gives that line to every workspace's trial magnet that still holds [#9301](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/9301)'s exact default. A trial magnet an owner has edited is never touched.
18
- - **`@working-theory/templates`**: `ROUTES` gains the `/trial` and `/trial/request` rows (module `signal-collectors`).
19
-
20
- - Updated dependencies [[`1d9b675`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1d9b6755b3fbffebfcd7c57a93ea7cbc9941bba0), [`875714a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/875714ad871e2b9b3778383ed106e8a1586fe3a6), [`42b37e2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/42b37e237d0f424573346b158290f0ecc4ae77a4), [`569b348`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/569b348a95aa7b1b414ed62151d810e41877f238), [`d648b1a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d648b1a98a84dfee56f6847e7ec5f9fd0421a163), [`5008d1d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5008d1d13283fe5ed04504dcfb17122d18892a18), [`a5c5d1c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/a5c5d1cc3443394d0da9507c7b11954b54e8c0da), [`67e75c8`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/67e75c87519235435f578ee22c2cf8fa2f74f17d), [`16c889b`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/16c889b7434ad49c3b18f900c42779c72e78f233)]:
21
- - @working-theory/validation@0.45.0
22
-
23
- ## 0.44.0
24
-
25
- ### Minor Changes
26
-
27
- - [#8955](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8955) [`1a84162`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1a841626a9e5664d926a2f186425f35e8757a6b4) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The Offerings data model and its typed read services ([#8876](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8876)).
28
-
29
- - **`@working-theory/database`** — three config tables, in migration `20261020120000_offerings_data_model`: `StripeConnection` (an Organization's own Stripe account by a restricted key — mode, last four, the key and webhook secret as ciphertext the database refuses in clear, a webhook token), `OrganizationOfferings` (the Products an Organization has switched on) and `WorkspaceOfferings` (what a workspace shows, its Recommended plan and add-on, and the last-good Stripe snapshot). Deploy the migration before the API. No existing table is touched.
30
- - **`@working-theory/ids`** — registers the `stripecon`, `orgoffer` and `wsoffer` prefixes for the new models.
31
- - **`@working-theory/validation`** — the Offerings data contract: `parseLookupKey` (the one lookup-key parser, `<plan>_<monthly|yearly|once>`), `periodOfStripePrice`, the text bounds, and the typed shapes `offeringsProductSchema`, `offeringsSnapshotSchema`, `orgEnabledProductsSchema`, `workspaceShownSetSchema` and `stripeConnectionSummarySchema`.
32
- - **`create-ailk`** — a scaffold's `apps/api` carries the Offerings read services (`getOrgEnabledProducts`, `getWorkspaceShownSet`, `getSellableProductIds`, the bounded snapshot refresh and the connection summary). No route reads them yet, so a site's behaviour is unchanged.
33
-
34
- - [#8968](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8968) [`8da1163`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8da1163fd04f083fd8d408a4a7d762b756b23274) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The Offerings Checkout session record ([#8930](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8930)).
35
-
36
- - **`@working-theory/database`** — one config table, in migration `20261021120000_offerings_checkout_session`: `OfferingsCheckoutSession`, one row per Checkout Session the hub created (its id, workspace, Organization, Price, lookup key and mode), with a CHECK on every column but `created_at`. Deploy the migration before the API. No existing table is touched.
37
- - **`@working-theory/ids`** — registers the `ocsess` prefix for the new model.
38
- - **`create-ailk`** — a scaffold's `apps/api` carries the record's one store (`recordCheckoutSession`, `readCheckoutSessionRecord`). No route calls it yet, so a site's behaviour is unchanged.
39
-
40
- - [#9091](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/9091) [`23cf71c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/23cf71c316c9e44c6109c76439cb64281e6368d5) Thanks [@samuelhenry](https://github.com/samuelhenry)! - A workspace's Offerings shown set is chosen per Stripe Price, and the Admin's Offerings page reads like Magnets ([#9070](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/9070)).
41
-
42
- - **`@working-theory/database`** — migration `20261023120000_offerings_shown_price_ids` adds `workspace_offerings.shown_price_ids TEXT[] NOT NULL DEFAULT '{}'` and two CHECKs (at most 300 non-null ids; Price ids only beside a shown Product). No row is rewritten: an empty array means every Price of each shown Product, so every workspace saved before this release shows exactly what it showed before. **Deploy the migration before the API, and the API before the Admin.** While the API and the Admin are on different versions the Offerings page cannot save (nothing is written and nothing new is sold).
43
- - **`@working-theory/validation`** — new exports `OFFERINGS_PRICE_IDS_MAX`, `offeringsPriceIdsSchema`, `workspaceOfferingsShownEntrySchema` and `workspaceOfferingsShownSchema`. Changed shapes: `workspaceOfferingsSelectionInputSchema` is now one Price's switch, `{ productId, period, shown }`, so no body names a Recommended or a whole set; `workspaceOfferingsSelectionSchema` gains `shownPriceIds`, empty exactly when `shownProductIds` is; `workspaceOfferingsViewSchema`'s available branch answers `shown` (`{ productId, periods }` per Product) in place of `shownProductIds`.
44
- - **`create-ailk`** — a scaffold's `PUT /v1/workspaces/:workspaceId/offerings` takes one Price per save and keeps or clears a stored Recommended but never sets one (`recommended_not_shown` is retired; a period the Product has no Price for is `400 price_not_offered`). Its audit row's `shown`, `added` and `removed` count Prices, not Products, from this release. `/pricing`, the agent pricing tools, the plan picker and checkout show and sell only the shown Prices, so a seller can show a yearly Price without its monthly sibling; a Price replaced in Stripe stays off until it is switched on. The Admin's Offerings page is a Title / Tags / Live table, one row per Price, with a New recommender button and no Recommended control.
45
-
46
- **Rollback.** Roll the API back, then run `UPDATE workspace_offerings SET shown_price_ids = '{}'` so every row reads at the Product grain again and the old route's saves succeed. Tell each owner who saved per Price that every Price of their shown Products — on `/pricing` and at checkout — is on sale again. Never drop the column while a per-Price row exists without that notice.
47
-
48
- ### Patch Changes
49
-
50
- - Updated dependencies [[`6ad87d6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6ad87d65d91013ac9c0945a62efbf28c627b1fce), [`d9c2cd3`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d9c2cd3c601d9a267d4d29cb9bcef77ec71cd518), [`407810f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/407810fbd63a02d14773aef36a10c1f9f04dd5e3), [`5875c18`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5875c189f72f66ea2af7b7c79a47baba53a329d1), [`13c0b3d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/13c0b3dd64a105292962821f5b0050c5cabc2d45), [`82bc2f1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/82bc2f1ecab1a12f23a45e326355841ba87d9f04), [`ea18e21`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ea18e2181241ba9357b4dcfa3a1d2f4c3ffe4518), [`8754f86`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8754f866b49003965c4be28cbe19b1f040aec4af), [`1a84162`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1a841626a9e5664d926a2f186425f35e8757a6b4), [`74cb7b3`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/74cb7b37adea5d27adc1f3ec3ea58b9941167c4d), [`25b4b61`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/25b4b6199d8632167bd5501a4e12d4774eed432a), [`8da1163`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8da1163fd04f083fd8d408a4a7d762b756b23274), [`bd1c9b5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/bd1c9b576ac337596e585145f09b08696e9f412e), [`d1dacc5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d1dacc5d76a9cc91f6ad3b1883067e327b5e3d3c), [`fff5487`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/fff5487a6d14a3010bf22cb99e7554e6542449a0), [`23cf71c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/23cf71c316c9e44c6109c76439cb64281e6368d5), [`75ecc58`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/75ecc584f43793bb5234f69e0f80b15327a99236), [`85ae357`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/85ae357410ebd6c11b08b04355a9ede1d2088d2d), [`059c892`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/059c89249f7db3dc106f133ef37180e9eb1e318a), [`c563360`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c563360db386758aa2d25309ab693a18a41e4139)]:
51
- - @working-theory/validation@0.44.0
52
- - @working-theory/ids@0.15.0
53
-
54
- ## 0.43.0
55
-
56
- ### Minor Changes
57
-
58
- - [#8775](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8775) [`ee8e713`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ee8e713b8194e8d65052f4b1dca928ca0c970318) Thanks [@claudio-planck](https://github.com/claudio-planck)! - A per-magnet completion setting — lead only, invite to account, or continue to checkout ([#8757](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8757), Phase 1).
59
-
60
- - **`@working-theory/database`** — `flow_definitions` gains `completion` (`lead` | `invite` | `checkout`, default `lead`) and `checkout_offering`, closed by three CHECKs. The migration backfills `onboarding`, `request-quote` and `job-application` to `invite` by slug; `contact` and every other magnet stay `lead`. Deploy the migration before the API.
61
- - **`@working-theory/validation`** — `flow-completion.ts`: `FLOW_COMPLETIONS`, `flowCompletionSettingSchema`, `flowCheckoutOfferingSchema`, `STANDARD_MAGNET_COMPLETIONS`, `leadSubmitNextSchema`, `accountEmailHintSchema`, `accountInvitePath`, the invite caps and the email defaults.
62
- - **`@working-theory/api-client`** — `Magnet` carries `completion` and `checkoutOffering`, `MagnetUpdateInput` can set them, and `LeadWriteResponse` gains an optional `next`.
63
- - **`@working-theory/ui`** — `AuthCard` takes an optional `defaultEmail`; `LeadCaptureFormState`'s success state takes an optional `next` link.
64
- - **`@working-theory/analytics`** — `email` and `login_hint` are scrubbed from URLs like `session_id`.
65
- - **`create-ailk`** — the API: the magnet PATCH writes the setting alone (`checkout` needs a person, the `commerce` claim and a published offering) and every full row serves it; a `flow:<slug>` submit to an `invite` magnet answers `next` and sends one capped confirmation email whose link starts sign-in with the address prefilled. The web: /contact's thank-you shows "Track this in your account", and sign-in opens with a hinted email on a site and through the hub. The Admin: one "When someone submits" control on the magnet page.
66
-
67
- - [#8807](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8807) [`956bfe6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/956bfe60fff4bd9a43135e6a2fb79e6f012e14f8) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Every hosted Stripe Checkout session collects terms acceptance, and a completed checkout records a dated grant for the buyer ([#8765](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8765), PR B).
68
-
69
- - **`@working-theory/stripe-client`** — both session creators set `consent_collection.terms_of_service: "required"` and a `custom_text.terms_of_service_acceptance` message: the site's account-terms sentence with its Terms, Privacy Policy and Working Agreement links resolved on the session's own return origin. Every session is stamped `metadata.ailk_terms` (`account_terms@2` by default). An optional `termsOfService` input overrides the sentence and its links. A Stripe refusal for a missing Terms URL is rethrown as `TermsOfServiceUrlMissingError`. **Precondition:** the seller's Stripe account needs a Terms of Service URL in its Dashboard's Public details, or Stripe refuses every session with the box.
70
- - **`@working-theory/validation`** — `CONSENT_SOURCES` gains `checkout`.
71
- - **`@working-theory/database`** — a migration widens the `consent_grants_source_known` CHECK to the eight sources. It writes no row.
72
- - **`create-ailk`** — the API: the hub's `checkout.session.completed` webhook records one `checkout` grant per session for the buyer's Person when the session carries the terms stamp and Stripe recorded the consent as accepted. A checkout row is an unverified (any-source) row. The Admin labels the source "Checkout".
73
-
74
- ### Patch Changes
75
-
76
- - [#8767](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8767) [`5ff341d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5ff341d683d35a024fc1073c1b010aa56956a1d2) Thanks [@claudio-planck](https://github.com/claudio-planck)! - A JobPosting names where to apply, and a standard Job application magnet is seeded like the Contact form and drawn on every job page ([#8746](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8746)).
77
-
78
- - **`@working-theory/schema`** — `ContentPageInput` gains an optional `origin` (the site's origin, passed by the caller; the package never reads the environment for it). When it is present, the JobPosting builder puts a `potentialAction` `ApplyAction` on the JobPosting whose `target` is the job page's own URL plus `#apply`: `<origin>/<locale>/careers/<slug>#apply`, the same form the page's BreadcrumbList uses. `buildJobPostingNode` takes an optional `applyUrl`. Every other builder ignores `origin`, so CareersList keeps its ItemList unchanged.
79
- - **`@working-theory/page-renderer`** — `toContentPageInput` passes the render's origin (the one the BreadcrumbList is built from).
80
- - **`@working-theory/validation`** — the magnet's one source: `JOB_APPLICATION_FLOW_SLUG` (`job-application`), `JOB_APPLICATION_FLOW_TITLE`, `JOB_APPLICATION_LANDING_PAGE` (`/careers`) and `jobApplicationFlowConfig` — one field step of First name, Last name and Email (required), Phone (`tel`) and LinkedIn URL (`url`). `RESERVED_FLOW_SLUGS` gains `job-application`, so no flow-engine write, spoke seed or new listing takes it.
81
- - **`@working-theory/database`** — the database seed writes the default workspace's Job application magnet: `diagnostic`, `live`, landing page `/careers`, insert-only.
82
- - **`create-ailk`** — the API seeds the magnet into every workspace insert-only (after `POST /v1/workspaces` and from the seed-presets CLI for existing workspaces), a magnet can be neither renamed from nor to `job-application`, and `GET /v1/content/:type/:slug` passes `_site.mdx`'s `baseUrl` as the origin, so the API's JobPosting JSON-LD carries the ApplyAction too. Each job page `/careers/<slug>` renders the magnet's field step under an `#apply` anchor, falling back to the same built-in form when the magnet is absent or off; a submission is a `flow:job-application` lead whose `name` is first + last and whose hidden `job` is the posting's slug, and the form thanks the applicant with the `careers` catalog's own `applicationSuccess` line. The `/careers` index carries no form.
83
-
84
- - [#8788](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8788) [`3a89742`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/3a89742f7b816deca6cd604863f2fd041a79abfa) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The standard magnets are seeded with their completion setting ([#8759](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8759)), so a workspace created after the [#8757](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8757) migration no longer depends on its backfill.
85
-
86
- - **`@working-theory/database`** — the database seed writes `completion` on the default workspace's magnets: `invite` on `request-quote` and `job-application`, `lead` on `contact`. On a fresh install the migration's backfill runs before the seed and finds no rows.
87
- - **`create-ailk`** — the API's insert-only seed writes `lead` on the Contact form and `invite` on the onboarding and Job application magnets, and `POST /v1/workspaces` creates the `request-quote` magnet at `invite`.
88
-
89
- - Updated dependencies [[`5032b3e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5032b3eefb05bbe67ebddf1b4b07904717100472), [`5ff341d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5ff341d683d35a024fc1073c1b010aa56956a1d2), [`ee8e713`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ee8e713b8194e8d65052f4b1dca928ca0c970318), [`c74bd72`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c74bd7270fa2cb82bebedfb1b53f89ca6e09917f), [`956bfe6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/956bfe60fff4bd9a43135e6a2fb79e6f012e14f8), [`97237f2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/97237f278006a43e17d58709ed9ac3b4f62ae76f), [`1eb9688`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1eb9688708dbc65cd4e2fdb6efeb40880e1606f0), [`b001413`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/b001413238973f4ecb3d4a5a18968cd7732210d8)]:
90
- - @working-theory/validation@0.43.0
91
-
92
- ## 0.42.0
93
-
94
- ### Patch Changes
95
-
96
- - [#8740](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8740) [`d1461bf`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d1461bff10a69aa4cf05627e393bd1902c358b00) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The database seed writes the default workspace's Contact form magnet ([#8661](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8661)): one live contact-kind magnet at slug `contact`, insert-only, so `/contact` reads it on a freshly seeded site.
97
-
98
- - Updated dependencies [[`cb2f3a5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cb2f3a50c38fe77b92aa52d1462d3d11a5981981), [`425e253`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/425e2538dfd22dfb6f0b6439d473fa2aafcbb883), [`da9253b`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/da9253bb6f8c792e7e75cfe1c1a7bba5ca569e26), [`df1b8e4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/df1b8e485f9cdd1885925430b7aaa186ffdf6ac1), [`d4e0598`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d4e0598c7659d9349bd56ba184e4ab941e3fde62)]:
99
- - @working-theory/validation@0.42.0
100
-
101
- ## 0.41.0
102
-
103
- ### Minor Changes
104
-
105
- - [#8540](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8540) [`48ff411`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/48ff41198ef01163412118249f51d64b66d4ce42) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The API's per-IP rate limiter counts in a shared database table when one is configured, so one visitor's limit holds across every concurrent isolate ([#5040](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5040)).
106
-
107
- New model `RateLimitCounter` (table `rate_limit_counters`, prefix `rlc`) in the `ops` namespace, holding one row per hashed bucket key. Run the migration before deploying the code that reads it — code deployed first falls back to the per-isolate in-process limiter, safely, until the table exists.
108
-
109
- - [#8545](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8545) [`41bc2df`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/41bc2df800c8fe69e2cbb528be68f579abfbd80d) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The Person record redesign ([#8514](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8514), docs/specs/8514-redesign-the-person-record-page-spec.md).
110
-
111
- - **database** — `people` gains the team's private note on a client (`notes`, who last saved it, when, and which agent), with format and pairing CHECKs. The same migration then removes `people-read` and `member-pieces-manage` from agents of members, where they were inert; deploy it before the code.
112
- - **validation** — members now hold `people-read`, `people-write` and `member-pieces-manage`. The new `AGENT_WITHHELD_PERMISSIONS` and `roleAllows` keep every agent off those three by role: an agent holds the grantable two only by an explicit grant, and `people-write` never. New `personNotes*` and `planOfferings*` schemas.
113
- - **api-client** — `people.notes` and `people.setNotes`.
114
- - **metadata** — two signed-in workspace tools, `get_person_notes` and `set_person_notes` (thirteen in all).
115
- - **ui** — `PhoneNumberField` shows its country format as a "Format: …" caption under the field and no longer puts the example in the placeholder.
116
- - **templates** — `ContactDetailsForm`, the one contact form the account page and the Admin share; Save stays disabled until something changes.
117
-
118
- - [#8574](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8574) [`83b7a96`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/83b7a96ccd115230f82e111a9776c8e2136b6bf9) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Standard client onboarding diagnostic and Start onboarding ([#8515](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8515), docs/specs/8515-standard-client-onboarding-diagnostic-and-spec.md).
119
-
120
- - `@working-theory/database`: `interactions_outbound_shape` admits one outbound payload, `{"action": "onboarding"}` (migration `20261017120000_outbound_message_action`; no row is rewritten).
121
- - `@working-theory/validation`: `ONBOARDING_FLOW_SLUG`, `ONBOARDING_FLOW_TITLE` and `onboardingFlowConfig`, the standard onboarding magnet every workspace holds; `OUTBOUND_MESSAGE_ACTIONS` and `onboardingStartBodySchema`; `memberMessageSchema` gains `action`; `memberOnboardingFormResponseSchema`, `memberOnboardingStepSchema`, `memberOnboardingReceiptSchema` and the `onboarding_off` member error code.
122
- - `@working-theory/api-client`: `member.onboarding` and `member.submitOnboarding`.
123
-
124
- - [#8572](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8572) [`16abdb4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/16abdb45ef60cc46aba35d4179960468b8df1a8b) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Proposals as an artifact kind ([#8516](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8516), docs/specs/8516-proposals-as-an-artifact-kind-spec.md).
125
-
126
- - `@working-theory/database`: `pieces` gains `kind` (`deliverable` by default, so every existing piece is unchanged), a proposal's optional price, the client's Checkout Session and the paid stamp, with their CHECKs and one unique index (migration `20261016120000_piece_kind`, DDL only).
127
- - `@working-theory/validation`: `PIECE_KINDS`, `pieceKindSchema`, `PROPOSAL_CURRENCIES`, `proposalPriceSchema`; `pieceSchema` serves `kind`; the new `proposals.ts` wire (`proposalCreateBodySchema`, `proposalSchema`, `proposalsListResponseSchema`, `proposalResultSchema`, `proposalPaymentsSchema`); `memberArtifactSchema` gains optional `kind`, `price` and `payment`; `isStripeCheckoutUrl`, `memberProposalPaymentResponseSchema` and three member error codes.
128
- - `@working-theory/api-client`: `people.proposals`, `people.createProposal` and `member.payArtifact`.
129
- - `@working-theory/metadata`: the `list_proposals` and `create_proposal` workspace tools.
130
- - `@working-theory/stripe-client`: `createQuotedCheckoutSession` takes optional `expiresAt` and `paymentMethodTypes`; existing callers' sessions are unchanged.
131
-
132
- ### Patch Changes
133
-
134
- - [#8551](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8551) [`13e1d6f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/13e1d6f74ef3db02b9cdedb5f33f84ad1a9a0d66) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Person gains a private team note (notes, notes_updated_at, notes_updated_by, notes_updated_by_agent) and tenant-db gains its one reader and writer ([#8514](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8514), PR 1 of 2 — the fence half; the API, MCP and Admin surfaces follow in PR 2).
135
-
136
- - Updated dependencies [[`1b0d07a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1b0d07acc0c97f519bf7a2dccf108d6b98c24065), [`48ff411`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/48ff41198ef01163412118249f51d64b66d4ce42), [`98b82b0`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/98b82b0e1cf29be3ba33886ebc7b8294ebff52f0), [`41bc2df`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/41bc2df800c8fe69e2cbb528be68f579abfbd80d), [`83b7a96`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/83b7a96ccd115230f82e111a9776c8e2136b6bf9), [`16abdb4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/16abdb45ef60cc46aba35d4179960468b8df1a8b)]:
137
- - @working-theory/validation@0.41.0
138
- - @working-theory/ids@0.14.0
139
-
140
- ## 0.40.0
141
-
142
- ### Minor Changes
143
-
144
- - [#8497](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8497) [`52df359`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/52df359fb2a4d1aff488136126dba16d13e49a26) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Contact details on the client record ([#8435](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8435), spec docs/specs/8435-contact-details-on-the-client-spec.md).
145
-
146
- A Person now carries a given name, a family name, an E.164 telephone, a six-part address, a company name and a job title, with the two columns that say who last saved them by hand. `callbacks` and `subscribers` gain a `person_id` foreign key. A capture fills only a blank field of an uncurated Person; the operator edits the contact from the Person page and a client edits their own on the site, from the account General tab. A magnet field's `mapsTo` tag names the contact field it fills: `email`, `name`, `givenName`, `familyName`, `phone`, `address`, `company`, `jobTitle`. Additive; the migration (`20261014120000_person_contact`, its second half the idempotent backfill) deploys before the code.
147
-
148
- - [#8490](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8490) [`64adcf9`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/64adcf9b58a3f3be3b42782e14018234b263b9bc) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The consent ledger ([#8438](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8438), the API half). The per-site consent registry gains a kind (`agreement` · `consent` · `preference`), a plain description, a policy link and a policy version per purpose, and its platform default now declares `service_terms`, `account_terms` and `analytics_cookies`; a registry stored before this change still parses and means what it meant. `consent_grants` becomes the one ledger: each row names its source (`cookie_banner` · `sign_up` · `magnet` · `account_settings` · `email_unsubscribe` · `api`), its policy version and, when known, its Person, and the database refuses to change or truncate a stored row. A new `consent_visitor_links` table joins a banner visitor to the Person a later form identifies. `@working-theory/api-client` gains `consent.recordCookieChoice`, `consent.unsubscribe`, `member.consents` and `member.setConsent`; `@working-theory/validation` gains their wire schemas and the `platform-consents` permission. Run the new migration before deploying code that writes the ledger.
149
-
150
- ### Patch Changes
151
-
152
- - Updated dependencies [[`52df359`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/52df359fb2a4d1aff488136126dba16d13e49a26), [`64adcf9`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/64adcf9b58a3f3be3b42782e14018234b263b9bc)]:
153
- - @working-theory/validation@0.40.0
154
- - @working-theory/ids@0.13.0
155
-
156
- ## 0.39.0
157
-
158
- ### Minor Changes
159
-
160
- - [#8177](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8177) [`6fa07d3`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6fa07d36321033e1661de34eaee8427eb7e1a6ca) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The member area data model ([#8168](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8168)): the schema and wire contract the member reads, member writes and provider routes build on. No route changes.
161
-
162
- - `@working-theory/database` — `PieceVersion` (`piece_versions`): one delivery of a piece to its client, a private file or an https link, numbered per piece, with the client's review on it; held to its shape by CHECKs and by one composite foreign key onto `pieces(id, person_id, workspace_id)`. `Piece.approvedAt`. `Interaction.kind` (`message` · `quote` · `review`) and `payload`, and `inbound` beside `outbound`; an outbound row stays a payload-free `message`. `FlowDefinition.customersEnabled`. Migration `20261012120000_member_contract` backfills a draft `request-quote` contact magnet into every workspace, never overwriting an existing one, and `db:seed` gives the default workspace the same magnet.
163
- - `@working-theory/validation` — the Phase 1 member contract in `member.ts`: reads, writes, write responses, the stored payloads, the vocabularies and `memberErrorCodeSchema`, and `isHttpsLink`. `requestQuoteFlowConfig`, `REQUEST_QUOTE_FLOW_SLUG`, `REQUEST_QUOTE_FLOW_TITLE`, `flowCustomersEnabledSchema` and `FLOW_CUSTOMERS_ENABLED_DEFAULT` in `flow.ts`. `plainText` is exported. `subscriptionMeResponseSchema` gains optional `planName` and `paymentMethod`; today's body still parses.
164
- - `@working-theory/site-config` — `MeetingsSchema` gains optional `customerSlugs` (no default, duplicates refused).
165
- - `@working-theory/ids` — the `pver_` prefix (`pieceVersion`).
166
-
167
- - [#8235](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8235) [`2f8a0fe`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2f8a0fed78739b758f9db44caecbb297e009d841) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `Lead.spokeCheckout` ([#8185](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/8185)): a `leads.spoke_checkout BOOLEAN NOT NULL DEFAULT false` column, migration `20261013120000_lead_spoke_checkout`. The hub sets it at creation for a spoke's live paid checkout lead (a registered spoke's key, not relayed, a `cs_live_` Idempotency-Key and the checkout shape) and never updates it. Existing rows read false; there is no backfill. Apply the migration before deploying the API that writes it.
168
-
169
- ### Patch Changes
170
-
171
- - [#8321](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8321) [`f17db78`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/f17db78cc14671473c976d4098b1bdc001f517be) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Licence metadata only: `LICENSE` is now the canonical, unmodified Apache-2.0 text, and the package ships a `NOTICE` file carrying the copyright notice (`Copyright 2026 SalesSmyth LLC`). The previous `LICENSE` appendix named a stale holder. No behavior change.
172
-
173
- - Updated dependencies [[`6fb73eb`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6fb73eb106836a6d201111f460de0811711a1f39), [`6fa07d3`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6fa07d36321033e1661de34eaee8427eb7e1a6ca), [`55567c6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/55567c678b2338523959569457499531c6aac374), [`f17db78`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/f17db78cc14671473c976d4098b1bdc001f517be), [`caeffba`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/caeffba335a8c8f232cedc901babfb6674e319f5)]:
174
- - @working-theory/validation@0.39.0
175
- - @working-theory/ids@0.12.0
176
-
177
- ## 0.38.0
178
-
179
- ### Minor Changes
180
-
181
- - [#8037](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8037) [`89eba8c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/89eba8c2bab16766a68284f52c872aae86f59fde) Thanks [@samuelhenry](https://github.com/samuelhenry)! - The member area contract ([#7877](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7877)): a client's pieces, plan and messages.
182
-
183
- - `@working-theory/database` — `Piece` and `Interaction` on Person (a composite `(person_id, workspace_id)` foreign key to `people`) and `WorkspacePieceStages`, a workspace's declared piece stages; migration `20261011120000_member_area`.
184
- - `@working-theory/ids` — the `piece_`, `intx_` and `pstages_` prefixes; `zPieceId` and `zInteractionId`.
185
- - `@working-theory/validation` — the member-area wire schemas (`pieces.ts`, `member.ts`), the Person timeline's `message` kind, the `people-write` permission (owner, admin; not agent-grantable) and the attachment helpers (`ATTACHABLE_CONTENT_TYPES`, `attachmentFilename`).
186
- - `@working-theory/api-client` — `member.pieces`, `member.messages` and `member.messageFile` (with `getRaw`), the reads a spoke's server makes for its signed-in client. A spoke that re-serves a file sends its five response headers unchanged.
187
- - `create-ailk` — the member-area files are co-owned by the `workspace` and `multi-tenant` slices.
188
-
189
- - [#8049](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8049) [`6a2a120`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6a2a120765c423303716d5e3ebf216c9c10e118b) Thanks [@samuelhenry](https://github.com/samuelhenry)! - An agent key may be granted `member-pieces-manage` ([#7878](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7878)).
190
-
191
- `@working-theory/validation`: the `member-pieces-manage` permission (owner, admin), the seventh entry of `AGENT_GRANTABLE_PERMISSIONS`. The member area's operator writes — a client's pieces, plan and outbound messages — check it through `allows`, so an agent granted it keeps them in its one workspace; `people-write` stays never-grantable. `@working-theory/database`: the `agents_grants_allowed` CHECK widened to admit it (additive).
192
-
193
- - [#8004](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/8004) [`d9ba65f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d9ba65f6334681b17bd77b64bb7ca9e069b1980f) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Person — the per-workspace client record ([#852](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/852)).
194
-
195
- `@working-theory/database`: a `Person` model (one client per normalized email per workspace), `personId` on `Lead` and `Appointment`, the schema and set-based backfill migrations, the post-cutover re-run script `scripts/person-backfill.sql`, the agent-grant CHECK widened to admit `people-read`, and the timeline's email-fallback SQL constants on the `tenancy` subpath. `@working-theory/ids`: the `person_` prefix and `zPersonId`. `@working-theory/validation`: the `people-read` permission (owner, admin; agent-grantable) and the People wire schemas. `@working-theory/api-client`: `people.list` and `people.get` for an agent key granted `people-read`.
196
-
197
- ### Patch Changes
198
-
199
- - Updated dependencies [[`89eba8c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/89eba8c2bab16766a68284f52c872aae86f59fde), [`6a2a120`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6a2a120765c423303716d5e3ebf216c9c10e118b), [`6d38b1a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6d38b1a5362b36e56d6bce79fdf96c878020cb18), [`d9ba65f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d9ba65f6334681b17bd77b64bb7ca9e069b1980f)]:
200
- - @working-theory/validation@0.38.0
201
- - @working-theory/ids@0.11.0
202
-
203
- ## 0.37.0
204
-
205
- ### Minor Changes
206
-
207
- - [#7821](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7821) [`878ffc6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/878ffc61e3c0baad68889e77d4686fdbc88a85c2) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Sign-in lands in the user's last workspace ([#7803](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7803)), the schema half.
208
-
209
- - `@working-theory/database` — `User` gains `lastWorkspaceId` (`users.last_workspace_id`), a nullable reference to `Workspace` with `ON DELETE SET NULL`, an index and the ADR-0031 `wksp_` format CHECK; `Workspace` gains the back-relation `lastActiveUsers`. The migration `20261008120000_user_last_workspace` is purely additive: one nullable column with no default, so no backfill runs and no existing row changes. Deploy it before the API that reads the column.
210
-
211
- - [#7901](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7901) [`6efec95`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6efec954914e40acbf42db1e0132569e983c3915) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Agent key grants ([#7864](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7864)): an owner or admin can grant an agent any of five
212
- permissions — content-edit, content-publish, assets-write, magnets-manage and
213
- meeting-types-manage. `@working-theory/validation` adds
214
- `AGENT_GRANTABLE_PERMISSIONS`, `isAgentGrantable`, `allows` and
215
- `setAgentGrantsBodySchema`, and the agent wire row gains `grants`;
216
- `@working-theory/database` adds the `agents.grants` column, held to those five
217
- by a CHECK. An agent with no grants behaves exactly as before.
218
-
219
- - [#7895](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7895) [`90451af`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/90451afcc7c264a0c5de7d239edcfbdefcf28f64) Thanks [@samuelhenry](https://github.com/samuelhenry)! - A lead write can be retried safely ([#7869](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7869)), the schema half.
220
-
221
- - `@working-theory/database` — `Lead` gains `idempotencyKey` (`leads.idempotency_key`), a nullable text column with a unique index over `(workspace_id, idempotency_key)`. The migration `20261008130000_lead_idempotency_key` is purely additive: one nullable column with no default and one unique index, so no backfill runs and no existing row changes (NULLs are distinct under the index). Deploy it before the API that writes the column.
222
-
223
- ### Patch Changes
224
-
225
- - Updated dependencies [[`d3f8ac6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d3f8ac6bd41959f23a1f5f591e3cccce42895cd0), [`c979e93`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c979e93a593606bfe47e815f29eef9e17be7e329), [`6efec95`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6efec954914e40acbf42db1e0132569e983c3915)]:
226
- - @working-theory/validation@0.37.0
227
-
228
- ## 0.36.0
229
-
230
- ### Patch Changes
231
-
232
- - Updated dependencies [[`14119fa`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/14119fac22bf0c26973d9286a74bced761ed1218), [`2475b60`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2475b608d65880d9986d94628494509faedd0cd9), [`7fdf60d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/7fdf60de18d86d878f5e567d6df5c2e0d64d97eb), [`47eeb95`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/47eeb958390f2eadd7b0c43a47c46fbbd1309872), [`4609e76`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4609e7640798c53c730b7b9f0e723df1300ca379), [`91c5f56`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/91c5f56121d0efe475f918c493ed4245834d9e7f), [`994094f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/994094f77619b8b0ff79688b24d7befb4b1b29fa)]:
233
- - @working-theory/validation@0.36.0
234
-
235
- ## 0.35.0
236
-
237
- ### Minor Changes
238
-
239
- - [#7671](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7671) [`25d4a69`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/25d4a699cefaac7cf9c73dafa802696ebdc995e8) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The agent seat, step A ([#3591](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/3591), PR-A of docs/specs/3591-tenant-scoped-agent-auth-secure-spec.md).
240
-
241
- - `@working-theory/database` — a new `auth` model, `Agent`, and its enum `AgentPermissionLevel` (`member`): a stored delegate of one person, bound to one workspace, keeping only the SHA-256 digest of its key. The migration `20261005120000_agents` is purely additive: one table, its indexes, the ADR-0031 `agent_` primary-key CHECK and format CHECKs on every reference column. Deleting the organization, the workspace or the person's membership deletes the agent; deleting the membership of the person last shown its key clears `key_issued_to_membership_id`.
242
- - `@working-theory/ids` — registers the `agent_` prefix and exports `zAgentId`.
243
-
244
- ### Patch Changes
245
-
246
- - Updated dependencies [[`589b167`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/589b167dcd5acb83cb37b46bd5cdb0a57a80df1a), [`25d4a69`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/25d4a699cefaac7cf9c73dafa802696ebdc995e8), [`0fb0f37`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/0fb0f3727db9ad32776b88f39ec8b0943671bcad), [`a6833f9`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/a6833f940da064c36f3150a4af614c9fd8b38628)]:
247
- - @working-theory/validation@0.35.0
248
- - @working-theory/ids@0.10.0
249
-
250
- ## 0.34.1
251
-
252
- ### Patch Changes
253
-
254
- - [#7566](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7566) [`64a3245`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/64a324556595861b42166a49d98a4c73cef5115a) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `build` runs `prisma generate` first and always re-emits `dist/client` ([#7565](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7565)), so a stale or skipped generated client can no longer be built into a release. Before this, `build` was `tsc -b` alone: it never regenerated the client, and `tsc -b` trusted `tsconfig.build.tsbuildinfo`, so `database@0.14.0` shipped without `FlowCheckout` and `database@0.34.0` without `Spoke`, `SchedulingConnection` and `AppointmentOrigin`. `db:generate` is now `pnpm run build`, so it still generates and builds, once.
255
-
256
- - Updated dependencies [[`4df3e2c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4df3e2cd0f4d22471f7422ada4018040ecca402b)]:
257
- - @working-theory/ids@0.9.1
258
- - @working-theory/validation@0.34.1
259
-
260
- ## 0.34.0
261
-
262
- ### Minor Changes
263
-
264
- - [#7544](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7544) [`aeefe93`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/aeefe93ea62d4b1c96da18f07b8a68674923e091) Thanks [@samuelhenry](https://github.com/samuelhenry)! - A hub API can register its spokes, and a spoke's public reads and writes resolve to its own workspace ([#7532](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7532)).
265
-
266
- - `@working-theory/database`: two new tables. `spokes` (auth) binds one spoke to one workspace and stores the SHA-256 digest of its hub-minted key, never the key. `appointment_origins` (inbox) records which workspace a booking made through a spoke belongs to. Migration `20261003120000_spoke_registry` is purely additive.
267
- - `@working-theory/ids`: two registered prefixes, `spoke` and `apptorg`.
268
- - `@working-theory/api-client`: `get`, `post` and `patch` send `AILK_SPOKE_KEY` as `x-ailk-spoke-key` on server-side calls over `https:` or loopback only, and refuse to follow a redirect while they carry it. With the variable unset, every call is unchanged. `isSafeTransport`, `LOOPBACK_HOSTS` and `SAFE_HEADER_TOKEN` move from `leads.ts` into `http.ts`.
269
-
270
- - [#7547](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/7547) [`d519d9f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d519d9ff7db3059375842d0729c482f94f74a13d) Thanks [@samuelhenry](https://github.com/samuelhenry)! - A scheduling connection per workspace ([#7533](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/7533)): each workspace can read and receive bookings through its own scheduling provider account.
271
-
272
- - **`@working-theory/database`** — new `SchedulingConnection` model (`scheduling_connections`, config namespace): one row per workspace holding the provider id, the credential and the webhook secret as AES-256-GCM ciphertext, an optional base URL and a unique webhook routing token. Migration `20261003130000_scheduling_connection`.
273
- - **`@working-theory/ids`** — registers the `schconn` prefix for the new model.
274
- - **`@working-theory/validation`** — `SchedulingProviderIdSchema` and the strict `SchedulingConnectionInputSchema` (`{ provider, apiKey, baseUrl? }`; the key is printable ASCII with no whitespace or control byte).
275
- - **`@working-theory/admin`** — the Meetings "not connected" state gains a Connect form for owners, showing the webhook URL and one-time secret to paste into the provider.
276
- - **`create-ailk`** — the `scheduling` slice carries the new connection and resolution files and their suites.
277
-
278
- ### Patch Changes
279
-
280
- - Updated dependencies [[`84c8f52`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/84c8f5206f1393f079ae2e542f352c03c3605488), [`a83dca7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/a83dca7cb2d327f990e53154fcfca9be2268dc8a), [`aeefe93`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/aeefe93ea62d4b1c96da18f07b8a68674923e091), [`d519d9f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d519d9ff7db3059375842d0729c482f94f74a13d), [`8f835bb`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8f835bbc57059acfef157ffc60a5b250be6981e7)]:
281
- - @working-theory/validation@0.34.0
282
- - @working-theory/ids@0.9.0
283
-
284
- ## 0.33.0
285
-
286
- ### Patch Changes
287
-
288
- - Updated dependencies [[`bf2c0a7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/bf2c0a722c08974f6a199e9f8bf3d837a100be58)]:
289
- - @working-theory/validation@0.33.0
290
-
291
- ## 0.32.0
292
-
293
- ### Patch Changes
294
-
295
- - Updated dependencies []:
296
- - @working-theory/validation@0.32.0
297
-
298
- ## 0.31.0
299
-
300
- ### Patch Changes
301
-
302
- - Updated dependencies [[`9ee4e93`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/9ee4e93b52ff57d23bc6f9b5c49ac7b2a742413c)]:
303
- - @working-theory/validation@0.31.0
304
-
305
- ## 0.30.0
306
-
307
- ### Patch Changes
308
-
309
- - Updated dependencies []:
310
- - @working-theory/validation@0.30.0
311
-
312
- ## 0.29.0
313
-
314
- ### Patch Changes
315
-
316
- - Updated dependencies [[`dc86291`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/dc862915d1700d8566e3ca82591128e31a7570a9), [`346c3c1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/346c3c1e8c405ead3080a2f7f6a828fee6d132a9), [`1dfc83e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/1dfc83ec63e5dc6e862b131b14af2735f4914eb6), [`6ccd87d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6ccd87dbd56df3b886584b215f101af7e2fd68c4)]:
317
- - @working-theory/validation@0.29.0
318
-
319
- ## 0.28.0
320
-
321
- ### Patch Changes
322
-
323
- - Updated dependencies [[`8955dbe`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8955dbe57b720ed516858d2373cc1bba158612e1), [`8a786be`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8a786be9e7f6292d7aee52891bbe3185508cf65e), [`c1b4538`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c1b4538d1faafb6c9fd9e6376430cd58548e0959), [`ea782e2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ea782e29a4867af89d76ad4359f501ed04bea0e9), [`491c3ff`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/491c3ff4719abdc614fc87ef5943c760c2e8fc7b)]:
324
- - @working-theory/validation@0.28.0
325
-
326
- ## 0.27.0
327
-
328
- ### Patch Changes
329
-
330
- - Updated dependencies [[`95287bd`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/95287bd24f4be6261f848e5228ccd18f47f06ebc), [`e4df16e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e4df16eafaf17657cdcacb950853b6e9e61315ca), [`72472c0`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/72472c018cdd6263585c5cc1c653aebc487bb9e0)]:
331
- - @working-theory/validation@0.27.0
332
-
333
- ## 0.26.0
334
-
335
- ### Patch Changes
336
-
337
- - Updated dependencies []:
338
- - @working-theory/validation@0.26.0
339
-
340
- ## 0.25.0
341
-
342
- ### Minor Changes
343
-
344
- - [#5813](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5813) [`518c590`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/518c59023876a0212504ace9a683084df0168be6) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Generalize `Artifact` into the workspace's content store, and add `Asset` ([#5800](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5800), roadmap D1/D7).
345
-
346
- `artifacts.session_id` was `NOT NULL` behind an `ON DELETE CASCADE`, so deleting an agent session deleted every artifact it had produced. It is now nullable behind `ON DELETE SET NULL`: the session is provenance, the workspace owns the artifact. Beside it, four columns the content store needs — `content_type` (the discriminator; `text/page` is what the editor writes), `locale` (defaulting to ADR 0019's `product.default_locale`), `slug` (NULL until publish) and `published_version_id`. `(workspace_id, content_type, locale, slug)` is unique and `(workspace_id, content_type, updated_at)` is the list index. `published_version_id` is a plain pointer, never a relation and never `is_current`, which remains the draft tip and is never the publish mechanism.
347
-
348
- `content_type` is ADDITIVE beside the existing `type` column rather than a rename: `apps/api/src/routes/workspaces/sessions.ts` reads `type` and keeps working unchanged. The migration backfills `content_type` from `type`, so the two agree row-for-row; new code reads `content_type`.
349
-
350
- `Asset { workspaceId, key, filename, contentType, bytes, size }` follows the inbox namespace's `DeliverableAsset` precedent — bytes in the row, no new infrastructure — with `(workspace_id, key)` unique and a relation-free `workspaceId` (ADR 0009 invariant 1). `@working-theory/ids` registers its `asset_` prefix (ADR 0031 rule 3) and exports `zAssetId`.
351
-
352
- The migration brackets the FK relaxation with zero-row assertions — no row already NULL and no orphan before the swap; no row lost, no row nulled and no `content_type`/`type` drift after it — so it applies to an empty database and to a populated one, and aborts rather than backfilling past a surprise.
353
-
354
- - [#6139](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6139) [`9f45297`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/9f4529701aaf2f56acbd2be416e8a8c17358e1aa) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Appointments from Cal.com webhooks ([#6085](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6085), brief H7).
355
-
356
- Adds `POST /v1/webhooks/calcom` — a signed receiver (HMAC-SHA256 over the raw
357
- body, `x-cal-signature-256`) that normalizes six `BOOKING_*` trigger events
358
- into a new `Appointment` row, guarded by three independent per-family
359
- watermarks (lifecycle / payment / no-show) and a 15-minute replay window —
360
- and `GET /v1/schedule/appointments`, a tenant-guarded, `owner|admin`-floored
361
- read of the site's own appointments, scoped strictly to
362
- `tenant.workspaceId` (never `currentSiteId()`, never a platform-operator
363
- escape hatch).
364
-
365
- `@working-theory/database` gains the `Appointment` model
366
- (`database/inbox/schema.prisma`) and its migration.
367
- `@working-theory/ids` registers the `appointment` → `appt` prefix (ADR-0031
368
- rule 3). `@working-theory/validation` gains `AppointmentSchema`,
369
- `AppointmentListSchema`, `listAppointmentsInputSchema` /
370
- `listAppointmentsOutputSchema`, and the inbound Cal.com webhook envelope
371
- schemas. `@working-theory/api-client` gains `schedule.appointments()`.
372
- `create-ailk` adds the receiver + read + service files (and their tests) to
373
- the `scheduling` module's `ownedFiles` — a keyless scaffold is unaffected;
374
- a `--modules scheduling` scaffold now carries the new surface.
375
-
376
- - [#6118](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6118) [`8b20866`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8b20866470f5aa3ef9fbbba1d11e4fc3b998da86) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `Asset` gains three columns the lightbox edits in place ([#6092](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6092), S4/D10): `title String?`, `description String?`, `tags String[] @default([])`.
377
-
378
- `title` and `description` are nullable with no default — `NULL` means the owner has not written one, distinct from an empty string meaning they cleared it, and neither is backfilled from `filename`. `tags` is non-null with an empty-array default: an untagged asset is an empty set, not an unknown one. The column stores tag SLUGS (`ad-creative`, `workspace-memory`, …), never the human labels a surface renders them as, and is deliberately unconstrained — the asset vocabulary and the document vocabulary (a document is a row in this same store) ride the one column, and a fixed set is a UI affordance, not a database constraint.
379
-
380
- Delivered by one additive migration, `20260918120000_asset_metadata_columns` — no column dropped or renamed, no value backfilled, the `(workspace_id, key)` identity and the `asset_` UUIDv7 CHECK untouched. An `INSERT` naming none of the three columns still succeeds.
381
-
382
- - [#6202](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6202) [`b85e147`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/b85e147d0d26150eb1a00e1933df138087727628) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `FlowDefinition` and `FlowSession` gain a nullable `workspaceId` column, backfilled 1:1 from `siteId` ([#6155](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6155)).
383
-
384
- The literal alias `"default"` resolves to the seeded sentinel workspace; every other alias resolves only by exact `workspaces.id` equality. A row whose `siteId` matches no workspace is left `NULL` — unset, never guessed — and stays invisible to every tenant-scoped read rather than visible to the wrong one. `siteId` is unchanged and the public flow engine keeps resolving it; nothing about the request or response shape of `/v1/flows/*` or either MCP flow tool changes.
385
-
386
- `database/tenancy.ts` also gains `resolveSentinelWorkspaceRow(prisma)` — the sentinel-existence sibling of `resolveDefaultWorkspaceRow`, carrying no `workspace.count()` gate, so a correctly-configured multi-workspace deployment that has not pinned `AILK_SITE_ID` still resolves the `"default"` alias.
387
-
388
- - [#6218](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6218) [`80f498e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/80f498e3dcd3d70931045dc376c293c0c9a88c65) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `FlowDefinition` gains four operator-facing columns — `kind`, `title`, `landingPage`, `status` ([#6156](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6156)) — backfilled for every existing row by a structural rule (never from slug), with the visitor-facing `config` left byte-identical.
389
-
390
- `status` (`draft` | `live`) carries NO column default and is backfilled `'live'` — every row that exists today is already serving, and a silent default would make publication the thing that happens when a future writer says nothing. `title` is likewise `NOT NULL` with no default, backfilled from `slug`. `kind` (`special-report` | `diagnostic` | `listicle` | `waitlist` | `contact` | `newsletter`) keeps its column default (`'contact'`) and is reclassified only where the row's own structure (a projected listing, a recommending-mode config, a `deliverables` block) says otherwise. `landingPage` is nullable with no backfill — a magnet has three public addresses, and NULL means the canonical route serves it.
391
-
392
- `@working-theory/validation`'s `flow.ts` gains `flowKindSchema` / `flowStatusSchema` / `flowLandingPageSchema` as standalone exports — never members of `flowConfigShapeSchema`, which stays `.strict()` and gains none of the four keys, so every stored `configSnapshot` keeps parsing unchanged.
393
-
394
- A `status` of `draft` refuses a NEW walk from starting (`resolveSession`'s definition branch) while a walk already in progress finishes on its pinned snapshot — the `sessionId` branch never re-reads the definition. `upsertFlowDefinition` supplies `kind`/`title`/`status` on CREATE only, never on UPDATE, so a re-seed or re-materialize can never overwrite what an operator later sets. The public routes and both MCP flow tools are unchanged.
395
-
396
- - [#6274](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6274) [`3bd8785`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/3bd87854c6589556426894720c85f54bf2daa801) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `ProjectListing` and `Lead` gain a nullable `workspaceId` column (`workspace_id`), indexed for a per-workspace list and backfilled from `siteId` for any existing row whose alias resolves to a real workspace ([#6203](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6203)). `tenantDb(tenant)` gains `projectListings` and `leads` read accessors, scoped by the injected `workspaceId` and never returning a row from another workspace. `siteId` stays the legacy alias, unchanged, on both models.
397
-
398
- - [#6280](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6280) [`2e7b0d2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2e7b0d2411944002104d5105edb6e8d59c8434c5) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `Lead` gains a nullable triage stamp — `handledAt` (`handled_at`) and `handledBy` (`handled_by`), the actor — plus a `(workspaceId, handledAt)` index for the Needs-you read ([#6204](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6204)). Existing rows are unaffected by the purely-additive migration and read as unhandled. `@working-theory/validation` gains `MESSAGE_LEAD_SOURCES` / `MESSAGE_LEAD_SOURCE_LIST` and `isMessageSource()` — the one closed allowlist declaring which `Lead.source` values are messages (a lead that needs an answer, operator decision Q1(a)), never a denylist and never a pattern test. `tenantDb(tenant).leads` gains `listUnhandledMessages` (bounded, workspace-scoped) and `markHandled` (an idempotent compare-and-swap), and `leads-inbox.ts` exposes the role-floored service pair over them. No route and no MCP tool — nothing new is reachable from this unit.
399
-
400
- - [#6360](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6360) [`2809d30`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2809d307d4d130541cb29ea7176b4af17e58679c) Thanks [@claudio-planck](https://github.com/claudio-planck)! - `Lead`, `ProjectListing`, `FlowDefinition`, `FlowSession` gain NOT NULL `workspaceId` plus a `CHECK (workspace_id = site_id)` equality constraint, and `WorkspaceSiteIdentity` gains `@@unique([id, workspaceId])` ([#6254](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6254), the tenancy-fence keystone).
401
-
402
- The issue's literal ask — a composite foreign key from the four fenced models to `WorkspaceSiteIdentity` — is not buildable against this tree: it crosses the `inbox` → `config` namespace boundary ADR-0009 forbids, `siteId` never holds a `WorkspaceSiteIdentity.id` (it holds the workspace id), and `WorkspaceSiteIdentity` is an optional per-workspace config blob whose required existence would break anonymous lead capture, a never-gate surface. The equality CHECK delivers the same guarantee — Postgres rejects a row whose `workspaceId` disagrees with its site — without a relation and without crossing the boundary; it is strictly tighter than the FK would have been. `docs/database/namespaces.md` documents the pattern for the fan-out ([#6255](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6255)–[#6260](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6260), [#6171](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6171), [#6314](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6314)), which land their own model changes into this same migration, `database/migrations/20260922120000_tenancy_fence`.
403
-
404
- `DeliverableGrant` (the fifth already-keyed model) is deliberately NOT touched — its `workspaceId` has no source column to derive from and `NULL` is the serve path's fail-closed sentinel; [#6257](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6257) fences it separately, at mint grain.
405
-
406
- Every write site that creates a `Lead`, `ProjectListing`, `FlowDefinition` or `FlowSession` row now derives `workspaceId` server-side from the resolved site alias (`apps/api/src/lib/site.ts`'s `resolveSiteWorkspaceId()` / `resolveWorkspaceIdForAlias()`), never from a request body. `routeLead`'s file-fallback no longer swallows a constraint violation into a silent success — it re-raises as a `persist_failed` error, while a genuine infrastructure outage still takes the file fallback unchanged.
407
-
408
- - [#6418](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6418) [`14dcb0f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/14dcb0fe7864a13f3fb9d573c303ddb8780dbdf5) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `ProjectListing` records the listicle magnet that captured it, so a magnet's Applications list can be scoped to its own submissions ([#6314](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6314)).
409
-
410
- Nothing constrains a workspace to one listicle-kind `FlowDefinition` — the model carries `@@unique([siteId, slug])` and no `@@unique([siteId, kind])` — so a workspace-only Applications list would silently show two listicle magnets' applications on both of their detail pages, with nothing to notice it. `ProjectListing` carried no reverse link to the magnet that captured it: the two pointers that existed (`FlowDefinition.listingId` and `ProjectListing.experimentKey`) are both written at APPROVAL time, when an approved listing is projected into its own diagnostic sub-flow, and name a different flow entirely.
411
-
412
- **`@working-theory/database`** — `ProjectListing` gains `capturedByFlowId String? @map("captured_by_flow_id")` and `@@index([workspaceId, capturedByFlowId])`. A plain scalar ref: no `@relation`, no foreign key, no `onDelete`, matching the intra-`inbox` convention every sibling reference on this model already follows (`leadId`, `listingId`, `grantId`, `flowSessionId` carry none, and all 24 foreign keys in the migration history target `auth`). Integrity rests on the server-side resolve and on the read carrying both scope terms; the column's own schema comment states that cost rather than arguing it away. Permanently nullable and **not** a backfill target — no existing row carries evidence naming the magnet that captured it, so every row written before this reads `NULL` for the life of the row: unattributed, absent from every per-magnet list, and unchanged in the workspace Inbox. `NULL` means "not attributed", never "attribution failed" and never "captured directly".
413
-
414
- **`@working-theory/validation`** — `projectListingStartSchema` gains one optional key, `capturedByFlowSlug: flowSlugSchema.optional()`. Additive on a `.strict()` schema, so every existing caller (the agent channel included) is accepted unchanged. It is a slug rather than an id because no public surface hands a visitor a `flow_<uuidv7>`; the server resolves it against the already-resolved `siteId`/`workspaceId` plus `kind: "listicle"` and stores the id it finds. A slug that resolves to nothing — naming no magnet, another workspace's magnet, or a non-listicle magnet — writes `NULL` and still returns `201`: this is a never-gate anonymous route where a refused body is a lost application, and a distinguishable error would make it a cross-workspace magnet-slug oracle. The operator's signal is a PII-safe server-side log line instead.
415
-
416
- - [#6383](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6383) [`e71eb5d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e71eb5d0d5796732e19dfab7768048a1009ef66d) Thanks [@claudio-planck](https://github.com/claudio-planck)! - **breaking** — the tenancy fence fan-out: thirteen models gain a required `workspace_id`.
417
-
418
- `Subscriber`, `Callback`, `ConsentGrant`, `Appointment`, `DeliverableAsset`,
419
- `FlowCheckout`, `WaitlistExperiment`, `WaitlistScore`, `WaitlistFollowUpSend`,
420
- `PlaybookInstance` and `SiteListingConfig` each gain a NOT NULL
421
- `workspaceId String @map("workspace_id")`, an `@@index([workspaceId])`, a
422
- `<table>_workspace_id_format` CHECK and a
423
- `<table>_workspace_site_agree CHECK (workspace_id = site_id)`. Every
424
- `create`/`upsert` of these models must now supply `workspaceId`, and it must
425
- equal the row's `site_id` — a server-resolved workspace id, never a value read
426
- from a request body.
427
-
428
- Two models carry no `site_id` and take a different shape:
429
-
430
- - `ListingCsvSend` gains NOT NULL `workspace_id` plus the format CHECK only —
431
- no equality CHECK and no foreign key. It is backfilled and stamped from the
432
- parent `ProjectListing`.
433
- - `SiteSetting` gains NOT NULL `workspace_id`, and **its unique key moves from
434
- `key` to `(workspaceId, key)`** — `key` alone is no longer unique, so
435
- `siteSetting.findUnique`/`upsert` must pass the compound
436
- `workspaceId_key` selector. Existing rows backfill to the sentinel
437
- workspace, and every `key` string is left verbatim.
438
-
439
- `DeliverableGrant.workspaceId` stays **nullable** — NULL remains the serve
440
- path's fail-closed sentinel for a legacy grant — but gains a NULL-tolerant
441
- `CHECK (workspace_id IS NULL OR workspace_id = site_id)`, and both mint sites
442
- now stamp it.
443
-
444
- Per [#6254](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6254) AC-1 this lands as an amendment to the single M32 migration
445
- `20260922120000_tenancy_fence` rather than a new migration directory. The
446
- amendment is a no-op on a database that already applied that migration, which
447
- is safe here under the operator's 2026-09-20 disposition that no persistent
448
- database carries state that must survive (spec § 1.5); if that ever stops
449
- holding, the SQL moves verbatim into a new migration directory and nothing
450
- else changes.
451
-
452
- - [#5939](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5939) [`0d2a2b5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/0d2a2b54eb622a904d4a8b80c31a495651ef19e7) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Add the shared one-workspace resolution predicate to the `./tenancy` subpath ([#5876](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5876)).
453
-
454
- `resolveDefaultWorkspaceRow(prisma)` and its structural `WorkspacePredicateClient` type join the sentinel constants already exported there — the deployment-level predicate `apps/api/src/services/default-tenant.ts` and `apps/mcp`'s new tenant resolution both delegate to, so the one-workspace check exists exactly once in the repository (NFR-7). Additive: no existing export changes shape.
455
-
456
- ### Patch Changes
457
-
458
- - [#6172](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6172) [`20bab3b`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/20bab3ba318e4ecb8ae7489e4ad638808a3a165d) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Fix `Appointment.noShow` — restore its `@map("no_show")`, matching every sibling field on the model and the column the `20260918120000_add_appointment` migration actually creates ([#6162](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6162)).
459
-
460
- Without the mapping, Prisma's generated client targeted the literal column `noShow`, which the live database does not have — every `prisma.appointment.create()` (and any other read/write touching this field) failed at runtime with `The column noShow of relation appointments does not exist in the current database.` No schema shape changed and no migration is added; this restores the field's intended, already-migrated column target. A new `database/__tests__/appointment.db.test.ts` proves the round trip against a live migrated database, and `tools/check-prisma-migration-drift.ts` — a new preflight check — fails when a Prisma schema field/model's implied column/table name disagrees with what the migration history actually creates, catching this exact class before merge.
461
-
462
- - [#6367](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6367) [`d3f599e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d3f599e1f1cadd3d998b92514231b0b4b7b7f77c) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `ProjectListing.consentAt` now declares `@db.Timestamptz(3)`, matching the `TIMESTAMPTZ` column its migration (`20260909180000_listing_draft_and_fields`) actually created ([#6171](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6171)). The Prisma schema previously declared this legal-consent timestamp as a plain, timezone-naive `DateTime`, which Prisma defaults to `TIMESTAMP(3)` on Postgres — a drift between the schema's declared type and the live column's real type. No migration is needed; the column already exists as `TIMESTAMPTZ`.
463
-
464
- - [#6224](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6224) [`454edc7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/454edc7bb960666c57b7f2651f644b3788194698) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Add the enabled-meeting-slugs gate ([#6183](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6183) S9b) — the operator's control over which meeting types the site's OWN PAGES publish.
465
-
466
- A fourth workspace site-config blob, `MeetingsSchema` (`enabledSlugs`, beside `ThemeSchema`/`SiteIdentitySchema`/`SEOSchema`), reads and writes through a new route, `GET|PUT /v1/workspaces/:workspaceId/meetings` (`apps/api/src/routes/workspaces/meetings.ts`) — a new route file and a new handler, but the SAME path shape, tenant guard and `{ok,data}` envelope as its three siblings, registered in its own scope gated on the `scheduling` module alone (its GET needs the scheduling provider seam, which a `workspace`/`multi-tenant`-only build does not carry). The write floor is `owner|admin`, matching every other publication-affecting write in this route family; the GET carries the SAME floor, since it echoes the deployment's provider catalog joined with which rows are enabled — a plain member should not read that. The GET also lists the scheduling provider's own bookable event types (`listEventTypes`, [#6182](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6182)), joined with `enabled: boolean`, so the Admin Meetings page can render a toggle list.
467
-
468
- A new anonymous route, `GET /v1/schedule/meeting-types`, is what lets the public `/meet` surface — which holds no session — honour the gate at request time for its OWN two pages: `/meet/[slug]` now 404s a disabled slug (gating both the page and `generateMetadata`, so a disabled event's title/description never reach the document head), and `/meet` lists the enabled set rather than a single configured link, titled from one batched `event-meta` read. An unconfigured deployment falls back to the singleton `SCHEDULING_CAL_LINK` already advertises, so no shipped page goes dark on upgrade. Both pages are `force-dynamic`: enabling or disabling a slug takes effect on the next request, no deploy.
469
-
470
- **This is a publication gate on this site's own pages, not an authorization boundary on the provider.** The three anonymous scheduling routes — `POST /v1/schedule/book`, `GET /v1/schedule/availability`, `GET /v1/schedule/event-meta` — are unchanged and still accept any `calLink` naming ANY event the provider knows about, disabled or not; none of them consults `enabledSlugs`. A disabled event's own page on this site 404s, but the event is still bookable at the provider's own public page and through those three routes directly, and nothing this repo can change alters that. Gating them would change a fenced scheduling-route contract this unit does not touch, and would not close the provider's own page regardless.
471
-
472
- - [#6407](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/6407) [`87535c1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/87535c162654d76af314395eb55e87bd0ef96021) Thanks [@samuelhenry](https://github.com/samuelhenry)! - `database/inbox/schema.prisma` drops the 'PLACEMENT IS A HARD REQUIREMENT' comment blocks ([#6261](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/6261)).
473
-
474
- Comment-only: no model, field, mapping, index or migration changes, so the generated client is byte-identical. The blocks documented a workaround for the tenant-scope drift guard's old model-body collector, which matched `/model\s+(\w+)\s+\{([^}]*)\}/` and stopped at the first closing-curly CHARACTER — including one written inside a doc comment — and so forced `workspaceId` to be declared above any comment that might contain one.
475
-
476
- The reader behind that guard now lives in `tools/lib/tenant-scope-schema.ts` and parses model bodies by brace DEPTH, outside `//` and `///` comments and outside double-quoted strings. Field placement no longer carries meaning for it, so the per-field 'DO NOT MOVE this field' clauses that referenced the blocks go with them. No field moved.
477
-
478
- - Updated dependencies [[`8eadc43`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8eadc437285a0c0121c9f4750ff83dac9591729e), [`2666bf3`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2666bf3ed24324a37a51cfc5c68019ad5d26403e), [`94ebca8`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/94ebca8f3c1c9f3b744182c720e91417012ecc9b), [`518c590`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/518c59023876a0212504ace9a683084df0168be6), [`8f931f1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8f931f1af0d170fb743bf027634154cd53aa1db9), [`ecab283`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ecab283284d5f6a6ba4a2a08b018b077257de288), [`3bb6a93`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/3bb6a93f41c7dfd8d24ea017f5c403edaae03fcf), [`ab6b792`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ab6b79258a369ff909fa62d7bffca7fe264fe532), [`9e7df0d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/9e7df0d93343e126c7b058a66b71ad4dda8ae9e4), [`28f14b5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/28f14b50dfe29d2d9bf8e75aa368eb1ef3767d47), [`9f45297`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/9f4529701aaf2f56acbd2be416e8a8c17358e1aa), [`80f498e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/80f498e3dcd3d70931045dc376c293c0c9a88c65), [`454edc7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/454edc7bb960666c57b7f2651f644b3788194698), [`2e7b0d2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/2e7b0d2411944002104d5105edb6e8d59c8434c5), [`6d061a0`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6d061a0cd48baec20899cec2962ff6877addaa85), [`14dcb0f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/14dcb0fe7864a13f3fb9d573c303ddb8780dbdf5), [`f917f0b`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/f917f0b182ea8daf657b4762551ea5e86fc90616)]:
479
- - @working-theory/validation@0.25.0
480
- - @working-theory/ids@0.8.0
481
-
482
- ## 0.24.0
483
-
484
- ### Patch Changes
485
-
486
- - Updated dependencies [[`885adcb`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/885adcbfb23b032424d105942ac0085a03209208), [`c1fb87c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c1fb87cbf3ee7ca97951b272cdcdf48c0d1f3a37), [`0b71694`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/0b71694feb662a9686d85cf9478a0b703cc92805), [`6f98cfd`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6f98cfdef3ebd995dd1c812071cbe62ba4324f64), [`f2a92c5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/f2a92c585cd5e81fd146c78f65d6fcbca52f7bca), [`ea1e07d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ea1e07dde98d451325d9c0e49c1dad3d243c7a68)]:
487
- - @working-theory/validation@0.24.0
488
-
489
- ## 0.23.0
490
-
491
- ### Patch Changes
492
-
493
- - Updated dependencies [[`10a9fc9`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/10a9fc97455ecadb760c06d295965035b45aa605)]:
494
- - @working-theory/validation@0.23.0
495
-
496
- ## 0.22.1
497
-
498
- ### Patch Changes
499
-
500
- - Updated dependencies []:
501
- - @working-theory/validation@0.22.1
502
-
503
- ## 0.22.0
504
-
505
- ### Minor Changes
506
-
507
- - [#5412](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5412) [`e94f08c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e94f08cccfe6cb9d096b6746a092c1b6921677cf) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The founder application collects first name, last name and phone on step one, and records email verification when the emailed resume link is opened ([#5407](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5407)).
508
-
509
- **Migration: `20260914120000_listing_founder_identity`.** Five nullable columns on `project_listings` — `founder_first_name`, `founder_last_name`, `founder_phone`, `email_verify_nonce_hash` and `email_verified_at` — with no backfill and no change to any existing column. `founder_name` stays NOT NULL and stays the single-line DISPLAY name every existing reader reads; the parts sit beside it, exactly as [#5279](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5279) put the six address parts beside `address`. Composition runs one way only, so no existing row's `founder_name` is split by guessing.
510
-
511
- The platform's default contact screen now asks first name, last name, email, phone and consent. Phone is required by default and a site relaxes it with `questions: [{ id: "founder_phone", required: false }]`. A site that still asks for one "Your name" line keeps parsing untouched: the required `founderName` contract row is satisfied either by a question writing it or by the two parts that compose it.
512
-
513
- `POST /v1/project-listings` accepts `founderFirstName` / `founderLastName` / `founderPhone` and composes `founder_name` server-side; a body carrying only `founderName`, as every caller before this release sends, is accepted unchanged.
514
-
515
- New anonymous, credential-gated route `POST /v1/project-listings/drafts/:id/verify-email`, reached from `projectListings.verifyEmail(id, resumeToken, verifyNonce)`. It takes two credentials, and only the second carries the proof: the resume token is in `start`'s own 201 body, so it says only that you opened the draft, while the verification NONCE is minted at `start`, stored as a digest, and handed to nothing but the resume-email builder — it reaches the outside world only as the `?verify=` parameter of the emailed link. The route stamps `email_verified_at` write-once by compare-and-swap, so repeat openings answer the first stamp; a wrong token, a wrong nonce and an unknown draft all return the same `404 not_found` the other token-gated routes return.
516
-
517
- `ListingApplicationFlow` calls it once when it mounts with a `resume.verifyNonce`, and a failure never blocks the founder. A resume link with no nonce still resumes the draft and records nothing — which is also what a site that has not switched the resume email on gets, permanently, since no nonce is ever delivered there.
518
-
519
- `start`'s request and response shapes are unchanged: the nonce is never in a response body and never in a log line.
520
-
521
- `founder_phone` and `email_verified_at` are omitted from the public listing read. The operator sees both on the tenant dashboard row and in the decision/review payload, and the weekly CSV sweep's outcome log now says whether the address it mailed had been proved.
522
-
523
- ### Patch Changes
524
-
525
- - Updated dependencies [[`941db5d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/941db5d317b7332c3c5bb4134d0cc18f80678781), [`cbe99c2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cbe99c228200b4720b2f36af50c822a4bcca2275), [`e94f08c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e94f08cccfe6cb9d096b6746a092c1b6921677cf), [`f42b96b`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/f42b96b7489b5dae503b6c32e2045a14f382c583), [`4d28c33`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4d28c33978dde5cd33540813ec6317436a42a877)]:
526
- - @working-theory/ids@0.7.0
527
- - @working-theory/validation@0.22.0
528
-
529
- ## 0.21.0
530
-
531
- ### Patch Changes
532
-
533
- - Updated dependencies []:
534
- - @working-theory/validation@0.21.0
535
-
536
- ## 0.20.0
537
-
538
- ### Minor Changes
539
-
540
- - [#5282](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5282) [`49e6ba4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/49e6ba470a0ff4a0e6d4f7d14147232e90a12259) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Consent purposes and grants ([#5275](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5275)): a site declares its consent purposes once, any form renders them as real checkboxes with inline policy links, and every answer produces a durable record carrying the exact wording the person read.
541
-
542
- `@working-theory/validation` gains `consent-config.ts` — the per-site consent registry contract (`siteConsentConfigSchema`, `SITE_CONSENT_CONFIG_DEFAULTS`, `consentConfigFor`, `resolveConsentStatement`), following `SiteListingConfig`: a Zod-validated blob, platform defaults, and an unparseable blob that resolves to those defaults rather than to a failed form. A statement's links are markdown-shaped with a KEY target (`[Privacy Policy](privacy)`) resolved against the site's policy map, so a config string can never carry a URL or a scheme. `fieldInputTypeSchema` gains the `consent` kind, carrying `purposes: string[]` (ids only; `options`/`minLength` are refused on it). `projectListingStartSchema` keeps `consent: z.literal(true)` and gains an optional `consents: Record<purposeId, boolean>` and `locale`, so every existing caller (agent submission included) still parses. The listing application's contact step compiles its consent control as the `consent` kind (an optional `consentPurposes` list, defaulting to the platform's `service_terms`) instead of a `select` carrying one fake option.
543
-
544
- `@working-theory/ui` gains two blocks: `ConsentStatement` (parses `[Label](key)` tokens; an unresolvable key renders as plain text, never a dead link; no code path renders an href taken from the statement string) and `ConsentGroup` (one `Checkbox` per purpose, every box unticked on first render, each named and described by its statement via `aria-labelledby`/`aria-describedby`, posting under a flat `<field>.<purposeId>` name). `ContactFormFields` accepts `type: "consent"`; `FlowStepper` gates advance on required purposes only and sends one `"true"`/`"false"` per purpose (a decline is a value, not an absent key); both take an optional `consentConfig` that defaults to the platform registry. `ListingApplicationFlow` now sends the founder's real grants (`consents` + `locale`) instead of a hardcoded `consent: true`.
545
-
546
- `@working-theory/database` gains the append-only `ConsentGrant` model (`consent_grants`): subject as a type + id pair of plain scalars (no cross-namespace relation), declines stored as `granted: false`, the resolved statement denormalized with its hash and served locale, no `updatedAt` and no unique constraint on subject + purpose. The migration backfills one row per pre-existing listing marked wording-unrecoverable, stamped at the listing's own `consent_at`, and never touches `project_listings`.
547
-
548
- Additive: a flow, form, or site declaring no consent config renders and parses exactly as before. The one deliberate behavior change is the listing application's consent control.
549
-
550
- - [#5294](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5294) [`cf6b325`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cf6b325298e92d22ab7edfe8538f5ca17f54ebfd) Thanks [@claudio-planck](https://github.com/claudio-planck)! - The founder application becomes data ([#5285](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5285)): a published field contract, questions and screens as records, and override by exception.
551
-
552
- `@working-theory/validation` gains `listing-application-contract.ts` — the fields the platform actually READS, each with the call site that reads it, which of them a published listing cannot do without, and the control a question writing one must declare. Two beliefs the design carried did not survive that grounding and are recorded in the module header: there is no `FAQPage` emission for a listing in this tree, and no resume-link email. `listing-application.ts` gains the question record (an id, a control, copy, options, validation, and either a `writesTo` naming a contract field or a `siteAnswer` destination carrying a visibility flag), the screen record (its own copy, an ordered list of question ids, and its own side-panel declaration), merge-by-id so a site rewording one question inherits every other default including ones added later, and a parse-time invariant: exactly one question writes each required contract field, with zero and two both named failures. The compiler emits ONE step per screen carrying every field its questions contribute — the generalization of the `contact` and `faqs` cases, not a third mechanism. `listing-application-defaults.ts` ships a complete default question set and a grouped arrangement following combine-selection, separate-composition; it deliberately reverses the ships-no-copy discipline and says why.
553
-
554
- `@working-theory/ui` reaches two capabilities that already existed and were thrown away in one line. `ListingApplicationFlow` returned the live tile unconditionally on every step, ignoring the view `FlowStepper` handed it; a screen declares its own side panel now, and a screen declaring none renders a full-width question with `FlowFrame`'s side region collapsed. `FlowFrame` gains a side cell with the same padding, measure and centring the active cell's step card has, so side content no longer hand-rolls its own inset, and its side region gains `md:flex-1` — without it the region carried `md:w-1/2` against an active region carrying `flex-1`, so a caller's gap came out of the question column alone. `FlowStepper` measures the step card and sizes the side cell to the tallest card observed, never shrinking, capped at the VISIBLE slot height rather than the frame's declared `h-dvh` — a page mounting the frame below a header makes it taller than the viewport.
555
-
556
- `@working-theory/database` gains the bounded site-answers store on `ProjectListing`, and the logo columns become writable from the application.
557
-
558
- Additive, with two boundaries stated precisely. The flat `steps` config parses and compiles to the byte-identical `FlowConfig` — verified old-against-new on a fifteen-step config exercising every step kind — and `steps` is now optional, with a config declaring both shapes, or declaring `steps` as an explicit `undefined`, a named parse failure. What is NOT unchanged is the rendered frame: the side-cell container, the shared gap and the measured panel height are fixes to `FlowFrame` and `FlowStepper`, so they reach every consumer of those two components by design, not only the listing application.
559
-
560
- A site that overrides one question's copy and declares no `screens` inherits every other default and renders new defaults added later. A site that declares its own `screens` inherits new defaults into its question set but does not render them — declared screens are that site's statement of what it asks, and inserting a screen into a live form is not something an upstream release should do. A new default that writes a REQUIRED contract field still fails that site's config at parse, by name.
561
-
562
- The three fields the application gained — the two logo URLs and the requested window — are OPT-IN: they are excluded from the default collected-field mask, so adding them cannot widen what an anonymous caller may write on a site that never asked for them. A site that wants them names them.
563
-
564
- - [#5298](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5298) [`57b0b04`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/57b0b047eb3f04d40f0712a893c89415b742c7f5) Thanks [@claudio-planck](https://github.com/claudio-planck)! - A verified owner link on a listing ([#5295](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5295)): a founder who signs in can read their own submitted listings, and nobody else's.
565
-
566
- `@working-theory/database` gains `ProjectListing.ownerUserId` / `ownerLinkedAt` — plain nullable scalars with no cross-namespace relation, exactly the shape `Lead.promotedUserId` / `promotedAt` already has (ADR 0009 invariant [#1](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/1)). A listing carried `founderEmail` and `leadId` and no user link, so the only join available for "the listings belonging to this signed-in person" was a session's email against `founderEmail`. That string is typed into an anonymous form and proves nothing: two people who type the same address are two people, and the join hands one of them the other's submission. These columns are the ownership claim a read may actually join on.
567
-
568
- The link is stamped only when all three of these hold: the reconciling user's own email is VERIFIED; that verified address matches the row's `founderEmail`; and the row's site resolves to one of that user's own tenant workspaces. Any one failing writes nothing and returns a count rather than throwing — the reconciliation path would otherwise fail an unrelated request. The email comparison is exact equality against the same normalization the write path applies, deliberately not Prisma's `mode: "insensitive"`, which compiles to `ILIKE` and would make `_` and `%` in the caller's own address wildcards that capture a neighbour's row.
569
-
570
- A fourth condition has no counterpart in the lead service: the match must be UNAMBIGUOUS. Two strangers can type the same address into the anonymous form, and when they do nothing says which of the two un-linked rows is whose — so a row is claimed only when it is the only un-linked row carrying that address at its site, and an ambiguous group stays null. The cost is a founder who legitimately submitted two applications at one site, which the concurrent limit allows: neither is linked. That is the deliberate trade, because nothing in the data separates their second application from a stranger's first. The write also repeats `ownerUserId: null`, making it a compare-and-swap, so two concurrent reconciliation runs cannot transfer a row away from whoever claimed it first.
571
-
572
- Candidacy is also restricted to submitted rows — every stored status except `draft`. A draft is addressed by its resume token, which is cleared at submit, so the token and the owner link hand off to each other cleanly and a draft needs no link. It is also a security boundary: draft creation is anonymous with the quota enforced at submit, so a claimable draft would let one unauthenticated request either disclose a stranger's text or, under the ambiguity refusal, permanently block someone from claiming their own listing.
573
-
574
- `@working-theory/validation` gains `projectListingMeResponseSchema` — an array of the existing founder-facing `projectListingDraftSchema`, reused rather than forked because the audience is the same person that shape already serves. Nothing existing changes.
575
-
576
- No existing row is backfilled, now or later. Every row predates verification, so deriving a link from `founderEmail` would assert the thing nobody proved. A listing submitted by someone who never signs in stays null for the life of the row, which is a legitimate resting state rather than a backlog.
577
-
578
- Additive throughout. Both columns are nullable with no default; the new schema export is new; the operator's `owner|admin` floor on the existing tenant-scoped listing routes is unchanged, and the founder reads their own rows through the owner link rather than through a relaxed floor.
579
-
580
- - [#5283](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5283) [`a713ea7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/a713ea78c12c1dc2519b80831deed197a4f227b4) Thanks [@claudio-planck](https://github.com/claudio-planck)! - A structured `address` field type in the flow vocabulary, and structured address storage for listings ([#5279](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5279)).
581
-
582
- `AddressFieldset` has shipped since [#4395](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4395) and `StepFlow` has rendered it ever since, but `fieldInputTypeSchema` exposed six input types and `address` was not one of them — so a flow config could not name the composite, and the founder application collected a whole published business address in a single free-text box capped at 300 characters.
583
-
584
- `fieldInputTypeSchema` gains `"address"`. The two cross-field rules already beneath that enum cover the new member without a new clause: `options` is select-only and `minLength` is text/textarea-only, so an address field declaring either is a named parse failure rather than a silently discarded setting. `flowAddressValueSchema` and `composeAddressLine` are new exports — the first declares the six-part value an address field submits, the second composes the single-line display string from those parts. There is deliberately no function that runs the conversion the other way.
585
-
586
- `FlowStepper` reads, validates, gates, seeds and submits the composite against the six fixed keys `AddressFieldset` posts under, which is the handling `StepFlow` has carried since [#4395](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4395). Required means every required sub-control has a value rather than that a key named `address` is non-empty. `ContactFormFields` already rendered the type and is unchanged, as are `AddressFieldset` and `ADDRESS_COUNTRIES`.
587
-
588
- `ProjectListing` keeps `address` as the single-line display string and gains six nullable columns for the parts beside it. A new application composes its display string from the parts, server-side. An existing row keeps its display string exactly as the founder typed it and its parts stay null — no stored address is ever parsed, split, or rewritten, and the migration does not backfill.
589
-
590
- Every change is additive: a flow config that declares no address field parses, renders and submits exactly as it did before, and a listing carrying only the legacy free-text address reads unchanged.
591
-
592
- ### Patch Changes
593
-
594
- - Updated dependencies [[`49e6ba4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/49e6ba470a0ff4a0e6d4f7d14147232e90a12259), [`cf6b325`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cf6b325298e92d22ab7edfe8538f5ca17f54ebfd), [`767a35c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/767a35ca83155f774667ea3f7a10eb0ce1c094ab), [`57b0b04`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/57b0b047eb3f04d40f0712a893c89415b742c7f5), [`65989b4`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/65989b4dc6915bf37608475ed6409f98cd5945e2), [`a713ea7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/a713ea78c12c1dc2519b80831deed197a4f227b4)]:
595
- - @working-theory/validation@0.20.0
596
-
597
- ## 0.19.0
598
-
599
- ### Minor Changes
600
-
601
- - [#5266](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5266) [`911e452`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/911e452c13b45e7fba213ed34290c981cc1bf346) Thanks [@claudio-planck](https://github.com/claudio-planck)! - `ProjectListing` (`inbox` namespace) gains `submittedCopy`, `copyEditedAt` and `copyEditedBy`, with migration `20260911120000_listing_copy_edit_audit`. They back the operator's copy edit — the third review outcome beside approve and reject: `copyEditedAt`/`copyEditedBy` mirror the existing `decidedAt`/`decidedBy` audit pair and are re-stamped on every edit, while `submittedCopy` is written once, on the first edit only, and preserves the five published copy fields exactly as the applicant submitted them. Additive — every existing column, model and migration is unchanged, and a row with the three columns unset behaves as before. Consumers that vendor `apps/api` need this version: `apps/api/src/services/project-listings.ts` writes the new fields and `PATCH /v1/project-listings/:id/copy` is the route that calls it.
602
-
603
- ### Patch Changes
604
-
605
- - [#5204](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5204) [`c74fdba`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c74fdbaab253941b4f862ac0da845fab7c879d49) Thanks [@claudio-planck](https://github.com/claudio-planck)! - License/publication flip: adds `license: Apache-2.0` + a root `LICENSE` file and flips `publishConfig.access` from `restricted` to `public`, per the `commercial_tier: oss` disposition (`architecture.yaml`, A1 [#5075](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5075)) and ADR 0033. No behavior change.
606
-
607
- - [#5156](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5156) [`ddac6c1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/ddac6c1c05ff30765d78c69e8f298a35082202ef) Thanks [@claudio-planck](https://github.com/claudio-planck)! - `@working-theory/metadata`: `mcp-tool-catalog.ts` gains an optional `module` field per tool entry (set on the scheduling and content-write tools), consumed by `apps/mcp/src/server.ts` to gate registration when a paid module is excluded (S1, [#5088](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5088)). Additive — `McpToolCatalogEntry`/`McpToolRegistration` both keep every existing field.
608
-
609
- `database` and `@working-theory/ui`: comment-only path-reference fixes after the S1 workspace move, which relocated the workspace app under the paid tree — no behavior change.
610
-
611
- - Updated dependencies [[`6b76b3d`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/6b76b3d65e3b9cfb5cf8bfeb4309b9b8fb9c1345), [`23c7fd6`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/23c7fd601e48a37f3f210e130cb8dcd37899b9ab), [`c74fdba`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/c74fdbaab253941b4f862ac0da845fab7c879d49)]:
612
- - @working-theory/validation@0.19.0
613
-
614
- ## 0.18.0
615
-
616
- ### Minor Changes
617
-
618
- - [#5056](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5056) [`8d2b130`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8d2b1305aa08dde674d15214b9c546fbdc3c60d1) Thanks [@claudio-planck](https://github.com/claudio-planck)! - <!--
619
- MINOR, not MAJOR, and the changes below are still breaking. The published
620
- group is on the `0.y.z` initial-development line, where MAJOR is pinned at 0
621
- (claude-setup `rules/operating-policy.md` § Hard floors are the SemVer public
622
- API, D7; AILK `docs/decisions/semver-activation.md`). A literal `major` here
623
- would take the whole fixed group from 0.17.0 straight to 1.0.0 — a declaration
624
- that the API is stable, which is a positioning act and not something a
625
- changeset should perform as a side effect of describing breakage. [#5043](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5043) hit
626
- that trap and [#5045](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5045) records the lesson. Pre-1.0, a breaking change is a MINOR
627
- flagged breaking in the changelog, which is what the "**Breaking —**"
628
- paragraphs below do.
629
-
630
- `@working-theory/api-client` is NOT listed: it sits in `.changeset/config.json`'s
631
- `ignore` list and changesets refuses a changeset mixing ignored and
632
- non-ignored packages. Its version is bumped by hand in this repo (the [#5013](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5013) /
633
- [#5036](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5036) precedent). Its change is described below anyway, because the
634
- description is what a consumer reads.
635
- -->
636
-
637
- The consumer half of project listings ships: a mountable founder application, its previews, its shelves and its card ([#5048](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5048))
638
-
639
- Project listings shipped backend-only. After [#5036](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5036) replaced one anonymous POST
640
- with a three-call resumable-draft protocol, every consuming site had to
641
- hand-write three proxy routes, a form that saved on each advance, and a
642
- decision about where a bearer credential lives. That is a platform capability,
643
- not per-site plumbing, and this is it.
644
-
645
- **`@working-theory/ui` — the mountable surface.** `ListingApplicationFlow` is a
646
- new section: a site passes its own step config, its own copy and a draft
647
- client, and gets a resumable multi-step application with a live preview tile.
648
- It is NOT a new stepper — it configures `FlowStepper` ([#3957](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/3957)) and supplies an
649
- `onSubmitStep` that calls the draft protocol. Also new: `ProjectListingCard`
650
- and `ProjectListingShelves` (the two shelves and the tile),
651
- `ListingPrivacyNotice` (the per-listing disclosure, rendered on the flow where
652
- a visitor submits, naming the founder as the party collecting their data),
653
- `ListingTilePreview`, `ListingQuestionReview` and `ListingFullPreview`.
654
-
655
- Not one of these ships a founder-readable string. Every prompt, option label,
656
- button label, band label and privacy sentence is a required prop or config
657
- value.
658
-
659
- **`@working-theory/ui` — `FlowStepper` gains three additive props.**
660
- `customSteps` resolves a `custom` step's renderer, `initialStepKey` lands a
661
- resumed flow past the step that minted its draft, and `sidePanel`'s view object
662
- gains `answers` and `live` so a side region can render what the visitor is
663
- typing right now. Every existing caller compiles and behaves unchanged.
664
-
665
- **`@working-theory/validation` — the configuration contract.**
666
- `listingApplicationConfigSchema` is what a site supplies, and
667
- `compileListingApplicationFlow` turns it into a `FlowConfig`. Two ordering
668
- constraints are ENFORCED at parse time rather than documented: `contact` must
669
- be the first step (the draft is keyed on the identity it captures, so nothing
670
- can save before it), and a `preview` step must follow every step kind it
671
- previews (ordered earlier it has nothing to render). Both fail loudly.
672
-
673
- `flowStepSchema` gains one additive member, `custom`, carrying a `renderer`
674
- identifier the mounting surface resolves. Every existing flow config parses
675
- unchanged.
676
-
677
- **Breaking — the application payload names its site by a PUBLIC KEY, not a
678
- `siteId`.** `projectListingStartSchema` carries `siteKey` where it carried
679
- `siteId`, and the server resolves the site from it. A body-supplied tenant
680
- identifier is exactly what the consuming site's proxy route existed to prevent;
681
- resolving it server-side is what lets the proxy go away. The schema is
682
- `.strict()`, so a body still carrying `siteId` is refused with a 400 naming the
683
- unrecognised key rather than silently honoured. The anonymous public read moves
684
- from `?siteId=` to `?siteKey=` for the same reason — one identifier for the
685
- whole mountable contract. `SiteListingConfig` gains a nullable, unique
686
- `publicKey` column as the mapping, with an `AILK_LISTING_PUBLIC_KEY` env
687
- fallback so a single-tenant scaffold needs no config row.
688
-
689
- **Breaking — submit-completeness derives from the site's configured field set.**
690
- `projectListingSubmitSchema` validated a fixed roster. It cannot: steps are
691
- individually optional, so a field whose step a site never rendered was never
692
- asked for, and requiring it silently refuses valid applications naming
693
- questions the founder never saw. `buildProjectListingSubmitSchema(caps,
694
- collectedFields)` builds the schema instead, and `SiteListingConfig` gains
695
- `collectedFields`, defaulting to the full roster — so a site that has
696
- configured nothing behaves exactly as before. The set is read server-side and
697
- never from a request: a caller that could post its own required-field set could
698
- post an empty one.
699
-
700
- **Breaking — the word caps are a site's numbers.** Ten words of headline and
701
- twenty-five of one-liner were platform constants compiled into a regex.
702
- `SiteListingConfig` gains `wordCaps`, and
703
- `buildProjectListingDraftPatchSchema` / `buildProjectListingSubmitSchema`
704
- compile the rules from it. The defaults reproduce the previous constants
705
- exactly, so no existing site's behaviour changes.
706
-
707
- **`@working-theory/api-client` (0.6.0 → 0.7.0, bumped by hand).**
708
- `projectListings.startDraft` and `.resumeDraft` bind a draft's id and its
709
- caller-held resume token into one session. The token is never a cookie and this
710
- package touches no browser storage: the resume link is emailed and doubles as
711
- address verification (salessmyth/samhenry [#316](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/316) D6b), and an agent-mediated
712
- caller ([#5039](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5039)) cannot present a cookie at all. `start`, `patchDraft` and
713
- `submit` are unchanged.
714
-
715
- **No honeypot and no timing heuristic ships anywhere in this change.** Both
716
- were removed deliberately ([#316](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/316) D6b) because [#5039](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5039) opens an agent-mediated
717
- submission channel they would close.
718
-
719
- ### Patch Changes
720
-
721
- - Updated dependencies [[`8d2b130`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/8d2b1305aa08dde674d15214b9c546fbdc3c60d1)]:
722
- - @working-theory/validation@0.18.0
723
-
724
- ## 0.17.0
725
-
726
- ### Minor Changes
727
-
728
- - [#5035](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5035) [`63974f5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/63974f52d241db3179df7b263a3dc1430c3810c1) Thanks [@claudio-planck](https://github.com/claudio-planck)! - <!--
729
- `@working-theory/api-client` was listed here by [#5035](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5035) and has been REMOVED
730
- ([#5036](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5036)). It is in `.changeset/config.json`'s `ignore` list, and changesets
731
- refuses a changeset that mixes ignored and non-ignored packages — so as
732
- written this changeset could not be consumed at all, and `changeset version`
733
- errored out before versioning anything. That would have blocked the very
734
- release this work is timed to ride. api-client's version is bumped by hand in
735
- this repo (the [#5013](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5013) precedent); its breaking changes are still described
736
- below, because the description is what a consumer reads.
737
- -->
738
-
739
- <!--
740
- MINOR, not MAJOR, and the changes below are still breaking. The published
741
- group is on the `0.y.z` initial-development line, where MAJOR is pinned at 0
742
- (claude-setup `rules/operating-policy.md` § Hard floors are the SemVer public
743
- API, D7; AILK `docs/decisions/semver-activation.md`, which puts the >=1.0.0
744
- hard-floor->MAJOR gate explicitly out of scope). A literal `major` here would
745
- take the whole 27-package fixed group from 0.16.0 straight to 1.0.0 — a
746
- declaration that the API is stable, which is a positioning act and not
747
- something a changeset should perform as a side effect of describing breakage.
748
- Pre-1.0, a breaking change is a MINOR flagged breaking in the changelog, which
749
- is what every "**Breaking —**" paragraph below does.
750
- -->
751
-
752
- Project listings become a platform feature: per-site window config, a five-state lifecycle, and a derived slug ([#5033](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5033))
753
-
754
- **Breaking — the apply payload no longer accepts `slug`.** `projectListingCreateSchema` is `.strict()`, so a payload still supplying one is a 400. The server derives the slug from `name` (lowercased, non-alphanumeric runs to hyphens, truncated to 48) and resolves collisions with a site-scoped numeric suffix; the created slug comes back in the 201 response, which is now the only place a caller learns it.
755
-
756
- **Breaking — the apply payload gains `requestedWindowDays`.** An applicant may request a listing window in whole days. The server clamps it against the site's own maximum instead of rejecting the application. The site's bounds are never representable in a request body.
757
-
758
- **Breaking — the status vocabulary changed.** `PROJECT_LISTING_STATUSES` is now `draft | requested | rejected | active | closed`, replacing `applied | approved | rejected | live | closed`. `closed` is computed from the listing's window end on every read and is never stored, so an expired listing cannot stay open because a scheduled job failed. Two new exports narrow what may be written: `PROJECT_LISTING_STORED_STATUSES` (the four persistable values) and `PROJECT_LISTING_DECISION_STATUSES` (`active | rejected`, the only transition targets).
759
-
760
- **Breaking — `backlinkUntil` is now `windowEndsAt`** on the row and the public read. The field bounds the whole listing rather than a backlink.
761
-
762
- **Breaking — `projectListingPatchSchema` changed shape** from a required `{ status }` over all five statuses to `{ status?, featured? }` with at least one field present, `status` narrowed to the two decision targets. `apiClient.projectListings.patch` takes `ProjectListingPatchInput` accordingly.
763
-
764
- **Added.** `siteListingConfigSchema`, `SITE_LISTING_CONFIG_DEFAULTS` and `clampWindowDays` in `@working-theory/validation`, backed by a new `SiteListingConfig` model keyed `siteId @unique` in the `config` namespace. The row and public read gain `featured`, `headline`, `logoMarkUrl` and `logoWordmarkUrl`; the logo columns ship nullable with no upload path.
765
-
766
- The ninety-day listing window that `apps/api` hardcoded was one consuming site's commercial terms. No duration constant remains in the published package outside the config schema's own defaults.
767
-
768
- ## The application becomes a resumable draft, and the listing carries the fields its page and tile render ([#5036](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5036))
769
-
770
- **Breaking — the single anonymous create is replaced by three operations.** `apiClient.projectListings.create` is gone. In its place: `start` (`POST /v1/project-listings` — the founder's name, email and a literal-`true` `consent`, returning `{ id, resumeToken }` at 201), `patchDraft` (`PATCH /v1/project-listings/drafts/:id` — merges a partial application and returns the merged row) and `submit` (`POST /v1/project-listings/drafts/:id/submit` — no body, returns `{ id, slug }`). All three answer with the API's `{ ok, data }` / `{ ok, error }` envelope on every path; the create they replace answered bare on success and enveloped on failure, so a client branching on `body.ok` read a successful apply as a failure. `projectListingCreateSchema` / `ProjectListingCreateInput` / `projectListingCreateResponseSchema` are replaced by `projectListingStartSchema`, `projectListingDraftPatchSchema`, `projectListingSubmitSchema` and their response schemas. The form the change exists for saves on every advance; a single terminal POST no longer describes it.
771
-
772
- **Breaking — validation moved from write-time to submit-time, so every application field on `projectListingSchema` is now nullable.** `slug`, `name`, `oneLiner`, `problem`, `product`, `commitment`, `teamComposition`, `faqs`, `anythingElse`, `address` and `questions` all read `T | null`. So does `leadId`: the `Lead` is written at SUBMIT rather than at start, because the founder's contact details are already captured on the listing row itself at step one, and `routeLead` sends an operator notification — which on an anonymous route meant a stranger could mail the operator by opening a draft they never finished. A draft is a legitimately incomplete row and only `submit` asserts completeness; a consumer that assumed a listing always carries a name must now handle the draft case. `submit` names the fields that are missing rather than reporting a generic failure.
773
-
774
- **Breaking — `patch`/`submit` are gated by a resume token.** `start` returns it once; only its sha-256 digest is stored, and lookup requires the listing id AND the digest, so a token is bound to one listing and grants access to no other. It travels in `Authorization: Bearer`, and `submit` clears it. There is no route that reads a token back.
775
-
776
- **Breaking — `PROJECT_LISTING_STAGES` and the `stage` field are gone.** `PROJECT_LISTING_PRODUCTS` and a `product` field replace them: `new-idea-written | wireframes | demo-video | working-prototype | live-no-users | live-some-users`. No shim translates the old four values — the ladders do not align rung-for-rung, so a silent translation would invent data. Existing rows are remapped once by the migration.
777
-
778
- **Breaking — `audience` is removed from the payload, the row and the public read.** No question feeds it any more; its guidance folded into `oneLiner`. Existing values are not migrated anywhere.
779
-
780
- **Breaking — `oneLiner` is word-capped, not character-capped.** It was `.max(160)`; it is now 25 words (with a 400-character backstop). `headline` becomes required at submit and is capped at 10 words alongside its existing single-line rule. What a tile has room for is a sentence, not a byte count.
781
-
782
- **Breaking — `ProjectListing.experimentId` becomes `experimentKey`.** `WaitlistScore` stores `experimentKey`, so a listing holding the experiment's id meant every listing-to-submissions read fetched the experiment purely to translate one into the other. The same string now sits on both sides.
783
-
784
- **Breaking — `WaitlistScore` is unique per `[leadId, experimentKey]`, not per `[leadId]`.** A visitor who joins two founders' waitlists is one lead with two scores; the old constraint permitted one, so the second write erased the first and a founder's CSV under-reported with no error raised. Overwrite-on-retake is preserved, scoped per experiment.
785
-
786
- **Added.** `@working-theory/validation` exports `segmentation.js`: `TEAM_COMPOSITIONS` (the canonical eight-value team-composition axis), `COMMITMENTS` (five values), their default label maps, and `TEAM_COMPOSITION_QUESTION_ID`. The application's `teamComposition` enum is the first six team values; the diagnostic renders the full list. A register is JSON and the constant is TypeScript, so neither imports the other and a test asserts the register's question-one values are a subset.
787
-
788
- **Added.** The row and the public read gain `commitment`, `teamComposition`, `faqs` (exactly three `{question, answer}` entries), `anythingElse`, `address` and `consentAt`. The founder's address is on the PUBLIC read deliberately: visitors answering that founder's diagnostic hand personal data to the founder, not the platform, and a per-listing privacy notice naming the collecting party cannot be built downstream without it.
789
-
790
- **Changed.** A `featured: true` listing is exempt from the computed `closed` status and may carry a null `windowEndsAt`; a non-featured `active` row with no window is a data error, logged and read `closed`. `computeListingStatus` takes the row's `featured` flag as a fourth argument.
791
-
792
- **Changed.** A founder may hold at most two listings in a non-terminal state (`draft`, `requested`, `active`) on one site. A third `submit` is refused with `listing_limit_reached`. Drafts count, or the limit is evaded by never submitting — but only for fourteen days, and `founderEmail` is lowercased before it is stored or counted. `founderEmail` is unverified on an anonymous surface, so an unbounded draft would let two anonymous requests lock a named founder out of applying permanently, and a case-sensitive comparison would let the limit be evaded by holding down shift.
793
-
794
- **Changed.** The project-listing diagnostic register resolves points by option VALUE rather than by a positional `q{n}:{i}of{k}` token. `LISTING_DIAGNOSTIC_SCORING` becomes `buildListingDiagnosticScoring(questions)`, and `listingOptionValue`, `LISTING_DIAGNOSTIC_ARITIES`, `LISTING_DIAGNOSTIC_OPTION_VALUES` and `listingDiagnosticQuestionOptions` are removed from `@working-theory/database/flows/listing-diagnostic`. Q5's urgency weights are now declared explicitly strongest-first, which corrects a scoring inversion the positional rule produced.
795
-
796
- **Changed.** `FlowDefinition` and `FlowSession` carry a nullable `listingId`. The link from a submission back to a listing was previously the coincidence that the generated flow's slug equalled the listing's slug; it is now stated. `upsertFlowDefinition` takes an optional third `listingId` argument.
797
-
798
- ### Patch Changes
799
-
800
- - Updated dependencies [[`933791e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/933791ef204baabed2038b9e66e5b4b09d3ed50c), [`63974f5`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/63974f52d241db3179df7b263a3dc1430c3810c1)]:
801
- - @working-theory/ids@0.6.0
802
- - @working-theory/validation@0.17.0
803
-
804
- ## 0.16.0
805
-
806
- ### Patch Changes
807
-
808
- - Updated dependencies []:
809
- - @working-theory/validation@0.16.0
810
-
811
- ## 0.15.0
812
-
813
- ### Minor Changes
814
-
815
- - [#5009](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/5009) [`19dbfa7`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/19dbfa77f0233c0591dc06c777fd2bfbb85910a8) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Add the project-listing diagnostic's shared scoring register and the
816
- `ListingCsvSend` model ([#5001](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/5001)).
817
-
818
- `database/flows/listing-diagnostic.ts` (exported as
819
- `@working-theory/database/flows/listing-diagnostic`, beside the existing
820
- `./flows/presets` subpath) is the ONE `WaitlistScoring` register every
821
- generated listing diagnostic shares: Q3–Q6 scored by option POSITION —
822
- `round(3·i/(k−1))` over a listing-independent `q{n}:{i}of{k}` option value —
823
- summed 0–12 into `now` (10–12) · `soon` (7–9) · `later` (4–6) · `curious`
824
- (0–3). Q1/Q2/Q7 and the extras carry no points.
825
-
826
- `ListingCsvSend` (`listing_csv_sends`, id prefix `lcsv_`) records one row per
827
- DELIVERED weekly founder CSV — `listingId`, `sentAt`, `rowCount`, `grantId` —
828
- and is the watermark the next sweep selects after.
829
-
830
- Additive: a new model plus a new export subpath, no change to any existing
831
- model, migration, or export. Consumers that vendor `apps/api` need this
832
- version — `apps/api/src/services/project-listing-flow.ts` imports the register
833
- and `listing-csv-sweep.ts` reads the new model.
834
-
835
- ### Patch Changes
836
-
837
- - Updated dependencies [[`e29589c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e29589c932e9d24bb84b7f0913ceac8e40d0fc36), [`d0f77a1`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/d0f77a1a175533eb90e31fa11c0ab6bb1b7f208e), [`3e3b63f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/3e3b63fe310abc6f0c1b8b315e51ef2670955c35)]:
838
- - @working-theory/ids@0.5.0
839
- - @working-theory/validation@0.15.0
840
-
841
- ## 0.14.0
842
-
843
- ### Minor Changes
844
-
845
- - [#4891](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/4891) [`4a41a0a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4a41a0a81bfbd8049771f289d577e236cffea6bf) Thanks [@claudio-planck](https://github.com/claudio-planck)! - Add the `FlowCheckout` model (`inbox` namespace, `@@map("flow_checkouts")`,
846
- `flchk_` ids) with migration `20260905230000_add_flow_checkout` ([#4837](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4837)) —
847
- the recommender's buyer record: one row per checkout attempt carrying the
848
- site, flow slug, experiment key, session, lead, offer key, the purchased
849
- configuration (seats / period / credit stop), the server's quote and its
850
- minor-unit amount + currency, the permalink, and the Stripe session /
851
- customer ids and `status` / `completedAt` the webhook stamps ([#4838](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4838)).
852
- Additive; no existing model or column changes.
853
-
854
- ### Patch Changes
855
-
856
- - Updated dependencies [[`4a41a0a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4a41a0a81bfbd8049771f289d577e236cffea6bf), [`4a41a0a`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/4a41a0a81bfbd8049771f289d577e236cffea6bf)]:
857
- - @working-theory/ids@0.4.0
858
- - @working-theory/validation@0.14.0
859
-
860
- ## 0.13.1
861
-
862
- ### Patch Changes
863
-
864
- - [#4746](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/4746) [`fbe5d42`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/fbe5d422bb96fc963c0f2132d7ac2416b4b1bdf0) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Rebuild + republish. The 0.13.0 tarballs were published from a stale `dist/` (the manual publish loop ran `pnpm publish` without `pnpm -r build`), so `@working-theory/validation`, `@working-theory/database` and others carry pre-[#4731](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4731)/[#4732](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4732) compiled output under the 0.13.0 version. No source change; this patch republishes every fixed-group package from a fresh build at `main`. Consumers pin `^0.13.1`.
865
-
866
- - Updated dependencies [[`fbe5d42`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/fbe5d422bb96fc963c0f2132d7ac2416b4b1bdf0)]:
867
- - @working-theory/validation@0.13.1
868
-
869
- ## 0.13.0
870
-
871
- ### Patch Changes
872
-
873
- - [#4739](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/4739) [`7fb762e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/7fb762eea3db575dada5569b53884b679707e7ef) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Add a changeset for FEAT-074 U3/U4a/U4b ([#4725](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4725), [#4727](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4727), [#4734](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4734)), which shipped
874
- without one. `waitlistExperimentConfigShapeSchema` (`waitlist.ts`) gains an
875
- optional `deliverables` block, and `compileWaitlistFlow` (`waitlist-compile.ts`)
876
- carries it into the compiled flow — a compiled waitlist flow may now declare
877
- deliverables. `@working-theory/database` adds the `PlaybookInstance` model
878
- (`inbox` namespace, migration `20260903010000_add_playbook_instance`,
879
- `@@map("playbook_instances")`) — the platform schema gains a `playbook_instances`
880
- table with `pbk_` ids, written append-only by targeting-maturity signup scoring.
881
- Both additive; an existing flow config or site-plan projection with no
882
- `deliverables` block is unaffected.
883
- - Updated dependencies [[`7fb762e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/7fb762eea3db575dada5569b53884b679707e7ef), [`93d14de`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/93d14de711e88d2768c38b97c0f88a0fb270193b)]:
884
- - @working-theory/validation@0.13.0
885
-
886
- ## 0.12.1
887
-
888
- ### Patch Changes
889
-
890
- - Updated dependencies []:
891
- - @working-theory/validation@0.12.1
892
-
893
- ## 0.12.0
894
-
895
- ### Patch Changes
896
-
897
- - Updated dependencies []:
898
- - @working-theory/validation@0.12.0
899
-
900
- ## 0.11.0
901
-
902
- ### Minor Changes
903
-
904
- - [#4693](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/4693) [`251003f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/251003f0ef26cf288c472f8cc4b5bf1818f7f085) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Extend the flow engine additively ([#4663](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4663) A3): per-step `showIf` branch
905
- predicates resolved by one shared pure resolver (`flow-visibility.ts`, used
906
- by both the engine and `FlowStepper`), derived + persisted session `flags`,
907
- `whenHidden` auto-answers for a hidden step, `multi`/`exclusiveValues`
908
- segmentation questions, a `url` field input type + `minLength`, and a fourth
909
- step type `aeo_score` that computes an AI-visibility score server-side inside
910
- its own invisible, auto-submitted step and persists it on `FlowSession`.
911
- `FlowStepper` gains opt-in back-navigation (`messages.goBack`), multi-select
912
- rendering, url autoformatting, and branch-aware progress. `compileWaitlistFlow`
913
- lifts its three prior refusals (`multi`, `showIf`, `exclusiveValues`) onto the
914
- extended grammar. Additive only — an existing linear flow with no `showIf`,
915
- `flags`, or `aeo_score` step is unaffected.
916
-
917
- - [#4673](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/pull/4673) [`cd23c21`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cd23c21e403abbad825bc794bc8c0d613325de01) Thanks [@samuelhenry](https://github.com/samuelhenry)! - Add the waitlist-experiment data model ([#4661](https://github.com/working-theory-labs/ai-launch-kit-internal/issues/4661) A1): the `waitlist.ts` register
918
- schemas (question set, scoring rules grammar, tracking, experiment config),
919
- `compileWaitlistFlow` in `waitlist-compile.ts`, an optional `experiment`
920
- binding block on `flowConfigSchema`, and the `WaitlistExperiment` +
921
- `WaitlistScore` Prisma models (`inbox` namespace) with their migration.
922
- Additive only — an existing flow config or site-plan projection with no
923
- `experiment`/`waitlistExperiments` block is unaffected.
924
-
925
- ### Patch Changes
926
-
927
- - Updated dependencies [[`251003f`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/251003f0ef26cf288c472f8cc4b5bf1818f7f085), [`48c7962`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/48c796243ee0f5c97440c1487737970a9d0124d3), [`e638747`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/e638747ab2ddfbae4ecfce14fd2f3ccf92523a3c), [`9a7fc2c`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/9a7fc2c129e095099f0be907a831190f24c9e7e3), [`cd23c21`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/cd23c21e403abbad825bc794bc8c0d613325de01), [`44e9795`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/44e9795dac30b9d6b87e57e33d81ce823a6c93da), [`fa5ece2`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/fa5ece2f86d5195988f69fe9568d9a06addc8e9d)]:
928
- - @working-theory/validation@0.11.0
929
- - @working-theory/ids@0.2.0
930
-
931
- ## 0.10.0
932
-
933
- ### Patch Changes
934
-
935
- - Updated dependencies [[`dd8cc0e`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/dd8cc0e46b042009f41915097b93c5737fcf80a0)]:
936
- - @working-theory/validation@0.10.0
937
-
938
- ## 0.9.0
939
-
940
- ### Patch Changes
941
-
942
- - Updated dependencies []:
943
- - @working-theory/validation@0.9.0
944
-
945
- ## 0.7.0
946
-
947
- ### Patch Changes
948
-
949
- - Updated dependencies []:
950
- - @working-theory/validation@0.7.0
951
-
952
- ## 0.6.0
953
-
954
- ### Patch Changes
955
-
956
- - Updated dependencies [[`3a10200`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/3a1020088c9df36d60f3539504c89dfe1cdd3827)]:
957
- - @working-theory/validation@0.6.0
958
-
959
- ## 0.5.0
960
-
961
- ### Patch Changes
962
-
963
- - Updated dependencies [[`b4a9e20`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/b4a9e20a9708f3f104f921511fce8ce56bcf3e2f)]:
964
- - @working-theory/validation@0.5.0
965
-
966
- ## 0.4.0
967
-
968
- ### Patch Changes
969
-
970
- - Updated dependencies [[`5c80fee`](https://github.com/Working-Theory-Labs/ai-launch-kit-internal/commit/5c80fee9ef52b5842fa5f62a682c14743032fb2e)]:
971
- - @working-theory/validation@0.4.0
972
-
973
- ## 0.3.0
974
-
975
- ## 0.2.0
976
-
977
- ## 0.1.3
978
-
979
- ## 0.1.2
980
-
981
- ## 0.1.1