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,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the list_pages MCP tool handler.
|
|
3
|
-
*
|
|
4
|
-
* Acceptance criteria verified here:
|
|
5
|
-
* - contentListParamsSchema requires `type` and rejects unknown type values
|
|
6
|
-
* - contentListQuerySchema takes an optional `page` / `pageSize` window
|
|
7
|
-
* - ailkListPages returns the route's paginated ItemList for a type
|
|
8
|
-
* - ailkListPages defaults the window to page 1 / pageSize 20 and clamps
|
|
9
|
-
* pageSize to 100, as the route does
|
|
10
|
-
* - Output validates against contentListResultSchema
|
|
11
|
-
* - No console.* calls in handler (structural test)
|
|
12
|
-
*
|
|
13
|
-
* #7168 (the operator's decision of 2026-10-19): the tool adopted its route's
|
|
14
|
-
* arguments (`type` required, `page`/`pageSize`) and result (the paginated
|
|
15
|
-
* `ItemList`, not `{ pages }`); the all-types fan-out is gone with the
|
|
16
|
-
* optional `type`.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
20
|
-
import { tmpdir } from "node:os";
|
|
21
|
-
import { resolve, join } from "node:path";
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
resetResolvedContentAdapter,
|
|
25
|
-
type ArtifactPrismaClient,
|
|
26
|
-
} from "@working-theory/content-adapters";
|
|
27
|
-
|
|
28
|
-
import {
|
|
29
|
-
ailkListPages,
|
|
30
|
-
contentListParamsSchema,
|
|
31
|
-
contentListQuerySchema,
|
|
32
|
-
contentListResultSchema,
|
|
33
|
-
} from "../src/tools/list_pages.js";
|
|
34
|
-
import {
|
|
35
|
-
__setMcpPublicWorkspaceForTest,
|
|
36
|
-
resetMcpPublicWorkspace,
|
|
37
|
-
} from "../src/lib/public-workspace.js";
|
|
38
|
-
|
|
39
|
-
// Content root for real-filesystem tests — repo-relative
|
|
40
|
-
const REPO_ROOT = resolve(__dirname, "../../..");
|
|
41
|
-
const CONTENT_ROOT = join(REPO_ROOT, "content");
|
|
42
|
-
const WORKSPACE_ID = "wksp_00000000-0000-7000-8000-000000000001";
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* A structural `ArtifactPrismaClient` stub (#5876 spec D11) — a published
|
|
46
|
-
* HomePage plus a draft-only HomePage that must never surface (AC-1's
|
|
47
|
-
* published-only half is a reach test — the invariant is the adapter's).
|
|
48
|
-
*/
|
|
49
|
-
function makeArtifactPrismaClientStub(): ArtifactPrismaClient {
|
|
50
|
-
return {
|
|
51
|
-
artifact: {
|
|
52
|
-
findFirst: jest.fn(),
|
|
53
|
-
findMany: jest.fn().mockResolvedValue([
|
|
54
|
-
{
|
|
55
|
-
id: "artifact_published",
|
|
56
|
-
workspaceId: WORKSPACE_ID,
|
|
57
|
-
contentType: "text/page",
|
|
58
|
-
locale: "en",
|
|
59
|
-
slug: "home",
|
|
60
|
-
title: "Home",
|
|
61
|
-
publishedVersionId: "version_published",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
id: "artifact_draft",
|
|
65
|
-
workspaceId: WORKSPACE_ID,
|
|
66
|
-
contentType: "text/page",
|
|
67
|
-
locale: "en",
|
|
68
|
-
slug: "draft-page",
|
|
69
|
-
title: "Draft Page",
|
|
70
|
-
publishedVersionId: null,
|
|
71
|
-
},
|
|
72
|
-
]),
|
|
73
|
-
create: jest.fn(),
|
|
74
|
-
updateMany: jest.fn(),
|
|
75
|
-
deleteMany: jest.fn(),
|
|
76
|
-
},
|
|
77
|
-
artifactVersion: {
|
|
78
|
-
findFirst: jest.fn(),
|
|
79
|
-
// Only the PUBLISHED version's row is ever returned — the adapter
|
|
80
|
-
// filters publishedIds to non-null before this query, so a draft-only
|
|
81
|
-
// artifact's version id never appears in the `id: { in: [...] }` set.
|
|
82
|
-
findMany: jest.fn().mockResolvedValue([
|
|
83
|
-
{
|
|
84
|
-
id: "version_published",
|
|
85
|
-
artifactId: "artifact_published",
|
|
86
|
-
workspaceId: WORKSPACE_ID,
|
|
87
|
-
content: {
|
|
88
|
-
type: "HomePage",
|
|
89
|
-
slug: "home",
|
|
90
|
-
title: "Home",
|
|
91
|
-
description: "The homepage.",
|
|
92
|
-
body: "# Hello",
|
|
93
|
-
},
|
|
94
|
-
isCurrent: false,
|
|
95
|
-
},
|
|
96
|
-
]),
|
|
97
|
-
create: jest.fn(),
|
|
98
|
-
updateMany: jest.fn(),
|
|
99
|
-
},
|
|
100
|
-
$transaction: jest.fn(),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
describe("contentListParamsSchema", () => {
|
|
105
|
-
it("requires type (#7168 — the route's required param)", () => {
|
|
106
|
-
const result = contentListParamsSchema.safeParse({});
|
|
107
|
-
expect(result.success).toBe(false);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("accepts a valid SchemaOrgType", () => {
|
|
111
|
-
const result = contentListParamsSchema.safeParse({ type: "HomePage" });
|
|
112
|
-
expect(result.success).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it("accepts HomePage", () => {
|
|
116
|
-
const result = contentListParamsSchema.safeParse({ type: "HomePage" });
|
|
117
|
-
expect(result.success).toBe(true);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("rejects an unknown type string", () => {
|
|
121
|
-
const result = contentListParamsSchema.safeParse({ type: "NotAType" });
|
|
122
|
-
expect(result.success).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("rejects a numeric type", () => {
|
|
126
|
-
const result = contentListParamsSchema.safeParse({ type: 42 });
|
|
127
|
-
expect(result.success).toBe(false);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe("contentListQuerySchema", () => {
|
|
132
|
-
it("accepts an empty window (page and pageSize are optional)", () => {
|
|
133
|
-
const result = contentListQuerySchema.safeParse({});
|
|
134
|
-
expect(result.success).toBe(true);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("coerces a string page and pageSize, as the route's query string parses", () => {
|
|
138
|
-
const result = contentListQuerySchema.safeParse({ page: "2", pageSize: "5" });
|
|
139
|
-
expect(result.success).toBe(true);
|
|
140
|
-
expect(result.data).toEqual({ page: 2, pageSize: 5 });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("rejects page 0 and pageSize 0", () => {
|
|
144
|
-
expect(contentListQuerySchema.safeParse({ page: 0 }).success).toBe(false);
|
|
145
|
-
expect(contentListQuerySchema.safeParse({ pageSize: 0 }).success).toBe(false);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("admits pageSize 500 — the clamp to 100 is the builder's, not a 400 (AC-13)", () => {
|
|
149
|
-
expect(contentListQuerySchema.safeParse({ pageSize: 500 }).success).toBe(true);
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe("ailkListPages handler", () => {
|
|
154
|
-
it("returns the route's paginated ItemList for a specific type", async () => {
|
|
155
|
-
const result = await ailkListPages({ type: "HomePage" }, CONTENT_ROOT);
|
|
156
|
-
|
|
157
|
-
expect(result["@context"]).toBe("https://schema.org");
|
|
158
|
-
expect(result["@type"]).toBe("ItemList");
|
|
159
|
-
expect(result.type).toBe("HomePage");
|
|
160
|
-
expect(Array.isArray(result.items)).toBe(true);
|
|
161
|
-
// The real content/ tree has at least one HomePage
|
|
162
|
-
expect(result.items.length).toBeGreaterThan(0);
|
|
163
|
-
for (const page of result.items) {
|
|
164
|
-
expect(page.type).toBe("HomePage");
|
|
165
|
-
expect(typeof page.slug).toBe("string");
|
|
166
|
-
expect(typeof page.title).toBe("string");
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("defaults the window to page 1 / pageSize 20, as the route does", async () => {
|
|
171
|
-
const result = await ailkListPages({ type: "HomePage" }, CONTENT_ROOT);
|
|
172
|
-
expect(result.pagination).toEqual({
|
|
173
|
-
page: 1,
|
|
174
|
-
pageSize: 20,
|
|
175
|
-
totalItems: result.items.length,
|
|
176
|
-
totalPages: 1,
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("returns an empty ItemList for a type with no content", async () => {
|
|
181
|
-
// An empty content root of its own (#9422): a scaffold's content/ seeds
|
|
182
|
-
// TeamMember placeholders (#8850), so the repo's tree cannot stand in.
|
|
183
|
-
const emptyRoot = mkdtempSync(join(tmpdir(), "list-pages-empty-"));
|
|
184
|
-
const result = await ailkListPages({ type: "TeamMember" }, emptyRoot);
|
|
185
|
-
rmSync(emptyRoot, { recursive: true, force: true });
|
|
186
|
-
expect(result.items).toEqual([]);
|
|
187
|
-
expect(result.pagination.totalItems).toBe(0);
|
|
188
|
-
expect(result.pagination.totalPages).toBe(1);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it("clamps pageSize 500 to 100 in pagination.pageSize (AC-13)", async () => {
|
|
192
|
-
const result = await ailkListPages(
|
|
193
|
-
{ type: "HomePage", pageSize: 500 },
|
|
194
|
-
CONTENT_ROOT,
|
|
195
|
-
);
|
|
196
|
-
expect(result.pagination.pageSize).toBe(100);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it("output validates against contentListResultSchema", async () => {
|
|
200
|
-
const result = await ailkListPages({ type: "HomePage" }, CONTENT_ROOT);
|
|
201
|
-
const parsed = contentListResultSchema.safeParse(result);
|
|
202
|
-
expect(parsed.success).toBe(true);
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe("contentListParamsSchema — Zod boundary security", () => {
|
|
207
|
-
it("rejects input with path traversal characters in type", () => {
|
|
208
|
-
const result = contentListParamsSchema.safeParse({ type: "../etc/passwd" });
|
|
209
|
-
expect(result.success).toBe(false);
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
describe("ailkListPages — CONTENT_ADAPTER=database (#5876)", () => {
|
|
214
|
-
const previous = process.env.CONTENT_ADAPTER;
|
|
215
|
-
|
|
216
|
-
beforeEach(() => {
|
|
217
|
-
process.env.CONTENT_ADAPTER = "database";
|
|
218
|
-
resetResolvedContentAdapter();
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
afterEach(() => {
|
|
222
|
-
if (previous === undefined) delete process.env.CONTENT_ADAPTER;
|
|
223
|
-
else process.env.CONTENT_ADAPTER = previous;
|
|
224
|
-
resetMcpPublicWorkspace();
|
|
225
|
-
resetResolvedContentAdapter();
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it("AC-1: lists only published pages", async () => {
|
|
229
|
-
const stub = makeArtifactPrismaClientStub();
|
|
230
|
-
__setMcpPublicWorkspaceForTest({
|
|
231
|
-
kind: "resolved",
|
|
232
|
-
workspaceId: WORKSPACE_ID,
|
|
233
|
-
prisma: stub,
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
const result = await ailkListPages({ type: "HomePage" });
|
|
237
|
-
|
|
238
|
-
expect(result.items).toEqual([
|
|
239
|
-
expect.objectContaining({ slug: "home", type: "HomePage" }),
|
|
240
|
-
]);
|
|
241
|
-
expect(stub.artifact.findMany).toHaveBeenCalledWith(
|
|
242
|
-
expect.objectContaining({
|
|
243
|
-
where: expect.objectContaining({ workspaceId: WORKSPACE_ID }),
|
|
244
|
-
}),
|
|
245
|
-
);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it("AC-2: returns the empty ItemList when the workspace is unresolved, with no query", async () => {
|
|
249
|
-
const stub = makeArtifactPrismaClientStub();
|
|
250
|
-
__setMcpPublicWorkspaceForTest({ kind: "unresolved", reason: "ambiguous" });
|
|
251
|
-
|
|
252
|
-
const result = await ailkListPages({ type: "HomePage" });
|
|
253
|
-
|
|
254
|
-
expect(result.items).toEqual([]);
|
|
255
|
-
expect(result.pagination.totalItems).toBe(0);
|
|
256
|
-
expect(stub.artifact.findMany).not.toHaveBeenCalled();
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
describe("architectural guard — no console calls", () => {
|
|
261
|
-
it("apps/mcp/src/tools/list_pages.ts does not call console.*", () => {
|
|
262
|
-
const src = readFileSync(
|
|
263
|
-
resolve(__dirname, "../src/tools/list_pages.ts"),
|
|
264
|
-
"utf-8",
|
|
265
|
-
);
|
|
266
|
-
expect(src).not.toMatch(/\bconsole\.(log|warn|error|info|debug)\b/);
|
|
267
|
-
});
|
|
268
|
-
});
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the locale parameter on content read MCP tools (Phase 3 S3).
|
|
3
|
-
*
|
|
4
|
-
* Acceptance criteria verified here:
|
|
5
|
-
* - read_content accepts an optional `locale` parameter
|
|
6
|
-
* - list_pages accepts an optional `locale` parameter
|
|
7
|
-
* - search_content accepts an optional `locale` parameter
|
|
8
|
-
* - Tool schemas accept any string `locale`, as the routes' do — the
|
|
9
|
-
* allowlist is the handler's `resolveLocale`, never the schema (#7167 DD1,
|
|
10
|
-
* the operator's decision of 2026-10-19: the tool adopted the API's
|
|
11
|
-
* arguments, so a malformed tag falls back silently instead of being
|
|
12
|
-
* refused)
|
|
13
|
-
* - Tool handlers return data when valid locale is passed (back-compat)
|
|
14
|
-
* - Invalid/unknown locales silently fall back to default (AC-i18n-07)
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { resolve, join } from "node:path";
|
|
18
|
-
|
|
19
|
-
import {
|
|
20
|
-
contentListParamsSchema,
|
|
21
|
-
contentListQuerySchema,
|
|
22
|
-
contentPageParamsSchema,
|
|
23
|
-
contentPageQuerySchema,
|
|
24
|
-
contentSearchQuerySchema,
|
|
25
|
-
} from "@working-theory/validation";
|
|
26
|
-
|
|
27
|
-
import { ailkListPages } from "../src/tools/list_pages.js";
|
|
28
|
-
import { ailkReadContent } from "../src/tools/read_content.js";
|
|
29
|
-
import { ailkSearchContent } from "../src/tools/search_content.js";
|
|
30
|
-
|
|
31
|
-
const REPO_ROOT = resolve(__dirname, "../../..");
|
|
32
|
-
const CONTENT_ROOT = join(REPO_ROOT, "content");
|
|
33
|
-
|
|
34
|
-
describe("locale parameter — input schemas", () => {
|
|
35
|
-
it("contentPageParamsSchema + contentPageQuerySchema accept a valid BCP-47 tag", () => {
|
|
36
|
-
expect(
|
|
37
|
-
contentPageParamsSchema.safeParse({ type: "HomePage", slug: "home" }).success,
|
|
38
|
-
).toBe(true);
|
|
39
|
-
expect(contentPageQuerySchema.safeParse({ locale: "en" }).success).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("contentPageQuerySchema accepts region-tagged BCP-47 (zh-CN)", () => {
|
|
43
|
-
expect(contentPageQuerySchema.safeParse({ locale: "zh-CN" }).success).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// #7167 DD1 — the route's `locale` is a bare optional string, and the tool
|
|
47
|
-
// parses the same export: a malformed tag is admitted here and falls back
|
|
48
|
-
// silently in the handler (`resolveLocale`), as it does on the route.
|
|
49
|
-
it("contentPageQuerySchema admits a malformed locale (uppercase) — the handler falls back", () => {
|
|
50
|
-
expect(contentPageQuerySchema.safeParse({ locale: "EN" }).success).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("contentPageQuerySchema admits a path-traversal-shaped locale — the handler falls back, never the filesystem", () => {
|
|
54
|
-
expect(
|
|
55
|
-
contentPageQuerySchema.safeParse({ locale: "../../etc/passwd" }).success,
|
|
56
|
-
).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("contentPageQuerySchema accepts absent locale (optional)", () => {
|
|
60
|
-
expect(contentPageQuerySchema.safeParse({}).success).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("contentListParamsSchema + contentListQuerySchema accept a valid locale", () => {
|
|
64
|
-
expect(contentListParamsSchema.safeParse({ type: "HomePage" }).success).toBe(true);
|
|
65
|
-
expect(contentListQuerySchema.safeParse({ locale: "en" }).success).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("contentSearchQuerySchema accepts a valid locale", () => {
|
|
69
|
-
const r = contentSearchQuerySchema.safeParse({
|
|
70
|
-
q: "foo",
|
|
71
|
-
locale: "en",
|
|
72
|
-
});
|
|
73
|
-
expect(r.success).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("locale parameter — handler behavior (real adapter)", () => {
|
|
78
|
-
it("ailkReadContent returns the page when locale=en", async () => {
|
|
79
|
-
const result = await ailkReadContent(
|
|
80
|
-
{ type: "HomePage", slug: "home", locale: "en" },
|
|
81
|
-
CONTENT_ROOT,
|
|
82
|
-
);
|
|
83
|
-
expect(result).toHaveProperty("page", expect.objectContaining({ slug: "home" }));
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("ailkReadContent silently falls back when locale=zz (unknown)", async () => {
|
|
87
|
-
const result = await ailkReadContent(
|
|
88
|
-
{ type: "HomePage", slug: "home", locale: "zz" },
|
|
89
|
-
CONTENT_ROOT,
|
|
90
|
-
);
|
|
91
|
-
// AC-i18n-07: silent fallback to default locale's content.
|
|
92
|
-
expect(result).toHaveProperty("page", expect.objectContaining({ slug: "home" }));
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("ailkListPages returns pages when locale=en", async () => {
|
|
96
|
-
const result = await ailkListPages(
|
|
97
|
-
{ type: "HomePage", locale: "en" },
|
|
98
|
-
CONTENT_ROOT,
|
|
99
|
-
);
|
|
100
|
-
expect(Array.isArray(result.items)).toBe(true);
|
|
101
|
-
expect(result.items.length).toBeGreaterThan(0);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("ailkListPages silently falls back when locale=zz", async () => {
|
|
105
|
-
const result = await ailkListPages(
|
|
106
|
-
{ type: "HomePage", locale: "zz" },
|
|
107
|
-
CONTENT_ROOT,
|
|
108
|
-
);
|
|
109
|
-
// Falls back to default-locale list.
|
|
110
|
-
expect(Array.isArray(result.items)).toBe(true);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("ailkSearchContent returns results when locale=en", async () => {
|
|
114
|
-
const result = await ailkSearchContent(
|
|
115
|
-
{ q: "AI", locale: "en" },
|
|
116
|
-
CONTENT_ROOT,
|
|
117
|
-
);
|
|
118
|
-
expect(Array.isArray(result.items)).toBe(true);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module-exclusion regression test (S1, #5088).
|
|
3
|
-
*
|
|
4
|
-
* Proves the mechanical claim card S1 exists to make true: when a paid
|
|
5
|
-
* module is excluded (`AILK_ENABLED_MODULES` omits it), none of the MCP
|
|
6
|
-
* tools that module contributes survive registration — the runtime half of
|
|
7
|
-
* "a tool and its apps/api route appear or vanish together" (API↔MCP
|
|
8
|
-
* parity). `packages/metadata/src/mcp-tool-catalog.ts`'s `module` field on
|
|
9
|
-
* each `TOOLS` entry is the map this test walks; it is not a second,
|
|
10
|
-
* hand-maintained list.
|
|
11
|
-
*
|
|
12
|
-
* Reverting the `shouldRegister` module filter in `../src/server.ts` (while
|
|
13
|
-
* leaving the `OSS_DISABLED_TOOLS` check alone) makes this test fail RED —
|
|
14
|
-
* see #5088 S1 verification notes.
|
|
15
|
-
*
|
|
16
|
-
* #7136: the module filter stays independent of the licence-feature gate —
|
|
17
|
-
* the matrix below also runs in refuse mode with every feature held. The
|
|
18
|
-
* catalog enumerations pin `featureGate: "warn"`, so they list every
|
|
19
|
-
* module-tagged tool whichever way `MCP_FEATURE_GATE_MODE` is set and can
|
|
20
|
-
* never iterate nothing.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { getMcpToolRegistrations } from "@working-theory/metadata";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
__setMcpFeatureGateForTest,
|
|
27
|
-
__setMcpHeldFeaturesForTest,
|
|
28
|
-
resetMcpCommerceClaim,
|
|
29
|
-
} from "../src/lib/commerce-claim.js";
|
|
30
|
-
import { createMcpServer, listRegisteredTools } from "../src/server.js";
|
|
31
|
-
|
|
32
|
-
// `content-write` left this list in #5853: its three tools (create_page /
|
|
33
|
-
// update_page / delete_page) were deleted with the untenanted HTTP routes they
|
|
34
|
-
// twinned, so the module now owns NO catalog tool at all and the
|
|
35
|
-
// "owns at least one" fixture check below would fail for it. The flag itself
|
|
36
|
-
// is unchanged — it still gates the tenant-guarded editor routes in apps/api
|
|
37
|
-
// (D8), which this MCP-side matrix has never covered.
|
|
38
|
-
const PAID_MODULES = ["scheduling", "signal-collectors"] as const;
|
|
39
|
-
|
|
40
|
-
/** Every module-tagged tool in the catalog, whatever the gate mode. */
|
|
41
|
-
function catalogRegistrations() {
|
|
42
|
-
return getMcpToolRegistrations({ featureGate: "warn" });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function withEnabledModules<T>(enabled: string, fn: () => T): T {
|
|
46
|
-
const prior = process.env.AILK_ENABLED_MODULES;
|
|
47
|
-
process.env.AILK_ENABLED_MODULES = enabled;
|
|
48
|
-
try {
|
|
49
|
-
return fn();
|
|
50
|
-
} finally {
|
|
51
|
-
if (prior === undefined) {
|
|
52
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
53
|
-
} else {
|
|
54
|
-
process.env.AILK_ENABLED_MODULES = prior;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
describe("MCP tool registration — module exclusion (S1, #5088)", () => {
|
|
60
|
-
afterEach(() => {
|
|
61
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("every module-tagged tool in the catalog names one of the modules this test covers", () => {
|
|
65
|
-
// Guards the test itself against drift: a future module tag added to
|
|
66
|
-
// the catalog without a matching entry here would silently go
|
|
67
|
-
// unverified.
|
|
68
|
-
const taggedModules = new Set(
|
|
69
|
-
catalogRegistrations()
|
|
70
|
-
.map((reg) => reg.module)
|
|
71
|
-
.filter((m): m is string => Boolean(m)),
|
|
72
|
-
);
|
|
73
|
-
expect(taggedModules.size).toBeGreaterThan(0);
|
|
74
|
-
for (const m of taggedModules) {
|
|
75
|
-
expect(PAID_MODULES).toContain(m);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it.each(PAID_MODULES)(
|
|
80
|
-
"excluding '%s' registers none of its tools",
|
|
81
|
-
(excluded) => {
|
|
82
|
-
const enabledModules = PAID_MODULES.filter((m) => m !== excluded).join(
|
|
83
|
-
",",
|
|
84
|
-
);
|
|
85
|
-
const excludedToolNames = catalogRegistrations()
|
|
86
|
-
.filter((reg) => reg.module === excluded)
|
|
87
|
-
.map((reg) => reg.name);
|
|
88
|
-
// Sanity check the fixture: every module this test parametrizes over
|
|
89
|
-
// actually owns at least one catalog tool, or the assertion below
|
|
90
|
-
// would vacuously pass.
|
|
91
|
-
expect(excludedToolNames.length).toBeGreaterThan(0);
|
|
92
|
-
|
|
93
|
-
const registeredNames = withEnabledModules(enabledModules, () =>
|
|
94
|
-
listRegisteredTools().map((t) => t.name),
|
|
95
|
-
);
|
|
96
|
-
for (const name of excludedToolNames) {
|
|
97
|
-
expect(registeredNames).not.toContain(name);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const server = withEnabledModules(enabledModules, () =>
|
|
101
|
-
createMcpServer(),
|
|
102
|
-
);
|
|
103
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- mirrors apps/mcp/__tests__/catalog-drift.test.ts
|
|
104
|
-
const registered = (server as any)._registeredTools as Record<
|
|
105
|
-
string,
|
|
106
|
-
unknown
|
|
107
|
-
>;
|
|
108
|
-
for (const name of excludedToolNames) {
|
|
109
|
-
expect(name in registered).toBe(false);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
it("with every module enabled, all module-tagged tools register (no over-exclusion)", () => {
|
|
115
|
-
const enabledModules = PAID_MODULES.join(",");
|
|
116
|
-
const registeredNames = new Set(
|
|
117
|
-
withEnabledModules(enabledModules, () =>
|
|
118
|
-
listRegisteredTools().map((t) => t.name),
|
|
119
|
-
),
|
|
120
|
-
);
|
|
121
|
-
const taggedNames = catalogRegistrations()
|
|
122
|
-
.filter((reg) => reg.module)
|
|
123
|
-
.map((reg) => reg.name);
|
|
124
|
-
expect(taggedNames.length).toBeGreaterThan(0);
|
|
125
|
-
for (const name of taggedNames) {
|
|
126
|
-
expect(registeredNames).toContain(name);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe("module exclusion is independent of the licence-feature gate (#7136)", () => {
|
|
132
|
-
beforeEach(() => {
|
|
133
|
-
__setMcpFeatureGateForTest("refuse");
|
|
134
|
-
__setMcpHeldFeaturesForTest(["scheduling", "flows-deliverables"]);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
afterEach(() => {
|
|
138
|
-
resetMcpCommerceClaim();
|
|
139
|
-
delete process.env.AILK_ENABLED_MODULES;
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it.each(PAID_MODULES)(
|
|
143
|
-
"refuse mode, every feature held: excluding '%s' still registers none of its tools",
|
|
144
|
-
(excluded) => {
|
|
145
|
-
const enabledModules = PAID_MODULES.filter((m) => m !== excluded).join(
|
|
146
|
-
",",
|
|
147
|
-
);
|
|
148
|
-
const excludedToolNames = catalogRegistrations()
|
|
149
|
-
.filter((reg) => reg.module === excluded)
|
|
150
|
-
.map((reg) => reg.name);
|
|
151
|
-
expect(excludedToolNames.length).toBeGreaterThan(0);
|
|
152
|
-
|
|
153
|
-
const registeredNames = withEnabledModules(enabledModules, () =>
|
|
154
|
-
listRegisteredTools().map((t) => t.name),
|
|
155
|
-
);
|
|
156
|
-
for (const name of excludedToolNames) {
|
|
157
|
-
expect(registeredNames).not.toContain(name);
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
it("refuse mode, every feature held, both modules enabled: all six register", () => {
|
|
163
|
-
const featureTools = catalogRegistrations()
|
|
164
|
-
.filter((reg) => reg.feature)
|
|
165
|
-
.map((reg) => reg.name);
|
|
166
|
-
expect(featureTools).toHaveLength(6);
|
|
167
|
-
|
|
168
|
-
const registeredNames = withEnabledModules(PAID_MODULES.join(","), () =>
|
|
169
|
-
listRegisteredTools().map((t) => t.name),
|
|
170
|
-
);
|
|
171
|
-
for (const name of featureTools) {
|
|
172
|
-
expect(registeredNames).toContain(name);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
});
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `start_purchase` visibility — the commerce add-on claim matrix (#5971).
|
|
3
|
-
*
|
|
4
|
-
* Supersedes S15a (#610), which asserted blanket absence while
|
|
5
|
-
* `OSS_DISABLED_TOOLS` carried the name. The gate is now the deployment's
|
|
6
|
-
* `commerce` licence claim, so the assertion is a MATRIX, not an absence:
|
|
7
|
-
*
|
|
8
|
-
* keyless (no claim) → absent from `listRegisteredTools()` and from
|
|
9
|
-
* `createMcpServer()._registeredTools`, and calling `ailkPurchase` BY
|
|
10
|
-
* NAME returns the module-disabled body with no `checkout.createSession`
|
|
11
|
-
* call;
|
|
12
|
-
* keyed (claim held) → present in both surfaces.
|
|
13
|
-
*
|
|
14
|
-
* Both halves are driven through `__setMcpCommerceClaimForTest()`, the same
|
|
15
|
-
* injector idiom `lib/public-workspace.ts` established (#5876). No test
|
|
16
|
-
* reaches a licence server.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { checkout } from "@working-theory/api-client";
|
|
20
|
-
|
|
21
|
-
import {
|
|
22
|
-
__setMcpCommerceClaimForTest,
|
|
23
|
-
resetMcpCommerceClaim,
|
|
24
|
-
} from "../src/lib/commerce-claim.js";
|
|
25
|
-
import { createMcpServer, listRegisteredTools } from "../src/server.js";
|
|
26
|
-
import { ailkPurchase } from "../src/tools/purchase.js";
|
|
27
|
-
|
|
28
|
-
jest.mock("@working-theory/api-client", () => ({
|
|
29
|
-
checkout: { createSession: jest.fn() },
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
const createSession = checkout.createSession as jest.MockedFunction<
|
|
33
|
-
typeof checkout.createSession
|
|
34
|
-
>;
|
|
35
|
-
|
|
36
|
-
function registeredNames(): string[] {
|
|
37
|
-
const server = createMcpServer();
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- #506/#507: pre-existing test-hygiene violation
|
|
39
|
-
const tools = (server as any)._registeredTools as Record<string, unknown>;
|
|
40
|
-
return Object.keys(tools);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
afterEach(() => {
|
|
44
|
-
jest.clearAllMocks();
|
|
45
|
-
resetMcpCommerceClaim();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe("start_purchase — keyless site (no commerce claim)", () => {
|
|
49
|
-
beforeEach(() => {
|
|
50
|
-
__setMcpCommerceClaimForTest("unclaimed");
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("is NOT in listRegisteredTools()", () => {
|
|
54
|
-
expect(listRegisteredTools().map((t) => t.name)).not.toContain(
|
|
55
|
-
"start_purchase",
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("is NOT in createMcpServer()._registeredTools", () => {
|
|
60
|
-
expect(registeredNames()).not.toContain("start_purchase");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("calling it by name returns the module-disabled body and creates no session", async () => {
|
|
64
|
-
const result = await ailkPurchase({ productCode: "pro-plan" });
|
|
65
|
-
|
|
66
|
-
expect(result).toEqual({ error: "not_found", message: "Not found" });
|
|
67
|
-
expect(createSession).not.toHaveBeenCalled();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("the module-disabled body does not hint that a licence gate exists", async () => {
|
|
71
|
-
const result = await ailkPurchase({ productCode: "pro-plan" });
|
|
72
|
-
|
|
73
|
-
expect(JSON.stringify(result)).not.toMatch(/commerce|licen[cs]e|claim/i);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("start_purchase — keyed site (commerce claim held)", () => {
|
|
78
|
-
beforeEach(() => {
|
|
79
|
-
__setMcpCommerceClaimForTest("claimed");
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("IS in listRegisteredTools()", () => {
|
|
83
|
-
expect(listRegisteredTools().map((t) => t.name)).toContain(
|
|
84
|
-
"start_purchase",
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("IS in createMcpServer()._registeredTools", () => {
|
|
89
|
-
expect(registeredNames()).toContain("start_purchase");
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe("fail-closed default", () => {
|
|
94
|
-
it("the un-initialised module state is unclaimed", () => {
|
|
95
|
-
// No injector call — this is the state a boot that never resolved the
|
|
96
|
-
// licence (or resolved it to a rejection) leaves behind.
|
|
97
|
-
expect(listRegisteredTools().map((t) => t.name)).not.toContain(
|
|
98
|
-
"start_purchase",
|
|
99
|
-
);
|
|
100
|
-
});
|
|
101
|
-
});
|