Skip to content

feat(connections): unify channel/app integration connect lifecycle - #1185

Open
realcodesiman wants to merge 2 commits into
mainfrom
feat/connection-lifecycle-redesign
Open

realcodesiman wants to merge 2 commits into
mainfrom
feat/connection-lifecycle-redesign

Conversation

@realcodesiman

Copy link
Copy Markdown
Contributor

Summary

  • Replace ~22 per-provider connect/disconnect action pairs and three cookie-based OAuth picker flows with one connection-providers / connections / connect-sessions resource family.
  • Add a server-side ConnectSession table (packages/database/src/schema/connect-session.ts) replacing the pending-auth cookies, so OAuth flows no longer depend on browser cookies and can be resumed/polled via /connect/[sessionId].
  • Serve the builder UI (private oRPC), the public API (workspace tokens), and MCP from the same registry and business services, so every IntegrationType is connectable and discoverable through one consistent surface. Legacy per-provider public lifecycle routes remain reachable but are marked deprecated.

Changes

  • New packages/connections package: provider registry + connection service.
  • New packages/business/src/connection and packages/business/src/connect-session: connection state/adapter services and session lifecycle service.
  • New DB tables/migrations: Connection, ConnectSession (packages/database/drizzle/20260914163422_consolidate_connection_scope, .../20260914170910_add_connection_tables), plus a backfill script (packages/database/scripts/backfill-connections.ts).
  • New apps/builder/src/features/connections (actions, oRPC private/public API, schemas) and apps/builder/src/app/connect/[sessionId] UI for the unified OAuth completion/handoff flow.
  • New worker schedule purge-expired-connect-sessions.
  • Removed apps/builder/src/lib/facebook-pending-auth.ts (cookie-based pending-auth) and its tests, superseded by ConnectSession.
  • Updated ~20 integration packages and their disconnect actions to route through the new connection lifecycle.
  • Updated i18n message files across all locales for new UI strings.

Test plan

  • pnpm lint / typecheck (ran automatically via pre-commit hooks — passed)
  • pnpm --filter builder check-types
  • Manually connect/disconnect a channel (e.g. Messenger) and an app integration (e.g. an AI provider) through the builder UI
  • Verify public API connections endpoints via a workspace token
  • Verify packages/database migrations apply cleanly (db:migrate — requires explicit approval per project rules)

🤖 Generated with Claude Code

Replace ~22 per-provider connect/disconnect action pairs and three
cookie-based OAuth picker flows with one connection-providers /
connections / connect-sessions resource family, backed by a new
server-side ConnectSession table instead of pending-auth cookies.

The same registry and business services now serve the builder UI
(private oRPC), the public API (workspace tokens), and MCP (generated
from the shared OpenAPI document), so every IntegrationType is
connectable and discoverable through one consistent surface. Legacy
per-provider public lifecycle routes remain but are marked deprecated.
@github-actions github-actions Bot added the feature New feature or request label Sep 15, 2026
…eview

Addresses the code-review findings on the Connection-lifecycle unification
(unify channel/app integration connect lifecycle, commit f437105):

Critical:
- ConnectSession.create writes targets/claimedTargetIds/resultConnectionIds/
  results explicitly (drizzle-kit never inlines a sql template default for
  jsonb/array columns) - every OAuth connect was NOT NULL-violating on
  insert.
- markOffline(reason) branches on instanceof AuthException: a revoked
  token still marks unhealthy, but a transient refresh failure now
  degrades (quota held) instead of releasing the channel's quota slot.
- Messenger/Instagram/InstagramFacebook disconnect actions now transition
  the Connection row (not just Inbox), fixing a quota double-charge on
  connect -> UI-disconnect -> reconnect.
- Telegram plus the 8 api_key marketing providers gained a live
  fromCredentials validator; api/smtp/webchat/chatbotx are explicitly
  gated unavailableReason "notImplemented" pending their sourceId
  identity model instead of silently 500ing.

Important:
- Telegram's Connection.sourceId derives from the bot token's numeric
  prefix instead of a colliding "workspace" constant.
- Disconnect teardown failures are surfaced onto Connection.lastError;
  the satellite-row delete and FSM transition share one db.transaction.
- Telegram's verify() returns a ConnectionHealth failure instead of
  throwing.
- drip/activeCampaign/getResponse's isRevokedTokenError TODO stubs now
  classify real 401/403 responses.
- ConnectionStateService.transition consumes quota before the status
  write (never needs a rollback) and throws instead of silently
  skipping a required quota edge with no resolvable owner.
- completeAuthorization's exchangeCode catch now records exchange_failed
  instead of overloading provider_denied (real denial is filtered
  upstream by the OAuth callback's own error query-param check).
- Messenger's exchangeCode/listCandidates carry the real callbackUrl as
  redirectUrl instead of an empty string.
- /connect is public (the ConnectSession completion page never requires
  a builder session).

Simplifications:
- packages/connections/src/service.ts split into internal.ts, lifecycle.ts,
  credentials.ts, and connect-session-flow.ts (each under the 800-line
  cap), deduplicating the revive-or-insert-then-transition block into
  upsertConnectionRow.
- Shared isUnauthorizedStatusError SDK helper replaces duplicated 401/403
  duck-typing across 7 marketing providers.
- Shared verifyMetaToken(label) factory for Messenger/Instagram-Facebook.
- .agents/rules/data-access.md documents packages/connections as the
  registry-aware tier above packages/business.

Plus test coverage for every fix above (ordering, auth-safety, scope
enforcement on the public API, the inbox-status write guard, registry
invariants) and five stale comments and docs corrected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant