manifest, thin proxy router, and the sidecar backend

ported from the standalone officer-atelier service: providers (adapter-shaped, openai the only
adapter today), the generation queue, collections, and the database layer — kept on its own
Postgres database rather than folded into officer_db, since both collections and provider_settings
had rows on the machine this was extracted from.

what changed rather than just moved:
- images are served from an authenticated GET /files/:filename instead of an unauthenticated
  PUBLIC_URL-prefixed static route
- the OpenAI-key bootstrap fallback reads the secret store (getSecret) before .env, per-adapter
- provider_settings (the one-row-per-adapter shape providers replaced) did not come along — it has
  no callers left anywhere in the server code, only a migration script that also did not move

ping/echo (smoke-test routes with no caller) did not move either; the sidecar's own /_health covers
liveness.

not yet wired into the platform: sidecar/index.ts exists but nothing mounts it, and web/ has not
been written, so this is not yet a discoverable plugin.
This commit is contained in:
2026-08-20 03:53:53 +00:00
commit f23ec1283b
36 changed files with 2759 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
import { createRouter } from './create-router';
import { openaiError } from './errors';
import type { HonoVariables } from './create-router';
import type { Hono } from 'hono';
import { imagesRouter } from './api/images';
import { providersRouter } from './api/providers';
import { collectionsRouter } from './api/collections';
import { filesRouter } from './api/files';
/**
* Every router this sidecar answers, and the prefix it answers on.
*
* Bare — no `/api` prefix of its own. `createSidecarProxy` (../api/router.ts, on the platform side)
* already strips `/api/atelier` before forwarding, so what arrives here is exactly the subpath: a
* request for `/api/atelier/images/generations` arrives as `/images/generations`.
*
* `ping` and `echo` from the standalone service are not here — they were smoke-test routes with no
* caller; the sidecar's own `/_health` (see index.ts) covers liveness instead.
*/
const MOUNTS: [string, Hono<{ Variables: HonoVariables }>][] = [
['/images', imagesRouter],
['/providers', providersRouter],
['/collections', collectionsRouter],
['/files', filesRouter],
];
export function buildHonoApp() {
const app = createRouter();
for (const [prefix, router] of MOUNTS) app.route(prefix, router);
app.notFound((ctx) => ctx.json(openaiError('Not found', 'not_found'), 404));
app.onError((error, ctx) => {
console.error('[atelier]', error);
return ctx.json(openaiError('Internal Server Error', 'server_error'), 500);
});
return app;
}