Admin Assistant
The portfolio admin shell includes a private Eve assistant. Its bottom-right panel stays mounted while the browser navigates between /admin/* pages, and its durable Eve session and event log are stored in the browser so the conversation also survives a reload.
The assistant reads the current portfolio configuration, first-party analytics, analytics controls, and chat settings. It can change project visibility, analytics controls, and chat settings after an explicit approval in the conversation.
Trust boundaries
flowchart LR
browser[Authenticated admin browser] -->|Auth.js cookie| proxy["/api/admin/assistant/eve/*"]
proxy -->|admin channel JWT<br/>sub: portfolio-admin-chat| eve[Eve agent]
public[Public portfolio chat] -->|public channel JWT<br/>sub: portfolio-chat| eve
eve --> gate{Dynamic capability gate}
gate -->|admin subject only| adminTools[Admin instructions and tools]
gate -->|public subject| publicTools[Public portfolio persona and tools]
adminTools -->|subject-scoped service JWT<br/>sub: portfolio-admin-assistant| dispatcher["/api/internal/admin-agent/tool"]
dispatcher --> stores[(DynamoDB / analytics / GitHub read model)]
adminTools -. mutation request .-> approval[Human approval in admin UI]
approval -. approved .-> dispatcher
The controls are intentionally layered:
- Middleware protects every
/api/admin/*request. - The assistant proxy independently calls
getAdminRequestContext()before forwarding anything. - The proxy replaces browser credentials with a short-lived admin channel JWT. The browser never receives the shared channel secret.
- Eve resolves admin instructions and tools only when the verified channel subject is
portfolio-admin-chat. The public subject cannot discover those tools. - Admin tool callbacks use a separate agent-to-portfolio JWT subject,
portfolio-admin-assistant. The internal dispatcher rejects the generic public-agent service token. - Every state-changing tool uses Eve's durable
always()approval gate. A mutation cannot execute until the pending run receives an approval response from the admin UI.
Capabilities
Read operations do not require approval:
- portfolio project visibility, ordering, slugs, and overrides;
- portfolio or Clankie analytics for 24 hours, 7, 30, or 90 days;
- analytics collection switches and sample rates;
- chat budget, kill switch, saved model, and deployed model.
State changes require approval:
- show or hide a portfolio project;
- enable or disable analytics collection or change its sample rate;
- change the chat cost limit, kill switch, or saved Eve model.
Changing portfolio visibility also revalidates the public project surface and reconciles the project's semantic-search documents. Changing the saved model does not hot-swap the running agent; the next deployment bakes it into Eve.
Session persistence
The UI uses useEveAgent against the authenticated same-origin proxy. It persists both the complete authoritative event stream and Eve's full session cursor (sessionId, continuationToken, and streamIndex). The cursor resumes the durable conversation, while the events rebuild the visible transcript without replaying the full server stream.
The panel lives in ConditionalLayout, outside the page transition subtree. Navigating between admin pages therefore updates the route context without unmounting the assistant or interrupting an active run.
