File storage abstraction with pluggable backends (S3, local, GCS)
| Tier | infrastructure |
| Role | unclassified (baselined) |
| Path | crates/infrastructure/storage |
| Edition | 2021 |
| Targets | infrastructure_storage |
| Public items | 29 across 2 modules |
| Tests | 47 |
What it is for
File storage abstraction with pluggable backends.
Supports local filesystem, S3, and other storage backends.
Capabilities
local (other)
Local filesystem storage backend.
| Item |
|---|
pub const DEFAULT_MAX_FILE_SIZE: usize |
LocalStorage:LocalStorage
Local filesystem storage backend.
| Item |
|---|
pub struct LocalStorage |
LocalStorage:delete
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn delete(& self, path : & str) -> Result <(), StorageError> |
LocalStorage:download
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn download(& self, path : & str) -> Result <Vec <u8>, StorageError> |
LocalStorage:exists
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn exists(& self, path : & str) -> Result <bool, StorageError> |
LocalStorage:fs
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: fn fs_path(& self, path : & str) -> PathBuf |
LocalStorage:get
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn get_by_sha256(& self, sha256_hex : & str, scope : & StoreScope,) -> Result <Option <StoredFile>, StorageError> |
LocalStorage:new
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: fn new(root : impl AsRef <Path>) -> Self |
LocalStorage:private
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: fn private_root(& self) -> & Path |
LocalStorage:public
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: fn public_root(& self) -> & Path |
LocalStorage:put
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn put_bytes(& self, content : & u8, filename : & str, content_type : & str, scope : & StoreScope,) -> Result <StoredFile, StorageError> |
LocalStorage:upload
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn upload(& self, content : & u8, filename : & str, content_type : & str,) -> Result <StoredFile, StorageError> |
LocalStorage:url
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: async fn url(& self, path : & str) -> Result <String, StorageError> |
LocalStorage:with
Local filesystem storage backend.
| Item |
|---|
LocalStorage :: fn with_private_root(root : impl AsRef <Path>, private_root : impl AsRef <Path>) -> Self |
LocalStorage :: fn with_max_size(root : impl AsRef <Path>, max_file_size : usize) -> Self |
S3Config
S3 / Cloudflare-R2 storage backend (Media Centralization, Group C).
| Item |
|---|
pub struct S3Config |
S3Config :: fn from_env() -> Result <Self, StorageError> |
S3Storage
S3 / Cloudflare-R2 storage backend (Media Centralization, Group C).
| Item |
|---|
pub struct S3Storage |
S3Storage :: fn new(config : S3Config) -> Self |
S3Storage :: fn with_max_size(config : S3Config, max_file_size : usize) -> Self |
S3Storage :: fn from_env() -> Result <Self, StorageError> |
S3Storage :: fn bucket(& self) -> & str |
S3Storage :: async fn upload(& self, content : & u8, filename : & str, content_type : & str,) -> Result <StoredFile, StorageError> |
S3Storage :: async fn download(& self, path : & str) -> Result <Vec <u8>, StorageError> |
S3Storage :: async fn delete(& self, path : & str) -> Result <(), StorageError> |
S3Storage :: async fn exists(& self, path : & str) -> Result <bool, StorageError> |
S3Storage :: async fn url(& self, path : & str) -> Result <String, StorageError> |
S3Storage :: async fn put_bytes(& self, content : & u8, filename : & str, content_type : & str, scope : & StoreScope,) -> Result <StoredFile, StorageError> |
S3Storage :: async fn get_by_sha256(& self, sha256_hex : & str, scope : & StoreScope,) -> Result <Option <StoredFile>, StorageError> |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
infrastructure_storage
locals3
flowchart TD n_infrastructure_storage["infrastructure_storage"] n_infrastructure_storage --> n_local["local"] n_infrastructure_storage --> n_s3["s3"]
Public surface
`local`
| Item | What it is |
|---|---|
pub const DEFAULT_MAX_FILE_SIZE: usize | Default maximum file size: 10 MB. |
pub struct LocalStorage | Local filesystem storage backend |
LocalStorage :: fn new(root : impl AsRef <Path>) -> Self | Creates a new local storage backend with the given public root directory |
LocalStorage :: fn with_private_root(root : impl AsRef <Path>, private_root : impl AsRef <Path>) -> Self | Creates a new local storage backend with an explicit public + private root |
LocalStorage :: fn with_max_size(root : impl AsRef <Path>, max_file_size : usize) -> Self | Creates a new local storage backend with a maximum file size limit. |
LocalStorage :: fn public_root(& self) -> & Path | The public root (where a ServeDir may be mounted) |
LocalStorage :: fn private_root(& self) -> & Path | The private root (never served) |
LocalStorage :: fn fs_path(& self, path : & str) -> PathBuf | Resolve a stored logical path to its absolute on-disk location, routing private-scope paths (the __private prefix) to the non-served private root |
LocalStorage :: async fn upload(& self, content : & u8, filename : & str, content_type : & str,) -> Result <StoredFile, StorageError> | — |
LocalStorage :: async fn download(& self, path : & str) -> Result <Vec <u8>, StorageError> | — |
LocalStorage :: async fn delete(& self, path : & str) -> Result <(), StorageError> | — |
LocalStorage :: async fn exists(& self, path : & str) -> Result <bool, StorageError> | — |
LocalStorage :: async fn url(& self, path : & str) -> Result <String, StorageError> | — |
LocalStorage :: async fn put_bytes(& self, content : & u8, filename : & str, content_type : & str, scope : & StoreScope,) -> Result <StoredFile, StorageError> | — |
LocalStorage :: async fn get_by_sha256(& self, sha256_hex : & str, scope : & StoreScope,) -> Result <Option <StoredFile>, StorageError> | — |
`s3`
| Item | What it is |
|---|---|
pub struct S3Config | Configuration for S3Storage |
S3Config :: fn from_env() -> Result <Self, StorageError> | Builds a config from environment variables (see module docs for the full table) |
pub struct S3Storage | S3 / R2 storage backend |
S3Storage :: fn new(config : S3Config) -> Self | Builds an S3Storage from an explicit S3Config |
S3Storage :: fn with_max_size(config : S3Config, max_file_size : usize) -> Self | Builds an S3Storage with a maximum file size limit (bytes). |
S3Storage :: fn from_env() -> Result <Self, StorageError> | Convenience constructor reading S3Config::from_env |
S3Storage :: fn bucket(& self) -> & str | Returns the bucket name (test/inspection helper). |
S3Storage :: async fn upload(& self, content : & u8, filename : & str, content_type : & str,) -> Result <StoredFile, StorageError> | — |
S3Storage :: async fn download(& self, path : & str) -> Result <Vec <u8>, StorageError> | — |
S3Storage :: async fn delete(& self, path : & str) -> Result <(), StorageError> | — |
S3Storage :: async fn exists(& self, path : & str) -> Result <bool, StorageError> | — |
S3Storage :: async fn url(& self, path : & str) -> Result <String, StorageError> | — |
S3Storage :: async fn put_bytes(& self, content : & u8, filename : & str, content_type : & str, scope : & StoreScope,) -> Result <StoredFile, StorageError> | — |
S3Storage :: async fn get_by_sha256(& self, sha256_hex : & str, scope : & StoreScope,) -> Result <Option <StoredFile>, StorageError> | — |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
StorageBackend | backend::StorageBackend |
StorageError | error::StorageError |
StoredFile | stored_file::StoredFile |
{LocalStorage,DEFAULT_MAX_FILE_SIZE} | local::{LocalStorage,DEFAULT_MAX_FILE_SIZE} |
{S3Config,S3Storage} | s3::{S3Config,S3Storage} |
{path_is_private,StoreScope,PRIVATE_PREFIX} | scope::{path_is_private,StoreScope,PRIVATE_PREFIX} |
Boundary
Reaches into foundation.
Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | infrastructure |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/infrastructure/storage |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_infrastructure["infrastructure"] --> n_foundation["foundation"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `foundation-basemodels` | foundation | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
async-trait | ^0.1 | — | no | always |
aws-config | ^1 | — | yes | always |
aws-sdk-s3 | ^1 | — | yes | always |
chrono | ^0.4 | serde | no | always |
hex | ^0.4 | — | no | always |
mime_guess | ^2 | — | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
sha2 | ^0.10 | — | no | always |
sqlx | ^0.8 | runtime-tokio, postgres, chrono, uuid, json | no | always |
thiserror | ^2 | — | no | always |
tokio | ^1 | full, fs | no | always |
uuid | ^1 | v4, v7, serde, js | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tempfile | ^3 | — | no | always |
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. 11 workspace crates.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR n_application_cms["application-cms"] -->|uses| SELF n_application_wiki["application-wiki"] -->|uses| SELF n_content_assets["content-assets"] -->|uses| SELF n_domain_legal_documents["domain-legal-documents"] -->|uses| SELF n_domain_legal_evidence["domain-legal-evidence"] -->|uses| SELF n_domain_legal_procedure["domain-legal-procedure"] -->|uses| SELF n_infrastructure_acquire["infrastructure-acquire"] -->|uses| SELF n_infrastructure_fetcher["infrastructure-fetcher"] -->|uses| SELF n_infrastructure_web_ingest["infrastructure-web-ingest"] -->|uses| SELF n_platform_api["platform-api"] -->|uses| SELF n_platform_privacy_scan_api["platform-privacy-scan-api"] -->|uses| SELF SELF["infrastructure-storage"] SELF -->|runtime| n_foundation_basemodels["foundation-basemodels"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
| Feature | Enables | On by default |
|---|---|---|
aws-config | dep:aws-config | no |
aws-sdk-s3 | dep:aws-sdk-s3 | no |
default | — | yes |
s3 | aws-sdk-s3, aws-config | no |
flowchart LR n_aws_config["aws-config"] --> n_dep_aws_config["dep:aws-config"] n_aws_sdk_s3["aws-sdk-s3"] --> n_dep_aws_sdk_s3["dep:aws-sdk-s3"] n_default["default"] n_s3["s3"] --> n_aws_sdk_s3["aws-sdk-s3"] n_s3["s3"] --> n_aws_config["aws-config"]
Targets
| Kind | Name | Source |
|---|---|---|
| lib | infrastructure_storage | `src/lib.rs` |
Error model
No public error type was detected: no public item declares a type named *Error, and no public signature returns one.
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | yes |
| database access | yes |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
11 workspace crates depend on this one: application-cms, application-wiki, content-assets, domain-legal-documents, domain-legal-evidence, domain-legal-procedure, infrastructure-acquire, infrastructure-fetcher, infrastructure-web-ingest, platform-api, platform-privacy-scan-api.
Verification
| Kind | Count |
|---|---|
| Unit tests | 47 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
local | 2 | 0 | 7 |
s3 | 2 | 0 | 0 |
What the tests establish, by name:
download_round_trips_private_object—src/lib.rsfs_path_routes_private_to_private_root_and_public_to_public_root—src/lib.rsget_by_sha256_global_does_not_find_tenant_content—src/lib.rsget_by_sha256_returns_none_when_hash_absent—src/lib.rsget_by_sha256_returns_stored_file_when_present_in_scope—src/lib.rsget_by_sha256_tenant_a_does_not_find_tenant_b_content—src/lib.rsget_by_sha256_tenant_does_not_find_global_content—src/lib.rsnew_derives_private_root_as_sibling_not_under_public_root—src/lib.rsput_bytes_private_writes_outside_public_root—src/lib.rsput_bytes_same_content_same_scope_same_hash—src/lib.rsput_bytes_writes_to_shared_root_under_global_scope—src/lib.rsput_bytes_writes_to_tenant_prefixed_path_under_tenant_scope—src/lib.rsstore_scope_tenant_and_global_are_distinct—src/lib.rsstore_scope_two_distinct_tenants_are_distinct—src/lib.rsstored_file_with_tenant_builder_sets_tenant_id—src/lib.rstest_file_too_large—src/lib.rstest_file_within_limit_succeeds—src/lib.rstest_local_storage_delete—src/lib.rstest_local_storage_download—src/lib.rstest_local_storage_exists—src/lib.rstest_local_storage_generates_unique_paths—src/lib.rstest_local_storage_sha256_hash—src/lib.rstest_local_storage_upload—src/lib.rstest_path_is_private_detects_private_prefix—src/lib.rstest_path_traversal_delete—src/lib.rstest_path_traversal_download—src/lib.rstest_path_traversal_exists—src/lib.rstest_private_scope_prefix—src/lib.rstest_stored_file_extension—src/lib.rstest_stored_file_human_readable_size—src/lib.rs- _… 17 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 15 | 29 |
Public modules with a //! block | 2 | 2 |
pie showData
title Public items with rustdoc
"Documented" : 15
"No rustdoc detected" : 14
Metrics
| Metric | Value |
|---|---|
| Rust source files | 7 |
| Source lines | 1831 |
| Code lines | 1258 |
| Public API items | 29 |
| Public modules | 2 |
| Tests | 47 |
| Examples | 0 |
| Cargo features | 4 |
| Direct runtime dependencies | 14 |
| Workspace reverse dependencies | 11 |
pie showData
title Public API by kind
"constant" : 1
"method" : 25
"struct" : 3
pie showData
title Rust source composition
"Code" : 1258
"Blank or comment" : 573
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.