Skip to content

Connection

A Connection is inseam’s plugin-defined port for reaching a data endpoint: a Gmail mailbox, a Twilio account, a local filesystem, a paired Apple Watch, another inseam node. A plugin contributes a ConnectionDefinition per kind it supports; core registers it, drives interactive setup, persists the credential opaquely, runs liveness verification, and tears the connection down on uninstall. Plugins compile against @inseam/connection-contract alone.

Connection is one leg of the Connection / Source / Access split:

  • Connection holds reach — how to talk to an endpoint, and whether it’s currently live.
  • Source holds addresses — the indexable rows you want to remember.
  • Access holds scope — who is permitted to see what.

A Connection row stores the opaque credential blob plus liveness metadata. Core never decodes the credential; it calls serializeCredential once on setup completion and parseCredential per verify / teardown.

Two surfaces, split by package:

  • @inseam/connection-contractConnectionDefinition, SetupStep, SetupContext, VerifyContext, VerifyResult, InboundHttpService, CallbackHandle, plus the error hierarchy. Zero runtime deps.
  • @inseam/core (Connection contribution) — openConnectionRegistry, Connection, ConnectionRegistry, SetupSession. Owns the in-memory kind table, persistence, atomic liveness updates, and process-local liveness subscriptions.
  • ConnectionDefinition<Cred> — the contract a plugin implements per Connection kind. Declares kind, displayName, capabilities; supplies setup, serializeCredential/parseCredential, verify, teardown.
  • SetupStep — discriminated union (prompt, redirect, terminal done/failed) yielded from the plugin’s setup iterator. The host renders each step and calls advanceSetup to resume the iterator.
  • InboundHttpService — host-supplied service for OAuth-style redirect flows. A redirect step resumes itself when its awaitCallback() fires.
  • Liveness — coarse: live / offline / failing / unknown. A failing endpoint is data (liveness: "failing"), not an exception. Subscribers see process-local change events via Connection.onLivenessChange.

Exact signatures: @inseam/connection-contract API · arch/connection/spec.md.

Connections describe reach, not addresses or permissions. If you are tempted to put indexable data on a Connection row, that probably belongs on a Source instead. If you are tempted to put visibility rules on a Connection, that belongs in Access.

For OAuth2 specifically, the Connection OAuth2 helper is a one-liner factory that produces a complete ConnectionDefinition. Write ConnectionDefinition from scratch for API-key flows, webhook-secret flows, or any non-OAuth shape.

  • LLM summary — dense reference for agents.
  • Connection OAuth2 helper — the common-case factory.
  • Source — addresses live here, not on Connection rows.
  • Access — permissions live here.
  • arch/connection/design.md — why Connection is decoupled from Source and Access.
  • arch/connection/spec.md — types, behavior, errors, acceptance criteria.