Repository navigation
Releases: erikwang2013/e-cat
Release list
v7.1.1
Security
- 升级
rustls0.23.45 → 0.23.46,修复 RUSTSEC-2026-0346 / 0347 / 0348 / 0349
(cargo audit --deny warnings在 2026-10-14 新通告后失败)。 - 升级
quinn-proto0.11.16 → 0.11.18,修复 RUSTSEC-2026-0338 / 0339 / 0340 /
0341 / 0342(含两条 high)。纯依赖升级,无 API 变更。
v7.1.0
Added
ecat-cli:ecat pet子命令 ——list/show/export浏览并导出项目宠物的
13 个纯矢量形态(主形象 + 12 表情)。PetForm枚举携带 slug、中英文名、README 短代码
与内嵌 SVG;show接受 slug、短代码、中文名或英文名(如smile/:emoji-smile:/笑)。
资源随ecat-cli打包,ASSETS-LICENSE.md一并分发(SVG 不是 Apache-2.0)。- 项目宠物纯矢量化 —— 主形象与 12 个表情全部改为纯矢量 SVG,不再内嵌位图;
新增scripts/generate_pet_assets.py作为单一生成源,同步docs/、12 份 i18n 与
ecat-cli/assets/pet/,并以测试防止 CLI 内嵌资源与docs/漂移。 - Social Preview 更新 —— 使用新矢量形象重新生成 1280×640 卡片;crate 数与数据后端数
改为从 workspace members 推导,不再硬编码。
Changed
- 发布脚本 ——
scripts/release.sh支持patch/minor/major/ 显式X.Y.Z,
并在发布时同步全部 Cargo.toml(含 workspace 依赖与成员)、14 份 README、配置示例中的
版本串;新增main分支、干净工作树、CHANGELOG 段落与 tag 冲突前置检查。 - 文档 —— README 宠物章节补充
ecat pet用法;ecat-cli/README.md增加 Pet forms
说明与授权提示。
Fixed
scripts/mk-social-preview.py的圆形蒙版未乘 SVG 自身 alpha,导致 transparent 背景
被渲染成黑色。
v7.0.0
v7.0.0 — 批次 5b:11 个数据后端的出站韧性(超时/熔断/并发上限)+ 13 个 crate 的 metrics 构造即注册 破坏性变更:11 个后端 Config 新增公开字段(query_timeout_secs / breaker / max_concurrency 或 max_pool_size / min_pool_size)。这些结构体无 Default 也无 non_exhaustive,用结构体字面量 构造的用户代码需要补字段(E0063);走 serde 配置的写法不受影响。 发布判据(Task 13 Step 5 全量闸门,七步全绿): cargo test --workspace rc=0 1228 passed / 0 failed cargo test --workspace --doc rc=0 4 passed / 0 failed cargo fmt --all -- --check rc=0 cargo clippy --workspace --all-targets -D warnings rc=0 4 crate --all-features rc=0 181 passed / 0 failed 13 crate --features metrics rc=0 (16/13/17/22/21/21/22/23/20/28/17/20/35) 无源文件 >=500 行 + 版本一致性 6 项全中
v6.0.0
⚠️ 破坏性变更
ecat-data:run_with_timeout签名变更 ——(Option<Duration>, F)→
(BackendKind, Option<Duration>, F),返回的错误类型由写死的RdbmsError改为泛型
E: TimeoutError。全仓 13 个既有调用点已迁移。ecat-data:删除公开静态量QUERY_TIMEOUTS—— 由TIMEOUTS(按BackendKind
分 7 维)+timeout_counter(kind)取代。它只覆盖 RDBMS,且在新维度下不再被递增 ——
留着就是一颗哑弹:仍是公开 API,读它的人永远拿到冻结值。- (次要)
RedisConfig/ClickhouseConfig新增公开字段。两个结构体都没有Default
也没有#[non_exhaustive],用结构体字面量构造的用户代码需要补字段;走 serde 配置的
写法不受影响(新字段全部带#[serde(default)],省略即默认)。
Added
ecat-data:泛型超时助手(原run_with_timeout只服务 RDBMS 一条路径):BackendKind—— 7 个后端类别(Rdbms/Cache/Search/Graph/
Document/Storage/Tsdb),判别值即TIMEOUTS下标,顺序不可改;
BackendKind::slug()给出Error::reason用的短标识。
维度跟 trait 家族走而不是产品品类:ClickHouse 同时实现SqlExecutor与
TsdbClient,按「调用点包着哪个 trait」分。TimeoutErrortrait + 两个实现:RdbmsError(→RdbmsError::Timeout)与
ecat_errors::Error(→ErrorCode::DeadlineExceeded,reason填组件标识)——
六个非 RDBMS trait 共用后者,不需要六套。TIMEOUTS: [AtomicU64; 7]+timeout_counter(kind)。取槽走无_分支的match:
将来加第 8 个维度时编译失败,而不是运行期数错槽。- 泛型
run_with_timeout(kind, timeout, fut):None= 禁用超时;
Some(Duration::ZERO)= 立刻超时(不是禁用,别照抄本仓别处「0= 禁用」的惯例)。
ecat-data:熔断器错误的映射公开 ——map_breaker_error由pub(crate)改为pub,
并新增breaker_error_to_backend_error(ecat_errors::Error侧的同一套语义)。
Redis / ClickHouse 的包装层与RdbmsRouting复用同一套:后端自身的错误原样透出,
熔断打开/探测耗尽时后端根本没被调用,报「连接不可用」。
分两个函数是因为RdbmsError、ecat_errors::Error与BreakerError都是外部类型,
写不出统一的From(孤儿规则)。ecat-circuit-breaker:Breaker::opened_total()——Closed → Open的累计次数(半开探测失败重新打开也计入),
供ecat_outbound_breaker_open_total。用state()轮询猜测「开了几次」是错的
(轮询间隔决定准确性,两次探测之间开又关抓不到)。BreakerState::code()—— 指标数值编码0= closed /1= open /2= half-open。
放在枚举定义处而非指标侧,编码器与枚举才不会各改各的。BreakerConfig可反序列化:各字段#[serde(default)],配置文件里breaker: {}
与breaker: {"failure_ratio": 0.5}都能解析。
ecat-metrics:三个出站指标的全进程唯一 collector ——
register_outbound_metrics(backend, timeouts, breaker_opened, breaker_state)。
ecat_outbound_timeouts_total/ecat_outbound_breaker_open_total/
ecat_outbound_breaker_state,维度backend。幂等:同一个backend重复注册覆盖
(避免同一标签出现两份样本被抓取端判为重复)。collector 必须在ecat-metrics只建一份 ——
registry()是全进程一个,每 crate 各建一份会在Registry里撞名(见 Fixed 第二条)。ecat-metrics:四个ecat_rdbms_*家族的唯一 collector ——
register_rdbms_metrics(backend, connections, pool_timeouts, query_timeouts, transactions_leaked);ecat-data-sqlx/ecat-data-mssql的register_pool_metrics
改为往里挂数据源(签名未变)。ecat-data-redis:Cache路径内置超时 + 熔断(用户代码零改动):RedisConfig新增query_timeout_secs(0= 禁用;未配置 = 30 秒)与breaker
(省略即保守默认:失败率 0.5 / 窗口 30 秒 / 打开 10 秒)。RedisCache::breaker()暴露熔断器句柄;超时计数按BackendKind::Cache维度。- opt-in feature
metrics:register_outbound_metrics(Arc<Breaker>),标签backend="redis"。
ecat-data-clickhouse:SqlExecutor与TsdbClient两条路径内置超时 + 熔断 + 并发上限:ClickhouseConfig新增query_timeout_secs/breaker/max_concurrency
(未配置 = 32)。并发上限由本 crate 的信号量实现 —— reqwest 只有
pool_max_idle_per_host(空闲保留数),没有「最大总连接数」,默认无背压。- 两条路径共用一个
Breaker(同一个服务器、同一个故障域);超时维度分别按
Rdbms与Tsdb计。 TsdbClient实现搬到src/tsdb.rs;_with方法保持不进熔断器(见 Fixed 第三条)。- opt-in feature
metrics:标签backend="clickhouse"/backend="clickhouse-tsdb"。
docs/superpowers/checklists/backend-resilience-onboarding.md—— 5b 逐 crate 照做的
出站韧性接入 checklist(8 节)。docs/database-config-tutorial.md×13 补 Redis / ClickHouse 的超时与熔断字段,
并写明 Redis 多路复用的能力边界。
Fixed
ecat-circuit-breaker:半开探测名额泄漏(5.0.0 已发布缺陷)。
Breaker::call在半开分支于f().await之前借出探测名额,而名额的归还只在
await 之后的记录逻辑里。于是 future 被外部取消(tokio::select!、调用方自己的
超时层、请求处理被 drop)时名额有借无还 ——half_open_probes(默认 3)次之后
half_open_count >= half_open_probes恒成立,每次调用立即返回ProbesExhausted,
状态永久停在HalfOpen,只能靠重启进程恢复。
修法:探测名额改为 RAII 的ProbePermit,Drop时归还;探测已记入窗口则disarm
不再归还。归还用saturating_sub是承重的(探测 A 挂起 → 探测 B 失败重开 → 冷却期
Open → HalfOpen清零计数 → A 这时被取消,减在 0 上是可达的)。ecat-data-sqlx/ecat-data-mssql:四个ecat_rdbms_*同名家族互相顶掉
(5.0.0 已发布缺陷)。 两个 crate 的register_pool_metrics各建一份同名 collector,
而ecat-metrics的registry()是全进程一个:prometheus::Registry按名字去重,
后注册者整份被AlreadyReg吞掉 ⇒ 它的四个指标一条样本都不输出,无报错、无日志,
且单 crate 测试全绿(看不到另一个 crate 的注册)。
修法:collector 唯一化到ecat-metrics::register_rdbms_metrics,两个后端只挂数据源。
指标名、HELP 文本与标签语义一字未改;新增跨 crate 回归测试
(ecat-metrics/tests/rdbms_shared_families.rs,两个后端同进程时两族样本都在)。ecat-data-clickhouse:transaction()(硬编码「ClickHouse 不支持事务」)与_with
方法(落到SqlExecutor的 trait 默认实现)不进熔断器 —— 两者都不含任何 I/O,
包进去只会让「本就不支持的调用」被记成后端失败。加了两条把守测试防回归。
Known limitations
-
熔断没有总开关:
BreakerConfig只有阈值字段,没有enabled。要停用只能把阈值
调到不可能触发(如failure_ratio: 1.1)。配置教程已写明,别写{"enabled": false}
(那是反序列化错误)。 -
ecat-data-redis仍走MultiplexedConnection(多路复用),本版不换连接池 ——
超时 + 熔断下多路复用的边界见配置教程。 -
RedisLock的DistributedLock路径不在本版范围(用LockError,不共用本套映射)。 -
两个后端仍声明未使用的
prometheus直接依赖:ecat-data-sqlx与ecat-data-mssql的
Cargo.toml仍有prometheus = { version = "0.13", optional = true },metricsfeature 也仍写着
["dep:ecat-metrics", "dep:prometheus"]—— 但自本版起四个ecat_rdbms_*家族的 collector 搬到了
ecat-metrics,这两个 crate 已零 prometheus 引用。本版不删:feature 列表是对外可见的,
删它超出「换注册方式」的范围,留作后续清理。 -
README 的后端能力表未更新(本版只改了版本号):表里 ClickHouse / QuestDB 两行的
✅ 熔断仍指「可被CircuitBreakerExecutor包装」,而 ClickHouse 本版起已是内置;
配置字段表(ClickhouseConfig的base_url等)也还没列出三个新字段。
整体留给下一批与其余 10 个后端一并同步 —— 14 份手写镜像同步一次就够,不做两遍。
v5.0.0
⚠️ 破坏性变更
ecat-data:RdbmsError新增NoAvailableReplica变体。
副本全部熔断且RdbmsRouting::fallback_to_primary(false)时返回它。
该 enum 不是#[non_exhaustive],因此下游任何穷举match会编译失败 ——
这是本版进位主版本号的唯一理由。
(给它加#[non_exhaustive]降级不行:对已有的公开 enum 加该属性本身也是破坏性变更。)
Added
ecat-circuit-breaker抽出公开的熔断状态机(批次 5「14 个后端出站韧性」的前置):Breaker+BreakerConfig+BreakerState+BreakerErrorBreaker::state()—— 供调用方读熔断状态;含冷却期的Open → HalfOpen转换- 原 tower 的
CircuitBreakerLayer/CircuitBreakerService公开签名未变(内部改为委托Breaker),
12 个既有测试逐条保持全绿 - 该 crate 从单文件 546 行拆为 4 个文件(原文件已超项目 500 行约定)
ecat-data:CircuitBreakerExecutor<S>—— 给任意SqlExecutor逐端点包一层熔断。
熔断打开时内层一次都不被调用;dialect()不经熔断(纯本地判断)。ecat-data:RdbmsRouting—— 读写分离(写落主、读落从轮询、query_write落主、
事务落主且不经熔断),并跳过熔断打开的副本。
只做逐端点包熔断是不够的:从库挂掉后轮询仍会把 1/N 的读转过去靠熔断快速失败 ——
那不是故障隔离,是稳定的 1/N 失败率。fallback_to_primary控制副本全不可用时降级还是报错。ecat-data-sqlx/ecat-data-mssql:三个 opt-in feature(默认关闭,避免把 axum 拖进核心依赖树):metrics——register_pool_metrics(backend, pool),四个指标
(ecat_rdbms_pool_connections/_pool_timeouts_total/_query_timeout_total/
_transactions_leaked_total)。后两个接既有的进程级计数QUERY_TIMEOUTS/
TRANSACTIONS_LEAKED—— 把日志变成可告警的指标。health——RdbmsHealthCheck实现ecat_health::HealthCheck(池连通性SELECT 1)。tracing—— 超阈值 SQL 打 warn,阈值slow_query_ms可配;SQL 按字符截断
(不切半个 UTF-8),上限SQL_HEAD_CHARS = 200。
ecat(聚合入口):两个 opt-in featureorm/mssql,并补上对应重导出。
Fixed
ecat-circuit-breaker:state()此前不做冷却期转换 —— 而RdbmsRouting靠它跳过
Open的端点,于是被跳过的端点永远没人调call(转换在call里),
冷却期过后也不会被重新放行。后果不是「暂时少一个副本」,是任何失败过的副本被永久排除,
读能力单调缩水。现state()报告有效状态(冷却已过则报HalfOpen)。
Docs
- 修正多处文档与代码矛盾(均为既有问题,非本版引入):
- TLS 教程里的
tls: {} # 保留字段——SqlxConfig.tls实际是配了就报错
(批次 1 改的「响亮失败而非静默忽略」),照抄该 yaml 会启动失败。 - 「所有后端均支持
tls字段」—— 两处反例:ecat-data-sqlx配了报错、
ecat-data-memcached声明了但全 crate 无人读(静默无效)。 - 生态规划里「三项破坏性变更尚未发布;3.0.3 → 4.0.0」—— v4.0.0 / v4.1.0 均已发布。
- README 的 crate 数(51 → 56)、
README.en.md标题的后端数(18 → 19)、
多数据源列表补 SQL Server、目录树删除两个不存在的目录。 docs/i18n/{id,en,es,fr,ja,pt,ru}的目录树注释为中文残留 → 各语言译文
(4.1.0 新增的行本就已翻译,旧 56 行是半截翻译)。
- TLS 教程里的
- 新增
docs/social-preview.png(1280×640)。 - 12 语言 README / 生态规划 / 数据库配置教程同步更新。
Known limitations
ecat-data-memcached的tls字段是死字段:声明了但全 crate 无人读,配了静默无效。
与批次 1 修掉的SqlxConfig.tls同族,但改它是行为变更,留作独立任务。ecat-data-clickhouse(OLAP)未列入 README 的「多数据源」一行(表内有),既有遗漏。RdbmsRouting的内置Endpoint会在调用方已用CircuitBreakerExecutor包装端点时双重包装。
v4.1.0
Added
- 新 crate
ecat-orm+ecat-orm-derive(完整 ORM)。建立在 4.0.0 拆出的
SqlExecutor之上 —— 所有数据操作取&impl SqlExecutor,因此客户端与Transaction通吃。#[derive(Entity)]:表名/列/主键/标志位、from_row/to_values、关联与XxxRelation枚举、set_relation写回口- 方言层
DialectSpec:SQLite / PostgreSQL / MySQL / SQL Server / ANSI 五套纯函数 SQL 生成 - 查询构建器:类型状态
Unfiltered → Filtered(无过滤条件无法删改,编译期保证)+ 标识符白名单(未声明的列名不拼进 SQL) - CRUD(
insert/find_by_id/find_all/update/delete_by_id/hard_delete_by_id/save) - 批量分块:按各方言参数上限(SQLite 999 / SQL Server 2100 / 其余 65535)切分
- 分页(
Page<T>/paginate/paginate_without_count) - 关联预加载:一次
IN查询取回全部关联,杜绝 N+1(三种方向:has_many/has_one/belongs_to) - 自动行为:
created_at/updated_at填充、软删除、乐观锁(version冲突报OptimisticLockConflict) - 迁移系统:
Migrator(add/status/run/down)+ 实体工厂create_table::<E>()+ 版本表_ecat_migrations
ecat-data:SqlExecutor::execute_then_query(有默认实现,向后兼容)——
在同一条连接上原子地跑两条语句。Transaction覆写为「直接在自己身上跑」,
SqlxClient覆写为「开事务跑完提交」。这是「事务内 insert」能成立的前提
(MySQL 的LAST_INSERT_ID()是连接作用域的)。
Changed
ecat-data:DialectSpec::table_exists_sql改名create_table_prefix并改语义 ——
旧名承诺「一条语句」,但在 SQL Server 上返回空串,调用方照名字用会生成没有
CREATE TABLE关键字的非法 SQL。新名始终返回完整前缀(MSSQL 为CREATE TABLE [x]),
另加needs_exists_check_before_create()表达「建表前需先查存在性」。ecat-data:DialectSpec::limit_clause的limit参数改Option<u64>——
旧版用u64::MAX表示「未设置」,offset()不带limit()时会生成
LIMIT 18446744073709551615 OFFSET 20,超出 BIGINT、真库拒收。ecat-data/ecat-data-sqlx:find_by_id/find_all改走统一的查询构建器路径
(列清单、方言引号、占位符编号、软删除闸门全在一处,不另写第二条 SQL 生成路径)。
Known limitations
sqlite::memory:不支持跨连接事务场景:池只有一条被事务占住的连接,事务内第二条
语句会等到超时。需要多连接时用文件路径(sqlite:<path>?mode=rwc)。join的列清单不带表前缀:被连表与主体有同名列时真库报ambiguous column name。- 批量
update_many的乐观锁冲突无法定位到行:只能靠「返回行数 < 传入行数」察觉,
需要定位时用逐行update。 join的表名与 ON 条件不做白名单校验(join(table, on)收的是字符串,
字符串里没有类型信息);与filter_raw同一信任边界,文档已注明。
Tests
ecat-orm的 SQLite 全链路集成测试:实体定义 → 迁移建表 → CRUD → 关联预加载 →
分页 → 事务提交/回滚 → 软删除 → 乐观锁冲突,外加时间列无 CAST 往返
(断言在绑定参数上 —— SQLite 读路径会重新格式化偏移量文本,读回路断言是空的)。- 发布前
cargo test --workspace:1076 passed / 0 failed(4.0.0 时为 771)。
--doc有 4 条 doctest 实际执行(2 条compile_fail+ 2 条正向对照)——
编译期断言必须放在src/的非#[cfg(test)]位置:写在tests/*.rs里
rustdoc 不收,写在#[cfg(test)] mod里--doc编译时不开cfg(test),两处都不会执行。
v4.0.0
⚠️ 破坏性变更
ecat-data:RdbmsClient拆出SqlExecutorsupertrait。执行与方言能力
(execute/query/execute_with/query_with/query_write/dialect)
移入SqlExecutor,RdbmsClient只剩transaction()。直接实现过RdbmsClient
的下游会编译失败。仓库内 4 个实现者(SqlxClient/ClickhouseClient/
QuestdbClient/ 测试桩)已同步适配。ecat-data:TransactionInner签名扩张,Transaction现在实现SqlExecutor
—— 事务内可执行 SQL(此前只能commit/rollback)。
空事务(Transaction::new())执行 SQL 现在报错而非静默返回 0 行影响。ecat-data-sqlx:from_pool(AnyPool, Dialect)→from_pool(Pool),
并弃用AnyPool,改用 PG / MySQL / SQLite 三路原生池。ecat-data-sqlx:SqlxConfig.tls设了就报错(此前被 serde 接受但代码从不读,
是静默无效的配置项);TLS 请走 URL 参数(如?sslmode=require)。
Added
- 新数据后端
ecat-data-mssql(SQL Server) —— 数据后端从 15 个增至 16 个。
基于tiberius-ng0.13 +deadpool0.13,实现完整SqlExecutor+
RdbmsClient。支持 URL 形态(mssql://user:pass@host:1433/db,含
encrypt/trustservercertificate查询参数)与 ADO 形态
(Server=host,1433;Database=db;User Id=...)两种连接串。 ecat-data:Dialect枚举与Dialect::from_url(大小写与首尾空白/控制字符均容忍)。ecat-data:查询超时助手run_with_timeout,以及进程级超时计数
QUERY_TIMEOUTS/ 事务泄漏计数TRANSACTIONS_LEAKED。ecat-data-sqlx:连接池参数(max_connections/min_connections/
acquire_timeout_secs/idle_timeout_secs/max_lifetime_secs/
query_timeout_secs/test_before_acquire)与session_init
(会话初始化,默认按方言把库侧时区设为 UTC)、warm_up()预热。docker-compose.dev.yml:本地联调三库一键起(SQL Server 2022 / PostgreSQL 16 / MySQL 8.0),
不进 CI。
Fixed
ecat-data-sqlx:类型映射的 5 个静默错值(均由真库 A/B 实测发现)——
MySQLUNSIGNED整数此前在Bool/Null之间跳(BIGINT UNSIGNED正是最常见的自增主键)、
PGsmallint返回Null、bool分支抢走整数、NULL 无闸门(sqlite 下 NULL 会静默变false)、
OffsetDateTime的Display被误当作 RFC3339。未支持类型(numeric/uuid/jsonb等)
现在响亮报错(带列名与类型名)而非静默返回 null。ecat-data-sqlx:DATE输出纯YYYY-MM-DD,不伪造源数据里不存在的时刻与时区。ecat-data-sqlx:池默认值单一来源(pool()与PoolParams::default()此前会静默分叉);
connect()与from_config()的方言默认会话初始化此前不一致。ecat-data-mssql:idle_timeout_secs是空配置(deadpool 不提供空闲回收),已删除;
MssqlConfig加了deny_unknown_fields(拼错的键名此前被静默忽略)。ecat-data/ecat-data-sqlx/ecat-data-mssql:事务方法补上查询超时
(此前事务内挂死的查询会永久占住连接)。ecat-mq-nats:显式安装 rustls crypto provider。此前依赖「ring与aws-lc-rs
两个特性恰好启用一个」这一脆弱不变量 —— 任何引入第二个 provider 的依赖都会让它 panic
(且只在cargo test --workspace的特性合并下暴露)。全仓其余 4 处早已显式安装,
此处是唯一遗漏。ecat-data-clickhouse:建表缓存的 TTL 测试去掉时间依赖(5ms 余量导致 ~0.67% 概率假失败)。
Security
- 升级
h20.4.15 → 0.4.19(RUSTSEC-2026-0258)、rustls0.23.43 → 0.23.45
(RUSTSEC-2026-0285,5.3 medium)、chacha200.10.1 → 0.10.2(此前版本已 yanked),
连带rustls-webpki0.103.13 → 0.103.15。cargo audit --deny warnings闸门转绿。
Tests
ecat-data-sqlx/ecat-data-mssql:env 门控真库集成测试
(ECAT_TEST_PG_URL/ECAT_TEST_MYSQL_URL/ECAT_TEST_MSSQL_URL;
ECAT_REQUIRE_LIVE_DB=1让 CI 里「跳过即失败」)。三者与 SQLite 一起覆盖四类后端。- 真库用例做过三向验证:真 URL 通过 / 死端口必须失败(证明真在连库)/ 未设 URL 且
REQUIRE时 panic 并点名缺失键。 - 发布前
cargo test --workspace:771 passed / 0 failed / 0 panic(115 个测试二进制,
67 个套件)。跨 crate 特性合并是必需的一层 —— 本版ecat-mq-nats的 rustls provider
panic 只在这一层暴露,单 crate 跑 60 次全过。
v3.0.3
API 参考文档 docs/api.md:端口约定、/health /ready /metrics 内置端点、错误格式、GraphQL/OpenAPI/WebSocket/版本路由扩展接口
12 语言文档目录 docs/i18n/{en,ja,ko,ru,de,fr,es,pt,hi,ar,bn,id}/:全部 24 份文档翻译 + 3 张图片副本,README 顶部语言切换器互链
v3.0.2
v3.0.2: 审计修复全部落地 + 全面测试 + 文档水印 + 推送规则 修复(审计 8.17 backlog + 测试报告): - workspace: tokio minimal features、rustls-tls-no-provider、删死 crate(ecat-tracing-otlp/ecat-testing)、日志/追踪合并、lto=thin - auth: JWT key 一次构建、oauth2 1MiB+sub 必填、purge 阈值 - data: 6 单变体错误枚举统一 ecat-errors、8 crate 迁移、s3 默认 https、rdbms rollback 幂等 - security: MQ TLS/SASL 配置面(kafka/nats/mqtt/rabbitmq)、WS 大小可配、Consul 强制 https、client 不跟随重定向、413 语义、ratelimit proxy 头 opt-in - graphql: 查询复杂度限制(默认 10_000) - 测试报告修复: ecat-security URI 百分号解码防 SQLi 绕过、sqlx 驱动安装、influxdb 转义/排序、clickhouse 建表 TTL 测试:51 crate 全面单测 +206(675 全绿),报告 docs/test-report-2026-08-26.md 文档:README 版本/数量同步 3.0.2、CHANGELOG 3.0.2、图片加水印 erik.xyz 推送规则:scripts/release.sh(最新版本增量 bump → 提交推送 → tag,跳过打包)
v3.0.1
v3.0.1: 审计 5 项修复 + 版本同步 3.0.1(reviewer APPROVED) - ecat-mq-kafka auto_commit=true 消息丢失量化告警(break 前 warn 未消费条数) - ecat-data rdbms rollback 误报修复(rolled_back 标志) - OAuth2 内省 1MiB 有界读取 + sub 缺失/空拒绝 - [profile.release] lto="thin" - 补 FileSource::load() 4 测试 + circuit-breaker 状态机 2 测试 - 版本三处同步:Cargo.toml 16 处、Chart.yaml appVersion、CHANGELOG