1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Storage subsystem: object/file storage over OpenDAL, with a named-disk
//! registry and the `Storage::disk(name).put(...)` facade.
//!
//! This module owns the ergonomic boundary between an Arcature application
//! and object/file storage: a [`Storage`] facade over OpenDAL
//! [`opendal::Operator`]s, with a validated [`StoragePath`] object key, typed
//! errors, and resolved configuration.
//!
//! # What this module owns
//!
//! * A [`Storage`] facade wrapping a registry of named [`Disk`] handles, each
//! an OpenDAL [`opendal::Operator`]. [`Storage::disk`] resolves a named
//! disk; the data-path methods (`put`/`get`/`delete`/`exists`/`stat`/
//! `list`/`copy`/`rename`/`reader`/`writer`) live on [`Disk`].
//! * A [`StoragePath`] validated object key that rejects path traversal,
//! absolute paths, backslashes, control characters, and empty segments
//! *before* any storage work runs.
//! * Resolved configuration: [`StorageConfig`] (selecting [`FsConfig`] or
//! [`S3Config`]) -- accepted explicitly, credentials redacted.
//! * With the `uploads` feature, a `filename` sanitizer that turns a
//! client-authored `filename=` parameter into a `SafeFilename` fit to keep
//! as metadata, plus `StoragePath::from_filename` for the cases where that
//! name is also used as a key.
//! * With the `uploads` feature, `content` addressing: a `ContentAddress`
//! names an object after the SHA-256 of its own bytes, so no byte of the
//! request reaches the path.
//! * With the `uploads` feature, `Disk::begin_upload` and `UploadWriter`:
//! a streaming write that hashes as it goes, so an upload of any size costs
//! one chunk of memory and lands on a key derived from its own bytes.
//! * With the `uploads` feature, `sniff`: a magic-number check that holds an
//! object's bytes and its accepted extension to agreement. It compares byte
//! prefixes and never decodes -- the client's `Content-Type` is not
//! consulted anywhere in this module.
//!
//! # What this module does not own
//!
//! It does not reimplement object-storage protocols, S3 signing, AWS
//! credential machinery, a multipart upload engine, TLS, or cryptography.
//! OpenDAL owns the protocol layer; the certified rustls + aws-lc-rs stack
//! owns TLS; Tokio owns the runtime.
//!
//! # Security note -- credentials are never logged
//!
//! [`S3Config`] implements `Debug` manually and redacts the access key id and
//! secret access key.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use StoragePath;
pub use ;
pub use ;
pub use ;
// Re-export the certified OpenDAL and bytes crates so downstream code targets
// the Arcature-pinned versions.
pub use bytes;
pub use opendal;