## baas-gateway ### REQ-GW-001 统一入口 - 路由规则:`POST /api/com/{vendor}/{action}` - `vendor` ∈ {`dingtalk`, `aliwork`, `beisen`, `teambition`, `feishu`, `fxiaoke`, `h3yun`, ...}(以 `mjava/service/` 下 vendor 包实际存在为准) - `action` 为显式注册的 key,形如 `user.get` / `form.save` / `attendance.listRecord`(命名对应官方 API 文档语义) - 请求体 JSON;字段名**必须**与基座 Client 对应方法参数一致 ### REQ-GW-002 签名校验 - Header 必含 `X-Caller-Id` `X-Signature` `X-Timestamp` - 校验顺序:timestamp 窗口 5 分钟 → callerId 查注册表 → HMAC-SHA256 比对 → 调用方启用状态 - 任一失败:`401 { code: "AUTH_FAILED", reason: "..." }`(reason 不暴露具体环节,避免用户猜测) ### REQ-GW-003 动作白名单 - action 必须先在 `ActionRegistry` 代码显式注册(反射调基座 Client 方法) - 同时必须在 `application.yml` 的 `com.actions.enabled` 列表启用 - 调用方在宜搭权限表单的 `allowedActions` 包含该 action 才允许访问 - 三层校验任一不过:`403 { code: "ACTION_FORBIDDEN" }` ### REQ-GW-004 响应格式 - 返回 `McR`(基座已有):`{ success, code, message, data }` - 第三方原始响应放在 `data` 字段,保留全部原始结构(不做字段转义) - 第三方错误统一映射为 `McR.fail()`,`data` 含 vendor 原始错误码 ### REQ-GW-005 限流 - 按 callerId 本地 `RateLimiter`,阈值取宜搭权限表单 `rateLimit` 字段 - 超限返回 `429 { code: "RATE_LIMITED", retryAfter: 1 }` ### REQ-GW-006 审计扩展 - 日志字段在 `mjava-baseline §3.5` 基础上追加 `callerId` / `vendorAction` / `signatureValid` - 日志文件按 callerId 分片 ## caller-registry ### REQ-CR-001 注册源 - 调用方白名单维护于宜搭"权限表单"(formUuid 配置在 `com.caller.registry.formUuid`) - 字段约定见 `design.md` ### REQ-CR-002 加载与刷新 - 启动时全量拉取 `enabled=on` 的调用方到内存 `Map` - 默认 TTL 300 秒,可配 `com.caller.registry.ttlSeconds` - 失效后 stale-while-revalidate ### REQ-CR-003 密钥轮换 - 调用方申请新密钥 → 运营在宜搭表单更新 `callerSecret` → 下次拉取后生效 - 宜搭表单不保留历史版本(如需双密钥轮换,未来提案支持) ### REQ-CR-004 调用方停用 - `enabled=off` 后,注册表下次刷新移除 - 停用期间返回 `401 CALLER_DISABLED` ## 非目标明示 - 不做签名算法可插拔(固定 HMAC-SHA256;将来如需支持国密再提案) - 不做 mTLS / API Gateway 前置 - 不做请求体加密(HTTPS + HMAC 完整性足够) - 不做响应缓存(每次都直调基座 Client;幂等缓存由调用方自行做)