Files
fofos-admin/manifest.ts
T
pastilhasandClaude Opus 5 9da0c31a90 the media docs become an affordance, and the stale ones go
there were two markdown files sitting in media/originals/ — CLAUDE.md and
MEDIA_PROCESSING.md — carried in when that tree was copied. both are gone from
there now, and the originals in Projects/fofos are untouched and byte-identical, so
nothing was lost.

MEDIA_PROCESSING.md was not merely redundant, it was WRONG in three ways and each
would have failed on first use: it gave av-club's address as localhost:3020 (the
port is ephemeral now and it is reached at /api/av-club), it required a bearer token
(the platform's own gate handles that), and it described an upload-only model
(there is a path mode, so nothing needs uploading). it also pointed at
~/Projects/_avi_club_docs/, which does not exist on that machine.

documentation that lives beside the data goes stale invisibly — nobody re-reads a
file in a media folder when the service it describes changes. an affordance does not
have that failure mode: it ships with the plugin, updates with it, and disappears
when the plugin is removed.

KEPT SHORT DELIBERATELY. an affordance is compiled into EVERY conversation, unlike a
skill which is opened on demand — so this is the facts and a pointer, and the
reasoning stays in the media-conversion skill where it is read once by somebody who
needs it. the first draft was 206 words against gitea's 86; this one is under 120.

what it carries is the part an agent must not get wrong: originals are irreplaceable
and derived is rebuildable, and processing goes through av-club rather than a
hand-written ffmpeg line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 08:34:27 +01:00

65 lines
2.9 KiB
TypeScript

import type { PluginManifest } from '@@/plugins/manifest';
/**
* Fofos — the fofos website's admin, inside Officer.
*
* ── What it replaces ──
*
* A server-rendered admin on its own subdomain with its own argon2 passwords, its own session cookie
* and its own `/admin/setup` bootstrap. Every part of that duplicated something Officer already does,
* and none of it could be shared: giving somebody access to the machine still meant giving them
* access to the admin, separately, by hand. That is the whole reason this is a plugin.
*
* ── It holds no content ──
*
* fofos owns its own database and its own media store, and this reads and writes them over HTTP. The
* only thing in Officer's database is the connection — a URL and a token.
*
* That is a deliberate property rather than a convenience. **Deleting this plugin cannot lose a
* photograph or a line of the client's copy**, with the "delete its data" checkbox ticked or not,
* because none of it was ever here. The alternative — a `db/schema.ts` carrying fofos's own tables —
* would have put every one of them under an installer that is allowed to drop them.
*
* ── The permission is grantable; the credential is not ──
*
* Reading and editing the site is exactly what a member might be brought in to do. The TOKEN is a
* different matter: it is unrestricted write authority over everything the public sees, so `/_config`
* is `ownerOnly` — the split that field exists for, and the same shape proxy-manager and Jellyfin use
* for the same reason.
*
* ── No `screens` ──
*
* One screen at the mount prefix, labelled `label`. The nine sections are `?section=` on that one
* screen rather than nine routes: they are panels of one workspace, and `screens` is for a plugin
* contributing genuinely separate destinations.
*/
export const manifest: PluginManifest = {
publisher: 'officerdev',
version: '2026.08.29.18',
platform: '>=1.0.0',
label: 'Fofos',
summary: "The fofos website's content — pages, galleries, drops and collabs",
/** one website's admin, and useless without that website. */
tags: ['Personal'],
icon: 'PenLine',
color: '#c2410c',
// Nothing to declare. It talks HTTP to fofos and stores one row; there is no host binary anywhere
// on the path, and fofos itself is a separate deployment rather than something this installs.
permissions: [
{
key: 'fofos-admin',
label: 'Fofos',
description: 'Edit the fofos website — pages, galleries, drops, collabs and the messages people send',
// Where the fofos URL and token are set, and the probe that checks them. Prefix-matched, so
// `/_config/test` is covered too — deliberately, because that request carries the token in its
// BODY. A member who could call it would have an oracle pointed at a credential that can
// rewrite the whole public site.
ownerOnly: ['/_config'],
},
],
};