# 流程定义与不可变版本 状态:P4 定义校验、持久化发布及独立 Go SDK 已实现;实例启动、推进、等待和恢复尚未实现。规则格式见[结构版本1](workflow-definition-format.md),可运行源码及命令见[研发发布场景](../examples/workflow-definition.md)。 ## 1. 权限、传输与范围 使用 HTTPS、`Authorization: Bearer `、统一 `request_id` 信封。POST 必须有唯一 `Idempotency-Key` 头及 `Content-Type: application/json`。请求体最多512 KiB,完整定义编码最多256 KiB,JSON总深度最多32;拒绝未知字段、大小写别名、重复字段、非法Unicode、无效数字和不符合类型的null。 | 接口 | 权限 | 范围 | | --- | --- | --- | | `POST /v1/workflow-definitions` | `workflows:definitions:publish` | 当前凭据命名空间 | | `GET /v1/workflow-definitions/{definition_id}` | `workflows:definitions:read` | 当前命名空间元数据,不返回规则 | | `POST /v1/workflow-definitions/{definition_id}/versions` | `workflows:definitions:publish` | 定义及其引用的全部队列 | | `GET /v1/workflow-definitions/{definition_id}/versions/{version}` | `workflows:definitions:read` | 定义及其引用的全部队列 | 发布与完整版本读取均在事务中核对队列存在、命名空间归属及当前凭据队列范围。发布不要求`tasks:submit`,不创建任务;发布者可以与运行方分权。默认Bootstrap凭据没有流程权限,显式`--workflow-access`才增加上述两个动作。读取元数据只受命名空间级定义权限限制。 GET不接受查询参数。当前没有定义列表、修改、删除或latest接口;调用方保存创建回执中的定义ID,并显式使用版本名。 ## 2. 创建定义 `POST /v1/workflow-definitions` | 字段 | 类型 | 规则 | | --- | --- | --- | | name | string | 必填,1–128 ASCII字符;首位字母或数字,其余可含`.`、`_`、`-`;同命名空间唯一且区分大小写 | | description | string | 可省略为空,最多1024个Unicode字符,不允许NUL | ```json {"name":"object.pipeline","description":"通用对象作业"} ``` 首次创建201,原键重报200。回执示意(实际ID、时间由服务端生成): ```json { "request_id":"0123456789abcdef0123456789abcdef", "data":{ "definition":{ "id":"1123456789abcdef0123456789abcdef", "namespace_id":"2123456789abcdef0123456789abcdef", "name":"object.pipeline", "description":"通用对象作业", "revision":"1", "created_at":"2026-09-18T00:00:00Z", "updated_at":"2026-09-18T00:00:00Z" }, "deduplicated":false } } ``` `GET /v1/workflow-definitions/{definition_id}`的`data`直接返回上述`definition`对象。`revision`为字符串编码的uint64,初始1,每个新版本发布增加1。名称和说明在本阶段没有修改入口。原创建回执保留创建时的revision,当前值通过GET查询。 每个命名空间最多100个定义。不同键重用同一名称返回409;恢复创建结果必须使用原键,不能用名称猜测操作是否成功。 ## 3. 发布版本 `POST /v1/workflow-definitions/{definition_id}/versions` | 字段 | 类型 | 规则 | | --- | --- | --- | | version | string | 必填,1–64 ASCII字符,名称规则同上;研发指定的业务版本名,不与schema_version混用 | | specification | object | 必填,完整结构版本1定义;所有生效任务策略显式冻结 | | reason | string | 必填非空白,最多1024个Unicode字符,不允许NUL,写入发布审计 | 最小定义直接返回输入,可用于验证发布链路: ```json { "version":"v1", "reason":"initial developer release", "specification":{ "schema_version":1, "input_type":{"kind":"STRING"}, "timeout_ms":60000, "failure_policy":"REVIEW", "body":{ "output_type":{"kind":"STRING"}, "output":{"kind":"REFERENCE","reference":{"source":"input"}} } } } ``` 首次发布201;原键重报或不同键的同版本同内容发布200。信封`data`为: ```json { "version":{ "id":"3123456789abcdef0123456789abcdef", "namespace_id":"2123456789abcdef0123456789abcdef", "definition_id":"1123456789abcdef0123456789abcdef", "version":"v1", "specification":{ "schema_version":1, "input_type":{"kind":"STRING"}, "timeout_ms":60000, "failure_policy":"REVIEW", "body":{ "output_type":{"kind":"STRING"}, "output":{"kind":"REFERENCE","reference":{"source":"input"}} } }, "content_digest":"0000000000000000000000000000000000000000000000000000000000000000", "published_by":"4123456789abcdef0123456789abcdef", "published_at":"2026-09-18T00:00:00Z", "analysis":{"steps":0,"max_concurrency":0,"max_task_attempts":0,"queues":[]} }, "deduplicated":false } ``` 示意中的全零摘要不是上述请求的实际摘要。实际`content_digest`为64位小写十六进制SHA-256:对已校验结构的规范JSON加域前缀`orbit.weave.spec.v1\0`后计算。对象键顺序、数字的等值十进制表示不影响内容比较;数组顺序属于内容,包括枚举/状态分组数组。数字全程保留精度,不使用float64生成内容摘要。 `published_by`是最初发布凭据ID,`published_at`是原始数据库UTC时间;重复发布不改写。`analysis`按全部静态路径保守计算节点、并发与任务尝试上界,队列排序去重且始终为数组。它不是运行用量或已授予配额。 每个定义最多100个版本。达到上限仍可原键核对和同版本同内容确认。发布v2不改写v1。数据库不可变触发器拒绝UPDATE,关联关系由事务校验,无外键、无级联删除。 ## 4. 幂等、并发及未知结果 - 创建操作按命名空间和`workflow.definition.create`隔离;发布按命名空间、`workflow.version.publish`及定义ID隔离。幂等键格式和90天保留窗口沿用[公共规则](tasks.md)。 - 原键绑定整个命令,包括`reason`。原键不同内容为`IDEMPOTENCY_CONFLICT`;换键不允许覆盖已存在版本,不同规则为`STATE_CONFLICT`。 - 不同键、相同版本及相同规则返回第一次的版本。后续请求的原因不替换原审计,不增加父定义revision,不重复产生发布审计。 - 并发控制顺序为认证共享锁→应用额度行→操作身份→定义行→排序后的引用队列。定义、版本、父定义revision、审计和幂等回执同事务提交,审计失败全部回滚。 - 任何超时、连接中断或503都可能发生在提交前后。保留原ID、版本、内容、原因和键核对,禁止生成新身份或盲目修改规则重发。 - 每次重报仍核对当前权限和引用队列;权限被收回、队列缺失时不得用旧回执绕过。版本读取还验证存储原文、结构版本和内容摘要,损坏或不兼容数据返回503,不能默默忽略后继续使用。 ## 5. 读取与错误 `GET /v1/workflow-definitions/{definition_id}/versions/{version}`的`data`直接返回上述`version`对象,200。输入版本名被严格限制,不能携带路径片段。 | 状态 / code | 处理 | | --- | --- | | 400 / INVALID_ARGUMENT | 修正结构、引用、类型、预算或字段;此校验拒绝不发布版本 | | 401 / UNAUTHENTICATED | 核对凭据与有效期 | | 403 / PERMISSION_DENIED | 缺少定义动作权限 | | 404 / NOT_FOUND | 定义/版本/队列不存在、不同命名空间或队列范围不允许;不据此猜测他人资源 | | 409 / IDEMPOTENCY_CONFLICT | 原键绑定不同命令;回查原操作,不直接换键 | | 409 / STATE_CONFLICT | 名称冲突或同版本不同规则;有意更新需显式发布新版本 | | 409 / WORKFLOW_DEFINITION_LIMIT | 命名空间达到100个定义,原创建回执仍可恢复 | | 409 / WORKFLOW_VERSION_LIMIT | 定义达到100个版本,旧版本确认与读取不受此上限影响 | | 413 / BODY_TOO_LARGE | 整个HTTP请求超过512 KiB | | 415 / UNSUPPORTED_MEDIA_TYPE | 必须使用application/json | | 503 / UNAVAILABLE | 服务/事务/存储完整性异常,原身份核对;持续异常需要运维核查 | ## 6. SDK 独立module为`git.yuntuo.hk/k2safe/orbit/sdk/go`,无服务端模型、数据库或ORM依赖。 | 方法 | 输入 → 返回 | | --- | --- | | `CreateWorkflowDefinition(ctx,key,in)` | CreateWorkflowDefinitionRequest → WorkflowDefinitionResult | | `GetWorkflowDefinition(ctx,id)` | 定义ID → WorkflowDefinition | | `PublishWorkflowVersion(ctx,id,key,in)` | PublishWorkflowVersionRequest → WorkflowVersionResult | | `GetWorkflowVersion(ctx,id,version)` | 定义ID及固定版本 → WorkflowVersion | | `WorkflowRef(source,path...)` | 构造有类型校验的引用表达式;发布时校验作用域 | 规则通过`WorkflowSpecification`、`WorkflowStep`等强类型结构构建,常量使用`json.RawMessage`,避免把大整数先转float64。SDK不复制服务端完整校验器;发布返回权威校验结果。网络错误不会自动重试发布,也不自动变更版本。完整示例见[发布场景](../examples/workflow-definition.md)。