Files
pastilhas f23ec1283b 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.
2026-08-20 03:53:53 +00:00

25 lines
1.3 KiB
TypeScript

import { createRouter } from '../create-router';
import { IMAGES_DIR } from '../env';
// `GET /files/:filename` — the generated image bytes.
//
// Was an unauthenticated top-level `/images/*` route with a durable `PUBLIC_URL`-prefixed link on the
// standalone service. Inside Officer it is mounted like every other route — the permission gate on the
// platform side already authenticated the request before the proxy forwarded it here, so this route
// itself needs no auth of its own; it only needs to refuse path traversal.
//
// Named `/files`, not `/images`, to avoid any ambiguity with the JSON API mounted at `/images` in
// hono.ts — `/images/:filename` here would sit one segment away from `/images/generations/:id`.
export const filesRouter = createRouter();
filesRouter.get('/:filename', async (ctx) => {
const name = ctx.req.param('filename');
// No traversal: the name is a filename, so anything with a separator is not one.
if (!name || name.includes('/') || name.includes('\\') || name.includes('..')) {
return ctx.text('Not found', 404);
}
const file = Bun.file(`${IMAGES_DIR}/${name}`);
if (!(await file.exists())) return ctx.text('Not found', 404);
return new Response(file, { headers: { 'cache-control': 'private, max-age=31536000, immutable' } });
});