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
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
// auth namespace — tenancy models (Organization, Workspace, Membership, Invitation)
|
|
2
|
+
//
|
|
3
|
+
// The multi-tenant module's Organization → Workspace → Membership layer
|
|
4
|
+
// (FEAT-042). Per ADR 0009, the auth namespace's charter is identity + tenancy
|
|
5
|
+
// membership, so these live beside User/Session — @relation to User is allowed
|
|
6
|
+
// here (same namespace).
|
|
7
|
+
//
|
|
8
|
+
// Organization is the tenant boundary (members, billing, security key on
|
|
9
|
+
// organizationId). Workspace is the working context (operational config + all
|
|
10
|
+
// domain content key on workspaceId). Membership is org-level; workspace
|
|
11
|
+
// visibility follows org membership (per-workspace ACL is a future additive
|
|
12
|
+
// concern — do not add a workspace-member table without a new design pass).
|
|
13
|
+
//
|
|
14
|
+
// Organization / Membership / Invitation are managed by the Better Auth
|
|
15
|
+
// organization plugin (apps/workspace auth config maps member → Membership via
|
|
16
|
+
// modelName). Workspace is AILK's own model: the plugin's teams feature was
|
|
17
|
+
// evaluated and rejected because setActiveTeam requires per-team membership
|
|
18
|
+
// rows, contradicting org-level membership (see
|
|
19
|
+
// docs/research/ploy-capture/lessons/better-auth-teams-rejected-for-workspaces.md).
|
|
20
|
+
//
|
|
21
|
+
// Generator + datasource blocks live in database/schema.prisma (the root schema
|
|
22
|
+
// file). This file holds only model definitions for the auth-namespace tenancy
|
|
23
|
+
// tables; the same models are registered in the root schema for generation.
|
|
24
|
+
|
|
25
|
+
/// Role — membership role within an Organization. Hierarchy: owner > admin > member.
|
|
26
|
+
/// Values are lowercase to match the Better Auth organization plugin's role
|
|
27
|
+
/// strings ("owner" | "admin" | "member") so plugin writes pass Prisma enum
|
|
28
|
+
/// validation unmapped. Distinct from User.role (a per-deployment String).
|
|
29
|
+
enum Role {
|
|
30
|
+
owner
|
|
31
|
+
admin
|
|
32
|
+
member
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Organization — the tenant boundary. Owns membership, billing, security.
|
|
36
|
+
model Organization {
|
|
37
|
+
id String @id @default(dbgenerated("('org_'::text || (uuidv7())::text)")) @db.Text
|
|
38
|
+
name String
|
|
39
|
+
slug String @unique
|
|
40
|
+
logo String?
|
|
41
|
+
metadata String?
|
|
42
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
43
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
44
|
+
|
|
45
|
+
// Org-level billing identity + tier/subscription projection (org-scoped
|
|
46
|
+
// billing, #3601). Mirrors the User billing shape (see User L134-144) at the
|
|
47
|
+
// Organization level: in a multi-tenant deployment the Organization is the
|
|
48
|
+
// billing entity (individuals are billed as orgs-of-one on their sentinel
|
|
49
|
+
// default Organization). The Stripe webhook is the only writer (see
|
|
50
|
+
// apps/api/src/routes/webhooks/stripe.ts, keyed on checkout
|
|
51
|
+
// metadata.organizationId). Single-tenant deployments keep User-scoped
|
|
52
|
+
// billing (User fields above) and never touch these.
|
|
53
|
+
billingProvider String? @map("billing_provider") // "stripe"; provider-agnostic
|
|
54
|
+
billingCustomerId String? @map("billing_customer_id") // cus_xxx or equivalent
|
|
55
|
+
tier String @default("free") // "free" | "pro" | "pro_plus" | "enterprise"
|
|
56
|
+
hasCarePlan Boolean @default(false) @map("has_care_plan")
|
|
57
|
+
seatCount Int @default(1) @map("seat_count")
|
|
58
|
+
|
|
59
|
+
// Usage-billing balance counters — the Company-counter live on-demand
|
|
60
|
+
// credit model (FEAT-047 P1.S2, #3710 — capture D6, NOT a CreditUsagePeriod
|
|
61
|
+
// ledger table). Same-namespace additions to the existing billing identity
|
|
62
|
+
// fields above — no new relation. Read/written by the credit waterfall
|
|
63
|
+
// (apps/api/src/services/usage-credits.ts, #3716, the sanctioned
|
|
64
|
+
// tenant-scope exception) and the entitlement resolver (P1.S3).
|
|
65
|
+
usageBillingEnabled Boolean @default(false) @map("usage_billing_enabled")
|
|
66
|
+
stripeUsageMeterItemId String? @map("stripe_usage_meter_item_id")
|
|
67
|
+
includedCreditsCents Int @default(0) @map("included_credits_cents")
|
|
68
|
+
includedCreditsUsedCents Int @default(0) @map("included_credits_used_cents")
|
|
69
|
+
onDemandLimitCents Int? @map("on_demand_limit_cents")
|
|
70
|
+
onDemandUsedCents Int @default(0) @map("on_demand_used_cents")
|
|
71
|
+
onDemandPrechargedCents Int @default(0) @map("on_demand_precharged_cents")
|
|
72
|
+
/// Carry-forward credit balance. DB CHECK `>= 0`
|
|
73
|
+
/// (`organizations_on_demand_credit_balance_non_negative`, migration
|
|
74
|
+
/// 20260714030000) — Prisma cannot model CHECK, so the migration is the
|
|
75
|
+
/// source of truth. Debited only via the credit waterfall's compare-and-swap
|
|
76
|
+
/// (apps/api/src/services/usage-credits.ts, #3730); a negative balance would
|
|
77
|
+
/// INVERT the debit and hand out free credits.
|
|
78
|
+
onDemandCreditBalanceCents Int @default(0) @map("on_demand_credit_balance_cents")
|
|
79
|
+
creditsCycleEnd DateTime? @map("credits_cycle_end")
|
|
80
|
+
limitAllocationMode String @default("COMPANY_WIDE") @map("limit_allocation_mode") // "COMPANY_WIDE" | "INDIVIDUAL"
|
|
81
|
+
|
|
82
|
+
memberships Membership[]
|
|
83
|
+
invitations Invitation[]
|
|
84
|
+
workspaces Workspace[]
|
|
85
|
+
|
|
86
|
+
@@unique([billingProvider, billingCustomerId])
|
|
87
|
+
@@map("organizations")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Workspace — working context under an Organization. URL scope for all
|
|
91
|
+
/// domain content; operational config keys on workspaceId. Flat (org →
|
|
92
|
+
/// workspaces): no nesting — a future positioning-entity tree is a separate
|
|
93
|
+
/// feature and must not require tenancy rework.
|
|
94
|
+
model Workspace {
|
|
95
|
+
id String @id @default(dbgenerated("('wksp_'::text || (uuidv7())::text)")) @db.Text
|
|
96
|
+
organizationId String @map("organization_id")
|
|
97
|
+
name String
|
|
98
|
+
slug String
|
|
99
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
100
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
101
|
+
|
|
102
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
103
|
+
|
|
104
|
+
@@unique([organizationId, slug])
|
|
105
|
+
@@index([organizationId])
|
|
106
|
+
@@map("workspaces")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Membership — User ↔ Organization with a Role. Managed by the Better Auth
|
|
110
|
+
/// organization plugin (modelName "membership"). Org-level: grants visibility
|
|
111
|
+
/// into every workspace of the organization.
|
|
112
|
+
model Membership {
|
|
113
|
+
id String @id @default(dbgenerated("('member_'::text || (uuidv7())::text)")) @db.Text
|
|
114
|
+
organizationId String @map("organization_id")
|
|
115
|
+
userId String @map("user_id")
|
|
116
|
+
role Role @default(member)
|
|
117
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
118
|
+
|
|
119
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
120
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
121
|
+
|
|
122
|
+
@@unique([organizationId, userId])
|
|
123
|
+
@@index([userId])
|
|
124
|
+
@@index([organizationId])
|
|
125
|
+
@@map("memberships")
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Invitation — pending invite of an email address into an Organization.
|
|
129
|
+
/// Managed by the Better Auth organization plugin. status:
|
|
130
|
+
/// "pending" | "accepted" | "rejected" | "canceled".
|
|
131
|
+
model Invitation {
|
|
132
|
+
id String @id @default(dbgenerated("('invite_'::text || (uuidv7())::text)")) @db.Text
|
|
133
|
+
organizationId String @map("organization_id")
|
|
134
|
+
email String
|
|
135
|
+
role Role @default(member)
|
|
136
|
+
status String @default("pending")
|
|
137
|
+
expiresAt DateTime? @map("expires_at")
|
|
138
|
+
inviterId String @map("inviter_id")
|
|
139
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
140
|
+
|
|
141
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
142
|
+
inviter User @relation("sent_invitations", fields: [inviterId], references: [id], onDelete: Cascade)
|
|
143
|
+
|
|
144
|
+
@@index([organizationId])
|
|
145
|
+
@@index([email])
|
|
146
|
+
@@map("invitations")
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Usage-billing balances/subscription/plan (FEAT-047 P1.S2, #3710 — Epic
|
|
151
|
+
// #3704). Per ADR 0009 D2 (roadmap §4), billing balances/subscription/plan
|
|
152
|
+
// live in `auth` (identity+tenancy charter); pricing/markup/model config
|
|
153
|
+
// lives in `config` (see database/config/schema.prisma). organizationId is a
|
|
154
|
+
// plain String stable-id — no @relation to Organization, even though both
|
|
155
|
+
// live in this namespace (spec D4: cross-namespace assembly + billing writes
|
|
156
|
+
// are keyed on explicit id, not relation traversal — mirrors the sanctioned
|
|
157
|
+
// usage-credits.ts / entitlements.ts / webhooks/stripe.ts read/write shape).
|
|
158
|
+
// Field roster ported from docs/research/wt-billing-capture/schema.md.
|
|
159
|
+
// ============================================================================
|
|
160
|
+
|
|
161
|
+
/// Subscription — one per Organization; the plan link + Stripe subscription
|
|
162
|
+
/// identity + enterprise contract terms. contractType/paymentMode are
|
|
163
|
+
/// nullable — "enterprise contract fields" only apply to sales-assisted /
|
|
164
|
+
/// enterprise deals; a self-serve subscription leaves them unset (no
|
|
165
|
+
/// business default invented — see spec §5.3).
|
|
166
|
+
model Subscription {
|
|
167
|
+
id String @id @default(dbgenerated("('orgsub_'::text || (uuidv7())::text)")) @db.Text
|
|
168
|
+
organizationId String @unique @map("organization_id")
|
|
169
|
+
planId String @map("plan_id")
|
|
170
|
+
|
|
171
|
+
stripeSubscriptionId String? @map("stripe_subscription_id")
|
|
172
|
+
stripePriceId String? @map("stripe_price_id")
|
|
173
|
+
stripeCustomerId String? @map("stripe_customer_id")
|
|
174
|
+
|
|
175
|
+
contractType ContractType? @map("contract_type")
|
|
176
|
+
netTermsDays Int? @map("net_terms_days")
|
|
177
|
+
contractValueCents Int? @map("contract_value_cents")
|
|
178
|
+
paymentMode SubscriptionPaymentMode? @map("payment_mode")
|
|
179
|
+
|
|
180
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
181
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
182
|
+
|
|
183
|
+
@@map("subscriptions")
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/// Plan — the plan catalog (allowances, limits, Stripe price). Global
|
|
187
|
+
/// (not org-scoped) — the definitions a Subscription.planId references by
|
|
188
|
+
/// stable id, no @relation (spec D4).
|
|
189
|
+
model Plan {
|
|
190
|
+
id String @id @default(dbgenerated("('plan_'::text || (uuidv7())::text)")) @db.Text
|
|
191
|
+
slug String @unique
|
|
192
|
+
tier Int
|
|
193
|
+
|
|
194
|
+
baseTokens Int @map("base_tokens")
|
|
195
|
+
// Decimal, never Float: usageMultiplier scales a money amount. DOUBLE
|
|
196
|
+
// PRECISION admits NaN/Infinity, and NaN compares false against every
|
|
197
|
+
// spend-limit comparison — a float here fails OPEN past the limit gate.
|
|
198
|
+
// Matches the sibling money-multiplier convention (LlmModel.
|
|
199
|
+
// consumptionMultiplier, database/config/schema.prisma).
|
|
200
|
+
usageMultiplier Decimal @map("usage_multiplier") @db.Decimal(5, 2)
|
|
201
|
+
isPooled Boolean @map("is_pooled")
|
|
202
|
+
monthlyDollarCreditCents Int @map("monthly_dollar_credit_cents")
|
|
203
|
+
|
|
204
|
+
features Json
|
|
205
|
+
limits Json
|
|
206
|
+
|
|
207
|
+
stripePriceId String? @map("stripe_price_id")
|
|
208
|
+
|
|
209
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
210
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
211
|
+
|
|
212
|
+
@@map("plans")
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/// UsageSettings — one per Organization; the usage-based-billing opt-in +
|
|
216
|
+
/// monthly spend-limit gate (read by the spend-limit check, P2).
|
|
217
|
+
model UsageSettings {
|
|
218
|
+
id String @id @default(dbgenerated("('usgset_'::text || (uuidv7())::text)")) @db.Text
|
|
219
|
+
organizationId String @unique @map("organization_id")
|
|
220
|
+
|
|
221
|
+
usageBasedBillingEnabled Boolean @default(false) @map("usage_based_billing_enabled")
|
|
222
|
+
monthlySpendLimitCents Int? @map("monthly_spend_limit_cents")
|
|
223
|
+
|
|
224
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
225
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
226
|
+
|
|
227
|
+
@@map("usage_settings")
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
// === Relocated from root schema.prisma (ADR-0009 D4 Phase 2, #3607) ===
|
|
232
|
+
|
|
233
|
+
/// User - Dashboard users (site owners, admins, end-users)
|
|
234
|
+
///
|
|
235
|
+
/// emailVerified is a Boolean per Better Auth's contract (NextAuth previously
|
|
236
|
+
/// stored the verification timestamp as DateTime?). The five custom relations
|
|
237
|
+
/// — ApiToken, RefreshToken, OAuthAuthorization, PushToken, UserData — keep
|
|
238
|
+
/// their onDelete: Cascade semantics so user removal cleanly tears down all
|
|
239
|
+
/// dependent rows.
|
|
240
|
+
model User {
|
|
241
|
+
id String @id @default(dbgenerated("('user_'::text || (uuidv7())::text)")) @db.Text
|
|
242
|
+
email String @unique
|
|
243
|
+
name String?
|
|
244
|
+
image String?
|
|
245
|
+
emailVerified Boolean @default(false) @map("email_verified")
|
|
246
|
+
|
|
247
|
+
// Profile extensions
|
|
248
|
+
role String @default("user") // "user", "admin", "owner"
|
|
249
|
+
|
|
250
|
+
// Billing identity — provider-agnostic so Stripe is v1 value, not baked-in name.
|
|
251
|
+
// Webhook is the only writer (see apps/api/src/routes/webhooks/stripe.ts).
|
|
252
|
+
// #771 self-serve dashboard reads billingCustomerId for Stripe customer-portal URL.
|
|
253
|
+
billingProvider String? @map("billing_provider") // "stripe"; future: "lemonsqueezy", "paddle"
|
|
254
|
+
billingCustomerId String? @map("billing_customer_id") // cus_xxx (Stripe) or equivalent
|
|
255
|
+
|
|
256
|
+
// Subscription tier projection — derived from the Stripe webhook's product-aware
|
|
257
|
+
// routing (#898). Defaults to "free" until a customer.subscription.created event
|
|
258
|
+
// fires; flips to "pro" / "pro_plus" / etc. based on the line item's product.
|
|
259
|
+
// hasCarePlan is true only for pro_plus today; seatCount mirrors the line item
|
|
260
|
+
// quantity from Stripe's adjustable-quantity widget (1–50).
|
|
261
|
+
tier String @default("free") // "free" | "pro" | "pro_plus" | "enterprise" (retired "agency"/"commercial" rows migrated to "enterprise" — #3516)
|
|
262
|
+
hasCarePlan Boolean @default(false) @map("has_care_plan")
|
|
263
|
+
seatCount Int @default(1) @map("seat_count")
|
|
264
|
+
|
|
265
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
266
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
267
|
+
|
|
268
|
+
// Better Auth relations
|
|
269
|
+
sessions Session[]
|
|
270
|
+
accounts Account[]
|
|
271
|
+
|
|
272
|
+
// API & OAuth
|
|
273
|
+
apiTokens ApiToken[]
|
|
274
|
+
refreshTokens RefreshToken[]
|
|
275
|
+
oauthAuthorizations OAuthAuthorization[]
|
|
276
|
+
pushTokens PushToken[]
|
|
277
|
+
|
|
278
|
+
// Extensions
|
|
279
|
+
userData UserData[]
|
|
280
|
+
|
|
281
|
+
// Tenancy (multi-tenant module — database/auth/schema.prisma)
|
|
282
|
+
memberships Membership[]
|
|
283
|
+
sentInvitations Invitation[] @relation("sent_invitations")
|
|
284
|
+
|
|
285
|
+
@@unique([billingProvider, billingCustomerId])
|
|
286
|
+
@@map("users")
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/// Session - Active user sessions (Better Auth schema)
|
|
290
|
+
///
|
|
291
|
+
/// Session.token is the opaque cookie value the dual-mode preHandler reads.
|
|
292
|
+
/// Deleting a row revokes the session; deleting the parent User cascades.
|
|
293
|
+
model Session {
|
|
294
|
+
id String @id @default(dbgenerated("('sess_'::text || (uuidv7())::text)")) @db.Text
|
|
295
|
+
expiresAt DateTime @map("expires_at")
|
|
296
|
+
token String @unique
|
|
297
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
298
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
299
|
+
ipAddress String? @map("ip_address")
|
|
300
|
+
userAgent String? @map("user_agent")
|
|
301
|
+
userId String @map("user_id")
|
|
302
|
+
|
|
303
|
+
// Active tenant context (multi-tenant module). activeOrganizationId is the
|
|
304
|
+
// Better Auth organization plugin's session field; activeWorkspaceId is
|
|
305
|
+
// AILK's thin session extension (session.additionalFields in the
|
|
306
|
+
// apps/workspace auth config). Null in single-tenant deployments.
|
|
307
|
+
activeOrganizationId String? @map("active_organization_id")
|
|
308
|
+
activeWorkspaceId String? @map("active_workspace_id")
|
|
309
|
+
|
|
310
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
311
|
+
|
|
312
|
+
@@index([userId])
|
|
313
|
+
@@index([token])
|
|
314
|
+
@@map("sessions")
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/// Account - OAuth provider connections (Google, GitHub, etc.)
|
|
318
|
+
///
|
|
319
|
+
/// Better Auth's account shape: one row per (providerId, accountId) pair.
|
|
320
|
+
/// Cascade on User removal keeps OAuth links from orphaning.
|
|
321
|
+
model Account {
|
|
322
|
+
id String @id @default(dbgenerated("('acct_'::text || (uuidv7())::text)")) @db.Text
|
|
323
|
+
accountId String @map("account_id")
|
|
324
|
+
providerId String @map("provider_id")
|
|
325
|
+
userId String @map("user_id")
|
|
326
|
+
accessToken String? @map("access_token") @db.Text
|
|
327
|
+
refreshToken String? @map("refresh_token") @db.Text
|
|
328
|
+
idToken String? @map("id_token") @db.Text
|
|
329
|
+
accessTokenExpiresAt DateTime? @map("access_token_expires_at")
|
|
330
|
+
refreshTokenExpiresAt DateTime? @map("refresh_token_expires_at")
|
|
331
|
+
scope String?
|
|
332
|
+
password String?
|
|
333
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
334
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
335
|
+
|
|
336
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
337
|
+
|
|
338
|
+
@@unique([providerId, accountId])
|
|
339
|
+
@@index([userId])
|
|
340
|
+
@@map("accounts")
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/// Verification - Email / magic-link verification tokens (Better Auth schema)
|
|
344
|
+
model Verification {
|
|
345
|
+
id String @id @default(dbgenerated("('verify_'::text || (uuidv7())::text)")) @db.Text
|
|
346
|
+
identifier String
|
|
347
|
+
value String
|
|
348
|
+
expiresAt DateTime @map("expires_at")
|
|
349
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
350
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
351
|
+
|
|
352
|
+
@@index([identifier])
|
|
353
|
+
@@map("verifications")
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/// ApiToken - Bearer tokens for non-web clients (mobile apps, API integrations)
|
|
357
|
+
model ApiToken {
|
|
358
|
+
id String @id @default(dbgenerated("('apitok_'::text || (uuidv7())::text)")) @db.Text
|
|
359
|
+
userId String @map("user_id")
|
|
360
|
+
|
|
361
|
+
// Token identification
|
|
362
|
+
name String // "iPhone", "Android App", "API Integration"
|
|
363
|
+
token String @unique // Hashed token
|
|
364
|
+
tokenPrefix String @map("token_prefix") // First 8 chars for identification
|
|
365
|
+
|
|
366
|
+
// Client info
|
|
367
|
+
clientType String @default("api") @map("client_type") // "mobile", "api", "cli"
|
|
368
|
+
deviceInfo String? @map("device_info") // "iPhone 15 Pro", "Android 14"
|
|
369
|
+
|
|
370
|
+
// Permissions
|
|
371
|
+
scopes String[] @default([]) // ["read:profile", "write:data"]
|
|
372
|
+
|
|
373
|
+
// Lifecycle
|
|
374
|
+
expiresAt DateTime? @map("expires_at")
|
|
375
|
+
lastUsedAt DateTime? @map("last_used_at")
|
|
376
|
+
lastUsedIp String? @map("last_used_ip")
|
|
377
|
+
revokedAt DateTime? @map("revoked_at")
|
|
378
|
+
|
|
379
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
380
|
+
|
|
381
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
382
|
+
refreshTokens RefreshToken[]
|
|
383
|
+
|
|
384
|
+
@@index([userId])
|
|
385
|
+
@@index([token])
|
|
386
|
+
@@index([tokenPrefix])
|
|
387
|
+
@@map("api_tokens")
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/// RefreshToken - Long-lived tokens for mobile session refresh
|
|
391
|
+
model RefreshToken {
|
|
392
|
+
id String @id @default(dbgenerated("('reftok_'::text || (uuidv7())::text)")) @db.Text
|
|
393
|
+
userId String @map("user_id")
|
|
394
|
+
apiTokenId String @map("api_token_id")
|
|
395
|
+
|
|
396
|
+
token String @unique // Hashed
|
|
397
|
+
|
|
398
|
+
// Lifecycle
|
|
399
|
+
expiresAt DateTime @map("expires_at")
|
|
400
|
+
usedAt DateTime? @map("used_at") // Last time used to get new access token
|
|
401
|
+
revokedAt DateTime? @map("revoked_at")
|
|
402
|
+
|
|
403
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
404
|
+
|
|
405
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
406
|
+
apiToken ApiToken @relation(fields: [apiTokenId], references: [id], onDelete: Cascade)
|
|
407
|
+
|
|
408
|
+
@@index([userId])
|
|
409
|
+
@@index([apiTokenId])
|
|
410
|
+
@@index([token])
|
|
411
|
+
@@map("refresh_tokens")
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/// OAuthClient - Registered OAuth applications (ChatGPT, Slack, etc.)
|
|
415
|
+
model OAuthClient {
|
|
416
|
+
id String @id @default(dbgenerated("('oauthc_'::text || (uuidv7())::text)")) @db.Text
|
|
417
|
+
|
|
418
|
+
// Client identification
|
|
419
|
+
name String // "ChatGPT Plugin", "Slack Bot"
|
|
420
|
+
description String?
|
|
421
|
+
logoUrl String? @map("logo_url")
|
|
422
|
+
|
|
423
|
+
// OAuth credentials
|
|
424
|
+
clientId String @unique @map("client_id") // Public identifier
|
|
425
|
+
clientSecret String @map("client_secret") // Hashed secret
|
|
426
|
+
|
|
427
|
+
// OAuth config
|
|
428
|
+
redirectUris String[] @map("redirect_uris") // Allowed callback URLs
|
|
429
|
+
scopes String[] @default([]) // Allowed scopes
|
|
430
|
+
|
|
431
|
+
// Settings
|
|
432
|
+
enabled Boolean @default(true)
|
|
433
|
+
trusted Boolean @default(false) // Skip consent screen
|
|
434
|
+
|
|
435
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
436
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
437
|
+
|
|
438
|
+
authorizations OAuthAuthorization[]
|
|
439
|
+
|
|
440
|
+
@@map("oauth_clients")
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/// OAuthAuthorization - User grants to OAuth clients
|
|
444
|
+
model OAuthAuthorization {
|
|
445
|
+
id String @id @default(dbgenerated("('oautha_'::text || (uuidv7())::text)")) @db.Text
|
|
446
|
+
userId String @map("user_id")
|
|
447
|
+
clientId String @map("client_id")
|
|
448
|
+
|
|
449
|
+
// Granted scopes (may be subset of client's allowed scopes)
|
|
450
|
+
scopes String[]
|
|
451
|
+
|
|
452
|
+
// Tokens
|
|
453
|
+
accessToken String @unique @map("access_token") // Hashed
|
|
454
|
+
refreshToken String? @unique @map("refresh_token") // Hashed
|
|
455
|
+
|
|
456
|
+
// Lifecycle
|
|
457
|
+
expiresAt DateTime @map("expires_at")
|
|
458
|
+
revokedAt DateTime? @map("revoked_at")
|
|
459
|
+
|
|
460
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
461
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
462
|
+
|
|
463
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
464
|
+
client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
|
465
|
+
|
|
466
|
+
@@unique([userId, clientId])
|
|
467
|
+
@@index([userId])
|
|
468
|
+
@@index([clientId])
|
|
469
|
+
@@index([accessToken])
|
|
470
|
+
@@map("oauth_authorizations")
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/// PushToken - Device tokens for push notifications
|
|
474
|
+
model PushToken {
|
|
475
|
+
id String @id @default(dbgenerated("('pushtok_'::text || (uuidv7())::text)")) @db.Text
|
|
476
|
+
userId String @map("user_id")
|
|
477
|
+
|
|
478
|
+
// Token details
|
|
479
|
+
token String @unique // FCM or APNs token
|
|
480
|
+
platform String // "ios", "android", "web"
|
|
481
|
+
|
|
482
|
+
// Device info
|
|
483
|
+
deviceId String? @map("device_id") // Unique device identifier
|
|
484
|
+
deviceName String? @map("device_name") // "iPhone 15 Pro"
|
|
485
|
+
appVersion String? @map("app_version") // "1.2.3"
|
|
486
|
+
|
|
487
|
+
// Status
|
|
488
|
+
enabled Boolean @default(true)
|
|
489
|
+
failedAt DateTime? @map("failed_at") // Last delivery failure
|
|
490
|
+
failCount Int @default(0) @map("fail_count")
|
|
491
|
+
|
|
492
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
493
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
494
|
+
|
|
495
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
496
|
+
|
|
497
|
+
@@index([userId])
|
|
498
|
+
@@index([platform])
|
|
499
|
+
@@map("push_tokens")
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/// UserData - Flexible key-value storage for customer extensions
|
|
503
|
+
/// Use this for: preferences, saved items, custom fields, feature flags
|
|
504
|
+
model UserData {
|
|
505
|
+
id String @id @default(dbgenerated("('userd_'::text || (uuidv7())::text)")) @db.Text
|
|
506
|
+
userId String @map("user_id")
|
|
507
|
+
|
|
508
|
+
// Key-value storage
|
|
509
|
+
key String // "preferences", "saved_products", "notification_settings"
|
|
510
|
+
value Json // Flexible JSON storage
|
|
511
|
+
|
|
512
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
513
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
514
|
+
|
|
515
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
516
|
+
|
|
517
|
+
@@unique([userId, key])
|
|
518
|
+
@@index([userId])
|
|
519
|
+
@@index([key])
|
|
520
|
+
@@map("user_data")
|
|
521
|
+
}
|