orion-error 0.8.2

Structured error governance for layered Rust systems
Documentation
# Rust 里的错误处理,很多时候不是语法问题,而是系统设计问题

最近在整理 `orion-error` 的文档时,我越来越确定一件事:

很多系统后期越来越难维护,不是因为业务一定复杂,而是因为错误处理从来没有被认真设计过。

大家平时会讨论很多 Rust 错误处理话题,比如:

- `thiserror` 还是 `anyhow`
- 业务层要不要暴露底层错误
- `enum` 该按模块分,还是全局统一
- handler 里怎么映射 HTTP 状态码

这些问题都重要,但我现在更关心的是另一个层面:

**错误处理的核心问题,不是怎么表达失败,而是怎么治理失败。**

对系统来说,错误至少要同时满足两件事:

- 对调用方,分类要稳定,不然没法做重试、降级、告警和边界映射
- 对排障方,信息要够用,不然定位不到根因

问题是,这两件事天然互相拉扯。

- 只保留底层技术错误,诊断信息很全,但调用方会被实现细节绑死
- 只保留上层业务分类,治理是方便了,但排障时又经常断链

所以我这段时间把这个问题总结成一句话:

**系统需要让错误在治理层面收敛,在诊断层面保留有效信息。**

我现在用的做法,是把错误拆成三层:

```text
错误内部模型 = 契约通道 + 诊断通道
适配输出 = 对内部模型按策略生成的不同输出视图
```

- 契约通道负责稳定错误标识、分类和治理属性
- 诊断通道负责原因链、上下文和细节
- 输出层负责 HTTP、RPC、CLI、日志、指标这些边界视图

这样一来,错误内部保留完整信息,但对外暴露什么、如何暴露,不再由每个 handler 临时决定。

放到 Rust 里,我觉得至少有五条规则比较关键:

1. 按语义域定义 `Reason`,不要把全系统塞进一个 `AppError`
2. 底层错误首次进入体系时就结构化,不要先变字符串
3. 跨语义域传播时建立新边界,但保留下层错误
4. 边界只做输出,不重新解释错误
5. 测试错误标识,不测试错误文案

这也是我做 `orion-error` 时想解决的核心问题。它不是单纯减少错误样板代码,而是想把错误治理这件事,在 Rust 里收敛成一套更稳定的工程结构。

我现在比较关心两个问题:

1. 大家在 Rust 项目里,错误分类是按语义域拆,还是一个全局大枚举?
2. handler / service 边界上的错误输出策略,现在是集中做,还是散在各处 `match`
如果你们项目里已经踩过这些坑,也很想听听你们的做法。  
完整文章版我已经整理成文档,后面也会继续拆成更细的 Rust 落地内容。