The sixth plugin out, immediately after photos. A sidecar, a proxy router and 29 web files; no db/ directory, because there are no tables. ── The one thing that is not self-contained ── The connection lives in `service_connections`, a CORE table, reached through getServiceConnection/saveServiceConnection/getServiceCredentials. This plugin declares no schema. Deliberate: that table is the app store's shared credential store, keyed on (user_id, service), already encrypted at rest and already read by app-store/effects.ts. A private copy of the same three columns would be a second place the same fact could live, and the runbook is explicit that a move plus a data-format change gives any failure two causes. The cost, stated rather than hidden: this plugin depends on a core facility it does not own, and would break if that table changed shape. Photos, by contrast, owns photos_config outright. ── 38 palette classes paid down, mapped by meaning ── blue downloading / download speed -> info cyan checking (verifying) -> busy emerald seeding / complete -> success amber queued / stalled / warnings -> warning Collapsing blue and cyan into one tone would have lost a real distinction in the status dot, so `checking` went to `busy` — in-progress work, which is what that tone is for. ── A near-miss worth recording ── The first copy globbed *.tsx and *.ts and silently missed detail/ and dialogs/ — ten components. tsgo caught it as ten "cannot find module" errors. Worth stating because it is quiet in the other direction: had those been imported lazily, the typecheck would have passed and the panels would have broken at runtime. Check the directory tree, not the file glob. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.8 KiB
Transmission — the extraction record
Extracted from the platform on 2026-08-18, the sixth plugin out, immediately after photos.
plugins/EXTRACTING-A-PLUGIN.md is the runbook.
What moved
| Was | Is now |
|---|---|
src/servers/sidecar/transmission/* (6 files) |
sidecar/* |
src/servers/api/transmission/router.ts |
api/router.ts |
src/workspaces/officerdev/src/apps/Transmission/* (28 files, incl. detail/ and dialogs/) |
web/* |
src/apps/officer-web/Screens/Dashboard/Transmission/* |
web/layout.ts |
No db/ directory, because there are no tables — see below.
The one thing that is not self-contained
The connection lives in service_connections, a CORE table, reached through getServiceConnection /
saveServiceConnection / getServiceCredentials from officerdb. This plugin declares no schema.
That is deliberate rather than an oversight. The table is the app store's shared credential store, keyed
on (user_id, service), already encrypted at rest, and already read by app-store/effects.ts. Giving
transmission a private copy of the same three columns would create a second place the same fact could
live, and the extraction runbook is explicit that a move plus a data-format change gives any failure two
possible causes.
The cost, stated plainly: this plugin depends on a core facility it does not own. If
service_connections ever changes shape, this breaks with it. That is a real coupling and the only part
of this extraction that is not self-contained — recorded here rather than discovered later. Photos, by
contrast, owns photos_config outright.
Paid down on the way
38 palette classes, which the runbook is explicit about: a plugin using Tailwind palette numbers stops following the theme, and an extraction that leaves them exports colour debt into a repository nobody revisits.
They were mapped by MEANING rather than by hue, onto the closed tone set in components/Data/tone.ts:
| was | meant | is now |
|---|---|---|
| blue | downloading, download speed | info |
| cyan | checking (verifying) | busy |
| emerald | seeding, complete | success |
| amber | queued, stalled, warnings | warning |
Collapsing blue and cyan into one tone would have lost a real distinction in the status dot, which is why
checking went to busy — it is in-progress work, which is exactly what that tone is for.
Test fixtures. Transmission was the canonical members: 'none' fixture (a single-tenant daemon with no
user concept) across three app-store test files. Repointed at slskd, which has the identical shape,
rather than deleted — the assertions are about the installer, not about transmission.
A near-miss worth recording
The first copy took *.tsx and *.ts from the app directory and silently missed detail/ and
dialogs/ — ten components. Nothing said so; tsgo caught it as ten "cannot find module" errors
pointing at files that had simply not been copied.
Worth stating because the failure is quiet in the other direction too: had those subdirectories contained only components imported lazily, the typecheck would have passed and the panels would have broken at runtime. Check the directory tree, not the file glob, when moving a frontend.
Still open
- The daemon 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 theprovisionedhalf has no home until Docker provisioning for plugins exists. Point it at a daemon you already run. - No
assets/icon.png. Falls back to theDownloadglyph.