fix(node-sync): materialize the git identity into the context mount, not the overlay home#552
Merged
Merged
Conversation
…not the overlay home The agent still committed as "Centaur AI" after #546, with the identity file plainly on disk. The include mechanism poisons itself: entrypoint.sh runs `git config` at POD CREATION. git reads the global config, resolves the [include] target, gets ENOENT, and the kernel caches a NEGATIVE dentry for that path -- minutes before any claim exists. So the lookup has ALWAYS already missed by the time node-sync learns who the user is, and the only question is whether that negative entry gets invalidated. Overlay mount instances keep independent dentry trees, so a node-side create never invalidates the pod's entry -- into `upper` (shipped, failed) or through `merged` (#546, also failed). Forensic signature: readdir lists the file while lookup returns ENOENT. A bind mount of one ext4 superblock shares the dentry tree, so the create IS observed after a failed lookup. `~/context` is exactly that. Move the include target there. Measured both ways on a live prod pod before writing this. - Dockerfile: include.path -> /home/agent/context/.atrium-git-identity - node-sync: write into scoped_atrium_root (the context root), not the overlay - tests: assert through a bind mount AFTER a negative lookup -- the shape of the actual bug. The old test wrote before looking up, so it passed on the broken design too; that is how this shipped twice. - CONTRACT.md: record why, so it does not get tidied back into the home
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.
What
Agent commits still landed as
Centaur AIafter #546 — with the identity file sitting on disk, readable from the node. This moves the[include]target from the agent's overlay home onto the context mount (~/context/.atrium-git-identity).Why the overlay home can never work
The include mechanism poisons itself, and the ordering is not a race — it's guaranteed:
entrypoint.shrunsgit configat pod creation. git reads/opt/centaur/gitconfig, resolves the[include]target, getsENOENT, and the kernel caches a negative dentry — minutes before a claim exists to say who the user is. By the time node-sync writes the identity, the lookup has already missed. The only question is whether that negative entry gets invalidated.Overlay mount instances keep independent dentry trees, so a node-side create never invalidates the pod's entry — neither writing into
upper(shipped, failed) nor throughmerged(#546, failed). The forensic signature isreaddirlisting the file whilelookupreturnsENOENT.A bind mount of a single ext4 superblock shares one dentry tree, so the create is observed even after a failed lookup.
~/contextis exactly that (hostPath/var/lib/centaur/atrium/<session>,readOnlyon the pod side — the agent can read its identity but can't clobber it).Measured on a live prod pod, both ways, before this was written.
Verification
Negative control in a privileged container with a real-fs upperdir — proves the test discriminates rather than passing vacuously:
upperPrivileged Docker gate green:
cargo fmt --check,cargo clippy --all-targets -D warnings, fullcargo test(27 tests) including the newgit_identity_visibilityrunning as root (not skipped).Prod confirmed on
CENTAUR_SANDBOX_OVERLAY_FLAT_HOME=true, so~/contextis the context mount path.Notes
cargo testlane is unprivileged and reports this file as "ok" while skipping every case; the privileged step (renamed here) is what actually runs it.Centaur AI, i.e. pre-existing behavior.