create-ailk 0.24.0 → 0.26.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 +53 -22
- 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 +2 -1
- package/dist/lib/fetch-template-snapshot.js +8 -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 +36 -15
- package/dist/lib/module-tier.d.ts +2 -8
- package/dist/lib/module-tier.js +13 -12
- package/dist/module-architecture.d.ts +20 -3
- package/dist/module-architecture.js +129 -552
- package/dist/paid-sections.d.ts +25 -1
- package/dist/paid-sections.js +88 -3
- package/dist/starter-grid.d.ts +6 -6
- package/dist/starter-grid.js +12 -5
- package/dist/surfaces.js +39 -2
- package/dist/template-record.d.ts +21 -3
- package/dist/template-record.js +38 -7
- package/dist/topology.d.ts +16 -3
- package/dist/topology.js +54 -23
- package/dist/update.d.ts +10 -1
- package/dist/update.js +715 -21
- package/package.json +3 -3
- package/release-scope.json +2 -2
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +8 -2
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +2 -2
- package/site-templates/marketing-site/ailk-template.json +7 -1
- package/site-templates/marketing-site/provenance.json +7 -1
- package/site-templates/saas-product/ailk-template.json +2 -1
- package/site-templates/saas-product/provenance.json +1 -0
- 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 +20 -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 +23 -2
- package/templates/apps/api/CLAUDE.md +119 -83
- 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-client.js +16 -0
- 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 +90 -26
- 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 +31 -3
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
- package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +43 -4
- package/templates/apps/web/app/[locale]/(auth)/legal-footnote.tsx +35 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-in/__tests__/page.test.tsx +117 -8
- package/templates/apps/web/app/[locale]/(auth)/sign-in/page.tsx +14 -37
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +6 -6
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-text.ts +20 -35
- package/templates/apps/web/app/[locale]/(auth)/sign-up/__tests__/page.test.tsx +108 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-up/__tests__/sign-up-card.test.tsx +111 -5
- package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +78 -16
- package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +132 -12
- package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +53 -1
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/billing.test.tsx +38 -0
- package/templates/apps/web/app/[locale]/(authed)/account/billing/page.tsx +4 -2
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +47 -24
- package/templates/apps/web/app/[locale]/(authed)/signed-out-gate.generated.tsx +23 -4
- 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]/layout.tsx +33 -13
- package/templates/apps/web/app/[locale]/meet/confirmed/BookingHandOff.tsx +128 -0
- package/templates/apps/web/app/[locale]/meet/confirmed/__tests__/BookingHandOff.test.tsx +126 -0
- 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 +10 -6
- package/templates/apps/web/i18n/request.ts +49 -1
- package/templates/apps/web/jest.config.cjs +1 -0
- package/templates/apps/web/lib/__tests__/account-config.test.ts +7 -0
- package/templates/apps/web/lib/__tests__/auth-email.test.ts +276 -0
- package/templates/apps/web/lib/auth-email.ts +103 -21
- package/templates/apps/web/lib/hub-session/__tests__/sign-in-gate.test.tsx +72 -23
- package/templates/apps/web/lib/hub-session/sign-in-gate.tsx +94 -70
- package/templates/apps/web/lib/prisma-for-auth.ts +5 -2
- 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/lib/sign-up-agreements.ts +291 -28
- package/templates/apps/web/lib/site-contributions.ts +18 -0
- package/templates/apps/web/messages/en.json +186 -20
- package/templates/apps/web/messages/site/en.json +1 -0
- 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 +49 -36
- 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
package/versions.json
CHANGED
|
@@ -1,53 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
"@working-theory/admin-ui": "0.
|
|
3
|
-
"@working-theory/aeo": "0.
|
|
4
|
-
"@working-theory/agent-context": "0.
|
|
2
|
+
"@working-theory/admin-ui": "0.48.0",
|
|
3
|
+
"@working-theory/aeo": "0.48.0",
|
|
4
|
+
"@working-theory/agent-context": "0.48.0",
|
|
5
5
|
"@working-theory/agent-contract": "0.1.0",
|
|
6
6
|
"@working-theory/agent-memory": "0.0.0",
|
|
7
7
|
"@working-theory/ai": "0.1.0",
|
|
8
|
-
"@working-theory/analytics": "0.
|
|
9
|
-
"@working-theory/api
|
|
8
|
+
"@working-theory/analytics": "0.48.0",
|
|
9
|
+
"@working-theory/api": "0.48.0",
|
|
10
|
+
"@working-theory/api-client": "0.48.0",
|
|
10
11
|
"@working-theory/cda-filesystem": "0.0.0",
|
|
11
|
-
"@working-theory/cli": "0.
|
|
12
|
-
"@working-theory/common": "0.
|
|
12
|
+
"@working-theory/cli": "0.48.0",
|
|
13
|
+
"@working-theory/common": "0.48.0",
|
|
13
14
|
"@working-theory/consent": "0.1.0",
|
|
14
|
-
"@working-theory/content-adapters": "0.
|
|
15
|
-
"@working-theory/content-projection": "0.
|
|
16
|
-
"@working-theory/email": "0.
|
|
15
|
+
"@working-theory/content-adapters": "0.48.0",
|
|
16
|
+
"@working-theory/content-projection": "0.48.0",
|
|
17
|
+
"@working-theory/email": "0.48.0",
|
|
17
18
|
"@working-theory/env": "0.0.0",
|
|
18
|
-
"@working-theory/eslint-config": "0.
|
|
19
|
-
"@working-theory/fumadocs-schema": "0.
|
|
20
|
-
"@working-theory/ids": "0.
|
|
21
|
-
"@working-theory/jsonld": "0.
|
|
22
|
-
"@working-theory/license": "0.
|
|
23
|
-
"@working-theory/
|
|
24
|
-
"@working-theory/
|
|
25
|
-
"@working-theory/
|
|
19
|
+
"@working-theory/eslint-config": "0.48.0",
|
|
20
|
+
"@working-theory/fumadocs-schema": "0.48.0",
|
|
21
|
+
"@working-theory/ids": "0.16.0",
|
|
22
|
+
"@working-theory/jsonld": "0.48.0",
|
|
23
|
+
"@working-theory/license": "0.48.0",
|
|
24
|
+
"@working-theory/mcp-server": "0.48.0",
|
|
25
|
+
"@working-theory/metadata": "0.48.0",
|
|
26
|
+
"@working-theory/observability": "0.48.0",
|
|
27
|
+
"@working-theory/page-renderer": "0.48.0",
|
|
26
28
|
"@working-theory/plugin-mcp": "0.1.3",
|
|
27
|
-
"@working-theory/schema": "0.
|
|
28
|
-
"@working-theory/schema-pack-registry": "0.
|
|
29
|
-
"@working-theory/schema-validator": "0.
|
|
30
|
-
"@working-theory/sections-registry": "0.
|
|
31
|
-
"@working-theory/site-config": "0.
|
|
32
|
-
"@working-theory/spoke-checkout": "0.7.
|
|
33
|
-
"@working-theory/stripe-client": "0.
|
|
34
|
-
"@working-theory/templates": "0.
|
|
35
|
-
"@working-theory/theme": "0.
|
|
36
|
-
"@working-theory/ui": "0.
|
|
37
|
-
"@working-theory/validation": "0.
|
|
38
|
-
"@working-theory/web-i18n": "0.
|
|
29
|
+
"@working-theory/schema": "0.48.0",
|
|
30
|
+
"@working-theory/schema-pack-registry": "0.48.0",
|
|
31
|
+
"@working-theory/schema-validator": "0.48.0",
|
|
32
|
+
"@working-theory/sections-registry": "0.48.0",
|
|
33
|
+
"@working-theory/site-config": "0.48.0",
|
|
34
|
+
"@working-theory/spoke-checkout": "0.7.4",
|
|
35
|
+
"@working-theory/stripe-client": "0.48.0",
|
|
36
|
+
"@working-theory/templates": "0.48.0",
|
|
37
|
+
"@working-theory/theme": "0.48.0",
|
|
38
|
+
"@working-theory/ui": "0.48.0",
|
|
39
|
+
"@working-theory/validation": "0.48.0",
|
|
40
|
+
"@working-theory/web-i18n": "0.48.0",
|
|
41
|
+
"@working-theory/admin": "0.5.0",
|
|
42
|
+
"@working-theory/api-commerce": "0.1.2",
|
|
43
|
+
"@working-theory/api-content-write": "0.1.2",
|
|
44
|
+
"@working-theory/api-hub": "0.2.1",
|
|
45
|
+
"@working-theory/api-multi-tenant": "0.1.2",
|
|
46
|
+
"@working-theory/api-scheduling": "0.3.0",
|
|
47
|
+
"@working-theory/api-signal-collectors": "0.2.1",
|
|
48
|
+
"@working-theory/api-workspace": "0.2.1",
|
|
39
49
|
"@working-theory/billing-client": "0.0.0",
|
|
40
50
|
"@working-theory/branding": "0.0.0",
|
|
41
51
|
"@working-theory/license-client": "0.0.0",
|
|
42
52
|
"@working-theory/license-manifest": "0.0.0",
|
|
53
|
+
"@working-theory/mcp-scheduling": "0.3.1",
|
|
54
|
+
"@working-theory/mcp-signal-collectors": "0.2.2",
|
|
55
|
+
"@working-theory/mcp-workspace": "0.3.1",
|
|
43
56
|
"@working-theory/partner-session": "0.0.0",
|
|
44
57
|
"@working-theory/preview-protocol": "0.0.0",
|
|
45
|
-
"@working-theory/ui-commerce": "0.23.
|
|
46
|
-
"@working-theory/ui-docs-blog": "0.23.
|
|
47
|
-
"@working-theory/ui-scheduling": "0.
|
|
48
|
-
"@working-theory/ui-signal-collectors": "0.27.
|
|
58
|
+
"@working-theory/ui-commerce": "0.23.26",
|
|
59
|
+
"@working-theory/ui-docs-blog": "0.23.26",
|
|
60
|
+
"@working-theory/ui-scheduling": "0.25.0",
|
|
61
|
+
"@working-theory/ui-signal-collectors": "0.27.4",
|
|
49
62
|
"@working-theory/web": "0.0.0",
|
|
50
|
-
"@working-theory/api": "1.0.0",
|
|
63
|
+
"@working-theory/app-api": "1.0.0",
|
|
51
64
|
"@working-theory/mcp": "0.0.0",
|
|
52
|
-
"@working-theory/database": "0.
|
|
65
|
+
"@working-theory/database": "0.48.0"
|
|
53
66
|
}
|
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file commerce-claim-registration.test.ts
|
|
3
|
-
* @description The commerce PRIMITIVES serve on the license claim, not the
|
|
4
|
-
* module flag (DECISION-LOG D-64, epic #5770, #5796).
|
|
5
|
-
*
|
|
6
|
-
* `POST /v1/checkout/sessions` (the checkout launcher) and
|
|
7
|
-
* `POST /v1/webhooks/stripe` (the webhook receiver + customer mapping) are
|
|
8
|
-
* registered unconditionally in `server.ts` — no `isModuleEnabled("commerce")`
|
|
9
|
-
* gate. Every case below therefore runs with **no module flag set at all**
|
|
10
|
-
* (`AILK_ENABLED_MODULES` deleted), so a pass cannot be explained by module
|
|
11
|
-
* registration; only the stubbed `checkLicense()` result varies.
|
|
12
|
-
*
|
|
13
|
-
* The four gate cases:
|
|
14
|
-
*
|
|
15
|
-
* 1. keyless (free, no features) → checkout answers the module-disabled 404
|
|
16
|
-
* 2. keyless → the webhook answers the module-disabled 404
|
|
17
|
-
* 3. commerce claim → checkout serves (never 404)
|
|
18
|
-
* 4. commerce claim → the webhook serves (never 404)
|
|
19
|
-
*
|
|
20
|
-
* Plus D3's webhook order: a **signed** event on an **unclaimed** build is
|
|
21
|
-
* acked 200 and dropped with a structured log line — the signature is settled
|
|
22
|
-
* before the claim is consulted, so Stripe stops retrying against a site that
|
|
23
|
-
* turned commerce off, while an unsigned body on that same build gets the
|
|
24
|
-
* module-disabled 404 (indistinguishable from a build without the module).
|
|
25
|
-
*
|
|
26
|
-
* "Serves" is measured as "not Fastify's own 404 and not the gate's 404" —
|
|
27
|
-
* the same signal `module-exclusion.test.ts` uses. A registered-and-claimed
|
|
28
|
-
* checkout route answers 400 (Zod validation, empty body), never 404.
|
|
29
|
-
*
|
|
30
|
-
* Mirrors `src/__tests__/server.test.ts`'s external-boundary mocks.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
jest.mock('@fastify/cors', () => {
|
|
34
|
-
return jest.fn().mockResolvedValue(undefined);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
jest.mock('@fastify/rate-limit', () => {
|
|
38
|
-
return jest.fn().mockResolvedValue(undefined);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
jest.mock('@working-theory/email', () => ({
|
|
42
|
-
sendLeadNotification: jest.fn().mockResolvedValue({ ok: true }),
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
const mockCheckLicense = jest.fn();
|
|
46
|
-
// `checkLicense` is stubbed (it reaches the network and the clock);
|
|
47
|
-
// `readStoredJwtState` deliberately is NOT — the unreadable-storage case below
|
|
48
|
-
// proves the 503 through the package's REAL filesystem read, pointed at a
|
|
49
|
-
// fixture path via `AILK_LICENSE_STORAGE_PATH` (#5820). Stubbing it here would
|
|
50
|
-
// assert only that the stub was called.
|
|
51
|
-
jest.mock('@working-theory/license', () => ({
|
|
52
|
-
...jest.requireActual('@working-theory/license'),
|
|
53
|
-
checkLicense: (...args: unknown[]) => mockCheckLicense(...args),
|
|
54
|
-
}));
|
|
55
|
-
|
|
56
|
-
const mockVerifyWebhookSignature = jest.fn();
|
|
57
|
-
class MockStripeWebhookSignatureError extends Error {
|
|
58
|
-
constructor(message: string) {
|
|
59
|
-
super(message);
|
|
60
|
-
this.name = 'StripeWebhookSignatureError';
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// #6084 — GET /v1/checkout/sessions/:id's own retrieve, stubbed with a
|
|
64
|
-
// payload-free default so a claimed request that never called mockReset
|
|
65
|
-
// still answers 200 rather than throwing `undefined`.
|
|
66
|
-
const mockRetrieveCheckoutSession = jest.fn();
|
|
67
|
-
|
|
68
|
-
jest.mock('@working-theory/stripe-client', () => ({
|
|
69
|
-
verifyWebhookSignature: (...args: unknown[]) =>
|
|
70
|
-
mockVerifyWebhookSignature(...args),
|
|
71
|
-
StripeWebhookSignatureError: MockStripeWebhookSignatureError,
|
|
72
|
-
assertSandboxKey: jest.fn(),
|
|
73
|
-
createCheckoutSession: jest.fn(),
|
|
74
|
-
retrieveCheckoutSession: (...args: unknown[]) =>
|
|
75
|
-
mockRetrieveCheckoutSession(...args),
|
|
76
|
-
getStripeClient: jest.fn(),
|
|
77
|
-
STRIPE_API_VERSION: '2024-06-20',
|
|
78
|
-
StripeConfigError: class StripeConfigError extends Error {},
|
|
79
|
-
UnknownProductCodeError: class UnknownProductCodeError extends Error {},
|
|
80
|
-
UnknownSessionError: class UnknownSessionError extends Error {},
|
|
81
|
-
// #6866 — sessions.ts tests `instanceof UnknownCustomerError`.
|
|
82
|
-
UnknownCustomerError: class UnknownCustomerError extends Error {},
|
|
83
|
-
WEBHOOK_TOLERANCE_SECONDS: 300,
|
|
84
|
-
}));
|
|
85
|
-
|
|
86
|
-
// eslint-disable-next-line no-restricted-syntax -- lib/prisma.ts wraps the external DB boundary; __mocks__/prisma.ts is the repo-standard double.
|
|
87
|
-
jest.mock('../lib/prisma.js');
|
|
88
|
-
|
|
89
|
-
import { promises as fs } from 'fs';
|
|
90
|
-
import { tmpdir } from 'os';
|
|
91
|
-
import { join } from 'path';
|
|
92
|
-
|
|
93
|
-
import { __resetBuckets } from '../middleware/rate-limit.js';
|
|
94
|
-
import { prisma } from '../lib/prisma.js';
|
|
95
|
-
import { build } from '../server';
|
|
96
|
-
|
|
97
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- server is typed via Fastify generics
|
|
98
|
-
type App = any;
|
|
99
|
-
|
|
100
|
-
// The reserved-range sentinel values from database/tenancy.ts (ADR-0031
|
|
101
|
-
// rule 7) — re-declared here as literals so the test pins the WIRE values,
|
|
102
|
-
// the same convention middleware/__tests__/default-tenant.test.ts uses.
|
|
103
|
-
const DEFAULT_ORG_ID = 'org_00000000-0000-7000-8000-000000000001';
|
|
104
|
-
const DEFAULT_WORKSPACE_ID = 'wksp_00000000-0000-7000-8000-000000000001';
|
|
105
|
-
|
|
106
|
-
const FREE_LICENSE = {
|
|
107
|
-
tier: 'free' as const,
|
|
108
|
-
plan: null,
|
|
109
|
-
features: [] as string[],
|
|
110
|
-
expiresAt: null,
|
|
111
|
-
revoked: false,
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const COMMERCE_LICENSE = {
|
|
115
|
-
tier: 'pro' as const,
|
|
116
|
-
plan: 'pro-monthly',
|
|
117
|
-
features: ['commerce'] as string[],
|
|
118
|
-
expiresAt: null,
|
|
119
|
-
revoked: false,
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const CHECKOUT = { method: 'POST' as const, url: '/v1/checkout/sessions' };
|
|
123
|
-
const WEBHOOK = { method: 'POST' as const, url: '/v1/webhooks/stripe' };
|
|
124
|
-
// #6084 — the read half. `cs_test_...` shape-passes the route's own gate so
|
|
125
|
-
// a claim-gate assertion never masquerades as a shape-gate 400.
|
|
126
|
-
const CHECKOUT_SESSION_READ = {
|
|
127
|
-
method: 'GET' as const,
|
|
128
|
-
url: '/v1/checkout/sessions/cs_test_commerce_claim_fixture',
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/** Build with NO module flag set — the whole point of the matrix. */
|
|
132
|
-
async function buildKeylessModuleSet(): Promise<App> {
|
|
133
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
134
|
-
return build();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
describe('Commerce primitives gate on the license claim, not the module flag (D-64, #5796)', () => {
|
|
138
|
-
let app: App;
|
|
139
|
-
|
|
140
|
-
beforeEach(() => {
|
|
141
|
-
// #6155 D6 — build() now awaits assertSiteAliasResolves(), which reads
|
|
142
|
-
// prisma.workspace for the unpinned "default" alias every case here
|
|
143
|
-
// resolves under (no case sets AILK_SITE_ID). None of this file's
|
|
144
|
-
// assertions are about tenancy, so this stubs the healthy default —
|
|
145
|
-
// the seeded sentinel workspace resolving cleanly — rather than
|
|
146
|
-
// widening the shared mock's own default for every OTHER consumer.
|
|
147
|
-
(prisma.workspace.findUnique as jest.Mock).mockResolvedValue({
|
|
148
|
-
id: DEFAULT_WORKSPACE_ID,
|
|
149
|
-
organizationId: DEFAULT_ORG_ID,
|
|
150
|
-
});
|
|
151
|
-
mockCheckLicense.mockReset();
|
|
152
|
-
mockVerifyWebhookSignature.mockReset();
|
|
153
|
-
mockRetrieveCheckoutSession.mockReset();
|
|
154
|
-
mockRetrieveCheckoutSession.mockResolvedValue({
|
|
155
|
-
id: 'cs_test_commerce_claim_fixture',
|
|
156
|
-
status: 'complete',
|
|
157
|
-
paymentStatus: 'paid',
|
|
158
|
-
currency: 'usd',
|
|
159
|
-
amountTotal: 100,
|
|
160
|
-
lineItems: [],
|
|
161
|
-
});
|
|
162
|
-
// The GET's own rate limiter is MODULE-scoped (middleware/rate-limit.ts
|
|
163
|
-
// § "Module-scoped bucket store") and shared across every `it` in this
|
|
164
|
-
// file's single module instance.
|
|
165
|
-
__resetBuckets();
|
|
166
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
167
|
-
// A keyless deployment configures no licence at all — the state the gate
|
|
168
|
-
// reads as a positive "no". Tests that need the expired case set it.
|
|
169
|
-
delete process.env.AILK_LICENSE_KEY;
|
|
170
|
-
// Every case starts from a storage path that does NOT exist — the `absent`
|
|
171
|
-
// state. The unreadable case below creates a directory at its own path.
|
|
172
|
-
process.env.AILK_LICENSE_STORAGE_PATH = join(
|
|
173
|
-
tmpdir(),
|
|
174
|
-
`ailk-claim-absent-${process.pid}-${Date.now()}.jwt`,
|
|
175
|
-
);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
afterEach(async () => {
|
|
179
|
-
if (app) {
|
|
180
|
-
await app.close();
|
|
181
|
-
app = undefined;
|
|
182
|
-
}
|
|
183
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
184
|
-
delete process.env.AILK_LICENSE_KEY;
|
|
185
|
-
delete process.env.AILK_LICENSE_STORAGE_PATH;
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe('keyless build (checkLicense stubbed free)', () => {
|
|
189
|
-
beforeEach(() => {
|
|
190
|
-
mockCheckLicense.mockResolvedValue(FREE_LICENSE);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('answers the module-disabled response on POST /v1/checkout/sessions', async () => {
|
|
194
|
-
app = await buildKeylessModuleSet();
|
|
195
|
-
const res = await app.inject({
|
|
196
|
-
...CHECKOUT,
|
|
197
|
-
payload: { productCode: 'x', successUrl: 'https://a', cancelUrl: 'https://b' },
|
|
198
|
-
});
|
|
199
|
-
expect(res.statusCode).toBe(404);
|
|
200
|
-
expect(res.json()).toEqual({ error: 'not_found', message: 'Not found' });
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('answers the module-disabled response on POST /v1/webhooks/stripe', async () => {
|
|
204
|
-
app = await buildKeylessModuleSet();
|
|
205
|
-
const res = await app.inject({ ...WEBHOOK, payload: {} });
|
|
206
|
-
expect(res.statusCode).toBe(404);
|
|
207
|
-
expect(res.json()).toEqual({ error: 'not_found', message: 'Not found' });
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// #6084 AC-3/T-5 — the GET inherits the SAME scope preHandler as the
|
|
211
|
-
// POST above; this harness (a full server build with checkLicense
|
|
212
|
-
// stubbed) is the one that actually exercises the gate, unlike
|
|
213
|
-
// sessions.test.ts's/session.test.ts's own bare-registration harness
|
|
214
|
-
// (§9 SA-4).
|
|
215
|
-
it('answers the module-disabled response on GET /v1/checkout/sessions/:id', async () => {
|
|
216
|
-
app = await buildKeylessModuleSet();
|
|
217
|
-
const res = await app.inject(CHECKOUT_SESSION_READ);
|
|
218
|
-
expect(res.statusCode).toBe(404);
|
|
219
|
-
expect(res.json()).toEqual({ error: 'not_found', message: 'Not found' });
|
|
220
|
-
expect(mockRetrieveCheckoutSession).not.toHaveBeenCalled();
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
describe('commerce-claimed build (checkLicense stubbed with the claim)', () => {
|
|
225
|
-
beforeEach(() => {
|
|
226
|
-
mockCheckLicense.mockResolvedValue(COMMERCE_LICENSE);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('serves POST /v1/checkout/sessions with no module flag set', async () => {
|
|
230
|
-
app = await buildKeylessModuleSet();
|
|
231
|
-
expect(process.env.AILK_ENABLED_MODULES).toBeUndefined();
|
|
232
|
-
const res = await app.inject({ ...CHECKOUT, payload: {} });
|
|
233
|
-
expect(res.statusCode).not.toBe(404);
|
|
234
|
-
expect(res.statusCode).toBe(400); // Zod validation — the handler ran
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('serves POST /v1/webhooks/stripe with no module flag set', async () => {
|
|
238
|
-
app = await buildKeylessModuleSet();
|
|
239
|
-
expect(process.env.AILK_ENABLED_MODULES).toBeUndefined();
|
|
240
|
-
const res = await app.inject({ ...WEBHOOK, payload: {} });
|
|
241
|
-
expect(res.statusCode).not.toBe(404);
|
|
242
|
-
expect(res.statusCode).toBe(400); // signature-missing — the handler ran
|
|
243
|
-
expect(res.json()).toEqual({ error: 'signature-missing' });
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// #6084 AC-3/T-5
|
|
247
|
-
it('serves GET /v1/checkout/sessions/:id with no module flag set', async () => {
|
|
248
|
-
app = await buildKeylessModuleSet();
|
|
249
|
-
expect(process.env.AILK_ENABLED_MODULES).toBeUndefined();
|
|
250
|
-
const res = await app.inject(CHECKOUT_SESSION_READ);
|
|
251
|
-
expect(res.statusCode).not.toBe(404);
|
|
252
|
-
expect(res.statusCode).toBe(200); // the handler ran
|
|
253
|
-
expect(mockRetrieveCheckoutSession).toHaveBeenCalledWith({
|
|
254
|
-
sessionId: 'cs_test_commerce_claim_fixture',
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// Security review 2026-09-16, High, as disposed in round 2. The pre-review
|
|
260
|
-
// gate collapsed "no claim" and "could not read the licence" into one
|
|
261
|
-
// `false`, so a signed checkout.session.completed on a LIVE commerce site
|
|
262
|
-
// whose licence read merely failed was acked 200 and lost — Stripe records
|
|
263
|
-
// success and never redelivers, and the charge is never mapped.
|
|
264
|
-
//
|
|
265
|
-
// Round 2 widens `undetermined` past the throw: a REVOKED licence and a
|
|
266
|
-
// CONFIGURED-but-free (expired/unverifiable) one are both live commerce
|
|
267
|
-
// deployments mid-window, so neither may be dropped either.
|
|
268
|
-
describe('undetermined licence — the read established no "no", so nothing may be dropped', () => {
|
|
269
|
-
const SIGNED_EVENT = {
|
|
270
|
-
id: 'evt_undetermined_01',
|
|
271
|
-
type: 'checkout.session.completed',
|
|
272
|
-
data: { object: { id: 'cs_x', payment_status: 'paid' } },
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
it('holds a SIGNED event with a retryable 503 + Retry-After when the read throws', async () => {
|
|
276
|
-
mockCheckLicense.mockRejectedValue(new Error('licence read blew up'));
|
|
277
|
-
mockVerifyWebhookSignature.mockReturnValue(SIGNED_EVENT);
|
|
278
|
-
app = await buildKeylessModuleSet();
|
|
279
|
-
|
|
280
|
-
const res = await app.inject({
|
|
281
|
-
...WEBHOOK,
|
|
282
|
-
headers: { 'stripe-signature': 't=1,v1=deadbeef' },
|
|
283
|
-
payload: { any: 'body' },
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
expect(res.statusCode).toBe(503);
|
|
287
|
-
expect(res.json()).toEqual({ error: 'license-undetermined' });
|
|
288
|
-
// Stripe reads Retry-After; without it the redelivery schedule is the
|
|
289
|
-
// default backoff rather than the window this gate intends.
|
|
290
|
-
expect(res.headers['retry-after']).toBe('300');
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('holds a SIGNED event when the licence is REVOKED — a revoked site is still live mid-window', async () => {
|
|
294
|
-
mockCheckLicense.mockResolvedValue({ ...COMMERCE_LICENSE, revoked: true });
|
|
295
|
-
mockVerifyWebhookSignature.mockReturnValue(SIGNED_EVENT);
|
|
296
|
-
app = await buildKeylessModuleSet();
|
|
297
|
-
|
|
298
|
-
const res = await app.inject({
|
|
299
|
-
...WEBHOOK,
|
|
300
|
-
headers: { 'stripe-signature': 't=1,v1=deadbeef' },
|
|
301
|
-
payload: { any: 'body' },
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
expect(res.statusCode).toBe(503);
|
|
305
|
-
expect(res.headers['retry-after']).toBe('300');
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it('holds a SIGNED event when a licence IS configured yet resolves free — the EXPIRED case', async () => {
|
|
309
|
-
// Presence is the whole test — the gate never parses this value, so it
|
|
310
|
-
// is deliberately not JWT-shaped (a realistic stub trips the secret
|
|
311
|
-
// scanner's entropy rule for no benefit).
|
|
312
|
-
process.env.AILK_LICENSE_KEY = 'fixture';
|
|
313
|
-
mockCheckLicense.mockResolvedValue(FREE_LICENSE);
|
|
314
|
-
mockVerifyWebhookSignature.mockReturnValue(SIGNED_EVENT);
|
|
315
|
-
app = await buildKeylessModuleSet();
|
|
316
|
-
|
|
317
|
-
const res = await app.inject({
|
|
318
|
-
...WEBHOOK,
|
|
319
|
-
headers: { 'stripe-signature': 't=1,v1=deadbeef' },
|
|
320
|
-
payload: { any: 'body' },
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
expect(res.statusCode).toBe(503);
|
|
324
|
-
expect(res.headers['retry-after']).toBe('300');
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// #5820: the read did not throw and nothing is configured in env — the
|
|
328
|
-
// storage file simply could not be READ. Before this fix `readStoredJwt()`
|
|
329
|
-
// collapsed that into the same `null` it returns for "no file", so the
|
|
330
|
-
// event was acked 200 and dropped and the charge was never mapped. Proven
|
|
331
|
-
// through the package's real filesystem read (a directory at the storage
|
|
332
|
-
// path), not a stub.
|
|
333
|
-
it('holds a SIGNED event when the storage file is UNREADABLE — a directory at the licence path', async () => {
|
|
334
|
-
const tempDir = await fs.mkdtemp(join(tmpdir(), 'ailk-claim-storage-'));
|
|
335
|
-
const unreadable = join(tempDir, '.ailk-license.jwt');
|
|
336
|
-
await fs.mkdir(unreadable);
|
|
337
|
-
process.env.AILK_LICENSE_STORAGE_PATH = unreadable;
|
|
338
|
-
|
|
339
|
-
mockCheckLicense.mockResolvedValue(FREE_LICENSE);
|
|
340
|
-
mockVerifyWebhookSignature.mockReturnValue(SIGNED_EVENT);
|
|
341
|
-
app = await buildKeylessModuleSet();
|
|
342
|
-
|
|
343
|
-
try {
|
|
344
|
-
const res = await app.inject({
|
|
345
|
-
...WEBHOOK,
|
|
346
|
-
headers: { 'stripe-signature': 't=1,v1=deadbeef' },
|
|
347
|
-
payload: { any: 'body' },
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
expect(res.statusCode).toBe(503);
|
|
351
|
-
expect(res.json()).toEqual({ error: 'license-undetermined' });
|
|
352
|
-
expect(res.headers['retry-after']).toBe('300');
|
|
353
|
-
} finally {
|
|
354
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
// Round 2, D1: the CHECKOUT launcher does not hold. A checkout that cannot
|
|
359
|
-
// be started loses nothing, so both non-serving states answer the same
|
|
360
|
-
// module-disabled 404 and the route stays indistinguishable from a build
|
|
361
|
-
// without the module.
|
|
362
|
-
it('answers the module-disabled 404 on checkout — a checkout that cannot start loses nothing', async () => {
|
|
363
|
-
mockCheckLicense.mockRejectedValue(new Error('licence read blew up'));
|
|
364
|
-
app = await buildKeylessModuleSet();
|
|
365
|
-
const res = await app.inject({ ...CHECKOUT, payload: {} });
|
|
366
|
-
expect(res.statusCode).toBe(404);
|
|
367
|
-
expect(res.json()).toEqual({ error: 'not_found', message: 'Not found' });
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
describe('D3 — the Stripe signature is settled before the claim is consulted', () => {
|
|
372
|
-
it('acks a signed-but-unclaimed event 200 and drops it', async () => {
|
|
373
|
-
mockCheckLicense.mockResolvedValue(FREE_LICENSE);
|
|
374
|
-
mockVerifyWebhookSignature.mockReturnValue({
|
|
375
|
-
id: 'evt_unclaimed_0001',
|
|
376
|
-
type: 'customer.created',
|
|
377
|
-
data: { object: { id: 'cus_x', email: 'a@b.test' } },
|
|
378
|
-
});
|
|
379
|
-
app = await buildKeylessModuleSet();
|
|
380
|
-
|
|
381
|
-
const res = await app.inject({
|
|
382
|
-
...WEBHOOK,
|
|
383
|
-
headers: { 'stripe-signature': 't=1,v1=deadbeef' },
|
|
384
|
-
payload: { any: 'body' },
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
expect(res.statusCode).toBe(200);
|
|
388
|
-
expect(res.json()).toEqual({ received: true });
|
|
389
|
-
// The signature was verified BEFORE the claim was consulted.
|
|
390
|
-
expect(mockVerifyWebhookSignature).toHaveBeenCalledTimes(1);
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// "Rejected before the claim is read" in the only form AC 1 leaves open:
|
|
394
|
-
// on a CLAIMED build — where the claim cannot be what refuses it — an
|
|
395
|
-
// unsigned body is still refused 400 and never dispatched. The claim never
|
|
396
|
-
// admits an unverified body. (On an UNCLAIMED build the module-disabled
|
|
397
|
-
// 404 wins instead, which is AC 1 and round-1 D3, unchanged here.)
|
|
398
|
-
it('refuses an unsigned body on a CLAIMED build — the claim never admits an unverified body', async () => {
|
|
399
|
-
mockCheckLicense.mockResolvedValue(COMMERCE_LICENSE);
|
|
400
|
-
app = await buildKeylessModuleSet();
|
|
401
|
-
|
|
402
|
-
const res = await app.inject({ ...WEBHOOK, payload: { any: 'body' } });
|
|
403
|
-
|
|
404
|
-
expect(res.statusCode).toBe(400);
|
|
405
|
-
expect(res.json()).toEqual({ error: 'signature-missing' });
|
|
406
|
-
expect(mockVerifyWebhookSignature).not.toHaveBeenCalled();
|
|
407
|
-
});
|
|
408
|
-
});
|
|
409
|
-
});
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file agent-caller.ts
|
|
3
|
-
*
|
|
4
|
-
* An agent caller for route suites that mock `lib/prisma.js` inline (#3591
|
|
5
|
-
* D8): a key minted at run time — never a key-shaped literal in a fixture —
|
|
6
|
-
* plus the two reads the auth preHandler and the multi-tenant guard make for
|
|
7
|
-
* it, so the suite's existing `agent` and `membership` `findUnique` mocks can
|
|
8
|
-
* answer an agent without changing what they answer anyone else.
|
|
9
|
-
*
|
|
10
|
-
* Usage, inside a suite whose inline prisma mock declares
|
|
11
|
-
* `agent: { findUnique: jest.fn(), update: jest.fn() }`: build a caller with
|
|
12
|
-
* `buildAgentCaller({ organizationId, workspaceId })`, give the `agent`
|
|
13
|
-
* delegate's `findUnique` the `agentKeyLookup(caller)` implementation and the
|
|
14
|
-
* `membership` delegate's `findUnique` the `agentMembershipLookup(caller,
|
|
15
|
-
* existingImplementation)` one, then send the request with `caller.headers`.
|
|
16
|
-
* (This docblock names the delegates in prose: the tenant-scope lint in
|
|
17
|
-
* `architecture.yaml` scans comments too.)
|
|
18
|
-
*/
|
|
19
|
-
import { hashAgentKey, mintAgentKey } from "../../lib/agent-store.js";
|
|
20
|
-
|
|
21
|
-
export interface AgentCaller {
|
|
22
|
-
agentId: string;
|
|
23
|
-
/** The responsible person's user id — the agent acts on their behalf. */
|
|
24
|
-
userId: string;
|
|
25
|
-
membershipId: string;
|
|
26
|
-
organizationId: string;
|
|
27
|
-
workspaceId: string;
|
|
28
|
-
/** The person's own role; the guard clamps the agent to `member`. */
|
|
29
|
-
role: "owner" | "admin" | "member";
|
|
30
|
-
/** The agent's stored grants (#7864); the guard keeps those `role` holds. */
|
|
31
|
-
grants: string[];
|
|
32
|
-
headers: { authorization: string };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function buildAgentCaller(
|
|
36
|
-
scope: { organizationId: string; workspaceId: string },
|
|
37
|
-
overrides: Partial<
|
|
38
|
-
Pick<AgentCaller, "agentId" | "userId" | "membershipId" | "role" | "grants">
|
|
39
|
-
> = {},
|
|
40
|
-
): AgentCaller & { key: string } {
|
|
41
|
-
const key = mintAgentKey();
|
|
42
|
-
return {
|
|
43
|
-
agentId: "agent_00000000-0000-7000-8000-00000000a9e1",
|
|
44
|
-
userId: "user_00000000-0000-7000-8000-00000000a9e2",
|
|
45
|
-
membershipId: "member_00000000-0000-7000-8000-00000000a9e3",
|
|
46
|
-
role: "member",
|
|
47
|
-
grants: [],
|
|
48
|
-
...scope,
|
|
49
|
-
...overrides,
|
|
50
|
-
key,
|
|
51
|
-
headers: { authorization: `Bearer ${key}` },
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** The `agent` delegate's `findUnique` for the auth preHandler: the caller's row by its key's digest. */
|
|
56
|
-
export function agentKeyLookup(
|
|
57
|
-
caller: AgentCaller & { key: string },
|
|
58
|
-
): (args: {
|
|
59
|
-
where: { credentialHash?: string };
|
|
60
|
-
}) => Promise<Record<string, unknown> | null> {
|
|
61
|
-
const credentialHash = hashAgentKey(caller.key);
|
|
62
|
-
return ({ where }) =>
|
|
63
|
-
Promise.resolve(
|
|
64
|
-
where.credentialHash === credentialHash
|
|
65
|
-
? {
|
|
66
|
-
id: caller.agentId,
|
|
67
|
-
workspaceId: caller.workspaceId,
|
|
68
|
-
organizationId: caller.organizationId,
|
|
69
|
-
permissionLevel: "member",
|
|
70
|
-
grants: caller.grants,
|
|
71
|
-
enabled: true,
|
|
72
|
-
keyIssuedToMembershipId: caller.membershipId,
|
|
73
|
-
lastActiveAt: null,
|
|
74
|
-
responsible: { id: caller.membershipId, userId: caller.userId },
|
|
75
|
-
}
|
|
76
|
-
: null,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
type MembershipArgs = {
|
|
81
|
-
where: { organizationId_userId?: { organizationId: string; userId: string } };
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* The `membership` delegate's `findUnique`, answering the agent's person's membership
|
|
86
|
-
* and deferring every other read to `fallback` (the suite's own mock).
|
|
87
|
-
*/
|
|
88
|
-
export function agentMembershipLookup(
|
|
89
|
-
caller: AgentCaller,
|
|
90
|
-
fallback: (args: MembershipArgs) => unknown,
|
|
91
|
-
): (args: MembershipArgs) => unknown {
|
|
92
|
-
return (args) => {
|
|
93
|
-
const key = args.where.organizationId_userId;
|
|
94
|
-
if (
|
|
95
|
-
key?.organizationId === caller.organizationId &&
|
|
96
|
-
key.userId === caller.userId
|
|
97
|
-
) {
|
|
98
|
-
return Promise.resolve({ id: caller.membershipId, role: caller.role });
|
|
99
|
-
}
|
|
100
|
-
return fallback(args);
|
|
101
|
-
};
|
|
102
|
-
}
|