create-ailk 0.1.0 → 0.2.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/README.md +124 -3
- package/component-catalog.md +456 -0
- package/dist/cli.js +92 -16
- package/dist/component-catalog.d.ts +11 -0
- package/dist/component-catalog.js +39 -0
- package/dist/copy.d.ts +7 -0
- package/dist/copy.js +24 -0
- package/dist/derive-architecture.d.ts +13 -0
- package/dist/derive-architecture.js +238 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +19 -2
- package/dist/lib/extract-module-bundle.d.ts +16 -0
- package/dist/lib/extract-module-bundle.js +184 -0
- package/dist/lib/fetch-module.d.ts +55 -0
- package/dist/lib/fetch-module.js +125 -0
- package/dist/lib/module-license-gate.d.ts +48 -0
- package/dist/lib/module-license-gate.js +67 -0
- package/dist/lib/module-tier.d.ts +35 -0
- package/dist/lib/module-tier.js +37 -0
- package/dist/module-architecture.d.ts +175 -0
- package/dist/module-architecture.js +663 -0
- package/dist/parse-args.d.ts +47 -1
- package/dist/parse-args.js +143 -2
- package/dist/programmatic.d.ts +160 -3
- package/dist/programmatic.js +196 -7
- package/dist/surfaces.d.ts +211 -0
- package/dist/surfaces.js +532 -0
- package/dist/sync-routes.d.ts +92 -0
- package/dist/sync-routes.js +350 -0
- package/package.json +12 -5
- package/templates/.claude/rules/architecture.md +6 -2
- package/templates/.claude/skills/README.md +9 -9
- package/templates/.claude/skills/add-schema/SKILL.md +14 -7
- package/templates/.claude/skills/add-schema/references/schema-types.md +109 -6
- package/templates/.claude/skills/provision-config/SKILL.md +1 -1
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +498 -1
- package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +370 -0
- package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +376 -0
- package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +471 -0
- package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +365 -0
- package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +60 -0
- package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +446 -0
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +4 -4
- package/templates/.env.example +126 -2
- package/templates/CLAUDE.md +11 -5
- package/templates/README.md +1 -1
- package/templates/apps/api/.env.example +38 -0
- package/templates/apps/api/CLAUDE.md +78 -1
- package/templates/apps/api/LICENSE +201 -0
- package/templates/apps/api/api/index.ts +6 -141
- package/templates/apps/api/jest.config.cjs +16 -0
- package/templates/apps/api/package.json +22 -6
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +141 -0
- package/templates/apps/api/src/__tests__/server.test.ts +46 -0
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +211 -0
- package/templates/apps/api/src/bin/abandon-sweep.ts +42 -0
- package/templates/apps/api/src/bin/deliverable-resend.ts +144 -0
- package/templates/apps/api/src/bin/deliverable-upload.ts +114 -0
- package/templates/apps/api/src/bin/followup-sweep.ts +44 -0
- package/templates/apps/api/src/bin/listing-csv-sweep.ts +46 -0
- package/templates/apps/api/src/bin/seed-presets.ts +58 -0
- package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +104 -0
- package/templates/apps/api/src/bin/session-retention-sweep.ts +46 -0
- package/templates/apps/api/src/cli.ts +5 -11
- package/templates/apps/api/src/config/index.ts +35 -0
- package/templates/apps/api/src/config/modules.ts +43 -0
- package/templates/apps/api/src/lib/__mocks__/prisma-client.js +11 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -0
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +2 -2
- package/templates/apps/api/src/lib/site.ts +16 -0
- package/templates/apps/api/src/lib/stripe.ts +22 -0
- package/templates/apps/api/src/lib/tenant-db.ts +225 -0
- package/templates/apps/api/src/lib/ws-token.ts +91 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +91 -4
- package/templates/apps/api/src/middleware/auth.ts +43 -8
- package/templates/apps/api/src/middleware/rate-limit.ts +78 -3
- package/templates/apps/api/src/middleware/tenant.ts +99 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +92 -0
- package/templates/apps/api/src/openapi/spec.ts +312 -3
- package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +175 -0
- package/templates/apps/api/src/routes/aeo/index.ts +107 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +5 -2
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +22 -3
- package/templates/apps/api/src/routes/auth/tokens.ts +13 -1
- package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +450 -0
- package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +262 -0
- package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +436 -0
- package/templates/apps/api/src/routes/billing/index.ts +36 -0
- package/templates/apps/api/src/routes/billing/portal.ts +182 -0
- package/templates/apps/api/src/routes/billing/read.ts +75 -0
- package/templates/apps/api/src/routes/billing/usage.ts +153 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +99 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +20 -8
- package/templates/apps/api/src/routes/content/create.ts +1 -0
- package/templates/apps/api/src/routes/content/delete.ts +1 -0
- package/templates/apps/api/src/routes/content/index.ts +42 -6
- package/templates/apps/api/src/routes/content/update.ts +1 -0
- package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +393 -0
- package/templates/apps/api/src/routes/deliverables/index.ts +200 -0
- package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +443 -0
- package/templates/apps/api/src/routes/flow-checkouts/index.ts +82 -0
- package/templates/apps/api/src/routes/flows/README.md +147 -0
- package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +752 -0
- package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +671 -0
- package/templates/apps/api/src/routes/flows/index.ts +202 -0
- package/templates/apps/api/src/routes/flows/recommender.ts +443 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +438 -31
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +10 -10
- package/templates/apps/api/src/routes/leads/index.ts +43 -9
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +558 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +815 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +869 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +221 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +468 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +424 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +707 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +375 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +467 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +566 -0
- package/templates/apps/api/src/routes/project-listings/get.ts +70 -0
- package/templates/apps/api/src/routes/project-listings/index.ts +120 -0
- package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
- package/templates/apps/api/src/routes/project-listings/me.ts +76 -0
- package/templates/apps/api/src/routes/project-listings/patch-copy.ts +222 -0
- package/templates/apps/api/src/routes/project-listings/patch-draft.ts +97 -0
- package/templates/apps/api/src/routes/project-listings/patch.ts +136 -0
- package/templates/apps/api/src/routes/project-listings/public.ts +52 -0
- package/templates/apps/api/src/routes/project-listings/respond.ts +37 -0
- package/templates/apps/api/src/routes/project-listings/resume-token.ts +22 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +106 -0
- package/templates/apps/api/src/routes/project-listings/submit.ts +122 -0
- package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +490 -0
- package/templates/apps/api/src/routes/schedule/index.ts +249 -0
- package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +385 -0
- package/templates/apps/api/src/routes/slack/actions.ts +177 -0
- package/templates/apps/api/src/routes/slack/index.ts +38 -0
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +16 -6
- package/templates/apps/api/src/routes/test/auth/session.ts +8 -6
- package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +577 -0
- package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +78 -0
- package/templates/apps/api/src/routes/waitlist-experiments/index.ts +41 -0
- package/templates/apps/api/src/routes/waitlist-experiments/list.ts +64 -0
- package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +42 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +84 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +119 -0
- package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +238 -0
- package/templates/apps/api/src/routes/waitlist-signups/index.ts +101 -0
- package/templates/apps/api/src/routes/webhooks/README.md +35 -12
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +315 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +270 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +248 -20
- package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +356 -0
- package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +671 -0
- package/templates/apps/api/src/routes/workspaces/config.ts +125 -0
- package/templates/apps/api/src/routes/workspaces/index.ts +194 -0
- package/templates/apps/api/src/routes/workspaces/sessions.ts +218 -0
- package/templates/apps/api/src/server.ts +307 -7
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +489 -0
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +132 -0
- package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +65 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +282 -0
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +523 -0
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +359 -0
- package/templates/apps/api/src/services/__tests__/entitlements.test.ts +142 -0
- package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +425 -0
- package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +2840 -0
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +393 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +8 -8
- package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +560 -0
- package/templates/apps/api/src/services/__tests__/listing-promotion.test.ts +684 -0
- package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +406 -0
- package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +290 -0
- package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +736 -0
- package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +340 -0
- package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +983 -0
- package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +278 -0
- package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +71 -0
- package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +379 -0
- package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +941 -0
- package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +588 -0
- package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +768 -0
- package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +1314 -0
- package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +341 -0
- package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +567 -0
- package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +474 -0
- package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +354 -0
- package/templates/apps/api/src/services/abandon-email.ts +307 -0
- package/templates/apps/api/src/services/aeo-score.ts +288 -0
- package/templates/apps/api/src/services/answer-distributions.ts +138 -0
- package/templates/apps/api/src/services/consent.ts +236 -0
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +523 -0
- package/templates/apps/api/src/services/entitlements.ts +102 -0
- package/templates/apps/api/src/services/flow-aggregate.ts +232 -0
- package/templates/apps/api/src/services/flow-checkouts.ts +123 -0
- package/templates/apps/api/src/services/flow-engine.ts +1296 -0
- package/templates/apps/api/src/services/lead-promotion.ts +176 -0
- package/templates/apps/api/src/services/lead-routing.ts +3 -3
- package/templates/apps/api/src/services/listing-config.ts +102 -0
- package/templates/apps/api/src/services/listing-csv-sweep.ts +455 -0
- package/templates/apps/api/src/services/listing-promotion.ts +342 -0
- package/templates/apps/api/src/services/playbook-compile.ts +398 -0
- package/templates/apps/api/src/services/playbook-render.ts +263 -0
- package/templates/apps/api/src/services/project-listing-decision.ts +510 -0
- package/templates/apps/api/src/services/project-listing-flow.ts +426 -0
- package/templates/apps/api/src/services/project-listing-issue.ts +251 -0
- package/templates/apps/api/src/services/project-listings.ts +1472 -0
- package/templates/apps/api/src/services/recommender-capture.ts +835 -0
- package/templates/apps/api/src/services/scheduling/cal-provider.ts +392 -0
- package/templates/apps/api/src/services/scheduling/index.ts +63 -0
- package/templates/apps/api/src/services/scheduling/types.ts +88 -0
- package/templates/apps/api/src/services/slack-notify.ts +240 -0
- package/templates/apps/api/src/services/tenant-context.ts +451 -0
- package/templates/apps/api/src/services/usage-aggregation.ts +516 -0
- package/templates/apps/api/src/services/usage-credits.ts +340 -0
- package/templates/apps/api/src/services/usage-metering.ts +699 -0
- package/templates/apps/api/src/services/waitlist-dashboard.ts +947 -0
- package/templates/apps/api/src/services/waitlist-experiments.ts +213 -0
- package/templates/apps/api/src/services/waitlist-followup.ts +486 -0
- package/templates/apps/api/src/services/waitlist-scoring.ts +166 -0
- package/templates/apps/api/src/services/waitlist-signups.ts +165 -0
- package/templates/apps/api/src/vercel-handler.ts +165 -0
- package/templates/apps/api/tsconfig.json +0 -12
- package/templates/apps/mcp/CLAUDE.md +19 -9
- package/templates/apps/mcp/LICENSE +201 -0
- package/templates/apps/mcp/__tests__/create_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/delete_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +105 -0
- package/templates/apps/mcp/__tests__/parity.test.ts +70 -6
- package/templates/apps/mcp/__tests__/request_callback.test.ts +4 -4
- package/templates/apps/mcp/__tests__/schedule_tools.test.ts +242 -0
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +4 -4
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +4 -4
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +47 -0
- package/templates/apps/mcp/__tests__/update_page.test.ts +1 -0
- package/templates/apps/mcp/package.json +6 -4
- package/templates/apps/mcp/src/config/modules.ts +37 -0
- package/templates/apps/mcp/src/server.ts +109 -18
- package/templates/apps/mcp/src/tools/capture_lead.ts +1 -1
- package/templates/apps/mcp/src/tools/create_booking.ts +58 -0
- package/templates/apps/mcp/src/tools/create_page.ts +1 -0
- package/templates/apps/mcp/src/tools/delete_page.ts +1 -0
- package/templates/apps/mcp/src/tools/get_event_meta.ts +55 -0
- package/templates/apps/mcp/src/tools/get_flow.ts +61 -0
- package/templates/apps/mcp/src/tools/index.ts +25 -0
- package/templates/apps/mcp/src/tools/list_availability.ts +67 -0
- package/templates/apps/mcp/src/tools/purchase.ts +3 -0
- package/templates/apps/mcp/src/tools/submit_flow_step.ts +83 -0
- package/templates/apps/mcp/src/tools/update_page.ts +1 -0
- package/templates/apps/mcp/tsconfig.json +1 -9
- package/templates/apps/web/.env.example +44 -0
- package/templates/apps/web/CLAUDE.md +28 -0
- package/templates/apps/web/LICENSE +201 -0
- package/templates/apps/web/__tests__/__mocks__/code-highlight.jest-stub.ts +24 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl-server.ts +33 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl.ts +18 -0
- package/templates/apps/web/__tests__/__mocks__/server-only.ts +13 -0
- package/templates/apps/web/__tests__/__mocks__/style-mock.js +4 -0
- package/templates/apps/web/__tests__/__mocks__/vercel-analytics-server.ts +9 -0
- package/templates/apps/web/__tests__/jest-support/import-meta-transformer.cjs +90 -0
- package/templates/apps/web/__tests__/setup.ts +22 -32
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +6 -3
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +8 -2
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +260 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +263 -0
- package/templates/apps/web/app/[locale]/(authed)/account/sign-out-button.tsx +39 -0
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +54 -0
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +96 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +309 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +149 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +273 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/gate.test.tsx +172 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +171 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +179 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +116 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ForbiddenState.tsx +24 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +66 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +61 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +114 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +139 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +85 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +67 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/format.ts +111 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +179 -0
- package/templates/apps/web/app/[locale]/about/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +6 -1
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/careers/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/clients/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +21 -1
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +188 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +242 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +29 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/intake-analytics.test.ts +51 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +39 -15
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +21 -3
- package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +49 -0
- package/templates/apps/web/app/[locale]/contact/intake-script.ts +66 -0
- package/templates/apps/web/app/[locale]/contact/page.tsx +14 -4
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/courses/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +1 -0
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/downloads/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/events/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/faq/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +265 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +445 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +341 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +287 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +302 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +128 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +254 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +144 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +108 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +532 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +121 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +457 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +396 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +114 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +52 -0
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/integrations/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/launch-service/page.tsx +14 -1
- package/templates/apps/web/app/[locale]/layout.tsx +127 -16
- package/templates/apps/web/app/[locale]/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/partners/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/products/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +10 -0
- package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +110 -0
- package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/resources/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +92 -0
- package/templates/apps/web/app/[locale]/schedule/page.tsx +82 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/services/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/sign-in/__tests__/next-path.test.ts +31 -0
- package/templates/apps/web/app/[locale]/sign-in/__tests__/page.test.tsx +152 -0
- package/templates/apps/web/app/[locale]/sign-in/next-path.ts +0 -0
- package/templates/apps/web/app/[locale]/sign-in/page.tsx +83 -0
- package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +123 -0
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/testimonials/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +93 -0
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +48 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/globals.css +35 -0
- package/templates/apps/web/app/llms.txt/route.ts +2 -1
- package/templates/apps/web/app/og/route.tsx +10 -2
- package/templates/apps/web/auth.ts +8 -0
- package/templates/apps/web/components/sign-out-trigger.tsx +42 -0
- package/templates/apps/web/content/en/blog/README.txt +25 -0
- package/templates/apps/web/content/en/docs/index.mdx +28 -0
- package/templates/apps/web/jest.config.cjs +90 -27
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +112 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +499 -0
- package/templates/apps/web/lib/account-config.ts +13 -0
- package/templates/apps/web/lib/server-api.ts +85 -0
- package/templates/apps/web/lib/site-brand.tsx +121 -0
- package/templates/apps/web/lib/site-theme.ts +74 -0
- package/templates/apps/web/messages/en.json +275 -7
- package/templates/apps/web/middleware.ts +11 -3
- package/templates/apps/web/next.config.mjs +8 -2
- package/templates/apps/web/package.json +17 -7
- package/templates/apps/web/postcss.config.mjs +23 -0
- package/templates/apps/web/public/.well-known/security.txt +3 -3
- package/templates/apps/web/src/lib/routes.ts +15 -2
- package/templates/apps/web/tsconfig.json +1 -16
- package/templates/content/_site.mdx +36 -25
- package/templates/content/en/AboutPage/about.mdx +24 -14
- package/templates/content/en/ContactPage/contact.mdx +23 -14
- package/templates/content/en/FAQPage/faq.mdx +10 -392
- package/templates/content/en/HomePage/home.mdx +14 -285
- package/templates/database/CHANGELOG.md +443 -0
- package/templates/database/LICENSE +201 -0
- package/templates/database/README.md +3 -1
- package/templates/database/__tests__/flows-listing-diagnostic.test.ts +392 -0
- package/templates/database/__tests__/flows-presets.test.ts +173 -0
- package/templates/database/__tests__/prefixed-ids.db.test.ts +146 -0
- package/templates/database/__tests__/seed.test.ts +88 -0
- package/templates/database/__tests__/user-cascade.test.ts +19 -4
- package/templates/database/auth/schema.prisma +521 -0
- package/templates/database/config/schema.prisma +234 -0
- package/templates/database/content/schema.prisma +263 -0
- package/templates/database/flows/listing-diagnostic.ts +182 -0
- package/templates/database/flows/presets.ts +315 -0
- package/templates/database/inbox/__tests__/schema.test.ts +4 -0
- package/templates/database/inbox/schema.prisma +574 -3
- package/templates/database/jest.config.cjs +8 -0
- package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +201 -0
- package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +67 -0
- package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +46 -0
- package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +25 -0
- package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +49 -0
- package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +197 -0
- package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +32 -0
- package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +22 -0
- package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +151 -0
- package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +223 -0
- package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +22 -0
- package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +32 -0
- package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +40 -0
- package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +4 -0
- package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +2 -0
- package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +2 -0
- package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +29 -0
- package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +6 -0
- package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +39 -0
- package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +24 -0
- package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +3 -0
- package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +33 -0
- package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +30 -0
- package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +47 -0
- package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +16 -0
- package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +47 -0
- package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +10 -0
- package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +26 -0
- package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +90 -0
- package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +174 -0
- package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +14 -0
- package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +25 -0
- package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +32 -0
- package/templates/database/migrations/20260911180000_consent_grants/migration.sql +71 -0
- package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +30 -0
- package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +49 -0
- package/templates/database/ops/schema.prisma +27 -0
- package/templates/database/package.json +42 -4
- package/templates/database/prisma.config.ts +1 -1
- package/templates/database/schema.prisma +19 -435
- package/templates/database/seed-test.ts +14 -4
- package/templates/database/seed.ts +148 -0
- package/templates/database/tenancy.ts +45 -0
- package/templates/database/tsconfig.flows.json +15 -0
- package/templates/database/tsconfig.json +7 -1
- package/templates/database/tsconfig.tenancy.json +14 -0
- package/templates/package.json +30 -55
- package/templates/pnpm-workspace.yaml +0 -3
- package/templates/project.yaml +1 -1
- package/templates/tsconfig.json +1 -37
- package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +0 -94
- package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +0 -75
- package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +0 -82
- package/templates/apps/web/__tests__/auth/env-helpers.test.ts +0 -168
- package/templates/apps/web/__tests__/authority-list-routes.test.tsx +0 -208
- package/templates/apps/web/__tests__/better-stack.test.ts +0 -66
- package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +0 -87
- package/templates/apps/web/__tests__/blog-source-populated.test.ts +0 -130
- package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +0 -60
- package/templates/apps/web/__tests__/google-analytics.test.tsx +0 -104
- package/templates/apps/web/__tests__/i18n/middleware.test.ts +0 -119
- package/templates/apps/web/__tests__/i18n/routing.test.ts +0 -114
- package/templates/apps/web/__tests__/i18n/translations.test.ts +0 -191
- package/templates/apps/web/__tests__/json-ld.test.ts +0 -98
- package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +0 -580
- package/templates/apps/web/__tests__/layout-stealth.test.ts +0 -39
- package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +0 -103
- package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +0 -114
- package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +0 -94
- package/templates/apps/web/__tests__/page.test.tsx +0 -230
- package/templates/apps/web/__tests__/products-services-phase1.test.tsx +0 -321
- package/templates/apps/web/__tests__/projects-routes.test.tsx +0 -392
- package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +0 -475
- package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +0 -53
- package/templates/apps/web/__tests__/routes/blog-route.test.tsx +0 -191
- package/templates/apps/web/__tests__/routes/llms-txt.test.ts +0 -123
- package/templates/apps/web/__tests__/routes/robots-txt.test.ts +0 -52
- package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +0 -78
- package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +0 -203
- package/templates/apps/web/__tests__/section-routes.test.tsx +0 -693
- package/templates/apps/web/__tests__/security-headers.test.ts +0 -201
- package/templates/apps/web/__tests__/sentry-config.test.ts +0 -116
- package/templates/apps/web/__tests__/sitemap-locales.test.ts +0 -415
- package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +0 -844
- package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +0 -120
- package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +0 -202
- package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +0 -152
- package/templates/apps/web/content/en/blog/index.mdx +0 -15
- package/templates/apps/web/content/en/blog/launching-ailk.mdx +0 -20
- package/templates/apps/web/content/en/docs/getting-started.mdx +0 -30
- package/templates/content/.gitkeep +0 -0
- package/templates/content/CLAUDE.md +0 -85
- package/templates/content/ar/HomePage/home.mdx +0 -123
- package/templates/content/ar/_site.mdx +0 -35
- package/templates/content/de/_site.mdx +0 -29
- package/templates/content/en/.gitkeep +0 -0
- package/templates/content/en/AboutPage/about.schema.json +0 -82
- package/templates/content/en/BookCall/book-call.mdx +0 -19
- package/templates/content/en/BookCall/book-call.schema.json +0 -121
- package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +0 -20
- package/templates/content/en/CareersList/careers.mdx +0 -24
- package/templates/content/en/CaseStudiesList/case-studies.mdx +0 -22
- package/templates/content/en/CaseStudiesList/showcase.mdx +0 -8
- package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +0 -32
- package/templates/content/en/CaseStudy/schema-builder-migration.mdx +0 -41
- package/templates/content/en/ClientsList/clients.mdx +0 -38
- package/templates/content/en/ContactPage/contact.schema.json +0 -100
- package/templates/content/en/ContactPoint/primary.mdx +0 -14
- package/templates/content/en/Course/aeo-fundamentals.mdx +0 -37
- package/templates/content/en/Course/schema-builder-workshop.mdx +0 -62
- package/templates/content/en/CoursesList/courses.mdx +0 -22
- package/templates/content/en/DownloadsList/downloads.mdx +0 -22
- package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +0 -39
- package/templates/content/en/Event/ailk-launch-day-2026.mdx +0 -35
- package/templates/content/en/EventsList/events.mdx +0 -26
- package/templates/content/en/FAQPage/faq.schema.json +0 -231
- package/templates/content/en/GlossaryList/glossary.mdx +0 -19
- package/templates/content/en/GlossaryList/glossary.schema.json +0 -300
- package/templates/content/en/HomePage/home.schema.json +0 -88
- package/templates/content/en/HomePage/launch-service.mdx +0 -475
- package/templates/content/en/HomePage/launch-service.schema.json +0 -138
- package/templates/content/en/HowTo/add-mdx-content.mdx +0 -38
- package/templates/content/en/HowTo/configure-aeo-scoring.mdx +0 -35
- package/templates/content/en/HowTo/set-up-json-ld.mdx +0 -36
- package/templates/content/en/Integration/github-actions.mdx +0 -31
- package/templates/content/en/Integration/openai-api.mdx +0 -26
- package/templates/content/en/Integration/vercel.mdx +0 -32
- package/templates/content/en/IntegrationsList/integrations.mdx +0 -22
- package/templates/content/en/JobPosting/content-strategist.mdx +0 -46
- package/templates/content/en/JobPosting/developer-advocate.mdx +0 -47
- package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +0 -57
- package/templates/content/en/LandingPage/aeo-audit.mdx +0 -19
- package/templates/content/en/LandingPage/aeo-audit.schema.json +0 -92
- package/templates/content/en/LandingPage/agency-waitlist.mdx +0 -340
- package/templates/content/en/LandingPage/agency-waitlist.schema.json +0 -152
- package/templates/content/en/LandingPage/developers.mdx +0 -19
- package/templates/content/en/LandingPage/developers.schema.json +0 -109
- package/templates/content/en/LandingPage/for-agencies.mdx +0 -390
- package/templates/content/en/LandingPage/for-agencies.schema.json +0 -107
- package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +0 -417
- package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +0 -105
- package/templates/content/en/LandingPage/for-businesses.mdx +0 -19
- package/templates/content/en/LandingPage/for-businesses.schema.json +0 -96
- package/templates/content/en/LandingPage/platform.mdx +0 -369
- package/templates/content/en/LandingPage/platform.schema.json +0 -166
- package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +0 -19
- package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +0 -102
- package/templates/content/en/LandingPage/vs-wordpress.mdx +0 -19
- package/templates/content/en/LandingPage/vs-wordpress.schema.json +0 -53
- package/templates/content/en/NewsletterSignup/newsletter.mdx +0 -236
- package/templates/content/en/NewsletterSignup/newsletter.schema.json +0 -91
- package/templates/content/en/Organization/site-owner.mdx +0 -16
- package/templates/content/en/Partner/prisma.mdx +0 -31
- package/templates/content/en/Partner/supabase.mdx +0 -30
- package/templates/content/en/Partner/vercel.mdx +0 -28
- package/templates/content/en/PartnersList/partners.mdx +0 -22
- package/templates/content/en/Person/founder.mdx +0 -18
- package/templates/content/en/Pricing/pricing.mdx +0 -538
- package/templates/content/en/Pricing/pricing.schema.json +0 -209
- package/templates/content/en/PrivacyPage/privacy.mdx +0 -165
- package/templates/content/en/PrivacyPage/privacy.schema.json +0 -64
- package/templates/content/en/Product/ailk.mdx +0 -19
- package/templates/content/en/Product/ailk.schema.json +0 -94
- package/templates/content/en/Product/api-launch-kit.mdx +0 -26
- package/templates/content/en/Product/launch-kit.mdx +0 -28
- package/templates/content/en/ProductsList/products.mdx +0 -26
- package/templates/content/en/Project/ailk-phase-2.mdx +0 -54
- package/templates/content/en/ProjectsList/projects.mdx +0 -25
- package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +0 -27
- package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +0 -28
- package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +0 -39
- package/templates/content/en/ResourcesHub/resources.mdx +0 -22
- package/templates/content/en/Service/consulting.mdx +0 -22
- package/templates/content/en/Service/implementation.mdx +0 -30
- package/templates/content/en/Service/launch-service.mdx +0 -232
- package/templates/content/en/Service/launch.mdx +0 -228
- package/templates/content/en/ServicesList/services.mdx +0 -84
- package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +0 -44
- package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +0 -47
- package/templates/content/en/SoftwareProduct/ailk-schema.mdx +0 -49
- package/templates/content/en/TeamList/team.mdx +0 -63
- package/templates/content/en/TeamMember/founder.mdx +0 -72
- package/templates/content/en/TermsPage/terms.mdx +0 -19
- package/templates/content/en/TermsPage/terms.schema.json +0 -99
- package/templates/content/en/TestimonialsList/testimonials.mdx +0 -44
- package/templates/content/en/UseCasesList/use-cases.mdx +0 -30
- package/templates/content/en/Whitepaper/ax-first-product-development.mdx +0 -27
- package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +0 -27
- package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +0 -31
- package/templates/content/en-XA/AboutPage/about.mdx +0 -8
- package/templates/content/en-XA/FAQPage/faq.mdx +0 -8
- package/templates/content/en-XA/HomePage/home.mdx +0 -8
- package/templates/content/es/_site.mdx +0 -30
- package/templates/content/fr/_site.mdx +0 -30
- package/templates/content/ja/_site.mdx +0 -30
- package/templates/content/pt-BR/AboutPage/about.mdx +0 -8
- package/templates/content/pt-BR/FAQPage/faq.mdx +0 -8
- package/templates/content/pt-BR/HomePage/home.mdx +0 -23
|
@@ -25,23 +25,30 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import "dotenv/config";
|
|
27
27
|
|
|
28
|
+
import { PrismaPg } from "@prisma/adapter-pg";
|
|
29
|
+
|
|
28
30
|
import { PrismaClient } from "./generated/client/client.js";
|
|
29
31
|
|
|
32
|
+
// Fixed, well-known ids from the ADR-0031 reserved sentinel range (zero
|
|
33
|
+
// timestamp + version 7 + variant 8 + counter) — valid-shaped ids the
|
|
34
|
+
// users_id_format CHECK admits, stable so the e2e harness can put them in
|
|
35
|
+
// AILK_TEST_AUTH_USER_ALLOWLIST, and impossible to collide with a generated
|
|
36
|
+
// v7 id.
|
|
30
37
|
const TEST_USERS = [
|
|
31
38
|
{
|
|
32
|
-
id: "
|
|
39
|
+
id: "user_00000000-0000-7000-8000-0000000000e1",
|
|
33
40
|
email: "test:e2e-user@ailaunchkit.test",
|
|
34
41
|
name: "E2E Test User",
|
|
35
42
|
role: "user",
|
|
36
43
|
},
|
|
37
44
|
{
|
|
38
|
-
id: "
|
|
45
|
+
id: "user_00000000-0000-7000-8000-0000000000e2",
|
|
39
46
|
email: "test:e2e-admin@ailaunchkit.test",
|
|
40
47
|
name: "E2E Test Admin",
|
|
41
48
|
role: "admin",
|
|
42
49
|
},
|
|
43
50
|
{
|
|
44
|
-
id: "
|
|
51
|
+
id: "user_00000000-0000-7000-8000-0000000000e3",
|
|
45
52
|
email: "test:e2e-owner@ailaunchkit.test",
|
|
46
53
|
name: "E2E Test Owner",
|
|
47
54
|
role: "owner",
|
|
@@ -57,7 +64,10 @@ async function main(): Promise<void> {
|
|
|
57
64
|
process.exit(1);
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
|
|
67
|
+
// Prisma 7 requires an explicit driver adapter (mirrors seed.ts) —
|
|
68
|
+
// `new PrismaClient()` with no adapter throws at construction.
|
|
69
|
+
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
|
70
|
+
const prisma = new PrismaClient({ adapter });
|
|
61
71
|
try {
|
|
62
72
|
for (const user of TEST_USERS) {
|
|
63
73
|
await prisma.user.upsert({
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default-workspace provision seed (roadmap
|
|
3
|
+
* docs/roadmaps/site-config-workspace-tenancy-roadmap.md Phase 1, #3622).
|
|
4
|
+
*
|
|
5
|
+
* Single-tenant AILK has no Workspace at all today. This seed deterministically
|
|
6
|
+
* provisions exactly one default Organization + Workspace (well-known ids/slugs)
|
|
7
|
+
* so every deployment has a resolvable Workspace scope — a foundation for the
|
|
8
|
+
* Phase 2 session wiring (`activeWorkspaceId` resolution) and the Phase 3
|
|
9
|
+
* site-config re-anchor. See docs/specs/default-workspace-provision-spec.md.
|
|
10
|
+
*
|
|
11
|
+
* Race-safe: `upsert` on the unique keys (Organization.slug,
|
|
12
|
+
* Workspace.organizationId_slug) means a concurrent re-invocation converges
|
|
13
|
+
* rather than duplicating.
|
|
14
|
+
*
|
|
15
|
+
* Production-safe: NO `*_ENABLED`-style env guard (unlike seed-test.ts) —
|
|
16
|
+
* default-workspace provisioning is safe to run in production. The
|
|
17
|
+
* `count === 0` guard (not an unconditional upsert) is what keeps this a no-op
|
|
18
|
+
* once ANY Workspace exists — covering both single-tenant re-run idempotency
|
|
19
|
+
* and a multi-tenant deployment that already has real Workspaces.
|
|
20
|
+
*
|
|
21
|
+
* Run via:
|
|
22
|
+
* pnpm --filter @working-theory/database db:seed
|
|
23
|
+
*/
|
|
24
|
+
import "dotenv/config";
|
|
25
|
+
|
|
26
|
+
import { basename } from "node:path";
|
|
27
|
+
|
|
28
|
+
import type { PrismaClient } from "./generated/client/client.js";
|
|
29
|
+
import {
|
|
30
|
+
DEFAULT_ORG_ID,
|
|
31
|
+
DEFAULT_ORG_SLUG,
|
|
32
|
+
DEFAULT_WORKSPACE_ID,
|
|
33
|
+
DEFAULT_WORKSPACE_SLUG,
|
|
34
|
+
OPERATOR_MEMBERSHIP_ID,
|
|
35
|
+
} from "./tenancy.js";
|
|
36
|
+
|
|
37
|
+
// Re-exported so existing consumers (e.g. __tests__/seed.test.ts) keep
|
|
38
|
+
// importing the well-known ids from this module — `database/tenancy.ts` is
|
|
39
|
+
// the one declaration (spec D3); this file re-exports rather than declaring
|
|
40
|
+
// a second copy.
|
|
41
|
+
export {
|
|
42
|
+
DEFAULT_ORG_ID,
|
|
43
|
+
DEFAULT_ORG_SLUG,
|
|
44
|
+
DEFAULT_WORKSPACE_ID,
|
|
45
|
+
DEFAULT_WORKSPACE_SLUG,
|
|
46
|
+
OPERATOR_MEMBERSHIP_ID,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The DI surface `provisionDefaultWorkspace` needs — just the two Prisma
|
|
51
|
+
* delegates it touches. A `Pick` off the real `PrismaClient` type (not a
|
|
52
|
+
* hand-rolled shape), so a real client satisfies it by construction and the
|
|
53
|
+
* DB-free unit test can pass a lightweight stub with no live Postgres.
|
|
54
|
+
*/
|
|
55
|
+
export type DefaultWorkspacePrismaClient = Pick<
|
|
56
|
+
PrismaClient,
|
|
57
|
+
"organization" | "workspace"
|
|
58
|
+
>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Provisions one default Organization + Workspace when no Workspace exists
|
|
62
|
+
* yet; no-op (no create/upsert calls) once any Workspace is present — covering
|
|
63
|
+
* both single-tenant re-run idempotency and a multi-tenant deployment that
|
|
64
|
+
* already has real Workspaces.
|
|
65
|
+
*/
|
|
66
|
+
export async function provisionDefaultWorkspace(
|
|
67
|
+
prisma: DefaultWorkspacePrismaClient,
|
|
68
|
+
): Promise<{ created: boolean }> {
|
|
69
|
+
const existingWorkspaceCount = await prisma.workspace.count();
|
|
70
|
+
if (existingWorkspaceCount > 0) {
|
|
71
|
+
return { created: false };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await prisma.organization.upsert({
|
|
75
|
+
where: { slug: DEFAULT_ORG_SLUG },
|
|
76
|
+
create: {
|
|
77
|
+
id: DEFAULT_ORG_ID,
|
|
78
|
+
name: "Default Organization",
|
|
79
|
+
slug: DEFAULT_ORG_SLUG,
|
|
80
|
+
},
|
|
81
|
+
update: {},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await prisma.workspace.upsert({
|
|
85
|
+
where: {
|
|
86
|
+
organizationId_slug: {
|
|
87
|
+
organizationId: DEFAULT_ORG_ID,
|
|
88
|
+
slug: DEFAULT_WORKSPACE_SLUG,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
create: {
|
|
92
|
+
id: DEFAULT_WORKSPACE_ID,
|
|
93
|
+
organizationId: DEFAULT_ORG_ID,
|
|
94
|
+
name: "Default Workspace",
|
|
95
|
+
slug: DEFAULT_WORKSPACE_SLUG,
|
|
96
|
+
},
|
|
97
|
+
update: {},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return { created: true };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function main(): Promise<void> {
|
|
104
|
+
// Dynamic imports: the generated client + adapter are constructed only when
|
|
105
|
+
// this module actually runs as the seed entrypoint — never at import time
|
|
106
|
+
// (spec §5.2 Quality Constraints), matching the DI note on seed-test.ts's
|
|
107
|
+
// sibling and the lazy-require pattern in apps-paid/workspace/auth.ts.
|
|
108
|
+
const [{ PrismaClient: RealPrismaClient }, { PrismaPg }] = await Promise.all([
|
|
109
|
+
import("./generated/client/client.js"),
|
|
110
|
+
import("@prisma/adapter-pg"),
|
|
111
|
+
]);
|
|
112
|
+
// Prisma 7 requires an explicit driver adapter (mirrors
|
|
113
|
+
// apps/api/src/lib/prisma.ts) — `new PrismaClient()` with no adapter throws.
|
|
114
|
+
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
|
115
|
+
const prisma = new RealPrismaClient({ adapter });
|
|
116
|
+
try {
|
|
117
|
+
const { created } = await provisionDefaultWorkspace(prisma);
|
|
118
|
+
if (created) {
|
|
119
|
+
console.log(
|
|
120
|
+
`[seed] provisioned default workspace (org=${DEFAULT_ORG_ID}, workspace=${DEFAULT_WORKSPACE_ID})`,
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
console.log(
|
|
124
|
+
"[seed] no-op — a Workspace already exists (re-run or multi-tenant)",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
} finally {
|
|
128
|
+
await prisma.$disconnect();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Only run main() when this module is executed directly (`tsx seed.ts`), not
|
|
133
|
+
// when imported by the unit test — keeps the testable core free of any
|
|
134
|
+
// module-level client construction (spec §5.2 Quality Constraints).
|
|
135
|
+
//
|
|
136
|
+
// Compares argv[1]'s basename rather than `import.meta.url` or
|
|
137
|
+
// `require.main`: this package is `"type": "module"`, so neither `require`
|
|
138
|
+
// nor `__filename` exists at real runtime (tsx does not shim them under true
|
|
139
|
+
// ESM), and `import.meta` is a TS compile-time restriction under ts-jest's
|
|
140
|
+
// CommonJS-targeted transform (jest.config.cjs) that would break
|
|
141
|
+
// `__tests__/seed.test.ts` importing this module regardless of whether the
|
|
142
|
+
// guard ever evaluates true.
|
|
143
|
+
if (basename(process.argv[1] ?? "") === "seed.ts") {
|
|
144
|
+
main().catch((err) => {
|
|
145
|
+
console.error("[seed] failed:", err);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default tenancy identity constants — the SINGLE source of truth (spec D3).
|
|
3
|
+
*
|
|
4
|
+
* The well-known default Organization + Workspace ids/slugs that the
|
|
5
|
+
* single-tenant provision seed (Phase 1, #3622 — `database/seed.ts`) creates,
|
|
6
|
+
* and that the session-resolution guard (Phase 2, #3627 —
|
|
7
|
+
* `apps/api/src/services/tenant-context.ts`) binds on to resolve a default
|
|
8
|
+
* scope for a single-tenant deployment. Exported publicly via the
|
|
9
|
+
* `@working-theory/database/tenancy` subpath (see `package.json` `exports`)
|
|
10
|
+
* so `apps/api` can import them across the package boundary without a second,
|
|
11
|
+
* drift-prone declaration of the tenant-isolation identity.
|
|
12
|
+
*
|
|
13
|
+
* See docs/specs/single-tenant-session-workspace-spec.md §3 D3.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// The three constants below are SENTINEL ids from the reserved range of the
|
|
17
|
+
// prefixed-UUIDv7 scheme (ADR-0031 rule 7): zero timestamp bits + version 7 +
|
|
18
|
+
// variant 8 + a small counter suffix. They are valid-shaped v7 ids (the
|
|
19
|
+
// database CHECK constraints admit them), can never collide with a generated
|
|
20
|
+
// id (a real v7's timestamp bits are the current epoch-ms, never zero), and
|
|
21
|
+
// are recognizable via `isSentinel(id)` from `@working-theory/ids` — key on
|
|
22
|
+
// that predicate, never a hardcoded literal. They carry the branded `Id<E>`
|
|
23
|
+
// types so consumers get compile-time entity safety (ADR-0031 rule 5).
|
|
24
|
+
|
|
25
|
+
import type { Id } from "@working-theory/ids";
|
|
26
|
+
|
|
27
|
+
/** Well-known default Organization identity — a fixed reserved-range sentinel. */
|
|
28
|
+
export const DEFAULT_ORG_ID =
|
|
29
|
+
"org_00000000-0000-7000-8000-000000000001" as Id<"organization">;
|
|
30
|
+
export const DEFAULT_ORG_SLUG = "default";
|
|
31
|
+
|
|
32
|
+
/** Well-known default Workspace identity — a fixed reserved-range sentinel. */
|
|
33
|
+
export const DEFAULT_WORKSPACE_ID =
|
|
34
|
+
"wksp_00000000-0000-7000-8000-000000000001" as Id<"workspace">;
|
|
35
|
+
export const DEFAULT_WORKSPACE_SLUG = "default";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Well-known Membership id the single-tenant owner-pin binds the operator
|
|
39
|
+
* to (docs/specs/single-tenant-owner-pin-spec.md D2). A fixed sentinel id
|
|
40
|
+
* makes the TOFU operator-binding insert race-safe: the `Membership.id`
|
|
41
|
+
* primary-key uniqueness — not application-level "is this the first
|
|
42
|
+
* user?" logic — enforces exactly one owner under concurrent first-logins.
|
|
43
|
+
*/
|
|
44
|
+
export const OPERATOR_MEMBERSHIP_ID =
|
|
45
|
+
"member_00000000-0000-7000-8000-000000000001" as Id<"membership">;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": ".",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"noEmit": false,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"types": ["node"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["flows/**/*.ts"],
|
|
14
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/__tests__/**"]
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": ".",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"noEmit": false,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"types": ["node"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["tenancy.ts"]
|
|
14
|
+
}
|
package/templates/package.json
CHANGED
|
@@ -4,64 +4,28 @@
|
|
|
4
4
|
"description": "AI Launch Kit starter site.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"audit:coverage": "tsx tools/audit-coverage.ts",
|
|
15
|
-
"lint:coverage-thresholds": "tsx tools/lint-coverage-thresholds.ts",
|
|
16
|
-
"env:check": "tsx tools/validate-env.ts",
|
|
17
|
-
"schema:check": "tsx tools/validate-schemas.ts",
|
|
18
|
-
"spec-ac:check": "tsx tools/lint-spec-ac.ts",
|
|
19
|
-
"lint:rtl": "tsx tools/lint-rtl/check.ts",
|
|
20
|
-
"lint:styling-conformance": "tsx tools/lint-styling-conformance/check.ts",
|
|
21
|
-
"lint:required-checks": "tsx tools/lint-required-checks.ts",
|
|
22
|
-
"collisions:check": "bash tools/check-collisions.sh",
|
|
23
|
-
"component:inventory": "tsx scripts/component/component-inventory.ts",
|
|
24
|
-
"component:manifest": "tsx scripts/component/gen-sweep-manifest.ts",
|
|
25
|
-
"component:page-manifest": "tsx scripts/component/gen-page-manifest.ts docs/internal/pages/page-manifest.md",
|
|
26
|
-
"pages:check": "tsx scripts/component/gen-page-manifest.ts docs/internal/pages/page-manifest.md --check",
|
|
27
|
-
"check-page-types": "tsx scripts/component/check-page-type-alignment.ts",
|
|
28
|
-
"check-content-renders": "tsx tools/lint-check-content-renders.ts",
|
|
29
|
-
"check-mdx-vocabulary": "tsx tools/lint-mdx-component-vocabulary.ts",
|
|
30
|
-
"theme:check": "tsx scripts/check-design-system-sync.ts",
|
|
31
|
-
"content:compile": "TSX_TSCONFIG_PATH=tools/tsconfig.json tsx tools/content-compile/index.ts",
|
|
32
|
-
"codegen": "tsx tools/codegen/run.ts",
|
|
33
|
-
"preflight": "bash scripts/preflight.sh",
|
|
34
|
-
"preflight:frontend": "PREFLIGHT_SCOPE=frontend bash scripts/preflight.sh",
|
|
7
|
+
"dev": "pnpm --parallel -r dev",
|
|
8
|
+
"build": "pnpm -r build",
|
|
9
|
+
"start": "pnpm --filter @working-theory/web start",
|
|
10
|
+
"test": "pnpm -r test",
|
|
11
|
+
"test:watch": "pnpm -r test:watch",
|
|
12
|
+
"lint": "pnpm -r --if-present lint",
|
|
13
|
+
"type-check": "pnpm -r --if-present type-check",
|
|
35
14
|
"format": "prettier --write .",
|
|
36
15
|
"format:check": "prettier --check .",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"dev": "pnpm --parallel -r dev",
|
|
43
|
-
"db:generate": "pnpm --filter @working-theory/database exec prisma generate",
|
|
44
|
-
"db:migrate": "pnpm --filter @working-theory/database exec prisma migrate dev",
|
|
45
|
-
"db:migrate:deploy": "pnpm --filter @working-theory/database exec prisma migrate deploy",
|
|
46
|
-
"db:seed": "pnpm --filter @working-theory/database run seed",
|
|
47
|
-
"db:studio": "pnpm --filter @working-theory/database exec prisma studio",
|
|
48
|
-
"prepare": "husky",
|
|
49
|
-
"aeo": "pnpm --filter @working-theory/aeo run",
|
|
50
|
-
"changeset": "changeset",
|
|
51
|
-
"changeset:version": "changeset version && pnpm install --lockfile-only",
|
|
52
|
-
"changeset:publish": "changeset publish",
|
|
53
|
-
"storybook:build": "pnpm --filter @working-theory/theme run build && pnpm --filter @working-theory/ui run build && pnpm --filter @working-theory/ui exec storybook build -o ../../storybook-static",
|
|
54
|
-
"visual:test": "playwright test --config tests/visual/playwright.config.ts",
|
|
55
|
-
"visual:test:live-app": "playwright test --config tests/visual/playwright-live-app.config.ts"
|
|
16
|
+
"db:generate": "pnpm --filter @working-theory/database run db:generate",
|
|
17
|
+
"db:migrate": "pnpm --filter @working-theory/database run db:migrate",
|
|
18
|
+
"db:migrate:deploy": "pnpm --filter @working-theory/database run db:migrate:deploy",
|
|
19
|
+
"db:seed": "pnpm --filter @working-theory/database run db:seed",
|
|
20
|
+
"db:studio": "pnpm --filter @working-theory/database run db:studio"
|
|
56
21
|
},
|
|
57
22
|
"devDependencies": {
|
|
58
23
|
"@changesets/changelog-github": "^0.7.0",
|
|
59
|
-
"@playwright/test": "^1.61.1",
|
|
60
|
-
"http-server": "^14.1.1",
|
|
61
|
-
"wait-on": "^8.0.1",
|
|
62
24
|
"@changesets/cli": "^2.27.0",
|
|
63
25
|
"@eslint/js": "^10.0.1",
|
|
64
26
|
"@lhci/cli": "^0.15.1",
|
|
27
|
+
"@mdx-js/mdx": "^3.1.1",
|
|
28
|
+
"@playwright/test": "^1.61.1",
|
|
65
29
|
"@stryker-mutator/core": "^8.7.1",
|
|
66
30
|
"@stryker-mutator/jest-runner": "^8.7.1",
|
|
67
31
|
"@types/jest": "^30.0.0",
|
|
@@ -70,6 +34,7 @@
|
|
|
70
34
|
"@typescript-eslint/parser": "^8.62.1",
|
|
71
35
|
"ajv": "^8.20.0",
|
|
72
36
|
"ajv-formats": "^3.0.1",
|
|
37
|
+
"axe-core": "^4.10.0",
|
|
73
38
|
"eslint": "^10.6.0",
|
|
74
39
|
"eslint-import-resolver-typescript": "^4.4.5",
|
|
75
40
|
"eslint-plugin-import-x": "^4.17.1",
|
|
@@ -78,20 +43,24 @@
|
|
|
78
43
|
"eslint-plugin-promise": "^7.2.1",
|
|
79
44
|
"expect-type": "^1.4.0",
|
|
80
45
|
"globals": "^17.7.0",
|
|
81
|
-
"
|
|
46
|
+
"gray-matter": "^4.0.3",
|
|
47
|
+
"http-server": "^14.1.1",
|
|
82
48
|
"husky": "^9.1.7",
|
|
83
49
|
"jest": "^30.4.2",
|
|
84
50
|
"jiti": "^2.4.2",
|
|
85
51
|
"lint-staged": "^15.3.0",
|
|
86
52
|
"prettier": "^3.9.4",
|
|
53
|
+
"ts-declaration-location": "^1.0.7",
|
|
87
54
|
"ts-jest": "^29.4.11",
|
|
88
55
|
"tsx": "^4.22.4",
|
|
56
|
+
"turbo": "^2.10.4",
|
|
89
57
|
"typescript": "^6.0.3",
|
|
90
58
|
"typescript-eslint": "^8.62.1",
|
|
59
|
+
"wait-on": "^8.0.1",
|
|
91
60
|
"yaml": "^2.9.0",
|
|
92
61
|
"zod": "^4.2.1",
|
|
93
62
|
"zod-to-ts": "^2.1.0",
|
|
94
|
-
"@working-theory/cli": "^0.
|
|
63
|
+
"@working-theory/cli": "^0.20.0"
|
|
95
64
|
},
|
|
96
65
|
"lint-staged": {
|
|
97
66
|
"*.{ts,tsx}": [
|
|
@@ -104,22 +73,28 @@
|
|
|
104
73
|
"bash -c 'pnpm architecture'"
|
|
105
74
|
]
|
|
106
75
|
},
|
|
107
|
-
"packageManager": "pnpm@
|
|
76
|
+
"packageManager": "pnpm@10.34.5+sha512.a4ee05f2f73658255bd6a89859c065a45c28a57daefae2c893a168ee2b73168c37b91e83e57ea67654ad03f03031746430e8bce38e362e042605fb8abc80192e",
|
|
108
77
|
"engines": {
|
|
109
78
|
"node": ">=20.19.0"
|
|
110
79
|
},
|
|
111
80
|
"pnpm": {
|
|
81
|
+
"onlyBuiltDependencies": [
|
|
82
|
+
"prisma"
|
|
83
|
+
],
|
|
112
84
|
"auditConfig": {
|
|
113
85
|
"ignoreGhsas": [
|
|
114
86
|
"GHSA-gv7w-rqvm-qjhr"
|
|
115
87
|
]
|
|
116
88
|
},
|
|
117
89
|
"overrides": {
|
|
118
|
-
"tar": "^7.5.
|
|
90
|
+
"tar": "^7.5.21",
|
|
119
91
|
"protobufjs": "^8.4.1",
|
|
120
92
|
"@grpc/grpc-js": "^1.14.4",
|
|
121
93
|
"hono": ">=4.12.25",
|
|
122
|
-
"undici": "^7.28.0"
|
|
94
|
+
"undici": "^7.28.0",
|
|
95
|
+
"js-yaml@3": "^3.15.0",
|
|
96
|
+
"js-yaml@4": "^4.3.0",
|
|
97
|
+
"brace-expansion@2": "^2.1.2"
|
|
123
98
|
}
|
|
124
99
|
}
|
|
125
100
|
}
|
package/templates/project.yaml
CHANGED
|
@@ -3,7 +3,7 @@ schema_version: 1
|
|
|
3
3
|
# project.yaml — per-repo configuration consumed by Claude Code skills and
|
|
4
4
|
# global rules. Replace REPLACE_ME values with your repo's actual identity.
|
|
5
5
|
#
|
|
6
|
-
# See https://github.com/
|
|
6
|
+
# See https://github.com/working-theory-labs/ai-launch-kit/blob/main/project.yaml
|
|
7
7
|
# for AI Launch Kit's own canonical example.
|
|
8
8
|
|
|
9
9
|
identity:
|
package/templates/tsconfig.json
CHANGED
|
@@ -4,42 +4,6 @@
|
|
|
4
4
|
{ "path": "./apps/api" },
|
|
5
5
|
{ "path": "./apps/mcp" },
|
|
6
6
|
{ "path": "./apps/web" },
|
|
7
|
-
{ "path": "./database/tsconfig.build.json" }
|
|
8
|
-
{ "path": "./apps-paid/billing" },
|
|
9
|
-
{ "path": "./apps-paid/license-issuer" },
|
|
10
|
-
{ "path": "./apps-paid/marketing-api" },
|
|
11
|
-
{ "path": "./apps-paid/marketing-mcp" },
|
|
12
|
-
{ "path": "./packages/aeo" },
|
|
13
|
-
{ "path": "./packages/agent-context" },
|
|
14
|
-
{ "path": "./packages/analytics" },
|
|
15
|
-
{ "path": "./packages/api-client" },
|
|
16
|
-
{ "path": "./packages/common" },
|
|
17
|
-
{ "path": "./packages/license" },
|
|
18
|
-
{ "path": "./packages/cda-filesystem" },
|
|
19
|
-
{ "path": "./packages/cli" },
|
|
20
|
-
{ "path": "./packages/content-adapters" },
|
|
21
|
-
{ "path": "./packages/content-projection" },
|
|
22
|
-
{ "path": "./packages/email" },
|
|
23
|
-
{ "path": "./packages/env" },
|
|
24
|
-
{ "path": "./packages/fumadocs-schema" },
|
|
25
|
-
{ "path": "./packages/metadata" },
|
|
26
|
-
{ "path": "./packages/observability" },
|
|
27
|
-
{ "path": "./packages/schema" },
|
|
28
|
-
{ "path": "./packages/schema-validator" },
|
|
29
|
-
{ "path": "./packages/schema-pack-registry" },
|
|
30
|
-
{ "path": "./packages/sections-registry" },
|
|
31
|
-
{ "path": "./packages/site-config" },
|
|
32
|
-
{ "path": "./packages/stripe-client" },
|
|
33
|
-
{ "path": "./packages/theme" },
|
|
34
|
-
{ "path": "./packages/ui" },
|
|
35
|
-
{ "path": "./packages/validation" },
|
|
36
|
-
{ "path": "./packages/web-i18n" },
|
|
37
|
-
{ "path": "./packages-paid/billing-client" },
|
|
38
|
-
{ "path": "./packages-paid/branding" },
|
|
39
|
-
{ "path": "./packages-paid/license-client" },
|
|
40
|
-
{ "path": "./packages-paid/license-manifest" },
|
|
41
|
-
{ "path": "./packages-paid/marketing-api-client" },
|
|
42
|
-
{ "path": "./packages-paid/partner-session" },
|
|
43
|
-
{ "path": "./packages-paid/preview-protocol" }
|
|
7
|
+
{ "path": "./database/tsconfig.build.json" }
|
|
44
8
|
]
|
|
45
9
|
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file cookie-attributes.test.ts (S13 adversarial)
|
|
3
|
-
*
|
|
4
|
-
* Verifies that `apps/web/auth.ts` does NOT weaken Better Auth's secure-cookie
|
|
5
|
-
* defaults. Better Auth's `nextCookies()` plugin emits session cookies with
|
|
6
|
-
* `HttpOnly`, `Secure` (in non-dev environments), `SameSite=Lax`, and
|
|
7
|
-
* `Path=/`. The configuration in `auth.ts` must not override any of those.
|
|
8
|
-
*
|
|
9
|
-
* Strategy: mock `better-auth` so its real ESM-only module never loads in the
|
|
10
|
-
* Jest CJS preset. The mock's `betterAuth(options)` returns `{ options }` so
|
|
11
|
-
* the test can inspect the raw config object the AILK code passed in. The
|
|
12
|
-
* assertions guard the AILK-owned surface, not Better Auth's emission
|
|
13
|
-
* (that's the library's contract).
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
jest.mock("better-auth", () => ({
|
|
17
|
-
betterAuth: (options: unknown) => ({ options }),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
jest.mock("better-auth/adapters/prisma", () => ({
|
|
21
|
-
prismaAdapter: () => ({ id: "mock-prisma-adapter" }),
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
jest.mock("better-auth/next-js", () => ({
|
|
25
|
-
nextCookies: () => ({ id: "next-cookies" }),
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
import { createAuth } from "../../../auth";
|
|
29
|
-
|
|
30
|
-
// Stub PrismaClient — avoids a real DB connection at module-load time.
|
|
31
|
-
// Injected via createAuth({ prisma }) instead of jest.mock("../../../lib/prisma-for-auth").
|
|
32
|
-
// Pattern mirrors apps-paid/dashboard-web/auth.ts DI.
|
|
33
|
-
const stubPrisma = {} as NonNullable<NonNullable<Parameters<typeof createAuth>[0]>["prisma"]>;
|
|
34
|
-
const auth = createAuth({ prisma: stubPrisma });
|
|
35
|
-
|
|
36
|
-
type CookieAttrs = {
|
|
37
|
-
httpOnly?: boolean;
|
|
38
|
-
secure?: boolean;
|
|
39
|
-
sameSite?: "lax" | "strict" | "none";
|
|
40
|
-
path?: string;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
type AdvancedCookies = {
|
|
44
|
-
session_token?: { attributes?: CookieAttrs };
|
|
45
|
-
session_data?: { attributes?: CookieAttrs };
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
type AuthOptions = {
|
|
49
|
-
advanced?: {
|
|
50
|
-
useSecureCookies?: boolean;
|
|
51
|
-
cookies?: AdvancedCookies;
|
|
52
|
-
defaultCookieAttributes?: CookieAttrs;
|
|
53
|
-
};
|
|
54
|
-
plugins?: Array<{ id?: string }>;
|
|
55
|
-
session?: { expiresIn?: number; updateAge?: number };
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// eslint-disable-next-line no-restricted-syntax -- the mocked betterAuth returns { options: <unknown> }; the real type carries no public options shape, so a double assertion is the narrow path to inspect the AILK-owned config object.
|
|
59
|
-
const options = (auth as unknown as { options: AuthOptions }).options;
|
|
60
|
-
|
|
61
|
-
describe("S13 adversarial — cookie attributes (config surface)", () => {
|
|
62
|
-
it("does NOT disable useSecureCookies (Better Auth secure default preserved)", () => {
|
|
63
|
-
expect(options.advanced?.useSecureCookies).not.toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("does NOT override session_token cookie to drop HttpOnly", () => {
|
|
67
|
-
const sessionAttrs = options.advanced?.cookies?.session_token?.attributes;
|
|
68
|
-
expect(sessionAttrs?.httpOnly).not.toBe(false);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("does NOT override session_token cookie to drop Secure", () => {
|
|
72
|
-
const sessionAttrs = options.advanced?.cookies?.session_token?.attributes;
|
|
73
|
-
expect(sessionAttrs?.secure).not.toBe(false);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("does NOT relax sameSite to 'none' (CSRF protection preserved)", () => {
|
|
77
|
-
expect(
|
|
78
|
-
options.advanced?.cookies?.session_token?.attributes?.sameSite,
|
|
79
|
-
).not.toBe("none");
|
|
80
|
-
expect(options.advanced?.defaultCookieAttributes?.sameSite).not.toBe(
|
|
81
|
-
"none",
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("includes the nextCookies() plugin so Next.js sets cookies via Response", () => {
|
|
86
|
-
const pluginIds = (options.plugins ?? []).map((p) => p.id);
|
|
87
|
-
expect(pluginIds).toContain("next-cookies");
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("persists sessions in the database (admin-revocable model)", () => {
|
|
91
|
-
expect(options.session).toBeDefined();
|
|
92
|
-
expect(options.session?.expiresIn).toBeGreaterThan(0);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file oauth-state-parameter.test.ts (S13 adversarial)
|
|
3
|
-
*
|
|
4
|
-
* OAuth `state` parameter protection. Better Auth's social-signin flow
|
|
5
|
-
* generates an opaque `state` value on every OAuth handshake; the callback
|
|
6
|
-
* route validates it. The AILK-owned surface that could disable this is
|
|
7
|
-
* `auth.options` — there is no documented Better Auth knob to turn state
|
|
8
|
-
* generation off, but a future migration to a custom plugin (e.g.
|
|
9
|
-
* `genericOAuth`) could weaken it. This file pins the AILK config so a
|
|
10
|
-
* regression that introduces a state-disabling override is caught.
|
|
11
|
-
*
|
|
12
|
-
* Strategy: mock `better-auth` so the real ESM-only module never loads;
|
|
13
|
-
* inspect the options object the AILK code constructed.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
jest.mock("better-auth", () => ({
|
|
17
|
-
betterAuth: (options: unknown) => ({ options }),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
jest.mock("better-auth/adapters/prisma", () => ({
|
|
21
|
-
prismaAdapter: () => ({ id: "mock-prisma-adapter" }),
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
jest.mock("better-auth/next-js", () => ({
|
|
25
|
-
nextCookies: () => ({ id: "next-cookies" }),
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
import { createAuth } from "../../../auth";
|
|
29
|
-
|
|
30
|
-
// Stub PrismaClient — avoids a real DB connection at module-load time.
|
|
31
|
-
// Injected via createAuth({ prisma }) instead of jest.mock("../../../lib/prisma-for-auth").
|
|
32
|
-
// Pattern mirrors apps-paid/dashboard-web/auth.ts DI.
|
|
33
|
-
const stubPrisma = {} as NonNullable<NonNullable<Parameters<typeof createAuth>[0]>["prisma"]>;
|
|
34
|
-
const auth = createAuth({ prisma: stubPrisma });
|
|
35
|
-
|
|
36
|
-
type SocialProviderOpts = {
|
|
37
|
-
skipStateCheck?: boolean;
|
|
38
|
-
disableState?: boolean;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
type AuthOptions = {
|
|
42
|
-
plugins?: Array<{ id?: string }>;
|
|
43
|
-
socialProviders?: Record<string, SocialProviderOpts>;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// eslint-disable-next-line no-restricted-syntax -- the mocked betterAuth returns { options: <unknown> }; the real type carries no public options shape, so a double assertion is the narrow path to inspect the AILK-owned config object.
|
|
47
|
-
const options = (auth as unknown as { options: AuthOptions }).options;
|
|
48
|
-
|
|
49
|
-
describe("S13 adversarial — OAuth state parameter", () => {
|
|
50
|
-
it("auth config does NOT register a generic-oauth plugin (which would need explicit state config review)", () => {
|
|
51
|
-
const plugins = options.plugins ?? [];
|
|
52
|
-
const generic = plugins.find((p) => p.id === "generic-oauth");
|
|
53
|
-
expect(generic).toBeUndefined();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("active social providers do NOT carry a skipStateCheck override", () => {
|
|
57
|
-
const providers = options.socialProviders ?? {};
|
|
58
|
-
for (const [, opts] of Object.entries(providers)) {
|
|
59
|
-
// No Better Auth option named skipStateCheck/disableState exists today.
|
|
60
|
-
// The assertion guards against a custom wrapper that adds one.
|
|
61
|
-
expect(opts.skipStateCheck).toBeFalsy();
|
|
62
|
-
expect(opts.disableState).toBeFalsy();
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("social provider entries are syntactically valid (each has an id-shaped key)", () => {
|
|
67
|
-
const providers = options.socialProviders ?? {};
|
|
68
|
-
// When env vars are unset (OSS standalone default) the map is empty.
|
|
69
|
-
// Test passes vacuously. When wired, each provider has a non-empty key
|
|
70
|
-
// which Better Auth uses to route state into the right cookie namespace.
|
|
71
|
-
for (const name of Object.keys(providers)) {
|
|
72
|
-
expect(name.length).toBeGreaterThan(0);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
});
|