Files
atelier/README.md
T
pastilhas c892f2e700 officer_db with atelier_ prefixes, like every other plugin
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.
2026-08-20 17:30:53 +00:00

74 lines
4.4 KiB
Markdown

# Atelier
Image generation for an Officer server: a provider-shaped API over OpenAI's image endpoints, storing
what it makes so every image has a durable reference — a gallery you can browse, collections you can
organise, and a job an agent can poll rather than block on.
Atelier was a standalone service before this plugin existed
(`~/officer-dev/dockers/officer-atelier`, still running as `officer-atelier`, still what the mobile app
talks to). This plugin is a fresh extraction into Officer, not a replacement for it yet — see
`PLUGIN.md` before assuming the two are interchangeable.
## What you get
- **Generate** — a prompt, a model, size/quality/background, and a job you watch settle. `n` images
become `n` independently-tracked rows, so one failure out of four does not discard the three that
worked.
- **Gallery** — everything generated, newest first, with a lightbox: pan, zoom about the cursor,
checkerboard/dark/light backdrops for telling a transparent background from an opaque one that only
looks it.
- **Collections** — named sets of images. A generation request can name one by name and it is created on
first use; the gallery and the lightbox can file an image into one after the fact.
- **A provider-shaped backend.** "OpenAI" is code, written once; a *provider* is a row — which model,
whose key, on or off — and several can share one adapter. Today OpenAI is the only adapter; the point
of the shape is that a second one is a new file, not a redesign.
- **An OpenAI-compatible job API**, for agents. `POST /api/atelier/images/generations` accepts OpenAI's
request body verbatim and answers `202` with a job id rather than blocking for the length of the
generation — the caller polls `GET /api/atelier/images/generations/:id`, optionally with `?wait=` to
long-poll instead of retrying in a loop.
## Requirements
- An Officer server, version 1.0.0 or later.
- A **separate Postgres database**, and its own environment variable: `OFFICERDEV_POSTGRES_URL`. Atelier's
tables (`generations`, `collections`, `collection_items`, `providers`) do not live in `officer_db` —
see `PLUGIN.md` for why, and set this before installing. There is no default.
- An OpenAI API key, set with `bun run secret:set atelier-openai-key`, or configured per-provider in
Settings → Integrations → Atelier, or (for an install that predates the secret store) as
`OPENAI_API_KEY` in `.env`.
## Install
From the Officer marketplace: find Atelier, install. That mounts `/api/atelier` and `/atelier`, starts
the `officer-atelier` sidecar under PM2, and connects it to whatever `OFFICERDEV_POSTGRES_URL` points at —
which has to already have the schema (the standalone repo's own `bun db:push` creates it; this plugin
does not run migrations against a database it does not own the schema of).
Uninstalling stops the sidecar and unmounts the route. **It never touches your database** — Atelier's
tables and rows are not this plugin's to drop, since it does not own the schema push for them either.
## Permissions
One permission, `atelier`, grantable per role at read or write.
- **Read** lets an account use Generate, browse the Gallery and Collections, and see which providers are
configured (never a key, in any form — not even masked).
- **Write** additionally lets an account add, edit or delete providers, including their API keys. A
provider's key authorises real spend on someone's OpenAI account, so treat write here the way you
would treat write on any billing-adjacent surface.
Providers is not a panel — it is a platform Settings screen (Settings → Integrations → Atelier), because
it is owner-level configuration rather than a working view. See `PLUGIN.md` for why.
## Limitations, honestly
- **Two Ateliers can exist at once.** This plugin and the standalone service are independent — installing
this one does not migrate the standalone one's data, stop it, or repoint the mobile app. See
`PLUGIN.md`.
- **No per-user data.** Every account with `read` sees the same gallery and the same collections — there
is no ownership model yet, the same simple shape offscale shipped with first.
- **The database is separate from `officer_db`**, which means Atelier's tables are not covered by
`bun db:push`, are not part of the platform's usual backup story unless you back up the second
database too, and need their own connection string. Migrating them in is real, tracked follow-up work
— see `PLUGIN.md`.