photos, extracted from the platform into its own repository
The fifth plugin out, and the cheapest so far — offscale's shape rather than
music's or vault's. Nothing stayed behind and nothing had to be redesigned,
for three structural reasons recorded in PLUGIN.md:
• No reverse dependency. Nothing in src/ imported anything of photos'.
• Configuration was already right. The URL and API key live in photos_config,
a per-user registry encrypted at rest and driven from the app. Vault had to
move VAULTWARDEN_URL out of .env and invent a settings panel; here the
sidecar already read the database, and its own comment already said why
nothing reads process.env.
• The frontend was already panels. The screen was a WorkspaceView around
exactly photos-nav and photos-view, so web/panels.ts and web/layout.ts are
the screen's contents with the wrapper removed.
The router's prefix is now derived from mountPrefix rather than the literal
'/api/photos', which was correct only by coincidence — a third-party publisher
mounts at /api/p/<publisher>/photos and the literal would forward the wrong
path to the sidecar.
Palette debt paid down as the runbook requires: 6 classes (it says 47; someone
had already done most of it), all of them state colours wearing palette
numbers, now `success` and `warning` from the closed tone set so they follow
the theme.
Immich itself is still provisioned by the app store rather than by this plugin
— the `provisioned` half of its old catalogue entry has no home until Docker
provisioning for plugins exists. Point it at an instance you already run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# Photos — the extraction record
|
||||
|
||||
Extracted from the platform on **2026-08-18**, the fifth plugin out (after offscale, music, email, vault).
|
||||
`plugins/EXTRACTING-A-PLUGIN.md` is the runbook; this file is what it cost.
|
||||
|
||||
## The clean case
|
||||
|
||||
Offscale's shape rather than music's or vault's: **nothing stayed behind, and nothing had to be
|
||||
redesigned.** Worth recording why, because it is the cheapest extraction so far and the reasons are
|
||||
structural rather than luck.
|
||||
|
||||
- **No reverse dependency.** Nothing in `src/` imported anything of photos'. The whole platform surface
|
||||
was one commented router import, one barrel line, and the ordinary wiring (route, screen, registry,
|
||||
dock rule, catalogue entry). Compare vault, whose extraction had to invent an account-lifecycle hook
|
||||
because three core auth handlers called into it.
|
||||
- **Configuration was already right.** The URL and API key live in `photos_config` — a per-user registry
|
||||
with one active row, encrypted at rest, driven from the app. Vault had to move `VAULTWARDEN_URL` out of
|
||||
`.env` and invent a settings panel; here the sidecar already read the database and its own comment
|
||||
already said why nothing reads `process.env`: an `IMMICH_API_KEY` there would sit in the environment of
|
||||
every pm2 process, including the one with the largest attack surface and no code to use it.
|
||||
- **The frontend was already panels.** Two of them, `photos-nav` and `photos-view`, plus a layout. The
|
||||
screen was a `WorkspaceView` around exactly those, so `web/panels.ts` and `web/layout.ts` are the
|
||||
screen's own contents with the wrapper removed.
|
||||
|
||||
## What moved
|
||||
|
||||
| Was | Is now |
|
||||
| ------------------------------------------ | ------------------- |
|
||||
| `src/servers/sidecar/photos/*` (5 files) | `sidecar/*` |
|
||||
| `src/servers/api/photos/router.ts` | `api/router.ts` |
|
||||
| `src/databases/officer_db/src/photos/*` | `db/*` |
|
||||
| `src/workspaces/officerdev/src/apps/Photos/*` (25 files) | `web/*` |
|
||||
| `src/apps/officer-web/Screens/Dashboard/Photos/*` | `web/layout.ts` |
|
||||
|
||||
The prefix in `api/router.ts` is now DERIVED from `mountPrefix` rather than the literal `/api/photos`,
|
||||
which was right only by coincidence — see the comment there, and `plugins/music/api/router.ts` for the
|
||||
same fix and the same reasoning.
|
||||
|
||||
## What the platform lost
|
||||
|
||||
Deleted, not commented: the sidecar, the api router, the db directory, the Photos app, the screen, the
|
||||
`App.tsx` routes, the Dashboard barrel line, the `usePageTitle` rule, the `AppRegistry` wiring, the
|
||||
`officerdev` barrel re-exports, the permission registry entry, both database barrels, the `hono.ts`
|
||||
comment, and the `app-store/catalogue.ts` entry.
|
||||
|
||||
**The catalogue deletion is required, not tidying** — the trap the runbook records as having bitten
|
||||
twice. `permissionAvailability()` derives from `sidecar_installs`, which a plugin never gets a row in, so
|
||||
a leftover entry makes the permission permanently `unavailable`, puts `/photos` into `deniedRoutes` and
|
||||
withholds the dock tile, on a server where the plugin is installed and working.
|
||||
|
||||
## Two things paid down on the way
|
||||
|
||||
**Palette classes.** The runbook says to pay these down as part of the extraction rather than exporting
|
||||
colour debt into a repository nobody revisits, and it puts Photos at 47. It was **6** — someone had
|
||||
already done most of it. All six were state colours wearing palette numbers (`text-emerald-400` for the
|
||||
app's own tile, `text-emerald-500`/`text-amber-500` on a connection check) and are now `success` and
|
||||
`warning` from the closed tone set, so they follow the theme.
|
||||
|
||||
**Test fixtures.** Photos was the canonical app-store fixture across four test files, chosen for being
|
||||
`existing|provisioned` with `members: 'accounts'`. Repointed at `jellyfin`, which has the identical
|
||||
shape, rather than deleted — the assertions are about the installer, not about photos.
|
||||
|
||||
## Still open
|
||||
|
||||
- **Immich is still provisioned by the app store**, not by this plugin. `modes: ['existing',
|
||||
'provisioned']` and a compose template lived in the catalogue entry that had to be deleted, so the
|
||||
`provisioned` half has no home right now: you point it at an instance you already run. Docker
|
||||
provisioning for plugins is a design still in progress, and this is one of the features waiting for it.
|
||||
- **No `assets/icon.png`.** Falls back to the `Images` glyph, which is what the catalogue entry used.
|
||||
Reference in New Issue
Block a user