From 0a967bef9844d0297c254ccd967ffc232f1a21c5 Mon Sep 17 00:00:00 2001 From: Pastilhas Date: Fri, 28 Aug 2026 22:32:23 +0100 Subject: [PATCH] The name, and what it is for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An Officer plugin that puts the fofos admin inside Officer, as panels — so editing the site uses Officer's accounts and permissions rather than a second password on a second domain. Nothing is built. The README says so, and says what the shape will be: nav plus detail after plugins/proxy-manager, nine sections, messages first because it is one read-only route and proves the whole path before anything harder. The API it consumes already exists, at /api/admin in fofos/platform. It is there rather than here because the query layer is the only thing the site and the admin share, and a plugin carrying its own copy of that schema would be a second definition of the same tables in another repository. Co-Authored-By: Claude Opus 5 --- .gitignore | 3 ++ README.md | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac1e8f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +*.log +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..603fbeb --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +# Fofos Admin + +An **Officer plugin**. It puts the fofos website's admin inside Officer, as panels. + +**Status: nothing is built yet.** This repository is a name and a README. What it will be is below, +and the API it consumes already exists — see *The other half*. + +--- + +## What this is + +[fofos](https://gitea.officer.dev/fofos/platform) is a website with three surfaces in one process: a +public site generated to static files, a JSON API, and an admin that has until now been its own +server-rendered application on its own subdomain, behind its own password. + +That third one is moving here. Editing the site becomes something you do **inside Officer**, with +Officer's accounts, Officer's permissions and Officer's workspace — rather than a second login on a +second domain that has to be told separately who is allowed in. + +## Why a plugin, rather than leaving it where it was + +**One place to sign in.** The admin had its own argon2 passwords, its own session cookie and its own +`/admin/setup` bootstrap. All of it duplicated something Officer already does properly, and none of +it could be shared: a person given access to the machine still had to be given access to the admin, +separately, by hand. + +**Officer's permissions instead of a second answer.** One grantable permission, per role, at read or +write — the same page as every other plugin, with no special case to learn. + +**The site keeps its own data.** This plugin stores nothing of the client's. Content, uploads and +every photograph stay in fofos's own database and media store; the only thing in Officer's database +is the connection to reach them. So deleting this plugin — with or without the "delete its data" +checkbox — cannot lose a single line of copy or a single image. That is a deliberate property, not a +happy accident. + +## What it will look like + +A nav down the left and a detail panel beside it, following `plugins/proxy-manager` rather than +`plugins/gitea` — a list of sections over a remote service whose credential the plugin holds, which +is this problem exactly. + +Nine sections, in the order they will be built: + +| | | +|---|---| +| **Messages** | contact form submissions. Read only, and there is no delete | +| **Site settings** | partners, social links, contact details | +| **About** | one page of copy and a header photograph | +| **Home** | the hero, the intro, and an ordered gallery | +| **Gallery** · **Drops** · **Collabs** | pieces, each with ordered media | +| **Collections** | the nested one — collections hold items, items hold media | +| **Services** | a fixed tree. Content only: no adding, no removing, no reordering | + +Messages is first on purpose. It is one read-only route, so it proves the whole path — Officer panel, +through this plugin, to fofos and back — before anything harder is attempted. + +## The other half + +**The API this consumes is already built and running**, in the fofos repository at `/api/admin`. It +covers all nine sections, authenticates with a bearer token, and its full route reference is in +[`docs/SURFACES.md`](https://gitea.officer.dev/fofos/platform/src/branch/master/docs/SURFACES.md). + +It lives there rather than here for one reason worth stating: the query layer is the only thing the +site and the admin share, and a plugin carrying its own copy of fofos's database schema would be a +second definition of the same tables in a different repository, drifting from the day it was written. +So this plugin holds a URL and a token and knows nothing about Postgres. + +## Configuration + +One connection: where fofos is, and a token to reach it. Stored in a plugin-owned table, encrypted +under this plugin's own purpose key, and **never returned across the API boundary** — to anybody, +including the owner. A settings form asking "is one set" gets a boolean. + +`/_config` is `ownerOnly`. The token is write authority over the whole public site, so while reading +what is on the site is reasonable to delegate, handing over the credential is not. + +## Not in the marketplace + +This is a plugin for one website, and it is useless without that website. It installs from its git +URL and has no catalogue entry. + +--- + +## Files + +Nothing yet. What Officer requires, once there is something: + +``` +manifest.ts identity, the permission, ownerOnly on /_config +db/schema.ts ONE table: the fofos connection +api/router.ts mounted at /api/fofos-admin — forwards to fofos +web/panels.ts the panels. REQUIRED alongside web/ +web/layout.ts how they are arranged. REQUIRED alongside web/ +``` + +Presence is the declaration — Officer discovers a plugin by what is on disk, and `manifest.ts` holds +only what a directory listing cannot say. A `web/` missing either of its two files is refused at +discovery, by name. + +## Conventions + +**`master`, not `main`.** + +**Every colour is a semantic token** — `bg-muted`, `text-muted-foreground`, `border-border` — and +never a Tailwind palette class. Palette classes do not follow the theme, so a plugin using them looks +correct under exactly one theme and wrong under the rest.