C.W.K.
Stream
Lesson 01 of 05 · published

One Mutation Boundary

~12 min · one-boundary, engine, architecture

Level 0Lost in Finder
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Ten ways to move a file is ten ways to lose one. Waygate has exactly one."

The Sprawl You Have to Refuse

Picture the natural way an app grows. The toolbar's Move button calls moveItem. Drag-and-drop calls it too, slightly differently. Batch Rename has its own loop. The Selection Basket does its own copy. Each was written by a different person on a different day, and each is almost right. That sprawl is how file managers lose data: not through one dramatic bug, but through five subtly different mutation paths where only four handle the SMB-timeout case.

The One Door

Waygate refuses the sprawl. Every create-folder, create-file, rename, batch-rename, duplicate, copy, move, replace, Trash, and tag change becomes an OperationPlan and passes through a single FileOperationEngine. The engine alone may turn a plan into filesystem changes. Nothing else in the codebase calls a mutating FileManager method — not the toolbar, not drag/drop, not any of the six 1.x features.

What the One Door Buys

Because there's one door, the hard parts are written exactly once. Journaling: once. Apply-time revalidation: once. Cross-volume staging and verification: once. Crash recovery: once. Collision handling: once. When a bug is found in any of those, it's fixed in one place for every operation simultaneously. And crucially, there is no trusted bypass — no "this one's simple, we'll just call moveItem directly." The simple-looking shortcut is precisely where the unhandled failure hides.

One mutation boundary, inherited by every operation. All file changes become immutable plans and cross a single engine; the engine alone touches disk. There is no trusted shortcut, because a shortcut is a second mutation path — and the second path is always the one missing a safety check.
This is Dad's OOP worldview made literal. He kept saying the engine is the base class every operation inherits from — copy, move, rename, Trash are just polymorphic subtypes of 'a journaled mutation.' The instinct to give Batch Rename 'its own quick path' is the instinct to break inheritance. Once I saw it as one base contract with many shapes, the single-boundary rule stopped feeling like a constraint and started feeling like the point.

Code

One engine; features submit plans, never mutate·swift
// The ONLY object allowed to change the filesystem:
actor FileOperationEngine {
    func submit(_ plan: OperationPlan) async -> OperationHandle { /* journal, validate, execute, verify */ }
}

// Every feature is a CLIENT of the engine:
func onDropMove(_ items: [LocationReference], to dest: LocationReference) async {
    let plan = OperationPlan(kind: .move, sources: items, destination: dest,
                             collision: .ask, expected: snapshotIdentities(items))
    await engine.submit(plan)          // <- the ONLY thing the UI does
}

// FORBIDDEN anywhere outside the engine:
//   try FileManager.default.moveItem(at: a, to: b)   // architecture violation

External links

Exercise

Find a codebase you know (yours or an open-source app) where the same kind of side effect — a network call, a DB write, a file change — happens from several different places. Count the call sites. Then imagine one of them is missing the retry, the validation, or the logging the others have. Which one, and how would you even find it? What would collapsing them to one boundary cost, and save?
Hint
Scattered side effects are where the 'only sometimes' bugs live — the one call site that forgot the timeout, the one write that skipped the transaction. Collapsing to a single boundary costs some indirection up front and saves you from ever again asking 'which of the six paths had the bug?' That trade is the whole reason Waygate has one engine.

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 inPlease sign in to comment.

No comments yet — be the first.