# `PhoenixKit.Migrations.Postgres.V107`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.165/lib/phoenix_kit/migrations/postgres/v107.ex#L1)

V107: Pin AI endpoints to a specific integration row via
`integration_uuid` + add the missing unique index on `name`.

Prior to this migration, `phoenix_kit_ai_endpoints.provider` stored a
provider-type tag (`"openrouter"`) and the integrations system had to
guess which connection row to use at request time via
`find_first_connected/1` — necessary compensation for AI never having
recorded the user's actual choice. This column closes that gap: each
endpoint now references the integration row directly, so renaming or
re-labelling integrations doesn't change which one an endpoint uses,
and the resolver's `default`-based fallback chain becomes dead code.

## Up

- Adds nullable `integration_uuid uuid` column to
  `phoenix_kit_ai_endpoints`.
- Adds a btree index on the new column for FK-style lookups.
- Backfills `integration_uuid` from the existing `provider` strings:
  - For `provider = "openrouter:my-key"` → match the exact storage
    row `integration:openrouter:my-key`.
  - For `provider = "openrouter"` (bare) → pick the
    most-recently-validated `integration:openrouter:*` row, breaking
    ties on `uuid ASC` (UUIDv7 is time-ordered, so smaller uuid ≈
    older row → ASC = oldest first when timestamps tie).
  - Endpoints with no matching integration row stay NULL; the user
    re-picks via the endpoint form.
- Adds a UNIQUE index on `lower(name)` so duplicate endpoint names
  are rejected at the DB layer. `Endpoint.changeset/2` has
  registered `unique_constraint(:name)` since the schema was first
  extracted, but the V34 migration that created
  `phoenix_kit_ai_endpoints` never created the index — duplicate
  names were silently accepted. The hand-rolled test migration in
  `phoenix_kit_ai` masked this for years; surfaced when that test
  migration was removed (2026-04-29).

## Down

Drops the unique index, the integration_uuid index, and the
integration_uuid column. Lossy — endpoint→integration choices made
via the new picker are discarded.

# `down`

# `up`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
