create-ailk 0.18.0 → 0.19.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.
- package/LICENSE +6 -5
- package/NOTICE +2 -0
- package/dist/add-module.js +4 -1
- package/dist/category-profile.d.ts +10 -0
- package/dist/category-profile.js +21 -0
- package/dist/derive-architecture.d.ts +5 -1
- package/dist/derive-architecture.js +8 -3
- package/dist/lib/license-key-files.d.ts +6 -3
- package/dist/lib/license-key-files.js +8 -2
- package/dist/lib/scaffold-render-sweep.d.ts +9 -0
- package/dist/lib/scaffold-render-sweep.js +24 -3
- package/dist/license-set.d.ts +1 -1
- package/dist/license-set.js +13 -8
- package/dist/module-architecture.js +119 -0
- package/dist/programmatic.js +3 -0
- package/dist/spoke-checkout.d.ts +11 -3
- package/dist/spoke-checkout.js +62 -12
- package/dist/starter-grid.d.ts +1 -1
- package/dist/surfaces.js +140 -1
- package/dist/template-manifest.d.ts +4 -3
- package/dist/topology.d.ts +7 -2
- package/dist/topology.js +60 -3
- package/package.json +5 -4
- package/templates/.env.example +3 -3
- package/templates/.github/workflows/ci.yml +5 -0
- package/templates/apps/api/CLAUDE.md +25 -7
- package/templates/apps/api/LICENSE +6 -5
- package/templates/apps/api/NOTICE +2 -0
- package/templates/apps/api/jest.config.cjs +4 -29
- package/templates/apps/api/package.json +1 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +9 -0
- package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +38 -0
- package/templates/apps/api/src/lib/deliverable-asset-store.ts +5 -4
- package/templates/apps/api/src/lib/stripe.ts +81 -0
- package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +266 -39
- package/templates/apps/api/src/middleware/auth.ts +206 -46
- package/templates/apps/api/src/routes/leads/index.ts +4 -0
- package/templates/apps/api/src/server.ts +107 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +58 -0
- package/templates/apps/api/src/services/lead-routing.ts +30 -2
- package/templates/apps/api/vercel.json +2 -2
- package/templates/apps/mcp/.env.example +10 -0
- package/templates/apps/mcp/CLAUDE.md +9 -4
- package/templates/apps/mcp/LICENSE +6 -5
- package/templates/apps/mcp/NOTICE +2 -0
- package/templates/apps/mcp/__tests__/abuse/guard.test.ts +198 -0
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +15 -3
- package/templates/apps/mcp/__tests__/boot.test.ts +78 -1
- package/templates/apps/mcp/__tests__/http-transport.test.ts +291 -2
- package/templates/apps/mcp/__tests__/request_callback.test.ts +69 -7
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +69 -8
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +69 -7
- package/templates/apps/mcp/jest.config.cjs +3 -44
- package/templates/apps/mcp/src/abuse/index.ts +117 -21
- package/templates/apps/mcp/src/boot.ts +5 -23
- package/templates/apps/mcp/src/http-transport.ts +93 -73
- package/templates/apps/mcp/src/index.ts +2 -0
- package/templates/apps/mcp/src/request-context.ts +52 -0
- package/templates/apps/mcp/src/tools/capture_lead.ts +9 -1
- package/templates/apps/mcp/src/tools/request_callback.ts +9 -1
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +9 -1
- package/templates/apps/web/LICENSE +6 -5
- package/templates/apps/web/NOTICE +2 -0
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +3 -3
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/billing.test.tsx +288 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/general.test.tsx +568 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/hub-mode.test.tsx +272 -42
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/item.test.tsx +11 -13
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/layout.test.tsx +115 -16
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/new-menu.test.tsx +305 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/new-popups.test.tsx +82 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/notifications.test.tsx +126 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +163 -72
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/popups.test.tsx +451 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/security.test.tsx +139 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/settings.test.tsx +20 -390
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/support.test.tsx +16 -11
- package/templates/apps/web/app/[locale]/(authed)/account/account-data.ts +1 -1
- package/templates/apps/web/app/[locale]/(authed)/account/account-frame.tsx +114 -50
- package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +24 -45
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/page.tsx +253 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/review-form.tsx +145 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/versions/[version]/file/route.ts +100 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/file-route.test.ts +179 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/page.test.tsx +514 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/review.test.tsx +288 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/artifact-actions.ts +123 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/artifact-data.ts +82 -0
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/page.tsx +177 -0
- package/templates/apps/web/app/[locale]/(authed)/account/billing/page.tsx +172 -0
- package/templates/apps/web/app/[locale]/(authed)/account/billing-source.ts +147 -0
- package/templates/apps/web/app/[locale]/(authed)/account/components/request-quote.tsx +229 -0
- package/templates/apps/web/app/[locale]/(authed)/account/components/schedule-service.tsx +276 -0
- package/templates/apps/web/app/[locale]/(authed)/account/components/send-message.tsx +128 -0
- package/templates/apps/web/app/[locale]/(authed)/account/general/billing-anchor.tsx +27 -0
- package/templates/apps/web/app/[locale]/(authed)/account/general/deletion-request.tsx +132 -0
- package/templates/apps/web/app/[locale]/(authed)/account/general/page.tsx +131 -0
- package/templates/apps/web/app/[locale]/(authed)/account/general/profile-form.tsx +104 -0
- package/templates/apps/web/app/[locale]/(authed)/account/general/profile-source.ts +73 -0
- package/templates/apps/web/app/[locale]/(authed)/account/inbox/message/[id]/file/__tests__/route.test.ts +18 -8
- package/templates/apps/web/app/[locale]/(authed)/account/inbox/message/[id]/file/route.ts +4 -6
- package/templates/apps/web/app/[locale]/(authed)/account/layout.tsx +4 -1
- package/templates/apps/web/app/[locale]/(authed)/account/new-actions.ts +219 -0
- package/templates/apps/web/app/[locale]/(authed)/account/new-menu.tsx +340 -0
- package/templates/apps/web/app/[locale]/(authed)/account/new-popups.tsx +107 -0
- package/templates/apps/web/app/[locale]/(authed)/account/notifications/page.tsx +57 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +85 -26
- package/templates/apps/web/app/[locale]/(authed)/account/profile-actions.ts +116 -0
- package/templates/apps/web/app/[locale]/(authed)/account/security/page.tsx +80 -0
- package/templates/apps/web/app/[locale]/(authed)/account/settings/page.tsx +13 -354
- package/templates/apps/web/app/[locale]/(authed)/account/settings-frame.tsx +108 -0
- package/templates/apps/web/app/[locale]/(authed)/account/sign-in-method.ts +37 -0
- package/templates/apps/web/app/[locale]/(authed)/account/support-actions.ts +9 -10
- package/templates/apps/web/app/[locale]/layout.tsx +23 -4
- package/templates/apps/web/app/api/auth/hub/__tests__/continuation.test.ts +143 -0
- package/templates/apps/web/app/api/auth/hub/authorize/__tests__/route.test.ts +62 -10
- package/templates/apps/web/app/api/auth/hub/authorize/route.ts +22 -7
- package/templates/apps/web/app/api/auth/hub/continuation.ts +73 -0
- package/templates/apps/web/app/api/auth/hub/continue/[ref]/__tests__/route.test.ts +188 -0
- package/templates/apps/web/app/api/auth/hub/continue/[ref]/route.ts +53 -0
- package/templates/apps/web/app/robots.txt/route.ts +10 -4
- package/templates/apps/web/auth.ts +5 -1
- package/templates/apps/web/lib/__tests__/account-config.test.ts +258 -46
- package/templates/apps/web/lib/account-config.ts +188 -52
- package/templates/apps/web/lib/hub-session/__tests__/hub-session.test.ts +143 -0
- package/templates/apps/web/lib/hub-session/index.ts +1 -0
- package/templates/apps/web/lib/hub-session/reseal.ts +90 -0
- package/templates/apps/web/lib/hub-session/seal.ts +13 -9
- package/templates/apps/web/lib/topology.generated.ts +24 -0
- package/templates/apps/web/messages/en.json +156 -35
- package/templates/database/CHANGELOG.md +21 -0
- package/templates/database/LICENSE +6 -5
- package/templates/database/NOTICE +2 -0
- package/templates/database/README.md +1 -1
- package/templates/database/__tests__/member-area.db.test.ts +15 -3
- package/templates/database/__tests__/member-contract-migration.test.ts +85 -0
- package/templates/database/__tests__/member-contract.db.test.ts +413 -0
- package/templates/database/__tests__/seed.test.ts +54 -2
- package/templates/database/inbox/schema.prisma +90 -15
- package/templates/database/migrations/20261012120000_member_contract/migration.sql +192 -0
- package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +20 -0
- package/templates/database/package.json +3 -2
- package/templates/database/seed.ts +34 -2
- package/versions.json +36 -36
- package/templates/apps/api/src/__tests__/content-write-production-boot.test.ts +0 -104
- package/templates/apps/api/src/__tests__/cors.test.ts +0 -276
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +0 -279
- package/templates/apps/api/src/__tests__/openapi-keyless-hub.test.ts +0 -122
- package/templates/apps/api/src/__tests__/review-surface-registration.test.ts +0 -167
- package/templates/apps/api/src/__tests__/root-modules.test.ts +0 -175
- package/templates/apps/api/src/__tests__/schedule-forwarded-rate-limit.test.ts +0 -117
- package/templates/apps/api/src/__tests__/server.test.ts +0 -591
- package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +0 -175
- package/templates/apps/api/src/openapi/__tests__/surface-drift.test.ts +0 -293
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +0 -1620
- package/templates/apps/api/src/routes/project-listings/__tests__/directory.test.ts +0 -528
- package/templates/apps/api/src/routes/workspaces/__tests__/inbox-wire-schemas.test.ts +0 -198
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +0 -652
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +0 -408
- package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +0 -476
- package/templates/apps/mcp/__tests__/audit.test.ts +0 -346
- package/templates/apps/mcp/__tests__/parity.test.ts +0 -325
- package/templates/apps/mcp/__tests__/workspace-surface.test.ts +0 -364
- package/templates/apps/web/app/[locale]/(authed)/account/settings/color-mode.tsx +0 -68
- package/templates/apps/web/app/[locale]/(authed)/account/settings/deletion-request.tsx +0 -55
- package/templates/apps/web/app/[locale]/(authed)/account/settings/name-form.tsx +0 -118
- package/templates/database/__tests__/build.test.ts +0 -131
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// `--hub-sign-in` (#7894) it reads the sealed hub-session cookie.
|
|
8
8
|
// UNSERVED_MCP_TOOLS names the MCP tools /.well-known/mcp.json leaves out
|
|
9
9
|
// on this topology (#8070).
|
|
10
|
+
// loadSpokeBilling reaches the spoke billing action only on a spoke that
|
|
11
|
+
// signs in through its hub and carries commerce (#8217); elsewhere, null.
|
|
10
12
|
|
|
11
13
|
export const TOPOLOGY: "hub" | "spoke" = "hub";
|
|
12
14
|
export const UNSERVED_MCP_TOOLS: readonly string[] = [];
|
|
@@ -34,3 +36,25 @@ export async function registerSiteStores(): Promise<void> {
|
|
|
34
36
|
const { registerLicenseKeyStore } = await import("./license-key-store");
|
|
35
37
|
await registerLicenseKeyStore();
|
|
36
38
|
}
|
|
39
|
+
|
|
40
|
+
export type SpokeCard = { brand: string; last4: string; expMonth: number; expYear: number };
|
|
41
|
+
|
|
42
|
+
export type SpokeBillingRead =
|
|
43
|
+
| {
|
|
44
|
+
kind: "subscription";
|
|
45
|
+
status: "trialing" | "active" | "past_due" | "canceled";
|
|
46
|
+
planName: string | null;
|
|
47
|
+
paymentMethod: SpokeCard | null;
|
|
48
|
+
unreadable: boolean;
|
|
49
|
+
}
|
|
50
|
+
| { kind: "none"; unreadable: boolean }
|
|
51
|
+
| { kind: "failed" };
|
|
52
|
+
|
|
53
|
+
export type SpokeBilling = {
|
|
54
|
+
read(): Promise<SpokeBillingRead>;
|
|
55
|
+
portalUrl(): Promise<string | null>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export function loadSpokeBilling(): Promise<SpokeBilling | null> {
|
|
59
|
+
return Promise.resolve(null);
|
|
60
|
+
}
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"home": {
|
|
72
72
|
"heading": "My Site",
|
|
73
|
-
"emptyState": "
|
|
73
|
+
"emptyState": "Home page content coming soon."
|
|
74
74
|
},
|
|
75
75
|
"about": {
|
|
76
76
|
"heading": "About",
|
|
@@ -573,6 +573,57 @@
|
|
|
573
573
|
"account": {
|
|
574
574
|
"title": "Your account",
|
|
575
575
|
"description": "What changed, what's coming, and what needs you.",
|
|
576
|
+
"artifacts": {
|
|
577
|
+
"title": "Artifacts",
|
|
578
|
+
"lead": "Work delivered to you, newest first.",
|
|
579
|
+
"all": "All artifacts",
|
|
580
|
+
"facets": "Filter artifacts",
|
|
581
|
+
"reviewGroup": "Review",
|
|
582
|
+
"filter": "Show",
|
|
583
|
+
"empty": "Nothing has been delivered to you yet.",
|
|
584
|
+
"facetEmpty": "No artifacts here.",
|
|
585
|
+
"error": "We couldn't load your artifacts.",
|
|
586
|
+
"itemError": "We couldn't load this artifact.",
|
|
587
|
+
"retry": "Retry",
|
|
588
|
+
"back": "Artifacts",
|
|
589
|
+
"caption": "Artifact",
|
|
590
|
+
"versions": "Versions",
|
|
591
|
+
"version": "Version {version}",
|
|
592
|
+
"deliveredOn": "Delivered {date}",
|
|
593
|
+
"approvedOn": "Approved {date}",
|
|
594
|
+
"download": "Download {filename}",
|
|
595
|
+
"view": "View",
|
|
596
|
+
"columns": {
|
|
597
|
+
"title": "Title",
|
|
598
|
+
"latest": "Latest",
|
|
599
|
+
"delivered": "Delivered",
|
|
600
|
+
"review": "Review"
|
|
601
|
+
},
|
|
602
|
+
"states": {
|
|
603
|
+
"approved": "Approved",
|
|
604
|
+
"changesRequested": "Changes requested",
|
|
605
|
+
"ready": "Ready for review"
|
|
606
|
+
},
|
|
607
|
+
"reviewApproved": "You approved this version on {date}.",
|
|
608
|
+
"reviewChangesRequested": "You requested changes on {date}.",
|
|
609
|
+
"review": {
|
|
610
|
+
"heading": "Review version {version}",
|
|
611
|
+
"comment": "Comment",
|
|
612
|
+
"commentHint": "Needed to request changes.",
|
|
613
|
+
"approve": "Approve",
|
|
614
|
+
"requestChanges": "Request changes",
|
|
615
|
+
"submitting": "Sending…",
|
|
616
|
+
"sent": "Thanks — your review was sent.",
|
|
617
|
+
"waiting": "You requested changes. The next version will appear here.",
|
|
618
|
+
"errors": {
|
|
619
|
+
"commentRequired": "Add a comment to request changes.",
|
|
620
|
+
"closed": "This version can't be reviewed now. It may already be approved.",
|
|
621
|
+
"notLatest": "A newer version has arrived. Reload the page to review it.",
|
|
622
|
+
"rateLimited": "Too many requests. Try again later.",
|
|
623
|
+
"failed": "We couldn't send your review. Try again."
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
},
|
|
576
627
|
"frame": {
|
|
577
628
|
"home": "Home",
|
|
578
629
|
"inbox": "Inbox",
|
|
@@ -590,7 +641,9 @@
|
|
|
590
641
|
"collapseAside": "Collapse panel",
|
|
591
642
|
"expandAside": "Expand panel",
|
|
592
643
|
"openAside": "Open For you",
|
|
593
|
-
"closeAside": "Close For you"
|
|
644
|
+
"closeAside": "Close For you",
|
|
645
|
+
"library": "Library",
|
|
646
|
+
"artifacts": "Artifacts"
|
|
594
647
|
},
|
|
595
648
|
"forYou": {
|
|
596
649
|
"title": "For you",
|
|
@@ -617,10 +670,9 @@
|
|
|
617
670
|
"title": "Inbox",
|
|
618
671
|
"lead": "What changed, and what's coming.",
|
|
619
672
|
"tabs": {
|
|
620
|
-
"
|
|
621
|
-
"
|
|
622
|
-
"scheduled": "Scheduled"
|
|
623
|
-
"all": "All"
|
|
673
|
+
"all": "All",
|
|
674
|
+
"purchases": "Purchases",
|
|
675
|
+
"scheduled": "Scheduled"
|
|
624
676
|
},
|
|
625
677
|
"empty": "Nothing here yet.",
|
|
626
678
|
"error": "We couldn't load everything in your Inbox.",
|
|
@@ -642,60 +694,73 @@
|
|
|
642
694
|
},
|
|
643
695
|
"settings": {
|
|
644
696
|
"title": "Settings",
|
|
645
|
-
"
|
|
697
|
+
"back": "Back",
|
|
698
|
+
"account": "Account",
|
|
646
699
|
"general": {
|
|
647
700
|
"title": "General",
|
|
648
|
-
"lead": "Your
|
|
701
|
+
"lead": "Your profile and appearance.",
|
|
649
702
|
"colorMode": "Color mode",
|
|
650
703
|
"light": "Light",
|
|
651
704
|
"auto": "Auto",
|
|
652
705
|
"dark": "Dark",
|
|
653
706
|
"name": "Name",
|
|
654
|
-
"
|
|
707
|
+
"photo": "Photo",
|
|
708
|
+
"photoPlaceholder": "https://",
|
|
709
|
+
"photoHint": "A link to a square image, starting with https://. Leave it empty to show your initials.",
|
|
655
710
|
"email": "Email",
|
|
656
711
|
"save": "Save changes",
|
|
657
712
|
"saving": "Saving…",
|
|
658
713
|
"saved": "Saved.",
|
|
659
|
-
"unsaved": "Unsaved changes",
|
|
660
|
-
"clean": "No unsaved changes",
|
|
661
714
|
"nameRequired": "Enter your name.",
|
|
662
|
-
"saveError": "We couldn't save your
|
|
663
|
-
"
|
|
715
|
+
"saveError": "We couldn't save your changes. Try again.",
|
|
716
|
+
"photoInvalid": "Enter a link that starts with https://.",
|
|
717
|
+
"unverified": "Confirm your email address first, then try again.",
|
|
718
|
+
"unavailable": "Profile changes aren't available on this site yet."
|
|
664
719
|
},
|
|
665
720
|
"security": {
|
|
666
|
-
"title": "Security"
|
|
667
|
-
"lead": "The ways you can sign in to this site.",
|
|
668
|
-
"methods": "Sign-in methods",
|
|
669
|
-
"google": "Google",
|
|
670
|
-
"github": "GitHub",
|
|
671
|
-
"magicLink": "Email sign-in link",
|
|
672
|
-
"password": "Password",
|
|
673
|
-
"available": "Available",
|
|
674
|
-
"none": "No sign-in method is configured.",
|
|
675
|
-
"viaHub": "You sign in through our main site. Your sign-in methods are managed there."
|
|
721
|
+
"title": "Security"
|
|
676
722
|
},
|
|
677
723
|
"notifications": {
|
|
678
|
-
"title": "Notifications"
|
|
679
|
-
|
|
680
|
-
|
|
724
|
+
"title": "Notifications"
|
|
725
|
+
},
|
|
726
|
+
"signIn": {
|
|
727
|
+
"lead": "How you sign in to this site.",
|
|
728
|
+
"methods": {
|
|
729
|
+
"google": "Google",
|
|
730
|
+
"github": "GitHub",
|
|
731
|
+
"magicLink": "Email sign-in link",
|
|
732
|
+
"password": "Password"
|
|
733
|
+
},
|
|
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."
|
|
681
738
|
},
|
|
682
739
|
"privacy": {
|
|
683
|
-
"title": "Privacy",
|
|
684
740
|
"lead": "Cookies and your data.",
|
|
685
741
|
"cookies": "Cookie settings",
|
|
686
742
|
"deletion": "Request account deletion",
|
|
687
743
|
"deletionLead": "Ask the site owner to delete your account and its data. We'll confirm by email.",
|
|
688
|
-
"
|
|
744
|
+
"deletionSentSite": "Sent to the site operator. They'll confirm by email.",
|
|
745
|
+
"deletionSentHub": "Sent to the hub operator. They'll confirm by email.",
|
|
746
|
+
"deletionUnverified": "Confirm your email address first, then ask again.",
|
|
747
|
+
"deletionUnavailable": "This site can't take deletion requests right now.",
|
|
689
748
|
"deletionError": "We couldn't send your request. Try again in a moment.",
|
|
690
|
-
"
|
|
691
|
-
"
|
|
749
|
+
"deletionViaSupport": "To ask for your account to be deleted, contact support.",
|
|
750
|
+
"deletionSupportLink": "Contact support"
|
|
692
751
|
},
|
|
693
752
|
"billing": {
|
|
694
753
|
"title": "Billing",
|
|
695
|
-
"lead": "Your
|
|
696
|
-
"
|
|
697
|
-
"
|
|
698
|
-
"
|
|
754
|
+
"lead": "Your plan and payment method.",
|
|
755
|
+
"currentPlan": "Current plan",
|
|
756
|
+
"unnamedPlan": "Your subscription",
|
|
757
|
+
"accessEnds": "Access ends {date}",
|
|
758
|
+
"card": "{brand} ending in {last4}, expires {month}/{year}",
|
|
759
|
+
"noCard": "No card on file",
|
|
760
|
+
"manage": "Manage in Stripe",
|
|
761
|
+
"none": "You don't have a subscription.",
|
|
762
|
+
"unavailable": "We couldn't load your billing details.",
|
|
763
|
+
"unreadable": "Some of your billing is with another Stripe account, so it isn't shown here.",
|
|
699
764
|
"statuses": {
|
|
700
765
|
"trialing": "Trial",
|
|
701
766
|
"active": "Active",
|
|
@@ -731,7 +796,19 @@
|
|
|
731
796
|
"offer": "Offer",
|
|
732
797
|
"amount": "Amount",
|
|
733
798
|
"period": "Period",
|
|
734
|
-
"date": "Date"
|
|
799
|
+
"date": "Date",
|
|
800
|
+
"unavailable": "Not recorded"
|
|
801
|
+
},
|
|
802
|
+
"appointments": {
|
|
803
|
+
"heading": "My appointments",
|
|
804
|
+
"untitled": "Appointment",
|
|
805
|
+
"starts": "Starts",
|
|
806
|
+
"ends": "Ends",
|
|
807
|
+
"statuses": {
|
|
808
|
+
"pending": "Pending",
|
|
809
|
+
"confirmed": "Confirmed",
|
|
810
|
+
"cancelled": "Cancelled"
|
|
811
|
+
}
|
|
735
812
|
},
|
|
736
813
|
"pieces": {
|
|
737
814
|
"heading": "My pieces",
|
|
@@ -750,6 +827,50 @@
|
|
|
750
827
|
"subscription": {
|
|
751
828
|
"headline": "Your payment didn't go through",
|
|
752
829
|
"action": "Update payment method"
|
|
830
|
+
},
|
|
831
|
+
"new": {
|
|
832
|
+
"trigger": "New",
|
|
833
|
+
"close": "Close",
|
|
834
|
+
"loading": "Loading…",
|
|
835
|
+
"loadFailed": "This could not load.",
|
|
836
|
+
"retry": "Try again",
|
|
837
|
+
"submitting": "Sending…",
|
|
838
|
+
"optional": "Optional",
|
|
839
|
+
"actions": {
|
|
840
|
+
"scheduleService": "Schedule service",
|
|
841
|
+
"requestQuote": "Request quote",
|
|
842
|
+
"sendMessage": "Send message"
|
|
843
|
+
},
|
|
844
|
+
"schedule": {
|
|
845
|
+
"service": "Service",
|
|
846
|
+
"duration": "{minutes} min",
|
|
847
|
+
"time": "Time",
|
|
848
|
+
"notes": "Notes",
|
|
849
|
+
"submit": "Book",
|
|
850
|
+
"none": "No times are offered right now. You can send a message instead.",
|
|
851
|
+
"suggest": "Send a message",
|
|
852
|
+
"noSlots": "No open times in the next 14 days."
|
|
853
|
+
},
|
|
854
|
+
"quote": {
|
|
855
|
+
"submit": "Send request"
|
|
856
|
+
},
|
|
857
|
+
"message": {
|
|
858
|
+
"subject": "Subject",
|
|
859
|
+
"body": "Message",
|
|
860
|
+
"link": "Link",
|
|
861
|
+
"linkHelp": "Must start with https://.",
|
|
862
|
+
"submit": "Send"
|
|
863
|
+
},
|
|
864
|
+
"errors": {
|
|
865
|
+
"linkNotHttps": "A link must start with https://.",
|
|
866
|
+
"answersInvalid": "Some answers do not fit this form. Check them and try again.",
|
|
867
|
+
"requestFormOff": "Requests are switched off right now.",
|
|
868
|
+
"meetingTypeNotOffered": "This service is no longer offered.",
|
|
869
|
+
"slotUnavailable": "That time was just taken. Pick another.",
|
|
870
|
+
"tooManyRequests": "Too many requests. Try again later.",
|
|
871
|
+
"invalidInput": "Check what you entered and try again.",
|
|
872
|
+
"failed": "This could not be sent. Try again."
|
|
873
|
+
}
|
|
753
874
|
}
|
|
754
875
|
},
|
|
755
876
|
"admin": {
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @working-theory/database
|
|
2
2
|
|
|
3
|
+
## 0.39.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#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.
|
|
8
|
+
|
|
9
|
+
- `@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.
|
|
10
|
+
- `@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.
|
|
11
|
+
- `@working-theory/site-config` — `MeetingsSchema` gains optional `customerSlugs` (no default, duplicates refused).
|
|
12
|
+
- `@working-theory/ids` — the `pver_` prefix (`pieceVersion`).
|
|
13
|
+
|
|
14
|
+
- [#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.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [#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.
|
|
19
|
+
|
|
20
|
+
- 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)]:
|
|
21
|
+
- @working-theory/validation@0.39.0
|
|
22
|
+
- @working-theory/ids@0.12.0
|
|
23
|
+
|
|
3
24
|
## 0.38.0
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
Apache License
|
|
2
3
|
Version 2.0, January 2004
|
|
3
4
|
http://www.apache.org/licenses/
|
|
@@ -137,8 +138,8 @@
|
|
|
137
138
|
|
|
138
139
|
6. Trademarks. This License does not grant permission to use the trade
|
|
139
140
|
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
-
except as required for
|
|
141
|
-
reproducing the content of the NOTICE file.
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
143
|
|
|
143
144
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
145
|
agreed to in writing, Licensor provides the Work (and each
|
|
@@ -162,7 +163,7 @@
|
|
|
162
163
|
other commercial damages or losses), even if such Contributor
|
|
163
164
|
has been advised of the possibility of such damages.
|
|
164
165
|
|
|
165
|
-
9. Accepting Warranty or
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
167
|
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
168
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
169
|
or other liability obligations and/or rights consistent with this
|
|
@@ -171,7 +172,7 @@
|
|
|
171
172
|
of any other Contributor, and only if You agree to indemnify,
|
|
172
173
|
defend, and hold each Contributor harmless for any liability
|
|
173
174
|
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
-
of your accepting any such warranty or
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
175
176
|
|
|
176
177
|
END OF TERMS AND CONDITIONS
|
|
177
178
|
|
|
@@ -186,7 +187,7 @@
|
|
|
186
187
|
same "printed page" as the copyright notice for easier
|
|
187
188
|
identification within third-party archives.
|
|
188
189
|
|
|
189
|
-
Copyright
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
191
|
|
|
191
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
193
|
you may not use this file except in compliance with the License.
|
|
@@ -69,7 +69,7 @@ model RefreshToken {
|
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
71
|
# Mobile app authenticates with token
|
|
72
|
-
curl -H "Authorization: Bearer
|
|
72
|
+
curl -H "Authorization: Bearer <access-token>" \
|
|
73
73
|
https://api.customer-site.com/api/user/profile
|
|
74
74
|
|
|
75
75
|
# Refresh expired access token
|
|
@@ -61,14 +61,26 @@ const describeMonorepo = existsSync(join(REPO_ROOT, "packages", "validation"))
|
|
|
61
61
|
: describe.skip;
|
|
62
62
|
|
|
63
63
|
describeMonorepo("the member-area wire contract (#7877 AC-1, no database)", () => {
|
|
64
|
-
it("packages/validation's pieces and member schemas name no stage literal and no enum", () => {
|
|
64
|
+
it("packages/validation's pieces and member schemas name no stage literal and no stage enum", () => {
|
|
65
|
+
// #8168 narrowed this match to its intent: a stage LITERAL is a quoted
|
|
66
|
+
// stage name. member.ts now legitimately carries `deliveredAt`, the
|
|
67
|
+
// `changes-requested` review value and non-stage vocabularies
|
|
68
|
+
// (`z.enum(["message", "quote", "review"])`, D11) — none of them a stage.
|
|
69
|
+
// A stage enum would have to quote a stage name, so the quoted match
|
|
70
|
+
// still catches one; pieces.ts, where stages and offerings live, keeps
|
|
71
|
+
// the blanket no-`z.enum` rule.
|
|
65
72
|
for (const file of ["pieces.ts", "member.ts"]) {
|
|
66
73
|
const text = readFileSync(
|
|
67
74
|
join(REPO_ROOT, "packages", "validation", "src", "schemas", file),
|
|
68
75
|
"utf8",
|
|
69
76
|
);
|
|
70
|
-
expect(text).not.toMatch(/requested|in-progress|in-review|delivered|scoping
|
|
77
|
+
expect(text).not.toMatch(/["'`](requested|in-progress|in-review|delivered|scoping)["'`]/);
|
|
71
78
|
}
|
|
79
|
+
const pieces = readFileSync(
|
|
80
|
+
join(REPO_ROOT, "packages", "validation", "src", "schemas", "pieces.ts"),
|
|
81
|
+
"utf8",
|
|
82
|
+
);
|
|
83
|
+
expect(pieces).not.toMatch(/z\.enum/);
|
|
72
84
|
});
|
|
73
85
|
|
|
74
86
|
it("the product default stage list is named by no package", () => {
|
|
@@ -197,7 +209,7 @@ describeDb("the member-area tables (#7877 D1–D3, AC-1, live DB)", () => {
|
|
|
197
209
|
|
|
198
210
|
it.each([
|
|
199
211
|
["channel `email`", { channel: "email" }, "interactions_channel_allowed"],
|
|
200
|
-
["direction `
|
|
212
|
+
["direction `sideways`", { direction: "sideways" }, "interactions_direction_allowed"],
|
|
201
213
|
["a lead_ asset id", { asset_id: LEAD_ID }, "interactions_asset_id_format"],
|
|
202
214
|
["an empty subject", { subject: "" }, "interactions_subject_length"],
|
|
203
215
|
["a 10001-character body", { body: "b".repeat(10001) }, "interactions_body_length"],
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file member-contract-migration.test.ts
|
|
3
|
+
*
|
|
4
|
+
* DB-free: the `request-quote` backfill in
|
|
5
|
+
* migrations/20261012120000_member_contract writes its config as a JSONB
|
|
6
|
+
* literal, because SQL cannot import TS. This test holds that copy to the one
|
|
7
|
+
* TS source, `requestQuoteFlowConfig` (#8168 spec D8, D9; AC-6), and the
|
|
8
|
+
* block's slug and title literals to their constants — so the two can never
|
|
9
|
+
* drift. `member-contract.db.test.ts` re-executes the same block live.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
flowConfigSchema,
|
|
16
|
+
REQUEST_QUOTE_FLOW_SLUG,
|
|
17
|
+
REQUEST_QUOTE_FLOW_TITLE,
|
|
18
|
+
requestQuoteFlowConfig,
|
|
19
|
+
} from "@working-theory/validation";
|
|
20
|
+
|
|
21
|
+
const MIGRATION_SQL = readFileSync(
|
|
22
|
+
join(
|
|
23
|
+
__dirname,
|
|
24
|
+
"..",
|
|
25
|
+
"migrations",
|
|
26
|
+
"20261012120000_member_contract",
|
|
27
|
+
"migration.sql",
|
|
28
|
+
),
|
|
29
|
+
"utf8",
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/** The text between the `-- BEGIN request-quote backfill` / `-- END …` markers. */
|
|
33
|
+
function backfillBlock(sql: string): string {
|
|
34
|
+
const match =
|
|
35
|
+
/-- BEGIN request-quote backfill\n([\s\S]*?)-- END request-quote backfill/.exec(
|
|
36
|
+
sql,
|
|
37
|
+
);
|
|
38
|
+
if (!match?.[1]) throw new Error("request-quote backfill markers not found");
|
|
39
|
+
return match[1];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("the request-quote backfill literal (#8168 D9, AC-6)", () => {
|
|
43
|
+
const block = backfillBlock(MIGRATION_SQL);
|
|
44
|
+
|
|
45
|
+
it("carries exactly one JSONB config literal, and it deep-equals requestQuoteFlowConfig", () => {
|
|
46
|
+
const literals = [...block.matchAll(/'(\{[\s\S]*?\})'::jsonb/g)];
|
|
47
|
+
expect(literals).toHaveLength(1);
|
|
48
|
+
const parsed: unknown = JSON.parse(literals[0]![1]!);
|
|
49
|
+
expect(parsed).toEqual(requestQuoteFlowConfig);
|
|
50
|
+
expect(flowConfigSchema.safeParse(parsed).success).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("writes the constants' slug and title, kind contact, status draft, customers_enabled true", () => {
|
|
54
|
+
expect(block).toContain(
|
|
55
|
+
`SELECT w."id", w."id", '${REQUEST_QUOTE_FLOW_SLUG}',`,
|
|
56
|
+
);
|
|
57
|
+
expect(block).toContain(
|
|
58
|
+
`'contact', '${REQUEST_QUOTE_FLOW_TITLE}', 'draft', true, CURRENT_TIMESTAMP`,
|
|
59
|
+
);
|
|
60
|
+
expect(block).toContain(
|
|
61
|
+
`("site_id", "workspace_id", "slug", "config", "kind", "title", "status", "customers_enabled", "updated_at")`,
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("never overwrites a workspace's existing (site_id, slug) row", () => {
|
|
66
|
+
expect(block).toContain(`ON CONFLICT ("site_id", "slug") DO NOTHING;`);
|
|
67
|
+
expect(block).not.toMatch(/DO UPDATE/i);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("no round count, limit or remaining count in the migration (#8168 AC-7)", () => {
|
|
72
|
+
it("names no such column in piece_versions or in the pieces ADD COLUMN", () => {
|
|
73
|
+
const createTable = /CREATE TABLE "piece_versions" \(([\s\S]*?)\n\);/.exec(
|
|
74
|
+
MIGRATION_SQL,
|
|
75
|
+
)?.[1];
|
|
76
|
+
const addPieceColumn = /ALTER TABLE "pieces" ADD COLUMN[^;]*;/.exec(
|
|
77
|
+
MIGRATION_SQL,
|
|
78
|
+
)?.[0];
|
|
79
|
+
expect(createTable).toContain('"review_comment"');
|
|
80
|
+
expect(addPieceColumn).toContain('"approved_at"');
|
|
81
|
+
for (const ddl of [createTable ?? "", addPieceColumn ?? ""]) {
|
|
82
|
+
expect(ddl).not.toMatch(/round|remaining|limit|left/i);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|