Skip to main content
The API infrastructure is under active development. Some features described here are planned but not yet fully implemented. This document reflects both current implementation and planned architecture.
The API infrastructure provides a secure, unified entry point for all Spacedrive operations. It handles authentication, authorization, session management, and request routing across CLI, Tauri desktop app, and native applications.

Architecture Overview

All API requests flow through a common pipeline:
Application → SessionContext → ApiDispatcher → PermissionLayer → Operation
This design enforces security policies consistently while providing rich context to operations.

Session Management

Sessions encapsulate all request context, replacing simple parameter passing with structured metadata:
// Create a device session (current implementation)
let session = SessionContext::device_session(device_uuid, device_name)
    .with_library(library_uuid);

// Session includes pre-configured permissions and metadata
Sessions include: Authentication Info: Device or user credentials and authorization level. Library Context: Currently selected library for scoped operations. Permission Set: Granular permissions for the session. Request Metadata: Tracking information for auditing and debugging.

API Dispatcher

The dispatcher provides a unified interface for all operations:
// Execute a library action
let result = api.execute_library_action(
    CreateLocationAction { path: "/Users/data" },
    session
).await?;

// Execute a core query
let libraries = api.execute_core_query(
    ListLibrariesQuery {},
    session
).await?;
The dispatcher automatically:
  • Validates session permissions
  • Ensures library context for library operations
  • Tracks request metadata
  • Converts errors to API errors

Permission System

Permissions control access to specific operations:
#[derive(Debug, Clone)]
pub struct PermissionSet {
    pub core: CorePermissions,
    pub library: LibraryPermissions,
    pub network: NetworkPermissions,
    pub jobs: JobPermissions,
}
Each category has granular permissions:
pub struct LibraryPermissions {
    pub read_entries: bool,
    pub write_entries: bool,
    pub manage_locations: bool,
    pub manage_tags: bool,
    pub execute_jobs: bool,
}

Permission Enforcement

Configure enforcement behavior:
// Development: Permissive mode (allows all operations)
let api = ApiDispatcher::permissive(core_context);

// Production: Enforce permissions
let api = ApiDispatcher::new(core_context);

Authorization Levels

Four hierarchical levels provide increasing access: None: No authentication required (public operations only). Device: Authenticated device with basic permissions. User: Authenticated user with full library access. Admin: System administrator with all permissions. Higher levels inherit permissions from lower levels.

Error Handling

API errors provide structured information for clients:
pub enum ApiError {
    // Authentication/authorization failures
    Unauthorized { required_level: AuthLevel },
    PermissionDenied { operation: String, permission: String },

    // Validation errors
    ValidationError { field: String, message: String },
    InvalidInput { details: String },

    // Execution errors
    OperationFailed { operation: String, error: String },
    ResourceNotFound { resource: String, id: String },

    // System errors
    DatabaseError(String),
    InternalError(String),
}
Errors automatically map to HTTP status codes for REST endpoints.

Middleware Pipeline

Middleware pipeline is partially implemented. The infrastructure exists but middleware chaining is not yet active.
Cross-cutting concerns are handled through composable middleware:
let pipeline = MiddlewarePipeline::new()
    .with_logging()
    .with_metrics()
    .with_rate_limiting();

Logging Middleware

Tracks all requests with timing information:
[API] files.copy started (request_id: 7f3a2b1c)
[API] files.copy completed in 145ms (request_id: 7f3a2b1c)

Metrics Middleware

Records operation metrics for monitoring:
  • Request count by operation
  • Response times (p50, p90, p99)
  • Error rates by type
  • Active request count

Request Sources

Track where API calls originate:
pub enum RequestSource {
    Cli,          // Command-line interface
    Swift,        // iOS/macOS native application
    Internal,     // Internal system calls
    Other(String), // Other sources (including Tauri desktop app)
}
Tauri desktop app currently uses Other("tauri") or Internal. A dedicated Tauri variant is planned.
This enables source-specific behavior like CLI-friendly error messages.

API Discovery

API discovery is a planned feature, not yet implemented.
Applications will be able to query available operations:
// Planned feature
let surface = api.describe_api();

for op in surface.operations {
    println!("{} - {}", op.name, op.description);
    println!("  Permissions: {:?}", op.required_permissions);
    println!("  Auth Level: {:?}", op.required_auth_level);
}
This will power dynamic UI generation and permission checking.

Integration Examples

CLI Integration

// Create session from CLI context
let session = api.create_base_session()?
    .with_library(current_library_id());

// Execute operation
match api.execute_library_action(action, session).await {
    Ok(result) => println!("Success: {:?}", result),
    Err(ApiError::InsufficientPermissions { reason }) => {
        eprintln!("Permission denied: {}", reason);
    }
    Err(e) => eprintln!("Error: {}", e),
}

Tauri Integration

The Tauri desktop app integrates with the core through Rust FFI:
// Tauri command handlers call the API dispatcher
#[tauri::command]
async fn create_location(
    path: String,
    state: tauri::State<'_, AppState>,
) -> Result<Location, String> {
    let session = state.api.create_base_session()
        .map_err(|e| e.to_string())?
        .with_library(state.current_library_id);

    state.api.execute_library_action(
        CreateLocationAction { path },
        session
    ).await.map_err(|e| e.to_string())
}
The Tauri app can run the daemon in two modes:
  • In-Process: Daemon runs within the Tauri app process
  • Background Process: Daemon runs as a separate system process (requires macOS entitlements)
See apps/tauri/DAEMON_SETUP.md for configuration details.

Swift Integration

// Swift SDK uses generated types with session management
let session = SessionContext(
    auth: deviceAuth,
    library: currentLibrary.id,
    source: .swift
)

let location = try await api.libraries.createLocation(
    CreateLocationInput(path: "/Users/data"),
    session: session
)

Security Best Practices

Always use strict permissions in production: Development warnings help identify missing permissions during development. Validate library context: Library operations must have current_library_id set in the session. Track request metadata: Use request IDs for debugging distributed operations. Handle errors appropriately: Convert internal errors to user-friendly messages at the boundary.

Future Enhancements

Planned improvements include: User Authentication: OAuth and session token support. Rate Limiting: Per-user and per-operation limits. Request Caching: Smart caching for read operations. WebSocket Support: Real-time operation subscriptions.
The API infrastructure is designed to be transport-agnostic. While examples show Rust usage, the same patterns apply to REST endpoints and FFI boundaries.