sql-middleware 0.7.0

Lightweight async wrappers for tokio-postgres, rusqlite, turso, and tiberius.
Documentation
# Simulator crate design

Goal: add a `simulator` bin crate in the workspace (outside `src/`) to stress sql-middleware with deterministic, reproducible scenarios. Start with SQLite; make it extensible to other backends.

## Crate shape
- New workspace member `simulator/` (bin).
- Depends on `sql-middleware` via path. Own dev-only deps: `rand`/`fastrand`, `clap` for flags, `serde` for config, `tracing`/`tracing-subscriber` for logging, maybe `proptest` strategies for workloads.
- Entry: `cargo run -p simulator -- --backend sqlite --duration 60s --seed 123 --log out.log`.

## Core components
- **Fake clock**: single-threaded executor with a controllable “now”. Timers use the fake clock so interleavings are deterministic. Provides `sleep(duration)` that advances the clock and schedules wakes in a deterministic order.
- **Backend shims**:
  - For SQLite, replace the worker handle with a fake that models states (`Idle`, `InTx`, `Busy`, `Broken`) and can inject outcomes: ok, `SQLITE_BUSY`, I/O error, panic, slow execution.
  - Pluggable fault injectors: drop requests, reorder, delay, partial success, forced busy on rollback/commit, panic in worker.
  - Surface the same API shape the middleware expects so we can slot it behind feature flags or a test-only build of the simulator.
- **Scheduler/executor**: runs tasks (simulated clients) cooperatively; keeps a queue of ready tasks and timers; uses seeded RNG for event ordering (e.g., which task runs next when multiple are ready).
- **Workload generator**: produces sequences of operations per task:
  - Pool checkout/return, begin/commit/rollback, drop-in-scope, execute_batch/select, cancellations/timeouts, schema changes.
  - Parameters: pool size, number of tasks, op mix ratios, max in-flight transactions, DDL toggle, forced busy/error rates.
  - Seeds for reproducibility; ability to dump the seed and workload plan.
- **Correctness oracle**:
  - Shadow model of connection state: whether a pooled conn is idle/in_tx/broken/checked out.
  - Invariants: no checked-out broken conns, transactions end in a terminal state, rollback/commit errors mark broken as expected, pool slot ownership rules, no double-checkout.
  - After each op, compare implementation-observed state to model; assert on mismatch and emit a minimal trace.
- **Output/logging**:
  - Stream events to stdout with optional file sink.
  - Include seed, workload config, first N steps, failure trace (last M events), and oracle state diff.
  - Exit non-zero on invariant violation.

## Configuration / modes
- Flags: `--backend sqlite|postgres|...`, `--duration`, `--iterations` (alt to duration), `--seed`, `--pool-size`, `--tasks`, `--ddl-rate`, `--busy-rate`, `--panic-rate`, `--log`, `--quick` (prebaked short config), `--stress` (long-run defaults).
- Determinism: only RNG and scheduler order depend on seed; no wall-clock use.

## Integration approach
- Keep the simulator isolated; no changes to `src/` except optional feature-gated hooks if needed to swap the SQLite worker for a shim. Prefer to keep shims entirely inside the simulator crate and use the public API.
- CI: optional job running `--quick --iterations 10_000`; longer `--stress` for local/overnight runs.

## Extensions
- Add shims for other backends (network error injection, server-side aborts).
- Add metrics (counts of broken conns, max wait time) for trend tracking.
- Add replay file support: save a failing trace/seed and replay it exactly.