Skip to content

Integration Readiness

Updated: 2026-07-01

CaseSolo separates local preview configuration from live provider readiness. A provider is not launch-ready just because a local settings form works.

Provider Initialization Safety

All external provider clients use lazy initialization with explicit error messages when env vars are missing. This prevents crashes on import and gives clear diagnostics:

| Provider | Guard Pattern | File | |----------|--------------|------| | Stripe | getStripe() lazy getter, checks STRIPE_SECRET_KEY | src/lib/billing/stripe.ts | | Usermails | providerSend() + isEmailConfigured() | src/lib/email/client.ts | | Deepgram | getApiKey() + isDeepgramConfigured() | src/lib/voice/deepgram-stt.ts | | S3-compatible storage | getS3Client() + isR2Configured() | src/lib/storage/r2.ts | | Anthropic | getAnthropic() lazy getter | src/lib/ai/provider.ts | | OpenAI | getOpenAIProvider() lazy getter | src/lib/ai/execute.ts | | Textract | getTextractClient() returns null | src/lib/integrations/textract.ts | | Redis | getRedis() + isRedisConfigured() | src/lib/redis/client.ts | | PostHog | Guards NEXT_PUBLIC_POSTHOG_KEY before init | src/lib/analytics/posthog.ts | | Sentry | Guards dsn before Sentry.init() | sentry.*.config.ts | | ElevenLabs | isElevenLabsConfigured() + getTTSProvider() | src/lib/voice/tts-provider.ts | | Embeddings | Each provider checks API key before fetch | src/lib/ai/embedding-providers.ts |

Readiness API

GET /api/integrations/readiness is an admin-only, secret-safe launch gate. It returns one provider record per integration with:

Reliability Center

/integrations/health is a production-visible admin surface, not a beta-preview route. It is backed by GET /api/integrations/reliability and is the operator view for launch integration health.

The screen shows:

Navigation rules:

Current Providers

| Provider | Scope | Launch Readiness Rule | |---|---|---| | QuickBooks | Firm | QUICKBOOKS_CLIENT_ID + QUICKBOOKS_CLIENT_SECRET plus firm.settings.quickbooksOAuth.connected === true | | DocuSign | Firm | DOCUSIGN_CLIENT_ID + DOCUSIGN_CLIENT_SECRET plus firm.settings.docusignOAuth.connected === true | | Adobe Sign | Firm | ADOBE_SIGN_CLIENT_ID + ADOBE_SIGN_CLIENT_SECRET plus firm.settings.adobeSignOAuth.connected === true | | Google Calendar | User | GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET plus user.metadata.googleCalendar.connected === true | | Microsoft Calendar | User | MICROSOFT_CLIENT_ID + MICROSOFT_CLIENT_SECRET plus user.metadata.microsoftCalendar.connected === true | | Google Workspace | User | GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET, user.metadata.googleWorkspace.connected === true, usable OAuth tokens, and email or Drive sync enabled | | Microsoft 365 Workspace | User | MICROSOFT_CLIENT_ID + MICROSOFT_CLIENT_SECRET, user.metadata.microsoft365Workspace.connected === true, usable OAuth tokens, and mail or Drive sync enabled | | Twilio | Firm | Stored account SID, auth token, sending number, connected === true, and smsEnabled === true | | Stripe Legal Payments | Firm | STRIPE_SECRET_KEY, Firm.settings.legalPayments.enabled === true, a Stripe Connect account ID, and at least one enabled payment-link destination | | Textract OCR | Firm | AWS_TEXTRACT_REGION or AWS_REGION, plus Textract-specific or shared AWS access key and secret key | | Observability | Firm/platform | SENTRY_DSN, NEXT_PUBLIC_SENTRY_DSN, and NEXT_PUBLIC_POSTHOG_KEY |

Credentialed Real-Provider Smoke

npm run e2e:real-providers is the supported launch-smoke entry point for live external providers. It is intentionally opt-in so local CI cannot claim real OAuth or delivery success without credentials.

Default safe mode:

npm run e2e:real-providers

Expected result without provider credentials: the wrapper prints a skip message and exits 0.

Credentialed readiness and OAuth handoff smoke:

CASESOLO_REAL_PROVIDER_SMOKE=1 \
CASESOLO_REAL_PROVIDER_TARGETS=quickbooks,docusign,adobe-sign,google-calendar,microsoft-calendar,google-workspace,microsoft-365,twilio,stripe-legal-payments,textract-ocr,observability \
npm run e2e:real-providers

Live sync/send smoke:

CASESOLO_REAL_PROVIDER_SMOKE=1 \
CASESOLO_REAL_PROVIDER_MUTATE=1 \
CASESOLO_REAL_PROVIDER_TARGETS=quickbooks,google-calendar,microsoft-calendar,google-workspace,microsoft-365,twilio,docusign,adobe-sign \
CASESOLO_REAL_PROVIDER_TWILIO_TO=+15555550199 \
CASESOLO_REAL_PROVIDER_SIGNER_EMAIL=signer@example.com \
CASESOLO_REAL_PROVIDER_SIGNER_NAME="CaseSolo Smoke Signer" \
CASESOLO_DOCUSIGN_TEMPLATE_ID=template-id \
CASESOLO_ADOBE_SIGN_LIBRARY_DOCUMENT_ID=library-document-id \
npm run e2e:real-providers

Webhook handshake smoke:

CASESOLO_REAL_PROVIDER_SMOKE=1 \
CASESOLO_REAL_PROVIDER_WEBHOOKS=1 \
CASESOLO_REAL_PROVIDER_FIRM_ID=firm_id \
npm run e2e:real-providers

The Playwright spec validates:

Safety rules:

Verification

Focused coverage:

npm run test:run -- integration-readiness integrations-readiness integration-reliability-center integrations-reliability navigation-consolidation command-palette-actions
npm run e2e:real-providers
env CASESOLO_PLAYWRIGHT_PORT=3120 npx playwright test e2e/integrations.spec.ts --project=chromium --no-deps

Full launch claims still require a credentialed browser/runtime smoke run with CASESOLO_REAL_PROVIDER_SMOKE=1 for OAuth authorization, sync/delivery actions, failure states, and user-visible recovery paths.

Source: docs/dev/integration-readiness.md