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

Changes Nobody Wrote

~15 min · quarantine, drift-detection, tamper-evidence, operations

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

Plain Files Can Be Touched

Keeping the notes as plain Markdown was a deliberate gift: the vault opens in any editor with every service stopped. The cost of that gift is that anything can change those files without asking the door. An editor left open on the tree. A sync client that wakes up with an old copy. A script someone wrote in a hurry. A session that opened a path instead of calling soul-vault write. None of those leaves a commit, a request id, an actor or a reason.

The easy reactions are both wrong. Accepting such a change silently makes the door optional: the history and the state stop describing the vault. Reverting it silently throws away what might be Dad's own edit. Soul Vault does neither. It holds the change.

Held, Never Accepted, Never Lost

The external-edit guard is one shared class, HeldChanges in backends/guard.py; a child only tells it where its files and its accepted bytes are. On the Delta store it is always in enforce mode. When the read path or a scan finds a file on the canonical tree whose bytes differ from the accepted revision, or a file that appeared or vanished without a write:

  • The new bytes (or the fact of the deletion) are kept in a held entry, so nothing is lost.
  • Readers keep getting the accepted bytes, which git still has. Every session on every Mac goes on seeing the vault as the door last committed it.
  • Watchfire, the family's monitor, raises one alert per held change, carrying the exact commands that settle it.

Held entries are pending state, not history. They exist only until someone decides.

Two Ways to Settle

  • Apply (soul-vault quarantine apply): the held bytes are written through write_note, with compare-and-swap against the revision the change was held against. The change enters the history like any other write, with an actor and a reason. If a later real write has overtaken it, the apply is refused with revision_conflict; the guard never resolves a disagreement by last-write-wins.
  • Discard (soul-vault quarantine discard): the accepted bytes are put back on the tree and the held entry is dropped. Only a human actor may discard: in practice, only Dad decides that a change made outside the door should vanish.

Before any of this can work, the guard needs a baseline: what "accepted" means for every file. The folder-wrapping child recorded one with quarantine adopt, and a guard asked before that existed refused by name. The Delta store needs no such step: its baseline is its own committed bytes, so quarantine adopt there is refused with unsupported_capability, which says to apply the held change or let Dad discard it. Both settling commands also need --actor, the name of whoever decides; a discard needs --actor-kind human as well.

Run for Real

On the evening of 2026-11-10 the rare-path trial (Coop 1110-42) tested the guard on the live store: an edit, a created file and a removed file were each made directly on the tree. Each was held. Readers on the canonical Mac and on another Mac kept the committed bytes. Watchfire alerted once per held change with the settling commands. A discard by anyone but Dad was refused. Each apply went through write_note and appeared in the note's history. And an apply of an edit that a later write had overtaken was refused with revision_conflict.

Observe Before You Enforce

The guard did not start in enforce mode everywhere. During part 1, when cwkPippa still wrote some notes directly and the old folder's sync was still running, it ran in observe on the canonical Mac: drift was reported (by soul-vault quarantine status) but readers kept the disk. The plan for the old store was explicit: enforce only after the census reached zero and the folder's sync was off. The Delta store is enforce by design, because it arrived after part 1 had moved readers and writers to the door. Turning on a strict guard while honest writers still bypass it only teaches everyone to ignore its alerts.

Code

The guard's verbs·bash
soul-vault quarantine status            # what is held, and against which revision
soul-vault quarantine scan              # look for changes no write_note made
soul-vault quarantine apply <entry> --actor <who>
                                        # write the held bytes through write_note (CAS)
soul-vault quarantine discard <entry> --actor <who> --actor-kind human
                                        # put the accepted bytes back (Dad only)

# quarantine adopt recorded the baseline for the folder-wrapping child. The Delta
# store refuses it (unsupported_capability): its baseline is its own committed bytes.
Hold, don't accept and don't revert (sketch of the idea)·python
def read(note):
    accepted = state.accepted_sha(note)          # what the door last committed
    on_disk = sha256(file_of(note).read_bytes()) if file_of(note).exists() else None
    if on_disk != accepted:
        hold(note, file_of(note), against=accepted)  # keep the outside bytes, alert once
        return git_show(note, accepted)               # readers keep the accepted bytes
    return file_of(note).read_bytes()

def apply_held(entry, actor, request_id):
    # through the door, with compare-and-swap on the revision it was held against
    why = f"apply the held external {entry.kind} {entry.id}"
    if entry.kind == "delete":                       # a file removed outside the door
        return vault.delete_note(entry.note, expected_revision=entry.against,
                                 actor=actor, request_id=request_id, reason=why)
    return vault.write_note(entry.note, entry.text, expected_revision=entry.against,
                            actor=actor, request_id=request_id,
                            create=(entry.kind == "create"), reason=why)

External links

Exercise

For a directory your service owns but humans or other tools can also edit, write a guard: record a baseline of hashes, detect files that changed, appeared or vanished outside your write path, hold the new bytes in a pending area, keep serving the baseline bytes, and offer two settle commands, apply through your normal write path with a conflict check, and discard restricted to a named human.
Hint
Decide first what readers see while a change is held. Serving the outside bytes makes the guard a logger; serving nothing makes it an outage. Serving the last accepted bytes is what keeps the system honest and up at once.

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.