dbnexus 0.3.1

An enterprise-grade database abstraction layer for Rust with built-in permission control and connection pooling
Documentation
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.3.0] - 2026-07-03

### ⚠️ BREAKING CHANGES

- **版本号升级**: workspace 版本号 `0.2.0 → 0.3.0`(含 `Cargo.toml` + `macros/Cargo.toml` + `examples/Cargo.toml`- **README 重命名**: `README.md → README_EN.md``README_zh.md → README.md`(中文为主 README)
- **编译期互斥规则修复**: `sqlite`/`postgres`/`mysql` 现在真正互斥(原规则允许同时启用,与文档"Must enable exactly one"矛盾)
- **`observability` 预设修正**: 从 `["metrics", "health-check"]` 改为 `["metrics", "health-check", "tracing"]`(与 README 描述一致)
- **`dbentity-v2-rewrite` 变更归档**: 88/88 任务完成,归档到 `openspec/changes/archive/`

### Added

#### 新特性

- **`duckdb` feature**: DuckDB OLAP 后端支持,基于 `duckdb` crate(同步)+ `tokio::task::spawn_blocking` 桥接,作为分析只读旁路接入(绕过 sea-orm,因 sea-orm 2.0.0-rc.37 不支持 DuckDB)
  - 新增 `DbConnection::DuckDb` 枚举变体
  - 新增 `DuckDbConnection` 连接包装器,支持 `execute()`/`query()` 异步接口
  - `DatabaseType::DuckDb` 支持 `duckdb:` URL 前缀解析
- **`tracing` feature**: OpenTelemetry 分布式追踪,基于 `tracing` + `tracing-opentelemetry` + `opentelemetry-otlp`
  - 新增 `TracingGuard::init_with_otlp()` API
  - 集成 `tracing` 模块导出
- **结构化错误报告**: `QueryErrorReport` 按"权限不足/注入风险/语法错误/分片冲突"分类,含修复建议
- **连接串智能解析**: 用 `url` crate 替代 `starts_with("sqlite:")` 硬编码前缀匹配,支持标准 URI 格式
- **权限缓存 TTL + 动态热加载**: `PermissionCache` 新增 `expire_after` + 后台异步刷新任务
- **分片路由集成 Session**: `pool.get_session_for_shard(key, role)` 自动路由到对应分片

#### 工程化护栏

- `.github/dependabot.yml`: cargo + github-actions 依赖自动更新 PR
- `.github/codeql.yml`: 语义级安全扫描工作流
- `.editorconfig`: 跨编辑器一致性(Rust 4 空格缩进、UTF-8、LF 换行)
- `.pre-commit-config.yaml`: 集成 cargo-fmt / cargo-clippy / cargo-deny Rust 专有 hook

#### 测试覆盖

- `tests/authentication/`: AuthenticationManager/JwtManager/PasswordHasher 外部测试
- `tests/security/sensitive_masker_tests.rs`: SensitiveMasker/MaskType 外部测试(含 Unicode 安全测试)
- `tests/kit/kit_integration_tests.rs`: DbNexusKit 外部测试
- `benches/permission_engine_bench.rs`: 权限引擎基准测试
- `benches/sharding_bench.rs`: 分片路由基准测试
- `benches/metrics_bench.rs`: 指标收集基准测试

### Changed

- **`cache` feature 描述修正**: 从 "LRU" 改为 "oxcache(内部 moka L1 后端)"
- **协议兼容数据库文档化**: CockroachDB/YugabyteDB/TiDB/MariaDB/Aurora 无需代码改动即可使用,在 README 中明确说明

### Performance

- **DuckDB 连接池化**: 替换 DuckDB 单一 Mutex 为连接池(`DuckDbConnection`),支持 `with_pool_size(url, pool_size)` 并发查询
- **Session 短锁模式**: 避免 `Session` 持锁期间执行 async DB 调用,降低锁竞争
- **MetricsCollector 原子化**: 移除不必要的 `RwLock`,改用原子操作释放性能
- **SqlParser 全局共享单例**: `SqlParser::shared().await` 返回 `Arc<SqlParser>`,避免重复创建解析器实例

### Fixed

#### 正确性修复(diting 审查)

- **`mask_email` UTF-8 字节切片 panic**: 非 ASCII 本地部分(中文/emoji)按字节切片会 panic,改用 `chars()` 安全处理
- **`ShardRouter::default()` 除零 panic**: 默认 `total_shards=0` 导致 `% total_shards` 除零,改为 `total_shards=1`(单一分片语义)+ 防御性检查
- **`shard_id_for_key` 哈希器误用**: `shard_key.hash(&hasher)` 应为 `&mut hasher`(预存编译错误)
- **DuckDB `permit` 提前 drop**: `execute()`/`query()` 中 permit 在 `handle.await` 前 drop,信号量在 spawn_blocking 任务完成前释放,失去并发限制作用
- **`warmup_connections` 静默丢弃失败**: 全部失败时仍返回 `Ok(())`,改为全部失败返回 `Err` + 部分失败 warn 日志(规则 12)
- **`validate_role_name` 静默 fail-open**: 无权限配置时静默使用安全默认策略,添加 warn 日志显性化(规则 12,CRITICAL 风险保守修复)

#### 安全修复(diting 审查)

- **`verify_token` 不校验 `token_type`**: refresh token 可用作 access token(权限提升风险),新增 `verify_access_token`/`verify_refresh_token` 方法额外校验 `token_type`
- **`add_user` 无法验证密码强度**: 接收已哈希 `password_hash`,新增 `register_user(username, password, role)` 方法执行 `validate_strength → hash → insert` 完整流程

#### 安全审查修复(tiangang SAST + diting 6 CRITICAL/5 HIGH)

- **DuckDB SQL 注入防护**: `execute_duckdb_raw` 添加 admin role + DdlGuard AST 验证(对齐 `execute_raw_ddl` 行为),非 admin role 拒绝 DDL
- **令牌桶竞态修复**: RateLimiter 内部状态更新改为原子操作
- **`try_from` panic 修复**: `DbPool::try_from``permission` feature 启用时返回错误而非 panic
- **singleflight 违约修复**: 权限缓存 singleflight 协调逻辑修正
- **`eprintln!` 替换**: 所有 `eprintln!` 替换为 `tracing::warn!`/`tracing::error!`
- **`sql-parser` 依赖加固**: 显式声明 sql-parser 依赖防止权限绕过
- **假 DI setter 修复**: 移除误导性的依赖注入 setter
- **`Engine*` 双重导出修复**: 消除类型重复导出
- **`impl_` 目录清理**: 移除空实现目录
- **冗余预加载移除**: 优化启动时无用的预加载逻辑
- **`deny.toml` 添加 RUSTSEC-2023-0071**: 安全公告加入 cargo-deny 策略

#### 最终回归修复(T024)

- **DuckDB DDL 设计 bug**: `execute_duckdb_raw` 文档声明支持 DDL 但代码无条件拒绝,修复为 admin role + DdlGuard AST 验证后执行(对齐 `execute_raw_ddl`- **DuckDB 健康检查查询失败**: `SELECT 1 AS health``parse_operation_async` 返回 `Ok(None)` 被拒绝,修复为 admin role 允许执行(对齐 `execute` 的 None 路径)
- **`sqlite3://` scheme 缺失**: `DatabaseType::from_url` 不支持 `sqlite3://` 格式,添加支持
- **sharding flaky test 修复**: `test_shard_router_key_consistency` 假设两个特定 key 必映射不同 shard(10% 碰撞概率),改为验证确定性属性 + 统计分布属性

### Maintenance(v0.3.0 发版前加固)

#### 依赖升级(9 个 Cargo 依赖)

- **sqlparser**: 0.47 → 0.62(破坏性 API:`Statement` 枚举变体改为元组结构体,更新 `classify_statement``statement_type_name` 的模式匹配)
- **opentelemetry**: 0.27 → 0.32(`TracerProvider`/`Span` 等 API 重构)
- **opentelemetry_sdk**: 0.27 → 0.32
- **opentelemetry-otlp**: 0.27 → 0.32
- **tracing-opentelemetry**: 0.28 → 0.33
- **criterion**: 0.5 → 0.8(修复 `BenchmarkGroup` deprecation)
- **toml**: 1.0 → 1.1
- **parking_lot**: 0.12 patch 升级
- **url**: 2.5 patch 升级

#### CI 加固(9 个 GitHub Actions 升级 + 2 个不存在 action 修复)

- **actions/checkout**: v4 → v7(5 处)
- **actions/cache**: v4 → v6(3 处)
- **codecov/codecov-action**: v4 → v7
- **github/codeql-action/init**: v3 → v4
- **github/codeql-action/analyze**: v3 → v4
- **softprops/action-gh-release**: v2 → v3(2 处)
- **swatinmurthy/cache-for-rust@v1****Swatinem/rust-cache@v2**(4 处,原 action 仓库不存在,GitHub API 返回 404)
- **actions/attest-release-assets@v1****actions/attest-build-provenance@v3**(原 action 不存在,GitHub API 返回 404)
- **Swatinem/rust-cache 参数修复**: 移除不支持的 `path`/`restore-keys` 参数,改用 `shared-key` 区分缓存命名空间

#### CI 验证规则增强

- **clippy `--all-features` 修复**: lint job 缺少 `--all-features` 参数,feature-gated 代码从未被 lint
- **cargo doc check 新增**: lint job 新增 `cargo doc --all-features --no-deps --workspace`,提前捕获 rustdoc 警告

#### 文档警告修复(28 个 rustdoc 警告)

- **`src/domain/migration/converter.rs`**: 28 个 "unclosed HTML tag" 警告修复。markdown 表格中的泛型类型(如 `Option<TableRef>``Vec<ColumnDef>``Char(Option<u32>)`)未用反引号包裹,rustdoc 误判为 HTML 标签起始。全部加反引号包裹。

## [0.2.0] - 2026-06-27

### ⚠️ BREAKING CHANGES - ALL USERS MUST UPDATE

This is a **major breaking change** that affects **100% of users**. There is **NO backward compatibility** and **NO automatic migration path**.

#### Core Changes

- **Removed from default features**: `cache` is no longer enabled by default
- **Feature dependencies**: `permission`, `permission-engine`, and `sql-parser` now **require** `cache` feature
- **Compilation failure**: Code will not compile without correct feature flags
- **`foundation::pool` deprecated**: All database operations must use `database::pool` for Session management
- **Legacy `db_crud` macro removed**: Replaced by the unified `#[db_entity]` macro with explicit `primary_key` specification

#### Required Action for All Users

**Before (v0.1.x):**
```toml
dbnexus = "0.1"
# or
dbnexus = { version = "0.1", features = ["postgres"] }
```

**After (v0.2.0) - Choose ONE:**

```toml
# Option 1: Use presets (RECOMMENDED)
dbnexus = { version = "0.2", features = ["microservice"] }

# Option 2: Explicit features
dbnexus = { version = "0.2", features = [
    "postgres",
    "permission",
    "cache",
    "observability"
] }

# Option 3: Ultra-minimal (embedded)
dbnexus = { version = "0.2", features = ["embedded"] }
```

### Removed

- **`confers` configuration framework**: Removed the optional `confers` dependency and the `confers` feature flag entirely. The project now relies on `serde` / `serde_yaml_ng` / `serde_json` for direct deserialization.
  - Removed `confers = ["dep:confers"]` feature and the `confers` path dependency from `Cargo.toml`.
  - Removed `confers/yaml` and `confers/json` from the `config-yaml` feature; the `yaml` feature now drives YAML support directly.
  - Removed `confers/yaml` from the `permission-engine` feature.
  - Removed `confers` from the `required-features` of the `core_session_transaction` and `cross_cutting_benchmarks` test targets.
  - Removed `CacheConfig::from_confers`, `DbConfig::from_confers`, and `PermissionConfig::from_confers`.
  - Added `CacheConfig::from_yaml_str` / `CacheConfig::from_json_value`, `DbConfig::from_yaml_str` / `DbConfig::from_json_str`, and `PermissionConfig::from_yaml_str` / `PermissionConfig::from_json_str` as serde-based replacements.
  - Removed `#[cfg(feature = "confers")]` gates from `DbPool::load_permission_config` / `parse_permission_yaml` / `parse_permission_json`, `YamlPermissionProvider::new` / `parse_yaml_content` / `refresh`, `parse_permission_yaml_async`, and `permission_engine::YamlPermissionProvider::load_config`. The corresponding `#[cfg(not(feature = "confers"))]` Err branches were deleted.
  - Deleted `tests/confers_oxcache_integration.rs` (all tests were `#[ignore]`d and referenced an unimplemented `with_confers()` method).
  - Updated `enterprise` preset to no longer include `confers`.

- **`foundation::pool`**: Deprecated; all database operations must use `database::pool` for Session management.

- **Legacy `db_crud` macro**: Removed; replaced by the unified `#[db_entity]` macro with explicit `primary_key` specification.

- **`minimal` preset**: Replaced by `embedded` (different feature set).

- **Implicit cache dependency**: Cache is now optional and must be explicitly enabled.

- **Fallback behaviors**: No fallback or no-op implementations — compilation fails if required features are missing.

### Added

- **`#[db_entity]` unified macro** (`macros`): Single attribute macro replacing 5 separate macros (`db_entity`, `db_crud`, `db_audit`, `db_cache`, soft_delete). Supports `table_name`, `primary_key`, `timestamps`, `soft_delete`, `validate`, `hooks(...)` parameters.
  - **`schema(backend)`**: Generates `migration::schema::Table` from Entity via `sea_orm::Schema::create_table_from_entity` with custom converter.
  - **`query(session)`**: Returns Sea-ORM native `Select<E>` for chaining `filter/order_by/limit`.
  - **`paginate(session, page_size)`**: Returns Sea-ORM paginator with `num_items/num_pages/fetch_page`.
  - **`insert_many(session, models)`**: Batch insert returning `InsertResult` with `last_insert_id`.
  - **`update_many(session, filter, updates)`**: Conditional batch update returning affected row count.
  - **`find_with_deleted(session)`**: Find including soft-deleted records.
  - **`find_only_deleted(session)`**: Find only soft-deleted records.
  - **`force_delete(session, id)`**: Hard delete bypassing soft delete.
  - **`timestamps = true`**: Auto-manages `created_at` / `updated_at` via `ActiveModelBehavior::before_save` — insert sets both, update sets only `updated_at`.
  - **`validate`**: Integrates `validator` crate with `#[derive(Validate)]` and field-level `#[validate(...)]` attributes. Validation runs before timestamps in `before_save`.
  - **`hooks(...)`**: 6 event hooks — `before_insert`/`after_insert`/`before_update`/`after_update`/`before_delete`/`after_delete`. Hook orchestration order: `validate → timestamps → user_hooks` (any failure short-circuits).
  - **`soft_delete = true`**: Rewrites `find*` and `delete` semantics to auto-filter/set `deleted_at` column. Auto-injects `deleted_at: Option<time::OffsetDateTime>` field.

- **`with-time` feature**: Enables `sea-orm/with-time` dependency for `OffsetDateTime` timestamp support. Included in default features.

- **`validation` feature**: Gates `validator` crate with `features = ["derive"]` for `#[derive(Validate)]` macro support.

- **New combined features**:
  - **`cache`**: Independent cache feature (was implicitly enabled, now explicit)
  - **`observability`**: Combined feature for metrics + tracing + health-check
  - **`data-management`**: Combined feature for migration + auto-migrate + sharding + global-index
  - **`security`**: Combined feature for audit + permission-engine
  - **`bench`**: Performance testing dependencies (criterion)
  - **`test-utils`**: Testing utilities (tempfile, assert_cmd)

- **New presets**:
  - **`embedded`**: Ultra-minimal (runtime-tokio-rustls, sqlite, config-env) for embedded/edge devices
  - **`microservice`**: Optimized for microservice deployment (postgres, permission, sql-parser, config-env, observability)
  - **`monolith`**: Complete for monolithic applications (postgres, permission, sql-parser, config-yaml, data-management, security, observability)
  - **`enterprise`**: Full enterprise features (postgres + monolith + permission-engine)

- **Cache stampede protection** (`permission`): `PermissionContext` now uses singleflight request coalescing to prevent thundering herd when multiple requests hit an uncached role simultaneously. Concurrent cache-miss requests are collapsed into a single load; followers wait for the leader's result. A `stampede_events` counter tracks how many times coalescing occurred. New `get_cache_metrics()` method returns `(hit_rate, miss_count, stampede_count, cache_size)`.

- **Connection pool alerting** (`pool`): `acquire_connection` now tracks `wait_count` (current waiters) and `max_waiters` (historical peak) with CAS-safe updates. Timeout paths trigger tiered log alerts: warn ≥3s, error ≥5s, critical ≥10s.

- **Acquire duration histogram** (`metrics` feature): `MetricsCollector` now records `connection_acquire_duration` histograms with 100ms/500ms/1s/3s/5s/10s buckets. Slow acquires (>1s) increment `slow_acquires` counter. Timeout events are classified by level and counted separately.

- **Prometheus metrics export** (`metrics` feature): `MetricsCollector` now exports Prometheus-format metrics via `to_prometheus()`:
  - `dbnexus_pool_connections_total / active / idle` (gauges)
  - `dbnexus_connection_acquire_slow_total` (counter)
  - `dbnexus_connection_timeout_total{level="warn|error|critical"}` (counter)
  - `dbnexus_pool_acquire_duration_seconds` (histogram)

- **Rate limiter burst capacity**: `RateLimiter::new()` now accepts a `burst_capacity: u32` parameter (default = `max_requests`) to allow initial token count to exceed the steady-state refill rate. New `update_config(max_requests, window_duration)` method for runtime reconfiguration. New `with_defaults(max_requests, window_duration, max_buckets)` convenience constructor.

### Changed

- **Performance**: All metrics recording in `acquire_connection` is gated behind `#[cfg(feature = "metrics")]` — zero overhead when the feature is disabled.

- **Macro validation logic**: Fixed bug where `validate` + `timestamps = true` combination destroyed `ActiveValue::Set` state during `before_save`. Validation now clones `ActiveModel` for read-only validation, preserving original `Set/Unchanged/NotSet` states so UPDATE operations correctly persist changed fields.

- **Sea-ORM 2.0 `ActiveModelBehavior` signatures**: `after_save` receives `Model` (not `ActiveModel`); `after_delete` takes `self` by value and returns `Result<Self, DbErr>`.

- **Hook function signatures**: `before_*` must be `fn(&mut ActiveModel) -> Result<(), E>`, `after_*` must be `fn(&Model) -> Result<(), E>`.

- **Feature reorganization**:
  - **`permission`**: Now requires `cache` feature
  - **`sql-parser`**: Now requires `cache` feature
  - **`permission-engine`**: Now requires `cache` feature
  - **`minimal` preset**: Removed and replaced with `embedded` (truly minimal, no caching)

- **Dependency updates**:
  - **`oxcache`**: Changed to optional dependency (was required)
  - **`regex`**: Removed duplicate declarations across features
  - **`once_cell`**: Removed duplicate declarations across features

### Migration Guide

#### Step 1: Update Version

```toml
# In your Cargo.toml
[dependencies]
dbnexus = "0.2"  # Update from 0.1.x
```

#### Step 2: Choose a Configuration

**For most users:**
```toml
dbnexus = { version = "0.2", features = ["microservice"] }
```

**For embedded/edge devices:**
```toml
dbnexus = { version = "0.2", features = ["embedded"] }
```

**For full enterprise features:**
```toml
dbnexus = { version = "0.2", features = ["enterprise"] }
```

**For custom configuration:**
```toml
dbnexus = { version = "0.2", features = [
    "postgres",     # or mysql/sqlite
    "permission",    # requires cache
    "cache",         # REQUIRED by permission
    "observability"
] }
```

#### Step 3: Build and Test

```bash
cargo clean
cargo build
# If you get compilation errors about missing features,
# add the required features to your Cargo.toml
```

### Important Notes

- **No automatic migration**: You must manually update Cargo.toml
- **No compatibility layers**: v0.1.x and v0.2.0 are completely incompatible
- **Feature combinations**: Ensure `cache` is enabled if using `permission`, `permission-engine`, or `sql-parser`
- **Compilation errors**: If compilation fails, the error message will indicate which feature is required

### Performance Impact

**Without cache feature:**
- Binary size: Reduced by 5-10%
- Compile time: Reduced by 15-20%
- Runtime performance: May be significantly slower (100x for permission checks, 10x for SQL parsing)

**Recommendation**: Enable `cache` feature for production use unless targeting embedded devices.

## [0.1.2] - Previous Release

### Features
- Connection pooling with RAII lifecycle management
- Permission control (RBAC)
- Procedural macros for CRUD and permission checks
- SQL parser
- Transaction support
- Multi-database support (SQLite, PostgreSQL, MySQL)
- Enterprise features (metrics, tracing, audit, migration, sharding, etc.)

### Known Issues
- Cache feature was implicitly enabled, could not be disabled
- Documentation inconsistencies with Cargo.toml
- No practical presets for common use cases