CipherFS
In development · unreleased · format may change

Application server API

Build cipherfs serve with sync. These routes use the existing Bearer/private owner session under /api/v1 (or a configured vault alias). S3 application keys do not authorize the JSON API.

RequestBehavior
PUT /server/file?path=attachments/a&level=store&timeout_ms=30000Stream one complete replacement, commit locally, then wait for at least one store's content confirmation
PUT /server/file?file_id=<id>&level=full_devices&full_devices_count=2Replace that existing identity, then wait for two authorized Full devices holding its complete content
GET /server/file?file_id=<id>Read the selected identity, with the existing single Range support
GET /server/durability?version=<id>Inspect accepted content-holder observations for an exact version
POST /server/durabilityResume waiting for an existing version without writing another version
GET / PUT /server/cacheRead or replace this device's file pins and heat-prefetch settings
PUT / DELETE /server/pins?file_id=<id>Add or remove one exact file pin

A write requires exactly one path or file_id. level defaults to local; other choices are store and full_devices with full_devices_count in 1–128. The wait timeout is 1–3,600,000 milliseconds, default 30,000, and begins after local commitment. Invalid options and replication requests for local-only files are refused before consuming the body. Upload buffering, explicit EOF, declared/detected content type and cancellation reuse the ordinary file adapter.

A successful write includes a receipt containing the exact file, version and local_only values from its commit transaction. A store/full-device response succeeds only after that version's complete-content position is confirmed. Index-only peers, Partial devices and revoked devices do not count as Full replicas. The current owner counts when it is Full and holds the content. These are authenticated position observations, not a promise that a holder remains reachable forever.

A confirmation timeout returns HTTP 504 and the committed receipt; it does not undo the local write. Other confirmation failures also retain a known receipt. On revocation, an already admitted server write drains its worker and may return an error receipt, never a successful response or plaintext content. A disconnected client may still miss the response; retrying an upload is a new write.

Resume a barrier with:

{
  "version": "<exact-version-id>",
  "requirement": {"level": "full_devices", "count": 2},
  "timeout_ms": 30000
}

FileId reads and writes follow moves and do not select a different file that reuses the old path. A concurrent move during preparation can return a conflict requiring retry. Historical reads keep using the existing version APIs.

Cache settings are device-local and sealed in metadata:

{
  "pinned_files": [],
  "prefetch_max_files": 32,
  "prefetch_max_bytes": 67108864,
  "heat_ttl_ms": 3600000
}

Pins are sorted unique existing FileIds, up to 4,096, and retain each file's current content across moves and writes. They do not pin descendants or unrelated path replacements. Removing a file can leave a stale pin, which can be removed later. Directory pins remain available separately.

Heat tracks up to 1,024 accessed file identities in memory, decays by age and is cleared on sealing/restart. A Partial device can prefetch newer heads of recently accessed files. Each round selects at most prefetch_max_files (maximum 1,024), and missing ciphertext must fit prefetch_max_bytes (maximum 8 GiB) and the read-cache budget. A file exceeding the remaining budget is skipped. Set both limits to zero to disable heat prefetch, the default. Heat does not permanently pin data; ordinary eviction rules remain in force. heat_ttl_ms is positive and at most seven days.

For short retention, PUT /retention accepts the ordinary day fields and an optional application object:

{
  "version_max_age_days": 365,
  "trash_max_age_days": 365,
  "min_versions_per_file": 1,
  "grace_days": 30,
  "application": {
    "version_max_age_ms": 60000,
    "trash_max_age_ms": 60000,
    "grace_ms": 10000,
    "local_drop_margin_ms": 10000,
    "store_gc_delay_ms": 10000
  }
}

Overrides are vault-wide, authenticated and synchronized. Zero means no delay; each override is bounded to 100 years. Without application, the day-based behavior is unchanged. A proposal keeps the timings from its causal policy even after later policy edits. Current/conflict heads and unpublished modifications remain protected. Eligibility is not a real-time deletion guarantee: maintenance scheduling, live pack contents and independent orphan/repack safeguards still apply. The desktop day editor preserves an existing application override. See format details.

Rust applications can use Core's WriteReceipt, open_file_id_handle, write_file_id_from_reader, pin_file, server_cache_policy and version_durability. SyncedVault adds put_from_reader_version, FileId streaming reads/writes, cache controls and the cancellable wait_for_durability barrier. Timeout errors identify the version and last completed observation; a barrier never rolls back an earlier write.

Source file in the repository