Replicator authority: spike notes (the driver's VFS route; the admission as the existing Start commit moved before permission)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 file changed,
+15
−0
docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md+15 −0
CI passed — run details
diff --git a/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md b/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md| new file mode 100644 |
| index 000000000..ca6136036 |
| --- /dev/null |
| +++ b/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md |
| @@ -0,0 +1,15 @@ |
| +# Spike notes for the replicator's authority design |
| + |
| +Read-only findings (no code written or run), 2026-10-03 06:45, for plan step 0 of `2026-10-03-replicator-pinned-roots-design.md`. |
| + |
| +## The descriptor-rooted VFS on `modernc.org/sqlite` v1.55.0 |
| + |
| +- The driver ships a Go-registered VFS: `modernc.org/sqlite/vfs` registers a VFS table with `sqlite3.Xsqlite3_vfs_register` from Go (`vfs/patches.go:195`) and keeps Go state in `pAppData`. Its method table is a C source (`vfs/c/vfs.c`, 713 lines: `vfsOpen`, `vfsDelete`, `vfsAccess`, `vfsFullPathname`, `vfsRead`, `vfsWrite`, and locking that is a no-op) compiled through the same toolchain as the library, over an `fs.FS` and read-oriented. |
| +- So the route exists: a VFS implemented outside the library, registered by name, chosen per connection with `?vfs=<name>`. What ours must differ in: `xOpen` as `openat` from a retained directory descriptor with `O_NOFOLLOW|O_CLOEXEC|O_NOCTTY` for the main database and each derived name (journal, WAL, SHM); `xAccess` and `xDelete` as `faccessat` and `unlinkat` on it; `xFullPathname` returning the name unchanged (so no canonicalisation walks a tenant's ancestry); real `xLock`/`xUnlock`/`xCheckReservedLock` and `xShmMap`/`xShmLock`/`xShmBarrier`/`xShmUnmap` (WAL mode needs them; the demo's no-op locks are not acceptable), which can delegate to the default Unix VFS's file methods once the descriptor is open, since those operate on the file descriptor, not the path. |
| +- The spike's deliverable, when run: a throw-away program that registers such a VFS, opens a database and its WAL through a directory descriptor, writes, checkpoints, reopens, and shows with `fstat` that every file SQLite opened is beneath the descriptor; and the list of library entry points that take a pathname outside the VFS (none are expected for the connection; `sqlite3_open_v2` with `SQLITE_OPEN_URI` and the `vfs` parameter is the only path in). |
| +- Risk noted: the generated library's VFS structs are per-platform (`vfs_linux_amd64.go` and siblings); a VFS written in Go against them is per-platform too, and the agent builds for linux/arm64 as well as amd64 (the cross builds in the gate). |
| + |
| +## The admission's cost on the request path |
| + |
| +- `DurabilityClient.Start` (`internal/usage/durabilityledger.go:1007`) is already one transaction per attempt on a `synchronous=FULL` WAL database: an `INSERT` into `attempts`, `touchDay`, `noteInstant`, `persistSeq`, commit. The meter gives it `requestMeterBudget` (25 ms) and sends regardless of its outcome (`internal/lease/requestmeter.go`). |
| +- The design's admission is that same commit moved to before permission: the gate's answer waits for it, and a commit that misses the budget refuses the request instead of sending anyway. The cost is therefore not a second commit but a dependency: the request path's latency includes the ledger's commit, and a slow disk refuses requests rather than sending unrecorded ones. The spike's deliverable: the ledger's commit latency distribution on a box's disk under the replicator's request rate (litestream's sync interval per database times the fleet's size), and the budget to set from it. |