Files
BlueArchiveToolkit/docs/reference/rpc-backend-api.md
T
nyaKazuha 0784d5b532
bat-rust / Build and test Rust (push) Canceled after 0s
bat-rust / Build and test Go API (push) Canceled after 0s
feat(bat): 完善工作流调度与 dashboard RPC
补全资源拉取、解析、翻译、重打包和本地化发布命令,支持单次、限定次数与周期调度。移除 TUI 计划并通过 schedule.* RPC 暴露给 bat-api dashboard。

Closes #43
2026-08-03 22:18:52 +08:00

445 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Rust Resource Backend RPC API
本文档冻结本机 Rust Resource Backend API 的稳定调用边界。Go 项目
`bat-api`、Go 服务层、运维脚本和 `bat` CLI 都应以这里的 JSON-RPC
contract 为准,不应绕过 daemon 状态文件或扩展 `bat-ffi` 作为主路径。
## 传输
- 传输:Unix domain socket。
- 默认 socket`/tmp/bat-pid/bat.sock`
- 协议:JSON-RPC 2.0,每行一个 request,每行一个 response。
- 编码:UTF-8 JSON。
- 访问控制:依赖本机文件权限和状态目录权限;不要把 socket 暴露到公网。
请求:
```json
{"jsonrpc":"2.0","id":1,"method":"resource.repair","params":null}
```
成功响应的 JSON-RPC 顶层 `result` 一律是应用层 envelope
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"ok": true,
"status": "accepted",
"data": {"task_id": "task-1234-1", "kind": "resource.repair"},
"request_id": "req-1234-1"
}
}
```
应用层失败也放在 `result` 的 envelope 中:
```json
{
"ok": false,
"status": "error",
"error": {
"code": "BAT-ERR-700003",
"kind": "not_implemented",
"domain": "rpc",
"location": "rpc.dispatch",
"message": "方法尚未实现:daemon.clean-stable",
"retryable": false
},
"request_id": "req-1234-2"
}
```
只有 JSON 解析失败等传输层错误使用 JSON-RPC 顶层 `error`
## Envelope
| 字段 | 类型 | 说明 |
|---|---|---|
| `ok` | bool | 应用层是否成功。 |
| `status` | string | `ok``accepted``error`。 |
| `data` | object/null | 成功结果。失败时省略。 |
| `error` | object/null | `ApiError`。成功时省略。 |
| `request_id` | string | daemon 进程内请求 ID,用于日志关联。 |
`ApiError` 结构以 `core/src/error_code.rs` 码表为准:
| 字段 | 类型 | 说明 |
|---|---|---|
| `code` | string | `BAT-ERR-<6位>`。 |
| `kind` | string | 错误类别。 |
| `domain` | string | 错误域。 |
| `location` | string | Rust 侧出错位置。 |
| `message` | string | 可诊断错误信息。 |
| `retryable` | bool | 调用方是否可以按策略重试。 |
## 方法
### daemon
| 方法 | 状态 | params | data |
|---|---|---|---|
| `daemon.status` | 已实现 | `null` | 后台状态报告。 |
| `daemon.logs` | 已实现 | `{ "tail": 200 }` | 日志尾部报告。 |
| `daemon.stop` | 已实现 | `null` | accepted ack。 |
| `daemon.restart` | 已实现 | `null` | accepted ack;启动 Rust lifecycle controller,并在响应后停止当前 daemon。 |
| `daemon.reload` | 已实现 | `null` | accepted ack。 |
| `daemon.refresh` | 已实现 | `{ "force": false }` | accepted ack。 |
| `daemon.doctor` | 已实现 | `null` | 只读诊断报告。 |
| `daemon.clean-stable` | 保留 | `null` | live RPC 不执行;由 CLI 离线清理入口处理。 |
`daemon.restart` 不在 daemon 线程内手写第二套启动流程;它启动本机 Rust
`bat restart --state-dir ...` lifecycle controller,由既有 CLI restart 路径复用
保存的启动参数、代理凭据、PID/socket 替换和控制锁。
`bat.status``bat.stop``bat.restart``bat.reload``bat.refresh``bat.logs`
`bat.doctor``bat.clean-stable` 是兼容别名;新代码应使用 `daemon.*`
### resource
| 方法 | 状态 | params | data |
|---|---|---|---|
| `resource.state` | 已实现 | `null` | 资源发布根、版本状态、上次同步结果。 |
| `resource.sync` | 已实现 | `{ "force": false }` | `{ "task_id": "...", "kind": "resource.sync" }`。 |
| `resource.verify` | 已实现 | `null` | `{ "task_id": "...", "kind": "resource.verify" }`。 |
| `resource.repair` | 已实现 | `null` | `{ "task_id": "...", "kind": "resource.repair" }`。 |
| `resource.manifest` | 已实现 | `{ "offset": 0, "limit": 100 }` | 当前 download manifest 分页。 |
| `resource.list` | 已实现 | `{ "offset": 0, "limit": 100 }` | `resource.manifest` 的兼容别名。 |
| `resource.index` | 已实现 | `{ "offset": 0, "limit": 100, "type": "asset_bundle", "hash": "...", "path_pattern": "*", "release_id": "...", "platform": "windows", "destination": "...", "archive_entry": "...", "parse_status": "parsed", "format": "json" }` | 当前 `ResourceRepository` 分页/过滤查询。 |
`resource.repair` 会开启本地 manifest audit + repair,不继承 `force`
`resource.manifest` / `resource.list` 查询当前已发布 release 的
`official-download-manifest.json``resource.index` 查询可选导入产生的
SQLite `ResourceRepository`,索引不存在时返回 `ok=true`
`data.available=false`,不会隐式创建数据库。`resource.index` 可按
`resource_type`/`type``hash``path_pattern``official_release_id`/`release_id`
`platform``destination``bundle_path``archive_entry``parse_status`
`text_unit_format`/`format` 过滤;`path_id``class_id``field_path`
属于 `parse.text_units` / `parse.errors` 的对象级查询。`limit` 范围是
`1..=1000`,非法参数返回 `BAT-ERR-700002`
`resource.index``entries[]``Resource` JSON,除 `id``local_path`
`entry` 外会包含 `metadata``official_release_id``platform`
`bundle_path``archive_entries``parse_statuses``unity_versions`
`text_assets``text_unit_count``text_unit_formats`
`text_unit_error_count` 等字段。旧索引库会通过 `metadata_json` 迁移列得到
默认空 metadata。
`resource.state``catalog.status``parse.status``localized.status`
都会返回当前观察面的短状态 `status` 与稳定状态码 `status_code``status_code`
使用命名空间格式,例如 `official.up_to_date``official.published`
`parse.completed``translation.queued_offline``localized.published`
`distribution.ready`。这些状态码描述资源/解析/翻译 handoff/汉化/分发生命周期;
失败原因仍使用 `BAT-ERR-*` 错误码,二者不混用。响应还会包含
`status_phase``status_terminal``status_retryable`,供 `bat-api` 等读侧
决定展示、重试或 readiness。
官方资源完整新版本发布后,Rust 侧会先比较上一完整 release 与当前 release
的 download manifest,并在当前 release 根目录写出:
- `official-resource-changes.json`:记录 added / modified / removed 资源。
同一 destination 只有 size 或 BLAKE3 变化才算 modifiedURL 或 CDN root
变化但内容一致时不进入解析/翻译候选。
- `crowdin-translation-handoff.json`:只包含 added + modified 资源,作为后续
Crowdin worker 的稳定本地队列输入;当前 RPC 不直接调用 Crowdin API。
- `official-parse-cache.json`:解析缓存。up-to-date 轮询发现本地文件未变且缓存
有效时只读取摘要,不重复解析。
- `official-textunit-index.json`:TextUnit 明细和解析错误索引。up-to-date 轮询发现
本地文件未变且索引有效时复用,不重复解析。
- `official-textunit-tasks.json`:只由 added + modified 资源、parse cache 和
TextUnit 明细索引派生,记录 TextUnit 任务、跳过原因和解析诊断。
- `crowdin-textunit-queue.json`:只包含已产生 TextUnit 的离线任务,预留给后续
Crowdin worker;当前不会发出网络请求。
- `translation-tasks.sqlite`:当前 release 的可变 worker 状态库,记录
queued / running / failed / completed / skipped、attempt count、provider run
ID 和 failure reasonschema 由 `schema_migrations` 版本表管理。
- `translation-handoff.json`:当前 release 的版本化 job/unit/provider run 交接
快照;worker 更新后的实时状态仍以 `translation-tasks.sqlite` 为准。
删除资源只进入 `official-resource-changes.json`,不进入 Crowdin handoff。
### schedule
调度计划由 Rust `bat` 持有,状态文件为 daemon `state_dir` 下的
`bat-schedules.json`。CLI、RPC 和 `bat-api` dashboard 都调用同一组原子
读改写逻辑,不在 Go 侧复制计划状态。
| 方法 | 状态 | params | data |
|---|---|---|---|
| `schedule.list` | 已实现 | `null` | `{ "command": "schedule-list", "schedules": [...] }`。 |
| `schedule.add` | 已实现 | 调度 mutation | 新建 schedule report。 |
| `schedule.update` | 已实现 | 调度 mutation,必须有 `id` | 更新后的 schedule report。 |
| `schedule.remove` | 已实现 | `{ "id": "daily-pull" }` | 删除报告。 |
| `schedule.run` | 已实现 | `{ "id": "daily-pull", "force": true }`,字段可省略 | 到期或强制执行报告;省略 `id` 执行所有到期计划。 |
调度 mutation 字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | string | 计划 IDadd 必填,update/remove 用于定位。 |
| `group` | string | `res``parse``i18n`;对应一级工作流。 |
| `action` | string | `res``pull/refresh/verify/repair``parse``run/repack``i18n``run/export/publish`。 |
| `args` | string[] | 目标工作流的 CLI 参数。 |
| `next_run_unix_seconds` | uint64 | 指定下一次执行时间;不能和 `delay_seconds` 同时使用。 |
| `delay_seconds` | uint64 | 从当前时间计算下一次执行时间。 |
| `every_seconds` | uint64 | 周期秒数;必须大于 0。 |
| `count` | uint64 | 最大执行次数;省略周期无限执行,非周期计划默认执行一次。 |
| `clear_args` | bool | update 时清空工作流参数。 |
| `clear_every` | bool | update 时清除周期并转为单次计划。 |
| `enabled` | bool | 启用或停用计划。 |
`count > 1` 必须和周期同时存在;`schedule.run``force=true` 只忽略
到期时间,不会绕过 `enabled=false`。每次执行前先持久化下一次状态,执行后
再持久化成功/失败和错误信息,避免进程中断后重复领取同一计划。
### parse
| 方法 | 状态 | params | data |
|---|---|---|---|
| `parse.status` | 已实现 | `null` | 当前官方 release 的解析缓存状态。 |
| `parse.text_units` | 已实现 | `{ "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" }` | 当前官方 release 的 TextUnit 明细分页。 |
| `parse.errors` | 已实现 | `{ "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" }` | 当前官方 release 的解析错误分页。 |
| `translation.tasks` | 已实现 | `{ "offset": 0, "limit": 100, "task_id": "...", "release_id": "...", "destination": "...", "archive_entry": "...", "status": "skipped_parse_failed", "parse_status": "failed", "format": "json", "has_reason": true }` | 当前官方 release 的离线 TextUnit 翻译任务状态分页。 |
| `translation.handoff` | 已实现 | `null` | 当前官方 release 的 job、unit、provider run 交接视图;动态合并队列和 SQLite worker 状态。 |
| `translation.task.update` | 已实现 | `{ "task_id": "...", "status": "failed", "failure_reason": "...", "provider_run_id": "..." }` | 写入当前 release 的 provider worker 状态,返回可回查任务记录。 |
`parse.status` 是只读查询;没有当前 release 或没有解析缓存时返回
`ok=true``data.available=false`。解析缓存来自官方原版资源目录,不读取
汉化输出目录。存在 `official-textunit-index.json` 时,响应会包含
`textunit_index_available=true``textunit_index_path`
`textunit_index_summary`;存在 `official-textunit-tasks.json` 时,响应会包含
`textunit_queue_available=true``textunit_task_queue_path`
`textunit_task_summary`。当 TextUnit 队列存在且有离线任务时,
`translation_status_code=translation.queued_offline`;真实 Crowdin worker
尚未接入时不会返回翻译完成状态。
`parse.text_units` / `parse.errors` 是只读查询;没有当前 release 或没有
`official-textunit-index.json` 时返回 `ok=true``data.available=false`
分页参数 `offset` 默认 0`limit` 默认 100,范围是 `1..=1000`。过滤参数:
| 字段 | 类型 | 说明 |
|---|---|---|
| `destination` | string | official download manifest destination,支持 `*` 通配。 |
| `archive_entry` | string | zip 内条目,支持 `*` 通配;直接 bundle 通常为 `null`。 |
| `path_id` | integer | Unity object path id。 |
| `class_id` | integer | Unity class id。 |
| `field_path` | string | TypeTree/TextAsset 字段路径,支持 `*` 通配。 |
| `format` | string | TextUnit 格式,例如 `json``csv``tsv``plain``typetree_string`。 |
`parse.text_units``entries[]` 会包含 source text、source URL、
destination、archive entry、source kind、Unity version、serialized file、
path id、class id、field path、字段 offset/byte size、format、asset name 和
context。`parse.errors``entries[]` 会包含 source URL、destination、
archive entry、status、serialized file、path id、class id、field path、
offset 和 error。TypeTree-covered managed reference 字段会进入结构化字段遍历;
完整 managed reference registry 等暂不支持结构会进入解析错误,而不是静默降级为
低保真文本。
`translation.tasks` 优先查询当前 release 的 `translation-tasks.sqlite`,旧 release
没有该文件时回退到 `official-textunit-tasks.json`;用于查看离线 TextUnit
翻译任务候选和 provider worker 状态。没有当前 release 或没有任务队列时返回
`ok=true``data.available=false`。过滤参数包括 `task_id`
`official_release_id`/`release_id``destination``path_pattern`
`archive_entry``status`/`task_status``worker_status``parse_status`
`text_unit_format`/`format``has_reason``has_failure_reason`
`entries[]` 会包含 `official_release_id``destination``archive_entry`
`parse_status`、队列 `status``task_status``failure_reason``attempt_count`
`provider_run_id`、TextAsset/TextUnit 摘要和校验指纹。
`translation.task.update` 只更新当前 release 的 SQLite 状态库,不改写 immutable
队列文件,也不主动访问 Crowdin。`status` 支持 `queued``running``failed`
`completed``skipped`;进入 `running` 会增加 attempt count`completed`
记录完成时间,`failed` 可写入 `failure_reason`。因此 worker 消费 handoff 后,
bat-api 可通过 `translation.tasks` 查询单项任务,也可通过
`translation.handoff` 获取完整 job/unit/provider run 状态。`translation.handoff`
不会触发下载或 provider 网络请求;没有当前 release 或任务队列时返回
`data.available=false`
### localized
| 方法 | 状态 | params | data |
|---|---|---|---|
| `localized.status` | 已实现 | `null` | 汉化发布状态、当前官方 release 匹配关系和汉化输出目录。 |
`localized.status` 严格按 daemon / `.env` 中的 `BAT_LOCALIZED_OUTPUT`
`--localized-output` 查询汉化产物目录,不把 `./bat-resources`
`./bat-localized` 混用。当前支持未汉化发布状态和已汉化发布状态的只读报告。
`status` / `status_code` 使用生命周期短状态和稳定状态码,例如
`pending` / `localized.pending``stale` / `localized.stale``published` /
`localized.published`;旧的 `localized` / `not_localized` 业务标签放在
`localized_release_status`。返回 `localized_release_status=localized` 的条件是:
`localized-version-state.json` 的官方 release ID 匹配当前官方 release
`current` symlink 指向汉化发布根下对应的 `versions/<id>`,并且该版本目录中的
`localized-patch-manifest.json` 存在且 release ID 匹配。响应会返回
`patch_manifest_path``patch_manifest_available`
`patch_manifest_matches_release``patch_file_count`
`patch_text_asset_operation_count``rollback_previous_current_target`
### catalog
| 方法 | 状态 | params | data |
|---|---|---|---|
| `catalog.status` | 已实现 | `null` | 当前已发布 catalog 概览。 |
| `catalog.versions` | 已实现 | `null` | current / in_progress / previous / failed。 |
| `catalog.diff` | 已实现 | `null` | 当前 snapshot 相对上一可用版本的差异。 |
| `catalog.refresh` | 已实现 | `{ "force": false }` | `{ "task_id": "...", "kind": "catalog.refresh" }`。 |
只读查询在没有可用版本时返回 `ok=true``data.available=false`
`catalog.status` 可用时会返回 `status_code=official.published`,并用
`distribution_status_code=distribution.ready` 表示该官方 release 可被读侧分发;
不可用时对应 `official.unavailable` / `distribution.blocked`
### task
| 方法 | 状态 | params | data |
|---|---|---|---|
| `task.status` | 已实现 | `{ "task_id": "..." }` | 单个任务记录。 |
| `task.list` | 已实现 | `null` | `{ "tasks": [...] }`。 |
| `task.cancel` | 已实现 | `{ "task_id": "..." }` | cancel ack。 |
| `task.logs` | 已实现 | `{ "task_id": "..." }` | `{ "task_id": "...", "lines": [...] }`。 |
| `task.create` | 保留 | object | 不开放通用任务入口;由语义方法创建任务。 |
任务记录:
```json
{
"id": "task-1234-1",
"kind": "resource.repair",
"status": "queued",
"stage": null,
"message": null,
"created_at": 1780000000,
"updated_at": 1780000000,
"started_at": null,
"finished_at": null,
"error": null,
"result": null
}
```
`status` 取值:`queued``running``succeeded``failed``cancelled`
daemon 重启后仍处于 `queued``running` 的历史任务会被标记为
`failed`,错误码为 `BAT-ERR-700005`
### patch / unityfs
已开放的文件级写入方法:
- `patch.apply`:对显式 `source_path``patch_path``target_path` 执行
Binary/JSON/Text patch apply`kind` 取值为 `binary``json``text`
- `unityfs.patch_text_asset`:对显式 UnityFS `bundle_path` 中的
`serialized_file_path` / `path_id` TextAsset 应用 `replacement_path`,写入
`target_path`,可选 `expected_name`
- `unityfs.patch_string_field`:对显式 UnityFS `bundle_path` 中的
`serialized_file_path` / `path_id` / `field_path` TypeTree string 字段应用
`replacement_text` 或 UTF-8 `replacement_path`,写入 `target_path`,可选
`expected_value`
- `unityfs.patch_field`:对显式 UnityFS `bundle_path` 中的
`serialized_file_path` / `path_id` / `field_path` TypeTree 字段应用语义
`replacement` JSON,写入 `target_path`,可选 `expected_value``replacement`
使用 `{"kind":"signed","value":42}` 这类 tagged JSON;支持
`bool``signed``unsigned``float32``float64``string``bytes`
`enum``bit_field``p_ptr`、固定 Unity 叶子结构、object 字段组合和 TypeTree schema 支撑的 array/map 整体替换。enum 形如
`{"kind":"enum","value":{"type_name":"ScenarioDifficulty","storage_type":"int","value":3}}`
`type_name` 是 TypeTree enum 类型名,`storage_type` 是 backing integer 类型。`LayerMask` / `BitField` 形如
`{"kind":"bit_field","value":{"type_name":"LayerMask","storage_type":"UInt32","bits":9}}`
array 形如
`{"kind":"array","value":[{"kind":"string","value":"你好"}]}`map entry 用
object 表达,例如
`{"kind":"object","value":[{"name":"first","value":{"kind":"string","value":"jp"}}]}`
扩容时复用当前首个元素或 TypeTree data node 的编码 schemamap entry schema
变化、unknown 字段和未覆盖的 managed reference registry 变体仍会返回明确错误。
固定 Unity 叶子结构使用 raw bits/bytes 表达,例如
`{"kind":"float32_struct","value":{"type_name":"Vector3f","values":[1065353216,1073741824,1077936128]}}`
`{"kind":"fixed_bytes","value":{"type_name":"GUID","bytes":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}}`
这些方法同步执行,不进入 `task.*` 队列;输出文件使用临时文件原子写入,响应
`data` 会返回 source / patch 或 replacement / target 的 size 与 BLAKE3。`target_path`
不能与输入文件相同。
仍关闭的范围:发布级 `patch build` / `patch rollback`、复杂 UnityFS 语义编辑、
`unityfs.inspect`、通用 manifest 驱动 release 切换。调用这些规划方法仍返回
`BAT-ERR-700003`
CLI 对应关系:
| CLI | RPC |
|---|---|
| `bat patch-apply` | `patch.apply` |
| `bat unityfs-patch-text-asset` | `unityfs.patch_text_asset` |
| `bat unityfs-patch-string-field` | `unityfs.patch_string_field` |
| `bat unityfs-patch-field` | `unityfs.patch_field` |
## Go 调用边界
`bat-api` 应直接调用本 RPC contract,不通过 `exec` 调用 `bat` binary。
`bat` binary 是人类 CLI 和进程生命周期工具;默认 `refresh` / `repair`
在 daemon 可用时也会作为 RPC client 调用同一个 socket。`daemon.restart`
会启动 Rust lifecycle controller 复用同一套 CLI restart 路径,Go 层仍不直接
`exec` 或解析 `bat` stdout。
人类 CLI 的只读查询命令与 RPC 对应关系如下:
| CLI | RPC |
|---|---|
| `bat parse-status` | `parse.status` |
| `bat parse-text-units` | `parse.text_units` |
| `bat parse-errors` | `parse.errors` |
| `bat translation-tasks` | `translation.tasks` |
| `bat translation-handoff` | `translation.handoff` |
| `bat localized-status` | `localized.status` |
| `bat resource-index` | `resource.index` |
`bat resource-index` 支持 `--offset``--limit``--resource-type``--hash`
`--path-pattern``--release-id``--platform``--destination`
`--bundle-path``--archive-entry``--parse-status``--format`
`bat parse-text-units` / `bat parse-errors` 支持 `--offset``--limit`
`--destination``--path-pattern``--archive-entry``--path-id`
`--class-id``--field-path``--format``bat translation-tasks` 支持
`--offset``--limit``--task-id``--release-id``--destination`
`--path-pattern``--archive-entry``--task-status``--worker-status`
`--parse-status``--format``--has-reason``--has-failure-reason`。这些过滤参数不适用于
`parse-status``translation-handoff``localized-status`
### Go 客户端表面
`internal/backendrpc.Client` 是 Unix socket JSON-RPC 传输客户端:
- `Call` 可发送本文档中的任意已记录方法,并负责 JSON-RPC transport、
envelope 和 `ApiError` 解码;它不是 bat-api 的 HTTP 任意 RPC proxy。
- typed helper 已覆盖 daemon 已实现方法(`status/logs/stop/restart/reload/refresh/doctor`)、
`resource.state/sync/verify/repair/manifest/list``schedule.list/add/update/remove/run`
`catalog.*``parse.*`
`localized.status``task.*` 和三个
`unityfs.patch_*` 方法。
- `resource.index``translation.tasks``translation.handoff`
`translation.task.update``patch.apply` 当前没有专用 typed helper
需要直接使用 `Call`,并仍须遵守本契约的参数和响应定义。
`internal/api` 对 bat-api 生产路径进一步收窄接口:
| Go 接口 | 允许调用的 RPC | 用途 |
|---|---|---|
| `Backend` | `daemon.status``daemon.doctor``resource.state``catalog.status``resource.manifest` | 启动发现、周期刷新和资源分发 |
| `ControlBackend` | `daemon.restart``daemon.reload``daemon.refresh``resource.sync``resource.verify``resource.repair``catalog.refresh` | 鉴权后的管理控制白名单 |
| `ScheduleBackend` | `schedule.list``schedule.add``schedule.update``schedule.remove``schedule.run` | 鉴权后的 dashboard 调度计划控制 |
`daemon.stop``daemon.clean-stable` 和任意通用 RPC 不属于 bat-api 管理控制面。
Rust dispatch、Go transport 和 bat-api 接口的权威实现位置分别是
`infrastructure/src/bin/bat/app.rs``internal/backendrpc/client.go`
`internal/api/rpc_release.go`;修改方法、字段或 allowlist 时必须同步更新本文档。
Go mirror contract fixture 固化在 `internal/api/testdata/contract/`,覆盖
`catalog.status` available/unavailable、`resource.manifest` page0 和对应
`official-sync-snapshot.json`。这些 fixture 由 Rust 输出归一化而来,只用于
schema / mirror 回归;live daemon socket 和完整 release 切换仍需在允许 smoke 的
隔离环境中验证。
禁止事项:
- Go 服务层不直接读写 `bat-status.json``bat-tasks.json` 等 daemon 内部状态文件。
- Go 服务层不扩展 `bat-ffi` 为主控制面。
- Go 服务层不通过 stdout 解析 `bat status --json` 作为常规调用路径。