arizuko

arizukohowto › WebDAV mount

mount the workspace over WebDAV

Every arizuko group folder is exposed as WebDAV at https://<host>/dav/<group>/. Any WebDAV client (Finder, Windows Explorer, rclone, davfs2, curl) sees the same files the agent reads and writes.

quick start

One-time setup of an rclone remote against your instance, plus a mount:

# 1. point rclone at the WebDAV endpoint (no user/pass yet)
rclone config create arizuko webdav \
    url=https://fab.krons.cx/dav/ \
    vendor=other

# 2. issue a Bearer token from the dashboard:
#    open https://fab.krons.cx/dash/profile in a browser and copy it.

# 3. tell rclone to use the token (it stores it in ~/.config/rclone/rclone.conf)
rclone config update arizuko bearer_token=<paste-token-here>

# 4. mount a group as a local folder
mkdir -p ~/arizuko-atlas
rclone mount arizuko:atlas ~/arizuko-atlas --vfs-cache-mode writes

You should now see the group’s files under ~/arizuko-atlas/CLAUDE.md, diary/, facts/, media/, and so on. Edit them with your editor, drop files in, and the agent picks them up on its next turn.

Just want to peek? Sign in at /auth/login, then open https://<host>/dav/<group>/ in your browser. dufs (the underlying server) ships a directory UI, so you get a clickable file tree for free.

path structure

The URL /dav/<group>/<rest> maps one-to-one to /<group>/<rest> under the data directory on the host. davd serves <DATA_DIR>/groups/ read-write over WebDAV; proxyd strips the leading /dav before forwarding and applies the davAllow write-block guard on top.

URLon-disk path (host)
/dav/redirect to /dav/<first-group>/
/dav/atlas//srv/data/arizuko_<inst>/groups/atlas/
/dav/atlas/strengths//srv/data/arizuko_<inst>/groups/atlas/strengths/
/dav/atlas/CLAUDE.md/srv/data/arizuko_<inst>/groups/atlas/CLAUDE.md
/dav/atlas/users/alice.md/srv/data/arizuko_<inst>/groups/atlas/users/alice.md

<group> is the group’s folder name (the on-disk slug), not the human-friendly group name. If you don’t know it, the operator dashboard at /dash/groups lists them. The default group on a fresh instance is called main.

authentication

The same auth layer that gates /dash/ gates /dav/. There is no separate WebDAV password file and no Basic Auth.

client stylecredentialhow
browserJWT cookiesign in at /auth/login with GitHub / Google / Discord / Telegram; the refresh_token cookie carries through to /dav/
rclone, davfs2, curl, Finder, Windows ExplorerBearer tokenissue at /dash/profile, send as Authorization: Bearer <token>

An unauthenticated request to /dav/... returns 303 See Other with Location: /auth/login — that’s by design. The browser follows it; curl does not unless you pass -L. Verify directly:

curl -s -o /dev/null -w '%{http_code}\n' https://fab.krons.cx/dav/
# 303

curl -s -o /dev/null -w '%{http_code}\n' \
     -H "Authorization: Bearer $TOKEN" \
     https://fab.krons.cx/dav/atlas/
# 200
Bearer tokens are passwords. Treat them as such. Anyone who holds your token can read every group you have a grant on. Revoke at /dash/profile if you suspect a leak.

per-group access

Authentication tells proxyd who you are; grants tell it which group folders you may touch. Grants are stored as acl rows (with role:operator membership in acl_membership for the operator) and resolved at request time:

Grant scope decides what your token can read; auth alone is not enough. A user signed in to /dav/ with no grants gets 403 on every group path.

write-block guard

WebDAV is writable end-to-end — davd mounts <DATA_DIR>/groups/ read-write, and proxyd’s davAllow middleware is the single point of write enforcement. The full ruleset, lifted from proxyd/main.go:

The spec at specs/5/M-webdav.md is the source of truth.

common workflows

operator edits a channel’s CLAUDE.md from a laptop

rclone mount arizuko:atlas ~/atlas --vfs-cache-mode writes
$EDITOR ~/atlas/CLAUDE.md
# save, unmount. The agent picks up the new persona on its next turn.

user drops a file the agent should read

# put a CSV in the channel's media folder
curl -u :$TOKEN \
     -T ./quarterly.csv \
     https://fab.krons.cx/dav/atlas/media/quarterly.csv

# then in chat, ask the agent: "read media/quarterly.csv and summarise"

Or just drag-drop into a Finder window mounted at /dav/atlas/. -u :$TOKEN sends the token as the password with an empty username — curl maps that to a Basic header which proxyd ignores; the real auth still flows through the Bearer header below if you set it explicitly.

curl -H "Authorization: Bearer $TOKEN" \
     -T ./quarterly.csv \
     https://fab.krons.cx/dav/atlas/media/quarterly.csv

agent writes a file; user pulls it down

The agent runs inside a container with its group folder mounted read-write; it can drop generated artifacts (PDFs, charts, transcripts) anywhere except logs/. The user then pulls them down:

curl -H "Authorization: Bearer $TOKEN" \
     -o report.pdf \
     https://fab.krons.cx/dav/atlas/out/report.pdf

multi-user: peek at a per-user memory file

Per-user memory lives at <group>/users/<user>.md. With operator grants you can list them all:

curl -X PROPFIND \
     -H 'Depth: 1' \
     -H "Authorization: Bearer $TOKEN" \
     https://fab.krons.cx/dav/atlas/users/

per-client setup notes

rclone (recommended for scripts and headless boxes)

One-liner config (interactive prompts skipped):

rclone config create arizuko webdav \
    url=https://fab.krons.cx/dav/ \
    vendor=other \
    bearer_token=$TOKEN

Mount with the VFS cache so writes survive editor save-rename dances:

rclone mount arizuko:atlas ~/atlas \
    --vfs-cache-mode writes \
    --dir-cache-time 30s

macOS Finder

  1. In Finder, Go → Connect to Server (Cmd-K).
  2. Enter https://fab.krons.cx/dav/atlas/ (include the trailing slash and the group name).
  3. When prompted, choose Registered User; leave the name blank and paste your Bearer token in the password field. Some macOS versions reject empty usernames — in that case sign in to /auth/login in Safari first; the JWT cookie is shared.

Linux davfs2

Install davfs2, then add to /etc/davfs2/secrets (root-owned, mode 0600):

https://fab.krons.cx/dav/atlas/  ""  <your-bearer-token>

Mount:

sudo mkdir -p /mnt/atlas
sudo mount -t davfs https://fab.krons.cx/dav/atlas/ /mnt/atlas

davfs2 sends credentials over HTTP Basic; proxyd only accepts Authorization: Bearer <JWT> or the refresh_token cookie. davfs2 will not authenticate. Use rclone on Linux.

Windows Explorer

  1. Open This PCMap network drive.
  2. Folder: https://fab.krons.cx/dav/atlas/
  3. Tick Connect using different credentials.
  4. Username blank, password = your Bearer token.

Windows’ built-in client is conservative about HTTPS WebDAV — if it refuses to connect, install rclone and use that instead.

curl

# read a file
curl -H "Authorization: Bearer $TOKEN" \
     https://fab.krons.cx/dav/atlas/CLAUDE.md

# list a directory (Depth: 1 = immediate children only)
curl -X PROPFIND -H 'Depth: 1' \
     -H "Authorization: Bearer $TOKEN" \
     https://fab.krons.cx/dav/atlas/

# upload a file
curl -X PUT --data-binary @./notes.md \
     -H "Authorization: Bearer $TOKEN" \
     https://fab.krons.cx/dav/atlas/notes.md

troubleshooting

303 redirect to /auth/login
Not signed in. Browser: follow the redirect and log in. curl/rclone: pass Authorization: Bearer <token>. Token comes from /dash/profile.
403 Forbidden on a path you can read elsewhere
Either (a) the write-block guard fired — you tried to PUT under logs/ or against a sensitive segment (.env, *.pem, .git) — or (b) you don’t have a grant on that group. journalctl -u arizuko_<inst> | grep "dav (forbidden|blocked)" tells you which.
404 Not Found at /dav/<group>/
Either the group folder doesn’t exist, or proxyd has no davProxy configured (response body: WebDAV not configured). Check that WEBDAV_ENABLED=true in the instance .env and that compose has been regenerated (arizuko run <inst>).
423 Locked
Another WebDAV client (Finder is the usual culprit) holds a lock. Unmount that client, or wait for the lock TTL. dufs implements per-file locks; they expire on their own but can persist for minutes after a hard disconnect.
“WebDAV not configured” from proxyd
DAV_ADDR is unset on the proxyd container. compose/compose.go sets it to http://davd:8080 when WEBDAV_ENABLED=true; if you toggled it off, davd isn’t in the compose graph. Set WEBDAV_ENABLED=true in .env and re-run arizuko run.
Edits don’t reach the agent
The write landed (no 403 in proxyd logs) but the agent hasn’t seen it. Either it has nothing pending to react to — new files don’t trigger a turn on their own; ping the agent in chat — or you wrote to a path the agent doesn’t consult (e.g. an ad-hoc folder outside media/, facts/, users/). Reference its CLAUDE.md for what it reads.

security model

TLS terminates at the public edge (nginx in front of proxyd). From there inward — proxyd to davd, davd to disk — traffic is plain HTTP on the Docker bridge network; the network namespace is the trust boundary. Identity is signed at proxyd with HMAC over X-User-Sub/X-User-Name/X-User-Groups headers, but davd doesn’t verify those today — it trusts that anything reaching it has already cleared requireAuth + davAllow + auth.Authorize upstream. Full threat model in SECURITY.md.

going deeper