# Orbit HTTP 与 WebSocket 协议草案 > 版本 0.2 · 2026-09-17。HTTP + WS 已确认。本文保留首版设计建议;已实现能力以[正式接口手册](api/README.md)为准,其余路径、消息名、字段和状态码仍待对应阶段实现及验证。 实现更新:HTTP 任务/队列、Worker/Event WSS 以及 Weave 公共接口均已接入;实际帧名、字段、回执与边界见 [Worker 契约](api/worker.md)、[事件接口](api/subscriptions.md)和[流程接口](api/workflows.md)。本文保留协议推导和边界说明,生产兼容与拓扑验收仍以持续计划和发布清单为准。 ## 1. 通用契约 - 生产使用 HTTPS / WSS;HTTP 承担任务提交、流程启动与信号、查询、管理,WS 承担 Worker 双向通信与结果订阅。 - 数据采用 JSON;HTTP 契约使用 OpenAPI 描述,WS 消息使用版本化 JSON Schema 与交互时序描述。 - ID 与执行代次等可能超出跨语言整数精度的值使用字符串。时间使用 RFC 3339 UTC 字符串,时长字段注明单位。 - 请求体、消息、批量条数、查询页大小和发送缓冲都必须有限制;具体上限见待定参数表。 - 鉴权后校验应用、环境、队列和操作权限。请求中的命名空间、Worker ID、任务 ID 不能代替授权。 - SDK 与服务端维护兼容矩阵;不兼容的协议或处理器版本明确拒绝,不静默解释为当前版本。 ## 2. HTTP 接口草案 | 方法与路径 | 行为 | | --- | --- | | `POST /v1/tasks` | 幂等提交一项任务 | | `POST /v1/tasks:batch` | 已实现;逐项身份、四类结果与限制见[批量手册](api/batch-tasks.md) | | `GET /v1/tasks/{task_id}` | 查询权威任务状态与结果摘要 | | `GET /v1/tasks/{task_id}/attempts` | 分页查询执行尝试 | | `GET /v1/tasks` | 按有索引的字段分页查询,支持提交幂等键精确查找 | | `POST /v1/tasks/{task_id}:cancel` | 请求取消,记录原因 | | `POST /v1/tasks/{task_id}:retry` | 普通任务人工重试;流程关联任务须经 Weave 恢复入口 | | `POST /v1/schedules` | 创建计划,明确漏跑和重叠策略 | | `PATCH /v1/schedules/{schedule_id}` | 带预期版本修改计划,冲突时拒绝覆盖 | | `POST /v1/schedules/{schedule_id}:pause` | 暂停计划的新触发 | | `POST /v1/schedules/{schedule_id}:resume` | 按漏跑策略恢复计划 | | `GET /v1/schedules/{schedule_id}/occurrences` | 查询计划触发记录 | | `GET /health/live`、`GET /health/ready` | 进程存活与接单就绪状态,二者独立 | 应用、凭据、队列、配额和审计管理接口沿用同一鉴权、版本与错误规范,其完整路径清单在接口评审时补齐。就绪检查必须反映关键依赖,数据库不可用时不能继续宣称可安全接单。 Weave以下接口已接入公共HTTP与SDK,具体字段和权限以[实例接口](api/workflows.md)、[恢复接口](api/workflow-recovery.md)为准: | 方法与路径 | 行为 | | --- | --- | | `POST /v1/workflow-definitions/{definition_id}/versions` | 研发通过 SDK 发布不可变定义;同版本同内容幂等,不同内容冲突 | | `POST /v1/workflows` | 幂等启动流程,固定定义版本 | | `GET /v1/workflows/{workflow_id}` | 查询实例、定义版本、执行状态、暂停标记与等待摘要 | | `GET /v1/workflows/{workflow_id}/steps` | 按键返回最多128项步骤元数据;单个步骤详情另用`/steps/{key}`读取输入/输出、等待和查询预算 | | `POST /v1/workflows/{workflow_id}/signals` | 幂等受理信号,不等于信号已经被消费 | | `GET /v1/workflows/{workflow_id}/signals/{signal_id}` | 查询信号受理、匹配与消费结果 | | `POST /v1/workflows/{workflow_id}/control` | PAUSE/RESUME/CANCEL;按control_revision保存门控与意图 | | `POST /v1/workflows/{workflow_id}/recovery/*` | 六类有证据恢复,按当前实例/步骤/任务版本核对 | | `GET /v1/workflows/{workflow_id}/operations` | 有界分页读取流程操作审计摘要,正文另用单条查询 | 流程列表、实例筛选、激活/轮次/信号历史和状态事件时间线已交付;字段、权限和有界分页以[实例查询](api/workflow-queries.md)、[流程历史](api/workflow-history.md)和[事件时间线](api/workflow-events.md)为准。恢复必须带预期状态版本、稳定操作身份、原因与证据,不提供任意修改状态的通用入口。 暂停和继续使用独立管理权限、预期控制版本、幂等操作身份与原因;同一操作重报返回原确认,过期控制版本不能覆盖后来的操作。建议 `200` 确认门控已提交,后续执行进度通过查询观察;门控失效条件和终态操作错误在协议评审时固定。 ### 2.1 受理、幂等与错误 - 首次创建任务、流程或信号记录的建议响应为 `201 Created`,表示资源及幂等记录已可靠提交,不表示业务执行或信号消费完成。 - 相同幂等请求返回 `200` 和原资源 ID,标记 `deduplicated: true`;相同键不同语义请求返回 `409`。 - 单项提交使用 `Idempotency-Key`;已实现的批量每项使用 `idempotency_key`,与单项共用受理身份;不接受整批幂等头,见[批量接口](api/batch-tasks.md)。 - 普通任务提交幂等作用域为命名空间内的任务提交操作;流程启动使用独立操作作用域,信号按命名空间、实例与信号 ID 去重。其他管理写操作按命名空间、操作和资源界定作用域,避免同一个键在不同 API 间意外冲突。 - HTTP `request_id` 仅用于追踪,与业务幂等键分开。 - 请求超时后,使用原幂等键查询或重试;不能通过换一个键来猜测原请求是否失败。 - 语义哈希排除请求追踪、连接身份等传输字段,明确 JSON 规范化、缺省值和数组顺序;不能依赖普通 map 的序列化顺序。算法在协议冻结时确定。 建议统一响应结构:成功包含 `request_id` 和 `data`;失败包含 `request_id` 和 `error`,其中 `error` 含稳定的 `code`、可读 `message` 和受控的 `details`。 | HTTP 状态 | 用途 | | --- | --- | | 200 / 201 | 查询或已确认的操作结果 / 新资源可靠创建 | | 202 | 取消等操作已记录意图,最终行为仍在推进 | | 400 / 422 | 协议格式错误 / 语义校验失败 | | 401 / 403 | 未认证 / 无操作权限 | | 404 | 不存在或按访问策略隐藏的资源 | | 409 | 幂等内容冲突、资源版本冲突或操作状态冲突 | | 429 / 503 | 容量限制 / 服务暂不可用,可提供 `Retry-After` | 批量请求顶层校验通过后可返回 `200`,但每项必须给出索引、任务 ID 或错误。顶层成功不表示每项均被受理。限流或断线后的补交仍使用原逐项幂等键。 ## 3. Worker 连接 建议入口:`GET /v1/worker/connect`,使用 WebSocket Upgrade,协商子协议 `pulse.worker.v1`。SDK 在握手中携带应用凭据,不把长期密钥放在 URL 查询参数中。 连接生命周期:鉴权 → 协议协商 → 能力登记 → 恢复核对 → 可接单 → 排空 / 断线。 - `worker_instance_id` 标识一个进程实例,重连保留,重启建议新建;可另设可读名称。 - `session_id` 标识本次连接。新连接需有新的会话身份,旧连接消息不得继续修改新会话的执行权。 - 恢复执行必须校验认证身份、执行凭据和数据库中的当前归属,不能仅凭相同 Worker 名称认领。 - Worker 声明队列、处理器兼容版本及容量。平台授权与配额优先于客户端声明。 ## 4. 消息信封 以下为示意,时间与数值不是生产默认参数: ```json { "protocol_version": "1", "type": "task.assign", "message_id": "msg_example", "session_id": "session_example", "task_id": "task_example", "attempt_id": "attempt_example", "body": { "handler": "report.generate", "handler_version": "1", "payload_version": "1", "payload": {"report_ref": "report_example"}, "lease_token": "example-only-not-a-real-secret", "lease_expires_at": "2026-09-17T08:00:30Z" } } ``` 响应通过 `reply_to` 关联原消息。需要可靠确认的操作使用稳定消息 ID;跨重连重报时保留操作身份,但使用当前会话认证。传输会话变化不改变操作的语义哈希。 执行凭据属于敏感信息,不进入普通日志、管理查询或指标标签。Task / Attempt / Message / Session 四种 ID 分别表达业务工作、执行尝试、通信操作和连接。 ## 5. 消息类型与确认 | 消息 | 方向 | 语义 | | --- | --- | --- | | `worker.hello` / `worker.welcome` | 双向 | 协商能力、版本、会话与协议限制 | | `worker.resume` / `worker.resume.result` | 双向 | 核对断线前的执行尝试,逐项给出续接、停止或核查结果 | | `worker.capacity` | Worker → 平台 | 更新容量声明;带会话内序号,重复上报不得重复增加额度 | | `task.assign` | 平台 → Worker | 派发已持久化授权的任务与执行凭据 | | `task.start` | Worker → 平台 | 确认接单并申请开始;建议获平台确认后再调用处理器 | | `task.renew` | Worker → 平台 | 续期有效执行租约,可批量但逐项确认 | | `task.complete` | Worker → 平台 | 提交结果或结果引用,等待持久化确认 | | `task.fail` | Worker → 平台 | 提交错误分类及已知业务结果,平台按冻结策略决定后续行为 | | `task.cancel` | 平台 → Worker | 传递已保存的取消意图,不代表副作用被撤销 | | `task.finish` 的 `outcome=CANCELLED` | Worker → 平台 | 已实现的取消确认;需已保存取消意图且本次停止可确认,详见 [取消契约](api/cancellation.md);不使用单独的 task.cancelled 消息 | | `worker.drain` | 双向 | 停止接收新任务,受控完成已有任务 | | `ack` / `error` | 双向 | 关联明确操作的确认或错误,不能用连接 Pong 替代 | 建议采用两步派发:平台先保存 `LEASED` 并发送任务;Worker 发 `task.start`,平台原子确认有效租约和未被取消后保存 `RUNNING`,再确认执行。消息丢失时按同一尝试重报或核对,不能未经重新授权自行执行。 如关联执行门控已暂停,尚未获开始授权的 `task.start` 不能被确认可执行;已确认开始的操作重报只补取原确认,不授予第二次执行。具体暂挂、释放预占容量和恢复派发的消息细节在协议冻结时补齐。 `RUNNING` 表示平台已授权开始,不足以证明业务侧已经发生某项效果。租约前后派发与取消的竞争见 [可靠性模型](04-reliability-and-data.md)。 ### 5.1 完成确认丢失 1. 平台在同一事务内保存任务终态、尝试结果与待交付事件。 2. 提交成功后回复 `ack`。 3. SDK 未收到确认时,重报相同结果或查询任务。 4. 已确认的同一尝试、同一结果再次上报,返回原确认,即使此时原租约已经到期。 5. 不同结果冲突或过期尝试试图写入新结果时拒绝修改,保留可诊断记录。 先验证权限,再识别已完成操作的幂等重报,最后对新操作校验租约,避免将合法的确认补取误判为任务失败。 SDK 可以在进程存活期间缓存未确认消息;不得宣称内存缓存能跨进程崩溃恢复。业务效果已发生但结果尚未回报的情况,依赖业务幂等、业务侧操作记录或结果查询恢复。 ## 6. 心跳、重连与背压 - Ping/Pong 用于连接活性;具体任务的续租必须单独经过授权与持久化确认。[WebSocket 标准](https://www.rfc-editor.org/rfc/rfc6455.html#section-5.5.2) - 任务续租失败后,SDK 不能仅因连接仍在线就继续假定执行权有效。 - SDK 根据服务端确认的租约期限,结合请求耗时、安全余量及本地单调时钟管理停止边界;不直接信任客户端墙上时钟与服务器完全一致。 - 重连使用有上限的指数退避与抖动;支持凭据刷新、重新鉴权和恢复核对。 - 断线后允许在最后确认的有效租约内按策略推进;无法及时恢复有效执行权时,停止推进并尽力取消可取消操作。外部已发请求仍需核查。 - 重连可进入任一平台节点;有效旧尝试经原子校验迁移到新会话,失效尝试不得因重连复活。 - 平台为已派发未确认的任务预占容量。容量消息采用序号和明确的覆盖/计算规则,重复消息不能释放或重复发放额度。 - 单连接读写由独立循环管理;设置消息上限、读写期限和有界发送队列,处理器运行不占网络循环。 - 慢消费者停止追加派发;非关键进度更新可合并,关键状态与结果必须保留恢复路径。 - 负载均衡器支持 Upgrade、长连接超时和排空;网络断开不能触发无条件的业务重试。 ## 7. 可靠结果订阅 当前已实现独立 WSS 入口 `/v1/events/connect` 与子协议 `orbit.events.v1`,区分 Worker 消费权和结果订阅权。当前请求、响应、限制与机器可读 Schema 以 [订阅接口](api/subscriptions.md) 为准;下述涉及流程事件的描述仍为规划。 事件包含 `event_id`、资源类型、资源 ID、状态版本、事件类型及结果引用,可表达任务与流程事件。平台先持久化事件与交付状态,再发送 `event.deliver`;接收方完成自身的可靠处理后发送 `event.ack`。 未确认事件可重新发送,订阅方按事件 ID 去重;同一资源按状态版本处理迟到信息,不承诺跨资源全局顺序。事件保留到期、订阅失效与补偿查询行为必须公开。 实时控制台展示可使用合并后的进度通知,但业务流程推进不能依赖只有在线时才能收到的消息。 Weave 消费 Pulse 的内部持久化事件,不经此对外订阅入口;其事务与去重要求见 [流程协作](06-workflow-spec.md#5-pulse-与-weave-的事务协作)。 ## 8. 版本与协议验证 HTTP `/v1` 与 WS 子协议分别标识兼容边界,业务处理器版本独立。新增可选字段应兼容旧客户端;未知关键消息、状态或枚举不能被当作成功。 协议测试应覆盖断线、重复、迟到、会话切换、局部批量失败与凭据撤销。OpenAPI 与 WS Schema 要进入版本控制和兼容性检查,禁止服务端与 SDK 各自维护不同的状态解释。