OptimizedFileContent::Mmap was constructed nowhere — the documented "Tier 2:
memory-mapped I/O (10-100 MB)" path was never wired, so optimized_inner only
ever returns Bytes (<10 MB) or Stream (>=10 MB). The variant survived only as
an enum case plus two dead match arms in the file and share download handlers.
Remove the variant and its arms, and fix the now-misleading retrieval-service
tier docs (everything >=10 MB streams via CDC chunk reassembly with the
backend read-ahead; there is no mmap tier). Behaviour is unchanged — the
deleted arms were unreachable.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5yYZ9s868mJwqT2Qz7ez
Five new public endpoints under /api/s/{token}/...:
GET /contents
GET /contents/{folder_id}
GET /file/{file_id}
GET /zip
GET /zip/{folder_id}
All honour the unlock cookie from /verify, so password-protected
folder shares work end-to-end.
Folder/file IDs are validated against the share subtree via a single
ltree containment query (O(log N) on the existing GiST index).
Out-of-scope IDs return 404.
download_shared_file refactored to a Range/304/206/416-aware
serve_share_file helper, shared with the new /file/{file_id}
endpoint. content_disposition extracted from FileHandler so RFC 5987
formatting is identical across auth and share download paths.
After successful POST /api/s/{token}/verify, the server issues a
short-lived signed JWT cookie (oxi_share_unlock_<token>; HttpOnly;
SameSite=Lax; 1h TTL). Subsequent /api/s/{token} and
/api/s/{token}/download requests honour the cookie to bypass the
password gate, so password-protected file downloads work end-to-end.
- New module src/infrastructure/services/share_unlock_cookie.rs:
issue_jwt, verify_jwt, extract_from_cookie_header, build_set_cookie
+ 10 unit tests.
- New ShareService methods issue_unlock_jwt and
get_shared_link_with_unlock; trait method get_shared_link_by_token
delegates to a private fetch_share_resolved with an
allow_password_protected flag.
- access_shared_item, verify_shared_item_password, and
download_shared_file honour the unlock cookie.
Reuses OXICLOUD_JWT_SECRET, no new env var. Auth-token JWTs and
unlock-cookie JWTs cannot be confused: auth requires
username/email/role/jti claims, unlock has only sub/exp/iat.
Cross-share replay rejected via claims.sub == requested_token check.
Share links now point to /s/{token} (was /api/s/{token}) and render a
proper HTML page instead of raw JSON.
Changes:
- static/share.html: standalone public share page
- static/css/views/share-public.css: share page styles
- static/js/views/public/publicShare.js: client-side logic that fetches
share metadata via /api/s/{token}, handles password-protected shares,
and renders file download / folder info
- build.rs: include share.html in the HTML embed pipeline
- web/mod.rs: serve /s/{token} route (unauthenticated)
- share_dto.rs: generate URLs as /s/{token} instead of /api/s/{token}
- share_handler.rs: new download_shared_file() handler that validates the
share token and streams file content without requiring authentication
- routes.rs: mount GET /api/s/{token}/download (public, uses AppState)
- Add utoipa v5 dependency with ToSchema derives on all REST API DTOs
- Annotate free-function handlers with #[utoipa::path] (trash, share, favorites, recent)
- Create ApiDoc struct with OpenApi derive registering 37 schemas across 7 tags
- Add generate-openapi binary outputting resources/gen/openapi.json
- Serve OpenAPI spec at GET /api/openapi.json (public, no auth)
- Add justfile with common dev commands (build, test, lint, check, openapi, db)
- JWT secret auto-generates and persists to <STORAGE_PATH>/.jwt_secret
- Remove setup token: first admin setup is open until system initialized
- Fix schema.sql: move CREATE EXTENSION pg_trgm/ltree to top
- Update login UI and auth.js to remove setup token fields
- Add type aliases (FileRow, FolderRow, FolderRowPaginated, FolderRowOptUser) to reduce type complexity
- Simplify redundant closures in app_password_handler and webdav_handler
- Remove needless borrow in auth_handler
- Collapse nested if/let chains in login_lockout, webdav_lock, auth, rate_limit
- Box LockEntry in acquire() Err variant to fix large enum variant warning
- Rename DeviceCodeStatus::from_str to parse to avoid should_implement_trait lint
- Add #[allow(clippy::too_many_arguments)] and #[allow(clippy::result_unit_err)] where appropriate
- Convert integration_tests from cargo feature to custom cfg attribute
- Add check-cfg lint config in Cargo.toml for integration_tests cfg
Remove async-trait dependency and use native Rust async fn in traits.
Replace Arc<dyn Trait> with Arc<ConcreteType> throughout the codebase
to enable monomorphization and eliminate dynamic dispatch overhead.
Key changes:
- Remove write-behind cache (no implementation existed)
- Fix should_transcode static method call
- Use ContactStorageAdapter directly instead of dyn AddressBookUseCase
- Clean up unused trait imports across services and DI
https://claude.ai/code/session_01EbAFEfyJNLRmJHmmYDX3Tt
Standardize code formatting across all 173 Rust source files
using rustfmt. No functional changes - purely cosmetic.
This establishes a consistent code style baseline for the
project going forward.
- Fix showShareDialog: add try-catch, null checks, prevent textContent
from destroying header icon (use span child instead)
- Capture file/folder target before closeContextMenu to prevent race
- createSharedLink now calls real backend POST /api/shares instead of
localStorage-only mock (still caches locally for offline compat)
- Fix share_handler.rs: use OptionalAuthUser instead of AuthUser to
prevent 401 when auth is disabled (same pattern as delete/trash)
- Add null-safety to closeShareDialog
- Reset new-share-section on dialog open