feat: let an operator scope cache mounts per app - #18
Open
dviejokfs wants to merge 1 commit into
Open
Conversation
📓 Changelog previewThis is what your commits will add to the generated ## [Unreleased]
### Added
- Let an operator scope cache mounts per app |
Cache mount ids are derived from the cache name and its mount point, both constants per ecosystem, so every project built on a worker shares one /cache/npm, one /cache/pnpm, one /cache/yarn. For a content-addressed package store that is the point, and it is most of the value of caching at all, so it stays the default. But the mount is not a tenant boundary: install steps run app-controlled code as root and hold the store read-write, so on a worker shared between projects that do not trust each other, one build writes to a store the others read. AUTOPACK_CACHE_SCOPE=app mixes a digest of the app path into every id for operators who need that isolation, at the cost of a cold store per project. FNV-1a rather than DefaultHasher, whose output Rust does not promise to keep stable — an id that moved between autopack builds would silently discard every cache on upgrade. Refs #13
dviejokfs
force-pushed
the
feat/cache-scope
branch
from
August 6, 2026 08:07
d6febda to
d7f632e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #13.
The situation
cache_idisautopack-{name}-{sanitize(directory)}— the cache name and its mount point, both constants per ecosystem. Nothing app-specific enters it, so every project built on a worker shares one volume:Why this is not simply a bug
Sharing a content-addressed package store is the point of one. It is most of the value of caching at all, and per-app keys mean every project pays a cold install. So shared stays the default — this PR does not change what anyone gets today.
What is worth fixing is that the mount is not a tenant boundary and nothing said so. Install steps run app-controlled code as root — lifecycle scripts, and
pnpm run buildin the build step — and the install step is the one that holds the store read-write. On a worker shared between projects that are not mutually trusting, one build writes to a store the others read. pnpm's integrity checking limits what a consumer accepts but does not cover index/metadata files or anything a consumer's lockfile does not integrity-pin.AUTOPACK_CACHE_SCOPE=appgives operators in that position a switch:#12 corrected the comment on that line, which claimed the id already keyed the cache to the app's directory. This is the behaviour half.
Choices worth reviewing
DefaultHasher. Rust does not promiseDefaultHasher's output is stable across releases, and a cache id that shifted when autopack was rebuilt would silently discard every cache on upgrade. Twelve lines, no new dependency —sha2was deliberately dropped in build(deps): drop the unused sha2 dependency #7 and this is not worth bringing it back for.Test plan
cache_ids_are_shared_by_default_and_isolated_on_request— default id unchanged; two apps differ under scoping; two caches within one app still differcache_scope_is_opt_in_and_stable— digest is deterministic, distinct per path, fixed width, and pinned to a known value so a change to the hash is a test failure rather than a silent cache wipecargo test --workspace→ 231 passedcargo fmt --all -- --checkandcargo clippy --workspace --all-targets -- -D warningscleanLeft open in #13
Whether Temps Cloud specifically should default to
app. That is a deployment decision rather than a builder default, and it belongs with whoever operates the fleet.