Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt

Use this file to discover all available pages before exploring further.

A workspace_connector is an activation record that binds a generic Connector definition to a specific workspace, creating a live, credentialed integration instance. It is the unit of auth lifecycle management: it carries the per-workspace OAuth credentials (access token, refresh token, DCR client ID) inside an optional JSONB config column, tracks the lifecycle status of the integration, and optionally links to the Person who owns or administers the connection. Every sync run, connector mapping, and sync diagnostic in the pipeline is scoped to a workspace_connector. It serves as the FK target for junction tables ({entity}_workspace_connectors, workspace_connector_sync_targets, workspace_connector_sync_logs) and is the sourceWorkspaceConnector provenance pointer on ingested entities.
NamingValue
ObjectWorkspace Connector
Resource type (JSON:API type)workspace_connector
Collection / records rootworkspace_connectors
REST base/v1/workspace-connectors
Entity classWorkspaceConnector

API operations

OperationMethod & pathStatus
ListGET /v1/workspace-connectors✅ Implemented
RetrieveGET /v1/workspace-connectors/{id}✅ Implemented
CreatePOST /v1/workspace-connectors🟡 Planned
UpdatePATCH /v1/workspace-connectors/{id}🟡 Planned
DeleteDELETE /v1/workspace-connectors/{id}🟡 Planned

Data model

Attributes

FieldTypeRequiredConstraintsAllowed valuesDescription
workspace_connector_idstring, UUID✅ Yesunique, gen on onCreate via randomUUID()Public-facing stable identifier for this connector instance. Used as the external reference in all API responses and OAuth state parameters. Generated at row creation; never changes.
statusstring (StatusEnum)✅ Yesnative PG enum status_enumenabled, disabled, to_configure, processing, error, need_reconnect, suspendedCurrent lifecycle state of the connector instance. enabled means tokens are valid and sync can run. need_reconnect indicates token expiry or revocation requiring user re-auth. processing is set during an active sync run. error indicates a non-recoverable failure. suspended indicates a billing- or admin-triggered pause. to_configure is the initial state before OAuth is completed.
configjsonb, object⚪ Nonullable JSONB; never exposed in plaintext API responses without scrubbingPer-workspace encrypted credential store. For MCP OAuth connectors holds: client_id (DCR-registered or pre-configured), client_secret, dcr_access_token, access_token, refresh_token, token_expires_at (ISO-8601 string), pkce_code_verifier (ephemeral, cleared after exchange), pkce_state (ephemeral). Also stores provider-specific runtime metadata (e.g. tenant name, scopes) written back by McpOAuthService after token exchange. For API-key connectors, stores api_key. For WSSE connectors, stores auth_wsse.username and auth_wsse.secret.
created_attimestamp with time zone, 🔒 system✅ Yesset once on onCreate; never updatedRow creation timestamp. Set by MikroORM lifecycle hook on insert. Immutable after creation.
updated_attimestamp with time zone, 🔒 system⚪ Noset on onCreate and updated on every onUpdateLast-modified timestamp. Updated by MikroORM lifecycle hook on every persist. Null only if the row has never been updated after insert (edge case).
deleted_attimestamp with time zone⚪ Nonullable; soft-delete pattern — null means activeSoft-delete timestamp. When set, the connector instance is considered disconnected. All downstream queries filter deleted_at IS NULL to exclude soft-deleted connectors. A soft-deleted row preserves audit trail and is the trigger for token revocation on the provider side.

Relationships

NameTypeRequiredDescription
connectorto-one (Connector)✅ YesThe canonical connector definition this instance activates. Carries provider type, category/service IDs, authorization flow, transport type, auth_config (OAuth metadata URL, MCP server URL), and supported target models. A single Connector can have many workspace_connector activations across different workspaces.
workspaceto-one (Workspace)✅ YesThe workspace that owns and operates this connector instance. Acts as the tenant boundary: every sync run, entity ingested, and sync target scoped to this workspace_connector is isolated within this workspace.
personto-one (People)⚪ NoThe person (workspace member) who owns or administered the connection. Optional — connectors created programmatically (e.g. via API key or admin seeding) may have no person owner. Indexed via idx_workspace_connectors_person.
filter (virtual)to-one (ConnectorFilter)⚪ NoVirtual property — NOT a persisted FK column. Populated at query time by WorkspaceConnectorRepository. Resolves to either a custom ConnectorFilter for this workspace, or the template filter for the connector. Controls what data is ingested (e.g. date range, account scope). Not stored on the workspace_connectors table itself.
syncTargets (WorkspaceConnectorSyncTarget) — inverse referenceto-many (WorkspaceConnectorSyncTarget)⚪ NoInverse reference — NOT declared as @OneToMany on WorkspaceConnector. WorkspaceConnectorSyncTarget declares @ManyToOne(() => WorkspaceConnector). Junction rows defining which target workspaces this connector ingests data into (added in Migration20260527140000). Each row links this connector to a target_workspace_pk. Partial unique index idx_wcst_unique_active prevents duplicate active targets. Backfilled with a 1:1 self-pointing row for all pre-existing connectors.
connectorMappings (ConnectorMapping) — inverse referenceto-many (ConnectorMapping)⚪ NoInverse reference — NOT declared as @OneToMany on WorkspaceConnector. ConnectorMapping declares @ManyToOne({ entity: () => WorkspaceConnector, fieldName: 'workspace_connector_pk' }). The JSONata sync mapping configurations generated by the structured-jury pipeline for each target model (company, invoice, transaction, etc.). One mapping row per (workspace_connector, target_model). Holds the compiled JSONata expression, last_persist_count, and needs_regeneration flag.
syncDiagnostics (ConnectorSyncDiagnostic) — inverse referenceto-many (ConnectorSyncDiagnostic)⚪ NoInverse reference — NOT declared as @OneToMany on WorkspaceConnector. ConnectorSyncDiagnostic declares @ManyToOne({ entity: () => WorkspaceConnector, fieldName: 'workspace_connector_pk' }). Diagnostic and observability rows emitted by the sync pipeline — jury runs, schema drift, mapping failures, regression reverts. Each row references this workspace_connector as the sync context.
syncLogs (WorkspaceConnectorSyncLog) — inverse referenceto-many (WorkspaceConnectorSyncLog)⚪ NoInverse reference — NOT declared as @OneToMany on WorkspaceConnector. WorkspaceConnectorSyncLog declares @ManyToOne(() => WorkspaceConnector, { deleteRule: 'cascade' }). Sync execution log rows emitted per sync run. CASCADE-delete: all log rows are deleted when the parent workspace_connector row is hard-deleted.
documentWorkspaceConnectors (DocumentWorkspaceConnector) — inverse referenceto-many (DocumentWorkspaceConnector)⚪ NoInverse reference — NOT declared as @OneToMany on WorkspaceConnector. Junction table tracking which documents were ingested by this connector, with direction discrimination (input vs output). Equivalent to the company/people/account/invoice/transaction junction tables; DocumentWorkspaceConnector declares @ManyToOne(() => WorkspaceConnector).

System-computed

  • workspace_connector_id is generated via randomUUID() on the MikroORM onCreate hook — equivalent to gen_random_uuid() in Postgres.
  • created_at is set once on onCreate and is immutable. updated_at is refreshed on every onUpdate lifecycle call.
  • deleted_at follows the platform-wide soft-delete convention: null = active, non-null = soft-deleted. Downstream queries and Hasura RLS always filter deleted_at IS NULL.
  • config is a free-form JSONB column typed as Record<string, any> in the ORM. At runtime it is cast to McpOAuthWorkspaceConfig by McpOAuthService. The known sub-fields are: client_id, client_secret, dcr_access_token, access_token, refresh_token, token_expires_at, pkce_code_verifier (ephemeral — cleared after PKCE exchange), pkce_state (ephemeral — cleared after callback), plus provider-specific keys written back after token exchange (e.g. tenant info).
  • filter is a virtual (non-persisted) property. WorkspaceConnectorRepository resolves it at query time by finding either a workspace-scoped ConnectorFilter or the connector template filter. It does not correspond to any column on the workspace_connectors table.
  • The internal pk is an auto-increment integer used exclusively for FK joins. All public-facing references use workspace_connector_id (UUID).
  • OAuth state tracking for PKCE flows: McpOAuthService.getAuthorizationUrl() writes pkce_code_verifier and pkce_state into config before redirect; McpOAuthService.exchangeCodeForTokens() clears them and writes access_token, refresh_token, token_expires_at in their place.
  • DCR (Dynamic Client Registration): McpOAuthService.ensureClientRegistered() checks config.client_id before writing a new DCR client. Each workspace_connector gets its own OAuth client registered with the provider — DCR is per-workspace-connector, not per-connector-template.
  • Token refresh buffer: McpOAuthService refreshes when token_expires_at is within 5 minutes of expiry (enforced as an architectural constant).
  • The junction tables {entity}_workspace_connectors (company, people, account, invoice, transaction, document) reference workspace_connector_pk via FK — they track which connector ingested each entity row, with direction discrimination (input vs output).
  • workspace_connector_sync_targets was backfilled via Migration20260527140000 with a 1:1 self-pointing row for every active pre-existing connector to preserve legacy single-workspace ingestion semantics.
  • Composite idx_workspace_connectors_workspace_deleted on (workspace_pk, deleted_at) supports the hot-path workspace-scoped connector list query. Additional indexes on connector_pk, person_pk, and status support secondary traversals.
  • The WorkspaceConnectorSyncLog relationship carries deleteRule: 'cascade' on the child side — hard-deleting a workspace_connector row cascades to remove all associated sync log rows.

Example

{
  "type": "workspace_connector",
  "id": "a3c7e2b1-84f0-4d1e-9c3a-0f2b6d8e1a7c",
  "attributes": {
    "workspace_connector_id": "a3c7e2b1-84f0-4d1e-9c3a-0f2b6d8e1a7c",
    "status": "enabled",
    "config": {
      "client_id": "well_dcr_abc123",
      "dcr_access_token": "ey...",
      "access_token": "ey...",
      "refresh_token": "rt_xyz789",
      "token_expires_at": "2026-06-02T18:00:00.000Z"
    },
    "created_at": "2026-02-14T10:23:00.000Z",
    "updated_at": "2026-06-01T08:42:11.000Z",
    "deleted_at": null
  },
  "relationships": {
    "connector": {
      "data": { "type": "connector", "id": "b8f1d3a2-5c20-4e6b-8d4a-1e9c7f3b2d01" }
    },
    "workspace": {
      "data": { "type": "workspace", "id": "9f3e1c7a-2d44-4b8e-a1f5-0c6b3e9d7e42" }
    },
    "person": {
      "data": { "type": "people", "id": "d4a2c8f0-1b35-4c7d-90e2-5f8a6b3c1d20" }
    }
  }
}
Source: apps/api/src/database/entities/WorkspaceConnector.ts · domain: ingestion · tier: Platform