7663f803d3
Prevent services accessing directly to localstorage and prefer using an astraction layer to expose full blob. The abstraction layer (dedup services) will cover backend storage election (local, s3, ...), encryption, etc This change permit audio_metadata_service, media_metadaa_service, face_indexing_service to handle blobs without worring of the backend. note: prefered way to handle blob is the streamed way. Some services may not have this possibility
3.8 KiB
3.8 KiB
src/AGENTS.md — backend-only notes
Non-obvious rules that trip up new code. Terse on purpose.
Auth policy
- OIDC is the master identity provider. Whenever
AuthApplicationService::oidc_enabled()returns true, magic-link login MUST be off —is_magic_link_login_allowed()returns false regardless ofOXICLOUD_AUTH_METHODS. Rationale: OIDC may enforce 2FA / step-up; a mailbox-possession bypass would silently sidestep it. - Password / magic-link handlers gate via
is_password_login_allowed()/is_magic_link_login_allowed(), never raw config orpassword_login_disabled()alone. The composed helpers merge the legacy OIDC-only flag,OXICLOUD_AUTH_METHODS, SMTP wiring, and the OIDC-master rule in one place. - Magic-link redemption distinguishes login tokens (
resource_kind = None) from invitation tokens (File / Folder). The login gate only applies to the None case; invitations follow their own admin-mediated trust chain. OXICLOUD_REQUIRE_VERIFIED_EMAILgates login onemail_verified_at IS NOT NULL. Admin-created (admin_create_user) and setup-admin (setup_create_admin) users are stamped verified at creation — admin fiat counts. OIDC-JIT already stamps verified. Admins are EXEMPT from the gate at login regardless ofemail_verified_at— pre-existing admin accounts from before this flag shipped must never be locked out of their own instance. Regular users hit the gate; the frontend detects theEmailNotVerifiederror_type and offers a resend-magic-link CTA.- Startup gate in
main.rs: magic-link-only allowlist + no SMTP = panic. Never soften to warn.
New auth surfaces
- Any new endpoint that mints or consumes credentials/tokens must consult one of the
is_*_login_allowed()helpers, not the raw allowlist. - Any new "policy-disabled" refusal must emit an
audit-target line before returning — matchesauth.login_rejected,magic_link.redemption_rejectedconventions.
Storage backend access
- Read blob content through
Arc<DedupService>. It's the ONE canonical read abstraction — CDC-manifest-aware (file.blob_hashmay reference a chunk manifest, not a blob), backend-agnostic (Local/S3/Azure), wrapper-transparent (encryption/retry/cache). Never takeArc<dyn BlobStorageBackend>directly in a service that reads content; you'll silently break on any file ≥ 64 KiB (CDC_MIN_CHUNK). Followthumbnail_service,audio_metadata_service,media_metadata_service,face_indexing_service,search_index::content_index_workeras reference impls. - Reads use
DedupServicemethods:dedup.read_blob_bytes(hash)for byte-slice analyzers (ONNX, EXIF, ID3-via-Reader),dedup.stream_blob_to_tempfile(hash, &temp_dir, ".ext")for crates that only accept&Path(mp3_duration, ffprobe,nom-exifvideo),dedup.read_blob_stream(hash)for streaming to a downstreamStreamconsumer. - Never hand-craft blob paths. No
blob_root: PathBuffields, no<storage>/.blobs/<xx>/<hash>.blobconstructions.BlobStorageBackend::local_blob_pathreturnsNoneunderEncryptedBlobBackend; do not rely on it. The three services that did this pre-2026-08 (audio/media/face) are the anti-pattern — see memoryproject_services_bypassing_blob_backend. - Persistent state = backend, not
<storage_path>/*sidecars. Local sidecars (.thumbnails/,.transcoded/,.blob-cache/,.search-index/,.plugin-logs/,.uploads/) are only for caches (regenerable) or truly-temp scratch (deleted on drop). Anything a user would notice losing → blob backend. Tier-2 migration plan:docs/plan/derived-blobs.md. - Temp files use
OXICLOUD_TEMP_DIRvia the shared config path (AppConfig::temp_dir) — not rawstd::env::temp_dir(). Ops point it at real disk on RAM-constrained Linux deployments (default/tmp= tmpfs = RAM).