# Admin Agent — Plan **Goal:** manage the site through an AI agent (headless Claude) — create pages, edit content, upload images — from two surfaces: a full **/admin dashboard** and an **in-page console** ("open a page, tell it what to change"). **Decisions locked (2026-07-23):** - **Full-builder agent** — can create pages, edit any file, restructure. Highest ceiling, highest risk; sandboxing is mandatory, not optional. - **Both surfaces** — /admin dashboard + in-page console. - **Long-lived token** — `claude setup-token` on the server; agent reuses it. --- ## What already exists (don't rebuild) - `app/src/components/DevConsole.astro` — the in-page console UI (prompt box, element picker, preview link, Publish). Already on every live page, dormant. - `astroagent.config.json` — engine config: model, tools (`Read Write Edit Glob Grep WebSearch`), confined `agentUser` (`carlos-arias-agent`), skills (`brand`, `ui-ux`, `seo`), console route/port. - `api/` auth — `account.php` sessions + `ADMIN_TOKEN`. - Structured content already DB-driven and agent-friendly: `cja_projects`, `cja_changelog`, `cja_contact`, plus the seed scripts that write them. - Server has the `claude` CLI and Node 22. Project is a git repo on `main`. ## What's missing (the build) - The **runner service** the console talks to (`/devconsole/run|publish|...`) — frontend exists, backend does not. - **Image upload** anywhere in the flow. - **Model selector** and the structured **draft + prompt + images** panel. - The **/admin dashboard**. - **Media pipeline** (`cja_media` + optimisation). - **Hardening** — the code-writing agent is the highest-risk surface on the site. --- ## Architecture ``` Browser (you, authed) ├── /admin ................ dashboard SPA: pages, media, agent chat └── in-page console ........ DevConsole.astro on any page │ (same-origin fetch, session-authed) ▼ nginx ── /devconsole/* , /admin/* ──► localhost-only runner (Node, :3011) │ auth gate on every request │ │ ├── headless Claude Code │ │ (agentUser, confined to repo, │ │ tools: Read/Write/Edit/Glob/Grep/WebSearch) │ ├── preview build → public-preview// │ ├── publish → build public/ + chown + git commit │ └── media: optimise → app/public/media/ + cja_media ▼ Static site (public/) — unchanged for visitors ``` **Content model — hybrid:** - Freeform pages (`about`, `services/*`) → the agent edits `.astro` files directly. - New pages → the agent writes new `.astro` files. - Structured content (projects, changelog, services data) → DB, edited via structured tools or the seed JSON/scripts. - Images → `app/public/media/` (survives rebuilds) + `cja_media` rows. **Why preview-first matters:** the site is static. Every agent run builds to an isolated `public-preview//` you can open and review; **nothing goes live until you press Publish**, which rebuilds `public/` and commits to git. --- ## Phases ### Phase 0 — Foundation & safety *(do first, no features yet)* - Commit the current working tree as a clean baseline (75 files) so every future publish is a diff you can roll back. - Create/confirm the confined `carlos-arias-agent` OS user: can write only the repo, no sudo, no interactive shell. Install/point `claude` for that user. - `claude setup-token` on the server → store in `agents/.env` (git-ignored). - Admin auth: session login (reuse `api/account.php` or a dedicated admin login). - nginx: `/devconsole/*` and `/admin/*` → localhost runner, **auth-gated**, never exposed directly. Runner binds `127.0.0.1` only. - Audit log table (`cja_admin_log`): who ran what, when, published or discarded. ### Phase 1 — In-page console (finish the astroagent) - Build the runner service: `run` (spawn headless Claude with prompt + page context, stream output), `preview`, `publish`, `discard`, `ping`, `auth`, `logout`. Conversation state so follow-ups work ("now make it bigger"). - Wire `DevConsole.astro` to it. Element picker already works. - Publish pipeline: build → verify build passes → chown → git commit. - Milestone: open /about, "tighten the opening paragraph," preview, publish. ### Phase 2 — Media - `cja_media` table + `POST /devconsole/upload`. - Optimise on upload (resize/compress, like the manual ffmpeg step), write to `app/public/media/`, return URL + agent-generated alt text. - Image upload in the console; agent can place uploaded images in a page. - Milestone: on a project page, "add these three screenshots to the gallery." ### Phase 3 — Admin dashboard (/admin) - Login → dashboard. - **Pages**: list (filesystem scan of `app/src/pages` + DB content types), create-page flow ("make a page for my accounting services"), edit (hands off to the console or a structured form). - **Media library**: browse/upload/reuse. - **Agent panel — your exact spec**: model selector · draft-content box · prompt box · image-upload area. Draft + prompt + images post to the same runner. - **Activity log** from `cja_admin_log`. ### Phase 4 — Guardrails & polish - Feed the agent the brand guide + `brand`/`ui-ux`/`seo` skills so edits stay on-brand automatically. - "Build passes" gate is required before Publish is offered. - One-click **rollback** (git revert the last publish). - Per-session run/token limits; rate limiting. --- ## Risks & mitigations 1. **Security is the whole game.** A code-writing agent on a public server is the highest-value target here — a breach means full server control. Mitigations: admin auth on every request, runner bound to localhost, confined OS user, audit log, no direct exposure of the agent, rate limits. 2. **The agent can break the build.** → preview-first, build-passes gate, git commit per publish, one-click rollback. 3. **Unbounded token spend.** → per-session limits; the long-lived token is one account we can watch. 4. **On-brand drift.** → brand guide + skills injected into every agent run; preview-before-publish is the human gate. ## Not in scope (yet) - Multi-user / roles (single admin for now). - Scheduled autonomous edits (the `agents/` content pipeline is separate and currently tuned for the old blog — re-tune later if wanted). ## To start Phase 0, I need - Your go-ahead to commit the current tree as the baseline. - A decision on admin login: reuse the existing account system, or a simple single-user admin password to start.