I reproduced this one too, and this was the point where I stopped adding position-specific checks and moved the implementation up one abstraction level.
Your alias case is real: lstat() on
alias/.git/worktrees/victim
only protects the final component. The kernel has already followed alias while resolving the pathname.
So the actual invariant is:
final component non-symlink != locator non-redirected
I replaced the position-specific path-redirection checks with a reusable lexical Authority-locator qualifier. Every Git-metadata-derived Authority locator is now walked component-by-component with os.lstat() before that locator is trusted:
- directory -> continue
- symlink / unexpected required object ->
RepositoryAuthorityBindingError - non-absence observation failure ->
RepositoryAuthorityProbeError
The existing semantic binding checks are still separate: ordinary .git binding, standard linked-worktree location, commondir, back-binding, and index qualification still establish what each object is expected to be and how the objects bind together. The new path walk establishes that the locator used to reach those objects was not redirected on the way there.
The same rule now covers the commondir, private gitdir back-binding, and index metadata files themselves before they are read or consumed.
I also fixed the related symlink + .. case. A relative commondir relationship is joined onto the already-qualified private gitdir without normalizing it first; the still-unnormalized lexical path is qualified component-by-component, and only then is it normalized for the comparisons that follow. Otherwise normpath() can erase the symlink component before it is ever observed.
The tests were generalized too: the exact alias witness remains, but there is now a lexical-prefix symlink matrix plus probe-failure and unexpected-object matrices, along with explicit symlink + .. witnesses. The focused Git Authority suite is 48/48.
I kept the previous assurance boundary:
Authority object qualified != Authority locator qualified != external/historical Authority provenance
Profile A now qualifies the first two. It still does not claim to reconstruct which repository the operator historically intended, or to attest host/container/bind-mount provenance.
There is one further non-claim worth making explicit: this is point-in-time pathname qualification, not race-free descriptor-anchored traversal. The qualifier performs lstat() observations and later consumers still reopen the locator by pathname. Closing concurrent namespace mutation between those steps would require a different layer based on fd-relative traversal / openat() / O_NOFOLLOW, which Profile A does not claim.
So I think this witness identified the right abstraction: the thing that needed qualification was the locator, not the latest metadata object we happened to notice.