RustBox 0.2.2 release manifest Architecture: - database_backend = sqlite | mysql | pgsql selects authoritative SQL only - blob storage and search are independent from the SQL engine - PostgreSQL/MySQL single-node deployments may continue to use data_dir-backed filesystem/Tantivy - cluster mode clears an implicit/default data_dir; explicit data_dir is not forbidden, but local-only capabilities are rejected Blob storage: - filesystem: local single-node or shared POSIX with storage.shared=true - shared POSIX examples: NFS, CephFS, GlusterFS - s3: AWS S3 and S3-compatible endpoints such as MinIO/Ceph RGW - attachment rows use logical storage keys and SHA-256 metadata - storage migration command: rustbox storage migrate --from filesystem:/path --to configured [--dry-run] [--verify] Search: - local_tantivy: single-node only - opensearch: cluster-capable external index - disabled: no full-text index - OpenSearch operations are tenant-scoped by user_hash - durable SQL outbox provides claim/lease, retry/backoff and dead-letter handling - rebuild command: rustbox search reindex Database/schema: - migrations/{sqlite,mysql,pgsql}/schema.sql contain the current fresh schema - compatibility baseline remains V046 - runtime migration V047 adds attachment checksum metadata and search_outbox - next migration number: V048 PostgreSQL message mutation fix (0.2.2): - header_sync_generation UPSERT qualifies the current tenant user_meta.value on the UPDATE RHS - this prevents PostgreSQL from treating `value` as ambiguous during ON CONFLICT DO UPDATE - SQLite/MySQL equivalents were reviewed and require no matching SQL change - no schema migration is required PostgreSQL startup compile fix (0.2.2): - multi-statement global schema DDL uses `sqlx::Executor::execute()` on the transaction connection - avoids SQLx raw_sql mutable-connection lifetime inference failures (`Executor is not general enough`) - retains the startup transaction and `SET LOCAL client_min_messages TO WARNING` - no schema migration is required Database/session startup (0.2.2): - db::pool::configure() is the single owner of global schema initialization - database-backed session persistence does not execute schema.sql a second time - the fix applies uniformly to SQLite, MySQL and PostgreSQL - PostgreSQL expected IF NOT EXISTS notices are suppressed only inside the startup DDL transaction - no SQL migration is required; runtime schema remains V047 SQLite test isolation (0.2.2): - test builds initialize each requested SQLite database but do not publish a TempDir-backed path into the process-wide database OnceLock - account/database tests therefore remain isolated when Rust runs them in parallel - a regression test covers deleting the first TempDir before opening a second test database Docker examples: - docker/compose-single-sqlite.yml - docker/compose-postgres-s3-opensearch.yml (PostgreSQL + SILO/S3 + OpenSearch) - docker/compose-mysql-nfs-opensearch.yml (MySQL + real NFS volume + OpenSearch) Operations/docs: - README.md documents 0.2.2 storage/search configuration - docker/README.md documents Compose variants - docs/STORAGE_SEARCH_OPERATIONS.md documents failure modes, shared-storage requirements and migration behavior - TODO.md leaves live SILO/MinIO/AWS/Ceph and real multi-node acceptance validation explicitly pending Build/release metadata: - `scripts/package-release.sh` runs the full Rust release gate before creating ZIP/SHA256 artifacts - Cargo.toml version = 0.2.2 - rust-toolchain.toml pins Rust 1.88.0 - Cargo.lock is intentionally not shipped because this environment could not regenerate it after dependency changes - CI and scripts/build-release.sh generate Cargo.lock, then run locked tests/Clippy/release build