yggdrasil/migrations/017_mcp_tokens.sql
xfy 7b9dfa7851 feat(mcp): tracer bullet — /mcp 端点骨架与 search_posts 工具
T1 探针式实现,接通端到端链路并验证双目标编译:

- 依赖:rmcp=3.0.0-beta.3(server/macros/transport-streamable-http-server/
  transport-worker)+ aes-gcm,均经 server feature 门控。
- 迁移 017_mcp_tokens:UUID 主键、scope 约束、token_enc 密文 + token_hash
  唯一索引(仅未撤销),users.id 外键级联。
- 模型 src/models/mcp_token.rs:TokenScope(read<write<admin 偏序,grants)+
  McpToken/McpTokenSummary/CreateTokenResponse DTO。
- src/mcp/(server-only):
  - crypto.rs:AES-GCM-256 加解密(hex 密钥、每次独立 nonce、8 项单测)。
  - auth.rs:bearer→SHA-256→DB 常量查找→注入 McpPrincipal,刷新 last_used_at。
  - server.rs:rmcp ServerHandler,search_posts 工具(read 作用域,pg_trgm 查询)。
  - router.rs:StreamableHttpService(无状态+JSON 响应+Origin 白名单)挂载 /mcp。
- main.rs:merge mcp_route 到应用路由;models/mod.rs 注册 mcp_token 模块。

验证:rmcp+axum-0.8 兼容性经临时探针实测(tools/list、tools/call、Origin→403、
bearer→工具 principal 全链路);--features web 与 --features server 均编译通过;
clippy --all-features -D warnings 干净;639 单测+1 集成 +13 新 MCP 测试全绿。
2026-07-28 11:09:55 +08:00

26 lines
1.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- MCPModel Context Protocol服务器的访问令牌。
-- 令牌由管理员在后台签发绑定用户与作用域read/write/admin
-- 静态加密存储token_enc = AES-GCM 密文),并以 SHA-256 哈希做每请求常量查找。
-- 与 sessions 表一致:明文不入库;但本表支持「管理员重查明文」(解密 token_enc
-- 故不存裸明文而是可逆密文。expires_at 为 NULL 表示永不过期(签发时显式选择)。
CREATE TABLE IF NOT EXISTS mcp_tokens (
id UUID PRIMARY KEY, -- 应用层生成uuid crate
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL, -- 管理员自命名,仅展示
scope TEXT NOT NULL CHECK (scope IN ('read', 'write', 'admin')),
-- AES-GCM 密文nonce ‖ ct ‖ tag的 hex 编码;管理员可解密重查明文。
token_enc TEXT NOT NULL,
-- 明文 token 的 SHA-256 hex64 字符),用于每请求 O(1) 常量查找。
token_hash CHAR(64) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ, -- NULL = 永不过期(显式选择)
last_used_at TIMESTAMPTZ,
revoked_at TIMESTAMPTZ -- NULL = 有效;撤销后置为 NOW()
);
-- 仅在「未撤销」令牌间保证 token_hash 唯一:撤销后可回收同名 hash理论碰撞极低
CREATE UNIQUE INDEX IF NOT EXISTS mcp_tokens_token_hash_active_idx
ON mcp_tokens (token_hash) WHERE revoked_at IS NULL;
CREATE INDEX IF NOT EXISTS mcp_tokens_user_idx ON mcp_tokens (user_id);