create-ailk 0.17.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/env-catalog.js +5 -9
- 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 +15 -2
- package/dist/topology.js +83 -4
- 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 +58 -7
- 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__/app-entry.test.ts +325 -0
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +15 -3
- package/templates/apps/mcp/__tests__/boot.test.ts +280 -0
- package/templates/apps/mcp/__tests__/http-transport.test.ts +291 -2
- package/templates/apps/mcp/__tests__/index.test.ts +86 -47
- package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +5 -6
- package/templates/apps/mcp/__tests__/lib/content-root.test.ts +93 -0
- package/templates/apps/mcp/__tests__/request_callback.test.ts +69 -7
- package/templates/apps/mcp/__tests__/server.test.ts +63 -6
- 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/app.ts +32 -0
- package/templates/apps/mcp/src/boot.ts +167 -0
- package/templates/apps/mcp/src/http-transport.ts +132 -88
- package/templates/apps/mcp/src/index.ts +19 -126
- package/templates/apps/mcp/src/lib/audit-single-page.ts +7 -6
- package/templates/apps/mcp/src/lib/content-adapter.ts +34 -5
- package/templates/apps/mcp/src/lib/topology.generated.ts +3 -0
- package/templates/apps/mcp/src/request-context.ts +52 -0
- package/templates/apps/mcp/src/server.ts +10 -2
- package/templates/apps/mcp/src/serverless-app.ts +88 -0
- package/templates/apps/mcp/src/tools/capture_lead.ts +9 -1
- package/templates/apps/mcp/src/tools/get_business_hours.ts +6 -5
- package/templates/apps/mcp/src/tools/get_faq.ts +6 -5
- package/templates/apps/mcp/src/tools/get_locations.ts +6 -5
- package/templates/apps/mcp/src/tools/get_offerings.ts +6 -5
- package/templates/apps/mcp/src/tools/get_pricing.ts +6 -5
- package/templates/apps/mcp/src/tools/get_site_info.ts +6 -5
- package/templates/apps/mcp/src/tools/list_pages.ts +8 -7
- package/templates/apps/mcp/src/tools/read_content.ts +7 -7
- package/templates/apps/mcp/src/tools/request_callback.ts +9 -1
- package/templates/apps/mcp/src/tools/search_content.ts +6 -5
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +9 -1
- package/templates/apps/mcp/tsconfig.json +2 -0
- 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/.well-known/mcp.json/build-manifest.ts +16 -4
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +3 -0
- 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 +25 -32
- 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/__tests__/site-brand.test.ts +42 -0
- 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/site-brand.tsx +22 -6
- package/templates/apps/web/lib/topology.generated.ts +27 -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
package/LICENSE
CHANGED
|
@@ -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.
|
package/NOTICE
ADDED
package/dist/add-module.js
CHANGED
|
@@ -165,12 +165,15 @@ export async function applyModuleToScaffold(opts) {
|
|
|
165
165
|
});
|
|
166
166
|
// #7838 D8 — commerce on a spoke brings the spoke's own checkout, stamped
|
|
167
167
|
// from the site directory's name (the `projectName` scaffold() defaults to).
|
|
168
|
-
// A file the site already has is left as it is.
|
|
168
|
+
// A file the site already has is left as it is. #8217 D8 — on a spoke that
|
|
169
|
+
// signs in through its hub, the billing action and its seam render too, so
|
|
170
|
+
// re-running add-module commerce gives an existing commerce spoke the action.
|
|
169
171
|
const spokeCommerce = spoke !== undefined && opts.moduleName === "commerce";
|
|
170
172
|
const checkoutRows = spokeCommerce
|
|
171
173
|
? writeSpokeCheckoutSlice(targetAbs, {
|
|
172
174
|
site: spokeCheckoutSite(basename(targetAbs)),
|
|
173
175
|
versions: opts.versions,
|
|
176
|
+
signIn: spoke.signIn,
|
|
174
177
|
})
|
|
175
178
|
: [];
|
|
176
179
|
// #7876 D9 — a spoke that just gained the flow stepper says what its
|
|
@@ -50,6 +50,16 @@ export declare const CATEGORY_PROFILE_SHAPES: {
|
|
|
50
50
|
* set-equal to the `schema-dts` closure, so it cannot drift silently.
|
|
51
51
|
*/
|
|
52
52
|
export declare const LOCAL_BUSINESS_TYPES: ReadonlySet<string>;
|
|
53
|
+
/**
|
|
54
|
+
* The leaf category slugs, in registry order — create-ailk's own copy of the
|
|
55
|
+
* site-category registry's leaves (`SITE_CATEGORIES`, #5830). A literal, not
|
|
56
|
+
* a type import, so the emitted `.d.ts` of the public tarball names no
|
|
57
|
+
* `@working-theory/*` package (#8412); `category-slugs.test.ts` proves it
|
|
58
|
+
* equal to the registry, so it cannot drift silently.
|
|
59
|
+
*/
|
|
60
|
+
export declare const CATEGORY_SLUGS: readonly ["accounting", "legal", "consulting", "hvac", "roofing", "plumbing", "electrical", "landscaping", "auto-repair", "real-estate", "technology", "medical-specialty"];
|
|
61
|
+
/** A leaf category slug — the only thing a template's `categories` names. */
|
|
62
|
+
export type CategorySlug = (typeof CATEGORY_SLUGS)[number];
|
|
53
63
|
export declare const OFFERING_PRICING: readonly ["quote", "fixed", "hourly", "subscription"];
|
|
54
64
|
export declare const PROOF_KINDS: readonly ["credential", "reviews", "before-after", "response-time", "guarantee", "experience"];
|
|
55
65
|
export declare const CONTENT_POSTURES: readonly ["instructions", "sample"];
|
package/dist/category-profile.js
CHANGED
|
@@ -71,6 +71,27 @@ export const LOCAL_BUSINESS_TYPES = new Set([
|
|
|
71
71
|
"TennisComplex", "TireShop", "TouristInformationCenter", "ToyStore",
|
|
72
72
|
"TravelAgency", "VacationRental", "WholesaleStore", "Winery",
|
|
73
73
|
]);
|
|
74
|
+
/**
|
|
75
|
+
* The leaf category slugs, in registry order — create-ailk's own copy of the
|
|
76
|
+
* site-category registry's leaves (`SITE_CATEGORIES`, #5830). A literal, not
|
|
77
|
+
* a type import, so the emitted `.d.ts` of the public tarball names no
|
|
78
|
+
* `@working-theory/*` package (#8412); `category-slugs.test.ts` proves it
|
|
79
|
+
* equal to the registry, so it cannot drift silently.
|
|
80
|
+
*/
|
|
81
|
+
export const CATEGORY_SLUGS = [
|
|
82
|
+
"accounting",
|
|
83
|
+
"legal",
|
|
84
|
+
"consulting",
|
|
85
|
+
"hvac",
|
|
86
|
+
"roofing",
|
|
87
|
+
"plumbing",
|
|
88
|
+
"electrical",
|
|
89
|
+
"landscaping",
|
|
90
|
+
"auto-repair",
|
|
91
|
+
"real-estate",
|
|
92
|
+
"technology",
|
|
93
|
+
"medical-specialty",
|
|
94
|
+
];
|
|
74
95
|
export const OFFERING_PRICING = ["quote", "fixed", "hourly", "subscription"];
|
|
75
96
|
export const PROOF_KINDS = [
|
|
76
97
|
"credential",
|
|
@@ -22,7 +22,11 @@ export interface DeriveArchitectureOptions {
|
|
|
22
22
|
/** Spoke only: whether the spoke keeps `apps/mcp` (default true). */
|
|
23
23
|
mcp?: boolean;
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The only spoke files that may import @working-theory/spoke-checkout (#7873):
|
|
27
|
+
* the buy route, the webhook route and — on a spoke that signs in through its
|
|
28
|
+
* hub — the billing action (#8217 D9, a reviewed change to the #7873 rule).
|
|
29
|
+
*/
|
|
26
30
|
export declare const SPOKE_CHECKOUT_ROUTE_FILES: readonly string[];
|
|
27
31
|
/** The forbidden patterns a spoke's apps/web carries (#7873, brief Part 2 §2). */
|
|
28
32
|
export declare const SPOKE_WEB_FORBIDDEN_PATTERNS: readonly ForbiddenPattern[];
|
|
@@ -27,10 +27,15 @@ const SPOKE_TIERS = {
|
|
|
27
27
|
// import only to a workspace on disk, so the one way to ban an npm package is
|
|
28
28
|
// a line-level forbidden pattern. These go under the spoke's own `apps.web`
|
|
29
29
|
// and `apps.mcp` only — never top level, and never on a hub derivation.
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* The only spoke files that may import @working-theory/spoke-checkout (#7873):
|
|
32
|
+
* the buy route, the webhook route and — on a spoke that signs in through its
|
|
33
|
+
* hub — the billing action (#8217 D9, a reviewed change to the #7873 rule).
|
|
34
|
+
*/
|
|
31
35
|
export const SPOKE_CHECKOUT_ROUTE_FILES = Object.freeze([
|
|
32
36
|
"apps/web/app/api/checkout/[offering]/route.ts",
|
|
33
37
|
"apps/web/app/api/webhooks/stripe/route.ts",
|
|
38
|
+
"apps/web/app/[locale]/(authed)/account/billing/spoke-billing.action.ts",
|
|
34
39
|
]);
|
|
35
40
|
/**
|
|
36
41
|
* A line-level regex for an import of `specifier` or one of its subpaths, in
|
|
@@ -45,10 +50,10 @@ function specifierForm(specifier) {
|
|
|
45
50
|
const literal = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
46
51
|
return `\\b(?:from|import|require)\\s*\\(?\\s*${q}${literal}(?:/[^'"\`]*)?${q}`;
|
|
47
52
|
}
|
|
48
|
-
/** P1 with no exclusions — a kept apps/mcp's form; apps/web adds the
|
|
53
|
+
/** P1 with no exclusions — a kept apps/mcp's form; apps/web adds the route files. */
|
|
49
54
|
const SPOKE_CHECKOUT_PATTERN = Object.freeze({
|
|
50
55
|
pattern: specifierForm("@working-theory/spoke-checkout"),
|
|
51
|
-
reason: "Spoke checkout: only the buy route
|
|
56
|
+
reason: "Spoke checkout: only the buy route, the webhook route and the billing action may import @working-theory/spoke-checkout (brief Part 2 §2, #7873, #8217)",
|
|
52
57
|
});
|
|
53
58
|
const STRIPE_CLIENT_PATTERN = Object.freeze({
|
|
54
59
|
pattern: specifierForm("@working-theory/stripe-client"),
|
package/dist/lib/env-catalog.js
CHANGED
|
@@ -24,7 +24,7 @@ export const ENV_CATALOG = {
|
|
|
24
24
|
secret: false,
|
|
25
25
|
},
|
|
26
26
|
AILK_CONTENT_ROOT: {
|
|
27
|
-
description: "Overrides the on-disk content root; defaults to <repo-root>/content.",
|
|
27
|
+
description: "Overrides the on-disk content root (absolute, or relative to the working directory). Unset, the MCP server tries <cwd>/content, then <cwd>/../../content; the web app defaults to <repo-root>/content.",
|
|
28
28
|
secret: false,
|
|
29
29
|
},
|
|
30
30
|
AILK_ENABLED_MODULES: {
|
|
@@ -143,16 +143,12 @@ export const ENV_CATALOG = {
|
|
|
143
143
|
description: "The port the MCP HTTP transport binds; defaults to 8080.",
|
|
144
144
|
secret: false,
|
|
145
145
|
},
|
|
146
|
-
|
|
147
|
-
description: "
|
|
148
|
-
secret: false,
|
|
149
|
-
},
|
|
150
|
-
MCP_RATE_LIMIT_READ_PER_MIN: {
|
|
151
|
-
description: "Maximum MCP read-tool requests per minute per IP; defaults to 60.",
|
|
146
|
+
MCP_HTTP_STATELESS: {
|
|
147
|
+
description: 'Set to "true" or "1" for an MCP HTTP transport with no sessions, which any instance can answer; "false" or "0" keeps sessions in one process. Unset means stateless on Vercel (src/app.ts) and stateful on a port (src/index.ts).',
|
|
152
148
|
secret: false,
|
|
153
149
|
},
|
|
154
|
-
|
|
155
|
-
description: "
|
|
150
|
+
MCP_PUBLIC_HTTP_URL: {
|
|
151
|
+
description: "The public URL of the MCP HTTP transport, advertised by /.well-known/mcp.json.",
|
|
156
152
|
secret: false,
|
|
157
153
|
},
|
|
158
154
|
MCP_TRANSPORT: {
|
|
@@ -21,9 +21,12 @@ export declare function appendLine(text: string, line: string): string;
|
|
|
21
21
|
* `ailk.key` when no existing line covers it. Idempotent — a second call with
|
|
22
22
|
* the same key changes no byte.
|
|
23
23
|
*
|
|
24
|
-
* `apiEnv: false` skips the `apps/api/.env` line — a spoke (#7426 D6)
|
|
25
|
-
* `apps/api
|
|
24
|
+
* `apiEnv: false` skips the `apps/api/.env` line — a spoke (#7426 D6) or any
|
|
25
|
+
* site without `apps/api` (#7779) keeps the key in `ailk.key` alone.
|
|
26
|
+
*
|
|
27
|
+
* Returns the key files it holds the key in, relative to `dir`
|
|
28
|
+
* (`LICENSE_KEY_FILE`, then `LICENSE_ENV_FILE` when written).
|
|
26
29
|
*/
|
|
27
30
|
export declare function writeLicenseKeyFiles(dir: string, key: string, opts?: {
|
|
28
31
|
apiEnv?: boolean;
|
|
29
|
-
}):
|
|
32
|
+
}): string[];
|
|
@@ -86,16 +86,21 @@ function upsertEnvLine(existing, key) {
|
|
|
86
86
|
* `ailk.key` when no existing line covers it. Idempotent — a second call with
|
|
87
87
|
* the same key changes no byte.
|
|
88
88
|
*
|
|
89
|
-
* `apiEnv: false` skips the `apps/api/.env` line — a spoke (#7426 D6)
|
|
90
|
-
* `apps/api
|
|
89
|
+
* `apiEnv: false` skips the `apps/api/.env` line — a spoke (#7426 D6) or any
|
|
90
|
+
* site without `apps/api` (#7779) keeps the key in `ailk.key` alone.
|
|
91
|
+
*
|
|
92
|
+
* Returns the key files it holds the key in, relative to `dir`
|
|
93
|
+
* (`LICENSE_KEY_FILE`, then `LICENSE_ENV_FILE` when written).
|
|
91
94
|
*/
|
|
92
95
|
export function writeLicenseKeyFiles(dir, key, opts = {}) {
|
|
93
96
|
assertLicenseKeyShape(key);
|
|
94
97
|
writeOwnerOnly(join(dir, LICENSE_KEY_FILE), `${key}\n`);
|
|
98
|
+
const written = [LICENSE_KEY_FILE];
|
|
95
99
|
if (opts.apiEnv !== false) {
|
|
96
100
|
const envPath = join(dir, LICENSE_ENV_FILE);
|
|
97
101
|
const env = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
|
|
98
102
|
writeOwnerOnly(envPath, upsertEnvLine(env, key));
|
|
103
|
+
written.push(LICENSE_ENV_FILE);
|
|
99
104
|
}
|
|
100
105
|
const ignorePath = join(dir, ".gitignore");
|
|
101
106
|
const ignore = existsSync(ignorePath) ? readFileSync(ignorePath, "utf8") : "";
|
|
@@ -104,4 +109,5 @@ export function writeLicenseKeyFiles(dir, key, opts = {}) {
|
|
|
104
109
|
.some((l) => KEY_IGNORE_LINES.has(l.trim()));
|
|
105
110
|
if (!covered)
|
|
106
111
|
writeFileSync(ignorePath, appendLine(ignore, LICENSE_KEY_FILE));
|
|
112
|
+
return written;
|
|
107
113
|
}
|
|
@@ -53,6 +53,15 @@ export declare function assessClaimGatedRoute(input: {
|
|
|
53
53
|
hops: RedirectHop[];
|
|
54
54
|
status: number | null;
|
|
55
55
|
}): SweepVerdict;
|
|
56
|
+
/**
|
|
57
|
+
* A `redirect()` thrown by a Server Component after the shell has flushed is
|
|
58
|
+
* not an HTTP 3xx: the response is a 200 whose flight payload carries the
|
|
59
|
+
* digest `NEXT_REDIRECT;<replace|push>;<url>;<status>;`. The driver follows it
|
|
60
|
+
* as a hop exactly like a `Location` header (#8311 — `/account/settings`
|
|
61
|
+
* forwards to `/account/general` this way). Null when the HTML carries no
|
|
62
|
+
* such digest.
|
|
63
|
+
*/
|
|
64
|
+
export declare function streamedRedirect(html: string): RedirectHop | null;
|
|
56
65
|
/**
|
|
57
66
|
* Decide whether a page route rendered, under the real locale, with its own
|
|
58
67
|
* content. The first failed rule is the reason:
|
|
@@ -122,6 +122,24 @@ function htmlLang(html) {
|
|
|
122
122
|
function flightDigest(html) {
|
|
123
123
|
return /\\"digest\\":\\"([^"\\]*)\\"/.exec(html)?.[1] ?? null;
|
|
124
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* A `redirect()` thrown by a Server Component after the shell has flushed is
|
|
127
|
+
* not an HTTP 3xx: the response is a 200 whose flight payload carries the
|
|
128
|
+
* digest `NEXT_REDIRECT;<replace|push>;<url>;<status>;`. The driver follows it
|
|
129
|
+
* as a hop exactly like a `Location` header (#8311 — `/account/settings`
|
|
130
|
+
* forwards to `/account/general` this way). Null when the HTML carries no
|
|
131
|
+
* such digest.
|
|
132
|
+
*/
|
|
133
|
+
export function streamedRedirect(html) {
|
|
134
|
+
const digest = flightDigest(html);
|
|
135
|
+
if (digest === null || !digest.startsWith("NEXT_REDIRECT;"))
|
|
136
|
+
return null;
|
|
137
|
+
const [, , location = "", status = ""] = digest.split(";");
|
|
138
|
+
if (location === "")
|
|
139
|
+
return null;
|
|
140
|
+
const code = Number.parseInt(status, 10);
|
|
141
|
+
return { status: Number.isFinite(code) ? code : 307, location };
|
|
142
|
+
}
|
|
125
143
|
/**
|
|
126
144
|
* Whether an `<h1>`'s inner HTML carries a name: text once tags are stripped,
|
|
127
145
|
* or an image with a non-empty `alt` (the Hero's lockup renders the wordmark
|
|
@@ -170,9 +188,12 @@ export function assessPageRender(input) {
|
|
|
170
188
|
return { ok: false, reason: `${route} -> rendered under locale "${lang}"` };
|
|
171
189
|
const digest = flightDigest(html);
|
|
172
190
|
if (digest !== null) {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
const redirect = streamedRedirect(html);
|
|
192
|
+
const why = redirect !== null
|
|
193
|
+
? `streamed redirect to ${redirect.location} that was not followed`
|
|
194
|
+
: digest.startsWith("NEXT_HTTP_ERROR_FALLBACK;404")
|
|
195
|
+
? "streamed not-found"
|
|
196
|
+
: `streamed error (digest ${digest})`;
|
|
176
197
|
return { ok: false, reason: `${route} -> ${why}` };
|
|
177
198
|
}
|
|
178
199
|
const marker = ownContentMarker(html);
|
package/dist/license-set.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface LicenseSetIO {
|
|
|
24
24
|
/** Defaults to `spawnSync` with `shell: false` (see `defaultRunner`). */
|
|
25
25
|
runner?: LicenseSetRunner;
|
|
26
26
|
}
|
|
27
|
-
export declare const LICENSE_SET_HELP = "create-ailk license set \u2014 put your licence key into an existing site.\n\nUsage:\n pnpm create ailk@latest license set <key> [<target-dir>]\n pnpm create ailk@latest license set - [<target-dir>] < key.txt\n\nArguments:\n <key> Your licence key, or `-` to read it from stdin\n (keeps it out of your shell history).\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nWrites the key to ailk.key and apps/api/.env (owner-only, gitignored). When the
|
|
27
|
+
export declare const LICENSE_SET_HELP = "create-ailk license set \u2014 put your licence key into an existing site.\n\nUsage:\n pnpm create ailk@latest license set <key> [<target-dir>]\n pnpm create ailk@latest license set - [<target-dir>] < key.txt\n\nArguments:\n <key> Your licence key, or `-` to read it from stdin\n (keeps it out of your shell history).\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nWrites the key to ailk.key, and to apps/api/.env when the site has apps/api\n(owner-only, gitignored). When the site (or apps/api, or apps/web) is linked to\nVercel, it also replaces the production AILK_LICENSE_KEY variable and redeploys.\n";
|
|
28
28
|
/** `spawnSync`, never through a shell; stdin piped only when there is input. */
|
|
29
29
|
export declare const defaultRunner: LicenseSetRunner;
|
|
30
30
|
/**
|
package/dist/license-set.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 1. The target (default: cwd) must contain `architecture.yaml` — the
|
|
9
9
|
* `sync-routes` precondition — else exit 1 with nothing written.
|
|
10
|
-
* 2. `writeLicenseKeyFiles` — `ailk.key
|
|
11
|
-
* gitignored; the same
|
|
10
|
+
* 2. `writeLicenseKeyFiles` — `ailk.key`, plus `apps/api/.env` only when
|
|
11
|
+
* `apps/api` already exists (#7779), both 0600 and gitignored; the same
|
|
12
|
+
* writer `--license` uses. The output names only the files written.
|
|
12
13
|
* 3. For each of `<dir>`, `<dir>/apps/api`, `<dir>/apps/web` holding
|
|
13
14
|
* `.vercel/project.json`, with that directory as `cwd`:
|
|
14
15
|
* a. print the linked `projectId` about to change (SEC-13);
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
import { spawnSync } from "node:child_process";
|
|
32
33
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
33
34
|
import { join, relative, resolve } from "node:path";
|
|
34
|
-
import {
|
|
35
|
+
import { LICENSE_ENV_VAR, LICENSE_KEY_FILE, assertLicenseKeyShape, writeLicenseKeyFiles, } from "./lib/license-key-files.js";
|
|
35
36
|
export const LICENSE_SET_HELP = `create-ailk license set — put your licence key into an existing site.
|
|
36
37
|
|
|
37
38
|
Usage:
|
|
@@ -44,9 +45,9 @@ Arguments:
|
|
|
44
45
|
<target-dir> An already-scaffolded repo (contains
|
|
45
46
|
architecture.yaml). Defaults to the current dir.
|
|
46
47
|
|
|
47
|
-
Writes the key to ailk.key and apps/api/.env
|
|
48
|
-
site (or apps/api, or apps/web) is linked to
|
|
49
|
-
production AILK_LICENSE_KEY variable and redeploys.
|
|
48
|
+
Writes the key to ailk.key, and to apps/api/.env when the site has apps/api
|
|
49
|
+
(owner-only, gitignored). When the site (or apps/api, or apps/web) is linked to
|
|
50
|
+
Vercel, it also replaces the production AILK_LICENSE_KEY variable and redeploys.
|
|
50
51
|
`;
|
|
51
52
|
const LINK_DIRS = [".", join("apps", "api"), join("apps", "web")];
|
|
52
53
|
const VERCELIGNORE_LINES = [LICENSE_KEY_FILE, ".env"];
|
|
@@ -151,9 +152,13 @@ export function runLicenseSet(argv, io) {
|
|
|
151
152
|
if (!existsSync(join(target, "architecture.yaml"))) {
|
|
152
153
|
return fail(`not a scaffolded repo: no architecture.yaml at ${target}. Run it from your site's root, or pass the site's directory.`);
|
|
153
154
|
}
|
|
154
|
-
|
|
155
|
+
// A site without apps/api (a web-only spoke) keeps the key in ailk.key
|
|
156
|
+
// alone — writing apps/api/.env would create an app directory it never had.
|
|
157
|
+
const files = writeLicenseKeyFiles(target, key, {
|
|
158
|
+
apiEnv: existsSync(join(target, "apps", "api")),
|
|
159
|
+
});
|
|
155
160
|
const keyFile = join(target, LICENSE_KEY_FILE);
|
|
156
|
-
const written = `Wrote ${
|
|
161
|
+
const written = `Wrote ${files.map((f) => f.split("\\").join("/")).join(" and ")} in ${target}`;
|
|
157
162
|
io.stdout(`[create-ailk] ${written} (owner-only, gitignored).\n`);
|
|
158
163
|
const linked = LINK_DIRS.map((d) => join(target, d)).filter((d) => existsSync(join(d, ".vercel", "project.json")));
|
|
159
164
|
if (linked.length === 0) {
|
|
@@ -157,15 +157,41 @@ export const ARCHITECTURE_BASE = {
|
|
|
157
157
|
* file behind it — the three operator route files, the two member route
|
|
158
158
|
* files, the member resolution (`services/member-area.ts`) and the member
|
|
159
159
|
* data boundary (`lib/member-store.ts`).
|
|
160
|
+
*
|
|
161
|
+
* #8169 D9 adds the five Phase 1 member reads registered under that same
|
|
162
|
+
* disjunction. Its two other reads — `routes/member/meeting-types.ts` and
|
|
163
|
+
* `availability.ts` — reach `services/scheduling/`, so they are the
|
|
164
|
+
* `scheduling` slice's, not listed here.
|
|
165
|
+
*
|
|
166
|
+
* #8170 D11 adds the four member writes registered under that same
|
|
167
|
+
* disjunction (the message POST rides `messages.ts`). The fifth —
|
|
168
|
+
* `routes/member/bookings.ts` — reaches `services/scheduling/`, so it is the
|
|
169
|
+
* `scheduling` slice's.
|
|
160
170
|
*/
|
|
161
171
|
const MEMBER_AREA_FILES = [
|
|
162
172
|
"apps/api/src/routes/workspaces/pieces.ts",
|
|
163
173
|
"apps/api/src/routes/workspaces/plan.ts",
|
|
164
174
|
"apps/api/src/routes/workspaces/messages-out.ts",
|
|
175
|
+
// #8171 D8 — the workspace Requests read; imports only pieces.ts,
|
|
176
|
+
// lib/tenant-db.ts and @working-theory/validation.
|
|
177
|
+
"apps/api/src/routes/workspaces/requests.ts",
|
|
165
178
|
"apps/api/src/routes/member/pieces.ts",
|
|
166
179
|
"apps/api/src/routes/member/messages.ts",
|
|
180
|
+
"apps/api/src/routes/member/purchases.ts",
|
|
181
|
+
"apps/api/src/routes/member/appointments.ts",
|
|
182
|
+
"apps/api/src/routes/member/artifacts.ts",
|
|
183
|
+
"apps/api/src/routes/member/request-form.ts",
|
|
184
|
+
"apps/api/src/routes/member/billing.ts",
|
|
185
|
+
"apps/api/src/routes/member/requests.ts",
|
|
186
|
+
"apps/api/src/routes/member/artifact-review.ts",
|
|
187
|
+
"apps/api/src/routes/member/profile.ts",
|
|
188
|
+
"apps/api/src/routes/member/deletion-request.ts",
|
|
167
189
|
"apps/api/src/services/member-area.ts",
|
|
168
190
|
"apps/api/src/lib/member-store.ts",
|
|
191
|
+
// #8226 D12 — the member-request match CLI; both import member-store.ts,
|
|
192
|
+
// which a build without the member slice does not carry.
|
|
193
|
+
"apps/api/src/lib/member-request-match.ts",
|
|
194
|
+
"apps/api/src/bin/member-request-match.ts",
|
|
169
195
|
];
|
|
170
196
|
/**
|
|
171
197
|
* The workspace asset store (#5854), CO-OWNED by the `workspace` and
|
|
@@ -864,6 +890,18 @@ export const MODULE_SLICES = {
|
|
|
864
890
|
"apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx",
|
|
865
891
|
"apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx",
|
|
866
892
|
"apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx",
|
|
893
|
+
// #7389 — the three api suites that enable `multi-tenant` ALONE and so
|
|
894
|
+
// reach files this slice delivers (`services/tenant-context.ts` and the
|
|
895
|
+
// `routes/workspaces/` index). Each is listed individually, never as a
|
|
896
|
+
// glob (the `scheduling` slice's § D12 property 1: a glob entry is a
|
|
897
|
+
// silent no-op), so it ships to a keyed scaffold with the slice and is
|
|
898
|
+
// stripped from a keyless one with it — instead of a keyless scaffold
|
|
899
|
+
// carrying a test that raises `createNoMappedModuleFoundError`. A suite
|
|
900
|
+
// that enables SEVERAL paid modules cannot be owned by any one of
|
|
901
|
+
// them; those are `EXCLUDE_TEMPLATE_DIRS` entries below.
|
|
902
|
+
"apps/api/src/services/__tests__/lead-promotion.test.ts",
|
|
903
|
+
"apps/api/src/services/__tests__/leads-inbox.test.ts",
|
|
904
|
+
"apps/api/src/__tests__/content-write-production-boot.test.ts",
|
|
867
905
|
"apps-paid/admin/**",
|
|
868
906
|
],
|
|
869
907
|
// The whole-app glob above lands its files at their REPO-relative path
|
|
@@ -1232,6 +1270,13 @@ export const MODULE_SLICES = {
|
|
|
1232
1270
|
// records: "each tenancy slice must deliver it").
|
|
1233
1271
|
"apps/api/src/lib/tenant-db.ts",
|
|
1234
1272
|
"apps/api/src/services/tenant-context.ts",
|
|
1273
|
+
// #7389 — `routes/workspaces/__tests__/meetings.test.ts` and
|
|
1274
|
+
// `meetings-connection.test.ts` (listed below) register the real
|
|
1275
|
+
// `tenantPreHandlerPlugin` in front of `meetings.ts`, so a scheduling
|
|
1276
|
+
// scaffold without `multi-tenant` could not load them. It imports only
|
|
1277
|
+
// `services/tenant-context.ts` (owned above) and the base
|
|
1278
|
+
// `default-tenant.ts`, so co-owning it keeps the closure tight.
|
|
1279
|
+
"apps/api/src/middleware/tenant.ts",
|
|
1235
1280
|
// #7533 — a scheduling connection per workspace. `connections.ts` (the
|
|
1236
1281
|
// cipher + the one SchedulingConnection data-access boundary) and
|
|
1237
1282
|
// `resolve.ts` (the workspace-aware provider resolution the meetings,
|
|
@@ -1248,6 +1293,23 @@ export const MODULE_SLICES = {
|
|
|
1248
1293
|
"apps/api/src/routes/schedule/__tests__/public-connection.test.ts",
|
|
1249
1294
|
"apps/api/src/routes/webhooks/__tests__/calcom-connection.test.ts",
|
|
1250
1295
|
"apps/api/src/config/__tests__/scheduling-credential-key.test.ts",
|
|
1296
|
+
// #8169 D9 — the two member reads that reach `services/scheduling/`,
|
|
1297
|
+
// registered under `scheduling && (workspace || multi-tenant)`, plus
|
|
1298
|
+
// the three member files they import, which this slice then CO-OWNS
|
|
1299
|
+
// with the two tenancy slices (`MEMBER_AREA_FILES`) — exactly as it
|
|
1300
|
+
// co-owns `lib/tenant-db.ts` for `routes/workspaces/meetings.ts` above.
|
|
1301
|
+
"apps/api/src/routes/member/meeting-types.ts",
|
|
1302
|
+
"apps/api/src/routes/member/availability.ts",
|
|
1303
|
+
// #8170 D11 — the member booking, the same shape.
|
|
1304
|
+
"apps/api/src/routes/member/bookings.ts",
|
|
1305
|
+
"apps/api/src/routes/member/pieces.ts",
|
|
1306
|
+
"apps/api/src/services/member-area.ts",
|
|
1307
|
+
"apps/api/src/lib/member-store.ts",
|
|
1308
|
+
// #7389 — the two api suites that enable `scheduling` alone, so they
|
|
1309
|
+
// strip with `routes/schedule/index.ts`, which they load by a computed
|
|
1310
|
+
// specifier the import-graph closure cannot follow.
|
|
1311
|
+
"apps/api/src/__tests__/schedule-forwarded-rate-limit.test.ts",
|
|
1312
|
+
"apps/api/src/__tests__/openapi-keyless-hub.test.ts",
|
|
1251
1313
|
],
|
|
1252
1314
|
// pageContributions (spec 5478; parent § D6 shape 1) — the booker, the
|
|
1253
1315
|
// per-booking-type page and the confirmation page, whose route files
|
|
@@ -1463,6 +1525,10 @@ export const MODULE_SLICES = {
|
|
|
1463
1525
|
"apps/api/src/bin/listing-csv-sweep.ts",
|
|
1464
1526
|
"apps/api/src/bin/followup-sweep.ts",
|
|
1465
1527
|
"apps/api/src/bin/seed-waitlist-experiments.ts",
|
|
1528
|
+
// #7389 — the listing-directory suite enables `signal-collectors` alone
|
|
1529
|
+
// and loads `routes/waitlist-signups/index.ts` through the server it
|
|
1530
|
+
// builds, so it strips with that route. Individually, never as a glob.
|
|
1531
|
+
"apps/api/src/routes/project-listings/__tests__/directory.test.ts",
|
|
1466
1532
|
"apps/mcp/src/tools/get_flow.ts",
|
|
1467
1533
|
"apps/mcp/src/tools/submit_flow_step.ts",
|
|
1468
1534
|
// #3591 PR-E — the signed-in MCP tools that twin the tenant-scoped
|
|
@@ -2013,6 +2079,44 @@ export function coOwnedModuleDestinations() {
|
|
|
2013
2079
|
// docs/specs/7315-a-gated-pro-tool-re-spec.md D4) — same reason as the
|
|
2014
2080
|
// three suites above: it imports `SITE_ARGS` from the monorepo's root
|
|
2015
2081
|
// `tests/parity/` tree, which no scaffold carries.
|
|
2082
|
+
// - apps/mcp/__tests__/write-tool-guard.test.ts (#8071, spec
|
|
2083
|
+
// docs/specs/8071-mcp-write-guard-spec.md D4) — it reads every anonymous
|
|
2084
|
+
// catalog tool's handler file, and a scaffold carries only the handler
|
|
2085
|
+
// files of the modules it selected while the catalog lists every tool.
|
|
2086
|
+
// `WRITE_TOOLS` is edited in the monorepo, which is where it must run.
|
|
2087
|
+
// - the suites a keyless scaffold's own `pnpm test` cannot run (#7389) —
|
|
2088
|
+
// file entries, matched exactly. Two classes, neither of which a slice can
|
|
2089
|
+
// own (a slice's `ownedFiles` carries a suite that needs ONE paid module;
|
|
2090
|
+
// the six api suites that do are listed under `multi-tenant`, `scheduling`
|
|
2091
|
+
// and `signal-collectors` above, and a keyed scaffold runs them):
|
|
2092
|
+
// * monorepo fixtures — each reads a path only this repo has:
|
|
2093
|
+
// `services/__tests__/aeo-score.test.ts` (packages/aeo's result.json),
|
|
2094
|
+
// `routes/leads/__tests__/index.test.ts` (packages/validation's
|
|
2095
|
+
// newsletter-lead fixture), `routes/workspaces/__tests__/
|
|
2096
|
+
// inbox-wire-schemas.test.ts` (the root `tests/parity/` core),
|
|
2097
|
+
// mcp's `workspace-surface.test.ts` (the same core) and mcp's
|
|
2098
|
+
// `audit.test.ts` (the T1 fixture site's `project.yaml`).
|
|
2099
|
+
// * whole-composition suites — each builds the real server or reads
|
|
2100
|
+
// the whole tree under SEVERAL module sets, or asserts the
|
|
2101
|
+
// monorepo's own identity, so no single slice is its owner and a
|
|
2102
|
+
// scaffold that selected only some of the modules would fail it:
|
|
2103
|
+
// `server.test.ts` (asserts the monorepo's "AI Launch Kit API" name,
|
|
2104
|
+
// and a `signal-collectors` case), `cors.test.ts` (multi-tenant +
|
|
2105
|
+
// scheduling), `root-modules.test.ts`, `module-exclusion.test.ts`,
|
|
2106
|
+
// `openapi/__tests__/surface-drift.test.ts`,
|
|
2107
|
+
// `review-surface-registration.test.ts` and
|
|
2108
|
+
// `workspace-module-registration.test.ts` (each a matrix over module
|
|
2109
|
+
// sets), and mcp's `parity.test.ts` (counts the Server Actions and
|
|
2110
|
+
// tool handlers of the FULL tree, which a stripped scaffold lacks).
|
|
2111
|
+
// The exclusion is per file, not a `testPathIgnorePatterns` entry in the
|
|
2112
|
+
// scaffold's jest config: that would hide these suites from a keyed
|
|
2113
|
+
// scaffold too, and from the suites a slice owns.
|
|
2114
|
+
// - database/__tests__/build.test.ts (#7959) — the monorepo build probe
|
|
2115
|
+
// (#7565). Its `beforeAll` symlinks `REPO_ROOT/packages` and copies
|
|
2116
|
+
// `REPO_ROOT/tsconfig.base.json`, neither of which a scaffold has, so it
|
|
2117
|
+
// red the scaffold's database jest run. Matched exactly, not by basename
|
|
2118
|
+
// in `EXCLUDE_FILES`, which would drop a `build.test.ts` anywhere in the
|
|
2119
|
+
// snapshot; every other database suite still ships.
|
|
2016
2120
|
export const EXCLUDE_TEMPLATE_DIRS = [
|
|
2017
2121
|
"apps/web/__tests__",
|
|
2018
2122
|
"apps/web/app/__tests__",
|
|
@@ -2023,6 +2127,21 @@ export const EXCLUDE_TEMPLATE_DIRS = [
|
|
|
2023
2127
|
"apps/api/src/__tests__/api-parity-paid.test.ts",
|
|
2024
2128
|
"apps/mcp/__tests__/api-parity.test.ts",
|
|
2025
2129
|
"apps/mcp/__tests__/pro-tool-call-gate.test.ts",
|
|
2130
|
+
"apps/mcp/__tests__/write-tool-guard.test.ts",
|
|
2131
|
+
"apps/api/src/services/__tests__/aeo-score.test.ts",
|
|
2132
|
+
"apps/api/src/routes/leads/__tests__/index.test.ts",
|
|
2133
|
+
"apps/api/src/routes/workspaces/__tests__/inbox-wire-schemas.test.ts",
|
|
2134
|
+
"apps/api/src/__tests__/server.test.ts",
|
|
2135
|
+
"apps/api/src/__tests__/cors.test.ts",
|
|
2136
|
+
"apps/api/src/__tests__/root-modules.test.ts",
|
|
2137
|
+
"apps/api/src/__tests__/module-exclusion.test.ts",
|
|
2138
|
+
"apps/api/src/openapi/__tests__/surface-drift.test.ts",
|
|
2139
|
+
"apps/api/src/__tests__/review-surface-registration.test.ts",
|
|
2140
|
+
"apps/api/src/__tests__/workspace-module-registration.test.ts",
|
|
2141
|
+
"apps/mcp/__tests__/workspace-surface.test.ts",
|
|
2142
|
+
"apps/mcp/__tests__/parity.test.ts",
|
|
2143
|
+
"apps/mcp/__tests__/audit.test.ts",
|
|
2144
|
+
"database/__tests__/build.test.ts",
|
|
2026
2145
|
];
|
|
2027
2146
|
export function paidModuleTemplateExclusions(snapshotRoots, repoRoot) {
|
|
2028
2147
|
const roots = new Set(snapshotRoots);
|
package/dist/programmatic.js
CHANGED
|
@@ -747,11 +747,14 @@ export async function scaffold(opts) {
|
|
|
747
747
|
// two return pages, once every layer has landed (so the spoke filter has
|
|
748
748
|
// already dropped the hub-checkout files) and before the manifest, whose
|
|
749
749
|
// code-route rows then record /checkout/thank-you and /checkout/unavailable.
|
|
750
|
+
// #8217 D8 — a spoke that signs in through its hub also gets the billing
|
|
751
|
+
// action and the web seam render that reaches it.
|
|
750
752
|
const spokeCommerce = spoke !== undefined && result.modules.includes("commerce");
|
|
751
753
|
if (spokeCommerce) {
|
|
752
754
|
writeSpokeCheckoutSlice(result.targetDir, {
|
|
753
755
|
site: spokeCheckoutSite(projectName),
|
|
754
756
|
versions,
|
|
757
|
+
signIn: spoke.signIn,
|
|
755
758
|
});
|
|
756
759
|
}
|
|
757
760
|
// #6944 — the manifest records what this scaffold IS, once every layer has
|
package/dist/spoke-checkout.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EnvCatalogEntry, PlanEnvRowsOptions } from "./lib/declared-env.js";
|
|
2
2
|
import { type InstallReportRow } from "./lib/extract-module-bundle.js";
|
|
3
3
|
import { type WorkspaceVersionMap } from "./substitute.js";
|
|
4
|
+
import { type SignInMode } from "./topology.js";
|
|
4
5
|
/** The checkout package a spoke's two route files import. */
|
|
5
6
|
export declare const SPOKE_CHECKOUT_PACKAGE = "@working-theory/spoke-checkout";
|
|
6
7
|
/** The site's checkout data — written once, the site's from then on. */
|
|
@@ -48,13 +49,19 @@ export declare const CHECKOUT_E2E_WORKFLOW: string;
|
|
|
48
49
|
/**
|
|
49
50
|
* The slice for `site`, in order: the two route files, the config, the two
|
|
50
51
|
* pages (D3), then the checkout e2e workflow (#7839 D8), which does not
|
|
51
|
-
* depend on `site`.
|
|
52
|
+
* depend on `site`. With `signIn: "hub"` the billing action is the third
|
|
53
|
+
* pair, so the first three paths are `SPOKE_CHECKOUT_ROUTE_FILES` (#8217 D8).
|
|
54
|
+
* Throws `TopologyError` for an invalid stamp (SEC-7838-10).
|
|
52
55
|
*/
|
|
53
|
-
export declare function renderSpokeCheckoutFiles(site: string
|
|
56
|
+
export declare function renderSpokeCheckoutFiles(site: string, opts?: {
|
|
57
|
+
signIn?: SignInMode | undefined;
|
|
58
|
+
}): [string, string][];
|
|
54
59
|
/**
|
|
55
60
|
* Write the slice into `targetDir` (D3). A file that already exists is left
|
|
56
61
|
* byte-for-byte and reported `skipped` — the config is the site's once
|
|
57
|
-
* written.
|
|
62
|
+
* written. With `signIn: "hub"` (#8217 D8) the slice carries the billing
|
|
63
|
+
* action, and the web seam — generated, so always rewritten — becomes the
|
|
64
|
+
* billing render: reported `patched` when it changed, not at all when equal. Adds the package to `apps/web/package.json` when absent, and
|
|
58
65
|
* raises a plain pin older than the one it writes (#7839): the generated
|
|
59
66
|
* checkout e2e workflow runs a command a `^0.2.0` pin never reaches. Any
|
|
60
67
|
* other range — newer, `workspace:`, a tag — is the site's and is kept.
|
|
@@ -64,4 +71,5 @@ export declare function renderSpokeCheckoutFiles(site: string): [string, string]
|
|
|
64
71
|
export declare function writeSpokeCheckoutSlice(targetDir: string, opts: {
|
|
65
72
|
site: string;
|
|
66
73
|
versions: WorkspaceVersionMap;
|
|
74
|
+
signIn?: SignInMode | undefined;
|
|
67
75
|
}): InstallReportRow[];
|