The dropdown was listing "connections" — a row per adapter + model + key — which
made choosing a model an act of configuration, put a key icon and a bin inside a
menu item, and showed five accounts nobody had created.
A provider is now a vendor Officer curates. Every one is listed, set up or not,
because a vendor you have no key for is exactly what you need to see in order to
add one. The model is chosen per generation, from that provider's entry in the
catalogue, beside it.
With the model off the row, all that remained of a "provider" was the key for
OpenAI — and Officer already stores keys: one active value per purpose, 0600
inside a 0700 directory, outside the backup tarball, created on first use so
nothing needs provisioning. So `atelier_providers` is dropped, along with
`generations.provider_id` that pointed into it. `provider` and `model` stay as
text on each generation, which were always the historical fact rather than a
pointer to configuration.
`getSecret`, never `getKey`: this is a foreign credential, and getKey mints a
random value for a purpose it cannot find — which for someone else's API key
means authenticating with something invented.
Resolution follows: a request names a model, and the catalogue says whose it is,
rather than a database being asked which stored row served it. A model nobody
in the catalogue claims is still accepted — the catalogue is advisory, and a
model released today should work before we ship a file that mentions it.
Two routes replace five: PUT and DELETE on /providers/:name/key. Deleting a key
that came from the environment is refused rather than faked — it belongs to the
install, not to this screen.
the extraction kept atelier's own postgres database, because the brief said to
when the tables already had rows. the owner reversed it, and the reason is not
tidiness: a plugin that behaves differently from every other plugin is a
plugin nobody can reason about.
the separate database meant a second connection string to set before install,
a second thing to back up, a second thing to get wrong on a new machine, and
failure modes no other plugin shares — none of it bought anything except
avoiding a migration.
four tables now: atelier_collections, atelier_collection_items,
atelier_providers, atelier_generations. index and check constraint names carry
the prefix too — those are global in postgres and are the one thing that would
otherwise collide with another plugin.
db/schema.ts re-exports the definitions rather than duplicating them: they stay
beside the code that queries them in sidecar/db/, and that file exists to be
found by gen-plugin-schemas.
ATELIER_POSTGRES_URL is gone. db.ts reads OFFICERDEV_POSTGRES_URL ?? POSTGRES_URL,
which the platform already sets.
the standalone service's rows are NOT here and nothing depends on them being
here — the old service is still running against the old database, untouched,
and migrating is a separate watched step after this is proven on alpha.