docs: rewrite README and AGENTS.md etc..
This commit is contained in:
1 parent
cc64df3e70
commit
a9bf849697
22 files changed
+514
-665
No files matched your search
+40
-26
@@ -2,7 +2,7 @@
|
||||
|
||||
本文列出 Backend 的全部对外接口。通用规则见本文第 7 节「设计约束」;OpenAPI 3.1 文档在运行时由 `/openapi/v1.json` 提供,构建时同时生成快照 `backend/openapi/v1.json`。两者冲突时,以 OpenAPI 为准。
|
||||
|
||||
## 1. 分层
|
||||
## 1. 分层与资源
|
||||
|
||||
### IPv4 / IPv6
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
```text
|
||||
/api/public/* 只读。站点设为公开时匿名可访问,设为私有时需要登录或只读令牌;
|
||||
public_visible = false 的 Agent 对匿名访客隐藏
|
||||
/api/admin/* 管理。需要 Cookie 会话(含 CSRF 校验)或带有对应**能力**的 API 令牌;每个端点声明自己需要的一项能力(OpenAPI 里的 `x-moshiro-capability`),完整目录见 `GET /api/admin/capabilities`,设计见 [access.md](../security/access.md)
|
||||
/api/admin/* 管理。需要 Cookie 会话(含 CSRF 校验)或带有对应能力的 API 令牌;每个端点声明自己需要的一项能力(OpenAPI 里的 `x-moshiro-capability`),完整目录见 `GET /api/admin/capabilities`,设计见 [access.md](../security/access.md)
|
||||
/api/agent/v1/* 节点专用:注册(使用加入令牌)和 RPC(使用签名认证)
|
||||
/healthz /metrics /openapi/v1.json /install /install.ps1
|
||||
/api/release/offer CI 登记签名发布清单(凭签名,无需令牌)
|
||||
/healthz /metrics /openapi/v1.json /install/*
|
||||
```
|
||||
|
||||
资源总览:
|
||||
@@ -28,22 +29,26 @@
|
||||
├─ live SSE 实时推送
|
||||
├─ lines/{line_id} 线路详情(线路 = Agent 与 Probe 的一对,id 形如 agt_…~prb_…)
|
||||
├─ lines/{line_id}/series 历史曲线(指标与评分)
|
||||
├─ nodes about 节点的展示信息(系统、国家、运营商,开启后带版本和 tag);后端的版本信息
|
||||
├─ nodes about ipv6 节点的展示信息(系统、国家、运营商,开启后带版本和 tag);后端的版本信息;IPv6 配置与采集诊断(不含地址)
|
||||
├─ compare 多条线路对比
|
||||
├─ tests/{test_id} 测试结果
|
||||
└─ catalog/{kinds|plans|metrics|models} 目录(由代码注册表生成)
|
||||
|
||||
/api/admin
|
||||
├─ auth/{login|logout|me}
|
||||
├─ auth/{setup|login|logout|me|passkey|passkeys} 首次认领、登录、passkey
|
||||
├─ trust 操作员集合(信任根)
|
||||
├─ audit 管理操作审计日志
|
||||
├─ agents agents/{id} agents/{id}/{approve|disable|enable|takeover}
|
||||
├─ join-tokens
|
||||
├─ probes probes/{id} probes/{id}/revoke Probe(用 probe 角色的加入令牌注册、吊销、删除)
|
||||
├─ links links/{probe_id}/{agent_id} 线路开关:哪些(Probe,Agent)连成线路(自动连接 + 手动选择)
|
||||
├─ links links/{probe_id}/{agent_id}[/retry] 线路开关:哪些(Probe,Agent)连成线路(自动连接 + 手动选择),立即重试
|
||||
├─ tasks tasks/{id} 线路模板、针对单个 Agent 的覆盖、目标任务
|
||||
├─ lines/{line_id}/tests 在某条线路(某个 Probe)上发起按需测试;tests/{id}/cancel
|
||||
├─ lines/{line_id}/tests 在某条线路(某个 Probe)上发起按需测试、列出近期测试;tests/{id}/cancel
|
||||
├─ raw/chunks raw/chunks/{id} 原始数据检索与下载
|
||||
├─ build-info 后端和每个节点的版本、tag、提交、构建时间、更新状态
|
||||
├─ releases nodes/{id}/update CI 签名的发布清单(登记、列表);请求节点更新
|
||||
├─ releases release-key nodes/{id}/update CI 签名的发布清单、可信发布密钥;请求节点更新
|
||||
├─ backend/update backend/update/live Backend 自身的更新确认与通知
|
||||
├─ nodes/{id}/logs 节点近期运行日志
|
||||
├─ events analysis/recompute api-tokens settings users
|
||||
```
|
||||
|
||||
@@ -85,7 +90,7 @@
|
||||
|
||||
参数、响应示例和限额见 [query.md](../design/query.md)。
|
||||
|
||||
线路详情 `GET /api/public/lines/{line_id}` 带 `data_since`:这条线路最早的数据是什么时候(没有数据是 null),前端据此只提供「有数据」的时间范围。**展示端的响应里没有 Probe 的版本和来源地址**(那些只在管理端)。
|
||||
线路详情 `GET /api/public/lines/{line_id}` 带 `data_since`:这条线路最早的数据是什么时候(没有数据是 null),前端据此只提供「有数据」的时间范围。展示端的响应里没有 Probe 的版本和来源地址(那些只在管理端)。
|
||||
|
||||
### 2.3.1 Agent 的主机资源占用
|
||||
|
||||
@@ -94,16 +99,16 @@
|
||||
| `GET /api/public/hosts` | 每个对外可见的 Agent 和没被吊销的 Probe 的最新快照:`{id, kind, name, online, stale, last_seen_at, host}`(`kind` 是 `agent` 或 `probe`);超过 15 s 没有更新 `stale` 为真(离线,或者节点关了上报) |
|
||||
| `GET /api/public/hosts/{node_id}?range=1h` | Agent 或 Probe 的历史曲线(列式,按步长取平均;`range` 从 1 小时到 30 天):`cpu`、`mem`、`disk`(百分比)、`rx_bps`、`tx_bps` |
|
||||
|
||||
`host` 只有汇总的数字:CPU 占用、内存与根分区的已用和总量、网卡累计收发字节与瞬时网速、系统运行时长。**没有 CPU 型号、主机名、网卡名,也没有任何 IP**——Agent 不采集这些,公开接口当然也不会返回;有测试断言响应里不出现这类字段。实时更新走 SSE 的 `hosts` 主题,历史每个 Agent 每分钟存一个样本(`retention.host_days`,默认 7 天)。
|
||||
`host` 只有汇总的数字:CPU 占用、内存与根分区的已用和总量、网卡累计收发字节与瞬时网速、系统运行时长。没有 CPU 型号、主机名、网卡名,也没有任何 IP——Agent 不采集这些,公开接口当然也不会返回;有测试断言响应里不出现这类字段。实时更新走 SSE 的 `hosts` 主题,历史每个 Agent 每分钟存一个样本(`retention.host_days`,默认 7 天)。
|
||||
|
||||
### 2.3.2 节点的展示信息
|
||||
|
||||
`GET /api/public/nodes`:看得见的 Agent 和没被吊销的 Probe 的展示信息,`{id, kind, os, os_name, arch, country, isp_key, isp_name, isp_manual}`——系统(`linux` / `windows` / `macos`)、「Debian 12」这样的系统名、架构(`x64` / `arm64`…)、国家代码(`CN`)、运营商类别(`mobile` / `telecom` / `unicom` / `broadnet` / `other`)和名字。**没有 IP 地址、城市、ASN、经纬度**,有测试保证:公开接口的整个响应里不出现 IP 形状的字符串,也没有 `ip`、`city`、`asn` 这些字段。管理员在设置里打开 `site.show_build` 之后,每项还有 `version` 和 `tag`(节点自己上报的程序版本和 tag);关着时这两个字段是 `null`。
|
||||
`GET /api/public/nodes`:看得见的 Agent 和没被吊销的 Probe 的展示信息,`{id, kind, os, os_name, arch, country, isp_key, isp_name, isp_manual}`——系统(`linux` / `windows` / `macos`)、「Debian 12」这样的系统名、架构(`x64` / `arm64`…)、国家代码(`CN`)、运营商类别(`mobile` / `telecom` / `unicom` / `broadnet` / `other`)和名字。没有 IP 地址、城市、ASN、经纬度,有测试保证:公开接口的整个响应里不出现 IP 形状的字符串,也没有 `ip`、`city`、`asn` 这些字段。管理员在设置里打开 `site.show_build` 之后,每项还有 `version` 和 `tag`(节点自己上报的程序版本和 tag);关着时这两个字段是 `null`。
|
||||
|
||||
`GET /api/public/about`:`{show_build, backend}`。`show_build` 关着时 `backend` 是 `null`;打开后 `backend` 是 `{version, tag, built_at}`(后端自己的版本、tag、构建时间,不含提交号)。
|
||||
|
||||
- 系统和架构是节点自报的:Agent 和 Probe 都在各自连面板时的 `fleet.hello` 里自报。只有粗粒度的名字,没有主机名、内核版本、CPU 型号。
|
||||
- 国家和运营商由 **Backend** 用节点的来源地址向 IP 归属服务查一次(`MoShiro__GeoLookupUrl`,缺省 `https://ip.007995.xyz`,留空就不查):Probe 用 Agent 看到的来源 IP,Agent 用它的公开地址。**Probe 和 Agent 不访问任何外部服务。** 只查公网地址(回环、内网、CGNAT、链路本地一律不发出去);同一个地址一周内只查一次,失败 10 分钟后再试;查到的只留国家代码和运营商,地址只存在 Backend 内部的 `node_meta.geo_host`,不对外。
|
||||
- 国家和运营商由 Backend 用节点的来源地址向 IP 归属服务查一次(`MoShiro__GeoLookupUrl`,缺省 `https://ip.007995.xyz`,留空就不查):Probe 用 Agent 看到的来源 IP,Agent 用它的公开地址。Probe 和 Agent 不访问任何外部服务。只查公网地址(回环、内网、CGNAT、链路本地一律不发出去);同一个地址一周内只查一次,失败 10 分钟后再试;查到的只留国家代码和运营商,地址只存在 Backend 内部的 `node_meta.geo_host`,不对外。
|
||||
|
||||
### 2.4 测试结果与目录
|
||||
|
||||
@@ -113,7 +118,7 @@
|
||||
|
||||
### 2.5 跨域访问
|
||||
|
||||
默认前端和 Backend 同源(Cookie 会话)。前端在别的来源时(比如本机跑前端、连线上的 Backend),Backend 设 `MoShiro__CorsOrigins`(逗号分隔的来源,或 `*`;默认空 = 不允许)。只对 `/api/*` 生效,响应带 `Access-Control-Allow-Origin`,预检请求(`OPTIONS`)返回 204,允许的头是 `Authorization, Content-Type, X-CSRF-Token`。**不带凭据**,Cookie 不会跨域,所以跨域的调用只能用 `Authorization: Bearer <API 令牌>`:展示端用只读令牌(站点私有时需要),管理端用 admin 范围的令牌(`/api/admin/auth/me` 对令牌同样可用)。SSE 在跨域时前端用 fetch 读流,因为 `EventSource` 带不了请求头。
|
||||
默认前端和 Backend 同源(Cookie 会话)。前端在别的来源时(比如本机跑前端、连线上的 Backend),Backend 设 `MoShiro__CorsOrigins`(逗号分隔的来源,或 `*`;默认空 = 不允许)。只对 `/api/*` 生效,响应带 `Access-Control-Allow-Origin`,预检请求(`OPTIONS`)返回 204,允许的头是 `Authorization, Content-Type, X-CSRF-Token`。不带凭据,Cookie 不会跨域,所以跨域的调用只能用 `Authorization: Bearer <API 令牌>`:展示端用只读令牌(站点私有时需要),管理端用 admin 范围的令牌(`/api/admin/auth/me` 对令牌同样可用)。SSE 在跨域时前端用 fetch 读流,因为 `EventSource` 带不了请求头。
|
||||
|
||||
## 3. Admin API
|
||||
|
||||
@@ -134,7 +139,7 @@
|
||||
| POST | `/api/admin/agents/{id}/probes/{probe_id}/disconnect` | 让这个 Agent 断开这个 Probe 的会话(Probe 会重连,除非已吊销);没有会话时返回 409 `probe_offline` |
|
||||
| GET/POST | `/api/admin/tasks` | 列表和创建:line 模板(不带 `agent_id`)、单个 Agent 的覆盖(带 `agent_id` + `base_task_id`)、target 任务 |
|
||||
| GET/PATCH/DELETE | `/api/admin/tasks/{id}` | 参数按 Kind 的 `ParamSpec` 校验,并检查带宽预算 |
|
||||
| POST | `/api/admin/lines/{line_id}/tests` | `{plan, params?}` → **202** + `Location: /api/public/tests/{id}`;Probe 离线时返回 409 `probe_offline`,节点繁忙时返回 409 `test_busy` |
|
||||
| POST | `/api/admin/lines/{line_id}/tests` | `{plan, params?}` → 202 + `Location: /api/public/tests/{id}`;Probe 离线时返回 409 `probe_offline`,节点繁忙时返回 409 `test_busy` |
|
||||
| POST | `/api/admin/tests/{id}/cancel` | |
|
||||
| GET | `/api/admin/raw/chunks?agent_id=&kind=&from=&to=&test_id=` | 原始块元数据 |
|
||||
| GET | `/api/admin/raw/chunks/{chunk_id}` | 下载原始块(`application/vnd.moshiro.rawchunk`);过期返回 410 `raw_expired` |
|
||||
@@ -148,11 +153,18 @@
|
||||
| GET | `/api/admin/build-info` | 后端和每个 Agent、Probe 的版本、tag、提交、构建时间、系统,以及节点宿主机更新器报告的更新状态(管理端「系统 → 版本」) |
|
||||
| GET | `/api/admin/releases` | 每个组件最新的一份签名发布清单 |
|
||||
| GET/PUT/DELETE | `/api/admin/release-key` | 可信资产来源:GET 看官方发布密钥和(如果有)自有发布公钥的指纹;PUT `{public_key}` 另外信任自己的发布公钥(P-256 的 PEM,拒绝私钥);DELETE 停用它,只有它签过的已登记清单会被丢掉。官方密钥始终信任。PUT/DELETE 需要 `update.confirm`,写审计 |
|
||||
| POST | `/api/release/offer` | CI 登记发布清单的入口,**不需要令牌**:`{manifest, signature}` 的签名必须能用 Backend 内嵌的官方发布公钥或已开启的自有发布公钥验过(ECDSA P-256 / SHA-256,DER),否则 403;`seq` 必须比已登记的新,否则 409。登记不依赖面板里的任何凭证,清库、重装、还没有 passkey 时照常工作 |
|
||||
| POST | `/api/release/offer` | CI 登记发布清单的入口,不需要令牌:`{manifest, signature}` 的签名必须能用 Backend 内嵌的官方发布公钥或已开启的自有发布公钥验过(ECDSA P-256 / SHA-256,DER),否则 403;`seq` 必须比已登记的新,否则 409。登记不依赖面板里的任何凭证,清库、重装、还没有 passkey 时照常工作 |
|
||||
| GET | `/api/admin/links` | 每一对(Probe,Agent)的线路开关:`linked`(最终结果)、`override`(手动设置,`null` 跟随自动连接)、`connected`,以及 `auto_link` |
|
||||
| PUT | `/api/admin/links/{probe_id}/{agent_id}` | `{enabled: true|false|null}`:手动强制连或不连,`null` 取消手动设置;改完立即重新下发 |
|
||||
| POST | `/api/admin/nodes/{id}/update` | 请求一个在线的 Agent 或 Probe 更新到它收到的清单(节点不在线返回 409) |
|
||||
| GET/POST/PATCH | `/api/admin/users` | 首次启动时通过命令行或环境变量创建初始管理员 |
|
||||
| GET/POST/PATCH | `/api/admin/users`、`/api/admin/users/{id}` | 用户列表、创建、修改密码 |
|
||||
| GET/POST | `/api/admin/auth/setup` | 首次认领:GET 返回面板是否尚无用户;POST 凭后端日志中的认领码创建第一个管理员,响应同密码登录,已有用户后关闭 |
|
||||
| GET/POST | `/api/admin/trust` | 操作员集合(信任根):GET 返回创世指纹、版本、与已注册 passkey 是否一致;POST 提交 passkey 签名的下一版集合 |
|
||||
| GET | `/api/admin/audit` | 管理操作审计日志,按时间倒序 |
|
||||
| GET | `/api/admin/lines/{line_id}/tests` | 该线路的近期测试 |
|
||||
| POST | `/api/admin/links/{probe_id}/{agent_id}/retry` | 启用该线路并立即让 Probe 重试连接 |
|
||||
| GET | `/api/admin/nodes/{id}/logs` | 节点近期运行日志(经心跳上传) |
|
||||
| GET/POST | `/api/admin/backend/update`、GET `/backend/update/live` | Backend 自身的更新状态、管理员确认更新,以及 SSE 通知 |
|
||||
|
||||
任务的请求体示例:
|
||||
|
||||
@@ -165,7 +177,8 @@
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| POST | `/api/agent/v1/enroll` | 由 `MapFleetEnrollment` 提供(使用加入令牌认证),见 [../backend/fleet/README.md](../../backend/fleet/README.md) 的「注册」一节 |
|
||||
| POST | `/api/agent/v1/enroll` | 由 `MapFleetEnrollment` 提供(使用加入令牌认证),见 [Fleet 文档](../../backend/fleet/README.md)的「注册」一节 |
|
||||
| POST | `/api/agent/v1/enroll/trust` | 返回操作员集合链和加入令牌的授权,节点据此验证后再注册 |
|
||||
| GET | `/api/agent/v1/rpc` | 由 `MapFleetLink` 提供,升级为 WebSocket;MoShiro 的方法见 [protocol.md](../design/protocol.md) |
|
||||
|
||||
## 5. 运维端点
|
||||
@@ -175,7 +188,8 @@
|
||||
| `GET /healthz` | 无 | SQLite 与原始数据目录都可写 |
|
||||
| `GET /metrics` | admin 令牌 | Prometheus 格式:在线数、块入库速率、分析队列长度、重算进度、磁盘占用、SSE 连接数 |
|
||||
| `GET /openapi/v1.json` | 无 | |
|
||||
| `GET /install`(也接受 `/install.sh`)、`GET /install.ps1` | 无 | 静态安装脚本:Agent 和 Probe 共用同一份,原样返回、不替换任何值,所以哈希在一个版本内固定;角色、面板地址、代码和属主走环境变量 |
|
||||
| `GET /install`(也接受 `/install.sh`)、`GET /install.ps1`、`GET /install/openwrt.sh` | 无 | 静态安装脚本,原样返回、不替换任何值,所以哈希在一个版本内固定;角色、面板地址、代码和属主走环境变量 |
|
||||
| `GET /install/compose/{file}`、`GET /install/quadlet/{file}` | 无 | 静态的 compose 文件与 Quadlet 单元(`agent`、`probe`、`backend`),所有人拿到的字节相同 |
|
||||
| `GET /install/manifest?code=…`、`GET /install/manifest.sig?code=…` | 无(凭一次性代码) | 该角色已签名的发布清单(原样)和签名,安装脚本据此验签、按 digest 拉镜像;代码不能用就是 404 |
|
||||
|
||||
## 6. 错误码(节选,完整列表见共享的 `ErrorCode`)
|
||||
@@ -194,7 +208,7 @@
|
||||
|
||||
## 7. 设计约束
|
||||
|
||||
本文是所有 Backend REST 端点都必须遵守的**规则**;具体端点见上面第 1–6 节。规则参考了 [Microsoft Azure REST API Guidelines](https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md) 和 RFC 9457,并根据本项目做了取舍。内部协议(Probe↔Agent、Agent↔Backend)的兼容规则见 [protocol.md](../design/protocol.md) 第 4 节。
|
||||
本文是所有 Backend REST 端点都必须遵守的规则;具体端点见上面第 1–6 节。规则参考了 [Microsoft Azure REST API Guidelines](https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md) 和 RFC 9457,并根据本项目做了取舍。内部协议(Probe↔Agent、Agent↔Backend)的兼容规则见 [protocol.md](../design/protocol.md) 第 4 节。
|
||||
|
||||
### 7.1 契约生成链路
|
||||
|
||||
@@ -208,14 +222,14 @@ backend/openapi/v1.json(OpenAPI 3.1,提交到仓库)
|
||||
web:openapi-typescript 生成类型,调用方的类型错误会直接暴露
|
||||
```
|
||||
|
||||
- 端点**必须**声明精确的返回类型,例如 `Results<Ok<AgentDto>, NotFound<ProblemDetails>>`,不能返回 `IResult` 或匿名对象,否则 OpenAPI 文档会不准确。
|
||||
- 端点必须声明精确的返回类型,例如 `Results<Ok<AgentDto>, NotFound<ProblemDetails>>`,不能返回 `IResult` 或匿名对象,否则 OpenAPI 文档会不准确。
|
||||
- 每个端点都必须设置 `WithName("agents_list")`(即 operationId,snake_case、`资源_动作`)、`WithSummary`、`WithTags`。
|
||||
- 请求和响应 DTO 放在 `MoShiro.Backend.Api/Contracts/`,并注册到 Backend 的 JSON 源生成上下文。**不要直接暴露 `MoShiro.Protocol` 中的线协议类型**,因为 REST 与线协议的演进节奏不同。
|
||||
- **结构强类型,指标弱类型**:资源结构(Agent、任务、测试等)必须是强类型 DTO;而**指标值和评分**统一使用字典 `metrics: { "<metric_id>": number }`、`scores: { "<model_id>": number }`,键的含义、单位、版本由 `/api/public/catalog/*` 给出。这样新增指标或模型不需要改 OpenAPI,也不需要改前端类型。
|
||||
- 请求和响应 DTO 放在 `MoShiro.Backend.Api/Contracts/`,并注册到 Backend 的 JSON 源生成上下文。不要直接暴露 `MoShiro.Protocol` 中的线协议类型,因为 REST 与线协议的演进节奏不同。
|
||||
- 结构强类型,指标弱类型:资源结构(Agent、任务、测试等)必须是强类型 DTO;而指标值和评分统一使用字典 `metrics: { "<metric_id>": number }`、`scores: { "<model_id>": number }`,键的含义、单位、版本由 `/api/public/catalog/*` 给出。这样新增指标或模型不需要改 OpenAPI,也不需要改前端类型。
|
||||
|
||||
### 7.2 版本与兼容性
|
||||
|
||||
- 当前版本为 v1,路径前缀为 `/api/public`、`/api/admin`、`/api/agent/v1`。出现破坏性变更时,新增 `/api/v2/public`、`/api/v2/admin` 等路径。v1 内只允许**非破坏性变更**:
|
||||
- 当前版本为 v1,路径前缀为 `/api/public`、`/api/admin`、`/api/agent/v1`。出现破坏性变更时,新增 `/api/v2/public`、`/api/v2/admin` 等路径。v1 内只允许非破坏性变更:
|
||||
|
||||
| 非破坏性变更(v1 内允许) | 破坏性变更(需要新建 v2) |
|
||||
| --- | --- |
|
||||
@@ -231,7 +245,7 @@ web:openapi-typescript 生成类型,调用方的类型错误会直接暴露
|
||||
|
||||
### 7.3 URL 与方法
|
||||
|
||||
- **按调用方分层**:`/api/public`(只读展示)、`/api/admin`(管理)、`/api/agent`(节点)。同一个资源在不同层中可以有不同的 DTO,例如 public 层不暴露 `pubkey`、`local_limits`。
|
||||
- 按调用方分层:`/api/public`(只读展示)、`/api/admin`(管理)、`/api/agent`(节点)。同一个资源在不同层中可以有不同的 DTO,例如 public 层不暴露 `pubkey`、`local_limits`。
|
||||
- 路径全部小写,资源名用复数名词,多个单词用 `-` 连接:`/api/admin/join-tokens`。
|
||||
- 嵌套最多一层;子资源一旦有全局唯一 ID,就提供顶层路径(`/probes/{probe_id}`)。
|
||||
- 查询参数和 JSON 字段使用 snake_case。
|
||||
@@ -251,7 +265,7 @@ web:openapi-typescript 生成类型,调用方的类型错误会直接暴露
|
||||
|
||||
| 类别 | 规则 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| 时间点 | RFC 3339 UTC,以 `Z` 结尾,精确到毫秒。**唯一例外**:列式时序响应中的时间轴数组 `t` 使用 Unix 毫秒(见 [query.md](../design/query.md)) | `2026-09-27T10:00:00.000Z` |
|
||||
| 时间点 | RFC 3339 UTC,以 `Z` 结尾,精确到毫秒。唯一例外:列式时序响应中的时间轴数组 `t` 使用 Unix 毫秒(见 [query.md](../design/query.md)) | `2026-09-27T10:00:00.000Z` |
|
||||
| 时长 | 整数 + 单位后缀 | `interval_ms: 1000` |
|
||||
| 延迟 | 带小数的毫秒值(指标字典中的单位见目录) | `rtt_p95_ms: 58.93` |
|
||||
| 百分比 | 0–100 的数字 + `_pct` | `loss_pct: 0.5` |
|
||||
@@ -277,7 +291,7 @@ web:openapi-typescript 生成类型,调用方的类型错误会直接暴露
|
||||
}
|
||||
```
|
||||
|
||||
- `code` 取自共享的 `ErrorCode` 枚举,是客户端做判断的**唯一**依据;`title`/`detail` 只供人阅读,内容可能变化。
|
||||
- `code` 取自共享的 `ErrorCode` 枚举,是客户端做判断的唯一依据;`title`/`detail` 只供人阅读,内容可能变化。
|
||||
- `errors` 只在 400 `validation_failed` 中出现,键名是 JSON 字段路径。
|
||||
- 5xx 响应不能泄露异常信息或调用栈,只提供 `trace_id`,用于在日志中定位问题。
|
||||
|
||||
|
||||
Reference in new issue
Block a user