Files
fofos-admin/manifest.ts
T
pastilhasandClaude Opus 5 c38d269faf Media moves to the foot, and each section asks its own question
TWO REPORTS, AND THE SECOND ONE WAS A DESIGN MISTAKE RATHER THAN A SETTING.

Media is pinned now, beside Administration. it sat at the end of the scrolling list,
which is the bottom of the LIST and not the bottom of the panel. it belongs in the
foot for the same reason Administration does: both are about this machine, while
everything above them is about the site's pages.

and it was LOCKED BEHIND A CONNECTION IT NEVER USES. `ready` was one global flag —
"can anything be opened" — and Media is a folder on this disk that never speaks to
fofos. so sections now declare what they need:

  'connection'  the site's pages, which read fofos
  'root'        Media, which needs a folder and nothing else
  'nothing'     Administration, because locking the door you fix things through is
                locking somebody out entirely

`sectionOpen` is one function, used by the nav to decide whether to offer a link and
by the detail panel to decide what to render — so the two cannot disagree about a
section. that was already the rule with one flag; it matters more now that each
section asks a different question.

`/status` gained `rootSet`, a BOOLEAN, and stays not-owner-only. the nav needs the
answer for every account that can see the section; the path itself stays behind
`/_config`, which is owner-only. whether a root has been chosen reveals nothing
about the machine — where it is would.

the empty-state line follows too: "set a root location below to begin" before there
is one, "connect fofos to open the rest" after — rather than one sentence naming a
step that is not the next one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 08:44:11 +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.20',
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'],
},
],
};