mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-11-03 22:05:11 -05:00
Replaces the Mintlify setup (mint.json, docs.json, snippets) with a standalone Fumadocs app in docs/: Next.js app router, meta.json nav per section, its own bun install. Run with `just dev-docs`. Content pass alongside the migration: core architecture, data model, CLI, and networking pages rewritten around the daemon/source-store/ library split, new product-direction.mdx defining the product boundary, new drive-catalog plan, and the physical-drives plan updated to reference it. Whitepaper page retired.
152 lines
4.0 KiB
Plaintext
152 lines
4.0 KiB
Plaintext
---
|
|
title: Operations
|
|
description: Define one typed action or query for every client
|
|
sidebarTitle: Operations
|
|
---
|
|
|
|
Operations are the public behavior of Spacedrive core. Define an operation once
|
|
in Rust, register it, and consume the same input and output from local IPC, web,
|
|
CLI, peer networking, generated clients, skills, and MCP.
|
|
|
|
## Queries and actions
|
|
|
|
- A **query** reads state without hidden mutation.
|
|
- An **action** requests a state change.
|
|
|
|
Both can be core-scoped or library-scoped. Core operations handle daemon and
|
|
library lifecycle. Library operations handle sources, records, organization,
|
|
jobs, and policy.
|
|
|
|
## Module shape
|
|
|
|
Keep each feature under its domain:
|
|
|
|
~~~text
|
|
core/src/ops/files/share/
|
|
├── mod.rs
|
|
├── input.rs
|
|
├── output.rs
|
|
├── action.rs
|
|
└── job.rs
|
|
~~~
|
|
|
|
Small features can use fewer files. The boundary matters more than the exact
|
|
layout: inputs and outputs are public types, while filesystem and database
|
|
details remain behind the handler.
|
|
|
|
## Registration
|
|
|
|
Use registration macros. Never implement the wire trait manually.
|
|
|
|
~~~rust
|
|
pub struct FileShareAction;
|
|
|
|
crate::register_library_action!(FileShareAction, "files.share");
|
|
|
|
impl Action for FileShareAction {
|
|
type Input = ShareFileInput;
|
|
type Output = ShareFileOutput;
|
|
|
|
async fn run(
|
|
input: Self::Input,
|
|
ctx: &ActionContext,
|
|
) -> Result<Self::Output, ActionError> {
|
|
// Validate scope, commit state, and return structured output.
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Available macros register core or library queries and actions into the compile
|
|
time inventory.
|
|
|
|
## Input and output
|
|
|
|
Public types:
|
|
|
|
- derive serialization and Specta type metadata;
|
|
- use stable IDs instead of database row numbers;
|
|
- represent unavailable and partial state explicitly;
|
|
- avoid leaking provider-specific secrets;
|
|
- remain backward-compatible within a protocol version.
|
|
|
|
After changing a public Rust type, regenerate TypeScript:
|
|
|
|
~~~bash
|
|
cargo run --bin generate_typescript_types
|
|
~~~
|
|
|
|
Frontend code imports those generated types. It does not redefine or cast them
|
|
away.
|
|
|
|
## Action lifecycle
|
|
|
|
An action performs only enough synchronous work to validate the request and
|
|
commit a bounded state change. Long work dispatches a durable job.
|
|
|
|
Risky mutations follow:
|
|
|
|
1. **Preview** exact targets, conflicts, cost, and protection consequences.
|
|
2. **Commit** an immutable plan or bounded state change.
|
|
3. **Execute** durable work with progress and cancellation.
|
|
4. **Verify** effects against the origin and content evidence.
|
|
5. **Report** structured output and durable logs.
|
|
|
|
Not every action needs a preview. Creating a tag can commit directly. Deleting
|
|
the last verified copy cannot.
|
|
|
|
## Context and authorization
|
|
|
|
Handlers receive a context that identifies:
|
|
|
|
- authenticated session or peer;
|
|
- selected library;
|
|
- granted sources and subtrees;
|
|
- allowed query and mutation classes;
|
|
- request and trace IDs;
|
|
- access to approved services.
|
|
|
|
Operations check capabilities before resolving sensitive data. A handler must
|
|
not infer permission from the fact that a path exists.
|
|
|
|
## Errors
|
|
|
|
Return typed errors for invalid input, missing identity, offline origins,
|
|
permission denial, conflicts, provider failure, and verification failure.
|
|
|
|
Logs explain diagnostics. They are not the API response.
|
|
|
|
## Events
|
|
|
|
Publish change events after the durable transaction commits. Clients that react
|
|
to an event must be able to query the new state immediately.
|
|
|
|
Large operations emit scoped invalidation or batch events instead of one event
|
|
per record.
|
|
|
|
## Generic clients
|
|
|
|
The CLI can invoke a registered operation by name:
|
|
|
|
~~~bash
|
|
sd-cli op sources.list --json '{}'
|
|
~~~
|
|
|
|
Skills and MCP use the same names and schemas. They do not translate arbitrary
|
|
text into an unregistered shell command.
|
|
|
|
## Tests
|
|
|
|
Operation tests cover:
|
|
|
|
- input validation;
|
|
- authorization at every scope;
|
|
- typed error shape;
|
|
- idempotency or deduplication;
|
|
- transaction rollback;
|
|
- job dispatch and final output;
|
|
- generated client compatibility;
|
|
- event ordering.
|
|
|
|
See [API](/core/api) for transports and [Jobs](/core/jobs) for durable
|
|
execution.
|