Vancetope — WebDAV Access
Access to Project documents via WebDAV at
/brain/{tenant}/webdav/{project}/{path...}. The target is standard clients like macOS Finder (mounted volume) and Obsidian (WebDAV Sync plugin). WebDAV is a pure View on the document store — not a new data store, no separate authorization model.
1. Purpose
Users should be able to treat the documents of a Vancetope Project like a normal network drive: mount them in Finder, synchronize them as a Vault in Obsidian, and read and write them with any WebDAV-enabled tools. Access uses the same users and permissions as the rest of the system; data sovereignty remains with the DocumentService.
Distinction — what WebDAV is NOT: not a second document store, not a sync protocol with conflict resolution (Last-Writer-Wins at the document level, secured by Optimistic Locking), no Project enumeration (the mount always addresses exactly one Project).
2. Endpoint & Addressing
/brain/{tenant}/webdav/{project}/{path...}
{tenant}→tenantId{project}→projectId(business Project name){path...}→ logical document path within the Project (empty = Project root)
The bare root /brain/{tenant}/webdav (without a Project) is not browsable — Projects are not listed. A mount always points to a specific Project.
Prerequisite: Redis must be active (vance.redis.enabled=true). Lock state is cross-pod and lives in Redis; without Redis, the WebDAV surface is not registered (Brain still runs, WebDAV is simply unavailable).
3. Authentication
WebDAV clients use HTTP Basic-Auth, not the Bearer JWT of the rest of the Brain API. The /webdav/ path is therefore excluded from the JWT gate; authentication happens in the WebDAV layer:
Authorization: Basic <base64(user:password)>is checked against the same password mechanism as the regular login (active users withloginEnabled, password hash verification).- The Tenant comes from the URL — a user always authenticates only for the Tenant in the path; a login for Tenant A cannot access Tenant B.
- Missing/invalid credentials →
401withWWW-Authenticate: Basic realm="Vancetope".
The user’s normal login password serves as the Basic-Auth password.
4. Authorization
No separate permission model — the WebDAV layer uses the same authorization as the REST controllers:
| Target | Resource |
|---|---|
| Folder / Project Root | Project(tenant, project) |
| File | Document(tenant, project, path) |
Method mapping:
| WebDAV | Action |
|---|---|
GET / HEAD / PROPFIND / OPTIONS |
READ |
PUT (new) / MKCOL |
CREATE |
PUT (existing) / PROPPATCH / MOVE / DELETE |
WRITE |
The soft document edit protection (document-lock, lockedFor) automatically applies: if a document is locked for the USER role, a WebDAV write is rejected with 409 Conflict.
5. Folder Model
Folders are virtual — they are derived from the path prefixes of documents; there are no folder entities. A PROPFIND with Depth: 1 lists the direct subfolders and files.
MKCOL creates a hidden marker document for an empty folder, so that the folder persists until the first real document is added. The marker has a retention (default 1 day, TTL-driven): as soon as real files are in the folder, it becomes irrelevant and expires; an empty folder disappears automatically after expiration.
System paths with _ prefix (_vance/trash/, _vance/, …) are visible via WebDAV (deleted files appear under _vance/trash/).
6. Operations
| Method | Behavior | Success |
|---|---|---|
PROPFIND |
Folder listing / file properties | 207 Multi-Status |
GET |
Stream document content (Range supported) | 200 / 206 |
PUT |
Create new or replace content; MIME from file extension | 201 / 204 |
MKCOL |
Create virtual folder (marker) | 201 |
MOVE |
Rename/move file (within the same Project) | 201 |
COPY |
Copy file (within the same Project) | 201 |
DELETE |
Move to trash (_vance/trash/); recursive for folders |
204 |
LOCK / UNLOCK |
See §7 | 200/201 / 204 |
- MIME is always derived from the file extension (not from the client’s
Content-Type). MOVEpreserves document identity (lineageId) → version history follows the file;COPYcreates a new document with its own identity.- The ETag is based on the internal storage pointer and changes with every content write — clients reliably detect changes via
If-None-Match. - Moving/copying between Projects is not supported.
7. Locking (DAV Level 2)
WebDAV offers LOCK/UNLOCK (DAV Level 2) to allow macOS Finder Read-Write mounts. The lock is:
- exclusive, advisory, transient — a
LOCKreturns anopaquelocktoken; a secondLOCKon the same resource without this token returns423 Locked;UNLOCKreleases it. - cross-pod correct — the lock state resides in Redis with native TTL, so a client whose requests land on different pods sees the same lock; a crashed client automatically loses the lock due to TTL expiration.
- not an integrity guarantee — actual collision safety is provided by the Optimistic Locking of the document store (
@Version): concurrent writes fail with409 Conflict. The WebDAV lock primarily prevents the unpleasant mid-save409on the client.
OPTIONS advertises DAV: 1, 2.
8. macOS/Client-Sidecar Files
Finder and other clients generate auxiliary files that are not user documents (.DS_Store = folder view state, ._* = AppleDouble with Extended Attributes, plus .Spotlight-V100, Thumbs.db, desktop.ini, …). These are not persisted as documents, but opaquely cached in Redis (with TTL):
- hidden from directory listings (non-Apple clients like Obsidian never see them),
- delivered from cache on direct
GET, - stored in cache on
PUT(never in the document store).
Effect: macOS retains its folder view across requests and pods without polluting the document store. The cache is cosmetic — upon TTL expiration, only the folder view resets.
9. Configuration
Prefix vance.webdav.*:
| Property | Default | Meaning |
|---|---|---|
realm |
Vancetope |
Basic-Auth realm in the WWW-Authenticate challenge |
folder-marker.ttl (folderMarkerTtl) |
1 day | Retention of the MKCOL marker |
sidecarTtl |
1 day | Retention of Redis sidecar blobs |
lockTimeout |
1 h | Default lock timeout |
lockTimeoutMax |
12 h | Upper limit for client-requested timeouts |
sidecarPatterns |
see §8 | Ignore/sidecar filenames (Glob with *) |
Hard prerequisite: vance.redis.enabled=true (§2).
10. Attributes
WebDAV provides standard file attributes (displayname, getcontentlength, getcontenttype, getlastmodified, creationdate, resourcetype, getetag). Vancetope-specific attributes like color/tags are not exposed in v1; provision as vance:-DAV-Custom-Properties or as a bidirectional AppleDouble bridge is planned as a later extension.
Implementation history and design decisions: planning/webdav-support.md.