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

53 lines
2.1 KiB
TypeScript

import sharp from 'sharp';
export type ImageFacts = {
width: number | null;
height: number | null;
hasAlpha: boolean | null;
opaque: boolean | null;
};
const UNKNOWN: ImageFacts = { width: null, height: null, hasAlpha: null, opaque: null };
/**
* Measure the file that was actually written.
*
* Read from disk rather than echoed from the request, because the request is what was asked for and
* this is what arrived — and those are precisely the two things that come apart. The caller is an
* agent that cannot look at the image, so anything it is not told, it cannot know.
*
* `hasAlpha` and `opaque` answer different questions and the gap between them is the point:
*
* hasAlpha: false no alpha channel at all
* hasAlpha: true, opaque: false transparency present and used
* hasAlpha: true, opaque: true an alpha channel the model never used
*
* The third is the failure worth catching. `background: "transparent"` is accepted, the job succeeds,
* and every pixel comes back fully opaque — which for an app icon is the difference between usable and
* a black square, and is invisible from both ends without this field.
*
* Never throws. A generation that produced real bytes must not be recorded as failed because the
* measurement of it did; nulls say "not known" and the image is still there.
*/
export async function inspectImage(path: string): Promise<ImageFacts> {
try {
const image = sharp(path);
const metadata = await image.metadata();
// stats() decodes the pixels — the only way to answer "is anything actually transparent", since
// the header can only say whether a channel exists. Skipped when there is no alpha channel at
// all, where the answer is already known and the decode would be waste.
const opaque = metadata.hasAlpha ? (await image.stats()).isOpaque : true;
return {
width: metadata.width ?? null,
height: metadata.height ?? null,
hasAlpha: metadata.hasAlpha ?? null,
opaque,
};
} catch (error) {
console.error(`[inspect] could not read ${path}:`, error instanceof Error ? error.message : error);
return UNKNOWN;
}
}