# 快速 Demo 核心契约 V1 冻结日期:2026-07-27 状态:`frozen-target` ## 1. 契约边界 Demo 公共 HTTP API 由两部分共同组成: 1. `openapi/platform-api-v1.yaml`:已经运行的脚本、稳定版本详情、数据资源和文件编辑锁接口。 2. `openapi/demo-core-extension-v1.yaml`:第 15 小步冻结、后续小步实现的上下文、Jupyter 票据、稳定版本列表、调度和运行查询接口。 内部 Storage 与 Runtime 接口继续分别以 `openapi/storage-api-internal-v1.yaml` 和 `openapi/runtime-api-internal-v1.yaml` 为准。 ## 2. 不可变约束 - 主标识使用 ULID;调度节点只引用不可变的 `versions_id`。 - 当前认证上下文由 `X-User-ID`、`X-Workspace-ID` 提供;以后换成 JWT 时不得改变业务 DTO。 - 修改调度方案必须提交 `workflow_version`,冲突返回 `412`。 - 创建调度、立即运行、启停和取消使用 `Idempotency-Key`。 - `schedule_runs.schedule_snapshot` 固化本次执行 DAG,后续编辑不影响已创建的运行。 - 浏览器不能拿到 Jupyter 内部 Token,只能获得短期访问 Cookie。 ## 3. 状态值 - 调度运行:`queued / running / succeeded / failed / cancelled / timed_out` - 节点运行:`queued / running / succeeded / failed / skipped / cancelled / timed_out` - 失败策略:`stop / continue` - 触发类型:`manual / cron / api / retry` ## 4. MySQL Outbox 与 HTTP 推送 | 事件 | 写入方 | 处理方 | |---|---|---| | `schedule.run.requested` | Backend / Cron Dispatcher | Schedule Executor | | `job.node.execute` | Schedule Executor | Schedule Executor Worker | | `job.node.finished` | Schedule Executor Worker | Schedule Executor | 业务事务先写 `outbox_events`。Backend 对“立即运行”执行一次内部 HTTP 推送, Executor 同时轮询 MySQL 作为兜底;`consumer_inbox` 防止同一事件重复执行。 ## 5. 模块所有权 | 模块 | 拥有的数据与职责 | |---|---| | Platform API | 脚本、稳定版本、调度定义、运行查询、Outbox 写入 | | Runtime Manager | Workspace/Jupyter 生命周期与内部运行态 | | Nginx | 统一入口、Jupyter HTTP/WebSocket 代理 | | Schedule Orchestrator | 消费调度请求、解析 DAG、推进节点状态 | | Job Worker | 读取稳定版本、执行节点、保存日志/结果、报告终态 | | Storage Service | RustFS 对象元数据与预签名访问 | 模块间不得复制定义 DTO、状态枚举、错误结构或事件字段;契约变更必须先 升级本目录中的版本化文件。