create-ailk 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -5
- package/NOTICE +2 -0
- package/dist/add-module.js +11 -3
- 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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- 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 +32 -0
- package/dist/lib/scaffold-render-sweep.js +76 -3
- package/dist/license-set.d.ts +1 -1
- package/dist/license-set.js +13 -8
- package/dist/module-architecture.js +128 -3
- package/dist/programmatic.js +11 -1
- package/dist/site-roster.js +21 -4
- 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.d.ts +14 -0
- package/dist/surfaces.js +170 -1
- package/dist/template-manifest.d.ts +4 -3
- package/dist/topology.d.ts +7 -2
- package/dist/topology.js +88 -3
- package/package.json +5 -4
- package/templates/.env.example +3 -3
- package/templates/.github/workflows/ci.yml +5 -0
- package/templates/apps/api/.env.example +17 -1
- package/templates/apps/api/CLAUDE.md +31 -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/__tests__/factories/in-memory-prisma.ts +19 -0
- package/templates/apps/api/src/__tests__/stripe-boot.test.ts +132 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +17 -0
- package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +237 -0
- package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +334 -0
- package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +38 -0
- package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +217 -0
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +7 -0
- package/templates/apps/api/src/lib/consent-store.ts +335 -0
- package/templates/apps/api/src/lib/deliverable-asset-store.ts +5 -4
- package/templates/apps/api/src/lib/stripe.ts +176 -3
- package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +272 -39
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +51 -0
- package/templates/apps/api/src/middleware/auth.ts +214 -46
- package/templates/apps/api/src/middleware/rate-limit.ts +5 -0
- package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +167 -0
- package/templates/apps/api/src/routes/checkout/session.ts +3 -3
- package/templates/apps/api/src/routes/checkout/sessions.ts +6 -4
- package/templates/apps/api/src/routes/consent/cookie.ts +90 -0
- package/templates/apps/api/src/routes/consent/index.ts +18 -0
- package/templates/apps/api/src/routes/consent/unsubscribe.ts +127 -0
- package/templates/apps/api/src/routes/leads/index.ts +19 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +5 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +17 -4
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +2 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +159 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +158 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +2 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +17 -0
- package/templates/apps/api/src/server.ts +218 -16
- package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +503 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +18 -3
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +173 -4
- package/templates/apps/api/src/services/__tests__/person.test.ts +392 -0
- package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +87 -0
- package/templates/apps/api/src/services/__tests__/revalidation.test.ts +57 -17
- package/templates/apps/api/src/services/consent.ts +488 -3
- package/templates/apps/api/src/services/lead-routing.ts +135 -14
- package/templates/apps/api/src/services/person.ts +501 -1
- package/templates/apps/api/src/services/project-listings.ts +7 -2
- package/templates/apps/api/src/services/request-confirm.ts +52 -0
- package/templates/apps/api/src/services/revalidation.ts +11 -1
- 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__/account-frame-sign-out.test.tsx +175 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/billing.test.tsx +302 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/general.test.tsx +724 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/hub-mode.test.tsx +346 -41
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/item.test.tsx +11 -13
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/layout-sign-out.test.tsx +146 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/layout.test.tsx +232 -29
- 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 +140 -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 +409 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/settings.test.tsx +65 -380
- 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 +188 -54
- 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 +174 -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/contact-actions.ts +81 -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 +193 -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 +30 -4
- 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 +132 -0
- package/templates/apps/web/app/[locale]/(authed)/account/security/security-panel.tsx +102 -0
- package/templates/apps/web/app/[locale]/(authed)/account/security/security-source.ts +62 -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 +116 -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 +25 -2
- package/templates/apps/web/lib/__tests__/account-config.test.ts +258 -46
- package/templates/apps/web/lib/__tests__/auth-email.test.ts +84 -0
- package/templates/apps/web/lib/account-config.ts +188 -52
- package/templates/apps/web/lib/auth-email.ts +45 -10
- 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 +33 -0
- package/templates/apps/web/messages/en.json +194 -33
- package/templates/database/CHANGELOG.md +37 -0
- package/templates/database/LICENSE +6 -5
- package/templates/database/NOTICE +2 -0
- package/templates/database/README.md +1 -1
- package/templates/database/__tests__/consent-ledger.db.test.ts +345 -0
- package/templates/database/__tests__/fence-fan-out.db.test.ts +6 -2
- package/templates/database/__tests__/fixtures/person-contact-backfill.json +182 -0
- 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__/person-contact.db.test.ts +563 -0
- package/templates/database/__tests__/person.db.test.ts +3 -1
- package/templates/database/__tests__/seed.test.ts +54 -2
- package/templates/database/inbox/schema.prisma +166 -25
- 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/migrations/20261014120000_consent_ledger/migration.sql +122 -0
- package/templates/database/migrations/20261014120000_person_contact/migration.sql +231 -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/dist/surfaces.js
CHANGED
|
@@ -503,6 +503,31 @@ export function excludedContentPaths(enabled) {
|
|
|
503
503
|
}
|
|
504
504
|
return out.sort();
|
|
505
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* True when `path` (scaffold-relative, `/`-separated) lies inside one of the
|
|
508
|
+
* content directories `excludedContentPaths(enabled)` names, with `<locale>`
|
|
509
|
+
* matching any one path segment (#8427 D4).
|
|
510
|
+
*
|
|
511
|
+
* This is `excludedContentPaths`' first non-export reader — its own comment
|
|
512
|
+
* already named exactly this class ("orphan content makes `/sitemap.xml`
|
|
513
|
+
* advertise URLs that 404"). It is wired into the `skip` predicate
|
|
514
|
+
* `extractModuleBundle` already takes (`programmatic.ts`, `add-module.ts`),
|
|
515
|
+
* and into `layerInstalledSeeds`'s installed-seed count (`site-roster.ts`),
|
|
516
|
+
* so a module bundle never writes — and a roster check never counts — a
|
|
517
|
+
* seed under a gateable surface the scaffold does not enable.
|
|
518
|
+
*/
|
|
519
|
+
export function isUnservedSurfaceContent(path, enabled) {
|
|
520
|
+
const segments = path.split("/");
|
|
521
|
+
for (const contentPath of excludedContentPaths([...enabled])) {
|
|
522
|
+
const prefixSegments = contentPath.split("/");
|
|
523
|
+
if (prefixSegments.length > segments.length)
|
|
524
|
+
continue;
|
|
525
|
+
const matches = prefixSegments.every((segment, i) => segment === "<locale>" || segment === segments[i]);
|
|
526
|
+
if (matches)
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
506
531
|
/**
|
|
507
532
|
* Route manifest (#4986): every template route directory, keyed relative to
|
|
508
533
|
* ROUTE_ROOT (`apps/web/app/[locale]`), → the `@working-theory/*` fixed-group
|
|
@@ -630,6 +655,23 @@ export const ROUTE_SINCE = {
|
|
|
630
655
|
// new, so it attaches at today's fixed-group version, the same rule #7430
|
|
631
656
|
// applied above.
|
|
632
657
|
"(authed)/account/inbox/message/[id]/file": "0.37.0",
|
|
658
|
+
// #8232 — User settings' two pages, General and Billing (the old
|
|
659
|
+
// `(authed)/account/settings` now redirects to General). Genuinely new, so
|
|
660
|
+
// they attach at today's fixed-group version, the same rule #7430 applied.
|
|
661
|
+
"(authed)/account/general": "0.38.0",
|
|
662
|
+
"(authed)/account/billing": "0.38.0",
|
|
663
|
+
// #8339 — User settings' two new tabs, Security and Notifications
|
|
664
|
+
// (General and Billing now render through the shared account-settings
|
|
665
|
+
// composition). Genuinely new, so they attach at today's fixed-group
|
|
666
|
+
// version, the same rule #7430/#8232 applied.
|
|
667
|
+
"(authed)/account/security": "0.38.0",
|
|
668
|
+
"(authed)/account/notifications": "0.38.0",
|
|
669
|
+
// #8234 — the member Artifacts pages and a version's file route. Genuinely
|
|
670
|
+
// new, so they attach at today's fixed-group version, the same rule #7430
|
|
671
|
+
// applied.
|
|
672
|
+
"(authed)/account/artifacts": "0.38.0",
|
|
673
|
+
"(authed)/account/artifacts/[pieceId]": "0.38.0",
|
|
674
|
+
"(authed)/account/artifacts/[pieceId]/versions/[version]/file": "0.38.0",
|
|
633
675
|
// The leads inbox (#5678). The ROUTE ships in every scaffold, Free
|
|
634
676
|
// included — lead capture is a never-gate surface, so reading a lead back
|
|
635
677
|
// is one too. Whether it shows a ROW is a separate question with two
|
|
@@ -759,24 +801,144 @@ export const ROUTE_DEPENDENCIES = {
|
|
|
759
801
|
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
760
802
|
`${ROUTE_ROOT}/(authed)/account/error-row.tsx`,
|
|
761
803
|
`${ROUTE_ROOT}/(authed)/account/retry-button.tsx`,
|
|
804
|
+
// #8233 C9 — the New menu's files beside account-config.ts: new-popups.tsx
|
|
805
|
+
// binds the config's actions to the popups, which import the menu and its
|
|
806
|
+
// server actions. (account-config.ts itself imports none of them — a
|
|
807
|
+
// spoke without sign-in drops the `(authed)` group and keeps the config.)
|
|
808
|
+
`${ROUTE_ROOT}/(authed)/account/new-menu.tsx`,
|
|
809
|
+
`${ROUTE_ROOT}/(authed)/account/new-actions.ts`,
|
|
810
|
+
`${ROUTE_ROOT}/(authed)/account/new-popups.tsx`,
|
|
811
|
+
`${ROUTE_ROOT}/(authed)/account/components/schedule-service.tsx`,
|
|
812
|
+
`${ROUTE_ROOT}/(authed)/account/components/request-quote.tsx`,
|
|
813
|
+
`${ROUTE_ROOT}/(authed)/account/components/send-message.tsx`,
|
|
762
814
|
],
|
|
763
815
|
// #7920 — the member file read re-serves the hub's bytes with the
|
|
764
816
|
// credential `forwardedCookieInit` returns.
|
|
765
817
|
"(authed)/account/inbox/message/[id]/file": ["apps/web/lib/server-api.ts"],
|
|
818
|
+
// #8232 D13 — the settings route is a redirect now; what it still imports
|
|
819
|
+
// from outside itself is `theme-modes.ts`'s theme reader and the brand file
|
|
820
|
+
// that reader imports.
|
|
766
821
|
"(authed)/account/settings": [
|
|
822
|
+
"apps/web/lib/site-brand.tsx",
|
|
823
|
+
"apps/web/lib/site-theme.ts",
|
|
824
|
+
],
|
|
825
|
+
// #8232 D13 — General and Billing import files in their parent's directory
|
|
826
|
+
// too. Each listed parent file is new in #8232 or unchanged by it, so a
|
|
827
|
+
// scaffold that already has one keeps a copy that still compiles; the
|
|
828
|
+
// settings components General changed moved into `general/` instead (C3).
|
|
829
|
+
// `profile-actions.ts` imports `lib/hub-session/reseal.ts` by its own path,
|
|
830
|
+
// since a scaffold's existing `lib/hub-session/index.ts` is never updated.
|
|
831
|
+
//
|
|
832
|
+
// #8339 D11 — `settings/color-mode.tsx` drops: General's own color-mode
|
|
833
|
+
// control is now the shared `AccountSettings` composition's
|
|
834
|
+
// (@working-theory/templates/account). `sign-in-method.ts` stays: General no
|
|
835
|
+
// longer renders the Sign-in section itself (moved to Security), but it
|
|
836
|
+
// still imports `sign-in-method.ts` transitively through
|
|
837
|
+
// `profile-source.ts`'s `via` derivation.
|
|
838
|
+
"(authed)/account/general": [
|
|
767
839
|
"apps/web/lib/account-config.ts",
|
|
768
840
|
"apps/web/lib/auth-env.ts",
|
|
769
841
|
"apps/web/lib/server-api.ts",
|
|
770
842
|
"apps/web/lib/site-brand.tsx",
|
|
771
843
|
"apps/web/lib/site-theme.ts",
|
|
844
|
+
"apps/web/lib/hub-session/reseal.ts",
|
|
772
845
|
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
773
|
-
`${ROUTE_ROOT}/(authed)/account/
|
|
846
|
+
`${ROUTE_ROOT}/(authed)/account/settings-frame.tsx`,
|
|
847
|
+
`${ROUTE_ROOT}/(authed)/account/sign-in-method.ts`,
|
|
848
|
+
`${ROUTE_ROOT}/(authed)/account/profile-actions.ts`,
|
|
849
|
+
`${ROUTE_ROOT}/(authed)/account/settings/theme-modes.ts`,
|
|
850
|
+
// #8233 C9 — the New menu's files beside account-config.ts: new-popups.tsx
|
|
851
|
+
// binds the config's actions to the popups, which import the menu and its
|
|
852
|
+
// server actions. (account-config.ts itself imports none of them — a
|
|
853
|
+
// spoke without sign-in drops the `(authed)` group and keeps the config.)
|
|
854
|
+
`${ROUTE_ROOT}/(authed)/account/new-menu.tsx`,
|
|
855
|
+
`${ROUTE_ROOT}/(authed)/account/new-actions.ts`,
|
|
856
|
+
`${ROUTE_ROOT}/(authed)/account/new-popups.tsx`,
|
|
857
|
+
`${ROUTE_ROOT}/(authed)/account/components/schedule-service.tsx`,
|
|
858
|
+
`${ROUTE_ROOT}/(authed)/account/components/request-quote.tsx`,
|
|
859
|
+
`${ROUTE_ROOT}/(authed)/account/components/send-message.tsx`,
|
|
860
|
+
],
|
|
861
|
+
// #8339 D11 — Security holds the former Sign-in section, moved verbatim
|
|
862
|
+
// from General: `sign-in-method.ts` and what it imports. #8431 D8 — the
|
|
863
|
+
// tab's failed-read row (`error-row.tsx` and its `retry-button.tsx`); its
|
|
864
|
+
// own `security-source.ts` and `security-panel.tsx` live in the route dir
|
|
865
|
+
// and copy with it.
|
|
866
|
+
"(authed)/account/security": [
|
|
867
|
+
"apps/web/lib/account-config.ts",
|
|
868
|
+
"apps/web/lib/auth-env.ts",
|
|
869
|
+
"apps/web/lib/server-api.ts",
|
|
870
|
+
"apps/web/lib/hub-session/config.ts",
|
|
871
|
+
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
872
|
+
`${ROUTE_ROOT}/(authed)/account/error-row.tsx`,
|
|
873
|
+
`${ROUTE_ROOT}/(authed)/account/retry-button.tsx`,
|
|
874
|
+
`${ROUTE_ROOT}/(authed)/account/settings-frame.tsx`,
|
|
875
|
+
`${ROUTE_ROOT}/(authed)/account/sign-in-method.ts`,
|
|
876
|
+
],
|
|
877
|
+
// #8339 D11 — Notifications holds the former Privacy section's
|
|
878
|
+
// cookie-settings link, moved verbatim from General.
|
|
879
|
+
"(authed)/account/notifications": [
|
|
880
|
+
"apps/web/lib/account-config.ts",
|
|
881
|
+
"apps/web/lib/server-api.ts",
|
|
882
|
+
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
883
|
+
`${ROUTE_ROOT}/(authed)/account/settings-frame.tsx`,
|
|
884
|
+
],
|
|
885
|
+
"(authed)/account/billing": [
|
|
886
|
+
"apps/web/lib/account-config.ts",
|
|
887
|
+
"apps/web/lib/server-api.ts",
|
|
888
|
+
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
889
|
+
`${ROUTE_ROOT}/(authed)/account/actions.ts`,
|
|
890
|
+
`${ROUTE_ROOT}/(authed)/account/error-row.tsx`,
|
|
891
|
+
`${ROUTE_ROOT}/(authed)/account/retry-button.tsx`,
|
|
892
|
+
`${ROUTE_ROOT}/(authed)/account/settings-frame.tsx`,
|
|
893
|
+
`${ROUTE_ROOT}/(authed)/account/billing-source.ts`,
|
|
894
|
+
// #8233 C9 — the New menu's files beside account-config.ts: new-popups.tsx
|
|
895
|
+
// binds the config's actions to the popups, which import the menu and its
|
|
896
|
+
// server actions. (account-config.ts itself imports none of them — a
|
|
897
|
+
// spoke without sign-in drops the `(authed)` group and keeps the config.)
|
|
898
|
+
`${ROUTE_ROOT}/(authed)/account/new-menu.tsx`,
|
|
899
|
+
`${ROUTE_ROOT}/(authed)/account/new-actions.ts`,
|
|
900
|
+
`${ROUTE_ROOT}/(authed)/account/new-popups.tsx`,
|
|
901
|
+
`${ROUTE_ROOT}/(authed)/account/components/schedule-service.tsx`,
|
|
902
|
+
`${ROUTE_ROOT}/(authed)/account/components/request-quote.tsx`,
|
|
903
|
+
`${ROUTE_ROOT}/(authed)/account/components/send-message.tsx`,
|
|
904
|
+
],
|
|
905
|
+
// #8234 — the Artifacts pages import files in their parent's directory, as
|
|
906
|
+
// #7430's children do; the artifact page also imports its own parent's
|
|
907
|
+
// `artifact-data.ts` and `artifact-actions.ts`, which an older synced
|
|
908
|
+
// `artifacts/` might lack. The file route re-serves the hub's bytes with
|
|
909
|
+
// the credential `forwardedCookieInit` returns.
|
|
910
|
+
"(authed)/account/artifacts": [
|
|
911
|
+
"apps/web/lib/account-config.ts",
|
|
912
|
+
"apps/web/lib/server-api.ts",
|
|
913
|
+
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
914
|
+
`${ROUTE_ROOT}/(authed)/account/error-row.tsx`,
|
|
915
|
+
`${ROUTE_ROOT}/(authed)/account/retry-button.tsx`,
|
|
916
|
+
],
|
|
917
|
+
"(authed)/account/artifacts/[pieceId]": [
|
|
918
|
+
"apps/web/lib/account-config.ts",
|
|
919
|
+
"apps/web/lib/server-api.ts",
|
|
920
|
+
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
921
|
+
`${ROUTE_ROOT}/(authed)/account/error-row.tsx`,
|
|
922
|
+
`${ROUTE_ROOT}/(authed)/account/retry-button.tsx`,
|
|
923
|
+
`${ROUTE_ROOT}/(authed)/account/artifacts/artifact-data.ts`,
|
|
924
|
+
`${ROUTE_ROOT}/(authed)/account/artifacts/artifact-actions.ts`,
|
|
774
925
|
],
|
|
926
|
+
"(authed)/account/artifacts/[pieceId]/versions/[version]/file": ["apps/web/lib/server-api.ts"],
|
|
775
927
|
"(authed)/account/support": [
|
|
776
928
|
"apps/web/lib/account-config.ts",
|
|
777
929
|
"apps/web/lib/server-api.ts",
|
|
778
930
|
`${ROUTE_ROOT}/(authed)/account/account-data.ts`,
|
|
779
931
|
`${ROUTE_ROOT}/(authed)/account/support-actions.ts`,
|
|
932
|
+
// #8233 C9 — the New menu's files beside account-config.ts: new-popups.tsx
|
|
933
|
+
// binds the config's actions to the popups, which import the menu and its
|
|
934
|
+
// server actions. (account-config.ts itself imports none of them — a
|
|
935
|
+
// spoke without sign-in drops the `(authed)` group and keeps the config.)
|
|
936
|
+
`${ROUTE_ROOT}/(authed)/account/new-menu.tsx`,
|
|
937
|
+
`${ROUTE_ROOT}/(authed)/account/new-actions.ts`,
|
|
938
|
+
`${ROUTE_ROOT}/(authed)/account/new-popups.tsx`,
|
|
939
|
+
`${ROUTE_ROOT}/(authed)/account/components/schedule-service.tsx`,
|
|
940
|
+
`${ROUTE_ROOT}/(authed)/account/components/request-quote.tsx`,
|
|
941
|
+
`${ROUTE_ROOT}/(authed)/account/components/send-message.tsx`,
|
|
780
942
|
],
|
|
781
943
|
"(authed)/admin": [
|
|
782
944
|
"apps/web/lib/server-api.ts",
|
|
@@ -832,6 +994,13 @@ export const ROUTE_MESSAGE_NAMESPACES = {
|
|
|
832
994
|
"(authed)/account/inbox/[kind]/[id]": ["account"],
|
|
833
995
|
"(authed)/account/settings": ["account"],
|
|
834
996
|
"(authed)/account/support": ["account"],
|
|
997
|
+
"(authed)/account/general": ["account"],
|
|
998
|
+
"(authed)/account/security": ["account"],
|
|
999
|
+
"(authed)/account/notifications": ["account"],
|
|
1000
|
+
"(authed)/account/billing": ["account"],
|
|
1001
|
+
// #8234 — the two Artifacts pages; the file route renders no string.
|
|
1002
|
+
"(authed)/account/artifacts": ["account"],
|
|
1003
|
+
"(authed)/account/artifacts/[pieceId]": ["account"],
|
|
835
1004
|
"(authed)/admin": ["admin"],
|
|
836
1005
|
"(authed)/leads": ["leadsInbox"],
|
|
837
1006
|
// #5977 — every string on both editor routes comes from the `edit`
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* package already twice records that a fixed template FILE is the drift a
|
|
15
15
|
* registry removes.
|
|
16
16
|
*/
|
|
17
|
-
import type { CategorySlug } from "
|
|
17
|
+
import type { CategorySlug } from "./category-profile.js";
|
|
18
18
|
import { type PageRosterRow } from "./module-architecture.js";
|
|
19
19
|
import type { ModuleName } from "./parse-args.js";
|
|
20
20
|
import type { TemplateLayout } from "./site-chrome.js";
|
|
@@ -66,8 +66,9 @@ export interface TemplateManifest {
|
|
|
66
66
|
* The business categories this template is FOR — one or more LEAF slugs from
|
|
67
67
|
* the site-category registry (`@working-theory/schema/categories`, #5830),
|
|
68
68
|
* shared with content's frontmatter `categories`. Required, and typed against
|
|
69
|
-
* `CategorySlug
|
|
70
|
-
* `
|
|
69
|
+
* `CategorySlug` — create-ailk's drift-tested copy of the registry's leaves
|
|
70
|
+
* (`category-profile.ts`, #8412) — for the same reason `requires` is typed
|
|
71
|
+
* against `ModuleName`: an unrecognized name fails type-check rather than a runtime
|
|
71
72
|
* validation, and every template must be findable under at least one
|
|
72
73
|
* category on the hub's "Browse by business" band.
|
|
73
74
|
*
|
package/dist/topology.d.ts
CHANGED
|
@@ -134,9 +134,14 @@ export declare const SPOKE_UNSERVED_MCP_TOOLS: readonly string[];
|
|
|
134
134
|
* `apps/web/lib/topology.generated.ts` for `topology` (D5) and, on a spoke,
|
|
135
135
|
* its sign-in mode (#7894 D8). The hub render loads `auth.ts` only when a
|
|
136
136
|
* session is read, so a module that imports this seam for a constant never
|
|
137
|
-
* loads Better Auth.
|
|
137
|
+
* loads Better Auth. `opts.spokeBilling` (#8217 D7) makes `loadSpokeBilling`
|
|
138
|
+
* reach the spoke billing action — only on a spoke that signs in through its
|
|
139
|
+
* hub, the one render whose account area can call it.
|
|
140
|
+
* @throws TopologyError for `spokeBilling` on a hub or a default-mode spoke.
|
|
138
141
|
*/
|
|
139
|
-
export declare function renderWebSeam(topology: Topology, signIn?: SignInMode
|
|
142
|
+
export declare function renderWebSeam(topology: Topology, signIn?: SignInMode, opts?: {
|
|
143
|
+
spokeBilling?: boolean;
|
|
144
|
+
}): string;
|
|
140
145
|
/**
|
|
141
146
|
* `apps/web/app/[locale]/(authed)/signed-out-gate.generated.tsx` (#7894 D8).
|
|
142
147
|
* The hub render is the `(authed)` layout's no-session branch, moved; the
|
package/dist/topology.js
CHANGED
|
@@ -271,7 +271,11 @@ const WEB_SEAM_HEADER = `// topology.generated.ts — how this site reads a sess
|
|
|
271
271
|
// has no sign-in, so its render reads no session and imports nothing; with
|
|
272
272
|
// \`--hub-sign-in\` (#7894) it reads the sealed hub-session cookie.
|
|
273
273
|
// UNSERVED_MCP_TOOLS names the MCP tools /.well-known/mcp.json leaves out
|
|
274
|
-
// on this topology (#8070)
|
|
274
|
+
// on this topology (#8070).
|
|
275
|
+
// loadSpokeBilling reaches the spoke billing action only on a spoke that
|
|
276
|
+
// signs in through its hub and carries commerce (#8217); elsewhere, null.
|
|
277
|
+
// readOwnAccounts lists the signed-in person's own sign-in accounts through
|
|
278
|
+
// Better Auth on a hub (#8431); a spoke has none here, so it answers null.`;
|
|
275
279
|
const MCP_SEAM_HEADER = `// topology.generated.ts — how this MCP server resolves its workspace store.
|
|
276
280
|
//
|
|
277
281
|
// GENERATED by create-ailk for this site's topology (#7426). Do not edit:
|
|
@@ -301,6 +305,26 @@ const SITE_SESSION_TYPE = `export type SiteSession = {
|
|
|
301
305
|
createdAt?: Date | string | null;
|
|
302
306
|
};
|
|
303
307
|
} | null;`;
|
|
308
|
+
/**
|
|
309
|
+
* `readOwnAccounts` (#8431 D2a): the session's own sign-in accounts, which
|
|
310
|
+
* the account Security tab reads to say whether the person has a password.
|
|
311
|
+
* The hub render loads `auth.ts` only when it is called; a spoke has no local
|
|
312
|
+
* accounts, so its renders answer `null` and import nothing.
|
|
313
|
+
*/
|
|
314
|
+
function ownAccountsReader(topology) {
|
|
315
|
+
if (topology === "hub") {
|
|
316
|
+
return `export async function readOwnAccounts(
|
|
317
|
+
headers: Headers,
|
|
318
|
+
): Promise<ReadonlyArray<{ providerId: string }> | null> {
|
|
319
|
+
const { auth } = await import("../auth");
|
|
320
|
+
return auth.api.listUserAccounts({ headers });
|
|
321
|
+
}`;
|
|
322
|
+
}
|
|
323
|
+
return `export function readOwnAccounts(headers: Headers): Promise<ReadonlyArray<{ providerId: string }> | null> {
|
|
324
|
+
void headers;
|
|
325
|
+
return Promise.resolve(null);
|
|
326
|
+
}`;
|
|
327
|
+
}
|
|
304
328
|
/** The sign-in exports every web seam render carries (#7894 D8). */
|
|
305
329
|
function signInExports(values) {
|
|
306
330
|
const literal = (value) => value === null ? "null" : JSON.stringify(value);
|
|
@@ -310,13 +334,62 @@ export const SIGN_IN_PATH: string | null = ${literal(values.signInPath)};
|
|
|
310
334
|
export const SIGN_UP_PATH: string | null = ${literal(values.signUpPath)};
|
|
311
335
|
export const SIGN_OUT_ENDPOINT: string | null = ${literal(values.signOutEndpoint)};`;
|
|
312
336
|
}
|
|
337
|
+
/** The spoke billing action (#8217 D6), relative to the web seam. */
|
|
338
|
+
const SPOKE_BILLING_ACTION_IMPORT = "../app/[locale]/(authed)/account/billing/spoke-billing.action";
|
|
339
|
+
/** The billing types every web seam render carries (#8217 D7). */
|
|
340
|
+
const SPOKE_BILLING_TYPES = `export type SpokeCard = { brand: string; last4: string; expMonth: number; expYear: number };
|
|
341
|
+
|
|
342
|
+
export type SpokeBillingRead =
|
|
343
|
+
| {
|
|
344
|
+
kind: "subscription";
|
|
345
|
+
status: "trialing" | "active" | "past_due" | "canceled";
|
|
346
|
+
planName: string | null;
|
|
347
|
+
paymentMethod: SpokeCard | null;
|
|
348
|
+
unreadable: boolean;
|
|
349
|
+
}
|
|
350
|
+
| { kind: "none"; unreadable: boolean }
|
|
351
|
+
| { kind: "failed" };
|
|
352
|
+
|
|
353
|
+
export type SpokeBilling = {
|
|
354
|
+
read(): Promise<SpokeBillingRead>;
|
|
355
|
+
portalUrl(): Promise<string | null>;
|
|
356
|
+
};`;
|
|
357
|
+
/**
|
|
358
|
+
* `loadSpokeBilling` (#8217 D7): the billing render imports the action, by a
|
|
359
|
+
* dynamic import, so a module that reads this seam for a constant never
|
|
360
|
+
* loads the checkout package; every other render resolves `null`.
|
|
361
|
+
*/
|
|
362
|
+
function spokeBillingLoader(spokeBilling) {
|
|
363
|
+
if (!spokeBilling) {
|
|
364
|
+
return `${SPOKE_BILLING_TYPES}
|
|
365
|
+
|
|
366
|
+
export function loadSpokeBilling(): Promise<SpokeBilling | null> {
|
|
367
|
+
return Promise.resolve(null);
|
|
368
|
+
}`;
|
|
369
|
+
}
|
|
370
|
+
return `${SPOKE_BILLING_TYPES}
|
|
371
|
+
|
|
372
|
+
export async function loadSpokeBilling(): Promise<SpokeBilling | null> {
|
|
373
|
+
const { readSpokeBilling, spokeBillingPortalUrl } = await import(
|
|
374
|
+
"${SPOKE_BILLING_ACTION_IMPORT}"
|
|
375
|
+
);
|
|
376
|
+
return { read: readSpokeBilling, portalUrl: spokeBillingPortalUrl };
|
|
377
|
+
}`;
|
|
378
|
+
}
|
|
313
379
|
/**
|
|
314
380
|
* `apps/web/lib/topology.generated.ts` for `topology` (D5) and, on a spoke,
|
|
315
381
|
* its sign-in mode (#7894 D8). The hub render loads `auth.ts` only when a
|
|
316
382
|
* session is read, so a module that imports this seam for a constant never
|
|
317
|
-
* loads Better Auth.
|
|
383
|
+
* loads Better Auth. `opts.spokeBilling` (#8217 D7) makes `loadSpokeBilling`
|
|
384
|
+
* reach the spoke billing action — only on a spoke that signs in through its
|
|
385
|
+
* hub, the one render whose account area can call it.
|
|
386
|
+
* @throws TopologyError for `spokeBilling` on a hub or a default-mode spoke.
|
|
318
387
|
*/
|
|
319
|
-
export function renderWebSeam(topology, signIn = "off") {
|
|
388
|
+
export function renderWebSeam(topology, signIn = "off", opts = {}) {
|
|
389
|
+
const spokeBilling = opts.spokeBilling === true;
|
|
390
|
+
if (spokeBilling && (topology !== "spoke" || signIn !== "hub")) {
|
|
391
|
+
throw new TopologyError("the spoke billing loader renders only on a spoke that signs in through its hub (--hub-sign-in)");
|
|
392
|
+
}
|
|
320
393
|
if (topology === "hub") {
|
|
321
394
|
return `${WEB_SEAM_HEADER}
|
|
322
395
|
|
|
@@ -331,10 +404,14 @@ export async function readSession(headers: Headers): Promise<SiteSession> {
|
|
|
331
404
|
return auth.api.getSession({ headers });
|
|
332
405
|
}
|
|
333
406
|
|
|
407
|
+
${ownAccountsReader("hub")}
|
|
408
|
+
|
|
334
409
|
export async function registerSiteStores(): Promise<void> {
|
|
335
410
|
const { registerLicenseKeyStore } = await import("./license-key-store");
|
|
336
411
|
await registerLicenseKeyStore();
|
|
337
412
|
}
|
|
413
|
+
|
|
414
|
+
${spokeBillingLoader(false)}
|
|
338
415
|
`;
|
|
339
416
|
}
|
|
340
417
|
if (signIn === "hub") {
|
|
@@ -351,9 +428,13 @@ export function readSession(headers: Headers): Promise<SiteSession> {
|
|
|
351
428
|
return readHubSession(headers);
|
|
352
429
|
}
|
|
353
430
|
|
|
431
|
+
${ownAccountsReader("spoke")}
|
|
432
|
+
|
|
354
433
|
export function registerSiteStores(): Promise<void> {
|
|
355
434
|
return Promise.resolve();
|
|
356
435
|
}
|
|
436
|
+
|
|
437
|
+
${spokeBillingLoader(spokeBilling)}
|
|
357
438
|
`;
|
|
358
439
|
}
|
|
359
440
|
return `${WEB_SEAM_HEADER}
|
|
@@ -369,9 +450,13 @@ export function readSession(headers: Headers): Promise<SiteSession> {
|
|
|
369
450
|
return Promise.resolve(null);
|
|
370
451
|
}
|
|
371
452
|
|
|
453
|
+
${ownAccountsReader("spoke")}
|
|
454
|
+
|
|
372
455
|
export function registerSiteStores(): Promise<void> {
|
|
373
456
|
return Promise.resolve();
|
|
374
457
|
}
|
|
458
|
+
|
|
459
|
+
${spokeBillingLoader(false)}
|
|
375
460
|
`;
|
|
376
461
|
}
|
|
377
462
|
const AUTHED_GATE_SEAM_HEADER = `// signed-out-gate.generated.tsx — what the (authed) group shows a signed-out visitor.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ailk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Scaffolder for AI Launch Kit — `pnpm create ailk@latest <dir>` produces a starter repo consuming @working-theory/* from npm (per ADR 0007).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"component-catalog.json",
|
|
19
19
|
"component-catalog.md",
|
|
20
20
|
"README.md",
|
|
21
|
-
"LICENSE"
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"NOTICE"
|
|
22
23
|
],
|
|
23
24
|
"publishConfig": {
|
|
24
25
|
"access": "public"
|
|
@@ -27,8 +28,8 @@
|
|
|
27
28
|
"tar": "^7.5.21"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
|
-
"@working-theory/
|
|
31
|
-
"@working-theory/
|
|
31
|
+
"@working-theory/schema": "0.40.0",
|
|
32
|
+
"@working-theory/templates": "0.40.0"
|
|
32
33
|
},
|
|
33
34
|
"repository": {
|
|
34
35
|
"type": "git",
|
package/templates/.env.example
CHANGED
|
@@ -9,9 +9,9 @@ AILK_PUBLIC_DOMAIN=ailaunchkit.ai
|
|
|
9
9
|
# STEALTH defaults to "true" for new installs so a freshly-deployed instance
|
|
10
10
|
# isn't indexed by crawlers or unfurled by Slack/Twitter/LinkedIn before the
|
|
11
11
|
# operator is ready. Three layers gate on this single flag:
|
|
12
|
-
# 1. apps
|
|
13
|
-
# 2. X-Robots-Tag: noindex, nofollow, noarchive HTTP header (next.config.
|
|
14
|
-
# 3. <meta name="robots" content="noindex,nofollow"> tag (app/layout.tsx)
|
|
12
|
+
# 1. robots.txt answers "Disallow: /" for every crawler (apps/web/app/robots.txt/route.ts)
|
|
13
|
+
# 2. X-Robots-Tag: noindex, nofollow, noarchive HTTP header (apps/web/next.config.mjs)
|
|
14
|
+
# 3. <meta name="robots" content="noindex,nofollow"> tag (apps/web/app/[locale]/layout.tsx)
|
|
15
15
|
# At launch, set STEALTH=false on the hosting platform's env vars and redeploy.
|
|
16
16
|
# See README.md § "Going live" for the full flip checklist.
|
|
17
17
|
STEALTH=true
|
|
@@ -54,4 +54,9 @@ jobs:
|
|
|
54
54
|
|
|
55
55
|
- run: pnpm test
|
|
56
56
|
|
|
57
|
+
# apps/web's `next build` with the docs module outgrows Node's default
|
|
58
|
+
# ~2 GB heap and aborts with "JavaScript heap out of memory" (#8069).
|
|
59
|
+
# The hosted runner has ~7 GB; give the build room.
|
|
57
60
|
- run: pnpm build
|
|
61
|
+
env:
|
|
62
|
+
NODE_OPTIONS: --max-old-space-size=6144
|
|
@@ -32,8 +32,14 @@ DATABASE_URL="postgresql://user:password@localhost:5432/customer_template"
|
|
|
32
32
|
# Stripe (Optional)
|
|
33
33
|
# =============================================================================
|
|
34
34
|
# Consumed by apps/api/src/lib/stripe.ts via @working-theory/stripe-client wrapper.
|
|
35
|
-
# Use sandbox keys only — live-mode keys are rejected at runtime
|
|
35
|
+
# Use sandbox keys only — live-mode keys are rejected at runtime, unless
|
|
36
|
+
# STRIPE_MODE=live below admits a restricted live key (#8450).
|
|
36
37
|
STRIPE_SECRET_KEY=sk_test_xxx
|
|
38
|
+
# test (the default when unset) or live. `live` is admitted only beside a
|
|
39
|
+
# restricted live key, on a production build — VERCEL_ENV=production, or,
|
|
40
|
+
# off Vercel, NODE_ENV=production, so a staging host must not set the latter.
|
|
41
|
+
# Every other live key stays refused at boot and on every route.
|
|
42
|
+
STRIPE_MODE=test
|
|
37
43
|
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
38
44
|
|
|
39
45
|
# =============================================================================
|
|
@@ -46,6 +52,16 @@ STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
|
46
52
|
# Generate with: openssl rand -hex 32
|
|
47
53
|
# OSS_API_INTERNAL_SECRET=your-shared-secret-here
|
|
48
54
|
|
|
55
|
+
# =============================================================================
|
|
56
|
+
# Consent — the signed unsubscribe link (#8438)
|
|
57
|
+
# =============================================================================
|
|
58
|
+
# Keys the HMAC on the unsubscribe token an email's link carries
|
|
59
|
+
# (POST /v1/consent/unsubscribe). Optional: unset, no link can be minted and the
|
|
60
|
+
# route answers 503 link_secret_not_configured. When set it must be at least
|
|
61
|
+
# 32 bytes — a shorter value logs an error at boot and is treated as unset.
|
|
62
|
+
# Generate with: openssl rand -hex 32
|
|
63
|
+
# AILK_CONSENT_LINK_SECRET=
|
|
64
|
+
|
|
49
65
|
# =============================================================================
|
|
50
66
|
# Scheduling — the `booker` section's provider (#4416)
|
|
51
67
|
# =============================================================================
|