Yes, I ended up taking both branches of your last question, but at different layers.
For hf_integrity_job.py, I removed the direct-run fallback entirely. The Job wrapper now requires the revision-bound webhook trigger context; without it, it fails explicitly and never executes the mounted checker. Local/manual working-tree validation still exists, but its entrypoint is repo_integrity.py directly. So the deployed Job no longer has a weaker Git-discovered Authority ingress sitting beside the manifest path.
For local Profile A, I kept Git-backed Authority and hardened it rather than pretending the problem disappeared with the Job branch.
The first change was the one your .git experiment pointed at directly: .git is no longer a Boolean existence predicate. The local provider now distinguishes positive absence, observation failure, and observed-but-unbound metadata before any tracked path set is trusted.
The supported shapes are deliberately narrow:
- an ordinary
.gitdirectory is qualified against Git's owncore.bareandcore.worktreesemantics; - a standard linked-worktree gitfile is accepted only when its private gitdir has the Git back-binding to that exact gitfile;
- a
.gitsymlink is rejected as unbound Authority rather than followed; - a foreign or malformed gitfile is rejected before path loading;
- the real submodule gitfile layout is not claimed as supported by this pass.
That exposed the same trust-boundary problem twice more upstream.
First, the git config calls used to establish Authority were themselves capable of being redirected by the ambient Git environment. In particular, a foreign GIT_COMMON_DIR could make a command naming the correct --git-dir read another repository's config, and Git's config-injection environment could alter a plain config query.
So qualification and consumption now share the same sanitized subprocess environment. The qualification-time git config --local calls and the final git ls-files invocation strip the repository-selection variables, GIT_INDEX_FILE, object-directory overrides, and the indexed GIT_CONFIG_COUNT / GIT_CONFIG_KEY_* / GIT_CONFIG_VALUE_* surface.
Second, qualifying the git-dir did not qualify the object inside it that actually supplies ls-files with its path set. A clean victim/.git with:
victim/.git/index -> other/.git/index
still made the fully explicit:
git --git-dir=victim/.git --work-tree=victim ls-files
return the other repository's paths.
So the local chain is now:
working-tree root -> git-dir binding -> index binding -> git ls-files
The qualified git-dir's index is inspected with lstat() before Git is invoked:
- absent -> allowed, because a fresh repository may not have an index yet;
- regular file -> accepted as the local Profile-A Authority object;
- symlink or other filesystem object -> Authority binding failure;
- non-absence observation failure -> Authority probe failure.
Only after that does the tool call Git, with the already-qualified --git-dir, explicit --work-tree, and sanitized environment.
The focused Authority regression suite now includes real Git witnesses for the foreign .git symlink, foreign gitfile, linked worktree, core.worktree, Git boolean spellings for core.bare, environment substitution, and the symlinked-index substitution. The current focused run is 32/32.
I stopped the hardening boundary there deliberately. Profile A still treats the regular local Git index as its Authority; it does not claim external revision binding or independent content provenance for the index bytes. Those stronger claims belong to the manifest/revision-bound profiles.
So the abstraction I ended up with is slightly stronger than the four-state .git classification alone:
some Git metadata observed != Authority bound to this root
and then, recursively,
Authority source qualified != Authority object qualified != the qualified Authority is what the subprocess actually consumed.
Your “one function up” observation turned out to be the right direction: the weakness was not just in the next predicate, but in the process that establishes the universe the rest of the checker is allowed to validate.