Kiến trúc tổng thể — giải thích
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:
- Server verify chữ ký Cloudflare Access JWT và bỏ qua
x-forwarded-rolehoàn toàn. - nginx client xoá sạch
X-Forwarded-Email/User/Name/Roletừ 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êmX-Forwarded-Emailtừ đúng 1 IP tĩnh (.10) — request từ host tới127.0.0.1:8080bị 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)—spaceIdbắt buộc;nullchỉ 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àiALLOWED_HOSTSlà 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.jsonvào worktree mỗi run, thu hồi sau run. - Token housekeeping: user tokens (danh tính thật), persona tokens (
@personatheo task), reconciler Space role →global_rolechạy định kỳ.
11 containers làm gì?
| Nhóm | Container | Vai trò |
|---|---|---|
| Board | agentjira_server, agentjira_client, agentjira_db | API + runtime agent, SPA, Postgres Board |
| Arkon API | arkon_api, arkon_migrator | FastAPI + Alembic migration lúc boot |
| Arkon data | arkon_postgres, arkon_redis, arkon_minio | pgvector, queue MRP, object storage |
| Arkon worker | arkon_worker, arkon_worker_skills | Pipeline biên dịch Wiki, worker skills |
| Arkon UI | arkon_frontend | Portal :3119 |
| Docs (mới) | agentjira_docs | Site tài liệu này :8082 — tĩnh, không DB |