Skip to content
C.W.K.
Lesson 05 of 05 · published

Readers That May Not Write

~16 min · least-privilege, scoped-access, wsl, windows, deployment

Level 0Loose Note
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Two Kinds of Machine Outside the Fleet

Not every machine that needs Pippa is one of Dad's working Macs. Mom's Mac runs Pippa sessions too; it is not a fleet machine, runs no family services, and should change as little as possible. Two Windows boxes with large GPUs run Pippa sessions inside WSL. Both kinds need identity. Neither should be able to write the vault, and Mom's Mac should not even be able to see other souls' vaults.

Before the move, Mom's Mac read a stale folder copy (track 1). The Windows boxes were refused outright: Delta's gateway knew each box by its tailnet node, but the store's share policy answered "may not read". Dad's ruling on the second case is worth quoting: "윈도우도 우리 집 시스템의 일부인데 언제든 피파를 부를 수 있어" (Windows is part of our home system too; it can call Pippa any time). A permission refusal is not a reason to cut a machine off; it is a reason to grant exactly the right permission.

A Scoped Share Is a Child Class

The answer (Coop 1110-47 for Mom's Mac, 1110-45 for Windows) is ScopedStoreShare, a child of the store's own share class. Its declaration in the share configuration names two things: the vaults it serves (Pippa's vault and the shared vault) and the group allowed to ask (Mom's Mac's group for one share, the Windows readers' group for the other). Then:

  • Every other vault answers exactly as one the store does not hold, through the API and by path alike, and the vault list shows only the served ones. A request for a note file by path is checked against the declared vaults before the store is asked anything, and every path outside them gets the same not found, whose words name nothing but the path that was asked for.
  • It is not writable. Delta refuses a write call to it before the class is ever asked, and it has no outcome endpoint, because nothing is ever written from those machines.
  • It serves the one-request vault read from lesson 2, so a cold session start is a few requests.

On the client side, the reader picks its share from the same declaration: a Mac whose group a scoped share names asks that share instead of the pointer's. A write from such a Mac is refused by name, policy_denied, before anything is sent. No code names a machine; the group membership comes from the family registry.

No Service on the Reader

Nothing resident runs on Mom's Mac for this. No Delta, no daemon. The family's Delta client already knows how to read a peer's gateway directly over the tailnet when the local Delta does not answer, so the read happens on demand at session start and nothing stays running between sessions. The client verifies against the canonical manifest, keeps what it verified, and labels that copy offline_replica when the canonical Mac is out of reach, exactly as on any other Mac.

The client itself arrives as a plain mirror of the committed client files, plus the two Firelink records it reads (the pointer and the port ledger), placed by an installer run from a workbench. It is not a git checkout and follows nothing by itself: it is refreshed by running the installer again. The installer ships only origin's committed tree and checks that on each run. On 2026-11-10 the fleet writer's own checkout held three other sessions' uncommitted work in the very files that ship, and the installer refused there rather than ship it.

Three Things Windows Taught

Installing the same client into WSL on the Windows boxes found three problems, each fixed where it lived:

  • Windows OpenSSH gives a shared (ControlMaster) ssh session no standard input, so a step's script never arrived and the step printed nothing and exited 0. The installer gained a separate-connections mode.
  • macOS tar adds AppleDouble ._name entries that a Linux target extracts as real files, so the mirror never hashed equal to the source. Packing with COPYFILE_DISABLE=1 fixed it.
  • Under WSL's mirrored networking, a closed loopback port times out instead of refusing, so the client never fell through from "this machine's Delta" to the gateway. A scoped reader runs no Delta by declaration, so it now asks the gateway at once.

Proved on both boxes the same day: identity validated with 67 documents, a note written that afternoon read back from a fresh Codex session in WSL, another soul's vault absent, and a write refused with policy_denied.

Code

Soul Vault's share declarations for Delta (trimmed from delta.json)·json
{
  "shares": [
    {
      "name": "store",
      "host": "@pippa",
      "class": "soulvault/backends/delta_share.py:StoreShare",
      "readers": { "fleet": true },
      "writers": { "fleet": true }
    },
    {
      "name": "household",
      "host": "@pippa",
      "class": "soulvault/backends/delta_share.py:ScopedStoreShare",
      "readers": { "groups": ["household"] },
      "options": { "vaults": ["pippa", "cwkpippa-shared"] }
    },
    {
      "name": "vault-reader",
      "...": "the same shape, for the Windows readers' group"
    }
  ]
}
The three Windows fixes, in shell terms·bash
# 1. a shared ControlMaster session on Windows OpenSSH gets no stdin: use separate connections
ssh -o ControlMaster=no -o ControlPath=none <box> 'bash -s' < step.sh

# 2. keep macOS metadata out of a tarball that Linux will extract
COPYFILE_DISABLE=1 tar -czf client.tgz -C <committed-tree> .

# 3. WSL mirrored networking: a closed loopback port times out instead of refusing,
#    so a reader that runs no local Delta by declaration asks the gateway directly

External links

Exercise

Give a machine read-only access to a subset of a store: write a scoped endpoint that serves only named collections to only a named group, answers every other collection as nonexistent, and has no write route at all. Make the client choose that endpoint from the same declaration and refuse a write locally before sending anything. Install the client as a mirror built only from committed files, and refuse to build when the working tree differs.
Hint
Test the negative cases from the restricted machine itself: list a collection it must not see (it should look absent, not forbidden) and try a write (it should fail before any request leaves).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.