create-ailk 0.24.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -20
- package/component-catalog.json +3 -3
- package/component-catalog.md +3 -3
- package/dist/add-module.js +4 -2
- package/dist/add-route.d.ts +12 -1
- package/dist/add-route.js +31 -3
- package/dist/cli.js +12 -7
- package/dist/derive-architecture.d.ts +3 -4
- package/dist/derive-architecture.js +65 -29
- package/dist/lib/design-checks.d.ts +9 -4
- package/dist/lib/design-checks.js +13 -7
- package/dist/lib/extract-module-bundle.js +29 -2
- package/dist/lib/fetch-template-snapshot.d.ts +1 -1
- package/dist/lib/fetch-template-snapshot.js +7 -3
- package/dist/lib/import-graph.d.ts +1 -1
- package/dist/lib/import-graph.js +4 -4
- package/dist/lib/module-license-gate.d.ts +12 -1
- package/dist/lib/module-license-gate.js +34 -12
- package/dist/module-architecture.d.ts +20 -3
- package/dist/module-architecture.js +117 -550
- package/dist/paid-sections.d.ts +25 -1
- package/dist/paid-sections.js +88 -3
- package/dist/surfaces.js +10 -2
- package/dist/template-record.d.ts +14 -4
- package/dist/template-record.js +23 -5
- package/dist/topology.d.ts +16 -3
- package/dist/topology.js +31 -19
- package/dist/update.d.ts +10 -1
- package/dist/update.js +540 -16
- package/package.json +3 -3
- package/release-scope.json +1 -1
- package/templates/.claude/cloudparity-repo-hooks.json +5 -0
- package/templates/.claude/hooks/template-guard.sh +137 -0
- package/templates/.claude/rules/extending.md +106 -0
- package/templates/.claude/rules/loop-contract.md +2 -2
- package/templates/.claude/settings.json +11 -0
- package/templates/.env.example +5 -5
- package/templates/.github/workflows/ci.yml +7 -4
- package/templates/CLAUDE.md +11 -1
- package/templates/CONVENTIONS.md +8 -10
- package/templates/README.md +14 -13
- package/templates/apps/api/.env.example +2 -2
- package/templates/apps/api/CLAUDE.md +102 -76
- package/templates/apps/api/jest.config.cjs +15 -5
- package/templates/apps/api/package.json +16 -20
- package/templates/apps/api/src/__tests__/trusted-origins.server.test.ts +2 -2
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +4 -4
- package/templates/apps/api/src/index.ts +1 -1
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +3 -3
- package/templates/apps/api/src/modules/commerce.ts +10 -0
- package/templates/apps/api/src/modules/content-write.ts +10 -0
- package/templates/apps/api/src/modules/multi-tenant.ts +10 -0
- package/templates/apps/api/src/modules/scheduling.ts +10 -0
- package/templates/apps/api/src/modules/signal-collectors.ts +10 -0
- package/templates/apps/api/src/modules/workspace.ts +10 -0
- package/templates/apps/api/src/server.ts +117 -1882
- package/templates/apps/api/vercel.json +2 -2
- package/templates/apps/mcp/CLAUDE.md +67 -20
- package/templates/apps/mcp/__tests__/app-entry.test.ts +4 -254
- package/templates/apps/mcp/__tests__/boot-file.test.ts +92 -0
- package/templates/apps/mcp/jest.config.cjs +6 -1
- package/templates/apps/mcp/package.json +5 -13
- package/templates/apps/mcp/src/app.ts +8 -7
- package/templates/apps/mcp/src/index.ts +6 -34
- package/templates/apps/mcp/src/lib/paid-tools.generated.ts +10 -0
- package/templates/apps/mcp/src/lib/topology.generated.ts +2 -2
- package/templates/apps/mcp/src/site.ts +12 -0
- package/templates/apps/web/.env.example +1 -1
- package/templates/apps/web/CLAUDE.md +10 -3
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
- package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/magnet-page.test.tsx +22 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/magnet-page.tsx +7 -3
- package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +43 -0
- package/templates/apps/web/app/[locale]/pricing/page.tsx +7 -3
- package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +222 -0
- package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +10 -3
- package/templates/apps/web/app/api/revalidate/route.ts +3 -3
- package/templates/apps/web/auth.ts +2 -2
- package/templates/apps/web/jest.config.cjs +1 -0
- package/templates/apps/web/lib/auth-email.ts +1 -1
- package/templates/apps/web/lib/relay.ts +2 -2
- package/templates/apps/web/lib/release-scope.ts +47 -0
- package/templates/apps/web/lib/server-api.ts +1 -1
- package/templates/apps/web/src/lib/commerce-claim.ts +1 -1
- package/templates/customizations.yaml +37 -0
- package/templates/database/prisma.config.ts +10 -14
- package/templates/database/seed-test.ts +2 -2
- package/templates/database/seed.ts +5 -5
- package/templates/package.json +12 -6
- package/templates/pnpm-workspace.yaml +0 -1
- package/templates/project.yaml +16 -8
- package/templates/tools/jest/reporters.cjs +65 -0
- package/templates/tools/lint-architecture.ts +553 -7
- package/templates/tsconfig.json +1 -2
- package/versions.json +48 -35
- package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +0 -409
- package/templates/apps/api/src/__tests__/factories/agent-caller.ts +0 -102
- package/templates/apps/api/src/__tests__/factories/content-fixture.ts +0 -138
- package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +0 -441
- package/templates/apps/api/src/__tests__/factories/index.ts +0 -70
- package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +0 -82
- package/templates/apps/api/src/__tests__/leads-forwarded-rate-limit.test.ts +0 -135
- package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +0 -126
- package/templates/apps/api/src/__tests__/stripe-boot.test.ts +0 -132
- package/templates/apps/api/src/__tests__/support/hub-sign-in-fake-db.ts +0 -362
- package/templates/apps/api/src/bin/__tests__/rate-limit-probe.test.ts +0 -184
- package/templates/apps/api/src/bin/abandon-sweep.ts +0 -42
- package/templates/apps/api/src/bin/rate-limit-probe.ts +0 -53
- package/templates/apps/api/src/bin/spokes.ts +0 -198
- package/templates/apps/api/src/bin/stripe-connections-rekey.ts +0 -45
- package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +0 -196
- package/templates/apps/api/src/config/__tests__/index.test.ts +0 -233
- package/templates/apps/api/src/config/__tests__/modules.test.ts +0 -76
- package/templates/apps/api/src/config/__tests__/stripe-connection-key.test.ts +0 -185
- package/templates/apps/api/src/config/__tests__/trusted-origins.test.ts +0 -238
- package/templates/apps/api/src/config/index.ts +0 -596
- package/templates/apps/api/src/config/modules.ts +0 -83
- package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +0 -581
- package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +0 -143
- package/templates/apps/api/src/lib/__tests__/consent-ledger-double.ts +0 -237
- package/templates/apps/api/src/lib/__tests__/consent-store.test.ts +0 -353
- package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +0 -201
- package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +0 -224
- package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +0 -120
- package/templates/apps/api/src/lib/__tests__/errors.test.ts +0 -94
- package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +0 -144
- package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +0 -8
- package/templates/apps/api/src/lib/__tests__/flow-completion-store.test.ts +0 -149
- package/templates/apps/api/src/lib/__tests__/flow-rename-race.db.test.ts +0 -116
- package/templates/apps/api/src/lib/__tests__/hub-sign-in-store.test.ts +0 -209
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +0 -257
- package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +0 -96
- package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +0 -125
- package/templates/apps/api/src/lib/__tests__/prisma.test.ts +0 -165
- package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +0 -317
- package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +0 -129
- package/templates/apps/api/src/lib/__tests__/site.test.ts +0 -308
- package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +0 -89
- package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +0 -202
- package/templates/apps/api/src/lib/__tests__/stripe-admission.test.ts +0 -217
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -82
- package/templates/apps/api/src/lib/agent-store.ts +0 -613
- package/templates/apps/api/src/lib/auth-email-budget.ts +0 -161
- package/templates/apps/api/src/lib/consent-store.ts +0 -363
- package/templates/apps/api/src/lib/content-adapter.ts +0 -112
- package/templates/apps/api/src/lib/deliverable-asset-store.ts +0 -96
- package/templates/apps/api/src/lib/error-serializer.ts +0 -164
- package/templates/apps/api/src/lib/errors.ts +0 -95
- package/templates/apps/api/src/lib/file-fallback.ts +0 -87
- package/templates/apps/api/src/lib/flow-completion-store.ts +0 -136
- package/templates/apps/api/src/lib/hub-sign-in-store.ts +0 -455
- package/templates/apps/api/src/lib/lead-capture-store.ts +0 -122
- package/templates/apps/api/src/lib/lead-delivery.ts +0 -52
- package/templates/apps/api/src/lib/license-key-store.ts +0 -45
- package/templates/apps/api/src/lib/locales.ts +0 -201
- package/templates/apps/api/src/lib/outbound-http.ts +0 -127
- package/templates/apps/api/src/lib/prisma.ts +0 -21
- package/templates/apps/api/src/lib/proposal-paid-store.ts +0 -66
- package/templates/apps/api/src/lib/rate-limit-probe.ts +0 -165
- package/templates/apps/api/src/lib/rate-limit-store.ts +0 -142
- package/templates/apps/api/src/lib/require-commerce-claim.ts +0 -250
- package/templates/apps/api/src/lib/require-paid-tier.ts +0 -53
- package/templates/apps/api/src/lib/site.ts +0 -257
- package/templates/apps/api/src/lib/slice-load.ts +0 -90
- package/templates/apps/api/src/lib/spoke-store.ts +0 -180
- package/templates/apps/api/src/lib/stripe.ts +0 -321
- package/templates/apps/api/src/lib/webhook-idempotency.ts +0 -156
- package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +0 -111
- package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +0 -172
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +0 -119
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +0 -138
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-trusted-origins.test.ts +0 -142
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +0 -155
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +0 -139
- package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +0 -562
- package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +0 -76
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +0 -220
- package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +0 -97
- package/templates/apps/api/src/middleware/__tests__/auth.hub-session-path.test.ts +0 -557
- package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +0 -72
- package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +0 -140
- package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +0 -721
- package/templates/apps/api/src/middleware/__tests__/rate-limit-cross-isolate.db.test.ts +0 -220
- package/templates/apps/api/src/middleware/__tests__/rate-limit-store.test.ts +0 -430
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +0 -1409
- package/templates/apps/api/src/middleware/__tests__/write-budget.test.ts +0 -174
- package/templates/apps/api/src/middleware/auth.ts +0 -864
- package/templates/apps/api/src/middleware/default-tenant.ts +0 -166
- package/templates/apps/api/src/middleware/rate-limit.ts +0 -983
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +0 -391
- package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +0 -182
- package/templates/apps/api/src/openapi/index.ts +0 -18
- package/templates/apps/api/src/openapi/spec.ts +0 -2148
- package/templates/apps/api/src/openapi/surface-drift.ts +0 -195
- package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +0 -175
- package/templates/apps/api/src/routes/aeo/index.ts +0 -107
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +0 -196
- package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +0 -249
- package/templates/apps/api/src/routes/auth/__tests__/hub-sign-in.test.ts +0 -532
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +0 -313
- package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +0 -413
- package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +0 -609
- package/templates/apps/api/src/routes/auth/hub-sign-in.ts +0 -242
- package/templates/apps/api/src/routes/auth/tokens.ts +0 -211
- package/templates/apps/api/src/routes/auth/transactional-email.ts +0 -301
- package/templates/apps/api/src/routes/auth/user.ts +0 -305
- package/templates/apps/api/src/routes/billing/plan-checkout.ts +0 -332
- package/templates/apps/api/src/routes/checkout/__tests__/live-key.test.ts +0 -178
- package/templates/apps/api/src/routes/checkout/__tests__/offerings-authorization.test.ts +0 -1426
- package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +0 -448
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -1742
- package/templates/apps/api/src/routes/checkout/index.ts +0 -34
- package/templates/apps/api/src/routes/checkout/session.ts +0 -171
- package/templates/apps/api/src/routes/checkout/sessions.ts +0 -540
- package/templates/apps/api/src/routes/consent/__tests__/account.test.ts +0 -386
- package/templates/apps/api/src/routes/consent/__tests__/sign-up-rate-limit.test.ts +0 -160
- package/templates/apps/api/src/routes/consent/account.ts +0 -268
- package/templates/apps/api/src/routes/consent/cookie.ts +0 -90
- package/templates/apps/api/src/routes/consent/index.ts +0 -26
- package/templates/apps/api/src/routes/consent/unsubscribe.ts +0 -127
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +0 -853
- package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +0 -230
- package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +0 -44
- package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +0 -118
- package/templates/apps/api/src/routes/content/__tests__/offerings.test.ts +0 -731
- package/templates/apps/api/src/routes/content/__tests__/pricing.test.ts +0 -753
- package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +0 -51
- package/templates/apps/api/src/routes/content/__tests__/search.test.ts +0 -450
- package/templates/apps/api/src/routes/content/__tests__/shown-offerings.test.ts +0 -762
- package/templates/apps/api/src/routes/content/get-page.ts +0 -183
- package/templates/apps/api/src/routes/content/index.ts +0 -49
- package/templates/apps/api/src/routes/content/list-pages.ts +0 -74
- package/templates/apps/api/src/routes/content/list-types.ts +0 -19
- package/templates/apps/api/src/routes/content/offerings.ts +0 -184
- package/templates/apps/api/src/routes/content/pricing.ts +0 -176
- package/templates/apps/api/src/routes/content/rate-limit.ts +0 -22
- package/templates/apps/api/src/routes/content/search.ts +0 -100
- package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
- package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +0 -88
- package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +0 -171
- package/templates/apps/api/src/routes/leads/__tests__/magnet-completion.test.ts +0 -515
- package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +0 -392
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +0 -165
- package/templates/apps/api/src/routes/leads/index.ts +0 -639
- package/templates/apps/api/src/routes/leads/list.ts +0 -104
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +0 -626
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +0 -1268
- package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +0 -847
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +0 -491
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -476
- package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +0 -872
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +0 -1022
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +0 -484
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +0 -535
- package/templates/apps/api/src/routes/project-listings/index.ts +0 -164
- package/templates/apps/api/src/routes/project-listings/me.ts +0 -87
- package/templates/apps/api/src/routes/project-listings/patch-copy.ts +0 -224
- package/templates/apps/api/src/routes/project-listings/patch-draft.ts +0 -102
- package/templates/apps/api/src/routes/project-listings/public.ts +0 -98
- package/templates/apps/api/src/routes/project-listings/respond.ts +0 -48
- package/templates/apps/api/src/routes/project-listings/resume-token.ts +0 -27
- package/templates/apps/api/src/routes/project-listings/start.ts +0 -140
- package/templates/apps/api/src/routes/project-listings/submit.ts +0 -130
- package/templates/apps/api/src/routes/project-listings/verify-email.ts +0 -150
- package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +0 -686
- package/templates/apps/api/src/routes/requests/confirm.ts +0 -601
- package/templates/apps/api/src/routes/requests/index.ts +0 -54
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +0 -306
- package/templates/apps/api/src/routes/test/auth/session.ts +0 -143
- package/templates/apps/api/src/routes/webhooks/README.md +0 -398
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-checkout-consent.test.ts +0 -649
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +0 -749
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -449
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -264
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode-live.test.ts +0 -159
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-livemode.test.ts +0 -158
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-offerings.test.ts +0 -814
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -301
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-proposal-paid.test.ts +0 -369
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -215
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +0 -301
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-site-filter.test.ts +0 -809
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -1155
- package/templates/apps/api/src/routes/webhooks/index.ts +0 -141
- package/templates/apps/api/src/routes/webhooks/stripe-offerings.ts +0 -384
- package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -2028
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -645
- package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +0 -132
- package/templates/apps/api/src/services/__tests__/audit-log.test.ts +0 -1028
- package/templates/apps/api/src/services/__tests__/checkout-plan.test.ts +0 -313
- package/templates/apps/api/src/services/__tests__/consent-ledger.test.ts +0 -503
- package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +0 -65
- package/templates/apps/api/src/services/__tests__/consent.test.ts +0 -299
- package/templates/apps/api/src/services/__tests__/default-tenant.test.ts +0 -147
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +0 -877
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +0 -379
- package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +0 -368
- package/templates/apps/api/src/services/__tests__/entitlements.test.ts +0 -142
- package/templates/apps/api/src/services/__tests__/hub-sign-in.test.ts +0 -854
- package/templates/apps/api/src/services/__tests__/keyless-workspace-predicate.test.ts +0 -234
- package/templates/apps/api/src/services/__tests__/lead-accept-user.test.ts +0 -251
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +0 -2660
- package/templates/apps/api/src/services/__tests__/listing-config.test.ts +0 -166
- package/templates/apps/api/src/services/__tests__/magnet-completion.test.ts +0 -389
- package/templates/apps/api/src/services/__tests__/person.test.ts +0 -1204
- package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -450
- package/templates/apps/api/src/services/__tests__/project-listings.counts.test.ts +0 -202
- package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -151
- package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +0 -137
- package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +0 -531
- package/templates/apps/api/src/services/__tests__/revalidation.test.ts +0 -372
- package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +0 -348
- package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +0 -660
- package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +0 -941
- package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +0 -588
- package/templates/apps/api/src/services/__tests__/verified-email.test.ts +0 -78
- package/templates/apps/api/src/services/abandon-email.ts +0 -336
- package/templates/apps/api/src/services/aeo-score.ts +0 -325
- package/templates/apps/api/src/services/answer-distributions.ts +0 -138
- package/templates/apps/api/src/services/audit-log.ts +0 -961
- package/templates/apps/api/src/services/checkout-buyer.ts +0 -168
- package/templates/apps/api/src/services/consent.ts +0 -834
- package/templates/apps/api/src/services/default-tenant.ts +0 -416
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +0 -750
- package/templates/apps/api/src/services/dunning-policy.ts +0 -294
- package/templates/apps/api/src/services/enrichment-shim.ts +0 -53
- package/templates/apps/api/src/services/entitlements.ts +0 -338
- package/templates/apps/api/src/services/hub-sign-in.ts +0 -472
- package/templates/apps/api/src/services/lead-accept-user.ts +0 -126
- package/templates/apps/api/src/services/lead-promotion.ts +0 -160
- package/templates/apps/api/src/services/lead-routing.ts +0 -1372
- package/templates/apps/api/src/services/leads-inbox.ts +0 -312
- package/templates/apps/api/src/services/listing-config.ts +0 -178
- package/templates/apps/api/src/services/magnet-completion.ts +0 -242
- package/templates/apps/api/src/services/offerings/__tests__/catalog.test.ts +0 -348
- package/templates/apps/api/src/services/offerings/__tests__/checkout-session-record.test.ts +0 -268
- package/templates/apps/api/src/services/offerings/__tests__/connection.test.ts +0 -975
- package/templates/apps/api/src/services/offerings/__tests__/fixtures.ts +0 -416
- package/templates/apps/api/src/services/offerings/__tests__/org-products.test.ts +0 -400
- package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -685
- package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
- package/templates/apps/api/src/services/offerings/catalog.ts +0 -318
- package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -403
- package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
- package/templates/apps/api/src/services/offerings/connection.ts +0 -1083
- package/templates/apps/api/src/services/offerings/index.ts +0 -614
- package/templates/apps/api/src/services/offerings/source.ts +0 -140
- package/templates/apps/api/src/services/offerings/store.ts +0 -150
- package/templates/apps/api/src/services/owner-workspaces.ts +0 -132
- package/templates/apps/api/src/services/person.ts +0 -1211
- package/templates/apps/api/src/services/plan-offerings.ts +0 -125
- package/templates/apps/api/src/services/project-listing-resume-email.ts +0 -326
- package/templates/apps/api/src/services/project-listings.ts +0 -2085
- package/templates/apps/api/src/services/public-site-resolver.ts +0 -396
- package/templates/apps/api/src/services/request-confirm.ts +0 -698
- package/templates/apps/api/src/services/revalidation.ts +0 -235
- package/templates/apps/api/src/services/slack-notify.ts +0 -291
- package/templates/apps/api/src/services/usage-aggregation.ts +0 -516
- package/templates/apps/api/src/services/usage-credits.ts +0 -340
- package/templates/apps/api/src/services/verified-email.ts +0 -71
- package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +0 -52
- package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +0 -46
- package/templates/apps/mcp/__tests__/abuse/guard.test.ts +0 -198
- package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +0 -36
- package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +0 -54
- package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +0 -116
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +0 -299
- package/templates/apps/mcp/__tests__/boot.test.ts +0 -280
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +0 -359
- package/templates/apps/mcp/__tests__/config/modules.test.ts +0 -78
- package/templates/apps/mcp/__tests__/get_business_hours.test.ts +0 -82
- package/templates/apps/mcp/__tests__/get_faq.test.ts +0 -80
- package/templates/apps/mcp/__tests__/get_locations.test.ts +0 -65
- package/templates/apps/mcp/__tests__/get_offerings.test.ts +0 -557
- package/templates/apps/mcp/__tests__/get_pricing.test.ts +0 -524
- package/templates/apps/mcp/__tests__/get_site_info.test.ts +0 -81
- package/templates/apps/mcp/__tests__/http-transport.test.ts +0 -1232
- package/templates/apps/mcp/__tests__/index.test.ts +0 -195
- package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +0 -191
- package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +0 -531
- package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +0 -70
- package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -162
- package/templates/apps/mcp/__tests__/lib/content-root.test.ts +0 -93
- package/templates/apps/mcp/__tests__/lib/errors.test.ts +0 -75
- package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +0 -180
- package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
- package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -268
- package/templates/apps/mcp/__tests__/locale.test.ts +0 -120
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +0 -175
- package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +0 -101
- package/templates/apps/mcp/__tests__/rate-limit-write.test.ts +0 -189
- package/templates/apps/mcp/__tests__/read_content.test.ts +0 -511
- package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -160
- package/templates/apps/mcp/__tests__/search_content.test.ts +0 -271
- package/templates/apps/mcp/__tests__/server.test.ts +0 -388
- package/templates/apps/mcp/__tests__/start_purchase.test.ts +0 -448
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +0 -222
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -152
- package/templates/apps/mcp/__tests__/tools/create_project.test.ts +0 -243
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +0 -451
- package/templates/apps/mcp/src/abuse/daily-cap.ts +0 -47
- package/templates/apps/mcp/src/abuse/email-validator.ts +0 -25
- package/templates/apps/mcp/src/abuse/honeypot.ts +0 -21
- package/templates/apps/mcp/src/abuse/index.ts +0 -349
- package/templates/apps/mcp/src/abuse/user-agent-deny.ts +0 -58
- package/templates/apps/mcp/src/boot.ts +0 -167
- package/templates/apps/mcp/src/config/modules.ts +0 -43
- package/templates/apps/mcp/src/http-transport.ts +0 -564
- package/templates/apps/mcp/src/lib/audit-single-page.ts +0 -308
- package/templates/apps/mcp/src/lib/commerce-claim.ts +0 -263
- package/templates/apps/mcp/src/lib/content-adapter.ts +0 -116
- package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -140
- package/templates/apps/mcp/src/lib/errors.ts +0 -61
- package/templates/apps/mcp/src/lib/license-key-store.ts +0 -45
- package/templates/apps/mcp/src/lib/locales.ts +0 -171
- package/templates/apps/mcp/src/lib/prisma.ts +0 -39
- package/templates/apps/mcp/src/lib/public-workspace.ts +0 -133
- package/templates/apps/mcp/src/lib/resolve-locale.ts +0 -30
- package/templates/apps/mcp/src/lib/shown-offerings.ts +0 -105
- package/templates/apps/mcp/src/lib/site-config.ts +0 -53
- package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +0 -59
- package/templates/apps/mcp/src/request-context.ts +0 -52
- package/templates/apps/mcp/src/server.ts +0 -343
- package/templates/apps/mcp/src/serverless-app.ts +0 -88
- package/templates/apps/mcp/src/tools/audit.ts +0 -127
- package/templates/apps/mcp/src/tools/capture_lead.ts +0 -66
- package/templates/apps/mcp/src/tools/create_project.ts +0 -134
- package/templates/apps/mcp/src/tools/get_business_hours.ts +0 -68
- package/templates/apps/mcp/src/tools/get_faq.ts +0 -71
- package/templates/apps/mcp/src/tools/get_locations.ts +0 -88
- package/templates/apps/mcp/src/tools/get_offerings.ts +0 -96
- package/templates/apps/mcp/src/tools/get_pricing.ts +0 -94
- package/templates/apps/mcp/src/tools/get_site_info.ts +0 -86
- package/templates/apps/mcp/src/tools/index.ts +0 -138
- package/templates/apps/mcp/src/tools/list_pages.ts +0 -68
- package/templates/apps/mcp/src/tools/person_notes.ts +0 -25
- package/templates/apps/mcp/src/tools/proposals.ts +0 -27
- package/templates/apps/mcp/src/tools/purchase.ts +0 -205
- package/templates/apps/mcp/src/tools/read_content.ts +0 -81
- package/templates/apps/mcp/src/tools/request_callback.ts +0 -52
- package/templates/apps/mcp/src/tools/search_content.ts +0 -63
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -54
- package/templates/apps/mcp/src/workspace-server.ts +0 -224
- package/templates/database/CHANGELOG.md +0 -981
- package/templates/database/LICENSE +0 -202
- package/templates/database/NOTICE +0 -2
- package/templates/database/README.md +0 -243
- package/templates/database/__tests__/agents.db.test.ts +0 -320
- package/templates/database/__tests__/appointment.db.test.ts +0 -106
- package/templates/database/__tests__/artifact-content-store.db.test.ts +0 -316
- package/templates/database/__tests__/composite-fence.db.test.ts +0 -206
- package/templates/database/__tests__/consent-ledger.db.test.ts +0 -345
- package/templates/database/__tests__/consent-source-checkout-migration.test.ts +0 -79
- package/templates/database/__tests__/fence-fan-out.db.test.ts +0 -715
- package/templates/database/__tests__/fixtures/appointment-create-probe.ts +0 -79
- package/templates/database/__tests__/fixtures/person-backfill.json +0 -264
- package/templates/database/__tests__/fixtures/person-contact-backfill.json +0 -182
- package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +0 -100
- package/templates/database/__tests__/flow-completion-migration.test.ts +0 -115
- package/templates/database/__tests__/flow-completion.db.test.ts +0 -136
- package/templates/database/__tests__/flow-workspace-key.db.test.ts +0 -263
- package/templates/database/__tests__/flows-listing-diagnostic.test.ts +0 -392
- package/templates/database/__tests__/flows-presets.test.ts +0 -173
- package/templates/database/__tests__/in-page-magnets-migration.test.ts +0 -161
- package/templates/database/__tests__/lead-idempotency-key.db.test.ts +0 -92
- package/templates/database/__tests__/member-area.db.test.ts +0 -257
- package/templates/database/__tests__/member-contract-migration.test.ts +0 -85
- package/templates/database/__tests__/member-contract.db.test.ts +0 -413
- package/templates/database/__tests__/offerings-checkout-session.db.test.ts +0 -270
- package/templates/database/__tests__/offerings-migration.test.ts +0 -197
- package/templates/database/__tests__/offerings-shown-price-ids-migration.test.ts +0 -86
- package/templates/database/__tests__/offerings.db.test.ts +0 -303
- package/templates/database/__tests__/outbound-message-action.db.test.ts +0 -80
- package/templates/database/__tests__/person-contact.db.test.ts +0 -563
- package/templates/database/__tests__/person-notes.db.test.ts +0 -249
- package/templates/database/__tests__/person.db.test.ts +0 -586
- package/templates/database/__tests__/piece-kind-migration.test.ts +0 -67
- package/templates/database/__tests__/piece-kind.db.test.ts +0 -208
- package/templates/database/__tests__/prefixed-ids.db.test.ts +0 -222
- package/templates/database/__tests__/project-listing-consent-at.db.test.ts +0 -111
- package/templates/database/__tests__/seed.test.ts +0 -272
- package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
- package/templates/database/__tests__/tenancy.test.ts +0 -141
- package/templates/database/__tests__/trial-magnet-migration.test.ts +0 -186
- package/templates/database/__tests__/user-cascade.test.ts +0 -140
- package/templates/database/_gitignore +0 -8
- package/templates/database/auth/.gitkeep +0 -0
- package/templates/database/auth/schema.prisma +0 -641
- package/templates/database/config/.gitkeep +0 -0
- package/templates/database/config/schema.prisma +0 -441
- package/templates/database/content/.gitkeep +0 -0
- package/templates/database/content/schema.prisma +0 -339
- package/templates/database/eslint.config.mjs +0 -69
- package/templates/database/flows/listing-diagnostic.ts +0 -182
- package/templates/database/flows/presets.ts +0 -315
- package/templates/database/inbox/.gitkeep +0 -0
- package/templates/database/inbox/README.md +0 -3
- package/templates/database/inbox/__tests__/schema.test.ts +0 -44
- package/templates/database/inbox/schema.prisma +0 -1447
- package/templates/database/jest.config.cjs +0 -36
- package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +0 -328
- package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +0 -100
- package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +0 -28
- package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +0 -25
- package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +0 -42
- package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +0 -67
- package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +0 -21
- package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +0 -201
- package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +0 -67
- package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +0 -46
- package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +0 -25
- package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +0 -49
- package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +0 -197
- package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +0 -32
- package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +0 -22
- package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +0 -151
- package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +0 -223
- package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +0 -22
- package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +0 -32
- package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +0 -40
- package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +0 -4
- package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +0 -2
- package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +0 -2
- package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +0 -29
- package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +0 -6
- package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +0 -39
- package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +0 -24
- package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +0 -3
- package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +0 -33
- package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +0 -30
- package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +0 -47
- package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +0 -16
- package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +0 -47
- package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +0 -10
- package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +0 -26
- package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +0 -90
- package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +0 -174
- package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +0 -14
- package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +0 -25
- package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +0 -32
- package/templates/database/migrations/20260911180000_consent_grants/migration.sql +0 -71
- package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +0 -30
- package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +0 -49
- package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +0 -123
- package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +0 -15
- package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +0 -158
- package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +0 -40
- package/templates/database/migrations/20260918120000_add_appointment/migration.sql +0 -67
- package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +0 -70
- package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +0 -181
- package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +0 -172
- package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +0 -41
- package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +0 -185
- package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +0 -70
- package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +0 -57
- package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +0 -68
- package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +0 -1067
- package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +0 -210
- package/templates/database/migrations/20261003120000_spoke_registry/migration.sql +0 -80
- package/templates/database/migrations/20261003130000_scheduling_connection/migration.sql +0 -49
- package/templates/database/migrations/20261005120000_agents/migration.sql +0 -84
- package/templates/database/migrations/20261008120000_user_last_workspace/migration.sql +0 -35
- package/templates/database/migrations/20261008130000_lead_idempotency_key/migration.sql +0 -20
- package/templates/database/migrations/20261009120000_agent_grants/migration.sql +0 -33
- package/templates/database/migrations/20261010120000_person/migration.sql +0 -106
- package/templates/database/migrations/20261010121000_person_backfill/migration.sql +0 -132
- package/templates/database/migrations/20261010130000_agent_grants_people_read/migration.sql +0 -20
- package/templates/database/migrations/20261011120000_member_area/migration.sql +0 -158
- package/templates/database/migrations/20261011130000_agent_grants_member_pieces_manage/migration.sql +0 -21
- package/templates/database/migrations/20261012120000_member_contract/migration.sql +0 -192
- package/templates/database/migrations/20261013120000_lead_spoke_checkout/migration.sql +0 -20
- package/templates/database/migrations/20261014120000_consent_ledger/migration.sql +0 -122
- package/templates/database/migrations/20261014120000_person_contact/migration.sql +0 -231
- package/templates/database/migrations/20261015120000_person_notes/migration.sql +0 -77
- package/templates/database/migrations/20261015120000_rate_limit_counters/migration.sql +0 -43
- package/templates/database/migrations/20261016120000_piece_kind/migration.sql +0 -95
- package/templates/database/migrations/20261017120000_outbound_message_action/migration.sql +0 -30
- package/templates/database/migrations/20261018120000_flow_completion/migration.sql +0 -52
- package/templates/database/migrations/20261019120000_consent_source_checkout/migration.sql +0 -27
- package/templates/database/migrations/20261020120000_offerings_data_model/migration.sql +0 -146
- package/templates/database/migrations/20261021120000_offerings_checkout_session/migration.sql +0 -77
- package/templates/database/migrations/20261022120000_in_page_magnets/migration.sql +0 -45
- package/templates/database/migrations/20261023120000_offerings_shown_price_ids/migration.sql +0 -47
- package/templates/database/migrations/20261024120000_organization_plan_checkout_session/migration.sql +0 -16
- package/templates/database/migrations/20261025120000_trial_magnet/migration.sql +0 -28
- package/templates/database/migrations/20261026120000_trial_magnet_proof_line/migration.sql +0 -23
- package/templates/database/migrations/migration_lock.toml +0 -3
- package/templates/database/ops/.gitkeep +0 -0
- package/templates/database/ops/schema.prisma +0 -43
- package/templates/database/package.json +0 -89
- package/templates/database/schema.prisma +0 -71
- package/templates/database/scripts/db-generate-locked.sh +0 -80
- package/templates/database/scripts/person-backfill.sql +0 -132
- package/templates/database/tenancy.ts +0 -183
- package/templates/database/tsconfig.build.json +0 -16
- package/templates/database/tsconfig.flows.json +0 -15
- package/templates/database/tsconfig.json +0 -16
- package/templates/database/tsconfig.tenancy.json +0 -14
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
// content namespace — chat + artifact substrate (AgentSession, ConversationEvent,
|
|
2
|
-
// SessionReadReceipt, Artifact, ArtifactVersion, Asset)
|
|
3
|
-
//
|
|
4
|
-
// Backs the event-sourced conversation transport + artifact persistence in
|
|
5
|
-
// docs/research/ploy-capture/BACKEND-REQUIREMENTS.md (§1 transport R-T1..R-T7,
|
|
6
|
-
// §2 event envelope, §3 endpoints). Workspaces own all domain content, so every
|
|
7
|
-
// table here carries a non-null `workspaceId` tenant scope.
|
|
8
|
-
//
|
|
9
|
-
// Per ADR 0009 invariant 1: workspaceId / userId are plain String stable IDs —
|
|
10
|
-
// NO @relation into the auth namespace (Workspace/User live in database/auth/).
|
|
11
|
-
// Relations WITHIN this namespace (event → session, version → artifact) are
|
|
12
|
-
// real FKs. Cross-namespace assembly (e.g. tenant guard resolving a session's
|
|
13
|
-
// workspace) routes through apps/api/src/services/ (invariant 4).
|
|
14
|
-
//
|
|
15
|
-
// Generator + datasource blocks live in database/schema.prisma (the root schema
|
|
16
|
-
// file). This file holds only model definitions for the content namespace.
|
|
17
|
-
|
|
18
|
-
/// AgentSession — one agent conversation ("session"/captured "ploy") within a
|
|
19
|
-
/// workspace. lastSeq is the append watermark for the event log (R-T1).
|
|
20
|
-
model AgentSession {
|
|
21
|
-
id String @id @default(dbgenerated("('agsess_'::text || (uuidv7())::text)")) @db.Text
|
|
22
|
-
workspaceId String @map("workspace_id")
|
|
23
|
-
title String?
|
|
24
|
-
status String @default("idle")
|
|
25
|
-
lastSeq Int @default(0) @map("last_seq")
|
|
26
|
-
lastMessageAt DateTime? @map("last_message_at")
|
|
27
|
-
draftMessage String? @map("draft_message")
|
|
28
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
29
|
-
updatedAt DateTime @updatedAt @map("updated_at")
|
|
30
|
-
|
|
31
|
-
events ConversationEvent[]
|
|
32
|
-
artifacts Artifact[]
|
|
33
|
-
readReceipts SessionReadReceipt[]
|
|
34
|
-
|
|
35
|
-
@@index([workspaceId, lastMessageAt(sort: Desc)])
|
|
36
|
-
@@map("agent_sessions")
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/// ConversationEvent — append-only, seq-ordered event log entry (R-T1/R-T4).
|
|
40
|
-
/// Envelope: { agentId, seq, type, turnId, payload, createdAt } (§2).
|
|
41
|
-
/// workspaceId is denormalized so the scope layer filters events without a
|
|
42
|
-
/// join through agent_sessions.
|
|
43
|
-
model ConversationEvent {
|
|
44
|
-
id String @id @default(dbgenerated("('convev_'::text || (uuidv7())::text)")) @db.Text
|
|
45
|
-
sessionId String @map("session_id")
|
|
46
|
-
workspaceId String @map("workspace_id")
|
|
47
|
-
agentId String @map("agent_id")
|
|
48
|
-
seq Int
|
|
49
|
-
type String
|
|
50
|
-
turnId String? @map("turn_id")
|
|
51
|
-
payload Json
|
|
52
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
53
|
-
|
|
54
|
-
session AgentSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
|
55
|
-
|
|
56
|
-
@@unique([sessionId, seq])
|
|
57
|
-
@@index([workspaceId])
|
|
58
|
-
@@map("conversation_events")
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/// SessionReadReceipt — per-user read position for a session (R-T7 mark-read;
|
|
62
|
-
/// drives unread badges). userId is a stable auth-namespace ID — no FK.
|
|
63
|
-
model SessionReadReceipt {
|
|
64
|
-
id String @id @default(dbgenerated("('receipt_'::text || (uuidv7())::text)")) @db.Text
|
|
65
|
-
sessionId String @map("session_id")
|
|
66
|
-
workspaceId String @map("workspace_id")
|
|
67
|
-
userId String @map("user_id")
|
|
68
|
-
lastReadSeq Int @default(0) @map("last_read_seq")
|
|
69
|
-
updatedAt DateTime @updatedAt @map("updated_at")
|
|
70
|
-
|
|
71
|
-
session AgentSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
|
72
|
-
|
|
73
|
-
@@unique([sessionId, userId])
|
|
74
|
-
@@index([workspaceId])
|
|
75
|
-
@@map("session_read_receipts")
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/// Artifact — a piece of the WORKSPACE's versioned content (#3846, generalized
|
|
79
|
-
/// by #5800 / roadmap D1). Originally "a session's produced output"; a session
|
|
80
|
-
/// is now PROVENANCE, not ownership — `sessionId` is optional and `SetNull`, so
|
|
81
|
-
/// deleting the conversation that produced a page leaves the page standing.
|
|
82
|
-
///
|
|
83
|
-
/// `contentType` is the discriminator the content store reads: `text/page` is
|
|
84
|
-
/// what the editor writes, `text/document` the legacy chat artifact. A page's
|
|
85
|
-
/// public identity is `(workspaceId, contentType, locale, slug)`; `slug` stays
|
|
86
|
-
/// NULL until publish, and NULLs never collide in a Postgres unique index, so a
|
|
87
|
-
/// workspace may hold any number of unpublished drafts.
|
|
88
|
-
///
|
|
89
|
-
/// `publishedVersionId` is a plain pointer at the ArtifactVersion the public
|
|
90
|
-
/// read serves — deliberately NOT a relation (a FK back into `versions` would
|
|
91
|
-
/// make the delete order of an artifact's own history circular), and
|
|
92
|
-
/// deliberately NOT `ArtifactVersion.isCurrent`, which is the DRAFT TIP and is
|
|
93
|
-
/// never the publish mechanism. Saving a draft moves `isCurrent`; only publish
|
|
94
|
-
/// moves this pointer.
|
|
95
|
-
///
|
|
96
|
-
/// `type` is the LEGACY discriminator. It predates `contentType` and is still
|
|
97
|
-
/// read by apps/api/src/routes/workspaces/sessions.ts (the session-artifacts
|
|
98
|
-
/// route, a hard-floor surface), so #5800 added `contentType` beside it and
|
|
99
|
-
/// backfilled it from `type` rather than renaming the column out from under a
|
|
100
|
-
/// live consumer. New code reads `contentType`; retiring `type` belongs to the
|
|
101
|
-
/// card that moves that route.
|
|
102
|
-
model Artifact {
|
|
103
|
-
id String @id @default(dbgenerated("('artif_'::text || (uuidv7())::text)")) @db.Text
|
|
104
|
-
sessionId String? @map("session_id")
|
|
105
|
-
workspaceId String @map("workspace_id")
|
|
106
|
-
type String @default("text/document")
|
|
107
|
-
contentType String @default("text/document") @map("content_type")
|
|
108
|
-
locale String @default("en")
|
|
109
|
-
slug String?
|
|
110
|
-
title String
|
|
111
|
-
publishedVersionId String? @map("published_version_id")
|
|
112
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
113
|
-
updatedAt DateTime @updatedAt @map("updated_at")
|
|
114
|
-
|
|
115
|
-
session AgentSession? @relation(fields: [sessionId], references: [id], onDelete: SetNull)
|
|
116
|
-
versions ArtifactVersion[]
|
|
117
|
-
|
|
118
|
-
@@unique([workspaceId, contentType, locale, slug])
|
|
119
|
-
@@index([sessionId])
|
|
120
|
-
@@index([workspaceId])
|
|
121
|
-
@@index([workspaceId, contentType, updatedAt])
|
|
122
|
-
@@map("artifacts")
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/// ArtifactVersion — auto-saved version history; exactly one isCurrent per
|
|
126
|
-
/// artifact (enforced at the service layer on save/restore).
|
|
127
|
-
model ArtifactVersion {
|
|
128
|
-
id String @id @default(dbgenerated("('artiv_'::text || (uuidv7())::text)")) @db.Text
|
|
129
|
-
artifactId String @map("artifact_id")
|
|
130
|
-
workspaceId String @map("workspace_id")
|
|
131
|
-
content Json
|
|
132
|
-
isCurrent Boolean @default(true) @map("is_current")
|
|
133
|
-
savedAt DateTime @default(now()) @map("saved_at")
|
|
134
|
-
|
|
135
|
-
artifact Artifact @relation(fields: [artifactId], references: [id], onDelete: Cascade)
|
|
136
|
-
|
|
137
|
-
@@index([artifactId, savedAt(sort: Desc)])
|
|
138
|
-
@@index([workspaceId])
|
|
139
|
-
@@map("artifact_versions")
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/// Asset — a workspace's uploaded binary (#5800 / roadmap D7), following the
|
|
143
|
-
/// `DeliverableAsset` precedent in the inbox namespace: the bytes live in the
|
|
144
|
-
/// row, not in object storage. That precedent was deliberate — no new
|
|
145
|
-
/// infrastructure — and only the resolver changes if blob storage arrives later.
|
|
146
|
-
///
|
|
147
|
-
/// `workspaceId` is a plain String stable id with no @relation (ADR 0009
|
|
148
|
-
/// invariant 1), and `(workspaceId, key)` is the addressable identity. Ids are
|
|
149
|
-
/// UUIDv7 (ADR 0031), so a re-upload is a NEW id and a served asset can be
|
|
150
|
-
/// cached immutably. The upload route itself is #5802's scope, not this model's.
|
|
151
|
-
///
|
|
152
|
-
/// Since #6310: this is also the store a magnet's `deliverables.assets[].assetKey`
|
|
153
|
-
/// resolves against FIRST (by `(workspaceId, key)`), ahead of the legacy
|
|
154
|
-
/// `DeliverableAsset` fallback (database/inbox/schema.prisma) — read through
|
|
155
|
-
/// the scoped boundary in apps/api/src/lib/deliverable-asset-store.ts, never
|
|
156
|
-
/// a raw query.
|
|
157
|
-
model Asset {
|
|
158
|
-
id String @id @default(dbgenerated("('asset_'::text || (uuidv7())::text)")) @db.Text
|
|
159
|
-
workspaceId String @map("workspace_id")
|
|
160
|
-
/// The caller-chosen name an artifact's content references the asset by.
|
|
161
|
-
key String
|
|
162
|
-
/// Download filename (Content-Disposition). Stored RAW; sanitize at SERVE
|
|
163
|
-
/// time, exactly as the DeliverableAsset download route does.
|
|
164
|
-
filename String
|
|
165
|
-
contentType String @map("content_type")
|
|
166
|
-
bytes Bytes
|
|
167
|
-
size Int
|
|
168
|
-
/// Owner-authored display name, shown above the filename in the lightbox
|
|
169
|
-
/// (#6092, S4/D10). NULL means the owner has not written one — distinct from
|
|
170
|
-
/// an empty string, which means they cleared it. Never backfilled from
|
|
171
|
-
/// `filename`: the two are different facts (demo.html:782 renders both).
|
|
172
|
-
title String?
|
|
173
|
-
/// Owner-authored longer description. Same NULL-vs-empty contract as `title`.
|
|
174
|
-
description String?
|
|
175
|
-
/// Owner-controlled tag SLUGS (`ad-creative`, `workspace-memory`, …), never
|
|
176
|
-
/// the human labels — the label is presentation, resolved by the surface from
|
|
177
|
-
/// its own vocabulary (demo.html:358 `ATAGS`, :794 the Docs set). Free-form
|
|
178
|
-
/// by design: the asset vocabulary and the document vocabulary (D8/D9) ride
|
|
179
|
-
/// this one column, and the "fixed set" of D10 is a UI affordance, not a
|
|
180
|
-
/// database constraint (#6092, D2 of the spec).
|
|
181
|
-
tags String[] @default([])
|
|
182
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
183
|
-
|
|
184
|
-
@@unique([workspaceId, key])
|
|
185
|
-
@@index([workspaceId])
|
|
186
|
-
@@map("assets")
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// ============================================================================
|
|
190
|
-
// Usage-billing metering (FEAT-047 P1.S1, #3709 — Epic #3704)
|
|
191
|
-
//
|
|
192
|
-
// The metering event + its org-level aggregates. Per ADR 0009 D2 (roadmap §4),
|
|
193
|
-
// the metering event + UsagePeriod + UsageBillingReport live in `content`;
|
|
194
|
-
// balances/plans (S2) live in auth/config. organizationId/workspaceId/userId
|
|
195
|
-
// are plain String stable-ids — no @relation into auth (ADR 0009 invariant 1).
|
|
196
|
-
// Field roster ported from docs/research/wt-billing-capture/schema.md, modeled
|
|
197
|
-
// on WT's TraceLog billing columns (spec D1), with workspaceId/userId added to
|
|
198
|
-
// the event grain (spec D2). Cross-namespace assembly (e.g. resolving an
|
|
199
|
-
// event's owning Workspace) routes through apps/api/src/services/.
|
|
200
|
-
// ============================================================================
|
|
201
|
-
|
|
202
|
-
/// ModelTier — the pricing tier at event time. BASE is unlimited/free-ish;
|
|
203
|
-
/// PREMIUM/FRONTIER consume credits. Defined here (S1, the dependency root)
|
|
204
|
-
/// per spec OQ-1 — S2's LlmModel references the same enum through the merged
|
|
205
|
-
/// prismaSchemaFolder (one logical schema; an enum reference needs no
|
|
206
|
-
/// @relation, so this is not a cross-namespace FK).
|
|
207
|
-
enum ModelTier {
|
|
208
|
-
BASE
|
|
209
|
-
PREMIUM
|
|
210
|
-
FRONTIER
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/// UsageBillingStatus — UsageBillingReport lifecycle: PENDING → REPORTED →
|
|
214
|
-
/// INVOICED → PAID, or FAILED.
|
|
215
|
-
enum UsageBillingStatus {
|
|
216
|
-
PENDING
|
|
217
|
-
REPORTED
|
|
218
|
-
INVOICED
|
|
219
|
-
PAID
|
|
220
|
-
FAILED
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/// UsageEvent — one row per billable AI call (the metering event; modeled on
|
|
224
|
-
/// WT's TraceLog billing columns, spec D1). org+workspace+user grain (spec
|
|
225
|
-
/// D2); all three scope ids are plain String stable-ids — no cross-namespace
|
|
226
|
-
/// @relation (ADR 0009 invariant 1, spec D3). The three attribution portion
|
|
227
|
-
/// columns are the load-bearing billing split; only onDemandPortionCents is
|
|
228
|
-
/// ever reported to Stripe (P4, spec D4). completionStatus 'success' rows
|
|
229
|
-
/// drive billing — aggregation (P2) filters on it.
|
|
230
|
-
model UsageEvent {
|
|
231
|
-
id String @id @default(dbgenerated("('usagev_'::text || (uuidv7())::text)")) @db.Text
|
|
232
|
-
organizationId String @map("organization_id")
|
|
233
|
-
workspaceId String @map("workspace_id")
|
|
234
|
-
userId String @map("user_id")
|
|
235
|
-
|
|
236
|
-
provider String
|
|
237
|
-
model String
|
|
238
|
-
|
|
239
|
-
// Cache-aware token breakdown.
|
|
240
|
-
inputTokensCacheWrite Int @map("input_tokens_cache_write")
|
|
241
|
-
inputTokensNoCacheWrite Int @map("input_tokens_no_cache_write")
|
|
242
|
-
cacheReadTokens Int @map("cache_read_tokens")
|
|
243
|
-
outputTokens Int @map("output_tokens")
|
|
244
|
-
thinkingTokens Int @map("thinking_tokens")
|
|
245
|
-
totalTokens Int @map("total_tokens")
|
|
246
|
-
|
|
247
|
-
providerCostUsd Decimal @map("provider_cost_usd") @db.Decimal(10, 6)
|
|
248
|
-
billedCostUsd Decimal @map("billed_cost_usd") @db.Decimal(10, 6)
|
|
249
|
-
markupPercent Decimal @map("markup_percent") @db.Decimal(5, 2)
|
|
250
|
-
|
|
251
|
-
modelTier ModelTier @default(BASE) @map("model_tier")
|
|
252
|
-
wasAutoModel Boolean @map("was_auto_model")
|
|
253
|
-
|
|
254
|
-
// Attribution split — billedCostUsd apportioned across the three buckets;
|
|
255
|
-
// only onDemandPortionCents is ever Stripe-metered (P4, spec D4).
|
|
256
|
-
includedPortionCents Int @default(0) @map("included_portion_cents")
|
|
257
|
-
creditBalancePortionCents Int @default(0) @map("credit_balance_portion_cents")
|
|
258
|
-
onDemandPortionCents Int @default(0) @map("on_demand_portion_cents")
|
|
259
|
-
|
|
260
|
-
completionStatus String @map("completion_status")
|
|
261
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
262
|
-
|
|
263
|
-
@@index([organizationId, createdAt])
|
|
264
|
-
@@index([workspaceId, createdAt])
|
|
265
|
-
@@index([userId, createdAt])
|
|
266
|
-
@@index([provider, model])
|
|
267
|
-
@@index([modelTier, wasAutoModel])
|
|
268
|
-
@@map("usage_events")
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/// UsagePeriod — one row per (organizationId, periodStart); the org-scoped
|
|
272
|
-
/// spend/tier rollup the P2 write path upserts as UsageEvent rows land.
|
|
273
|
-
/// Carries the event-grain roll-up support for the Org → Workspace → User
|
|
274
|
-
/// aggregation (spec D2) — whether this model itself gains per-workspace
|
|
275
|
-
/// sub-rows is a P2 decision, not a P1 schema requirement (spec OQ-2).
|
|
276
|
-
model UsagePeriod {
|
|
277
|
-
id String @id @default(dbgenerated("('usagper_'::text || (uuidv7())::text)")) @db.Text
|
|
278
|
-
organizationId String @map("organization_id")
|
|
279
|
-
|
|
280
|
-
periodStart DateTime @map("period_start")
|
|
281
|
-
periodEnd DateTime @map("period_end")
|
|
282
|
-
|
|
283
|
-
tokensConsumed BigInt @default(0) @map("tokens_consumed")
|
|
284
|
-
baseTokensConsumed BigInt @default(0) @map("base_tokens_consumed")
|
|
285
|
-
premiumTokensConsumed BigInt @default(0) @map("premium_tokens_consumed")
|
|
286
|
-
frontierTokensConsumed BigInt @default(0) @map("frontier_tokens_consumed")
|
|
287
|
-
|
|
288
|
-
usageSpendCents Int @default(0) @map("usage_spend_cents")
|
|
289
|
-
|
|
290
|
-
@@unique([organizationId, periodStart])
|
|
291
|
-
@@index([baseTokensConsumed, premiumTokensConsumed, frontierTokensConsumed], map: "usage_periods_tier_tracking_idx")
|
|
292
|
-
@@map("usage_periods")
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/// UsageBillingReport — one per (organizationId, periodStart, periodEnd); the
|
|
296
|
-
/// Stripe-reporting unit rolled up from UsageEvent by P2 aggregation. Only
|
|
297
|
-
/// onDemandCents is ever reported to Stripe (P4, spec D4) — includedCents/
|
|
298
|
-
/// creditBalanceCents are informational attribution, never metered.
|
|
299
|
-
model UsageBillingReport {
|
|
300
|
-
id String @id @default(dbgenerated("('usagrept_'::text || (uuidv7())::text)")) @db.Text
|
|
301
|
-
organizationId String @map("organization_id")
|
|
302
|
-
|
|
303
|
-
periodStart DateTime @map("period_start")
|
|
304
|
-
periodEnd DateTime @map("period_end")
|
|
305
|
-
|
|
306
|
-
// AGGREGATE precision (#3738 H2) — these hold a MONTH of events, not one
|
|
307
|
-
// event, so they must NOT reuse UsageEvent's per-event widths. At the
|
|
308
|
-
// original Decimal(10,6)/Int, an org whose month crossed $9,999.999999 (or
|
|
309
|
-
// 2.15B tokens) overflowed the column, the upsert threw, and the report was
|
|
310
|
-
// never written on ANY subsequent run — silently stalling revenue for the
|
|
311
|
-
// largest customers, worsening monotonically. Decimal(20,6) ≈ $1e14 and int8
|
|
312
|
-
// give headroom far above the service's own MAX_TOTAL_USD / token caps, so
|
|
313
|
-
// the service's loud `aggregate_overflow` assertion is always the gate and a
|
|
314
|
-
// silent DB overflow is unreachable. See usage-aggregation.ts § Bounds.
|
|
315
|
-
totalProviderCost Decimal @map("total_provider_cost") @db.Decimal(20, 6)
|
|
316
|
-
totalMarkupAmount Decimal @map("total_markup_amount") @db.Decimal(20, 6)
|
|
317
|
-
totalBilledAmount Decimal @map("total_billed_amount") @db.Decimal(20, 6)
|
|
318
|
-
|
|
319
|
-
totalTokens BigInt @map("total_tokens")
|
|
320
|
-
eventCount Int @map("event_count")
|
|
321
|
-
|
|
322
|
-
// Attribution split — only onDemandCents is ever Stripe-metered (P4, spec D4).
|
|
323
|
-
includedCents Int @default(0) @map("included_cents")
|
|
324
|
-
creditBalanceCents Int @default(0) @map("credit_balance_cents")
|
|
325
|
-
onDemandCents Int @default(0) @map("on_demand_cents")
|
|
326
|
-
|
|
327
|
-
stripeUsageRecordId String? @map("stripe_usage_record_id")
|
|
328
|
-
reportedToStripeAt DateTime? @map("reported_to_stripe_at")
|
|
329
|
-
stripeInvoiceId String? @map("stripe_invoice_id")
|
|
330
|
-
|
|
331
|
-
status UsageBillingStatus @default(PENDING)
|
|
332
|
-
errorMessage String? @map("error_message")
|
|
333
|
-
|
|
334
|
-
@@unique([organizationId, periodStart, periodEnd], map: "usage_billing_reports_period_key")
|
|
335
|
-
@@index([organizationId, status])
|
|
336
|
-
@@index([status])
|
|
337
|
-
@@index([periodStart])
|
|
338
|
-
@@map("usage_billing_reports")
|
|
339
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// Self-contained ESLint flat config for this scaffolded package.
|
|
2
|
-
//
|
|
3
|
-
// It deliberately does NOT depend on @working-theory/eslint-config — that
|
|
4
|
-
// package is internal to the AI Launch Kit monorepo and is not published, so
|
|
5
|
-
// it cannot be a dependency of a scaffolded starter. Everything below comes
|
|
6
|
-
// from public npm packages already pinned as devDependencies (see
|
|
7
|
-
// package.json): @eslint/js, globals and typescript-eslint.
|
|
8
|
-
//
|
|
9
|
-
// Source file name (#5556): this file is checked in as `_eslint.config.mjs`,
|
|
10
|
-
// not `eslint.config.mjs` — build-templates.mjs renames it at snapshot time
|
|
11
|
-
// (renameScaffoldLintConfigs()). A file literally named `eslint.config.mjs`
|
|
12
|
-
// anywhere under this monorepo (even one this repo's own root eslint.config.ts
|
|
13
|
-
// lists in its `ignores`) is auto-discovered by ESLint's flat-config nested
|
|
14
|
-
// resolution as a competing config root, which breaks the monorepo's own
|
|
15
|
-
// lint runs (verified live: typescript-eslint's "multiple candidate
|
|
16
|
-
// TSConfigRootDirs" parser error across unrelated packages/create-ailk
|
|
17
|
-
// files). The underscore prefix keeps it invisible to that discovery while
|
|
18
|
-
// it lives in this checkout; only the snapshot in templates/ — which ships
|
|
19
|
-
// to the customer, not this repo — gets the real filename.
|
|
20
|
-
import js from "@eslint/js";
|
|
21
|
-
import globals from "globals";
|
|
22
|
-
import tseslint from "typescript-eslint";
|
|
23
|
-
|
|
24
|
-
export default tseslint.config(
|
|
25
|
-
{
|
|
26
|
-
ignores: [
|
|
27
|
-
"**/.next/**",
|
|
28
|
-
"**/dist/**",
|
|
29
|
-
"**/generated/**",
|
|
30
|
-
"**/node_modules/**",
|
|
31
|
-
],
|
|
32
|
-
},
|
|
33
|
-
js.configs.recommended,
|
|
34
|
-
...tseslint.configs.recommended,
|
|
35
|
-
{
|
|
36
|
-
languageOptions: {
|
|
37
|
-
globals: {
|
|
38
|
-
...globals.node,
|
|
39
|
-
...globals.browser,
|
|
40
|
-
...globals.jest,
|
|
41
|
-
},
|
|
42
|
-
// Explicit, self-contained root — this scaffold config is never meant
|
|
43
|
-
// to combine with any sibling scaffold package's config (each ships
|
|
44
|
-
// standalone), and leaving it unset makes typescript-eslint's
|
|
45
|
-
// candidate-root disambiguation ambiguous the moment more than one
|
|
46
|
-
// scaffold package's config resolves in the same ESLint process (e.g.
|
|
47
|
-
// this monorepo's own `templates/` build, where all four exist
|
|
48
|
-
// side by side; a real customer scaffold never has that problem,
|
|
49
|
-
// since it only ever ships and lints ONE of these four at a time).
|
|
50
|
-
parserOptions: {
|
|
51
|
-
tsconfigRootDir: import.meta.dirname,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
rules: {
|
|
55
|
-
// Downgraded rather than off, so both stay visible without failing a
|
|
56
|
-
// fresh scaffold's lint:
|
|
57
|
-
// - unused-vars: most of the source follows the underscore-prefix
|
|
58
|
-
// convention for intentionally-unused bindings, which this rule's
|
|
59
|
-
// default options don't recognize; a handful of test fixtures also
|
|
60
|
-
// carry genuinely-unused locals this minimal config doesn't try to
|
|
61
|
-
// triage file-by-file.
|
|
62
|
-
// - require-imports: CommonJS require() is the correct form in Jest
|
|
63
|
-
// config/mock files and in a few test-only dynamic re-require
|
|
64
|
-
// patterns.
|
|
65
|
-
"@typescript-eslint/no-unused-vars": "warn",
|
|
66
|
-
"@typescript-eslint/no-require-imports": "warn",
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
);
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file listing-diagnostic.ts
|
|
3
|
-
* @description The ONE scoring RULE every project-listing diagnostic shares
|
|
4
|
-
* (#5001, reworked by #5036 D4) — the template's Q3–Q6 resolved by option
|
|
5
|
-
* VALUE, never by option position.
|
|
6
|
-
*
|
|
7
|
-
* The mechanism (#5036 D4, "scoring by value, not position"): the generated
|
|
8
|
-
* flow emits each scored option under the FOUNDER'S OWN `option.value`, and
|
|
9
|
-
* the register's `optionWeights` map is keyed on those same values. Q3/Q4 are
|
|
10
|
-
* founder-authored, so their weights map is built PER LISTING from that
|
|
11
|
-
* listing's own options — the WEIGHT still comes from the founder's declared
|
|
12
|
-
* order via `listingOptionPoints(index, arity)`, but it is stored against the
|
|
13
|
-
* value rather than an index. Q5/Q6 carry fixed values
|
|
14
|
-
* (`projectListingQuestionsSchema`, #4998), so their weights are declared once
|
|
15
|
-
* here, shared by every listing.
|
|
16
|
-
*
|
|
17
|
-
* What that buys, and why the old `q{n}:{i}of{k}` encoding had to go: meaning
|
|
18
|
-
* now travels with the value. A register may reorder or insert options and an
|
|
19
|
-
* already-stored answer keeps scoring what it always meant, so the subset a
|
|
20
|
-
* surface renders no longer has to be a prefix of the register's list — which
|
|
21
|
-
* is what unblocks the shared team-composition value set (#5036 D3). It also
|
|
22
|
-
* dissolves the "shared register needs a shared value universe" problem
|
|
23
|
-
* (docs/lessons/2026-09-07-…): the generated experiment's `questionSet` now
|
|
24
|
-
* declares the listing's OWN options, so
|
|
25
|
-
* `waitlistExperimentConfigSchema`'s "every weights key must be a declared
|
|
26
|
-
* option" cross-validation is satisfied by construction rather than by
|
|
27
|
-
* declaring a finite universe of positional tokens.
|
|
28
|
-
*
|
|
29
|
-
* What is shared is therefore the RULE and the shape — same point names, same
|
|
30
|
-
* `total` sum, same tier floors, same 0–12 range — not a single frozen
|
|
31
|
-
* constant. Two listings' registers differ only in the Q3/Q4 KEYS, which are
|
|
32
|
-
* the founders' own option values.
|
|
33
|
-
*
|
|
34
|
-
* Q5 runs STRONGEST-FIRST, deliberately. `projectListingQuestionsSchema` pins
|
|
35
|
-
* Q5's values as `urgent | planning | exploring`, which is urgency descending,
|
|
36
|
-
* while the positional rule scores index 0 lowest — so the old positional
|
|
37
|
-
* encoding scored `urgent` 0 and `exploring` 3, backwards, a standing defect
|
|
38
|
-
* recorded in docs/lessons/2026-09-07-q5-fixed-order-is-strongest-first.md.
|
|
39
|
-
* Scoring by value is exactly the mechanism that resolves it: the weights
|
|
40
|
-
* below name `urgent` 3 and `exploring` 0 explicitly, with no reordering of
|
|
41
|
-
* the founder's rendered options and no per-question special case hidden
|
|
42
|
-
* inside a positional formula. That lesson's open question is closed here.
|
|
43
|
-
* Q6 (`low → critical`) is genuinely weakest-first and keeps 0 → 3.
|
|
44
|
-
*
|
|
45
|
-
* Q1 (contact), Q2 (segment), Q7 (free text) and the extras carry no points —
|
|
46
|
-
* they are absent from `points` entirely, so they contribute 0 by
|
|
47
|
-
* construction rather than by a zero weight that could drift.
|
|
48
|
-
*
|
|
49
|
-
* This module is data + the pure functions that generate it — it imports only
|
|
50
|
-
* TYPES from `@working-theory/validation` and introduces no dependency from
|
|
51
|
-
* `database/` toward `apps/*` (architecture.yaml's import boundary), exactly
|
|
52
|
-
* like `presets.ts` beside it. The rule lives here and only here; the
|
|
53
|
-
* projection (`apps/api/src/services/project-listing-flow.ts`) calls
|
|
54
|
-
* `buildListingDiagnosticScoring` rather than re-deriving weights, so the
|
|
55
|
-
* register and the flow can never disagree about what an answer is worth.
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
import type {
|
|
59
|
-
ProjectListingQuestions,
|
|
60
|
-
WaitlistScoring,
|
|
61
|
-
} from "@working-theory/validation";
|
|
62
|
-
|
|
63
|
-
/** The four scored template questions, in template order. */
|
|
64
|
-
export const LISTING_DIAGNOSTIC_SCORED_QUESTIONS = ["q3", "q4", "q5", "q6"] as const;
|
|
65
|
-
export type ListingDiagnosticScoredQuestion =
|
|
66
|
-
(typeof LISTING_DIAGNOSTIC_SCORED_QUESTIONS)[number];
|
|
67
|
-
|
|
68
|
-
/** The highest score any one question can contribute. */
|
|
69
|
-
export const LISTING_DIAGNOSTIC_MAX_QUESTION_POINTS = 3;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* The weight of option `index` (zero-based) of `arity` options —
|
|
73
|
-
* `round(3·i/(k−1))`, so the founder's first option always scores 0 and their
|
|
74
|
-
* last always scores 3, whatever the arity. This is still how a
|
|
75
|
-
* founder-authored question's weights are DERIVED (the founder orders their
|
|
76
|
-
* options weakest→strongest); what changed in #5036 D4 is where the result is
|
|
77
|
-
* STORED — against the option's value, not its index.
|
|
78
|
-
*
|
|
79
|
-
* A single-option question (`arity <= 1`) has no spread to score and yields 0;
|
|
80
|
-
* the template never produces one, and this guard exists so the expression can
|
|
81
|
-
* never divide by zero.
|
|
82
|
-
*/
|
|
83
|
-
export function listingOptionPoints(index: number, arity: number): number {
|
|
84
|
-
if (arity <= 1) return 0;
|
|
85
|
-
return Math.round((LISTING_DIAGNOSTIC_MAX_QUESTION_POINTS * index) / (arity - 1));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* `optionWeights` for one founder-authored question (Q3/Q4), keyed by the
|
|
90
|
-
* founder's own option values and weighted by their declared order.
|
|
91
|
-
*/
|
|
92
|
-
export function listingDiagnosticOptionWeights(
|
|
93
|
-
options: readonly { value: string }[],
|
|
94
|
-
): Record<string, number> {
|
|
95
|
-
const weights: Record<string, number> = {};
|
|
96
|
-
options.forEach((option, index) => {
|
|
97
|
-
weights[option.value] = listingOptionPoints(index, options.length);
|
|
98
|
-
});
|
|
99
|
-
return weights;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Q5's fixed urgency weights — STRONGEST FIRST, against the positional rule
|
|
104
|
-
* and deliberately so (see the file header). `urgent` is the strongest buying
|
|
105
|
-
* signal the question can carry and scores 3; `exploring` is the weakest and
|
|
106
|
-
* scores 0. The three weights are the same multiset a 3-option positional
|
|
107
|
-
* question produces (`{0, 2, 3}`), so the 0–12 total range is unchanged.
|
|
108
|
-
*/
|
|
109
|
-
export const LISTING_DIAGNOSTIC_Q5_WEIGHTS: Readonly<Record<string, number>> = {
|
|
110
|
-
urgent: 3,
|
|
111
|
-
planning: 2,
|
|
112
|
-
exploring: 0,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Q6's fixed band weights — weakest first, matching the schema's own
|
|
117
|
-
* `low → critical` low→high ordering, so these are exactly what the positional
|
|
118
|
-
* rule produced for a 4-option question.
|
|
119
|
-
*/
|
|
120
|
-
export const LISTING_DIAGNOSTIC_Q6_WEIGHTS: Readonly<Record<string, number>> = {
|
|
121
|
-
low: 0,
|
|
122
|
-
medium: 1,
|
|
123
|
-
high: 2,
|
|
124
|
-
critical: 3,
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
/** The four tier keys, strongest first — the order `tiers` is evaluated in. */
|
|
128
|
-
export const LISTING_DIAGNOSTIC_TIERS = ["now", "soon", "later", "curious"] as const;
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* The inclusive lower bound of each tier over the 0–12 total (4 questions ×
|
|
132
|
-
* 3 points): `now` 10–12, `soon` 7–9, `later` 4–6, `curious` 0–3. Ordered
|
|
133
|
-
* strongest-first because `evaluateWaitlistScoring` takes the FIRST matching
|
|
134
|
-
* tier, so a `gte` ladder read top-down is total and unambiguous.
|
|
135
|
-
*/
|
|
136
|
-
const TIER_FLOORS: Readonly<Record<(typeof LISTING_DIAGNOSTIC_TIERS)[number], number>> = {
|
|
137
|
-
now: 10,
|
|
138
|
-
soon: 7,
|
|
139
|
-
later: 4,
|
|
140
|
-
curious: 0,
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Build one listing's register from its own `questions` block. Embedded
|
|
145
|
-
* verbatim into that listing's generated `WaitlistExperiment.config` —
|
|
146
|
-
* `waitlistExperimentConfigSchema` carries the scoring block by value and
|
|
147
|
-
* offers no by-reference slot.
|
|
148
|
-
*
|
|
149
|
-
* Every listing gets the same point names, the same `total` sum, the same
|
|
150
|
-
* tier ladder and the same 0–12 range; only the Q3/Q4 weight KEYS differ,
|
|
151
|
-
* because those keys are the founder's own option values (#5036 D4).
|
|
152
|
-
*/
|
|
153
|
-
export function buildListingDiagnosticScoring(
|
|
154
|
-
questions: ProjectListingQuestions,
|
|
155
|
-
): WaitlistScoring {
|
|
156
|
-
const weights: Record<ListingDiagnosticScoredQuestion, Record<string, number>> = {
|
|
157
|
-
q3: listingDiagnosticOptionWeights(questions.q3.options),
|
|
158
|
-
q4: listingDiagnosticOptionWeights(questions.q4.options),
|
|
159
|
-
q5: { ...LISTING_DIAGNOSTIC_Q5_WEIGHTS },
|
|
160
|
-
q6: { ...LISTING_DIAGNOSTIC_Q6_WEIGHTS },
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
version: 1,
|
|
165
|
-
points: LISTING_DIAGNOSTIC_SCORED_QUESTIONS.map((question) => ({
|
|
166
|
-
name: `${question}_points`,
|
|
167
|
-
question,
|
|
168
|
-
kind: "optionWeights" as const,
|
|
169
|
-
weights: weights[question],
|
|
170
|
-
})),
|
|
171
|
-
scores: {
|
|
172
|
-
total: {
|
|
173
|
-
sum: LISTING_DIAGNOSTIC_SCORED_QUESTIONS.map((q) => `${q}_points`),
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
tiers: LISTING_DIAGNOSTIC_TIERS.map((key) => ({
|
|
177
|
-
key,
|
|
178
|
-
when: { score: "total", gte: TIER_FLOORS[key] },
|
|
179
|
-
})),
|
|
180
|
-
default: "curious",
|
|
181
|
-
};
|
|
182
|
-
}
|