# 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.