# Kestra V52 验证记录 - 代码分支:`codex/kestra-v50` - 验证日期:2026-07-19 - 变更范围:独立 DataOps Runner、短时任务令牌、单次领取账本、受治理节点执行、 数据源资源池复用和 Kestra 到 Runner 调用链 ## 实现结果 - 新增独立 Runner 服务,监听容器内 `5600`,本机健康端口仅绑定 `127.0.0.1:15600`;不与 Flask 请求进程共享连接池。 - Kestra 只调用内部网络别名 `dataops-runner`,不持有业务数据库账号、密码、 密文、连接串或 Runner 签名密钥。 - Runner 使用显式配置构造平台 PostgreSQL、Neo4j 和业务数据源连接池,不再依赖 Flask `current_app` 或请求上下文。 - 默认 2 个 Runner Worker、每数据源 `pool_size=1`、`max_overflow=1`、 每 Worker 最多 4 个空闲池,理论业务库连接上限为 16,配置预算为 32。 - Runner 容器根文件系统只读,并实际生效 1 CPU、512 MiB、128 PID 限制;没有 Docker Socket。 - 任务令牌使用 HS256,最长 300 秒,绑定 `task_uid`、DataFlow UID、流程版本、 节点 ID/类型/摘要、用途、关联 ID 和一次性 `jti`,不携带数据源凭据。 - 新增 `runner_task_executions` 持久账本,`token_jti` 为主键、 `task_uid` 唯一,跨 Worker 原子拒绝重复领取,并记录数据源 UID、幂等键、 状态和 `commit_outcome`。 - SQL 查询只接受单条只读语句和绑定参数,使用原数据源池的只读事务;写节点必须 同时具备受信任写授权和 WorkflowSpec 幂等策略。数据库连接在 COMMIT 时中断会 记录为 `unknown`,不会被转换为普通可重试失败。 - Python 节点不接受任意源码,只允许镜像内注册处理器;子进程限制 CPU、内存、 文件句柄、执行时间并禁用网络。默认白名单为空,未注册处理器失败关闭。 - HTTP 节点要求 HTTPS、部署白名单、无 URL 凭据和无内联授权头,禁止重定向并 限制响应大小。 ## TDD 与定向验证 测试均先确认缺失实现、安全约束或运行契约导致失败,再实现转绿。 ### L1/L2 定向集合覆盖: - `tests/runner` - `tests/core/data_source` - `tests/core/orchestration/test_kestra_compiler.py` - `tests/test_datasource_api_security.py` - `tests/test_datasource_pool_diagnostics.py` - `tests/test_database_migrations.py` 覆盖令牌过期/篡改/节点绑定、重复领取、账本不可用失败关闭、SQL 只读边界、写授权、 未知提交结果、Python 时间/网络限制、HTTP 白名单、显式运行时、连接预算、Compose 隔离和数据库迁移。 最终 L1/L2 定向回归为 `89 passed, 1 skipped, 1 warning`。跳过项是需要临时 管理员数据库 URL 的通用空库迁移测试;V52 迁移已在当前隔离 PostgreSQL 中单独 完成升级、降级、再次升级和重复升级。警告来自本机 Python/LibreSSL 组合。 ### L3 - Runner 镜像构建成功,PostgreSQL、Neo4j、两个外部数据源、Kestra 和 Runner 均达到健康状态。 - `tests/integration/test_runner_datasource_pool.py` 对真实 PostgreSQL/MySQL 完成 受治理查询;相同任务令牌第二次提交返回 409,账本只记录两次成功执行。 - `tests/integration/test_datasource_pool_failures.py` 停止 MySQL 后确认该数据源 单独熔断,外部 PostgreSQL 和平台控制数据库仍可用,恢复后连接池正常重建。 - `tests/integration/test_kestra_runner_execution.py` 完成真实链路: Kestra 执行输入携带节点令牌,HTTP Task 调用 Runner,Runner 通过资源池读取 PostgreSQL,Kestra 执行最终为 `SUCCESS`。 - 端到端首次执行暴露内部 DNS 名称缺失:编译器使用 `dataops-runner`,Compose 只注册 `runner`。补充网络别名并增加自动化契约后,DNS 健康检查和完整执行转绿。 - V52 迁移在真实 PostgreSQL 完成升级、降回 V51、再次升级和重复升级,最终版本为 `20260719_70 (head)`。 - 停止 Runner 时,平台健康接口与 n8n 健康接口均保持 HTTP 200,平台 PostgreSQL `SELECT 1` 成功;重新启动 Runner 后恢复健康。 - Runner/Kestra 日志扫描未发现测试业务库密码、业务连接串、凭据主密钥或密文字段; Kestra 当前测试流程数为 0。 最终 L3 定向回归为 `3 passed, 1 warning`。警告同样来自本机 Python/LibreSSL 组合。 ## 未执行的验证 - 未运行全仓库测试、前端构建或全量容器验收;本版本只运行 V52 相关增量集合。 - 未开放任意 Python 代码执行,默认处理器白名单为空。 - 未由 AI/MCP 直接签发任务令牌或授予写权限;这些必须由 V53 策略、审批和审计 Gateway 处理。 - 未执行正式影子写入或切换 n8n 主路径。 ## 回滚 - 停止 Runner 和 Kestra 测试调用即可退出 V52 新执行路径。 - 保留现有 Flask 数据源资源池和 n8n 主路径,不需要回滚数据源定义或凭据治理。 - `runner_task_executions` 只保存受限执行元数据,不保存业务结果或凭据。 ## 结论 V52 的独立 Runner、受治理执行、真实数据源池、重复提交防护、故障隔离和 Kestra 端到端调用已通过,当前允许进入 V53。V53 应实现 MCP Gateway、策略审批、 受信任令牌签发和全链路审计,保持“AI 可规划但不能自行扩大写权限”的边界。