diff --git a/CLAUDE.md b/CLAUDE.md index d51dedc3..c267348a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,7 +78,7 @@ Hexagonal / Clean Architecture with four layers. Dependencies point inward only. - **DI via `AppState`**: All services are `Arc`-wrapped and assembled in `common/di.rs`. `AppState` is wrapped in `Arc` and passed as Axum state. Many services are `Option>` because they depend on features being enabled (auth, WOPI, trash, etc.). -- **Content-addressable storage**: Files use SHA-256 blob dedup. `storage.file_blobs` stores content; `storage.file_metadata` references blobs with ref-counting. See `file_blob_write_repository.rs` and `file_blob_read_repository.rs`. +- **Content-addressable storage**: Files use BLAKE3 blob dedup. `storage.file_blobs` stores content; `storage.file_metadata` references blobs with ref-counting. See `file_blob_write_repository.rs` and `file_blob_read_repository.rs`. - **ltree paths**: Folder hierarchy uses PostgreSQL `ltree` for efficient subtree queries (recursive copies, moves, searches). diff --git a/docs/architecture/caching.md b/docs/architecture/caching.md index be1776cc..ed93aae6 100644 --- a/docs/architecture/caching.md +++ b/docs/architecture/caching.md @@ -10,7 +10,7 @@ OxiCloud uses **moka** (a lock-free, concurrent cache) for write-behind caching | Directory listings | 120 s | 10 000 | Frequently accessed folder contents | | Thumbnail cache | configurable | 1 000 | Generated WebP/AVIF thumbnails | | Image transcode | configurable | 500 | On-the-fly image transcoding results | -| Blob hash | 30 s TTI | 5 000 | SHA-256 hashes for dedup lookups | +| Blob hash | 30 s TTI | 5 000 | BLAKE3 hashes for dedup lookups | | Audio metadata | — | 2 000 | ID3 tags and duration | ## How It Works diff --git a/docs/guide/index.md b/docs/guide/index.md index 25fd1e0e..15127f77 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -14,7 +14,7 @@ NextCloud was too slow on a home server. So OxiCloud was built to run on minimal | **Cold start** | < 1 s | 5–15 s | | **CPU at idle** | ~0 % | 1–5 % (cron, background jobs) | | **Min. hardware** | 1 vCPU / 512 MB RAM | 2 vCPU / 2 GB RAM | -| **File dedup** | SHA-256 content-addressable | None | +| **File dedup** | BLAKE3 content-addressable | None | | **Dependencies** | Single binary + PostgreSQL | PHP, Apache/Nginx, Redis, Cron, … | | **WebDAV** | Built-in (RFC 4918) | Built-in | | **CalDAV / CardDAV** | Built-in | Via apps | @@ -28,7 +28,7 @@ NextCloud was too slow on a home server. So OxiCloud was built to run on minimal ### Storage & Files - Drag-and-drop upload, multi-file, grid & list views - Chunked uploads (TUS-like, parallel, resumable, MD5 integrity) -- SHA-256 content-addressable file deduplication with ref-counting +- BLAKE3 content-addressable file deduplication with ref-counting - Adaptive compression (zstd / gzip per MIME type) - Trash bin with soft-delete and auto-purge - Favourites, recent files, full-text search diff --git a/docs/index.md b/docs/index.md index e65f730c..b7889a62 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,7 +25,7 @@ features: details: Single Rust binary, ~40 MB Docker image, <1s cold start, 30–50 MB idle RAM. - icon: 📁 title: Full File Management - details: Chunked uploads, SHA-256 deduplication, trash, favourites, full-text search, thumbnails. + details: Chunked uploads, BLAKE3 deduplication, trash, favourites, full-text search, thumbnails. - icon: 🔗 title: WebDAV / CalDAV / CardDAV details: RFC-compliant protocols for files, calendars, and contacts. Works with all major clients. diff --git a/src/interfaces/api/handlers/dedup_handler.rs b/src/interfaces/api/handlers/dedup_handler.rs index 97dbfa6c..9ed5b746 100644 --- a/src/interfaces/api/handlers/dedup_handler.rs +++ b/src/interfaces/api/handlers/dedup_handler.rs @@ -21,7 +21,7 @@ type GlobalState = Arc; pub struct HashCheckResponse { /// Whether a blob with this hash already exists pub exists: bool, - /// The SHA-256 hash that was checked + /// The BLAKE3 hash that was checked pub hash: String, /// If exists, the size of the existing blob #[serde(skip_serializing_if = "Option::is_none")] @@ -36,7 +36,7 @@ pub struct HashCheckResponse { pub struct DedupUploadResponse { /// Whether this was a new file or an existing one pub is_new: bool, - /// The SHA-256 hash of the content + /// The BLAKE3 hash of the content pub hash: String, /// The size of the content in bytes pub size: u64, @@ -95,13 +95,13 @@ impl DedupHandler { ) -> impl IntoResponse { let dedup = &state.core.dedup_service; - // Validate hash format (SHA-256 = 64 hex chars) + // Validate hash format (BLAKE3 = 64 hex chars) if hash.len() != 64 || !hash.chars().all(|c| c.is_ascii_hexdigit()) { return Response::builder() .status(StatusCode::BAD_REQUEST) .header(header::CONTENT_TYPE, "application/json") .body(Body::from( - r#"{"error": "Invalid hash format. Expected SHA-256 (64 hex characters)"}"#, + r#"{"error": "Invalid hash format. Expected BLAKE3 (64 hex characters)"}"#, )) .unwrap() .into_response(); @@ -508,7 +508,7 @@ impl DedupHandler { get, path = "/api/dedup/check/{hash}", params( - ("hash" = String, Path, description = "SHA-256 hash (64 hex characters)"), + ("hash" = String, Path, description = "BLAKE3 hash (64 hex characters)"), ), responses( (status = 200, description = "Hash check result (user-scoped)", body = HashCheckResponse), @@ -564,7 +564,7 @@ pub async fn get_stats(state: State, auth_user: AuthUser) -> impl I get, path = "/api/dedup/blob/{hash}", params( - ("hash" = String, Path, description = "SHA-256 hash of the blob (64 hex characters)"), + ("hash" = String, Path, description = "BLAKE3 hash of the blob (64 hex characters)"), ), responses( (status = 200, description = "Raw blob content (user-scoped)"),