fc4e1c75ed884b25fcf672283154296812310616
Listener auth (kb#180, DESIGN-a2a-agents.md §4)
-----------------------------------------------
agap-mcp binds :3100 on every interface (network_mode: host) and the LAN
carries VPN-terminated peers, so an unauthenticated JSON-RPC listener handed
ha_call_service / gitea_wiki_write / wiki_edit / radicale+todoist writes and
POST /capture-idea to any LAN peer. Only vw_* was gated before (kb#147), and
only at ENFORCE=1.
src/listener-auth.js now requires `Authorization: Bearer <token>` resolving to
a known agent id on every route except /health, which stays open so a
misconfigured token map is still diagnosable. Two gates stay deliberately
layered and independently switchable: "are you an agent at all?" (this file)
vs "are you trusted enough for the vault?" (trust-gate.js), both reading the
same token map.
Also closes an SSE session-hijack hole: /messages previously trusted any
sessionId with no credential, so a guessed or leaked id was full tool access.
Sessions are now pinned to the caller identity captured at the /sse handshake,
comparing agent id *and* token.
Auth defaults ON, and boot fails loudly if the token map is empty rather than
serving 401 to everyone while /health reports ok. Rollback is
AGAP_MCP_REQUIRE_AUTH=0.
Verified live: unauthenticated and bad-token /mcp -> 401, unauthenticated
/capture-idea -> 401, /health -> 200, both real agent tokens -> 200 with 36
tools, including from inside the adolf container.
Pin the bw CLI
--------------
The Dockerfile installed @bitwarden/cli unpinned. Rebuilding jumped
2026.2.0 -> 2026.7.0, whose WASM cipher deserializer rejects any stored login
carrying `"uri": null` ("invalid type: JsValue(Object({...})), expected a
string") -- 33 of 49 items in this vault have that shape. `bw list` then exits
1, server init fails, and the container crash-loops. Pinned to 2026.2.0.
Do not unpin: 2026.7.0 cannot authenticate against this Vaultwarden
(2025.12.0) at all -- it refuses plain HTTP outright and 404s on the identity
endpoint over HTTPS. Updating the CLI requires upgrading Vaultwarden first.
capture / classifier
--------------------
Adds the POST /capture-idea REST endpoint and the idea classifier behind it
(consumed by the todoist-capture plugin), with tests. Carried in the same
commit because server.js wires both this and the auth boot path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Agap Home Server
Docker Compose configurations for the Agap self-hosted home server infrastructure.
Services
- Immich (
immich-app/) — Photo management and backup (port 2283) - Gitea (
gitea/) — Self-hosted Git server with web UI (port 3000, SSH 222) - Open WebUI (
openai/) — AI chat interface with Ollama, GPU-accelerated (port 3125)
Quick Start
Start Immich (main service)
docker compose up -d
Start Gitea (from gitea/ directory)
cd gitea
docker compose up -d
Start Open WebUI (from openai/ directory)
cd openai
docker compose up -d
Configuration
Environment variables are in the root .env file for Immich:
UPLOAD_LOCATION— where photo originals are storedTHUMB_LOCATION— thumbnail cache directoryENCODED_VIDEO_LOCATION— transcoded video cacheDB_DATA_LOCATION— Postgres database directoryDB_PASSWORD— Postgres password
Storage
Media is stored on:
/mnt/media/upload— Immich originals/mnt/ssd1/media/— Immich thumbnails, encoded video, and Postgres database/mnt/misc/gitea— Gitea repositories and data
GPU Support
For GPU acceleration (Open WebUI/Ollama, Immich ML):
- Install NVIDIA Docker runtime:
sudo ./nvidia-docker-install.sh - Install CUDA toolkit:
./install-cuda.sh
Documentation
See CLAUDE.md for detailed developer instructions and Gitea wiki integration guidelines.
See the Gitea wiki for infrastructure documentation (storage, network, services setup).
Description
Languages
JavaScript
49%
Python
39.8%
Shell
6.9%
Dockerfile
1.8%
HTML
1.5%
Other
1%