9.5 KiB
Release Notes — agent-platform v0
Version: v0 (api.py declares
0.3.0; first public release) Date: 2026-07-06 Release auditor: 3rd call this project (per 3-block cadence rule) Decision: HOLD for production — see §6 and §8 Repo: https://forgejo.media-on.de/Leopoldadmin/agent-platform Commit:347ccb0onmain
1. What ships in v0
Architecture (matches PLAN.md §2)
- Two-container deployment on Coolify:
agent-platform(FastAPI + LiteLLM + Pydantic-AI, HTMX UI, SQLite, audit)mcp-tools(FastMCP server, 6 generic tools:echo,get_time,calculate,http_get,list_env,json_format)
- MCP transport:
http://mcp-tools:8501/mcp(FastMCPstreamable-http). - SQLite at
/data/agent-platform.db(named volumeagent-data). - Traefik labels via env interpolation — durable fix for the Coolify-v4
build_pack stripping
loadbalancer.server.portonexpose.
Features
- Agents — code-defined (
agents/Python modules) and DB-defined. CRUD: list / create / get / update / delete.enabledtoggle (admin). - Chat —
/api/chat/<agent_id>(and/<conv_id>). LiteLLM provider abstraction viaLLM_PROVIDERenv (e.g.openrouter,anthropic,openai). Tool-call loop with per-agentallowed_toolswhitelist. - Audit — every write action logged in
audittable. - UI — server-rendered HTML (HTMX + Jinja2). Pages: dashboard, agents list, agent detail, chat, audit (admin).
- Health —
/health(no auth) returns status, agent count, MCP reachability, current model. - Auth — Bearer token (static master + per-session token via
sessionstable).
Operational
.gitea/workflows/test.ymlrunspyteston push/PR.- Coolify resource UUID
n27nquozfhcgbph182ivbht3runs both containers with healthchecks +depends_on: service_healthy.
2. Known issues (release-blocking? see §6)
Tag legend — 🟥 = production-blocker · 🟧 = risk to accept in writing · 🟨 = quality nit · 🟩 = mitigated
Security
- 🟧 S2 —
mcp_tools/server.py::http_get: SSRF protection blocks private/loopback/reserved IPv4, butfollow_redirects=Trueplus un-pinned DNS allows DNS-rebinding bypass to internal targets. Effort: S (dropfollow_redirectsor resolve once + re-check). - 🟧 S3 —
agents/example.pyincludeslist_envinallowed_tools. Tool masksKEY/SECRET/TOKEN/PASSWORD, but any other env name (custom names likeAGENT_PLATFORM_DB_PATH,MCP_*) leaks raw. Effort: S (narrowallowed_toolsper agent or add explicit whitelist tolist_env). - 🟧 S5 — Master
AUTH_TOKENlogins are not recorded inaudit. No way to detect token compromise from logs. Effort: S (addlog_audit(..., action="token_auth")inauth.get_current_user).
Correctness
- 🟨 C2 —
DELETE /api/agents/<id>is annotatedstatus_code=204but the handler alsoreturns a JSON body. FastAPI emits 204 + body — non-conformant; some clients may reject. Effort: XS (drop thereturn, or removestatus_code=204and return 200). - 🟨 C4 —
llm.pydoes not capture LiteLLMcached_tokens(prompt-cache billing). Budget tracking will be off for cached calls. Effort: XS. - 🟨 C5 —
db.pyusesdatetime.utcnow()(deprecated in 3.12). Will start emittingDeprecationWarningunder Python ≥ 3.12. Effort: XS (datetime.now(timezone.utc)). - 🟨 C6 —
discover_agents()is called on every FastAPI boot (sync_code_agentsin lifespan). Once per process is already the case — partially mitigated by commit history; ongoing cost is just the import-time scan ofagents/. Effort: XS.
Data
- 🟧 D1 — No automated SQLite backup. The
agent-datavolume has no cron snapshotting. A volume loss = audit + agent-config loss. Effort: S (dailysqlite3 .backupcron on host + offsite). - 🟧 D3 — No
alembic. Schema changes rely onCREATE TABLE IF NOT EXISTS. Adding a column = hand-edited SQL. Effort: M (init alembic on next schema change).
Missing
- 🟧 M2 — UI auth flow (login page → token submit → cookie) not verified end-to-end in a real browser. Effort: S (manual click-through).
- 🟧 M4 — No
userstable. Sessionuser_idis a free-text column populated only via token-issuance (no UI). Multi-user identity is not enforceable. Effort: M.
Quality / DX (X1–X7)
- 🟨 Various developer-experience nits — docstrings, type hints, README polish. Not release-relevant. Effort: combined < M.
Mitigated (closed) — quality review v1
- 🟩 B1–B5 staging blockers (boot guard, MCP path, Dockerfile user, healthchecks/depends_on, Traefik labels).
- 🟩 C3 — case-insensitive Bearer prefix (
auth.py). - 🟩 S1 —
MCPClient.health()CancelledError+asyncio.Lock(mcp_client.py). - 🟩 S6, X5 and the other 7 critical quality-review issues.
- 🟩 21 pytest collected, 19 passed + 2 xpassed (
347ccb0).
3. Upgrade path
There is no prior version of agent-platform on this repo — this is the
first deploy. Future versions will follow the existing 6-phase lifecycle:
- Tag
vNon the merge commit tomain. - Re-run
release_auditor(this audit template). - Promote to production via the checklist in §6.
Because agent-data is a Docker volume, schema-changing releases need:
- Read-only backup of
/data/agent-platform.dbbefore upgrade. - Alembic migration (once D3 lands).
4. Production checklist (PROMOTE runbook)
Apply exactly these changes when promoting from staging → production. No environment-level "magic" beyond what is listed.
- Clone Coolify resource from staging (
n27nquozfhcgbph182ivbht3) into a new production resource. Do not reuse the staging UUID. - Bind production domain — replace the Traefik host label via the
FQDNenv var (compose already interpolates${FQDN:-…}). - Generate & paste a fresh
AUTH_TOKEN(python -c "import secrets;print(secrets.token_urlsafe(48))"). Paste into Coolify env, not into.envin the repo. ≥ 32 chars, never the default literal. - Rotate
AUTH_TOKENeven on a feature-identical deploy — the staging token leaked to humans in chat logs. - Paste
LLM_API_KEY(provider-specific). Until then,/api/chat/*returns 500 (deliberate, surfaced by Gate-3 smoke test). - Decide on residual security risk — sign off in writing on S2/S3/S5 or land the S-effort patches first (see §2).
- Enable SQLite backup cron —
0 3 * * * /usr/local/bin/sqlite3 /data/agent-platform.db ".backup /backups/agent-$(date +%F).db"(closes D1). Offsite-copy to Backblaze / S3 / Nextcloud. - Verify post-deploy —
curl -fsS https://<prod-fqdn>/health→ 200mcp_server: "reachable";curl -fsS -H "Authorization: Bearer $NEW_TOKEN" https://<prod-fqdn>/api/agents→ 200 array.
- Tag the release commit:
git tag -a v0.0.0 <sha> -m "agent-platform v0" && git push origin v0.0.0. - Update
current_status.md§2 to reflect production URL.
5. Rollback plan
Trigger: post-deploy health check fails, OR 5xx-rate > 1% in first 10 min.
- In Coolify UI: select the production resource → Stop (does not delete the volume). < 30 s.
- Re-deploy last known-good image tag —
4847d3eb05ab324273d80c4594956b1a79483fe9(audit-verified, post-C3+S1 staging image). To do this, pin the imagetag:in Coolify's compose editor to that digest and redeploy. - Verify:
curl -fsS https://<prod-fqdn>/health→ 200. - Inform user: post-mortem template lives in
docs/postmortem_template.md(TODO; not yet generated). For v0 the minimum is a 5-line summary to#platform-status. - Volume rollback — if the rollback needs pre-upgrade SQLite,
docker cp agent-platform-prod-1:/data /tmp/db-before-rollbackbefore any redeploy. Coolify UI exposes per-container console for this.
Recovery time objective (RTO): ~ 5 minutes (Coolify stop + redeploy). Recovery point objective (RPO): 0–24 h depending on backup cron.
6. Promote decision
Verdict: HOLD (with the option to escalate to PROMOTE).
Reasoning:
- Staging is fully green (health, CRUD, UI, MCP reachability).
- 21/21 effective tests pass; CI workflow present.
- Three issues remain open that the promoter (human) should sign off
on in writing before production, because they are policy / threat-
model decisions, not pure engineering tasks:
- S2 / SSRF — accept as-is for v0 internal-only deployment, or land the fix (S-effort).
- S3 / list_env — narrow example agent's
allowed_tools, or hardenlist_env(S-effort). - S5 / master-token audit — at minimum, leave the audit trail off for the master token in v0 to avoid log volume; revisit at v0.1.
- All other residual items are quality / DX nits that do not block production.
If the promoter signs off on S2/S3/S5 in writing, this verdict flips to PROMOTE without further code changes — proceed to §4 step 1.
Effort to flip HOLD → PROMOTE without signing off on residuals:
- ≤ 1 day for an engineering pass that closes C2, C4, C5, D1, M2.
- That is not requested in this audit window.
7. Artefacts produced by this audit
docs/current_status.md— phase, deploy state, single next action.docs/test_report.md— pytest 21/21, xfail/xpass log, smoke-test evidence.docs/RELEASE_NOTES.md— this file.
All three are committed in a single change as docs: release audit + current_status + test_report + release notes (T010).