Chuyển tới nội dung chính

Kiến trúc tổng thể

Trang này giải thích vì sao hệ thống gồm 11 container với server chỉ nghe loopback sau nginx, và mỗi lựa chọn kiến trúc đánh đổi điều gì.

Vì sao stack có hình dạng như hiện tại: 11 containers, loopback, strip header, JWT verify. Lệnh vận hành: Vận hành hằng ngày.

Sơ đồ runtime (production)​

Vì sao server bind loopback?​

agentjira_server từng publish 0.0.0.0:8080. Kết hợp danh tính qua header, ai chạm được port đó đều gửi được x-forwarded-email: attacker@x.com và approve task — merge code agent vào nhánh chính. Hai chốt độc lập chặn lại:

  1. Server verify chữ ký Cloudflare Access JWT và bỏ qua x-forwarded-role hoàn toàn.
  2. nginx client xoá sạch X-Forwarded-Email/User/Name/Role từ request inbound.
Không bao giờ republish 8080 ra 0.0.0.0.

Vì sao nginx đứng giữa?​

  • Là mặt tiền duy nhất (:8081) serve SPA, proxy /api + WebSocket (timeout dài cho stream realtime).
  • Là nơi strip header danh tính do client gửi — server chỉ tin JWT đã verify hoặc proxy được liệt kê (TRUSTED_PROXY_IPS + TRUST_PROXY_IDENTITY=1 ở dev).
  • Ở DEV FULL-STACK, nginx.dev.conf.template đóng vai Cloudflare: tiêm X-Forwarded-Email từ đúng 1 IP tĩnh (.10) — request từ host tới 127.0.0.1:8080 bị NAT thành IP gateway bridge nên giả mạo header vẫn fail, nhờ đó pentest Human Gate local mới có ý nghĩa.

WebSocket room theo Space (0C4)​

Mặc định (cờ tắt) mọi event tới mọi browser — vừa phí vừa là cross-space read (member Space B nhận tiêu đề task Space A). Bật AGENTBOARD_WS_TOPICS, socket phải subscribe từng Space và chỉ nhận event của room đã vào:

  • broadcast(message, spaceId) — spaceId bắt buộc; null chỉ dành cho sự kiện toàn cục (tạo/xoá Space). Fail-closed: socket chưa vào room thì không nhận gì.
  • Danh tính subscribe lấy từ upgrade request, không tin gì client tự khai; không member → FORBIDDEN, chưa giải được danh tính → IDENTITY_PENDING (thử lại được, khác với bị từ chối).
  • Tắt cờ = broadcast toàn cục y Phase 1. Vì bật cờ mà socket không bao giờ nối được thì tính năng vừa bật coi như không tồn tại — nên thiếu AGENT_BOARD_PUBLIC_URL / host ngoài ALLOWED_HOSTS là server từ chối boot.

Khối 0B — Arkon substrate (gọn)​

  • Space-membership / provisioning: tạo Space mở transaction → Department Arkon + Wiki Home + 5 persona + mint MCP token (mã hoá at-rest).
  • Plan-apply / spec-mirror: plan duyệt xong apply nguyên tử; spec task mirror sang Wiki.
  • MCP-adapter: bơm .mcp.json + .claude/settings.json vào worktree mỗi run, thu hồi sau run.
  • Token housekeeping: user tokens (danh tính thật), persona tokens (@persona theo task), reconciler Space role → global_role chạy định kỳ.

11 containers làm gì?​

NhómContainerVai trò
Boardagentjira_server, agentjira_client, agentjira_dbAPI + runtime agent, SPA, Postgres Board
Arkon APIarkon_api, arkon_migratorFastAPI + Alembic migration lúc boot
Arkon dataarkon_postgres, arkon_redis, arkon_miniopgvector, queue MRP, object storage
Arkon workerarkon_worker, arkon_worker_skillsPipeline biên dịch Wiki, worker skills
Arkon UIarkon_frontendPortal :3119
Docs (mới)agentjira_docsSite tài liệu này :8082 — tĩnh, không DB