# CModel 数据契约

统一平台接口、模块、事件、任务和持久化层的数据类型与响应结构。

CModel 是百积木内部能力之间的统一数据契约。新接口、模块方法、Connector 业务载荷、工作流输入输出、异步任务和持久化模型都必须先定义 CModel 类型，再由各语言实现映射；不能以某个框架、数据库或前端组件的默认序列化结果作为公共契约。

CModel 错误响应使用显式 `contractVersion`，当前稳定契约为 `1.0.0`。完整结构、HTTP 语义和机器可读 Schema 见 [CModel 错误模型](/integration/cmodel-error-model/)。

## 统一响应

非流式调用统一返回以下 envelope。三个基础字段均为必填：

```json
{
  "contractVersion": "1.0.0",
  "errorCode": "0",
  "data": {}
}
```

- `contractVersion`：严格 SemVer；当前为 `1.0.0`。
- `errorCode`：成功固定为字符串 `"0"`，失败为稳定错误码。
- `data`：成功数据；失败时为 `null` 或标准 `{ message, retryable }` 公开错误详情。
- 成功和业务失败响应都使用 HTTP `200`；业务成败只由 `errorCode` 判断，失败详情只用于展示和重试策略。具体规则见 [CModel 错误模型](/integration/cmodel-error-model/)。

禁止返回只包含 `success`、`message` 或 `error` 字符串的私有 envelope。网关、模块和调用方不得用 HTTP 状态或自然语言错误文本判断业务错误类型。

## 类型定义

模块和工作流必须使用结构化 `DataType`，包括数组元素和对象属性。下面的 `groups` 不是泛化的 `array<object>`，而是可被平台校验、生成表单和传递给调用方的完整契约：

```json
{
  "name": "groups",
  "type": {
    "@type": "DataType",
    "type": "array",
    "nullable": false,
    "items": {
      "@type": "DataType",
      "type": "object",
      "nullable": false,
      "additionalProperties": false,
      "required": ["conversationId", "conversationName"],
      "properties": {
        "conversationId": { "@type": "DataType", "type": "string", "nullable": false },
        "conversationName": { "@type": "DataType", "type": "string", "nullable": false },
        "memberCount": { "@type": "DataType", "type": "integer", "nullable": true },
        "lastTimestamp": { "@type": "DataType", "type": "integer", "nullable": true }
      }
    }
  }
}
```

公共契约必须遵守：

- 对象明确 `properties`、`required` 和 `additionalProperties`。
- 数组明确 `items`，不能只声明为泛化对象。
- 可空和缺省是两种语义；`nullable` 不等于可以省略必填参数。
- ID、金额、时间、持续时间和枚举不得为了组件显示方便改成字符串。
- 发生不兼容的字段改名或类型变化时，发布主版本，并同步升级所有生产者、消费者和 Bundle 锁定版本。

## 边界规则

外部系统可以使用 RFC 3339、秒级时间戳或供应商私有 envelope，但适配器必须在进入百积木业务边界时一次性转换为 CModel；内部链路不得继续传播外部格式。对外调用时同样只在最外层适配器转换。

如果某个传输协议强制规定了自己的元数据格式，该格式只存在于协议 envelope 中，不能复制到业务 `payload`、模块参数或数据库列。业务数据仍按 CModel 传递。

## 变更检查

发布前至少验证：

1. 生产者输出、方法定义、消费者入参和数据库列使用同一类型与单位。
2. 成功和失败响应都符合 CModel envelope；反序列化失败也不能返回纯文本或 HTML。
3. 错误类型、错误码和时间单位通过自动化测试覆盖。
4. Bundle Manifest、模块版本、平台应用版本和 Connector 版本锁定到同一代契约。
5. 线上回归同时验证正确输入和错误单位、错误类型的拒绝行为。
