Skip to content

Connector Generation Migrations

Connector generation migrations move an existing connection from one published generation of a connector to another generation of the same connector. The migration workflow runs one connection at a time, applies connector-authored hooks, performs automatic setup/auth analysis, updates the connection atomically, and queues any active notifications the actor should see. Use this page when you are authoring a connector change, planning a rollout, or reviewing how AuthProxy protects stored credentials during an upgrade.

Bulk rollout is intentionally a host concern. Hosts can call the single connection endpoint for each connection they want to move and track the returned task ids.

The connector’s ID, name, namespace, labels, and annotations belong to the logical connector, not an individual definition generation. Every source and target generation therefore projects the same connector name. A generation migration changes the connection’s recorded generation but does not rename the connector or connection. Rename the logical connector separately through its ID-addressed update endpoint.

flowchart LR
    Host["Host rollout job"] --> API["Migrate one connection"]
    API --> Worker["Background workflow"]
    Worker --> Hooks["Run connector hooks"]
    Hooks --> Analysis["Analyze setup, auth, and probes"]
    Analysis --> Commit["Atomic connection update"]
    Commit --> Notices["Actor notifications"]

A connector generation can define shared JavaScript and optional migration hooks:

javascript: |
function migrateUp() {
return {
config: {
set: {
sync_mode: "standard"
}
}
};
}
function migrateDown() {
return {
config: {
unset: ["sync_mode"]
}
};
}
migrations:
up:
javascript: migrateUp()
down:
javascript: migrateDown()

The migrations.up.javascript and migrations.down.javascript values are JavaScript expressions. AuthProxy validates expression syntax when the connector definition is validated, but it does not execute migration hooks until a connection migration workflow crosses that generation.

Hooks run in the same deterministic connector JavaScript environment as predicates and setup data-source transforms. They receive:

Variable Shape Description
cfg object The connection configuration collected by setup steps.
labels object User-owned connection labels visible to connector JavaScript.
annotations object Connection annotations.

Hooks cannot call network, database, or host application APIs.

When migrating upward, AuthProxy runs each target-side up hook in order:

  • v1 -> v3: run v2.up, then v3.up.

When migrating downward, AuthProxy runs each source-side down hook in reverse order:

  • v3 -> v1: run v3.down, then v2.down.

If any hook fails, the workflow fails without persisting partial hook output. Rollback is the same workflow pointed at an earlier connector generation.

Migration hooks return a JSON-like object. Every section is optional:

return {
config: {
set: {
workspace_id: "default"
},
unset: ["legacy_workspace"]
},
labels: {
set: {
"host.example/sync": "enabled"
},
unset: ["host.example/legacy"]
},
annotations: {
set: {
"host.example/migrated-by": "connector-v2"
},
unset: ["host.example/review"]
},
notifications: {
set: [
{
key: "review-required",
level: "warning",
title: "Connection needs review",
message: "Review this connection before using the new connector generation.",
actionUrl: "/connections/cxn_123?action=configure",
metadata: {
reason: "workspace mapping changed"
}
}
],
unset: [
{
key: "review-required"
}
]
}
};

config.set values may be strings, numbers, booleans, arrays, or objects. labels and annotations use string values and must pass the same validation as normal connection updates. See labels and annotations for the ownership model. System-owned labels under apxy/* are not connector-owned and cannot be set by hooks.

Connector-authored notifications are keyed per connection. A hook can unset a previous notice by returning the same notifications.unset[].key.

After hooks run, AuthProxy compares the source and target connector definitions and updates the migration candidate:

  • Target-only setup fields with JSON Schema defaults are filled automatically.
  • Missing required configure fields set setupStepId so the actor can resume setup.
  • Missing required preconnect fields or required OAuth scope changes leave the connection configured but unhealthy, requiring re-authentication.
  • Optional new fields and optional OAuth scopes do not require user action.
  • OAuth client, token endpoint, or refresh input changes trigger a refresh attempt when the auth method supports refresh. Auth methods without refresh treat this as a no-op.
  • If the migration is not blocked by required setup or re-authentication, AuthProxy runs the target connector’s enabled probes once after the generation switch.

The workflow writes the connector generation, encrypted configuration, labels, annotations, setup state, health state, and notification changes in one transaction.

Notifications are high-level actor-visible conditions, not per-field change logs. The built-in migration analysis queues at most one required-action notification per connection:

  • Re-authentication required: /connections/{id}?action=reauth
  • Setup required: /connections/{id}?action=configure

Re-authentication is more severe than setup because the re-authentication flow will also lead the actor through any required setup steps. If a connection already has an active re-authentication notification, a migration reuses the same deterministic key instead of creating a duplicate.

The notification API is:

GET /api/v1/notifications?includeViewed=true
POST /api/v1/notifications/{id}/_viewed
POST /api/v1/notifications/_viewed

GET /notifications returns a NotificationList. Each item is a read-only, resource-shaped projection of a durable notification row. It is not a client-managed desired resource: status.viewed is specific to the authenticated actor, and status.action is present only when that actor can perform the suggested action.

{
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Notification",
"metadata": {
"id": "ntf_01example",
"namespace": "root.acme",
"createdAt": "2026-08-16T12:00:00Z",
"updatedAt": "2026-08-16T12:00:00Z"
},
"spec": {
"key": "connection:cxn_01example:auth_required",
"level": "warning",
"resourceRef": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connection",
"id": "cxn_01example"
},
"title": "Connection requires re-authentication",
"message": "Reconnect to refresh credentials."
},
"status": {
"state": "active",
"viewed": false,
"action": {"url": "/connections/cxn_01example?action=reauth"}
}
}

Marking one notification viewed uses a typed action and returns the same action with status.viewed: true:

{
"apiVersion": "authproxy.net/v1alpha1",
"kind": "NotificationView",
"metadata": {
"target": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Notification",
"id": "ntf_01example"
}
},
"spec": {}
}

The batch endpoint uses kind: NotificationBatchView, with Notification references in metadata.targets and an empty spec. Its response reports status.viewedCount.

Start a single connection migration with:

POST /api/v1/connections/{id}/_migrateGeneration
Content-Type: application/json
{
"apiVersion": "authproxy.net/v1alpha1",
"kind": "ConnectionGenerationMigration",
"metadata": {
"target": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connection",
"id": "cxn_..."
}
},
"spec": {
"connectorRef": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connector",
"id": "cxr_...",
"generation": 3
},
"timeoutSeconds": 600
}
}

The response binds the workflow task to the caller:

{
"apiVersion": "authproxy.net/v1alpha1",
"kind": "ConnectionGenerationMigration",
"metadata": {
"target": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connection",
"id": "cxn_..."
}
},
"spec": {
"connectorRef": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connector",
"id": "cxr_...",
"generation": 3
},
"timeoutSeconds": 600
},
"status": {
"taskId": "tsk_...",
"sourceConnectorRef": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connector",
"id": "cxr_...",
"generation": 1
},
"targetConnectorRef": {
"apiVersion": "authproxy.net/v1alpha1",
"kind": "Connector",
"id": "cxr_...",
"generation": 3
}
}
}

The endpoint rejects no-op migrations, cross-connector targets, draft or archived targets, invalid timeouts, and concurrent migrations for the same connection.