# AI Gateway Go AI Gateway 的全量 Go 重构工程。M0–M6 工程实现已完成,当前可运行基线包含 PostgreSQL、双 Redis、独立迁移器、Art Design Pro 管理端/门户端、OpenAI 兼容网关和可发布的 AI 资产编排运行时。 ## 当前能力 - `GET /healthz`:进程存活检查。 - `GET /readyz`:PostgreSQL、critical Redis 和 cache Redis 状态;前两者失败会返回 `503`。 - `GET /metrics`:不依赖外部组件的基础 Prometheus 文本指标。 - `POST /v1/chat/completions`、`POST /v1/responses`、`POST /v1/embeddings`、`POST /v1/messages`:透明代理,支持 SSE。 - `GET /v1/models`:透明代理。 - 独立 `gateway-migrator`,API 启动时不会修改数据库结构。 - PostgreSQL 权威管理员/门户身份、PBKDF2 旧密码兼容和 Redis 可撤销会话。 - 管理端与门户端 RFC 6238 TOTP 两步验证、5 分钟挑战令牌、时间步防重放和一次性备用码。 - Provider 管理 API;凭据使用 AES-256-GCM 加密,变更与 outbox 同事务提交。 - PostgreSQL Provider 原子运行时快照、默认/显式路由、能力校验和共享 HTTP 连接池;刷新失败保留上一有效版本。 - Provider 连接测试和模型目录同步;上游缺失模型保留历史记录并自动停用,同步事件与目录更新同事务提交。 - 管理员/门户账号管理、内置角色与可扩展 `resource:action` 权限字符串;账号和权限变更即时生效。 - 层级部门管理和门户账号部门绑定;循环层级、停用父部门和停用在用部门均由服务端约束。 - OIDC Authorization Code + PKCE 登录、RS256 ID Token 校验、外部账号映射与自动开户。 - SAML 2.0 SP 发起登录、SP metadata、签名断言验证、RelayState/Request ID 绑定、断言防重放与自动开户。 - 旧系统 38 个持久化实体的数据字典,以及幂等的旧 ID → UUIDv5 兼容映射基础设施。 - PostgreSQL API Key(明文仅显示一次、scope、过期时间、Redis 共享缓存、即时撤销)及 Art 管理页面。 - 按 API Key 配置的每分钟请求上限、UTC 自然月请求配额和 Token 配额;critical Redis Lua 原子执行,Token 采用请求前预留、JSON/SSE usage 回写校准,返回 429、`Retry-After` 和配额响应头。 - Provider 级响应头超时、幂等安全重试与熔断;POST 只有在客户端提供 `Idempotency-Key` 且请求体可重放时才会重试。 - PostgreSQL 模型别名和条件路由,按 endpoint、API Key、tenant 过滤,并在最高优先级组内做确定性加权 Provider 选择;规则通过不可变快照运行并由 Redis 通知多实例刷新。 - 有界异步调用审计和按日 usage 聚合:批量写 PostgreSQL,记录状态、延迟及输入/输出 Token;管理端提供权限隔离的筛选查询,审计存储异常不会阻塞模型调用。 - 独立事务 Outbox Worker:多实例 `SKIP LOCKED` 抢占、Redis Stream 原子去重投递、指数退避与死信;管理端可审阅并人工重试,消费者可用同事务幂等入口。 - PostgreSQL 审计月分区维护:自动预创建、default 分区在线迁移、过期整分区快速丢弃、边界精确清理和更长期的 usage 保留策略。 - 可扩展内容策略:Go RE2 不可变编译快照,按端点、模型/API Key 匹配,支持仅审计、阻断与提示词文本脱敏;默认保护常见 API Key、Token、密码和 secret。 - 带时间版本的模型价格与成本核算:按 Provider/模型选择价格,输入与输出 Token 分别计价,结果进入调用审计和 PostgreSQL 按日聚合。 - Prompt 分类、模板和不可变版本,支持显式变量定义、必填校验、历史版本激活与 API Key 渲染接口。 - PostgreSQL 知识库:2 MiB 有界文本正文、段落感知重叠分块、FTS + 中文二元词片混合检索,以及可替换的 `Retriever` 接口;向量化由 M8 的 pgvector/Ollama 阶段提供。 - 声明式 HTTP 工具:JSON Schema 基础校验、KEK 加密请求头、注册和拨号双层 SSRF 防护、禁止重定向、1 MiB 响应限制与调用记录。 - AI 应用草稿和不可变发布版本,将模型、Prompt、知识库、工具组合为 `/v1/applications/{code}/chat/completions`;所有模型轮次继续经过鉴权、配额、内容策略、路由、成本和审计。 - 独立通知 Worker 消费可靠 outbox,按精确事件或末尾 `*` 模式投递 HMAC-SHA256 Webhook;内容策略命中由审计批处理异步产生脱敏事件,失败投递可在 Art 管理端重试。 - 门户自助工作台:部门范围资产目录、Prompt 搜索/收藏、个人审计/用量/成本、模型访问申请与管理员审批。 - M8 对象存储:自托管 MinIO,上传/下载全部经网关代理(不暴露主机端口),管理端文件管理与门户个人文件仓库,`sha256` 完整性校验与严格归属隔离。 - 门户应用托管会话:服务端加密运行凭证、单会话租约、不可变消息序列和 SHA-256 哈希链,不向浏览器暴露应用 API Key。 - 独立事实核验配置、作用域策略与事件契约,复用 Provider 加密凭据和知识库引用,为同步/异步执行器保留清晰模块边界。 - 旧 Python 源码 201 条路由全部有覆盖、替代或退役决策,未决契约缺口为 0;OpenAPI 0.10.0 覆盖全部 Go 字面量路由。 M8 起 MinIO(对象存储)纳入基线部署并由 compose 提供,但不作为启动依赖:网关启动时 MinIO 未就绪只告警、上传请求得到明确报错,服务不会因对象存储缺失而崩溃。ClickHouse 不属于基线,审计与统计继续存放在 PostgreSQL。 ## 本地启动 1. 复制 `.env.example` 为 `.env` 并修改密钥。 2. 启动 PostgreSQL 和两套 Redis:`docker compose -f deploy/docker-compose.yml up -d postgres redis-critical redis-cache`。 3. 执行迁移:`go run ./cmd/gateway-migrator`。 4. 设置 `BOOTSTRAP_ADMIN_PASSWORD` 后执行 `go run ./cmd/gateway-bootstrap` 创建初始管理员。 5. 启动 API:`go run ./cmd/gateway-api`。 6. 启动可靠事件投递:`go run ./cmd/gateway-outbox-worker`。 7. 启动审计分区与保留维护:`go run ./cmd/gateway-maintenance`。 8. 启动通知投递:`go run ./cmd/gateway-notification-worker`。 完整容器部署可执行 `docker compose -f deploy/docker-compose.yml up -d --build`。Art Design Pro 管理端默认暴露在 `http://127.0.0.1:8081`,门户端在 `http://127.0.0.1:8082`;两者同源代理 `/api/*`、`/v1/*`、`/healthz` 和 `/readyz` 到 Go API,Go API 仍可从 `8080` 端口直接访问。 生产部署请使用 `deploy/docker-compose.production.yml` 和 `deploy/production.env.example`,完整步骤见 [`deploy/PRODUCTION.md`](deploy/PRODUCTION.md)。生产编排默认仅绑定回环地址、要求显式提供数据库/Redis/加密密钥,并关闭迁移期 bootstrap API key。 如果主机未安装 Go,可以在 Compose 依赖启动和迁移完成后执行: ```bash docker compose -f deploy/docker-compose.yml run --rm \ -e BOOTSTRAP_ADMIN_PASSWORD='替换为强口令' \ --entrypoint gateway-bootstrap gateway-api ``` 未设置 `HTTP_ADDR` 时只监听 `127.0.0.1:8080`;容器配置会显式监听 `:8080`。 生产环境必须设置 `APP_ENV=production`,并使用带 TLS 的数据库和 Redis 地址。启用环境变量上游回退时必须设置 `UPSTREAM_API_KEY`。数据库 API Key 已可用于网关请求;bootstrap key 默认关闭,仅用于迁移兼容,需要时显式设置 `GATEWAY_BOOTSTRAP_API_KEY_ENABLED=true` 并配置强随机值,迁移结束后立即关闭,此时无需再配置 bootstrap key。`gateway_bootstrap_api_key_uses_total` 指标可用于确认旧客户端是否已经清零。bootstrap key 会绕过按 key 的限流与配额,切勿长期开启。 内置管理员角色为 `superadmin`、`operator`、`auditor`。超级管理员拥有通配权限;运维管理员默认管理 Provider 和 API Key;审计员只有读取权限。账号还可获得独立的 `resource:action` 权限,服务端每次请求都会从 PostgreSQL 复核账号状态和权限,因此停用或权限回收即时生效。 内容策略和模型价格以 PostgreSQL 为权威源,管理端保存后本实例立即刷新;其他实例分别按 `CONTENT_POLICY_REFRESH_INTERVAL`、`PRICING_REFRESH_INTERVAL`(默认 30 秒)加载不可变快照。正则采用 Go RE2,不支持回溯、环视等可能导致灾难性耗时的表达式。价格金额以微货币单位整数保存,避免浮点累计误差;例如 USD 2.50/百万 Token 存为 `2500000`。 部门采用稳定 UUID 与邻接表层级。部门仍包含启用门户用户或启用子部门时不能停用;移动部门时会在事务内检测自身引用和任意深度循环。门户账号只能绑定启用部门,解绑不会删除任何历史身份数据。 OIDC 登录使用 Redis 保存 5 分钟一次性 `state`、`nonce` 和 PKCE verifier;回调校验发现文档、JWKS/RS256 签名、issuer、audience/azp、iat/nbf/exp 与 nonce。门户会话令牌不进入回调 URL,只使用 60 秒一次性交换码。OIDC Client Secret 使用 `identity-provider-credentials` 独立 AEAD 用途加密。 SAML 当前只开放 SP-initiated Redirect 登录和 POST ACS,显式拒绝 IdP-initiated 与 Artifact 绑定。IdP metadata 通过 SSRF 安全客户端获取并短时缓存,启用前校验 Entity ID、Redirect SSO 端点、签名证书和过期时间。ACS 依次验证 XML 签名、issuer、audience、destination、recipient、InResponseTo 和时间窗,只接受 SHA-256 及以上的签名/摘要算法,并使用 Redis 防止 RelayState 和 Assertion ID 重放。 登录防爆破采用两层叠加:账号锁定(`LOGIN_MAX_FAILURES` 次失败后锁定 `LOGIN_LOCK_DURATION`,针对单账号)与按 IP 的 Redis 滑动窗口限流(`LOGIN_RATE_LIMIT_MAX` 次/`LOGIN_RATE_LIMIT_WINDOW`,超出返回 429,针对跨账号撞库)。限流在 Redis 不可用时 fail-open,账号锁定仍然生效。来源 IP 取自 `X-Forwarded-For`:`deploy/nginx-web.conf` 在 `/api/` 路径用 `$remote_addr` 覆盖该头,避免客户端伪造头绕过限流;直接访问网关端口绕过 nginx 的请求仍可伪造该头,因此生产建议将管理面代理收敛在受信网络内。 旧 Python 数据结构的完整字段字典见 `docs/legacy-data-dictionary.md`。迁移使用 `gateway.legacy_id_mappings` 保存来源、实体、旧 ID 与新 UUID 的对应关系;新 UUID 由固定 namespace 的 UUIDv5 生成,同一条旧数据可安全重跑而不会生成不同主键。字段字典可用 `scripts/export_legacy_dictionary.py` 从旧工程重新生成。 `CREDENTIAL_MASTER_KEY` 必须是 32 字节密钥的 Base64 编码。Compose 中的默认值只允许本地开发,生产环境必须替换并纳入密钥托管与备份;丢失该密钥会导致 Provider 凭据、TOTP、工具请求头、通知签名密钥和应用运行凭证无法解密。每类密文使用独立用途标签,不能相互替换。 工具端点和通知 Webhook 默认只允许公网 HTTP(S) 地址,并在实际拨号时重新解析与校验地址。确有内网服务时分别显式设置 `ALLOW_PRIVATE_TOOL_URLS=true`、`ALLOW_PRIVATE_WEBHOOK_URLS=true`;这两个开关与 Provider 私网开关相互独立。 影子流量默认关闭。设置 `SHADOW_BASE_URL`、专用 `SHADOW_API_KEY` 和大于 0 的 `SHADOW_SAMPLE_RATE` 后,只复制确定性采样的非流式 JSON POST;生产客户端凭据不会转发。主响应不等待影子请求,Prometheus 指标只比较 HTTP 状态和 JSON 结构签名,不记录提示词或模型正文。压测使用独立 `gateway-loadtest` 二进制,可用错误率和 p95 阈值直接控制退出码。 旧路由矩阵由 `scripts/compare_route_contracts.py` 从 Python AST 与 Go OpenAPI 生成。旧源码当前实际包含 201 个路由装饰器,并非早期估算的 141 个;矩阵明确区分同契约覆盖、新契约替代、退役和真实缺口。切换步骤见 `docs/cutover-runbook.md`,旧数据暂存与密文边界见 `docs/legacy-import-runbook.md`。 KEK 轮换时,将 `CREDENTIAL_KEK_VERSION` 和 `CREDENTIAL_MASTER_KEY` 设置为新活动版本与新密钥,并用 `CREDENTIAL_KEK_KEYRING` 加载历史密钥,例如 `{"1":""}`。服务重启并确认可解密后,在供应商页面执行“轮换凭据”;所有旧版本 Provider 凭据和对应 outbox 事件会在一个事务内提交。确认全部 Provider 已切换后才能从 keyring 移除旧密钥。TOTP 同样通过 keyring 保持历史版本可解密,新配置会使用活动版本。 Provider 以 PostgreSQL 为权威源,在进程内构建不可变快照。管理 API 修改后会刷新本实例并通过 critical Redis Pub/Sub 通知其他实例立即刷新;默认每 5 秒轮询仍作为通知丢失或 Redis 短暂异常时的兜底。请求可通过 `X-Gateway-Provider` 指定 Provider;未指定时使用 `config.default=true` 的启用项,否则使用按 code 排序的第一项。`UPSTREAM_FALLBACK_ENABLED=false` 可关闭环境变量上游回退。 供应商连接测试和模型同步访问 OpenAI-compatible `/v1/models`。控制面请求限制为 10 秒、4 MiB 响应,拒绝重定向,并在禁用私网 Provider 时对实际拨号地址再次执行 SSRF 校验。模型同步不会物理删除旧模型,本次未出现的模型会标记为停用,为后续别名和路由规则保留引用稳定性。 ## 目录 - `api/openapi`:对外契约。 - `cmd`:可部署二进制。 - `internal/platform`:配置、数据库、缓存、HTTP 运行时。 - `internal/provider`:上游 Provider 扩展接口及实现。 - `internal/gateway`:协议入口和代理编排。 - `internal/workbench`:Prompt、知识、工具、应用编排和通知。 - `internal/portal`:门户目录、申请、个人统计、加密应用凭证与托管会话。 - `internal/factcheck`:事实核验设置、策略和事件契约。 - `migrations`:仅由 migrator 执行的 PostgreSQL 迁移。 - `web`:Art Design Pro 管理端和门户端。