create-ailk 0.23.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 +68 -33
- package/component-catalog.json +3 -3
- package/component-catalog.md +3 -3
- package/dist/add-module.js +10 -3
- package/dist/add-route.d.ts +12 -1
- package/dist/add-route.js +38 -4
- package/dist/cli.js +12 -7
- package/dist/derive-architecture.d.ts +3 -4
- package/dist/derive-architecture.js +75 -22
- 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/lib/scaffold-render-sweep.d.ts +33 -0
- package/dist/lib/scaffold-render-sweep.js +45 -0
- package/dist/module-architecture.d.ts +20 -3
- package/dist/module-architecture.js +122 -538
- package/dist/paid-sections.d.ts +25 -1
- package/dist/paid-sections.js +88 -3
- package/dist/surfaces.js +10 -2
- package/dist/sync-routes.d.ts +30 -4
- package/dist/sync-routes.js +271 -18
- 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 +9 -5
- package/templates/.github/workflows/ci.yml +7 -4
- package/templates/CLAUDE.md +15 -3
- package/templates/CONVENTIONS.md +8 -10
- package/templates/README.md +14 -13
- package/templates/apps/api/.env.example +9 -2
- package/templates/apps/api/CLAUDE.md +122 -82
- 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 +7 -4
- 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 -1857
- package/templates/apps/api/vercel.json +2 -2
- package/templates/apps/mcp/CLAUDE.md +77 -24
- 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 -12
- 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 +21 -5
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +9 -3
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +14 -4
- package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +1 -1
- package/templates/apps/web/app/[locale]/contact/intake-script.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 +28 -7
- 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/__tests__/magnet-routes.test.ts +7 -0
- package/templates/apps/web/lib/auth-email.ts +1 -1
- package/templates/apps/web/lib/magnet-routes.ts +3 -1
- package/templates/apps/web/lib/newsletter.actions.ts +9 -6
- 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 +32 -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 +757 -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 -292
- 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 -254
- 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 -318
- 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 -264
- 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 -1815
- 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 -325
- 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 -1300
- 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 -268
- package/templates/apps/api/src/routes/content/index.ts +0 -49
- package/templates/apps/api/src/routes/content/list-pages.ts +0 -95
- 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 -129
- package/templates/apps/api/src/routes/content/shown-offerings.ts +0 -229
- package/templates/apps/api/src/routes/content/slug.ts +0 -9
- 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 -573
- 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 -480
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +0 -465
- 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 -448
- 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 -808
- 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 -2026
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +0 -528
- 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 -867
- 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 -1176
- package/templates/apps/api/src/services/__tests__/plan-offerings.test.ts +0 -444
- package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +0 -154
- 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 -313
- 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 -755
- 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 -295
- 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 -868
- 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 -396
- package/templates/apps/api/src/services/offerings/__tests__/readers.test.ts +0 -681
- package/templates/apps/api/src/services/offerings/__tests__/source.test.ts +0 -231
- package/templates/apps/api/src/services/offerings/catalog.ts +0 -308
- package/templates/apps/api/src/services/offerings/checkout-authorization.ts +0 -385
- package/templates/apps/api/src/services/offerings/checkout-session-record.ts +0 -192
- package/templates/apps/api/src/services/offerings/connection.ts +0 -1003
- 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 -1188
- 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 -2073
- 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 -1151
- 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 -65
- package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +0 -187
- 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 -165
- package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +0 -124
- package/templates/apps/mcp/__tests__/list_pages.test.ts +0 -228
- package/templates/apps/mcp/__tests__/locale.test.ts +0 -135
- 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__/read_content.test.ts +0 -474
- package/templates/apps/mcp/__tests__/request_callback.test.ts +0 -225
- package/templates/apps/mcp/__tests__/search_content.test.ts +0 -256
- 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 -307
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +0 -223
- 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 -342
- 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 -526
- 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 -142
- package/templates/apps/mcp/src/lib/empty-content-adapter.ts +0 -139
- 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/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 -64
- 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 -137
- package/templates/apps/mcp/src/tools/list_pages.ts +0 -74
- 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 -75
- package/templates/apps/mcp/src/tools/request_callback.ts +0 -59
- package/templates/apps/mcp/src/tools/search_content.ts +0 -67
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +0 -57
- package/templates/apps/mcp/src/workspace-server.ts +0 -224
- package/templates/database/CHANGELOG.md +0 -961
- 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 -240
- package/templates/database/__tests__/spoke-registry.db.test.ts +0 -191
- package/templates/database/__tests__/tenancy.test.ts +0 -141
- 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/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,210 +0,0 @@
|
|
|
1
|
-
-- #6314 — ProjectListing gains `captured_by_flow_id`: the listicle-kind
|
|
2
|
-
-- FlowDefinition that CAPTURED the application, so a magnet's own
|
|
3
|
-
-- Applications list can be scoped to its own submissions rather than to the
|
|
4
|
-
-- whole workspace. Nothing constrains a workspace to one listicle magnet
|
|
5
|
-
-- ("flow_definitions" carries a (site_id, slug) unique and no
|
|
6
|
-
-- (site_id, kind) one), so workspace-only scoping would silently conflate
|
|
7
|
-
-- two listicle magnets' applications.
|
|
8
|
-
--
|
|
9
|
-
-- A NEW MIGRATION DIRECTORY, not an amendment of the already-merged
|
|
10
|
-
-- 20260922120000_tenancy_fence (spec D8). #6254 AC-1's one-migration-per-
|
|
11
|
-
-- milestone rule names #6314 by number in that migration's own header, so
|
|
12
|
-
-- this is a DEPARTURE taken deliberately and with the operator's
|
|
13
|
-
-- confirmation (2026-09-20), not a gap that rule failed to cover. Two
|
|
14
|
-
-- reasons, in order of weight:
|
|
15
|
-
-- 1. Prisma records a per-migration CHECKSUM. `prisma migrate deploy`
|
|
16
|
-
-- refuses a migration whose file no longer matches `_prisma_migrations`,
|
|
17
|
-
-- so a database that already applied the fence directory would never
|
|
18
|
-
-- receive this column or its index while the new code assumes both.
|
|
19
|
-
-- "Editing it in place is a silent no-op" is true of the SQL; it is not
|
|
20
|
-
-- true of the checksum.
|
|
21
|
-
-- 2. apps/api/CLAUDE.md: "Never edit a shipped migration — add a new one."
|
|
22
|
-
-- Where a spec's convenience and an in-repo rule disagree, the rule wins.
|
|
23
|
-
--
|
|
24
|
-
-- PURELY ADDITIVE: one nullable column, one index. NO UPDATE, NO backfill,
|
|
25
|
-
-- and NO foreign key.
|
|
26
|
-
--
|
|
27
|
-
-- NO BACKFILL, deliberately (spec § 3.5 / AC-3, operator ruling 2026-09-19).
|
|
28
|
-
-- No existing row carries evidence naming the magnet that captured it — no
|
|
29
|
-
-- referrer, no session link, no slug. A backfill would have to guess "the
|
|
30
|
-
-- workspace's only listicle magnet", which is exactly the conflation this
|
|
31
|
-
-- column exists to remove, made permanent and unauditable. Every row written
|
|
32
|
-
-- before this migration therefore reads NULL for the life of the row:
|
|
33
|
-
-- unattributed, excluded from every per-magnet list (NULL never equals a
|
|
34
|
-
-- magnet id, so the exclusion is a property of the query, not a filter that
|
|
35
|
-
-- can be forgotten), and UNCHANGED in the workspace Inbox — no operator loses
|
|
36
|
-
-- access to any application. This is the same discipline the founder-name
|
|
37
|
-
-- parts (#5407), the address parts (#5279) and `owner_user_id` (#5295) each
|
|
38
|
-
-- follow: a value that can only be guessed must not be asserted.
|
|
39
|
-
--
|
|
40
|
-
-- NO foreign key, deliberately (spec § 3.2, operator decision 2026-09-20,
|
|
41
|
-
-- which withdrew the 2026-09-19 ruling's "on-delete set-null" clause). Both
|
|
42
|
-
-- models live in the `inbox` namespace, so ADR 0009 invariant #1 (which bans
|
|
43
|
-
-- CROSS-namespace relations) does not reach this column — permission was
|
|
44
|
-
-- never the question. The convention is: of the 24 foreign-key constraints
|
|
45
|
-
-- under database/migrations/**, every one targets the `auth` namespace
|
|
46
|
-
-- ("users"); the intra-inbox columns listing_id, lead_id, grant_id and
|
|
47
|
-
-- flow_session_id carry none. The composite (workspace_id, …) shape was
|
|
48
|
-
-- itself offered and declined on "listing_csv_sends" the day before this
|
|
49
|
-
-- spec's pin. Integrity rests on the server-side resolve in
|
|
50
|
-
-- `startProjectListingDraft` (site_id + workspace_id + kind = 'listicle')
|
|
51
|
-
-- and on the read carrying the injected workspace_id alongside the magnet id
|
|
52
|
-
-- — so a dangling or foreign value yields no rows, never another workspace's.
|
|
53
|
-
-- Nothing deletes a flow_definitions row either (routes/magnets D5: "No
|
|
54
|
-
-- DELETE"), so ON DELETE SET NULL would have described no live code path.
|
|
55
|
-
--
|
|
56
|
-
-- RE-RUNNABLE: IF NOT EXISTS on both DDL statements, the census temp table is
|
|
57
|
-
-- dropped-if-exists before it is built, and post-assertion 2 is skipped on a
|
|
58
|
-
-- re-apply (it proves this file grew no backfill, which only the first
|
|
59
|
-
-- application can show — see its own comment). So re-applying this directory
|
|
60
|
-
-- against a database that already has the column is inert rather than an abort
|
|
61
|
-
-- that would wedge the ledger.
|
|
62
|
-
--
|
|
63
|
-
-- ORDER-SAFE: the index references "workspace_id", added by
|
|
64
|
-
-- 20260919140000_inbox_workspace_key and made NOT NULL by
|
|
65
|
-
-- 20260922120000_tenancy_fence — both of which this migration sorts strictly
|
|
66
|
-
-- after. The guard below is therefore a formality in the normal case, kept
|
|
67
|
-
-- for the reason 20260920130000_lead_workspace_source_index keeps one: IF NOT
|
|
68
|
-
-- EXISTS guards the INDEX's own name, not the column it references, so an
|
|
69
|
-
-- unguarded CREATE INDEX would abort inside prisma migrate's per-migration
|
|
70
|
-
-- transaction and wedge the ledger for the whole deployment if that earlier
|
|
71
|
-
-- migration were ever skipped, renamed, or rolled back on a given database.
|
|
72
|
-
--
|
|
73
|
-
-- CREATE INDEX is NOT CONCURRENT, and cannot be: CONCURRENTLY may not run
|
|
74
|
-
-- inside prisma migrate's per-migration transaction. It therefore takes a
|
|
75
|
-
-- lock on "project_listings" for its duration — the same accepted risk
|
|
76
|
-
-- 20260920130000_lead_workspace_source_index names. A deployment with a large
|
|
77
|
-
-- project_listings table should create this index out-of-band with
|
|
78
|
-
-- CONCURRENTLY first; the IF NOT EXISTS guard then makes the statement a
|
|
79
|
-
-- no-op.
|
|
80
|
-
--
|
|
81
|
-
-- Rollback:
|
|
82
|
-
-- DROP INDEX "project_listings_workspace_id_captured_by_flow_id_idx";
|
|
83
|
-
-- ALTER TABLE "project_listings" DROP COLUMN "captured_by_flow_id";
|
|
84
|
-
-- Safe at any point: the column is nullable and unconstrained, and no row's
|
|
85
|
-
-- correctness depends on it beyond per-magnet attribution.
|
|
86
|
-
|
|
87
|
-
-- A census, so the post-assertions below can prove nothing moved.
|
|
88
|
-
--
|
|
89
|
-
-- `column_preexisted` is captured HERE, before the ALTER, and it is what keeps
|
|
90
|
-
-- assertion 2 honest on a RE-APPLY. That assertion proves a property of THIS
|
|
91
|
-
-- FILE (it performs no backfill), which is only observable on the application
|
|
92
|
-
-- that first adds the column: once the application has written even one real
|
|
93
|
-
-- attribution, "no row is attributed" is false for reasons this migration had
|
|
94
|
-
-- nothing to do with. Asserting it unconditionally would abort inside prisma
|
|
95
|
-
-- migrate's per-migration transaction and wedge the ledger for every later
|
|
96
|
-
-- migration on that database — on a restored snapshot, a `migrate resolve
|
|
97
|
-
-- --rolled-back` redeploy, or a branch of production.
|
|
98
|
-
-- `pg_temp.`-qualified: DROP TABLE does not distinguish temporary from
|
|
99
|
-
-- permanent relations, and at this point the session holds no temp table, so
|
|
100
|
-
-- an unqualified name would resolve through search_path to `public` and drop
|
|
101
|
-
-- a same-named PERMANENT table — inside the transaction prisma commits.
|
|
102
|
-
DROP TABLE IF EXISTS pg_temp."_6314_capture_census";
|
|
103
|
-
CREATE TEMP TABLE "_6314_capture_census" AS
|
|
104
|
-
SELECT
|
|
105
|
-
count(*) AS p,
|
|
106
|
-
EXISTS (
|
|
107
|
-
SELECT 1 FROM information_schema.columns
|
|
108
|
-
-- `table_schema = current_schema()` is load-bearing, not tidiness:
|
|
109
|
-
-- `information_schema.columns` spans EVERY schema in the database, so
|
|
110
|
-
-- without it the probe answers "does any table anywhere named
|
|
111
|
-
-- project_listings carry this column" rather than "does the table this
|
|
112
|
-
-- migration is about to alter carry it". A pre-migration snapshot in a
|
|
113
|
-
-- side schema (`CREATE TABLE backup.project_listings AS SELECT ...`, a
|
|
114
|
-
-- `pg_dump -n` restore) would then make a genuine FIRST apply take the
|
|
115
|
-
-- skip branch below and wave a real backfill through unchecked — the
|
|
116
|
-
-- exact AC-8 property assertion 2 exists to prove.
|
|
117
|
-
WHERE table_schema = current_schema()
|
|
118
|
-
AND table_name = 'project_listings'
|
|
119
|
-
AND column_name = 'captured_by_flow_id'
|
|
120
|
-
) AS column_preexisted
|
|
121
|
-
FROM "project_listings";
|
|
122
|
-
|
|
123
|
-
-- AlterTable — the capturing magnet's id. Nullable and unconstrained, so a
|
|
124
|
-
-- row predating this migration reads NULL and nothing here can reject it.
|
|
125
|
-
ALTER TABLE "project_listings" ADD COLUMN IF NOT EXISTS "captured_by_flow_id" TEXT;
|
|
126
|
-
|
|
127
|
-
-- CreateIndex — the read is workspace_id = $1 AND captured_by_flow_id = $2,
|
|
128
|
-
-- ordered by created_at desc. A two-column (workspace_id, captured_by_flow_id)
|
|
129
|
-
-- index serves it directly. With no foreign key there is no cascade, so no
|
|
130
|
-
-- referencing-side index is owed beyond this one.
|
|
131
|
-
DO $$ BEGIN
|
|
132
|
-
IF EXISTS (
|
|
133
|
-
SELECT 1 FROM information_schema.columns
|
|
134
|
-
-- `table_schema = current_schema()` for the same reason the census probe
|
|
135
|
-
-- above carries it, and the failure direction here is WORSE. A decoy
|
|
136
|
-
-- `project_listings` in another schema makes this EXISTS spuriously true;
|
|
137
|
-
-- the CREATE INDEX below then runs against the table search_path actually
|
|
138
|
-
-- resolves, hits `column "workspace_id" does not exist`, and aborts the
|
|
139
|
-
-- whole migration transaction — a wedged ledger, where the census probe's
|
|
140
|
-
-- equivalent merely skips an assertion. The guard must ask about the table
|
|
141
|
-
-- the statement it protects will really touch.
|
|
142
|
-
WHERE table_schema = current_schema()
|
|
143
|
-
AND table_name = 'project_listings'
|
|
144
|
-
AND column_name = 'workspace_id'
|
|
145
|
-
) THEN
|
|
146
|
-
CREATE INDEX IF NOT EXISTS "project_listings_workspace_id_captured_by_flow_id_idx"
|
|
147
|
-
ON "project_listings"("workspace_id", "captured_by_flow_id");
|
|
148
|
-
ELSE
|
|
149
|
-
RAISE NOTICE '#6314: project_listings.workspace_id absent — index skipped. 20260919140000_inbox_workspace_key has not run against this database; the per-magnet Applications read cannot be served efficiently until it does.';
|
|
150
|
-
END IF;
|
|
151
|
-
END $$;
|
|
152
|
-
|
|
153
|
-
-- Post-assertions, in 20260922120000_tenancy_fence's own idiom.
|
|
154
|
-
DO $$
|
|
155
|
-
DECLARE
|
|
156
|
-
before_p bigint;
|
|
157
|
-
after_p bigint;
|
|
158
|
-
attributed bigint;
|
|
159
|
-
preexisted boolean;
|
|
160
|
-
BEGIN
|
|
161
|
-
SELECT p, column_preexisted INTO before_p, preexisted FROM "_6314_capture_census";
|
|
162
|
-
SELECT count(*) INTO after_p FROM "project_listings";
|
|
163
|
-
|
|
164
|
-
-- 1. Nothing LOST. Deliberately `<`, not `<>`.
|
|
165
|
-
--
|
|
166
|
-
-- An equality test here has no true-positive mode and one guaranteed
|
|
167
|
-
-- false-positive mode, which is the worst shape a guard can have. No
|
|
168
|
-
-- statement in this file modifies a row of "project_listings" (the whole
|
|
169
|
-
-- file is five statements; read them), so the two counts can only diverge
|
|
170
|
-
-- through a write committed by ANOTHER session between them. The census
|
|
171
|
-
-- takes ACCESS SHARE; the ALTER takes ACCESS EXCLUSIVE, and until it does,
|
|
172
|
-
-- the table stays open to writers. "project_listings" is written by an
|
|
173
|
-
-- ANONYMOUS, unauthenticated route, so on a live deploy one application
|
|
174
|
-
-- started mid-migration aborts the migration — and the retry meets the
|
|
175
|
-
-- same race. That is a wedged ledger caused by the system working
|
|
176
|
-
-- normally.
|
|
177
|
-
--
|
|
178
|
-
-- `<` keeps the property the assertion is actually for — this migration
|
|
179
|
-
-- must never destroy a row — while letting a concurrent INSERT through.
|
|
180
|
-
-- A DELETE or TRUNCATE creeping into this file still trips it.
|
|
181
|
-
IF after_p < before_p THEN
|
|
182
|
-
RAISE EXCEPTION
|
|
183
|
-
'#6314 post-assertion: project_listings LOST row(s) across a purely additive migration (% -> %)',
|
|
184
|
-
before_p, after_p;
|
|
185
|
-
END IF;
|
|
186
|
-
|
|
187
|
-
-- 2. Nothing guessed (AC-8): every PRE-EXISTING row reads NULL. This
|
|
188
|
-
-- migration performs no UPDATE, so a non-NULL row on the application that
|
|
189
|
-
-- first adds the column would mean the file grew a backfill the ruling
|
|
190
|
-
-- refused.
|
|
191
|
-
--
|
|
192
|
-
-- Skipped when the column already existed: on a re-apply, attributed rows
|
|
193
|
-
-- are the APPLICATION's own writes, not a backfill, and failing on them
|
|
194
|
-
-- would wedge the migration ledger (see the census above). The assertion
|
|
195
|
-
-- still fires where it can mean anything — the first application, which is
|
|
196
|
-
-- the only run that can introduce a backfill.
|
|
197
|
-
IF preexisted THEN
|
|
198
|
-
RAISE NOTICE '#6314 post-assertion 2 skipped: captured_by_flow_id already existed, so this is a re-apply and any attributed row is an application write rather than a backfill.';
|
|
199
|
-
ELSE
|
|
200
|
-
SELECT count(*) INTO attributed
|
|
201
|
-
FROM "project_listings" WHERE "captured_by_flow_id" IS NOT NULL;
|
|
202
|
-
IF attributed <> 0 THEN
|
|
203
|
-
RAISE EXCEPTION
|
|
204
|
-
'#6314 post-assertion: % project_listings row(s) carry a captured_by_flow_id after a migration that performs no UPDATE — existing rows must stay unattributed (no backfill by guess)',
|
|
205
|
-
attributed;
|
|
206
|
-
END IF;
|
|
207
|
-
END IF;
|
|
208
|
-
END $$;
|
|
209
|
-
|
|
210
|
-
DROP TABLE pg_temp."_6314_capture_census";
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
-- #7532 — the hub's spoke registry and the booking-origin record (spec
|
|
2
|
-
-- docs/specs/7532-a-spoke-s-public-reads-spec.md D1, D5).
|
|
3
|
-
--
|
|
4
|
-
-- spokes (auth) — one row per separately deployed site that
|
|
5
|
-
-- calls this hub, bound to ONE workspace. It
|
|
6
|
-
-- stores the SHA-256 digest of the spoke's
|
|
7
|
-
-- hub-minted key, never the key. Deleting a
|
|
8
|
-
-- workspace deletes its spokes (the FK below).
|
|
9
|
-
-- appointment_origins (inbox) — (provider, booking uid) → workspace, written
|
|
10
|
-
-- when a spoke's booking is created so the
|
|
11
|
-
-- deployment-wide Cal.com webhook stores the
|
|
12
|
-
-- booking in the spoke's workspace. One origin
|
|
13
|
-
-- per booking uid. No foreign key and no
|
|
14
|
-
-- relation (ADR 0009): workspace_id and
|
|
15
|
-
-- spoke_id are plain columns with format CHECKs.
|
|
16
|
-
--
|
|
17
|
-
-- PURELY ADDITIVE: two new tables, their indexes and one FK to "workspaces".
|
|
18
|
-
-- No statement touches an existing table's rows or columns, so there is no
|
|
19
|
-
-- pre-assertion block — this migration cannot lose a row.
|
|
20
|
-
--
|
|
21
|
-
-- Rollback: DROP TABLE "appointment_origins"; DROP TABLE "spokes". Safe while
|
|
22
|
-
-- nothing but #7532's own code reads them.
|
|
23
|
-
|
|
24
|
-
-- CreateTable
|
|
25
|
-
CREATE TABLE "spokes" (
|
|
26
|
-
"id" TEXT NOT NULL DEFAULT ('spoke_'::text || (uuidv7())::text),
|
|
27
|
-
"workspace_id" TEXT NOT NULL,
|
|
28
|
-
"name" VARCHAR(120) NOT NULL,
|
|
29
|
-
"credential_hash" CHAR(64) NOT NULL,
|
|
30
|
-
"credential_prefix" VARCHAR(24) NOT NULL,
|
|
31
|
-
"revoked_at" TIMESTAMP(3),
|
|
32
|
-
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
33
|
-
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
34
|
-
|
|
35
|
-
CONSTRAINT "spokes_pkey" PRIMARY KEY ("id")
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
-- CreateTable
|
|
39
|
-
CREATE TABLE "appointment_origins" (
|
|
40
|
-
"id" TEXT NOT NULL DEFAULT ('apptorg_'::text || (uuidv7())::text),
|
|
41
|
-
"provider" VARCHAR(32) NOT NULL DEFAULT 'cal',
|
|
42
|
-
"provider_booking_uid" VARCHAR(200) NOT NULL,
|
|
43
|
-
"workspace_id" TEXT NOT NULL,
|
|
44
|
-
"spoke_id" TEXT NOT NULL,
|
|
45
|
-
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
46
|
-
|
|
47
|
-
CONSTRAINT "appointment_origins_pkey" PRIMARY KEY ("id")
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
-- CreateIndex
|
|
51
|
-
-- The lookup a spoke's every request makes (`findSpokeByKeyHash`).
|
|
52
|
-
CREATE UNIQUE INDEX "spokes_credential_hash_key" ON "spokes"("credential_hash");
|
|
53
|
-
|
|
54
|
-
-- CreateIndex
|
|
55
|
-
CREATE INDEX "spokes_workspace_id_idx" ON "spokes"("workspace_id");
|
|
56
|
-
|
|
57
|
-
-- CreateIndex
|
|
58
|
-
CREATE INDEX "appointment_origins_workspace_id_idx" ON "appointment_origins"("workspace_id");
|
|
59
|
-
|
|
60
|
-
-- CreateIndex
|
|
61
|
-
-- One origin per booking uid (spec D5). The bind inserts with
|
|
62
|
-
-- ON CONFLICT DO NOTHING against this key.
|
|
63
|
-
CREATE UNIQUE INDEX "appointment_origins_provider_provider_booking_uid_key" ON "appointment_origins"("provider", "provider_booking_uid");
|
|
64
|
-
|
|
65
|
-
-- AddForeignKey
|
|
66
|
-
ALTER TABLE "spokes" ADD CONSTRAINT "spokes_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
67
|
-
|
|
68
|
-
-- ADR-0031 rule 3 — spokes: spoke_, appointment_origins: apptorg_ (registered
|
|
69
|
-
-- in packages/ids/src/registry.ts; this migration's path is added to
|
|
70
|
-
-- migration-sync.test.ts's PK_CHECK_MIGRATIONS).
|
|
71
|
-
ALTER TABLE "spokes" ALTER COLUMN "id" TYPE text COLLATE "C";
|
|
72
|
-
ALTER TABLE "spokes" ALTER COLUMN "id" SET DEFAULT ('spoke_'::text || (uuidv7())::text);
|
|
73
|
-
ALTER TABLE "spokes" ADD CONSTRAINT "spokes_id_format" CHECK ("id" ~ '^spoke_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
74
|
-
ALTER TABLE "spokes" ADD CONSTRAINT "spokes_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
75
|
-
|
|
76
|
-
ALTER TABLE "appointment_origins" ALTER COLUMN "id" TYPE text COLLATE "C";
|
|
77
|
-
ALTER TABLE "appointment_origins" ALTER COLUMN "id" SET DEFAULT ('apptorg_'::text || (uuidv7())::text);
|
|
78
|
-
ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_id_format" CHECK ("id" ~ '^apptorg_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
79
|
-
ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_spoke_id_format" CHECK ("spoke_id" ~ '^spoke_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
80
|
-
ALTER TABLE "appointment_origins" ADD CONSTRAINT "appointment_origins_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
-- #7533 — the SchedulingConnection model: a workspace's own scheduling
|
|
2
|
-
-- provider account (spec docs/specs/7533-a-scheduling-connection-per-workspace-spec.md
|
|
3
|
-
-- D1). One row per workspace, keyed `@unique(workspace_id)` like its config
|
|
4
|
-
-- sibling workspace_meetings; the credential and webhook secret columns hold
|
|
5
|
-
-- AES-256-GCM ciphertext written only by apps/api's
|
|
6
|
-
-- services/scheduling/connections.ts. `webhook_token` is the per-connection
|
|
7
|
-
-- webhook entry point's routing id, unique so a delivery resolves at most
|
|
8
|
-
-- one row.
|
|
9
|
-
--
|
|
10
|
-
-- One new table, two unique indexes, in the house style of
|
|
11
|
-
-- 20260919130000_workspace_meetings (CreateTable + CreateIndex immediately
|
|
12
|
-
-- followed by the ADR-0031 rule-3 id-format completion, in ONE migration
|
|
13
|
-
-- since the table is new and needs no retrofit). No `workspace_id_format`
|
|
14
|
-
-- CHECK and no `provider` CHECK, matching that same precedent (the API
|
|
15
|
-
-- accepts only the provider ids its factory table knows).
|
|
16
|
-
--
|
|
17
|
-
-- No backfill, no constraint relaxed, no existing table touched.
|
|
18
|
-
--
|
|
19
|
-
-- Rollback: DROP TABLE "scheduling_connections". Every stored connection is
|
|
20
|
-
-- lost; each workspace returns to the unconfigured state (or, on a
|
|
21
|
-
-- one-workspace deployment, to the CAL_API_KEY env fallback).
|
|
22
|
-
|
|
23
|
-
-- CreateTable
|
|
24
|
-
CREATE TABLE "scheduling_connections" (
|
|
25
|
-
"id" TEXT NOT NULL DEFAULT ('schconn_'::text || (uuidv7())::text),
|
|
26
|
-
"workspace_id" TEXT NOT NULL,
|
|
27
|
-
"provider" VARCHAR(32) NOT NULL,
|
|
28
|
-
"credential_ciphertext" TEXT NOT NULL,
|
|
29
|
-
"webhook_token" VARCHAR(64) NOT NULL,
|
|
30
|
-
"webhook_secret_ciphertext" TEXT NOT NULL,
|
|
31
|
-
"base_url" TEXT,
|
|
32
|
-
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
33
|
-
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
34
|
-
|
|
35
|
-
CONSTRAINT "scheduling_connections_pkey" PRIMARY KEY ("id")
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
-- CreateIndex
|
|
39
|
-
CREATE UNIQUE INDEX "scheduling_connections_workspace_id_key" ON "scheduling_connections"("workspace_id");
|
|
40
|
-
|
|
41
|
-
-- CreateIndex
|
|
42
|
-
CREATE UNIQUE INDEX "scheduling_connections_webhook_token_key" ON "scheduling_connections"("webhook_token");
|
|
43
|
-
|
|
44
|
-
-- ADR-0031 rule 3 — scheduling_connections: schconn_ (registered in
|
|
45
|
-
-- packages/ids/src/registry.ts ENTITY_PREFIX.schedulingConnection; this
|
|
46
|
-
-- migration's path is added to migration-sync.test.ts's PK_CHECK_MIGRATIONS).
|
|
47
|
-
ALTER TABLE "scheduling_connections" ALTER COLUMN "id" TYPE text COLLATE "C";
|
|
48
|
-
ALTER TABLE "scheduling_connections" ALTER COLUMN "id" SET DEFAULT ('schconn_'::text || (uuidv7())::text);
|
|
49
|
-
ALTER TABLE "scheduling_connections" ADD CONSTRAINT "scheduling_connections_id_format" CHECK ("id" ~ '^schconn_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
-- #3591 — the agent seat, step A (spec
|
|
2
|
-
-- docs/specs/3591-tenant-scoped-agent-auth-secure-spec.md D1).
|
|
3
|
-
--
|
|
4
|
-
-- agents (auth) — one row per agent: a stored delegate of ONE person (its
|
|
5
|
-
-- responsible Membership), bound to ONE workspace. It stores
|
|
6
|
-
-- the SHA-256 digest of the agent's key, never the key.
|
|
7
|
-
-- Deleting the organization, the workspace or the person's
|
|
8
|
-
-- membership deletes the agent; deleting the membership of
|
|
9
|
-
-- the person who was last shown its key sets
|
|
10
|
-
-- key_issued_to_membership_id null, which the guard refuses
|
|
11
|
-
-- until the agent is re-keyed. created_by_user_id is a plain
|
|
12
|
-
-- column with no foreign key, so deleting the creator does
|
|
13
|
-
-- not delete the agents they made for someone else.
|
|
14
|
-
--
|
|
15
|
-
-- PURELY ADDITIVE: one new enum, one new table, its indexes and four FKs (to
|
|
16
|
-
-- "organizations", "workspaces" and twice to "memberships"). No statement
|
|
17
|
-
-- touches an existing table's rows or columns, so there is no pre-assertion
|
|
18
|
-
-- block — this migration cannot lose a row.
|
|
19
|
-
--
|
|
20
|
-
-- Rollback: DROP TABLE "agents"; DROP TYPE "AgentPermissionLevel". Safe while
|
|
21
|
-
-- nothing but #3591's own code reads them.
|
|
22
|
-
|
|
23
|
-
-- CreateEnum
|
|
24
|
-
CREATE TYPE "AgentPermissionLevel" AS ENUM ('member');
|
|
25
|
-
|
|
26
|
-
-- CreateTable
|
|
27
|
-
CREATE TABLE "agents" (
|
|
28
|
-
"id" TEXT NOT NULL DEFAULT ('agent_'::text || (uuidv7())::text),
|
|
29
|
-
"organization_id" TEXT NOT NULL,
|
|
30
|
-
"workspace_id" TEXT NOT NULL,
|
|
31
|
-
"responsible_membership_id" TEXT NOT NULL,
|
|
32
|
-
"name" VARCHAR(80) NOT NULL,
|
|
33
|
-
"permission_level" "AgentPermissionLevel" NOT NULL DEFAULT 'member',
|
|
34
|
-
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
35
|
-
"credential_hash" CHAR(64) NOT NULL,
|
|
36
|
-
"credential_prefix" VARCHAR(24) NOT NULL,
|
|
37
|
-
"last_active_at" TIMESTAMP(3),
|
|
38
|
-
"created_by_user_id" TEXT NOT NULL,
|
|
39
|
-
"key_issued_to_membership_id" TEXT,
|
|
40
|
-
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
41
|
-
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
42
|
-
|
|
43
|
-
CONSTRAINT "agents_pkey" PRIMARY KEY ("id")
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
-- CreateIndex
|
|
47
|
-
-- The lookup an agent's every request makes (`findAgentByKeyHash`).
|
|
48
|
-
CREATE UNIQUE INDEX "agents_credential_hash_key" ON "agents"("credential_hash");
|
|
49
|
-
|
|
50
|
-
-- CreateIndex
|
|
51
|
-
CREATE INDEX "agents_organization_id_idx" ON "agents"("organization_id");
|
|
52
|
-
|
|
53
|
-
-- CreateIndex
|
|
54
|
-
CREATE INDEX "agents_workspace_id_idx" ON "agents"("workspace_id");
|
|
55
|
-
|
|
56
|
-
-- CreateIndex
|
|
57
|
-
CREATE INDEX "agents_responsible_membership_id_idx" ON "agents"("responsible_membership_id");
|
|
58
|
-
|
|
59
|
-
-- AddForeignKey
|
|
60
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
61
|
-
|
|
62
|
-
-- AddForeignKey
|
|
63
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
64
|
-
|
|
65
|
-
-- AddForeignKey
|
|
66
|
-
-- Leaving stops the agent: removing the person's membership deletes it.
|
|
67
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_responsible_membership_id_fkey" FOREIGN KEY ("responsible_membership_id") REFERENCES "memberships"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
68
|
-
|
|
69
|
-
-- AddForeignKey
|
|
70
|
-
-- A key dies with the person who received it: SET NULL, which the guard refuses.
|
|
71
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_key_issued_to_membership_id_fkey" FOREIGN KEY ("key_issued_to_membership_id") REFERENCES "memberships"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
72
|
-
|
|
73
|
-
-- ADR-0031 rule 3 — agents: agent_ (registered in packages/ids/src/registry.ts;
|
|
74
|
-
-- this migration's path is added to migration-sync.test.ts's
|
|
75
|
-
-- PK_CHECK_MIGRATIONS). Each reference column carries the format CHECK of the
|
|
76
|
-
-- entity it names, in the exact pattern the spoke migration uses.
|
|
77
|
-
ALTER TABLE "agents" ALTER COLUMN "id" TYPE text COLLATE "C";
|
|
78
|
-
ALTER TABLE "agents" ALTER COLUMN "id" SET DEFAULT ('agent_'::text || (uuidv7())::text);
|
|
79
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_id_format" CHECK ("id" ~ '^agent_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
80
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_organization_id_format" CHECK ("organization_id" ~ '^org_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
81
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
82
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_responsible_membership_id_format" CHECK ("responsible_membership_id" ~ '^member_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
83
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_key_issued_to_membership_id_format" CHECK ("key_issued_to_membership_id" ~ '^member_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
84
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_created_by_user_id_format" CHECK ("created_by_user_id" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
-- #7803 — sign-in lands in the user's last workspace (spec
|
|
2
|
-
-- docs/specs/7803-sign-in-last-workspace-spec.md D1).
|
|
3
|
-
--
|
|
4
|
-
-- users.last_workspace_id (auth) — the workspace this person last activated.
|
|
5
|
-
-- Written only by activateWorkspace after its membership
|
|
6
|
-
-- grant; read only by listTenancy, which reports it only
|
|
7
|
-
-- when the workspace is in the caller's own listing
|
|
8
|
-
-- (apps/api/src/services/tenant-context.ts). Deleting the
|
|
9
|
-
-- workspace sets it null.
|
|
10
|
-
--
|
|
11
|
-
-- PURELY ADDITIVE: one nullable column with no default, its index, one FK to
|
|
12
|
-
-- "workspaces" and the ADR-0031 format CHECK on the new reference column. No
|
|
13
|
-
-- backfill runs and no existing row changes, so there is no pre-assertion
|
|
14
|
-
-- block — this migration cannot lose a row. A NULL passes the CHECK.
|
|
15
|
-
--
|
|
16
|
-
-- Rollout: deploy this migration BEFORE the API code that reads the column
|
|
17
|
-
-- (SEC-7803-3). Being nullable, it is safe to apply ahead of the code.
|
|
18
|
-
--
|
|
19
|
-
-- Rollback: ALTER TABLE "users" DROP COLUMN "last_workspace_id"; (this drops
|
|
20
|
-
-- the index, the FK and the CHECK with it). Safe while nothing but #7803's own
|
|
21
|
-
-- code reads it.
|
|
22
|
-
|
|
23
|
-
-- AlterTable
|
|
24
|
-
ALTER TABLE "users" ADD COLUMN "last_workspace_id" TEXT;
|
|
25
|
-
|
|
26
|
-
-- CreateIndex
|
|
27
|
-
CREATE INDEX "users_last_workspace_id_idx" ON "users"("last_workspace_id");
|
|
28
|
-
|
|
29
|
-
-- AddForeignKey
|
|
30
|
-
-- A deleted workspace clears every pointer to it.
|
|
31
|
-
ALTER TABLE "users" ADD CONSTRAINT "users_last_workspace_id_fkey" FOREIGN KEY ("last_workspace_id") REFERENCES "workspaces"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
32
|
-
|
|
33
|
-
-- ADR-0031 rule 3 — the reference column carries the format CHECK of the
|
|
34
|
-
-- entity it names (wksp_), in the exact pattern the agents migration uses.
|
|
35
|
-
ALTER TABLE "users" ADD CONSTRAINT "users_last_workspace_id_format" CHECK ("last_workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
-- #7869 (spoke-pattern roadmap Phase 1, D5) — Lead idempotency key: the
|
|
2
|
-
-- caller's optional `Idempotency-Key` header on POST /v1/leads/submit, so a
|
|
3
|
-
-- retried lead write (a client retry, a spoke's fulfilment replay) finds the
|
|
4
|
-
-- first lead instead of writing a second. Mirrors the column-add shape of
|
|
5
|
-
-- 20260906000000_add_flow_checkout_idempotency (one AlterTable, one unique
|
|
6
|
-
-- index under the Prisma section headers).
|
|
7
|
-
--
|
|
8
|
-
-- The column is nullable with no default, so no pre-existing row needs a
|
|
9
|
-
-- backfill and none collides on the new unique — Postgres treats NULLs as
|
|
10
|
-
-- distinct. The unique is scoped by workspace_id: one key in two workspaces
|
|
11
|
-
-- is two leads.
|
|
12
|
-
--
|
|
13
|
-
-- Rollback: ALTER TABLE "leads" DROP COLUMN "idempotency_key"; (the index
|
|
14
|
-
-- goes with it).
|
|
15
|
-
|
|
16
|
-
-- AlterTable
|
|
17
|
-
ALTER TABLE "leads" ADD COLUMN "idempotency_key" TEXT;
|
|
18
|
-
|
|
19
|
-
-- CreateIndex
|
|
20
|
-
CREATE UNIQUE INDEX "leads_workspace_id_idempotency_key_key" ON "leads"("workspace_id", "idempotency_key");
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
-- #7864 — grant an agent key five named abilities (spec
|
|
2
|
-
-- docs/specs/7864-agent-key-grants-spec.md D2).
|
|
3
|
-
--
|
|
4
|
-
-- agents.grants (auth) — the permissions an owner or admin granted this
|
|
5
|
-
-- agent one by one. Written only by setServedAgentGrants
|
|
6
|
-
-- (apps/api/src/lib/agent-store.ts, the PUT
|
|
7
|
-
-- …/agents/:agentId/grants route); read by the auth
|
|
8
|
-
-- preHandler's key lookup and the agent list. The tenant
|
|
9
|
-
-- guards hold an agent to the grants its person's own role
|
|
10
|
-
-- also holds, so a stored grant never outranks the person.
|
|
11
|
-
--
|
|
12
|
-
-- The CHECK names the same five permissions as @working-theory/validation's
|
|
13
|
-
-- AGENT_GRANTABLE_PERMISSIONS; database/__tests__/agents.db.test.ts reads
|
|
14
|
-
-- this file and fails if the two lists differ (SEC-7864-G).
|
|
15
|
-
--
|
|
16
|
-
-- PURELY ADDITIVE: one NOT NULL column with an empty-array default and its
|
|
17
|
-
-- CHECK. No backfill runs: every existing agent takes the default, no
|
|
18
|
-
-- grants, and so behaves exactly as before. No existing row changes beyond
|
|
19
|
-
-- the default fill, so there is no pre-assertion block.
|
|
20
|
-
--
|
|
21
|
-
-- Rollout: deploy this migration BEFORE the API code that reads the column.
|
|
22
|
-
-- Code without the column fails closed — its key lookup errors and every
|
|
23
|
-
-- agent is answered 401 (SEC-7864-F).
|
|
24
|
-
--
|
|
25
|
-
-- Rollback: ALTER TABLE "agents" DROP COLUMN "grants"; (this drops the CHECK
|
|
26
|
-
-- with it). Safe while nothing but #7864's own code reads it.
|
|
27
|
-
|
|
28
|
-
-- AlterTable
|
|
29
|
-
ALTER TABLE "agents" ADD COLUMN "grants" TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[];
|
|
30
|
-
|
|
31
|
-
-- Only the five grantable permissions may be stored.
|
|
32
|
-
ALTER TABLE "agents" ADD CONSTRAINT "agents_grants_allowed"
|
|
33
|
-
CHECK ("grants" <@ ARRAY['content-edit','content-publish','assets-write','magnets-manage','meeting-types-manage']::TEXT[]);
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
-- #852 — Person, the per-workspace client record (spec
|
|
2
|
-
-- docs/specs/852-person-the-per-workspace-client-spec.md D1, D2).
|
|
3
|
-
--
|
|
4
|
-
-- people (inbox) — one client of one workspace, keyed on a lowercased,
|
|
5
|
-
-- trimmed email unique per workspace. Created only by
|
|
6
|
-
-- apps/api/src/services/person.ts's findOrCreatePerson.
|
|
7
|
-
-- workspace_id and user_id are plain columns with no
|
|
8
|
-
-- foreign key (ADR 0009): they name auth-namespace rows.
|
|
9
|
-
-- leads.person_id, appointments.person_id — the Person each row belongs
|
|
10
|
-
-- to, stamped at creation by the intake paths.
|
|
11
|
-
--
|
|
12
|
-
-- PURELY ADDITIVE, DDL ONLY: one new table with its indexes and CHECKs, and
|
|
13
|
-
-- one nullable column with no default on each of "leads" and "appointments",
|
|
14
|
-
-- so Postgres changes only the catalog for those two. No existing row's
|
|
15
|
-
-- values change here — the backfill is the next migration,
|
|
16
|
-
-- 20261010121000_person_backfill, split out so its row updates never run
|
|
17
|
-
-- under the exclusive locks these ALTER TABLEs take (SEC-852-E). Prisma runs
|
|
18
|
-
-- this file as one transaction, so each ALTER TABLE's ACCESS EXCLUSIVE lock
|
|
19
|
-
-- is held until the file commits — through the plain CREATE INDEX on the new
|
|
20
|
-
-- column — blocking reads AND writes of "leads" and "appointments" (lead
|
|
21
|
-
-- capture included) for one heap scan of each. Accepted: the scan is short
|
|
22
|
-
-- next to the backfill it is split from.
|
|
23
|
-
--
|
|
24
|
-
-- Rollout: deploy this migration (and the backfill) BEFORE the API code that
|
|
25
|
-
-- writes person_id; code without the column fails every lead write.
|
|
26
|
-
--
|
|
27
|
-
-- Rollback: ALTER TABLE "leads" DROP COLUMN "person_id"; ALTER TABLE
|
|
28
|
-
-- "appointments" DROP COLUMN "person_id"; DROP TABLE "people"; (the indexes
|
|
29
|
-
-- and CHECKs go with them). Safe while nothing but #852's own code reads them.
|
|
30
|
-
|
|
31
|
-
-- AlterTable
|
|
32
|
-
ALTER TABLE "appointments" ADD COLUMN "person_id" TEXT;
|
|
33
|
-
|
|
34
|
-
-- AlterTable
|
|
35
|
-
ALTER TABLE "leads" ADD COLUMN "person_id" TEXT;
|
|
36
|
-
|
|
37
|
-
-- CreateTable
|
|
38
|
-
CREATE TABLE "people" (
|
|
39
|
-
"id" TEXT NOT NULL DEFAULT ('person_'::text || (uuidv7())::text),
|
|
40
|
-
"workspace_id" TEXT NOT NULL,
|
|
41
|
-
"email" VARCHAR(254) NOT NULL,
|
|
42
|
-
"name" VARCHAR(200),
|
|
43
|
-
"user_id" TEXT,
|
|
44
|
-
"billing_provider" VARCHAR(32),
|
|
45
|
-
"billing_customer_id" VARCHAR(255),
|
|
46
|
-
"plan_offering" VARCHAR(100),
|
|
47
|
-
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
48
|
-
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
49
|
-
|
|
50
|
-
CONSTRAINT "people_pkey" PRIMARY KEY ("id")
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
-- CreateIndex
|
|
54
|
-
-- The webhook's first match: a customer id within one workspace (D3 step 2).
|
|
55
|
-
-- NOT unique — the spokes share one Stripe account.
|
|
56
|
-
CREATE INDEX "people_workspace_id_billing_customer_id_idx" ON "people"("workspace_id", "billing_customer_id");
|
|
57
|
-
|
|
58
|
-
-- CreateIndex
|
|
59
|
-
-- The People list: workspace_id = $1 ORDER BY created_at DESC (D7).
|
|
60
|
-
CREATE INDEX "people_workspace_id_created_at_idx" ON "people"("workspace_id", "created_at");
|
|
61
|
-
|
|
62
|
-
-- CreateIndex
|
|
63
|
-
-- One Person per address per workspace — what findOrCreatePerson's
|
|
64
|
-
-- INSERT … ON CONFLICT DO NOTHING absorbs a concurrent duplicate on.
|
|
65
|
-
CREATE UNIQUE INDEX "people_workspace_id_email_key" ON "people"("workspace_id", "email");
|
|
66
|
-
|
|
67
|
-
-- CreateIndex
|
|
68
|
-
-- One Person per User per workspace. NULLs are distinct, so any number of
|
|
69
|
-
-- unlinked Persons fit.
|
|
70
|
-
CREATE UNIQUE INDEX "people_workspace_id_user_id_key" ON "people"("workspace_id", "user_id");
|
|
71
|
-
|
|
72
|
-
-- CreateIndex
|
|
73
|
-
CREATE INDEX "appointments_person_id_idx" ON "appointments"("person_id");
|
|
74
|
-
|
|
75
|
-
-- CreateIndex
|
|
76
|
-
CREATE INDEX "leads_person_id_idx" ON "leads"("person_id");
|
|
77
|
-
|
|
78
|
-
-- ADR-0031 rule 3 — people: person_ (registered in packages/ids/src/registry.ts;
|
|
79
|
-
-- this migration's path is added to migration-sync.test.ts's
|
|
80
|
-
-- PK_CHECK_MIGRATIONS). Each reference column carries the format CHECK of the
|
|
81
|
-
-- entity it names, in the agents-migration shape.
|
|
82
|
-
ALTER TABLE "people" ALTER COLUMN "id" TYPE text COLLATE "C";
|
|
83
|
-
ALTER TABLE "people" ALTER COLUMN "id" SET DEFAULT ('person_'::text || (uuidv7())::text);
|
|
84
|
-
ALTER TABLE "people" ADD CONSTRAINT "people_id_format" CHECK ("id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
85
|
-
ALTER TABLE "people" ADD CONSTRAINT "people_workspace_id_format" CHECK ("workspace_id" ~ '^wksp_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
86
|
-
ALTER TABLE "people" ADD CONSTRAINT "people_user_id_format" CHECK ("user_id" ~ '^user_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$');
|
|
87
|
-
|
|
88
|
-
-- The stored address is already normalized: printable ASCII only (no
|
|
89
|
-
-- whitespace, no control or invisible character), exactly one @ with a
|
|
90
|
-
-- non-empty side each, lower case. findOrCreatePerson's
|
|
91
|
-
-- isStorablePersonEmail applies the same rule before any write (D3).
|
|
92
|
-
ALTER TABLE "people" ADD CONSTRAINT "people_email_normalized"
|
|
93
|
-
CHECK ("email" = lower("email" COLLATE "C") AND "email" ~ '^[!-?A-~]+@[!-?A-~]+$');
|
|
94
|
-
|
|
95
|
-
-- A provider and its customer id are written together or not at all — the
|
|
96
|
-
-- same provider-agnostic pair User and Organization carry.
|
|
97
|
-
ALTER TABLE "people" ADD CONSTRAINT "people_billing_pair"
|
|
98
|
-
CHECK (("billing_provider" IS NULL) = ("billing_customer_id" IS NULL));
|
|
99
|
-
|
|
100
|
-
-- The two new reference columns carry the person_ format CHECK, added NOT
|
|
101
|
-
-- VALID and then validated: the file runs as one transaction, so the ALTER
|
|
102
|
-
-- TABLE's lock is still held, and the scan is of an all-NULL column.
|
|
103
|
-
ALTER TABLE "leads" ADD CONSTRAINT "leads_person_id_format" CHECK ("person_id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') NOT VALID;
|
|
104
|
-
ALTER TABLE "leads" VALIDATE CONSTRAINT "leads_person_id_format";
|
|
105
|
-
ALTER TABLE "appointments" ADD CONSTRAINT "appointments_person_id_format" CHECK ("person_id" ~ '^person_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') NOT VALID;
|
|
106
|
-
ALTER TABLE "appointments" VALIDATE CONSTRAINT "appointments_person_id_format";
|