docs: migrate legacy docs to official site

This commit is contained in:
Diocrafts
2026-04-22 07:50:41 +02:00
parent e10a908f07
commit c0cb86c273
63 changed files with 1646 additions and 10136 deletions
@@ -0,0 +1,74 @@
# Database Transactions
OxiCloud uses explicit PostgreSQL transactions for multi-step operations that must either commit together or fail together.
## ACID Guarantees
- Atomicity: all work succeeds or the entire transaction rolls back
- Consistency: constraints and invariants remain valid before and after commit
- Isolation: concurrent work behaves predictably
- Durability: committed writes survive process and system failures
## Transaction Helper
The PostgreSQL repositories use a helper like `with_transaction` to standardize the transaction lifecycle:
```rust
pub async fn with_transaction<F, T, E>(
pool: &Arc<PgPool>,
operation_name: &str,
operation: F,
) -> Result<T, E>
where
F: for<'c> FnOnce(&'c mut Transaction<'_, Postgres>) -> futures::future::BoxFuture<'c, Result<T, E>>,
E: From<SqlxError> + std::fmt::Display,
{ /* ... */ }
```
That wrapper handles begin, commit, rollback, and lifecycle logging so repository code can focus on the actual domain operation.
## Common Use Cases
### User management
Transactions keep related user changes together, such as creating a user and attaching the dependent records required for a valid account.
### Session management
Session creation and session revocation can update multiple tables in a single logical step, which avoids stale or mismatched security state.
### File and folder workflows
Moves, renames, trash operations, and other multi-step metadata changes rely on transactions so the tree stays consistent.
## Isolation Levels
OxiCloud can use different isolation levels depending on the operation.
| Level | Use case |
| --- | --- |
| `Read Committed` | Default application work |
| `Repeatable Read` | Stable reads during a longer unit of work |
| `Serializable` | Highest safety for conflict-prone critical operations |
Higher isolation can introduce retries or contention, so it should be reserved for the few flows that need it.
## Best Practices
- Keep transactions short
- Avoid heavy I/O inside a transaction when possible
- Group only operations that must commit together
- Choose the lowest isolation level that preserves correctness
- Log and surface rollback causes clearly
## Why It Matters
- Prevents partial metadata updates
- Keeps concurrent user activity predictable
- Reduces race conditions in critical operations
- Makes failures recoverable and easier to reason about
## Related Pages
- [Storage Safety](/architecture/file-system-safety)
- [Internal Architecture](/architecture/)
+77
View File
@@ -0,0 +1,77 @@
# Storage Safety
OxiCloud protects file integrity with two layers working together:
- PostgreSQL transactions for metadata
- Atomic blob writes for content
The result is a simple guarantee: operations either complete fully or fail cleanly enough to recover without corrupting user data.
## Storage Model
- Metadata such as names, folders, MIME types, quotas, and trash state lives in PostgreSQL
- File content is stored as content-addressed blobs under the storage backend
- Deduplication metadata is tracked separately so multiple files can reference the same content safely
## Metadata Safety
PostgreSQL protects metadata with ACID transactions.
- Single-row writes are atomic by default
- Multi-step operations use explicit transactions
- Foreign keys prevent orphaned references
- Unique constraints prevent illegal duplicates in the same scope
- Trash uses soft-delete semantics until permanent deletion is requested
## Content Safety
Blob writes rely on an atomic write pattern:
1. Write new content to a temporary file
2. `fsync` the file to push data and metadata to durable storage
3. Rename the temp file into its final content-addressed path
4. Sync parent directory metadata when needed
This prevents partially written blobs from appearing as valid stored content.
## Deduplication Notes
OxiCloud's deduplication pipeline uses BLAKE3 hashing and chunk manifest tracking. The storage layer can therefore reuse identical content while still keeping metadata changes transactional.
If content is stored successfully but the later metadata transaction fails, the content may remain as an unreferenced blob. That is a space leak, not a consistency leak, and can be cleaned up later.
## Upload Flow
```text
1. Receive content and spool it safely to storage
2. Finalize the content-addressed blob write
3. Begin metadata transaction
4. Insert or update file metadata in PostgreSQL
5. Commit
```
If step 1 or 2 fails, no metadata is committed. If step 4 or 5 fails, metadata rolls back and the storage layer can clean up unreferenced content later.
## Delete Flow
```text
1. Begin metadata transaction
2. Remove or soft-delete the metadata row
3. Commit
4. Decrement blob references and remove physical content when the refcount reaches zero
```
If the metadata transaction fails, the physical file is not considered deleted. If the refcount cleanup fails, the system may keep extra content on disk, but user-visible metadata remains correct.
## Why This Matters
- Crash resilience during uploads and deletes
- Safe recovery after power loss or host restarts
- Clean separation between metadata correctness and background storage cleanup
- Predictable behavior for trash, deduplication, and shared storage backends
## Related Pages
- [Internal Architecture](/architecture/)
- [Database Transactions](/architecture/database-transactions)
- [Storage Quotas](/architecture/storage-quotas)
+11
View File
@@ -37,6 +37,17 @@ All cross-layer dependencies point **inward** via trait-based ports. The DI cont
8. **ZIP service** (last, depends on file & folder services)
9. **Assemble `AppState`**
## AppState Shape
The assembled `AppState` groups the application into a few stable buckets:
- `core` for cross-cutting runtime services such as path resolution, caching, chunked uploads, deduplication, compression, thumbnails, and ZIP handling
- `repositories` for PostgreSQL-backed folder, file, trash, and i18n persistence
- `applications` for the use-case layer exposed to handlers
- optional auth, admin, trash, share, favorites, recent, storage usage, calendar, and contact services when those features are enabled
This lets handlers depend on stable interfaces while the concrete implementation details stay inside the DI container.
## Project Structure
```
+74
View File
@@ -0,0 +1,74 @@
# Share Integration
OxiCloud supports public file and folder sharing through signed share links. A share can be public, password-protected, time-limited, or scoped by permissions.
## What a Share Contains
A share record tracks:
- The shared item ID and whether it is a file or folder
- A public token used in the share URL
- Optional password protection
- Optional expiration timestamp
- Permissions for read, write, and reshare
- The creator and access count
## Public and Private Routes
### Authenticated management routes
| Method | Path | Description |
| --- | --- | --- |
| `POST` | `/api/shares/` | Create a new share |
| `GET` | `/api/shares/` | List current user's shares |
| `GET` | `/api/shares/{id}` | Fetch one share |
| `PUT` | `/api/shares/{id}` | Update permissions, password, or expiration |
| `DELETE` | `/api/shares/{id}` | Delete a share |
### Public access routes
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/s/{token}` | Access a shared item |
| `POST` | `/api/s/{token}/verify` | Verify a password-protected share |
## Service Responsibilities
The share service is responsible for:
- Validating that the underlying file or folder exists
- Generating unique share IDs and public tokens
- Enforcing password checks and expiration rules
- Mapping domain permissions into API DTOs
- Recording access counts
Share metadata is persisted separately from the file content itself. The shared resource still uses the normal storage model for files and folders.
## Example Workflow
### Creating a share link
1. A user selects a file or folder in the UI
2. The frontend submits a request to `/api/shares/`
3. OxiCloud validates the target and requested permissions
4. The backend generates a token and public URL
5. The share metadata is saved and returned to the caller
### Opening a share link
1. A guest opens `/api/s/{token}`
2. OxiCloud verifies the token and checks expiration
3. If the share is password protected, the client verifies the password first
4. Access is counted and the shared resource is returned according to the granted permissions
## Security Notes
- Passwords are stored as hashes, never as plaintext
- Expired shares are rejected before content access
- Permissions are checked per action, not only when the share is created
## Related Pages
- [OIDC / SSO](/config/oidc)
- [Admin Settings](/config/admin-settings)
- [Internal Architecture](/architecture/)
+12
View File
@@ -15,6 +15,10 @@ OXICLOUD_ENABLE_USER_STORAGE_QUOTAS=true
3. If the upload would exceed the quota, it's rejected with a `413 Payload Too Large` error
4. Admins can view and set quotas via the admin panel or API
## Usage Calculation
The storage usage service recalculates logical usage from the user's home folder tree and sums file sizes recursively. Directory entries are skipped and the final value is written back to `auth.users.storage_used`.
## API
| Method | Endpoint | Description |
@@ -26,6 +30,14 @@ OXICLOUD_ENABLE_USER_STORAGE_QUOTAS=true
The admin panel (`/admin.html`) shows each user's current usage vs. quota with a visual progress bar.
The dashboard also exposes aggregate quota stats such as:
- total quota bytes
- total used bytes
- overall storage usage percent
- users above 80% usage
- users over quota
## Deduplication Interaction
Storage usage is calculated based on **logical file size** (what the user uploaded), not physical blob size. This means: