> ## 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.

# Workspace Connector

> A `workspace_connector` is an activation record that binds a generic `Connector` definition to a specific workspace, creating a live, credentialed integration i

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.

| Naming                          | Value                      |
| ------------------------------- | -------------------------- |
| Object                          | Workspace Connector        |
| Resource type (JSON:API `type`) | `workspace_connector`      |
| Collection / records root       | `workspace_connectors`     |
| REST base                       | `/v1/workspace-connectors` |
| Entity class                    | `WorkspaceConnector`       |

## API operations

| Operation | Method & path                          | Status        |
| --------- | -------------------------------------- | ------------- |
| List      | `GET /v1/workspace-connectors`         | ✅ Implemented |
| Retrieve  | `GET /v1/workspace-connectors/{id}`    | ✅ Implemented |
| Create    | `POST /v1/workspace-connectors`        | 🟡 Planned    |
| Update    | `PATCH /v1/workspace-connectors/{id}`  | 🟡 Planned    |
| Delete    | `DELETE /v1/workspace-connectors/{id}` | 🟡 Planned    |

## Data model

### Attributes

| Field                    | Type                                | Required | Constraints                                                                | Allowed values                                                                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------ | ----------------------------------- | -------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| workspace\_connector\_id | string, UUID                        | ✅ Yes    | unique, 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.                                                                                                                                                                                                                                                                                                                                                                                         |
| status                   | string (StatusEnum)                 | ✅ Yes    | native PG enum `status_enum`                                               | enabled, disabled, to\_configure, processing, error, need\_reconnect, suspended | Current 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.                                                                                                                                                                      |
| config                   | jsonb, object                       | ⚪ No     | nullable JSONB; never exposed in plaintext API responses without scrubbing | —                                                                               | Per-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\_at              | timestamp with time zone, 🔒 system | ✅ Yes    | set once on onCreate; never updated                                        | —                                                                               | Row creation timestamp. Set by MikroORM lifecycle hook on insert. Immutable after creation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| updated\_at              | timestamp with time zone, 🔒 system | ⚪ No     | set on onCreate and updated on every onUpdate                              | —                                                                               | Last-modified timestamp. Updated by MikroORM lifecycle hook on every persist. Null only if the row has never been updated after insert (edge case).                                                                                                                                                                                                                                                                                                                                                                                                                            |
| deleted\_at              | timestamp with time zone            | ⚪ No     | nullable; soft-delete pattern — null means active                          | —                                                                               | Soft-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

| Name                                                                         | Type                                   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------------------------------------------------------------------- | -------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| connector                                                                    | to-one (Connector)                     | ✅ Yes    | The 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.                                                                                                                                                                                 |
| workspace                                                                    | to-one (Workspace)                     | ✅ Yes    | The 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.                                                                                                                                                                                                                                                                                             |
| person                                                                       | to-one (People)                        | ⚪ No     | The 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)               | ⚪ No     | Virtual 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 reference               | to-many (WorkspaceConnectorSyncTarget) | ⚪ No     | Inverse reference — NOT declared as `@OneToMany` on WorkspaceConnector. `WorkspaceConnectorSyncTarget` declares `@ManyToOne(() =&gt; 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 reference                     | to-many (ConnectorMapping)             | ⚪ No     | Inverse reference — NOT declared as `@OneToMany` on WorkspaceConnector. `ConnectorMapping` declares `@ManyToOne(&#123; entity: () =&gt; WorkspaceConnector, fieldName: 'workspace_connector_pk' &#125;)`. 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 reference                | to-many (ConnectorSyncDiagnostic)      | ⚪ No     | Inverse reference — NOT declared as `@OneToMany` on WorkspaceConnector. `ConnectorSyncDiagnostic` declares `@ManyToOne(&#123; entity: () =&gt; WorkspaceConnector, fieldName: 'workspace_connector_pk' &#125;)`. 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 reference                     | to-many (WorkspaceConnectorSyncLog)    | ⚪ No     | Inverse reference — NOT declared as `@OneToMany` on WorkspaceConnector. `WorkspaceConnectorSyncLog` declares `@ManyToOne(() =&gt; WorkspaceConnector, &#123; deleteRule: 'cascade' &#125;)`. 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 reference | to-many (DocumentWorkspaceConnector)   | ⚪ No     | Inverse 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(() =&gt; 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

```json theme={null}
{
  "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" }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/WorkspaceConnector.ts` · domain: ingestion · tier: Platform</sub>
