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:
status:ready,needs_env,needs_connection, orpreview_only.requiredEnv: environment variable names with boolean presence only; secret values are never returned.previewConfigured: local preview/config state exists.liveConnected: OAuth or live credential state exists for the current firm/user.liveReady: all required env and live connection checks pass.blockingReason: user-facing reason when launch smoke cannot run.
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:
- OAuth/readiness state and blocking reason.
- Token and credential expiry state.
- Webhook endpoint health, failed deliveries, and dead letters.
- Last sync, sync backlog, and last failure.
- Replay backlog plus an Open replay queue control that routes operators to the webhook replay surface.
- Failed jobs as an explicit summary and connector metric.
- Impacted workflows, recent provider actions, health signals, and next best actions.
Navigation rules:
- Admins see Reliability under the Integrations section in production mode.
- Non-admin users do not see the admin-only page/action.
- Command palette access mirrors the Integrations navigation.
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:
/api/integrations/readinessreports every target provider asliveReady: trueand does not leak secret values./integrationsrenders target provider cards or readiness rows in an authenticated browser session.- OAuth providers, including calendar and workspace sync providers, return external authorization URLs with app callback redirect URIs.
- Live mutation mode calls provider-backed sync/send actions instead of local preview actions.
- Webhook mode verifies provider callback handshakes for QuickBooks, Adobe Sign, Microsoft Calendar, Google Calendar, Twilio, and DocuSign.
Safety rules:
- Never set
CASESOLO_REAL_PROVIDER_MUTATE=1against production firms unless the smoke recipients/accounts are approved for test traffic. - Twilio delivery uses
send_sms_live, which calls the production Twilio client and applies TCPA consent checks. - Twilio production messaging now supports Messaging Service routing, status callbacks, strict webhook signature verification, inbound contact/case threading, and TCPA-aware SMS templates.
- DocuSign and Adobe Sign delivery can send real signature traffic. Prefer sandbox accounts and dedicated smoke templates.
- A passing default skip is not a launch claim; launch claims require an enabled credentialed run and saved evidence.
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.