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,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The testable part of the Vercel entry (#8070 D2, D5).
|
|
3
|
-
*
|
|
4
|
-
* `src/app.ts` is the thin file Vercel's Node-backend detection finds: it
|
|
5
|
-
* awaits the boot at module level and default-exports the
|
|
6
|
-
* {@link serverlessHandler} for the app. A module-level
|
|
7
|
-
* `await` does not compile under the package's ts-jest CommonJS preset, so
|
|
8
|
-
* everything app.ts does beyond that lives here, where a test can build the
|
|
9
|
-
* same app (`__tests__/app-entry.test.ts`).
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
13
|
-
|
|
14
|
-
import type { FastifyInstance } from "fastify";
|
|
15
|
-
|
|
16
|
-
import { httpTransportConfigFromEnv, readStatelessEnv } from "./boot.js";
|
|
17
|
-
import { registerHttpTransport } from "./http-transport.js";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Trust exactly one proxy hop — the immediate peer — and nothing behind it
|
|
21
|
-
* (D5). Fastify then takes `request.ip` from the LAST `X-Forwarded-For`
|
|
22
|
-
* entry, the address Vercel's edge saw, and a value a caller writes earlier
|
|
23
|
-
* in the header cannot move it.
|
|
24
|
-
*
|
|
25
|
-
* A function, not `trustProxy: 1`: Fastify 5.12 treats a numeric hop count as
|
|
26
|
-
* trust-nothing ("hop-count-only trust cannot validate the immediate peer"),
|
|
27
|
-
* so `1` would silently key every caller on the edge's address. A hop-only
|
|
28
|
-
* function is safe here for the reason Fastify's warning names: a Vercel
|
|
29
|
-
* function cannot be reached except through Vercel's edge, so its immediate
|
|
30
|
-
* peer is always the edge. It would NOT be safe on a host a client can reach
|
|
31
|
-
* directly — which is why the long-running entry (`buildHttpTransportApp`)
|
|
32
|
-
* sets no `trustProxy` at all.
|
|
33
|
-
*
|
|
34
|
-
* Trusting hop 0 also makes `request.host` and `request.protocol` follow
|
|
35
|
-
* `X-Forwarded-Host` / `X-Forwarded-Proto`. Nothing in apps/mcp reads either
|
|
36
|
-
* today; anything that starts to must remember they come from the edge.
|
|
37
|
-
*/
|
|
38
|
-
export function trustOneHop(_address: string, hop: number): boolean {
|
|
39
|
-
return hop === 0;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The Fastify options the Vercel entry builds its app with: no logger, and
|
|
44
|
-
* {@link trustOneHop} — so the per-IP rate limit and the daily caps key on
|
|
45
|
-
* the real caller. That holds for the topology the sites deploy: the MCP host
|
|
46
|
-
* name points straight at the Vercel project. A second proxy in front
|
|
47
|
-
* (Cloudflare in proxied mode, a rewrite from another Vercel project) would
|
|
48
|
-
* make every caller that proxy's address.
|
|
49
|
-
*/
|
|
50
|
-
export const SERVERLESS_FASTIFY_OPTIONS = {
|
|
51
|
-
logger: false,
|
|
52
|
-
trustProxy: trustOneHop,
|
|
53
|
-
} as const;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Register the MCP HTTP transport on the Vercel entry's app, from the
|
|
57
|
-
* environment. Stateless unless `MCP_HTTP_STATELESS` says otherwise (D1): a
|
|
58
|
-
* stateful transport keeps its sessions in one instance's memory, which a
|
|
59
|
-
* multi-instance host cannot honour. The port is read and ignored — Vercel
|
|
60
|
-
* calls the exported {@link serverlessHandler} and nothing listens.
|
|
61
|
-
*/
|
|
62
|
-
export async function configureServerlessApp(
|
|
63
|
-
app: FastifyInstance,
|
|
64
|
-
): Promise<void> {
|
|
65
|
-
const { port: _port, ...config } = httpTransportConfigFromEnv();
|
|
66
|
-
await registerHttpTransport(app, {
|
|
67
|
-
...config,
|
|
68
|
-
stateless: readStatelessEnv(true),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* The `(req, res)` function the Vercel entry default-exports (#8070 D2,
|
|
74
|
-
* amendment 2). Vercel's Node runtime accepts a request function, an object of
|
|
75
|
-
* web handlers, or an `http.Server` the module starts listening — a Fastify
|
|
76
|
-
* instance is none of these, and exporting one answered every request with a
|
|
77
|
-
* 500. `app.server` is the `http.Server` Fastify builds without listening;
|
|
78
|
-
* emitting `request` on it is Fastify's own request path, so routing,
|
|
79
|
-
* `trustProxy` and every hook behave as on a listening server. The app must
|
|
80
|
-
* already be `ready()`.
|
|
81
|
-
*/
|
|
82
|
-
export function serverlessHandler(
|
|
83
|
-
app: FastifyInstance,
|
|
84
|
-
): (req: IncomingMessage, res: ServerResponse) => void {
|
|
85
|
-
return (req, res) => {
|
|
86
|
-
app.server.emit("request", req, res);
|
|
87
|
-
};
|
|
88
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* audit — runs the AEO Layer 1 scoring engine against a single page.
|
|
3
|
-
*
|
|
4
|
-
* Pure read: imports runAudit from @working-theory/aeo (ADR 0011). No auth required.
|
|
5
|
-
* The adapter (audit-single-page) resolves URL or slug to a filesystem read;
|
|
6
|
-
* no fetch() is called anywhere in this file or the adapter.
|
|
7
|
-
*
|
|
8
|
-
* Input: { slug, type? } | { url }
|
|
9
|
-
* slug branch — lowercase [a-z0-9-]+ slug; type optional (defaults BlogPosting)
|
|
10
|
-
* url branch — absolute URL on the AILK installation's own domain only
|
|
11
|
-
* (same-origin check uses AILK_BASE_URL || NEXT_PUBLIC_BASE_URL)
|
|
12
|
-
*
|
|
13
|
-
* Output: { score, perRule, perPage, meta }
|
|
14
|
-
* score — 0–100 overall
|
|
15
|
-
* perRule — per-rule breakdown (id, name, weight, status, evidence?, advice?)
|
|
16
|
-
* perPage — per-page summary (slug, type, score)
|
|
17
|
-
* meta — { auditedAt, ruleSet, locale }
|
|
18
|
-
*
|
|
19
|
-
* Session/scope: none — read-only public content.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
runAudit,
|
|
24
|
-
alwaysFails,
|
|
25
|
-
alwaysPasses,
|
|
26
|
-
entityMarkup,
|
|
27
|
-
faqHowtoIncentive,
|
|
28
|
-
jsonldValidity,
|
|
29
|
-
offerOnPricedPage,
|
|
30
|
-
policiesPresent,
|
|
31
|
-
schemaCoverage,
|
|
32
|
-
taxCodeWhenStripeTax,
|
|
33
|
-
type Rule,
|
|
34
|
-
} from "@working-theory/aeo";
|
|
35
|
-
import {
|
|
36
|
-
auditInputSchema,
|
|
37
|
-
auditOutputSchema,
|
|
38
|
-
type AuditInput,
|
|
39
|
-
type AuditOutput,
|
|
40
|
-
} from "@working-theory/validation";
|
|
41
|
-
|
|
42
|
-
import {
|
|
43
|
-
buildSinglePageAuditInput,
|
|
44
|
-
type SinglePageInput,
|
|
45
|
-
} from "../lib/audit-single-page.js";
|
|
46
|
-
|
|
47
|
-
export { auditInputSchema, auditOutputSchema };
|
|
48
|
-
export type { AuditInput, AuditOutput };
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* The MCP audit's rule set. Imported from the @working-theory/aeo public API;
|
|
52
|
-
* must not be re-implemented here.
|
|
53
|
-
*
|
|
54
|
-
* It is NOT identical to `packages/aeo/src/cli/index.ts`'s RULES array, and
|
|
55
|
-
* this comment used to claim it was. The two differ by exactly one member:
|
|
56
|
-
* the CLI carries `schemaCorrectness` (10 rules) and this set does not
|
|
57
|
-
* (9 rules). Everything else — including the two `always-*` example rules —
|
|
58
|
-
* is shared.
|
|
59
|
-
*
|
|
60
|
-
* The cause is mechanical, not a choice: `packages/aeo/src/index.ts` — the
|
|
61
|
-
* package's PUBLIC barrel — does not re-export `schemaCorrectness`, while
|
|
62
|
-
* `rules/index.ts` (the internal barrel the CLI imports from) exports all of
|
|
63
|
-
* them. A rule absent from the public barrel is unreachable from any app.
|
|
64
|
-
* Closing that gap would change this tool's `score` on every page, which is
|
|
65
|
-
* why #5949 left it alone; it is recorded as that spec's residual 1.
|
|
66
|
-
*/
|
|
67
|
-
const RULES: Rule[] = [
|
|
68
|
-
alwaysPasses,
|
|
69
|
-
alwaysFails,
|
|
70
|
-
schemaCoverage,
|
|
71
|
-
jsonldValidity,
|
|
72
|
-
faqHowtoIncentive,
|
|
73
|
-
entityMarkup,
|
|
74
|
-
policiesPresent,
|
|
75
|
-
offerOnPricedPage,
|
|
76
|
-
taxCodeWhenStripeTax,
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* audit handler.
|
|
81
|
-
*
|
|
82
|
-
* Accepts an optional `contentRoot` override for testing. When omitted,
|
|
83
|
-
* resolves the content root relative to cwd (supports ESM runtime).
|
|
84
|
-
*
|
|
85
|
-
* `projectRoot` is the matching seam for the project.yaml the readiness rules'
|
|
86
|
-
* Stripe-Tax signal is read from (#5949 D9); it likewise defaults to cwd.
|
|
87
|
-
*/
|
|
88
|
-
export async function ailkAudit(
|
|
89
|
-
input: AuditInput,
|
|
90
|
-
contentRoot?: string,
|
|
91
|
-
projectRoot?: string,
|
|
92
|
-
): Promise<AuditOutput> {
|
|
93
|
-
auditInputSchema.parse(input);
|
|
94
|
-
|
|
95
|
-
// Cast: AuditInput's Zod-inferred optional fields include `undefined` in
|
|
96
|
-
// their union, but SinglePageInput uses exactOptionalPropertyTypes where `?`
|
|
97
|
-
// means "absent." The auditInputSchema.parse above guarantees validity.
|
|
98
|
-
const auditInput = await buildSinglePageAuditInput(
|
|
99
|
-
input as unknown as SinglePageInput,
|
|
100
|
-
contentRoot,
|
|
101
|
-
projectRoot,
|
|
102
|
-
);
|
|
103
|
-
const report = runAudit(auditInput, RULES);
|
|
104
|
-
|
|
105
|
-
const result: AuditOutput = {
|
|
106
|
-
score: report.score,
|
|
107
|
-
perRule: report.perRule.map((r) => ({
|
|
108
|
-
ruleId: r.id,
|
|
109
|
-
name: r.id, // rule description not on PerRuleResult; use id as name
|
|
110
|
-
weight: r.weight,
|
|
111
|
-
status: r.pass ? "pass" : "fail",
|
|
112
|
-
...(r.evidence !== undefined && { evidence: r.evidence }),
|
|
113
|
-
})),
|
|
114
|
-
perPage: report.perPage.map((p) => ({
|
|
115
|
-
slug: p.slug,
|
|
116
|
-
type: p.type,
|
|
117
|
-
score: p.score,
|
|
118
|
-
})),
|
|
119
|
-
meta: {
|
|
120
|
-
auditedAt: report.meta.auditedAt,
|
|
121
|
-
ruleSet: `${report.meta.schemaVersion}/${report.meta.registryVersion}`,
|
|
122
|
-
locale: auditInput.locale,
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
return auditOutputSchema.parse(result);
|
|
127
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* capture_lead — capture a lead: the body `POST /v1/leads/submit` takes.
|
|
3
|
-
*
|
|
4
|
-
* The tool adopted the API, arguments and results (#7171 — the operator's
|
|
5
|
-
* decision of 2026-10-19). Its input IS the route's `leadSubmitBodySchema`
|
|
6
|
-
* (the catalog registers the same shape, so the SDK has already parsed the
|
|
7
|
-
* arguments against it; the `safeParse` here keeps the stdio path and the
|
|
8
|
-
* `invalid_input` branch honest), the parsed body is posted as the agent
|
|
9
|
-
* sent it — no `siteId`, no stamped `source`, no wrapping — and the route's
|
|
10
|
-
* 201 body `{ id, persisted, email }` comes back unchanged. One addition
|
|
11
|
-
* survives, because it is deployment attribution rather than an argument:
|
|
12
|
-
* the spoke marker `payload.site` from `AILK_LEAD_SITE` (#7397), spread LAST
|
|
13
|
-
* over the agent's `payload` as the site's own writer
|
|
14
|
-
* (`apps/web/src/lib/lead-write.ts`) does; unset or blank, the payload goes
|
|
15
|
-
* as sent. No business logic — orchestration lives in apps/api.
|
|
16
|
-
*
|
|
17
|
-
* Paired with captureLeadAction Server Action per ADR 0013.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { apiClient } from "@working-theory/api-client";
|
|
21
|
-
import {
|
|
22
|
-
LEAD_SITE_MARKER_KEY,
|
|
23
|
-
leadSubmitBodySchema,
|
|
24
|
-
leadWriteOutputSchema,
|
|
25
|
-
type LeadSubmitBody,
|
|
26
|
-
type LeadWriteOutput,
|
|
27
|
-
} from "@working-theory/validation";
|
|
28
|
-
|
|
29
|
-
import { visitorForwardHeadersForThisCall } from "../request-context.js";
|
|
30
|
-
|
|
31
|
-
export { leadSubmitBodySchema, leadWriteOutputSchema };
|
|
32
|
-
export type { LeadSubmitBody, LeadWriteOutput };
|
|
33
|
-
|
|
34
|
-
export async function ailkCaptureLead(
|
|
35
|
-
input: LeadSubmitBody,
|
|
36
|
-
): Promise<LeadWriteOutput> {
|
|
37
|
-
const parsed = leadSubmitBodySchema.safeParse(input);
|
|
38
|
-
if (!parsed.success) {
|
|
39
|
-
return {
|
|
40
|
-
ok: false,
|
|
41
|
-
error: { kind: "invalid_input", issues: parsed.error.issues },
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// The spoke marker (#7397) — unset or blank leaves the payload as sent.
|
|
46
|
-
const site = process.env.AILK_LEAD_SITE?.trim();
|
|
47
|
-
const body = site
|
|
48
|
-
? {
|
|
49
|
-
...parsed.data,
|
|
50
|
-
payload: { ...parsed.data.payload, [LEAD_SITE_MARKER_KEY]: site },
|
|
51
|
-
}
|
|
52
|
-
: parsed.data;
|
|
53
|
-
|
|
54
|
-
// #8073 — forward the address the transport trusted (never an identity
|
|
55
|
-
// argument on this tool's own schema) so the hub counts the write in that
|
|
56
|
-
// visitor's own rate-limit bucket rather than this MCP host's.
|
|
57
|
-
const headers = visitorForwardHeadersForThisCall();
|
|
58
|
-
const res = headers
|
|
59
|
-
? await apiClient.leads.submit(body, { headers })
|
|
60
|
-
: await apiClient.leads.submit(body);
|
|
61
|
-
if (!res.ok) {
|
|
62
|
-
return { ok: false, error: { kind: "api_error", status: res.status } };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return res.body;
|
|
66
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* create_project — creates an AI Launch Kit starter project via create-ailk.
|
|
3
|
-
*
|
|
4
|
-
* Agent-only: no web Server Action equivalent. Scaffolding is an
|
|
5
|
-
* orchestration-layer action that only makes sense for an agent driving a
|
|
6
|
-
* project setup flow.
|
|
7
|
-
*
|
|
8
|
-
* Implementation: spawns the `create-ailk` CLI binary via Node's spawnSync.
|
|
9
|
-
* `apps/mcp` does NOT import `create-ailk` directly — the package is not on
|
|
10
|
-
* the apps/mcp allow-list in architecture.yaml (it is a standalone CLI, not a
|
|
11
|
-
* side-effect-free read library per ADR 0011). Spawning the built CLI binary
|
|
12
|
-
* is the architecturally correct delegation pattern.
|
|
13
|
-
*
|
|
14
|
-
* The CLI binary path defaults to `<cwd>/packages/create-ailk/dist/cli.js`.
|
|
15
|
-
* The MCP server runs from the repo root (cwd = repo root), so this resolves
|
|
16
|
-
* correctly in production and in integration tests.
|
|
17
|
-
*
|
|
18
|
-
* Input: { targetDir, projectName, preset? }
|
|
19
|
-
* The tool builds the Free organization-product starter (`--shape
|
|
20
|
-
* organization-product`, #6754 D9); `preset` stays reserved. Always builds
|
|
21
|
-
* the Free module set (`--modules marketing`, #6759 D6, SEC-7): a licence
|
|
22
|
-
* key sitting in the MCP server's own environment never widens what an
|
|
23
|
-
* anonymous caller receives — the explicit keep list takes precedence over
|
|
24
|
-
* any key-derived level probe before the child process reads its env.
|
|
25
|
-
* targetDir — absolute or relative path to scaffold into; must not exist
|
|
26
|
-
* or must be empty (enforced by create-ailk ValidationError)
|
|
27
|
-
* projectName — project name used in README and package.json
|
|
28
|
-
* preset — permissive string; reserved for Phase 3 U6 named starters
|
|
29
|
-
* // TODO(U6): narrow to z.enum([...]) once named presets land
|
|
30
|
-
*
|
|
31
|
-
* Output: { targetDir, filesCreated }
|
|
32
|
-
* targetDir — resolved absolute path that was scaffolded
|
|
33
|
-
* filesCreated — number of files written
|
|
34
|
-
*
|
|
35
|
-
* Session/scope: none — scaffolding is a write to the local filesystem
|
|
36
|
-
* initiated by the agent; no auth required for the tool itself.
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
import { spawnSync } from "node:child_process";
|
|
40
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
41
|
-
import { join, resolve } from "node:path";
|
|
42
|
-
|
|
43
|
-
import {
|
|
44
|
-
scaffoldInputSchema,
|
|
45
|
-
scaffoldOutputSchema,
|
|
46
|
-
type ScaffoldInput,
|
|
47
|
-
type ScaffoldOutput,
|
|
48
|
-
} from "@working-theory/validation";
|
|
49
|
-
|
|
50
|
-
export { scaffoldInputSchema, scaffoldOutputSchema };
|
|
51
|
-
export type { ScaffoldInput, ScaffoldOutput };
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Resolve the path to the create-ailk CLI binary.
|
|
55
|
-
*
|
|
56
|
-
* Uses process.cwd() — the MCP server always starts from the repo root.
|
|
57
|
-
* Accepts an override for tests.
|
|
58
|
-
*/
|
|
59
|
-
function resolveCliBin(override?: string): string {
|
|
60
|
-
if (override) return override;
|
|
61
|
-
return join(process.cwd(), "packages/create-ailk/dist/cli.js");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Count all files recursively under a directory.
|
|
66
|
-
*/
|
|
67
|
-
function countFiles(dir: string): number {
|
|
68
|
-
if (!existsSync(dir)) return 0;
|
|
69
|
-
let count = 0;
|
|
70
|
-
const stack: string[] = [dir];
|
|
71
|
-
while (stack.length > 0) {
|
|
72
|
-
const current = stack.pop()!;
|
|
73
|
-
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
74
|
-
if (entry.isDirectory()) {
|
|
75
|
-
stack.push(`${current}/${entry.name}`);
|
|
76
|
-
} else {
|
|
77
|
-
count++;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return count;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* ailkCreateProject handler.
|
|
86
|
-
*
|
|
87
|
-
* Spawns the create-ailk CLI binary to scaffold a starter project into
|
|
88
|
-
* targetDir. The binary must be pre-built (`pnpm --filter create-ailk build`).
|
|
89
|
-
*
|
|
90
|
-
* Accepts an optional `cliBin` override for testing (mirrors the contentRoot
|
|
91
|
-
* override pattern in ailkAudit).
|
|
92
|
-
*/
|
|
93
|
-
export async function ailkCreateProject(
|
|
94
|
-
input: ScaffoldInput,
|
|
95
|
-
cliBin?: string,
|
|
96
|
-
): Promise<ScaffoldOutput> {
|
|
97
|
-
scaffoldInputSchema.parse(input);
|
|
98
|
-
|
|
99
|
-
const bin = resolveCliBin(cliBin);
|
|
100
|
-
const targetAbs = resolve(input.targetDir);
|
|
101
|
-
|
|
102
|
-
// Spawn the CLI synchronously — no network, no async I/O needed.
|
|
103
|
-
// Hard-coded node invocation; only targetDir flows through user input. The
|
|
104
|
-
// CLI refuses a run naming no shape and no template, so the tool names one.
|
|
105
|
-
// `--modules marketing` is pinned explicitly (#6759 D6, SEC-7): an explicit
|
|
106
|
-
// keep list takes the keep branch and resolves before the child ever reads
|
|
107
|
-
// AILK_LICENSE_KEY, so a licence key in the server's own environment can
|
|
108
|
-
// never turn this anonymous call into the keyed level probe.
|
|
109
|
-
const result = spawnSync(
|
|
110
|
-
"node",
|
|
111
|
-
[bin, targetAbs, "--shape", "organization-product", "--modules", "marketing"],
|
|
112
|
-
{
|
|
113
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
114
|
-
shell: false,
|
|
115
|
-
encoding: "utf8",
|
|
116
|
-
},
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
if (result.status !== 0) {
|
|
120
|
-
// Extract the error message from stderr (CLI writes "[create-ailk] <msg>").
|
|
121
|
-
const stderr = (result.stderr ?? "").trim();
|
|
122
|
-
const msg = stderr.replace(/^\[create-ailk\]\s*/, "") || "scaffold failed";
|
|
123
|
-
throw new Error(msg);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const filesCreated = countFiles(targetAbs);
|
|
127
|
-
|
|
128
|
-
const output: ScaffoldOutput = {
|
|
129
|
-
targetDir: targetAbs,
|
|
130
|
-
filesCreated,
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
return scaffoldOutputSchema.parse(output);
|
|
134
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* get_business_hours — returns business hours from LocalBusiness structured data.
|
|
3
|
-
*
|
|
4
|
-
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
-
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
6
|
-
* Resolves a page by slug (default: "home") and extracts LocalBusiness schema.
|
|
7
|
-
* Returns null when the page is not found or has no openingHoursSpecification.
|
|
8
|
-
*
|
|
9
|
-
* Phase 3 S3: optional `locale` parameter (BCP-47). Validated against the
|
|
10
|
-
* project's allowlist; invalid or unknown values silently fall back to the
|
|
11
|
-
* default locale (AC-i18n-07).
|
|
12
|
-
*
|
|
13
|
-
* Input: { slug?: string, locale?: string }
|
|
14
|
-
* Output: Array<{ dayOfWeek, opens, closes, validFrom?, validThrough? }> | null
|
|
15
|
-
* Session/scope: none — read-only public content.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
getBusinessHoursInputSchema,
|
|
20
|
-
getBusinessHoursOutputSchema,
|
|
21
|
-
type GetBusinessHoursInput,
|
|
22
|
-
type GetBusinessHoursOutput,
|
|
23
|
-
} from "@working-theory/validation";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
getMcpContentAdapter,
|
|
27
|
-
mcpContentRoot,
|
|
28
|
-
} from "../lib/content-adapter.js";
|
|
29
|
-
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
30
|
-
|
|
31
|
-
export { getBusinessHoursInputSchema, getBusinessHoursOutputSchema };
|
|
32
|
-
export type { GetBusinessHoursInput, GetBusinessHoursOutput };
|
|
33
|
-
|
|
34
|
-
const DEFAULT_SLUG = "home";
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* get_business_hours handler.
|
|
38
|
-
*
|
|
39
|
-
* Accepts an optional `contentRoot` override for testing. When omitted,
|
|
40
|
-
* resolves it through `mcpContentRoot()` (#8070 D3).
|
|
41
|
-
*/
|
|
42
|
-
export async function ailkGetBusinessHours(
|
|
43
|
-
input: GetBusinessHoursInput,
|
|
44
|
-
contentRoot?: string,
|
|
45
|
-
): Promise<GetBusinessHoursOutput> {
|
|
46
|
-
getBusinessHoursInputSchema.parse(input);
|
|
47
|
-
|
|
48
|
-
const root = contentRoot ?? mcpContentRoot();
|
|
49
|
-
const locale = resolveLocale(input.locale);
|
|
50
|
-
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
51
|
-
|
|
52
|
-
const slug = input.slug ?? DEFAULT_SLUG;
|
|
53
|
-
const data = await adapter.extractStructuredData("LocalBusiness", slug, locale);
|
|
54
|
-
if (!data) return null;
|
|
55
|
-
|
|
56
|
-
const hours = data.openingHoursSpecification;
|
|
57
|
-
if (!Array.isArray(hours) || hours.length === 0) return null;
|
|
58
|
-
|
|
59
|
-
return getBusinessHoursOutputSchema.parse(
|
|
60
|
-
(hours as Record<string, unknown>[]).map((h) => ({
|
|
61
|
-
dayOfWeek: h["dayOfWeek"] as string,
|
|
62
|
-
opens: h["opens"] as string,
|
|
63
|
-
closes: h["closes"] as string,
|
|
64
|
-
validFrom: h["validFrom"] as string | undefined,
|
|
65
|
-
validThrough: h["validThrough"] as string | undefined,
|
|
66
|
-
})),
|
|
67
|
-
);
|
|
68
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* get_faq — returns FAQ question/answer pairs from FAQPage structured data.
|
|
3
|
-
*
|
|
4
|
-
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
-
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
6
|
-
* Resolves a page by slug (default: "faq") and extracts FAQPage schema.
|
|
7
|
-
* Returns null when the page is not found or has no mainEntity questions.
|
|
8
|
-
*
|
|
9
|
-
* Phase 3 S3: optional `locale` parameter (BCP-47). Validated against the
|
|
10
|
-
* project's allowlist; invalid or unknown values silently fall back to the
|
|
11
|
-
* default locale (AC-i18n-07).
|
|
12
|
-
*
|
|
13
|
-
* Input: { slug?: string, locale?: string }
|
|
14
|
-
* Output: { questions: Array<{ question, answer }> } | null
|
|
15
|
-
* Session/scope: none — read-only public content.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
getFaqInputSchema,
|
|
20
|
-
getFaqOutputSchema,
|
|
21
|
-
type GetFaqInput,
|
|
22
|
-
type GetFaqOutput,
|
|
23
|
-
} from "@working-theory/validation";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
getMcpContentAdapter,
|
|
27
|
-
mcpContentRoot,
|
|
28
|
-
} from "../lib/content-adapter.js";
|
|
29
|
-
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
30
|
-
|
|
31
|
-
export { getFaqInputSchema, getFaqOutputSchema };
|
|
32
|
-
export type { GetFaqInput, GetFaqOutput };
|
|
33
|
-
|
|
34
|
-
const DEFAULT_SLUG = "faq";
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* get_faq handler.
|
|
38
|
-
*
|
|
39
|
-
* Accepts an optional `contentRoot` override for testing. When omitted,
|
|
40
|
-
* resolves it through `mcpContentRoot()` (#8070 D3).
|
|
41
|
-
*/
|
|
42
|
-
export async function ailkGetFaq(
|
|
43
|
-
input: GetFaqInput,
|
|
44
|
-
contentRoot?: string,
|
|
45
|
-
): Promise<GetFaqOutput> {
|
|
46
|
-
getFaqInputSchema.parse(input);
|
|
47
|
-
|
|
48
|
-
const root = contentRoot ?? mcpContentRoot();
|
|
49
|
-
const locale = resolveLocale(input.locale);
|
|
50
|
-
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
51
|
-
|
|
52
|
-
const slug = input.slug ?? DEFAULT_SLUG;
|
|
53
|
-
const data = await adapter.extractStructuredData("FAQPage", slug, locale);
|
|
54
|
-
if (!data) return null;
|
|
55
|
-
|
|
56
|
-
const entities = data.mainEntity;
|
|
57
|
-
if (!Array.isArray(entities) || entities.length === 0) return null;
|
|
58
|
-
|
|
59
|
-
const questions = (entities as Record<string, unknown>[]).map((item) => ({
|
|
60
|
-
question: (item["name"] as string) ?? "",
|
|
61
|
-
answer:
|
|
62
|
-
typeof item["acceptedAnswer"] === "object" &&
|
|
63
|
-
item["acceptedAnswer"] !== null
|
|
64
|
-
? (((item["acceptedAnswer"] as Record<string, unknown>)[
|
|
65
|
-
"text"
|
|
66
|
-
] as string) ?? "")
|
|
67
|
-
: ((item["acceptedAnswer"] as string) ?? ""),
|
|
68
|
-
}));
|
|
69
|
-
|
|
70
|
-
return getFaqOutputSchema.parse({ questions });
|
|
71
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* get_locations — returns all Place locations from structured data site-wide.
|
|
3
|
-
*
|
|
4
|
-
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
-
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
6
|
-
* Lists all pages of type "Place" and extracts Place schema from each.
|
|
7
|
-
* Returns an empty array when no Place pages exist.
|
|
8
|
-
*
|
|
9
|
-
* Phase 3 S3: optional `locale` parameter (BCP-47). Validated against the
|
|
10
|
-
* project's allowlist; invalid or unknown values silently fall back to the
|
|
11
|
-
* default locale (AC-i18n-07). Page enumeration is locale-scoped.
|
|
12
|
-
*
|
|
13
|
-
* Input: { locale?: string }
|
|
14
|
-
* Output: { locations: Array<{ name, address, geo?, telephone? }> }
|
|
15
|
-
* Session/scope: none — read-only public content.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { SCHEMA_ORG_TYPES } from "@working-theory/content-adapters";
|
|
19
|
-
import {
|
|
20
|
-
getLocationsInputSchema,
|
|
21
|
-
getLocationsOutputSchema,
|
|
22
|
-
type GetLocationsInput,
|
|
23
|
-
type GetLocationsOutput,
|
|
24
|
-
} from "@working-theory/validation";
|
|
25
|
-
|
|
26
|
-
import {
|
|
27
|
-
getMcpContentAdapter,
|
|
28
|
-
mcpContentRoot,
|
|
29
|
-
} from "../lib/content-adapter.js";
|
|
30
|
-
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
31
|
-
|
|
32
|
-
export { getLocationsInputSchema, getLocationsOutputSchema };
|
|
33
|
-
export type { GetLocationsInput, GetLocationsOutput };
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* get_locations handler.
|
|
37
|
-
*
|
|
38
|
-
* Accepts an optional `contentRoot` override for testing. When omitted,
|
|
39
|
-
* resolves it through `mcpContentRoot()` (#8070 D3).
|
|
40
|
-
*/
|
|
41
|
-
export async function ailkGetLocations(
|
|
42
|
-
input: GetLocationsInput,
|
|
43
|
-
contentRoot?: string,
|
|
44
|
-
): Promise<GetLocationsOutput> {
|
|
45
|
-
getLocationsInputSchema.parse(input);
|
|
46
|
-
|
|
47
|
-
const root = contentRoot ?? mcpContentRoot();
|
|
48
|
-
const locale = resolveLocale(input.locale);
|
|
49
|
-
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
50
|
-
|
|
51
|
-
// Place is not a page-level SchemaOrgType, so we iterate all types to find
|
|
52
|
-
// pages whose schema field has Place structured data.
|
|
53
|
-
const allPages = await Promise.all(
|
|
54
|
-
SCHEMA_ORG_TYPES.map((type) => adapter.listPages(type, locale)),
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
// Deduplicate slugs before extracting — a slug can appear in multiple types.
|
|
58
|
-
const slugsSeen = new Set<string>();
|
|
59
|
-
const uniquePages = allPages.flat().filter((page) => {
|
|
60
|
-
if (slugsSeen.has(page.slug)) return false;
|
|
61
|
-
slugsSeen.add(page.slug);
|
|
62
|
-
return true;
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Parallelize extraction — each call is an independent fs read.
|
|
66
|
-
const extracted = await Promise.all(
|
|
67
|
-
uniquePages.map(async (page) => ({
|
|
68
|
-
page,
|
|
69
|
-
data: await adapter.extractStructuredData("Place", page.slug, locale),
|
|
70
|
-
})),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const locations: GetLocationsOutput["locations"] = [];
|
|
74
|
-
for (const { page, data } of extracted) {
|
|
75
|
-
if (!data) continue;
|
|
76
|
-
const place = data as Record<string, unknown>;
|
|
77
|
-
const address = place["address"] as Record<string, unknown> | undefined;
|
|
78
|
-
if (!address) continue;
|
|
79
|
-
locations.push({
|
|
80
|
-
name: page.title,
|
|
81
|
-
address,
|
|
82
|
-
geo: place["geo"] as Record<string, unknown> | undefined,
|
|
83
|
-
telephone: place["telephone"] as string | undefined,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return getLocationsOutputSchema.parse({ locations });
|
|
88
|
-
}
|