# SyncBridge 合作伙伴集成 API 规范

**版本**：2.4.0  
**最后更新**：2026-04-10  
**作者**：台湾集成团队 — Wei-Lin Chen、Mei-Hua Tsai  
**状态**：最终审查

---

## 1. 概述

SyncBridge 是一个企业级数据同步平台（enterprise-grade data synchronization platform），可在合作伙伴系统之间实现实时双向数据流转。本文档规定了集成合作伙伴必须实现的 REST API，以便将其服务接入 SyncBridge 生态系统。

本 API 遵循 RESTful 规范，所有请求与响应的载荷（Payload）均采用 JSON 格式。身份验证（Authentication）通过 OAuth 2.0 客户端凭证流程结合 JWT 持有者令牌（Bearer Token）来完成。所有端点均强制执行速率限制（Rate Limiting），且传输层安全性要求使用 TLS 1.2 或更高版本。

### 1.1 目标读者

本规范面向正在构建其平台与 SyncBridge 连接器的后端工程师及集成架构师。读者应具备 REST API、OAuth 2.0 以及基于 Webhook 的事件系统的相关知识。

### 1.2 基础 URL

所有 API 端点均相对于合作伙伴已注册的基础 URL：

```
https://{partner-domain}/api/v2/syncbridge
```

基础 URL 在合作伙伴接入（Onboarding）期间完成配置，并存储于 SyncBridge API 网关（API Gateway）的配置中。合作伙伴可以为预发布环境和生产环境分别注册不同的基础 URL。

### 1.3 版本控制

本 API 采用基于 URL 的版本控制方式（`/v2/`）。重大变更（Breaking Changes）将递增主版本号；非重大的新增内容（如新增可选字段、新增端点）则在当前版本内直接添加。合作伙伴应在处理响应载荷时对未知字段实现容错处理。

---

## 2. 身份验证与授权

### 2.1 OAuth 2.0 流程

SyncBridge 采用 OAuth 2.0 客户端凭证（Client Credentials）流程进行服务端到服务端的身份验证。合作伙伴在接入时会获得 `client_id` 和 `client_secret`。

**令牌端点**：
```
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={client_id}
&client_secret={client_secret}
&scope=syncbridge.read syncbridge.write syncbridge.admin
```

**响应**：
```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "syncbridge.read syncbridge.write syncbridge.admin"
}
```

访问令牌（Access Token）是一个已签名的 JWT，其中包含合作伙伴的身份标识、已授权的权限范围（Scope）以及过期时间戳。后续所有 API 请求均必须在 `Authorization` 请求头中携带该令牌。

### 2.2 令牌验证

合作伙伴必须使用以下地址发布的公钥，对来自 SyncBridge 的入站令牌进行验证：

```
GET /oauth/.well-known/jwks.json
```

验证步骤：
1. 使用已发布的公钥验证 JWT 签名（Signature）
2. 检查 `exp` 声明（Claim）是否已过期
3. 验证 `iss` 声明是否匹配 `https://auth.syncbridge.io`
4. 验证 `aud` 声明是否包含合作伙伴已注册的 Client ID
5. 检查 `scope` 声明中是否存在所需的权限范围

### 2.3 凭证轮换

合作伙伴应至少每 90 天轮换一次 Client Secret。凭证轮换（Credential Rotation）端点支持零停机轮换：在可配置的宽限期（Grace Period，默认 24 小时）内，允许同时存在两个有效的 Secret。

```
POST /admin/credentials/rotate
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "grace_period_hours": 24
}
```

**响应**：
```json
{
  "new_client_secret": "sb_secret_v2_...",
  "old_secret_valid_until": "2026-04-11T14:30:00Z",
  "rotation_id": "rot_8f3a2b1c"
}
```

---

## 3. 核心数据端点

### 3.1 实体同步

实体同步（Entity Sync）端点是 SyncBridge 与合作伙伴系统之间交换数据的主要机制，支持推送（Push，SyncBridge → Partner）和拉取（Pull，Partner → SyncBridge）两种操作模式。

#### 3.1.1 接收实体（推送模式）

当源系统发生变更时，SyncBridge 会将实体（Entity）更新推送至合作伙伴的端点。

```
POST /entities/sync
Authorization: Bearer {access_token}
Content-Type: application/json
X-SyncBridge-Idempotency-Key: {uuid}
X-SyncBridge-Batch-Id: {batch_uuid}

{
  "batch_id": "batch_a1b2c3d4",
  "source_system": "crm",
  "entities": [
    {
      "entity_id": "ent_001",
      "entity_type": "contact",
      "operation": "upsert",
      "timestamp": "2026-04-10T08:15:30Z",
      "data": {
        "name": "Alice Wang",
        "email": "alice@example.com",
        "phone": "+886-2-1234-5678",
        "tags": ["enterprise", "priority"],
        "metadata": {
          "source_region": "APAC",
          "last_activity": "2026-04-09T16:42:00Z"
        }
      },
      "schema_version": "2.1"
    }
  ],
  "pagination": {
    "page": 1,
    "total_pages": 3,
    "total_entities": 250
  }
}
```

**必须在 30 秒内返回的响应**：

```json
{
  "batch_id": "batch_a1b2c3d4",
  "status": "accepted",
  "results": [
    {
      "entity_id": "ent_001",
      "status": "success",
      "partner_id": "p_contact_12345"
    }
  ],
  "processing_time_ms": 142
}
```

**错误响应**：

```json
{
  "batch_id": "batch_a1b2c3d4",
  "status": "partial_failure",
  "results": [
    {
      "entity_id": "ent_001",
      "status": "error",
      "error": {
        "code": "VALIDATION_FAILED",
        "message": "Field 'email' failed format validation",
        "field": "data.email",
        "retry_eligible": true
      }
    }
  ]
}
```

#### 3.1.2 提供实体（拉取模式）

SyncBridge 会定期从合作伙伴系统拉取实体数据。合作伙伴必须实现此端点，返回自指定游标（Cursor）时间戳以来发生变更的实体。

```
GET /entities?since={iso_timestamp}&limit={n}&cursor={opaque_cursor}
Authorization: Bearer {access_token}
Accept: application/json
```

**查询参数**：

| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|------|------|----------|--------|------|
| `since` | ISO 8601 | 是（首次请求） | — | 返回该时间戳之后发生变更的实体 |
| `limit` | integer | 否 | 100 | 每页返回的最大实体数量（上限 500） |
| `cursor` | string | 否 | — | 上次响应中返回的不透明分页游标 |
| `entity_type` | string | 否 | all | 按实体类型筛选 |
| `include_deleted` | boolean | 否 | false | 是否包含软删除的实体 |

**响应**：

```json
{
  "entities": [
    {
      "entity_id": "p_contact_12345",
      "entity_type": "contact",
      "operation": "upsert",
      "timestamp": "2026-04-10T09:00:00Z",
      "data": {
        "name": "Bob Lin",
        "email": "bob@partner.tw",
        "department": "Engineering"
      },
      "schema_version": "2.1"
    }
  ],
  "pagination": {
    "cursor": "eyJsYXN0X2lkIjoiMTIzNDUifQ==",
    "has_more": true,
    "total_estimate": 1500
  }
}
```

### 3.2 Schema 注册中心

合作伙伴必须将其实体 Schema 注册到 SyncBridge，以便在同步时对字段映射（Field Mapping）进行验证。Schema 注册中心（Schema Registry）提供了一组用于管理这些 Schema 的端点。

#### 3.2.1 注册 Schema

```
PUT /schemas/{entity_type}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "entity_type": "contact",
  "version": "2.1",
  "fields": [
    {
      "name": "name",
      "type": "string",
      "required": true,
      "max_length": 255,
      "description": "Full name of the contact"
    },
    {
      "name": "email",
      "type": "string",
      "required": true,
      "format": "email",
      "description": "Primary email address"
    },
    {
      "name": "phone",
      "type": "string",
      "required": false,
      "format": "e164",
      "description": "Phone number in E.164 format"
    },
    {
      "name": "tags",
      "type": "array",
      "items_type": "string",
      "required": false,
      "description": "Classification tags"
    },
    {
      "name": "metadata",
      "type": "object",
      "required": false,
      "description": "Extensible metadata key-value pairs"
    }
  ],
  "indexes": ["email", "phone"],
  "primary_key": "entity_id"
}
```

#### 3.2.2 验证 Schema 兼容性

在部署新 Schema 版本之前，合作伙伴可以验证其与 SyncBridge 中已注册的前一版本是否向后兼容。

```
POST /schemas/{entity_type}/validate
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "proposed_version": "2.2",
  "fields": [ ... ]
}
```

**响应**：

```json
{
  "compatible": true,
  "warnings": [
    {
      "type": "NEW_OPTIONAL_FIELD",
      "field": "linkedin_url",
      "message": "New optional field added — existing integrations will not be affected"
    }
  ],
  "breaking_changes": []
}
```

---

## 4. 事件系统

### 4.1 Webhook 配置

SyncBridge 通过 Webhook 向合作伙伴实时推送事件。合作伙伴必须注册 Webhook 端点，并配置所需接收的事件类型。

#### 4.1.1 注册 Webhook

```
POST /webhooks
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "url": "https://partner.example.com/hooks/syncbridge",
  "events": [
    "entity.created",
    "entity.updated",
    "entity.deleted",
    "sync.completed",
    "sync.failed",
    "schema.updated"
  ],
  "secret": "whsec_a1b2c3d4e5f6",
  "metadata": {
    "environment": "production",
    "team": "integrations"
  }
}
```

**响应**：

```json
{
  "webhook_id": "wh_9f8e7d6c",
  "status": "active",
  "created_at": "2026-04-10T10:00:00Z",
  "test_url": "https://api.syncbridge.io/webhooks/wh_9f8e7d6c/test"
}
```

#### 4.1.2 Webhook 载荷格式

所有 Webhook 投递均采用统一的信封格式：

```json
{
  "event_id": "evt_abc123",
  "event_type": "entity.updated",
  "timestamp": "2026-04-10T10:15:00Z",
  "webhook_id": "wh_9f8e7d6c",
  "data": {
    "entity_id": "ent_001",
    "entity_type": "contact",
    "changes": {
      "email": {
        "old": "alice@old.com",
        "new": "alice@example.com"
      }
    }
  },
  "metadata": {
    "delivery_attempt": 1,
    "correlation_id": "corr_xyz789"
  }
}
```

#### 4.1.3 Webhook 签名验证

每次 Webhook 投递都会在请求头中附带 `X-SyncBridge-Signature`，其值为使用 Webhook 密钥计算的 HMAC-SHA256 签名。合作伙伴在处理任何 Webhook 载荷之前，必须验证该签名。

```python
import hmac
import hashlib

def verify_signature(payload_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode('utf-8'),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)
```

### 4.2 事件投递与重试

SyncBridge 对投递失败的 Webhook 采用指数退避策略：

| 尝试次数 | 延迟时间 | 累计时间 |
|---------|---------|---------|
| 1 | 立即 | 0 |
| 2 | 30 秒 | 30s |
| 3 | 2 分钟 | 2m 30s |
| 4 | 15 分钟 | 17m 30s |
| 5 | 1 小时 | 1h 17m 30s |
| 6 | 4 小时 | 5h 17m 30s |
| 7（最终） | 12 小时 | 17h 17m 30s |

7 次尝试全部失败后，事件将被转移至死信队列（Dead-Letter Queue）。合作伙伴可通过仪表盘或 API 重放死信队列中的事件。

**投递成功**：合作伙伴端点在 30 秒内返回 HTTP 2xx。
**投递失败**：返回非 2xx 响应、请求超时或连接错误。

### 4.3 事件订阅管理

合作伙伴可以动态管理事件订阅，无需重新注册 Webhook。

```
PATCH /webhooks/{webhook_id}/subscriptions
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "add": ["batch.started", "batch.progress"],
  "remove": ["sync.failed"]
}
```

---

## 5. 速率限制

### 5.1 限制规格

SyncBridge 对合作伙伴 API 调用执行以下速率限制：

| 套餐等级 | 请求数/分钟 | 突发量 | 最大并发连接数 |
|---------|-----------|-------|-------------|
| Standard | 600 | 100 | 50 |
| Premium | 3000 | 500 | 200 |
| Enterprise | 12000 | 2000 | 1000 |

每次 API 响应均通过请求头返回当前速率限制信息：

```
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 542
X-RateLimit-Reset: 1712736000
X-RateLimit-Retry-After: 0
```

### 5.2 速率限制的处理

触发速率限制时，API 返回 HTTP 429，并附带 `Retry-After` 请求头，指明合作伙伴可以重试的时间。合作伙伴必须实现退避逻辑，不应立即重试。

**速率限制响应**：

```json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Please retry after the specified time.",
    "retry_after_seconds": 12,
    "limit": 600,
    "window": "1m"
  }
}
```

### 5.3 速率限制最佳实践

1. **实现客户端速率追踪**：持续监控 `X-RateLimit-Remaining` 请求头，在触及限制前主动降低请求频率。
2. **使用批量端点**：优先使用批次操作，而非单条实体请求，以减少 API 调用次数。
3. **缓存令牌响应**：访问令牌有效期为 1 小时——不应为每次 API 调用都申请新令牌。
4. **使用 Webhook 事件**：以 Webhook 事件接收实时变更通知，替代轮询方式。

---

## 6. 错误处理

### 6.1 错误响应格式

所有 API 错误均遵循统一的 JSON 结构：

```json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description",
    "details": {
      "field": "data.email",
      "constraint": "format",
      "expected": "valid email address"
    },
    "request_id": "req_abc123",
    "documentation_url": "https://docs.syncbridge.io/errors/ERROR_CODE"
  }
}
```

### 6.2 错误码

| 错误码 | HTTP 状态码 | 说明 | 可重试？ |
|-------|-----------|-----|--------|
| `AUTHENTICATION_FAILED` | 401 | 令牌无效或已过期 | 是（刷新令牌后重试） |
| `AUTHORIZATION_DENIED` | 403 | 权限范围不足 | 否 |
| `NOT_FOUND` | 404 | 资源不存在 | 否 |
| `VALIDATION_FAILED` | 422 | 请求体验证失败 | 否（修正载荷后重试） |
| `RATE_LIMITED` | 429 | 超出速率限制 | 是（延迟后重试） |
| `CONFLICT` | 409 | 并发修改冲突 | 是（获取最新数据后重试） |
| `IDEMPOTENCY_CONFLICT` | 409 | 幂等键被不同载荷重复使用 | 否 |
| `BATCH_TOO_LARGE` | 413 | 批次超出最大限制（1000 个实体） | 否（缩减批次后重试） |
| `SCHEMA_MISMATCH` | 422 | 实体数据与已注册 Schema 不符 | 否（修正数据或 Schema 后重试） |
| `UPSTREAM_ERROR` | 502 | 上游系统不可用 | 是（退避后重试） |
| `SERVICE_UNAVAILABLE` | 503 | SyncBridge 维护中 | 是（延迟后重试） |
| `TIMEOUT` | 504 | 请求处理超时 | 是 |

### 6.3 幂等性

所有变更类端点均通过 `X-SyncBridge-Idempotency-Key` 请求头支持幂等操作。合作伙伴应为每个逻辑操作生成唯一的 UUID 并随请求一并提交。若以相同的幂等键发送完全相同的载荷，SyncBridge 将直接返回原始响应，不再重复处理。若载荷不同，则返回 `409 IDEMPOTENCY_CONFLICT` 错误。

幂等键在 24 小时后过期。过期后，同一个键可以用于新的操作。

---

## 7. 监控与可观测性

### 7.1 健康检查端点

合作伙伴必须实现一个健康检查（Health Check）端点，SyncBridge 每隔 60 秒会对其发起轮询：

```
GET /health
```

**正常响应**（HTTP 200）：

```json
{
  "status": "healthy",
  "version": "2.4.0",
  "uptime_seconds": 864000,
  "dependencies": {
    "database": "healthy",
    "cache": "healthy",
    "message_queue": "healthy"
  }
}
```

**降级响应**（HTTP 200，含降级状态）：

```json
{
  "status": "degraded",
  "version": "2.4.0",
  "issues": [
    {
      "component": "cache",
      "status": "unhealthy",
      "message": "Redis connection pool exhausted",
      "since": "2026-04-10T11:30:00Z"
    }
  ]
}
```

### 7.2 指标端点

合作伙伴应该暴露一个兼容 Prometheus 的指标端点：

```
GET /metrics
```

**必须上报的指标**：

| 指标 | 类型 | 说明 |
|------|------|------|
| `syncbridge_entities_received_total` | Counter | 通过推送接收到的实体总数 |
| `syncbridge_entities_sent_total` | Counter | 通过拉取发送的实体总数 |
| `syncbridge_sync_duration_seconds` | Histogram | 同步操作耗时 |
| `syncbridge_errors_total` | Counter | 按类型统计的错误总数 |
| `syncbridge_webhook_deliveries_total` | Counter | 收到的 Webhook 投递总数 |
| `syncbridge_active_connections` | Gauge | 当前活跃连接数 |

### 7.3 日志记录要求

合作伙伴必须记录所有与 SyncBridge API 的交互日志，并包含以下上下文字段，以便故障排查：

| 字段 | 说明 |
|------|------|
| `request_id` | 请求中 `X-SyncBridge-Request-Id` 请求头的值 |
| `batch_id` | 实体同步操作的批次标识符 |
| `correlation_id` | 跨多个服务的端到端关联 ID |
| `partner_id` | 合作伙伴的客户端 ID |
| `timestamp` | 日志条目的 ISO 8601 时间戳 |
| `duration_ms` | 请求处理耗时（毫秒） |
| `status_code` | HTTP 响应状态码 |

---

## 8. 数据格式规范

### 8.1 时间戳

所有时间戳均采用 UTC 时区的 ISO 8601 格式：

```
2026-04-10T08:15:30Z
2026-04-10T08:15:30.123Z
```

合作伙伴必须同时接受秒精度和毫秒精度的时间戳。响应中应该在条件允许时使用毫秒精度。

### 8.2 实体 ID 格式

实体 ID 必须是全局唯一的字符串，并满足以下约束：

- 最大长度：128 个字符
- 允许的字符：字母、数字、连字符、下划线
- 不得以连字符或下划线开头
- 区分大小写

推荐格式：`{type_prefix}_{uuid_v4}`（例如：`contact_a1b2c3d4-e5f6-7890-abcd-ef1234567890`）

### 8.3 分页

所有列表端点均采用基于游标的分页方式。游标是一个不透明字符串，应该在后续请求中原样传回。合作伙伴不得尝试解码或自行构造游标。

**分页参数**：

| 参数 | 说明 |
|------|------|
| `limit` | 每页返回的条目数（默认：100，最大：500） |
| `cursor` | 上一次响应返回的不透明游标 |

**分页响应字段**：

| 字段 | 说明 |
|------|------|
| `cursor` | 下一页的游标（若为最后一页则为 null） |
| `has_more` | 布尔值，表示是否还有更多分页 |
| `total_estimate` | 总数估算值（可能不精确） |

### 8.4 字段映射配置

合作伙伴可通过仪表盘或 API 配置自身 Schema 与 SyncBridge 标准 Schema 之间的字段映射：

```
PUT /mappings/{entity_type}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "entity_type": "contact",
  "mappings": [
    {
      "source_field": "full_name",
      "target_field": "name",
      "transform": "none"
    },
    {
      "source_field": "email_address",
      "target_field": "email",
      "transform": "lowercase"
    },
    {
      "source_field": "created_date",
      "target_field": "created_at",
      "transform": "iso8601"
    },
    {
      "source_field": "department.name",
      "target_field": "department",
      "transform": "flatten"
    }
  ],
  "unmapped_field_policy": "passthrough"
}
```

**可用转换操作**：

| 转换操作 | 说明 |
|----------|------|
| `none` | 直接传递原始值 |
| `lowercase` | 将字符串转为小写 |
| `uppercase` | 将字符串转为大写 |
| `iso8601` | 解析并规范化为 ISO 8601 UTC 格式 |
| `flatten` | 使用点分表示法从嵌套对象中提取值 |
| `array_join` | 将数组元素拼接为逗号分隔的字符串 |
| `string_split` | 将逗号分隔的字符串拆分为数组 |
| `hash_sha256` | 单向哈希（用于 PII（个人身份信息）脱敏） |
| `mask` | 保留最后 4 位，其余字符全部掩码处理 |
| `custom` | 由合作伙伴提供的自定义 JavaScript 转换函数 |

---

## 9. 测试与沙箱

### 9.1 沙箱环境

SyncBridge 提供功能完整的沙箱环境，供集成测试使用：

- **基础 URL**：`https://sandbox.syncbridge.io/api/v2/`
- **令牌端点**：`https://sandbox.syncbridge.io/oauth/token`
- **速率限制**：与生产环境相同（以便测试速率限制处理逻辑）
- **数据保留**：沙箱数据每 30 天清除一次

### 9.2 测试夹具

SyncBridge 通过沙箱 API 提供预置的测试夹具：

```
GET /sandbox/fixtures
Authorization: Bearer {sandbox_token}
```

可用的测试夹具包括：

- `basic_contacts` — 50 个字段各异的联系人实体
- `large_batch` — 1000 个实体，用于批次处理测试
- `schema_evolution` — 跨多个 Schema 版本的实体
- `error_scenarios` — 专门用于触发特定错误码的实体
- `unicode_stress` — 包含 CJK 字符、Emoji 及从右到左（RTL）文本的实体

### 9.3 集成测试检查清单

合作伙伴必须通过以下集成测试，方可上线：

| # | 测试项 | 说明 | 端点 |
|---|--------|------|------|
| 1 | 认证流程 | 完整的 OAuth 令牌交换 | `/oauth/token` |
| 2 | 推送同步 | 接收并处理包含 100 个实体的批次 | `/entities/sync` |
| 3 | 拉取同步 | 返回自指定时间戳起已修改的实体 | `/entities` |
| 4 | 接收 Webhook | 处理 Webhook 投递并返回 200 | Webhook URL |
| 5 | 验证 Webhook | 正确验证 Webhook 签名 | Webhook URL |
| 6 | 速率限制处理 | 优雅处理 429 响应 | 任意端点 |
| 7 | Schema 注册 | 成功注册实体 Schema | `/schemas/{type}` |
| 8 | 错误处理 | 对无效请求返回规范的错误格式 | 任意端点 |
| 9 | 健康检查 | 返回包含依赖信息的正常状态 | `/health` |
| 10 | 幂等性 | 使用相同幂等键正确处理重复请求 | `/entities/sync` |
| 11 | 分页 | 正确分页遍历大型结果集 | `/entities` |
| 12 | 并发同步 | 处理 10 个并发同步请求 | `/entities/sync` |

---

## 10. 部署与上线

### 10.1 上线前检查清单

在将生产流量接入之前，合作伙伴必须完成以下事项：

- [ ] 在沙箱环境中通过全部集成测试
- [ ] 注册生产环境的 Webhook 端点
- [ ] 为 SyncBridge 相关指标配置监控与告警
- [ ] 完成日志记录配置，包含所有必需的上下文字段
- [ ] 实现凭证轮换自动化
- [ ] 编写 SyncBridge 故障响应的内部运维手册
- [ ] 完成 Webhook 签名验证的安全审查
- [ ] 按预期生产流量进行负载测试（建议使用 2 倍峰值）

### 10.2 上线流程

1. **预发布验证**：在预发布环境中执行完整的集成测试套件
2. **Schema 注册**：在生产环境中注册所有实体 Schema
3. **Webhook 激活**：启用生产环境 Webhook 端点
4. **影子模式（Shadow Mode）**：SyncBridge 将流量复制发送至合作伙伴端点，但不要求对方返回响应（持续 72 小时）
5. **灰度发布**：流量在 7 天内按 10% → 25% → 50% → 100% 逐步提升
6. **观察期**：为期 14 天的观察期，SyncBridge 支持团队全程待命

### 10.3 SLA 要求

| 指标 | 目标 | 衡量方式 |
|------|------|----------|
| 可用性 | 99.9% | 月度正常运行时间百分比 |
| 推送同步延迟 | p95 < 500ms | 从请求发出到收到响应的时间 |
| 拉取同步延迟 | p95 < 1s | 从请求发出到收到响应的时间 |
| Webhook 确认延迟 | p95 < 5s | 从 Webhook 投递到收到 2xx 响应的时间 |
| 错误率 | < 0.1% | 失败请求数 / 总请求数 |
| 数据新鲜度 | < 5 分钟 | 从数据源变更到同步完成的时间 |

---

## 11. 安全要求

### 11.1 传输安全

SyncBridge 与合作伙伴系统之间的所有通信必须使用 TLS 1.2 或更高版本。合作伙伴必须提供由受信任证书颁发机构签署的有效 SSL/TLS 证书。自签名证书在生产环境中不予接受，但可以在沙箱环境中用于测试。

**TLS 配置要求**：
- 最低版本：TLS 1.2
- 推荐版本：TLS 1.3
- 加密套件：必须支持 ECDHE-RSA-AES256-GCM-SHA384 或同等强度的套件
- 证书轮换：合作伙伴应在 TLS 证书到期前至少 30 天完成轮换
- HSTS：合作伙伴应启用 HTTP 严格传输安全（HTTP Strict Transport Security）响应头

### 11.2 数据保护

合作伙伴必须对所有同步数据采取适当的数据保护措施：

1. **静态加密**：所有实体数据必须使用 AES-256 或同等算法进行静态加密。数据库级加密（例如透明数据加密，Transparent Data Encryption）亦为可接受方案。

2. **PII（个人身份信息）处理**：电子邮件、电话号码、姓名等 PII 字段的处理必须符合适用的隐私法规（GDPR、CCPA、台湾个人资料保护法）。合作伙伴必须支持以下 PII 操作：
   - **数据主体访问请求**：在 72 小时内返回指定实体的全部数据
   - **删除权**：在收到请求后 30 天内永久删除实体数据
   - **数据可携权**：以机器可读的 JSON 格式导出实体数据

3. **审计日志**：对同步数据的所有读写操作必须记录足够详细的日志，以满足安全审计需求。日志必须至少保留 12 个月。

4. **访问控制**：合作伙伴必须对内部访问同步数据实施基于角色的访问控制（RBAC）。SyncBridge 服务账户应遵循最小权限原则——仅拥有对同步实体类型的读写权限，不得访问合作伙伴的内部数据。

### 11.3 安全事件响应

合作伙伴在发现任何可能影响同步数据的安全事件后，必须在 24 小时内通知 SyncBridge。通知内容必须包含：

- 事件的性质与范围
- 受影响的实体类型及大致数量
- 事件时间线（发现、遏制、解决）
- 已采取或计划采取的补救措施
- 合作伙伴安全团队的联系方式

SyncBridge 提供专用的安全事件端点，用于程序化通知：

```
POST /security/incidents
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "severity": "high",
  "category": "data_breach",
  "description": "Unauthorized access detected to entity sync database",
  "affected_entity_types": ["contact", "order"],
  "estimated_affected_count": 1500,
  "discovery_time": "2026-04-10T14:00:00Z",
  "containment_time": "2026-04-10T14:30:00Z",
  "contact": {
    "name": "Security Team Lead",
    "email": "security@partner.example.com",
    "phone": "+886-2-9876-5432"
  }
}
```

### 11.4 并发与冲突解决

当多个同步操作同时针对同一实体时，SyncBridge 通过版本戳（Version Stamp）实现乐观并发控制（Optimistic Concurrency Control）。每个实体携带一个 `_version` 字段，每次成功更新后该字段自动递增。合作伙伴在发送更新请求时必须包含当前版本号，并优雅地处理版本冲突错误。

**冲突检测流程**：
1. 合作伙伴收到 `_version: 5` 的实体
2. 合作伙伴在本地修改后，携带 `_version: 5` 发送更新请求
3. 若其他更新已将版本递增至 6，SyncBridge 返回 `409 CONFLICT`
4. 合作伙伴必须重新获取最新实体，合并变更后携带新版本号重试

**合并策略**：合作伙伴可按实体类型配置各自偏好的合并策略：

| 策略 | 行为 |
|------|------|
| `last_write_wins` | 以最新时间戳为准（默认策略） |
| `source_priority` | 始终采用上游系统的版本 |
| `partner_priority` | 始终采用合作伙伴的版本 |
| `manual_review` | 冲突在仪表盘中标记，等待人工处理 |
| `field_level_merge` | 无冲突的字段变更自动合并；冲突字段单独标记 |

对于高吞吐量场景，合作伙伴应在本地实现带去重功能的队列，以减少并发更新冲突。推荐的模式是：在一个短时间窗口内（例如 500 毫秒）将更新积攒于本地，按实体 ID 去重并仅保留最新状态，然后通过单次 API 调用将去重后的批次发送至 SyncBridge。

### 11.5 网络安全

合作伙伴应为其 SyncBridge 集成端点实施以下网络层安全控制：

- **IP 白名单（IP Allowlisting）**：SyncBridge 在 `https://api.syncbridge.io/.well-known/ip-ranges.json` 发布其出口 IP 段。合作伙伴应将集成端点的入站流量限制为这些 IP 段。
- **DDoS 防护**：合作伙伴应为 Webhook 端点部署 DDoS 缓解措施，因为故障恢复期间的 Webhook 重放可能产生流量峰值。
- **WAF 规则**：WAF（Web Application Firewall）规则应允许 SyncBridge 的 JSON 载荷通过，同时拦截常见攻击模式。需确保 WAF 规则不会干扰大型批量载荷（最大 1MB）。
- **mTLS（可选）**：对于企业级合作伙伴，SyncBridge 支持将 mTLS 双向认证作为额外的安全层。如需启用 mTLS，请联系您的集成经理。

---

## 附录 A：变更日志

| 版本 | 日期 | 变更内容 |
|------|------|----------|
| 2.4.0 | 2026-04-10 | 新增字段映射转换功能及上线影子模式 |
| 2.3.0 | 2026-03-15 | 新增 Schema 兼容性验证端点 |
| 2.2.0 | 2026-02-01 | 新增事件订阅管理及死信队列重放功能 |
| 2.1.0 | 2026-01-10 | 新增批次进度事件及指标端点 |
| 2.0.0 | 2025-11-01 | 主版本升级：全新身份验证流程、游标分页、Webhook 签名 |

## 附录 B：术语表

| 术语 | 定义 |
|------|------|
| 实体（Entity） | 在系统间同步的独立数据记录（例如联系人、订单、产品） |
| 批次（Batch） | 在单次 API 调用中作为一组一并处理的实体操作集合 |
| 游标（Cursor） | 一种不透明的分页令牌，用于编码当前在结果集中的位置 |
| 幂等键（Idempotency Key） | 唯一标识符，确保重试请求产生相同的处理结果 |
| 死信队列（Dead-Letter Queue） | 用于暂存所有投递尝试均失败的 Webhook 事件的缓冲区 |
| 影子模式（Shadow Mode） | 预生产阶段，流量被镜像发送至目标端点，但不要求其返回响应 |
| Schema 注册中心（Schema Registry） | 用于集中存储实体类型定义和字段映射配置的中央仓库 |
| 字段映射（Field Mapping） | 将合作伙伴字段名称与格式转换为 SyncBridge 标准 Schema 的配置 |
| Webhook 密钥（Webhook Secret） | 用于计算 Webhook 载荷 HMAC 签名以供验证的共享密钥 |
| 宽限期（Grace Period） | 凭证轮换过程中，旧密钥与新密钥同时有效的时间窗口 |
| 上游（Upstream） | 数据的源系统，数据从此处流经 SyncBridge 向下传递 |
| 下游（Downstream） | 接收 SyncBridge 同步数据的目标系统 |
