create-ailk 0.19.0 → 0.20.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 (197) hide show
  1. package/README.md +64 -7
  2. package/dist/add-module.js +7 -2
  3. package/dist/cli.js +35 -0
  4. package/dist/copy.d.ts +41 -0
  5. package/dist/copy.js +87 -21
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/lib/fetch-template-snapshot.d.ts +21 -0
  9. package/dist/lib/fetch-template-snapshot.js +205 -0
  10. package/dist/lib/merge-three-way.d.ts +31 -0
  11. package/dist/lib/merge-three-way.js +65 -0
  12. package/dist/lib/scaffold-render-sweep.d.ts +23 -0
  13. package/dist/lib/scaffold-render-sweep.js +52 -0
  14. package/dist/module-architecture.js +64 -5
  15. package/dist/programmatic.d.ts +7 -1
  16. package/dist/programmatic.js +40 -3
  17. package/dist/site-roster.js +21 -4
  18. package/dist/spoke-checkout.d.ts +7 -0
  19. package/dist/spoke-checkout.js +8 -1
  20. package/dist/surfaces.d.ts +14 -0
  21. package/dist/surfaces.js +98 -3
  22. package/dist/template-record.d.ts +59 -0
  23. package/dist/template-record.js +183 -0
  24. package/dist/topology.js +29 -1
  25. package/dist/update.d.ts +48 -0
  26. package/dist/update.js +504 -0
  27. package/package.json +3 -3
  28. package/templates/.claude/cloudparity-repo-hooks.json +9 -0
  29. package/templates/.claude/hooks/architecture-check.sh +8 -0
  30. package/templates/.claude/rules/loop-contract.md +129 -0
  31. package/templates/.claude/settings.json +3 -2
  32. package/templates/.env.example +13 -0
  33. package/templates/CLAUDE.md +1 -1
  34. package/templates/CONVENTIONS.md +3 -2
  35. package/templates/_gitignore +162 -0
  36. package/templates/apps/api/.env.example +17 -1
  37. package/templates/apps/api/CLAUDE.md +18 -8
  38. package/templates/apps/api/package.json +2 -1
  39. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +41 -2
  40. package/templates/apps/api/src/__tests__/setup.ts +7 -0
  41. package/templates/apps/api/src/__tests__/stripe-boot.test.ts +132 -0
  42. package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +184 -0
  43. package/templates/apps/api/src/bin/rate-limit-probe.ts +53 -0
  44. package/templates/apps/api/src/lib/__mocks__/prisma.ts +8 -0
  45. package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +237 -0
  46. package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +334 -0
  47. package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +217 -0
  48. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +7 -0
  49. package/templates/apps/api/src/lib/consent-store.ts +335 -0
  50. package/templates/apps/api/src/lib/proposal-paid-store.ts +49 -0
  51. package/templates/apps/api/src/lib/rate-limit-probe.ts +165 -0
  52. package/templates/apps/api/src/lib/rate-limit-store.ts +142 -0
  53. package/templates/apps/api/src/lib/stripe.ts +97 -5
  54. package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +13 -4
  55. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +2 -0
  56. package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +220 -0
  57. package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +430 -0
  58. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +72 -14
  59. package/templates/apps/api/src/middleware/auth.ts +16 -4
  60. package/templates/apps/api/src/middleware/default-tenant.ts +9 -0
  61. package/templates/apps/api/src/middleware/rate-limit.ts +295 -82
  62. package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +167 -0
  63. package/templates/apps/api/src/routes/checkout/session.ts +3 -3
  64. package/templates/apps/api/src/routes/checkout/sessions.ts +6 -4
  65. package/templates/apps/api/src/routes/consent/cookie.ts +90 -0
  66. package/templates/apps/api/src/routes/consent/index.ts +18 -0
  67. package/templates/apps/api/src/routes/consent/unsubscribe.ts +127 -0
  68. package/templates/apps/api/src/routes/leads/index.ts +15 -0
  69. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +5 -0
  70. package/templates/apps/api/src/routes/webhooks/README.md +33 -5
  71. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +17 -4
  72. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +2 -0
  73. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +159 -0
  74. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +158 -0
  75. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +369 -0
  76. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +2 -0
  77. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +442 -0
  78. package/templates/apps/api/src/routes/webhooks/stripe.ts +201 -6
  79. package/templates/apps/api/src/server.ts +125 -18
  80. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +91 -0
  81. package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +503 -0
  82. package/templates/apps/api/src/services/__tests__/consent.test.ts +18 -3
  83. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +115 -4
  84. package/templates/apps/api/src/services/__tests__/person.test.ts +392 -0
  85. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +87 -0
  86. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +57 -17
  87. package/templates/apps/api/src/services/audit-log.ts +72 -10
  88. package/templates/apps/api/src/services/consent.ts +488 -3
  89. package/templates/apps/api/src/services/default-tenant.ts +12 -3
  90. package/templates/apps/api/src/services/hub-sign-in.ts +2 -1
  91. package/templates/apps/api/src/services/lead-routing.ts +105 -12
  92. package/templates/apps/api/src/services/person.ts +501 -1
  93. package/templates/apps/api/src/services/project-listings.ts +7 -2
  94. package/templates/apps/api/src/services/public-site-resolver.ts +21 -2
  95. package/templates/apps/api/src/services/request-confirm.ts +52 -0
  96. package/templates/apps/api/src/services/revalidation.ts +11 -1
  97. package/templates/apps/api/vercel.json +1 -1
  98. package/templates/apps/mcp/CLAUDE.md +19 -7
  99. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +95 -8
  100. package/templates/apps/mcp/src/tools/person_notes.ts +25 -0
  101. package/templates/apps/mcp/src/tools/proposals.ts +27 -0
  102. package/templates/apps/mcp/src/workspace-server.ts +16 -0
  103. package/templates/apps/web/_gitignore +6 -0
  104. package/templates/apps/web/app/[locale]/(auth)/sign-up/__tests__/sign-up-card.test.tsx +165 -0
  105. package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +19 -0
  106. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +106 -23
  107. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up.actions.ts +125 -0
  108. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/account-frame-sign-out.test.tsx +175 -0
  109. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/agreements-prompt.test.tsx +281 -0
  110. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/billing.test.tsx +17 -3
  111. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/general.test.tsx +154 -53
  112. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/hub-mode.test.tsx +116 -27
  113. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/item.test.tsx +57 -2
  114. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/layout-sign-out.test.tsx +146 -0
  115. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/layout.test.tsx +124 -18
  116. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/notifications.test.tsx +116 -18
  117. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/onboarding.test.tsx +323 -0
  118. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/privacy.test.tsx +365 -0
  119. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/security.test.tsx +290 -20
  120. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/settings.test.tsx +56 -0
  121. package/templates/apps/web/app/[locale]/(authed)/account/account-frame.tsx +74 -4
  122. package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +8 -0
  123. package/templates/apps/web/app/[locale]/(authed)/account/agreements-actions.ts +170 -0
  124. package/templates/apps/web/app/[locale]/(authed)/account/agreements-prompt.tsx +181 -0
  125. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/page.tsx +88 -3
  126. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/pay-form.tsx +65 -0
  127. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/review-form.tsx +27 -0
  128. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/page.test.tsx +176 -3
  129. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/pay.test.tsx +193 -0
  130. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/review.test.tsx +188 -0
  131. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/artifact-actions.ts +65 -4
  132. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/artifact-data.ts +17 -0
  133. package/templates/apps/web/app/[locale]/(authed)/account/artifacts/page.tsx +15 -9
  134. package/templates/apps/web/app/[locale]/(authed)/account/billing/page.tsx +3 -3
  135. package/templates/apps/web/app/[locale]/(authed)/account/general/contact-actions.ts +81 -0
  136. package/templates/apps/web/app/[locale]/(authed)/account/general/page.tsx +70 -27
  137. package/templates/apps/web/app/[locale]/(authed)/account/layout.tsx +26 -3
  138. package/templates/apps/web/app/[locale]/(authed)/account/notifications/page.tsx +65 -19
  139. package/templates/apps/web/app/[locale]/(authed)/account/onboarding/actions.ts +120 -0
  140. package/templates/apps/web/app/[locale]/(authed)/account/onboarding/onboarding-form.tsx +322 -0
  141. package/templates/apps/web/app/[locale]/(authed)/account/onboarding/page.tsx +126 -0
  142. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +43 -1
  143. package/templates/apps/web/app/[locale]/(authed)/account/privacy/actions.ts +65 -0
  144. package/templates/apps/web/app/[locale]/(authed)/account/privacy/page.tsx +226 -0
  145. package/templates/apps/web/app/[locale]/(authed)/account/security/page.tsx +89 -37
  146. package/templates/apps/web/app/[locale]/(authed)/account/security/security-panel.tsx +102 -0
  147. package/templates/apps/web/app/[locale]/(authed)/account/security/security-source.ts +62 -0
  148. package/templates/apps/web/app/[locale]/(authed)/account/settings-frame.tsx +44 -34
  149. package/templates/apps/web/app/[locale]/(authed)/account/sign-in-method.ts +1 -1
  150. package/templates/apps/web/app/[locale]/consent-banner.tsx +32 -0
  151. package/templates/apps/web/app/[locale]/consent.actions.ts +71 -0
  152. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +13 -1
  153. package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +25 -3
  154. package/templates/apps/web/app/[locale]/layout.tsx +23 -2
  155. package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +12 -1
  156. package/templates/apps/web/app/[locale]/unsubscribe/__tests__/unsubscribe-rsc-boundary.test.tsx +209 -0
  157. package/templates/apps/web/app/[locale]/unsubscribe/__tests__/unsubscribe.test.tsx +158 -0
  158. package/templates/apps/web/app/[locale]/unsubscribe/page.tsx +54 -0
  159. package/templates/apps/web/app/[locale]/unsubscribe/unsubscribe-button.tsx +73 -0
  160. package/templates/apps/web/app/[locale]/unsubscribe/unsubscribe.actions.ts +55 -0
  161. package/templates/apps/web/app/robots.txt/route.ts +13 -10
  162. package/templates/apps/web/auth.ts +20 -1
  163. package/templates/apps/web/jest.config.cjs +3 -0
  164. package/templates/apps/web/lib/__tests__/auth-email.test.ts +84 -0
  165. package/templates/apps/web/lib/__tests__/consent-visitor.test.ts +163 -0
  166. package/templates/apps/web/lib/__tests__/relay.test.ts +49 -0
  167. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +96 -7
  168. package/templates/apps/web/lib/account-config.ts +31 -16
  169. package/templates/apps/web/lib/auth-email.ts +45 -10
  170. package/templates/apps/web/lib/consent-visitor.ts +103 -0
  171. package/templates/apps/web/lib/relay.ts +20 -0
  172. package/templates/apps/web/lib/topology.generated.ts +9 -0
  173. package/templates/apps/web/messages/en.json +121 -18
  174. package/templates/apps/web/next.config.mjs +8 -2
  175. package/templates/database/CHANGELOG.md +55 -0
  176. package/templates/database/__tests__/consent-ledger.db.test.ts +345 -0
  177. package/templates/database/__tests__/fence-fan-out.db.test.ts +6 -2
  178. package/templates/database/__tests__/fixtures/person-contact-backfill.json +182 -0
  179. package/templates/database/__tests__/outbound-message-action.db.test.ts +80 -0
  180. package/templates/database/__tests__/person-contact.db.test.ts +563 -0
  181. package/templates/database/__tests__/person-notes.db.test.ts +249 -0
  182. package/templates/database/__tests__/person.db.test.ts +3 -1
  183. package/templates/database/__tests__/piece-kind-migration.test.ts +67 -0
  184. package/templates/database/__tests__/piece-kind.db.test.ts +208 -0
  185. package/templates/database/_gitignore +8 -0
  186. package/templates/database/inbox/schema.prisma +114 -22
  187. package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +122 -0
  188. package/templates/database/migrations/20261014120000_person_contact/migration.sql +231 -0
  189. package/templates/database/migrations/20261015120000_person_notes/migration.sql +77 -0
  190. package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +43 -0
  191. package/templates/database/migrations/20261016120000_piece_kind/migration.sql +95 -0
  192. package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +30 -0
  193. package/templates/database/ops/schema.prisma +16 -0
  194. package/templates/database/package.json +1 -1
  195. package/templates/project.yaml +6 -3
  196. package/versions.json +35 -35
  197. package/templates/.claude/rules/preserve-existing-style.md +0 -51
@@ -9,6 +9,8 @@
9
9
  // on this topology (#8070).
10
10
  // loadSpokeBilling reaches the spoke billing action only on a spoke that
11
11
  // signs in through its hub and carries commerce (#8217); elsewhere, null.
12
+ // readOwnAccounts lists the signed-in person's own sign-in accounts through
13
+ // Better Auth on a hub (#8431); a spoke has none here, so it answers null.
12
14
 
13
15
  export const TOPOLOGY: "hub" | "spoke" = "hub";
14
16
  export const UNSERVED_MCP_TOOLS: readonly string[] = [];
@@ -32,6 +34,13 @@ export async function readSession(headers: Headers): Promise<SiteSession> {
32
34
  return auth.api.getSession({ headers });
33
35
  }
34
36
 
37
+ export async function readOwnAccounts(
38
+ headers: Headers,
39
+ ): Promise<ReadonlyArray<{ providerId: string }> | null> {
40
+ const { auth } = await import("../auth");
41
+ return auth.api.listUserAccounts({ headers });
42
+ }
43
+
35
44
  export async function registerSiteStores(): Promise<void> {
36
45
  const { registerLicenseKeyStore } = await import("./license-key-store");
37
46
  await registerLicenseKeyStore();
@@ -57,7 +57,6 @@
57
57
  },
58
58
  "consent": {
59
59
  "title": "Cookie Preferences",
60
- "body": "We use analytics to understand how visitors use this site. We don't sell your data.",
61
60
  "acceptLabel": "Accept",
62
61
  "rejectLabel": "Reject",
63
62
  "policyLinkLabel": "Privacy policy",
@@ -535,6 +534,7 @@
535
534
  "signUpSubmit": "Create account",
536
535
  "signUpFooterPrompt": "Already have an account?",
537
536
  "signUpFooterLink": "Sign in",
537
+ "signUpAgreementsLegend": "Agreements",
538
538
  "signUpNotConfiguredSubhead": "Sign-up is not configured for this site yet. Set a provider's environment variables to enable it.",
539
539
  "signUpFailed": "We couldn't create your account. Check your details and try again.",
540
540
  "providerFailed": "We couldn't start sign-up with that provider. Try again.",
@@ -622,6 +622,17 @@
622
622
  "rateLimited": "Too many requests. Try again later.",
623
623
  "failed": "We couldn't send your review. Try again."
624
624
  }
625
+ },
626
+ "proposal": {
627
+ "caption": "Proposal",
628
+ "price": "Price {amount}",
629
+ "approve": "Approve proposal",
630
+ "heading": "Your decision on version {version}",
631
+ "pay": "Pay now",
632
+ "paying": "Opening payment…",
633
+ "paid": "Paid {date}",
634
+ "paidPending": "Payment received — it may take a minute to show here.",
635
+ "payError": "We couldn't open the payment page. Try again."
625
636
  }
626
637
  },
627
638
  "frame": {
@@ -630,6 +641,7 @@
630
641
  "forYou": "For you",
631
642
  "settings": "Settings",
632
643
  "signOut": "Log out",
644
+ "signOutFailed": "We couldn't log you out. You're still signed in; try again.",
633
645
  "help": "Help",
634
646
  "contactSupport": "Contact support",
635
647
  "helpCenter": "Help center",
@@ -715,30 +727,87 @@
715
727
  "saveError": "We couldn't save your changes. Try again.",
716
728
  "photoInvalid": "Enter a link that starts with https://.",
717
729
  "unverified": "Confirm your email address first, then try again.",
718
- "unavailable": "Profile changes aren't available on this site yet."
730
+ "unavailable": "Profile changes aren't available on this site yet.",
731
+ "contact": {
732
+ "title": "Contact details",
733
+ "lead": "Kept on this site, for the people you work with here.",
734
+ "givenName": "First name",
735
+ "familyName": "Last name",
736
+ "telephone": "Phone",
737
+ "address": "Address",
738
+ "companyName": "Company",
739
+ "jobTitle": "Job title",
740
+ "save": "Save contact details",
741
+ "saving": "Saving…",
742
+ "saved": "Saved.",
743
+ "addressIncomplete": "Fill in the address line, city, state or region, postal code and country, or clear the whole address.",
744
+ "unavailable": "Contact details aren't available on this site right now.",
745
+ "errors": {
746
+ "telephone": "Enter the phone number with its country code.",
747
+ "invalid": "Some of these details couldn't be saved. Check them and try again.",
748
+ "unverified": "Confirm your email address first, then try again.",
749
+ "unavailable": "Contact details can't be saved on this site yet.",
750
+ "failed": "We couldn't save your contact details. Try again."
751
+ }
752
+ }
719
753
  },
720
754
  "security": {
721
- "title": "Security"
722
- },
723
- "notifications": {
724
- "title": "Notifications"
725
- },
726
- "signIn": {
727
- "lead": "How you sign in to this site.",
755
+ "title": "Security",
756
+ "methodsHeading": "Sign-in methods",
757
+ "passwordLabel": "Password",
758
+ "passwordSet": "Set",
759
+ "passwordNotSet": "Not set",
760
+ "setHint": "Add a password so you can also sign in with your email and password.",
761
+ "changeHint": "Change the password you sign in with.",
762
+ "setNote": "We'll email {email} a secure link to create your password.",
763
+ "changeNote": "We'll email {email} a secure link to change your password.",
764
+ "setButton": "Set password",
765
+ "changeButton": "Change password",
766
+ "sending": "Sending…",
767
+ "sent": "Link sent. It works once, for an hour. Saving a password signs you out everywhere.",
768
+ "sendFailed": "We couldn't send the email. Try again in a few minutes.",
769
+ "logOut": "Log out",
770
+ "logOutFailed": "Log out didn't finish. Try again.",
771
+ "signsInWith": "You sign in with {methods}.",
772
+ "signedInAs": "You're signed in as {email}.",
728
773
  "methods": {
729
774
  "google": "Google",
730
775
  "github": "GitHub",
731
- "magicLink": "Email sign-in link",
732
- "password": "Password"
776
+ "magicLink": "a link sent to {email}",
777
+ "password": "your email and password"
733
778
  },
734
- "available": "Available",
735
- "none": "No sign-in method is configured.",
736
- "viaHub": "You sign in through {hub}.",
737
- "viaHubUnnamed": "You sign in through our main site."
779
+ "managedAt": "Your sign-in is managed at {hub}.",
780
+ "managedUnnamed": "Your sign-in is managed by our main site.",
781
+ "manageOnHub": "Manage sign-in on {hub}",
782
+ "passwordUnavailable": "We couldn't check your password settings."
783
+ },
784
+ "notifications": {
785
+ "title": "Notifications",
786
+ "lead": "What we send you.",
787
+ "empty": "There's nothing to set here yet."
788
+ },
789
+ "signIn": {
790
+ "lead": "How you sign in to this site."
738
791
  },
739
792
  "privacy": {
793
+ "title": "Privacy",
740
794
  "lead": "Cookies and your data.",
741
- "cookies": "Cookie settings",
795
+ "summary": "How we use your data.",
796
+ "policyLink": "Read our privacy policy",
797
+ "cookiesTitle": "Cookies",
798
+ "cookiesAccepted": "Accepted",
799
+ "cookiesDeclined": "Declined",
800
+ "cookiesUnset": "Not chosen yet",
801
+ "cookiesChange": "Change",
802
+ "consentsTitle": "Data use",
803
+ "consentsEmpty": "This site asks for no other data-use consents.",
804
+ "agreementsTitle": "Agreements accepted",
805
+ "agreementsEmpty": "None yet",
806
+ "version": "Version {version}",
807
+ "given": "Given {date}",
808
+ "withdrawn": "Withdrawn {date}",
809
+ "accepted": "Accepted {date}",
810
+ "unavailable": "Your consent choices can't be shown right now.",
742
811
  "deletion": "Request account deletion",
743
812
  "deletionLead": "Ask the site owner to delete your account and its data. We'll confirm by email.",
744
813
  "deletionSentSite": "Sent to the site operator. They'll confirm by email.",
@@ -757,7 +826,7 @@
757
826
  "accessEnds": "Access ends {date}",
758
827
  "card": "{brand} ending in {last4}, expires {month}/{year}",
759
828
  "noCard": "No card on file",
760
- "manage": "Manage in Stripe",
829
+ "manage": "Manage billing",
761
830
  "none": "You don't have a subscription.",
762
831
  "unavailable": "We couldn't load your billing details.",
763
832
  "unreadable": "Some of your billing is with another Stripe account, so it isn't shown here.",
@@ -769,6 +838,12 @@
769
838
  }
770
839
  }
771
840
  },
841
+ "agreements": {
842
+ "titleNew": "Please accept our terms",
843
+ "titleUpdated": "We've updated our terms",
844
+ "accept": "Accept",
845
+ "error": "We couldn't save that. Try again."
846
+ },
772
847
  "gate": {
773
848
  "emptyHeadline": "Sign-in isn't available yet",
774
849
  "emptyDescription": "This site hasn't turned on sign-in for members yet. Check back soon, or contact the site owner.",
@@ -822,7 +897,26 @@
822
897
  "heading": "My messages",
823
898
  "sentAt": "Sent",
824
899
  "file": "File",
825
- "download": "Download {filename}"
900
+ "download": "Download {filename}",
901
+ "openOnboarding": "Open onboarding"
902
+ },
903
+ "onboarding": {
904
+ "title": "Onboarding",
905
+ "unavailable": "Onboarding isn't open to you here right now.",
906
+ "back": "Back to your account",
907
+ "optional": "Optional",
908
+ "submit": "Send answers",
909
+ "submitting": "Sending…",
910
+ "sent": "Thank you — your answers were sent.",
911
+ "retry": "Retry",
912
+ "errors": {
913
+ "load": "We couldn't load your onboarding questions.",
914
+ "onboardingOff": "Onboarding isn't open to you here right now.",
915
+ "answersInvalid": "Some answers do not fit these questions. Check them and try again.",
916
+ "linkNotHttps": "A link must start with https://.",
917
+ "tooManyRequests": "Too many submissions. Try again later.",
918
+ "failed": "Your answers could not be sent. Try again."
919
+ }
826
920
  },
827
921
  "subscription": {
828
922
  "headline": "Your payment didn't go through",
@@ -1039,5 +1133,14 @@
1039
1133
  "sending": "Subscribing…",
1040
1134
  "success": "You're subscribed. Thanks for signing up!",
1041
1135
  "consentStatement": "I accept the [Terms](terms)."
1136
+ },
1137
+ "unsubscribe": {
1138
+ "title": "Unsubscribe",
1139
+ "lead": "Stop these emails?",
1140
+ "button": "Unsubscribe",
1141
+ "done": "You're unsubscribed from {description}.",
1142
+ "already": "You were already unsubscribed.",
1143
+ "invalid": "This link isn't valid.",
1144
+ "unavailable": "Unsubscribing isn't available right now."
1042
1145
  }
1043
1146
  }
@@ -5,6 +5,7 @@ import bundleAnalyzer from "@next/bundle-analyzer";
5
5
  import { withSentryConfig } from "@sentry/nextjs";
6
6
  import createNextIntlPlugin from "next-intl/plugin";
7
7
  import { legacyRedirects } from "@working-theory/templates/routes";
8
+ import { parseStealth } from "@working-theory/web-i18n/stealth";
8
9
 
9
10
  // @next/bundle-analyzer — enabled when ANALYZE=true (set by ci-bundle.yml).
10
11
  // analyzerMode 'json' writes .next/analyze/client.json (and nodejs.json,
@@ -16,11 +17,16 @@ const withBundleAnalyzer = bundleAnalyzer({
16
17
  analyzerMode: "json",
17
18
  });
18
19
 
19
- // When STEALTH=true, every response carries X-Robots-Tag: noindex, nofollow,
20
+ // When STEALTH is on, every response carries X-Robots-Tag: noindex, nofollow,
20
21
  // noarchive — paired with the <meta robots> tag in app/layout.tsx. Layer 2 of
21
22
  // the three-layer stealth posture (#884); new AILK installs default to
22
23
  // STEALTH=true so a forked instance doesn't ship indexable by accident.
23
- const STEALTH = process.env.STEALTH === "true";
24
+ // parseStealth is the one shared parse (#8511): true, 1, yes or on turn it on;
25
+ // false, 0, no, off, empty or unset leave it off; any other value throws here,
26
+ // so `next build` (and a non-standalone `next start`) fails before a page
27
+ // renders. A standalone server.js does not load this file, so there the
28
+ // robots route and every page's <meta robots> throw per request instead.
29
+ const STEALTH = parseStealth(process.env.STEALTH);
24
30
 
25
31
  // next-intl plugin — no explicit path: uses next-intl's default convention
26
32
  // lookup (./i18n/request.ts). We use `next build --webpack` (see package.json)
@@ -1,5 +1,60 @@
1
1
  # @working-theory/database
2
2
 
3
+ ## 0.41.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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)).
8
+
9
+ 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.
10
+
11
+ - [#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).
12
+
13
+ - **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.
14
+ - **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.
15
+ - **api-client** — `people.notes` and `people.setNotes`.
16
+ - **metadata** — two signed-in workspace tools, `get_person_notes` and `set_person_notes` (thirteen in all).
17
+ - **ui** — `PhoneNumberField` shows its country format as a "Format: …" caption under the field and no longer puts the example in the placeholder.
18
+ - **templates** — `ContactDetailsForm`, the one contact form the account page and the Admin share; Save stays disabled until something changes.
19
+
20
+ - [#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).
21
+
22
+ - `@working-theory/database`: `interactions_outbound_shape` admits one outbound payload, `{"action": "onboarding"}` (migration `20261017120000_outbound_message_action`; no row is rewritten).
23
+ - `@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.
24
+ - `@working-theory/api-client`: `member.onboarding` and `member.submitOnboarding`.
25
+
26
+ - [#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).
27
+
28
+ - `@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).
29
+ - `@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.
30
+ - `@working-theory/api-client`: `people.proposals`, `people.createProposal` and `member.payArtifact`.
31
+ - `@working-theory/metadata`: the `list_proposals` and `create_proposal` workspace tools.
32
+ - `@working-theory/stripe-client`: `createQuotedCheckoutSession` takes optional `expiresAt` and `paymentMethodTypes`; existing callers' sessions are unchanged.
33
+
34
+ ### Patch Changes
35
+
36
+ - [#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).
37
+
38
+ - 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)]:
39
+ - @working-theory/validation@0.41.0
40
+ - @working-theory/ids@0.14.0
41
+
42
+ ## 0.40.0
43
+
44
+ ### Minor Changes
45
+
46
+ - [#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).
47
+
48
+ 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.
49
+
50
+ - [#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.
51
+
52
+ ### Patch Changes
53
+
54
+ - 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)]:
55
+ - @working-theory/validation@0.40.0
56
+ - @working-theory/ids@0.13.0
57
+
3
58
  ## 0.39.0
4
59
 
5
60
  ### Minor Changes