鉴权与 Analytics MCP
Dashboard / API 可选用 Token + Session + Passkey 保护数据面;外部 Agent 通过 MCP 拉取同一批 HTTP API,并可用 submit_intel 转发已签名的情报信封。控制面(pause / flatten / 下单)永远不走 HTTP 或 MCP。
详细技术说明与仓库文件同步:
Dashboard Auth & Analytics MCP
Auth model
| Client | Credential |
|---|---|
| Browser Dashboard | Token login → ab_session HttpOnly cookie; optional Passkey |
| MCP / scripts | Authorization: Bearer <token> or X-API-Token: <token> |
| Health probes | Always open: /health/live, /health/ready |
- Empty
ALPHABOUND_API_TOKEN: auth disabled (local dev default). - Token set: all
/api/v1/*data routes return 401 without token/session; HTML shell stays public and shows login gate. - Passkey register requires an existing session (bootstrap with token once).
- Credentials file:
<db_path>.webauthn(gitignore via*.db*patterns / var layout).
Env
ALPHABOUND_API_TOKEN=... # long random (≥24 chars; 32+ recommended for public)
ALPHABOUND_WEBAUTHN_RP_ID=localhost # hostname only
ALPHABOUND_WEBAUTHN_ORIGIN=http://127.0.0.1:8080
ALPHABOUND_TRUST_PROXY=1 # ONLY behind a trusted TLS/proxy edge
ALPHABOUND_TRUSTED_PROXY_HOPS=1 # XFF: use Nth IP from the right (default 1)
X-Forwarded-For can be forged
| Setup | Client can spoof lockout key? |
|---|---|
TRUST_PROXY off (default) | No — FailGuard keys on TCP peer only |
TRUST_PROXY=1 + take left-most XFF | Yes — attacker rotates forged IPs, bypasses lockout |
TRUST_PROXY=1 + take right-most (our default hops=1) | No for a single append-style proxy that always adds the real peer |
Rules:
- Default off. Direct internet → alphabound: never enable trust proxy.
- Enable only when Azure App Gateway / Front Door / nginx terminates TLS and is the only path to the process (NSG / private bind / no public :8080).
- We parse XFF as append-chain and pick
hopsfrom the right (default 1 = right-most). Left-most client junk is ignored. - Prefer edge WAF rate limits; FailGuard is in-process last line. Peer IP of the proxy alone would collapse all users into one bucket if XFF were missing — still fail-closed for brute force.
Brute-force / rate limits
When token auth is enabled, the single-threaded web loop keeps an in-memory FailGuard:
| Signal | Counts as failure? | Effect |
|---|---|---|
POST /api/v1/auth/login wrong token | yes | per-IP fail counter |
POST .../passkey/login bad assertion | yes | per-IP fail counter |
Authorization / X-API-Token wrong | yes | per-IP fail counter |
| Missing credential (browser first paint) | no | plain 401 |
| Successful token/passkey login | clears IP slot |
Defaults (compile-time in src/web/auth.zig):
- 8 failures / IP / 15 min window → lockout 15 min → HTTP 429 +
Retry-After - Global login flood: 60 login POSTs / rolling minute (all IPs) → 429
This is process-local (resets on restart). Put Azure Front Door / WAF / nginx in front for edge rate limits; FailGuard is the in-process last line.
Public exposure checklist:
- Long random
ALPHABOUND_API_TOKEN(e.g.openssl rand -hex 32) - HTTPS terminator;
ALPHABOUND_TRUST_PROXY=1only if the edge is trusted and clients cannot reach the app directly - Prefer session cookie / passkey after first login; do not put the raw token in browser JS storage
- Keep
/health/*open for probes; never put secrets in health bodies - Do not expose dashboard port publicly without the proxy; forged XFF is useless if
TRUST_PROXYstays off
Passkey / WebAuthn 限制(重要)
浏览器要求 secure context:
| 打开方式 | Token 登录 | Passkey |
|---|---|---|
http://127.0.0.1:8080 / http://localhost:8080 | ✅ | ✅ |
https://your-host/... | ✅ | ✅ |
http://10.x.x.x:8080(内网 HTTP IP) | ✅ | ❌ API 被禁用 |
内网直连 IP 时请用 Token。要用 Passkey:
ssh -L 8080:127.0.0.1:8080 USER@HOST
# 浏览器打开 http://127.0.0.1:8080/
服务端会按请求 Host 解析 rpId/origin;仍无法绕过浏览器对非 localhost HTTP 的限制。
MCP (ideal remote path)
- Enable token on daemon (
secrets.env→ deploy). - Point an IDE at the MCP via npx auto-install (same token +
ALPHABOUND_API_BASE):
{
"mcpServers": {
"alphabound": {
"command": "npx",
"args": ["-y", "alphabound-mcp"],
"env": {
"ALPHABOUND_API_BASE": "http://127.0.0.1:18180",
"ALPHABOUND_API_TOKEN": "YOUR_TOKEN"
}
}
}
}
npx -y alphabound-mcp install --client copilot
# before npm publish: --source github
# from a clone: node tools/alphabound-mcp/src/index.js install --source local --client copilot
- stdio is the IDE default (
npx -y alphabound-mcp).npx -y alphabound-mcp --httpis a small remote tool gateway (bind loopback; tunnel as needed). - The same binary is a CLI for every MCP tool. Token comes from
ALPHABOUND_API_TOKEN(orDASHBOARD_API_TOKEN) at call time:
export ALPHABOUND_API_BASE=http://127.0.0.1:18180
export ALPHABOUND_API_TOKEN=YOUR_TOKEN
npx -y alphabound-mcp tools
npx -y alphabound-mcp get_system
npx -y alphabound-mcp submit_intel --file envelope.json
Hard rule: MCP does not place orders, flatten, resume, or read secrets.
Control stays on --control / local admin.
The sole write is submit_intel: a pre-signed alphabound.intel.v1
envelope forwarded to POST /api/v1/intel. MCP never holds
ALPHABOUND_INTEL_HMAC. See docs/INTEL.md.
See also: docs/AGENT_ANALYTICS_MCP_PLAN.md.
快速启用
# secrets.env(chmod 600)
ALPHABOUND_API_TOKEN=$(openssl rand -hex 32)
# 浏览器打开的 origin(本机)
ALPHABOUND_WEBAUTHN_RP_ID=localhost
ALPHABOUND_WEBAUTHN_ORIGIN=http://127.0.0.1:18180
重启 daemon 后:
curl -sS http://127.0.0.1:18180/api/v1/auth/status
# auth_required=true 时数据 API 需 token/session
MCP
IDE / Copilot 用 npx -y 自动安装,不必先 clone:
{
"mcpServers": {
"alphabound": {
"command": "npx",
"args": ["-y", "alphabound-mcp"],
"env": {
"ALPHABOUND_API_BASE": "http://127.0.0.1:18180",
"ALPHABOUND_API_TOKEN": "YOUR_TOKEN"
}
}
}
}
npx -y alphabound-mcp install --client copilot
# 尚未发布到 npm 时:--source github
# 本仓库源码:node tools/alphabound-mcp/src/index.js install --source local --client copilot
从源码跑 stdio / HTTP / CLI(token 走环境变量):
cd tools/alphabound-mcp
npm install
export ALPHABOUND_API_BASE=http://127.0.0.1:18180
export ALPHABOUND_API_TOKEN=YOUR_TOKEN # 与 daemon 相同
npx alphabound-mcp # stdio,给 IDE
npx alphabound-mcp tools # 列出全部 MCP 工具
npx alphabound-mcp get_system # CLI 调用同一工具面
# 或本机 HTTP 网关:
# npx alphabound-mcp --http
工具列表见 tools/alphabound-mcp/README.md。
规划背景:AGENT_ANALYTICS_MCP_PLAN.md。