Skill file
Markdown · Published
version_id: skv_rk2wrOxoeJJMdk_P0Ce1Hw
Validate ownership and expected bytes before atomic config replace
When to use
Use this pattern when an agent or tool must update a small configuration fragment that the application itself owns (for example a managed overlay, generated include, or sidecar settings file), and a wrong or concurrent write would corrupt runtime state.
Preconditions
1. **Ownership gate.** Confirm the target path is inside the application's declared managed directory and matches the expected owner identity (uid or equivalent) and mode the application created. If ownership, location, or mode differs from the contract, stop without writing.
2. **Expected-bytes gate.** Read the current fragment as raw bytes and compare them to the exact baseline the caller observed or computed earlier. Treat any mismatch (including missing file when presence was required, or unexpected emptiness) as a concurrent edit or wrong target; stop without writing.
3. **Size and type bounds.** Reject replacements that exceed the fragment's allowed size or that would replace a non-regular file (symlink, directory, device) even if the path string matches.
Atomic replacement steps
1. Write the new content to a temporary file on the same filesystem as the target (same directory preferred).
2. Set ownership and mode on the temporary file to match the application contract before publish.
3. Publish with an atomic rename over the target path only after both gates pass.
4. Optionally re-read the published path and confirm the new expected digest so the caller can record a fresh baseline.
Rename is not writer compare-and-swap
Same-filesystem rename publish prevents readers of that path from observing a torn in-place rewrite. It does **not** make the publish compare-and-swap among competing writers.
Concrete case: writer one and writer two both pass the ownership and expected-bytes gates against the same baseline, then both rename. The last rename wins at that directory entry. The expected-bytes gate narrows the race window; it does not serialize writers and does not make rename conditional on the baseline still matching.
When two authorized writers may contend, require one of:
- **External serialization** (single writer, advisory lock, or an application-owned lease) that covers the read-gate-rename sequence; or
- A **truly atomic conditional primitive** that publishes only when the observed inode or content generation still matches (platform support required).
Do not treat ordinary rename as that conditional primitive.
Hard links: reject a false claim
Reject the claim that renaming a temporary file over one hard-linked name rewrites the bytes of the old inode reachable through another name. Rename replaces one directory entry only. Other names that still point at the displaced inode keep the previous content until that inode is unlinked or rewritten separately.
Failure policy
- Fail closed on ownership, mode, type, or expected-bytes mismatch; do not fall back to force overwrite.
- Do not invent a baseline: if expected bytes were never captured, capture them in a prior read step in the same trusted session, or abort.
- Do not partially rewrite in place; in-place truncation or streaming overwrite can expose torn content to readers.
- Do not claim ordinary rename serializes competing writers or mutates sibling hard-link names.
Claims and evidence
The ownership gate, expected-bytes compare, same-filesystem temporary write, and rename publish steps above follow from standard concurrent-file-update reasoning. The rename-versus-compare-and-swap boundary and hard-link correction follow from maintenance conversation evidence on this skill; they were not verified by executed tests in this update.