T2 token 管理(src/api/mcp_tokens.rs):create/list/reveal/revoke + get_mcp_client_configs
服务端函数,均经 get_current_admin_user 鉴权;TokenLifetime 枚举(1/7/30/90天/永不过期)。
src/mcp/config.rs 生成 4 种客户端配置(Claude Code/Cursor/Cline/通用 + CLI)。
src/pages/admin/mcp.rs 令牌管理页:列表 + 新建表单 + 一次性明文展示/重查 + 撤销 +
配置片段卡片。路由 /admin/mcp,导航项加入 admin_layout。
T3 read 工具 + Resources(tools/read.rs, resources.rs):search_posts/get_post/list_tags
(read 作用域,仅已发布);published-post Resources(post://{slug},游标分页)。
search_published 提取为共享函数。
T4 write 工具(tools/{posts,comments,tags,media}.rs):create/update/publish/trash/delete_post、
评论审核、标签 CRUD、媒体 base64 上传(WebP 转码 + 去重)。复用既有 helper 的 SQL 与
缓存失效(moka + ssr_cache)。write 作用域,可读草稿。
T5 admin 工具(tools/{settings,runner}.rs):get/update_settings、run_code(沙箱执行)。
admin 作用域。
合并(server.rs):用 rmcp tool_router 的「命名路由 + 组合」模式,7 个工具组在
YggMcpServer 上 impl,combined_router 用 + 合并成单一 ServerHandler。各工具组鉴权
独立,经 Extension<Parts> 读 McpPrincipal + scope.grants 校验。
新增依赖 base64 0.22(媒体上传解码)。验证:server/web 双目标编译通过、clippy
--all-features -D warnings 干净、659 单测 + 1 集成全绿(+20 新测试)。
34 lines
1.7 KiB
Markdown
34 lines
1.7 KiB
Markdown
# T6 — Hardening (rate limit, sanitization, audit, last_used_at)
|
|
|
|
## Blocking edges
|
|
- **Blocks:** T7 (verification exercises a hardened endpoint).
|
|
- **Blocked by:** T3, T4, T5 (tools must exist to harden their outputs).
|
|
|
|
## Target files
|
|
- `src/mcp/rate_limit.rs` — token-keyed governor.
|
|
- `src/mcp/auth.rs` — `last_used_at` update path, body-size cap.
|
|
- `src/mcp/server.rs` / tool outputs — snippet sanitization.
|
|
- audit log integration (tracing, or a dedicated table if the project has one — check
|
|
existing conventions first).
|
|
|
|
## Change
|
|
1. **Token-keyed rate limit** on `/mcp` only: extract bearer → `user_id` → governor key.
|
|
Leave the existing IP-keyed governor on the web app untouched. Add tunable
|
|
`RATE_LIMIT_MCP_PER_SEC` / `_BURST` (match the existing env-var naming pattern).
|
|
2. **`last_used_at`** updated on each authenticated request (cheap UPDATE, or batched —
|
|
match the session-recheck pattern).
|
|
3. **Snippet/output sanitization:** treat search + tool output as indirect-prompt-
|
|
injection surface — strip control chars, cap length, no raw executable instructions.
|
|
Keep read vs write tools on separate scopes (already enforced).
|
|
4. **Body-size cap** on `/mcp` POST (e.g. 1 MiB) to bound abuse.
|
|
5. **Audit logging** of mutating tool calls (token id, tool, outcome) via the project's
|
|
existing logging convention (`tracing`).
|
|
|
|
## Acceptance
|
|
- A token exceeding its rate budget is throttled (429 / MCP rate-limit error).
|
|
- `last_used_at` advances on authenticated requests.
|
|
- Search output is sanitized (no raw control chars; length bounded).
|
|
- Oversized POST body is rejected.
|
|
- Mutating tool calls leave an audit trace.
|
|
- Both targets compile; clippy clean; existing tests pass.
|