sdforge 0.5.0-rc.2

Multi-protocol SDK framework with unified macro configuration
# 🏗️ Sdforge 架构文档

本文档描述 SDForge 的设计原则、系统架构、模块划分、数据流以及安全与性能设计。SDForge 是一个基于 Rust 的声明式多协议 SDK 框架:`#[forge]` 过程宏在编译期从统一的函数注解生成多协议(HTTP + MCP + gRPC + WebSocket + CLI)注册代码,未启用的协议不产生任何编译代码。

## 📋 目录

<details open>

- [概述]#-概述
- [设计原则]#-设计原则
- [系统架构]#️-系统架构
- [模块划分]#-模块划分
- [数据流]#-数据流
- [安全设计]#-安全设计
- [性能设计]#-性能设计

</details>

## 🧭 概述

SDForge 由两个 crate 组成:

- **`sdforge-macros`**:过程宏 crate,实现 `#[forge]` / `#[service_module]`,负责解析注解并按 feature 门控生成各协议的注册代码
- **`sdforge`**:运行时库,提供各协议实现、核心类型、配置、安全与文档生成能力

框架的运行时骨架建立在 [inventory](https://crates.io/crates/inventory) 之上:宏生成的注册项(HTTP 路由、MCP 工具、gRPC handler、CLI 命令等)在编译期通过 `inventory::submit!()` 提交,应用启动时由 `init_all_plugins()` 一次性收集固化。

## 🧭 设计原则

1. **编译时协议选择** — 所有协议实现都由 `#[cfg(feature = "...")]` 门控。启用 `http` 不编译 MCP/gRPC/CLI 的任何代码;反之 `mcp``grpc``openapi``cli``streaming``cache` 也独立于 `http``#[forge(path=...)]` 生成的 HTTP 注册代码同样被 `#[cfg(feature = "http")]` 包裹)。量化收益:`http` only 相比 `full` 节省约 46–47% 编译时间、约六成库体积(见 [性能基准]benchmarks/vs-server-less.md)。
2. **统一接口定义** — 单个 `#[forge]` 注解描述端点,多协议各自消费同一份元数据(名称、版本、描述、参数 schema),消除跨协议的重复定义。
3. **Inventory 注册模式** — 编译期 `inventory::submit!()` 注册、运行期收集;`init_all_plugins()` 通过 `OnceLock` 缓存收集结果,防止 release 构建(LTO + 死代码消除)剔除注册项,并返回各协议注册计数用于自检。
4. **统一注册系统** — HTTP、MCP、WebSocket、gRPC 四大协议模块共享 `define_registration!` 宏与 `Registration` trait 抽象,消除重复样板代码。
5. **三种构造模式** — 所有组件必须支持 `new()`(开箱即用)、`builder()`(Builder 模式)、`with_dependencies()`(依赖注入)。
6. **不使用数据库** — 所有数据交互通过 oxcache(内存缓存)完成,框架自身零外部服务依赖;限流复用 limiteron,日志可桥接 inklog,依赖注入复用 trait-kit(`kit` feature)。
7. **统一 handler 契约** — 所有协议的 handler 遵循 `fn(HandlerArgs, HandlerState) -> HandlerFuture``HandlerArgs` 由 clap / tonic / axum extractor 构造,`HandlerState` 通过 `downcast_state::<T>()` 注入。

## 🏛️ 系统架构

```mermaid
flowchart TB
    subgraph Compile["编译期"]
        A["#[forge] / #[service_module] 宏<br/>(sdforge-macros)"] -->|"cfg(feature) 门控代码生成"| B["inventory::submit!<br/>HTTP 路由 / MCP 工具 / gRPC handler / CLI 命令 / OpenApiRouteInfo"]
    end
    subgraph Boot["启动期"]
        B --> C["init_all_plugins()<br/>inventory::iter 收集 → OnceLock 固化 → PluginCounts"]
    end
    subgraph Runtime["运行期"]
        C --> D["协议入口"]
        D --> D1["HTTP: axum Router<br/>build() / build_with_config()"]
        D --> D2["MCP: StatelessServerHandler<br/>(HTTP 头协议 / stdio)"]
        D --> D3["gRPC: SdForgeGrpcService<br/>(tonic)"]
        D --> D4["CLI: CliBuilder::execute<br/>(clap)"]
        D1 --> E["中间件栈<br/>auth_middleware / 限流 / 安全头 / CORS"]
        E --> F["版本路由 /api/{version}<br/>→ 统一 handler (HandlerArgs + HandlerState)"]
        F --> G["业务函数 Result<T, ApiError>"]
        G --> H["ServiceResponse<br/>(status / timestamp / i18n / logging)"]
    end
```

仓库布局:

```
sdforge/
├── src/                # 运行时库
├── macros/             # 过程宏 crate (#[forge])
├── examples/           # 综合示例库 (workspace member: sdforge-examples)
├── benches/            # 基准测试
├── proto/              # protobuf 定义 (gRPC)
├── docs/               # 文档(本目录)
├── tests/              # 集成/单元/宏测试
└── scripts/            # 构建和实用脚本
```

## 🧱 模块划分

| 模块(`src/`| Feature | 职责 |
|----------------|---------|------|
| `core/` || 核心类型:`ServiceError` / `ServiceResponse``ApiMetadata`、统一 handler 契约(`handler.rs`)、inventory 注册抽象(`registration.rs`)、JSON 工具、`RegexCache`、校验(`validation.rs`|
| `error/` || 框架错误:`ApiError``SdForgeError` / `SdForgeResult``ErrorContext`、错误 i18n |
| `domain/` || 领域抽象(如 `ForgeRateLimiter`),供集成层消费 |
| `i18n/` | `i18n`(格式化部分) | 翻译注册表(始终可用)+ ICU4X `HttpI18nFormatter` |
| `http/` | `http` | Axum 协议实现:`build()` / `build_with_config()`、版本路由、安全头、响应构造、路由注册 |
| `mcp/` | `mcp` | rmcp 集成:`StatelessServerHandler`、HTTP 头协议(`headers.rs`)、MRTR 会话(`mrtr.rs`)、缓存语义(`cache_semantics.rs`)、schema 校验 |
| `grpc/` | `grpc` | tonic 服务:`SdForgeGrpcService``GrpcServerConfig`、protobuf(`proto/`,build.rs 生成)、handler 注册与拦截器 |
| `websocket/` | `websocket` | 连接管理(`connection.rs`)、handler 分发(`handler.rs`)、广播(`broadcast.rs`)、消息解析(`message.rs`|
| `streaming/` | `streaming` | SSE:`StreamEvent` / `StreamResponse``stream_to_sse``StreamBuilder` |
| `cli/` | `cli` | clap 集成:`CliBuilder``dispatch``GlobalArg`、docs 子命令 |
| `security/` | `security` / `ratelimit` / `ratelimit-http` | 认证(Bearer / API Key,`bearer/``types/`)、限流(limiteron 适配)、审计(`audit/`)、中间件 |
| `cache/` | `cache` | oxcache 透传与适配:`SyncCache` / `SharedCache` / `DashMapCache` |
| `openapi/` | `openapi` | `OpenApiRouteInfo` 收集与 utoipa 规范生成、`OpenApiBuilder`、路径参数 schema 映射 |
| `docs/` | `docs` | 统一文档输出:Swagger UI 路由、CLI/MCP Markdown(`generate_docs` / `write_docs`|
| `config/` | `http` | `AppConfig` / `ServerConfig` / `AuthConfig` / `CorsConfig` / `CacheConfig` 等模块化配置 + 集中默认值 + Builder |
| `logging.rs` | `logging` | `StructuredLogger`、全局 Logger |
| `inklog.rs` | `inklog` |`log` → inklog `LoggerManager` 桥接 |
| `integrations/` | `limiteron-integration` / `kit` | trait-kit 0.3 AsyncKit 集成(`SdforgeModule`)、`LimiteronForgeAdapter` |

`macros/`(独立 crate):`#[forge]` / `#[service_module]` 解析、参数校验、路径参数提取与 schema 生成、按 feature 门控的多协议代码生成、trybuild 编译失败测试。

## 🔀 数据流

### 编译期

1. 开发者标注 `#[forge(name, version, path, method, ...)]`
2. 宏解析参数并校验(trybuild 覆盖编译失败用例)
3. 按启用的 feature 生成注册代码:
   - `http``RouteRegistration`(路径/方法/版本)+ 路径参数提取器(多参数生成 `Path<(T1, ...)>` 元组按序解构;标量 Query 生成专用提取结构体)
   - `mcp``McpToolRegistration` + `input_schema`(required / unknown-field 校验)
   - `grpc``GrpcHandlerRegistration`(按 `grpc_method` 键)
   - `cli``CliCommandRegistration` + `CliHandlerRegistration`(1:1 成对)
   - `openapi``OpenApiRouteInfo`(含 `OpenApiPathParam`,路径 `:id``{id}`4. 全部注册项经 `inventory::submit!()` 进入编译产物

### 启动期

5. `main` 调用 `init_all_plugins()`:对每类注册项执行 `inventory::iter::<T>().collect()` 存入 `OnceLock<Mutex<Vec<&'static T>>>`(收集结果进程级缓存、幂等;Mutex 中毒时降级返回 0 而非连锁 panic),返回 `PluginCounts`
6. HTTP 侧 `http::build()` 依据 `RouteRegistration` 构建 Axum `Router`(含版本前缀 `/api/{version}``#[service_module]` 前缀拼接)

### 请求期(以 HTTP 为例)

7. 请求进入中间件栈:认证(`auth_middleware`,API Key / JWT Bearer)→ 限流(`RateLimitLayer`,基于 `ConnectInfo` 提取的 TCP 对端 IP)→ 安全头 / CORS / 超时
8. 版本路由匹配 `/api/{version}`,将请求分发到目标 handler;宏生成的提取器把路径/查询参数反序列化为函数参数
9. 统一 handler 契约执行:`HandlerArgs`(extractor 构造)+ `HandlerState``downcast_state` 注入)→ 业务函数 → `Result<T, ApiError>`
10. 响应管道:`ServiceResponse` 封装(显式 `status` / `success_with_status`)→ 可选 timestamp / logging / i18n 处理 → JSON 输出

其他协议入口复用 7–10 的后段:MCP 经 `Mcp-Method` / `Mcp-Name` 头(或 stdio)由 `StatelessServerHandler` 路由到同一批工具 handler;gRPC 经 `SdForgeGrpcService::call()` 按 `grpc_method` 路由(载荷上限 1 MiB);CLI 经 `CliBuilder::execute()` 完成 parse → dispatch → `extract_value`(`Value::String` 输出原始串)→ 退出码。

## 🔒 安全设计

- **认证**`security` feature 提供 API Key(版本管理、LRU 缓存、显式播种 `ApiKeySeed`、空库 fail-loud、过期反向索引强制)与 JWT Bearer(HMAC-SHA256 验签,`MIN_SECRET_LENGTH=32` 强制密钥长度)
- **fail-safe 默认值**`ServerConfig` 默认绑定 `127.0.0.1`(而非 `0.0.0.0`);CORS 校验同时检查 scheme 与 host,`"http://"` 这类仅 scheme 的 origin 被拒绝
- **不可伪造的客户端 IP**:无 `ConnectInfo` 时不信任 `X-Forwarded-For` / `X-Real-IP`,直接返回 `None`,由调用方安全兜底——IP 限流/封禁只能基于 TCP 对端地址
- **审计**`AuditLogger` 记录安全事件,支持 HMAC-SHA256 签名防篡改;密钥轮换动作有审计日志
- **错误脱敏**`ApiError::Internal.message` 清洗后输出(不含路径/堆栈),`error_id` 供日志侧关联;`ErrorContext` 仅在服务端保留
- **输入防御**:MCP 工具 `input_schema` 的 required / unknown-field 校验;MCP 与 gRPC 载荷 1 MiB 上限;并发安全模式(Mutex/RwLock 中毒感知、缓存一致性锁序、usize 下溢防护)经系统化审计修复
- **供应链**`cargo-audit` + `cargo-deny``deny.toml` 策略)+ Dependabot + CodeQL;发布前强制 tiangang SAST(0 CRITICAL)与 diting 审查(无 HIGH)

详见 [安全文档](SECURITY.md)。

## ⚡ 性能设计

- **编译时裁剪是第一性能设计**:特性门控让未用协议的依赖(tonic/prost、rmcp、tokio-tungstenite、argon2/sha2 等)完全不进入编译图。实测(2026-07-03,详见 [性能基准]benchmarks/vs-server-less.md):
  - 编译时间:`http` only 相比 `full` 节省 47.0%(debug)/ 46.2%(release)
  - 框架库 rlib:debug 33.9 MB vs 100.2 MB(-66.2%);release 3.57 MB vs 9.07 MB(-60.6%)
  - 依赖图:396 vs 478 个唯一 crate
- **运行期零协议税**:协议选择发生在编译期,不存在运行时协议探测或动态加载
- **注册收集幂等缓存**`init_all_plugins()``OnceLock` 缓存 inventory 迭代结果,重复调用零开销
- **正则缓存**`core::RegexCache` 以 LRU 缓存编译后的正则(修复过 MRU 误驱逐缺陷),避免热路径重复编译
- **内存缓存**:oxcache 承载响应/工具结果缓存,支持键规范化、模式失效、批量操作与统计
- **发布 profile**`lto = true``codegen-units = 1``opt-level = "z"`,最大化死代码消除与体积优化(注意:链接期消除可稀释二进制层级的裁剪收益,但编译期成本节省不受影响)