# 授权验证模块开发计划
## 概述
为 ibkr-mcp 实现商业化授权验证系统,通过 API Key 管理用户权限层级。
## 统一装饰器设计
```python
# auth.py
class Tier(Enum):
FREE = "free" # 需配额检查
PRO = "pro" # 需 tier + 配额检查
PREMIUM = "premium" # 只需 tier 检查(无限额)
def require_tier(required: Tier = Tier.FREE):
"""权限检查装饰器"""
def decorator(func: Callable) -> Callable:
@wraps(func)
async def wrapper(*args, **kwargs):
auth = get_auth_manager()
# tier 错误提示
if required == Tier.PRO and not auth.can_use_pro():
return {"error": "pro_required", "message": "需要 PRO 账户", "upgrade_url": "..."}
if required == Tier.PREMIUM and not auth.can_use_premium():
return {"error": "premium_required", "message": "需要 PREMIUM 账户", "upgrade_url": "..."}
# quota 检查 (FREE/PRO)
ok, msg = auth.check_quota()
if not ok:
return {"error": "quota_exceeded", "message": msg, "upgrade_url": "..."}
return await func(*args, **kwargs)
return wrapper
return decorator
```
## 使用方式
```python
# FREE (默认,需要配额检查)
@mcp.tool()
@require_tier()
async def get_portfolio(...) -> ...:
...
# PRO
@mcp.tool()
@require_tier(required=Tier.PRO)
async def scan_option_signals(...) -> ...:
...
# PREMIUM
@mcp.tool()
@require_tier(required=Tier.PREMIUM)
async def admin_feature(...) -> ...:
...
```
## 权限矩阵
| 装饰器 | 无 Key (10/天) | Free Key (100/天) | Pro Key (1000/天) | Premium Key |
|--------|----------------|-------------------|-------------------|-------------|
| `@require_tier()` | ✅ 配额 10 | ✅ 配额 100 | ✅ 配额 1000 | ✅ 无限 |
| `@require_tier(PRO)` | ❌ 需注册 | ❌ 需升级 | ✅ 配额 1000 | ✅ 无限 |
| `@require_tier(PREMIUM)` | ❌ 需注册 | ❌ 需升级 | ❌ 需升级 | ✅ 无限 |
## 配额模型
| 层级 | API Key | 每日配额 | 同步方式 |
|------|---------|----------|----------|
| **无 Key** | 无 | 10 次 | 本地缓存 |
| **Free** | `AM` + 29字符 | 100 次 | 云端追踪 |
| **Pro** | `AM` + 29字符 | 1000 次 | 云端追踪 |
| **Premium** | `AM` + 29字符 | 无限制 | 云端追踪 |
## API Key 格式
```
格式: AM[29个字母数字] = 共31个字符
示例: AMSv3Kj9Xx2Pq5Rw8Z1Y6Dc4N7B0fGh
解析规则:
- 无 Key: 默认 Free tier,10次/天
- 有 Key: 调用 alphameta.app 验证并获取 tier
```
## 无 Key vs Free Key 区别
| | 无 API Key | Free Key |
|---|------------|----------|
| 注册 | 否 | 是 (alphameta.app) |
| 配额 | 10 次/天 | 100 次/天 |
| 追踪 | 本地缓存 | 云端 |
| 用途 | 试用体验 | 轻度用户 |
## 配额同步策略
- **无 Key 用户**:本地计数,到期重置 (UTC 0点)
- **Free/Pro/Premium**:每次调用后实时同步到 alphameta.app
## 目录结构
```
src/ibkr_mcp/core/
├── auth.py # 授权管理器 AuthManager + require_tier 装饰器
└── __init__.py # 导出
src/ibkr_mcp/mcp/
├── tools.py # 工具实现
└── resources.py # 资源定义
```
## 核心文件设计
### auth.py - 授权管理器和装饰器
```python
class Tier(Enum):
FREE = "free"
PRO = "pro"
PREMIUM = "premium"
class AuthManager:
DAILY_QUOTA = 10 # 无 API Key: 10次/天
async def initialize(self, api_key: Optional[str] = None):
self._api_key = api_key
self._tier = Tier.FREE
self._quota = self.DAILY_QUOTA
self._load_from_cache()
def can_use_pro(self) -> bool:
return False # MVP: 始终返回 False
def can_use_premium(self) -> bool:
return False # MVP: 始终返回 False
def check_quota(self) -> tuple[bool, str]:
# 本地缓存到 ~/.ibkr-mcp/quota.json
# UTC 0点重置
def require_tier(required: Tier = Tier.FREE):
"""权限检查装饰器"""
...
```
## alphameta.app API 设计
### 验证接口
```
GET /api/v1/auth/verify
Header: Authorization: Bearer <API_KEY>
Response 200:
{
"tier": "pro",
"quota": {"daily": 1000, "used": 150},
"expires_at": 1735689600
}
Response 401:
{"error": "invalid_api_key"}
```
## 缓存机制
- 本地缓存文件: `~/.ibkr-mcp/quota.json`
- 缓存 TTL: 1 小时
- 后台刷新间隔: 30 分钟
## 错误响应格式
```json
// PRO 权限不足
{
"error": "pro_required",
"message": "需要 PRO 账户",
"upgrade_url": "https://alphameta.app"
}
// PREMIUM 权限不足
{
"error": "premium_required",
"message": "需要 PREMIUM 账户",
"upgrade_url": "https://alphameta.app"
}
// 配额用尽
{
"error": "quota_exceeded",
"message": "Daily quota exceeded (10/10)",
"upgrade_url": "https://alphameta.app"
}
```
## MVP 边界
- 无 API Key: 本地配额 10次/天
- 有 API Key: 暂不实现(未来接入 alphameta.app)
- PRO/PREMIUM tier 检查:错误提示(始终返回权限不足)
- 无云端 API 调用(配额)
## 实现步骤
1. [ ] 创建 `src/ibkr_mcp/core/auth.py`
2. [ ] 更新 `src/ibkr_mcp/core/__init__.py` 导出
3. [ ] 修改 `src/ibkr_mcp/mcp/tools.py` 添加装饰器
4. [ ] 更新 `src/ibkr_mcp/mcp/resources.py` 添加认证状态资源(可选)
5. [ ] 更新 `src/ibkr_mcp/server.py` 集成 AuthManager
6. [ ] 测试各层级权限控制