# Guard the canonical database path, not the base directory · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/commit/14a9306ea6ad4d11cb7e861952a79e5be477c679)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

Requested revision: 14a9306ea6ad4d11cb7e861952a79e5be477c679

Requested commit: 14a9306ea6ad4d11cb7e861952a79e5be477c679

Commit: 14a9306ea6ad4d11cb7e861952a79e5be477c679

Tree: d293d7cdf1e7a8df4f55e304ede0f86535ba5d65

Author: Theo Browne

Committer: Theo Browne

## Message

```
Guard the canonical database path, not the base directory

Macroscope found a bypass in the shared-home refusal: the guard
canonicalized the *base* directory, but a base can canonicalize to
itself while its `userdata` or `dev` subdirectory is a symlink into
`~/.t3`. The base comparison then passes and the seed destructively
replaces the real shared database — the exact accident the guard exists
to refuse. Reproduced with a symlinked fixture before fixing.

The database path is what gets opened, so it is what gets checked now:
canonicalize the resolved db path and refuse when it lies under the
canonical shared home. The same-source check moves to db paths for the
same reason. Guard ordering shifts after state-dir resolution, which the
guard now depends on; the missing-target check runs first either way.

Verified all three ways: the symlinked base is refused with the shared
database untouched, a direct --to at the shared home is still refused,
and a legitimate worktree seed still succeeds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

```

## Parents

- [6045ce23d0bd5a51b1a65ed9c5aeb42ca9050312](https://git.cafe/pingdotgg/t3code/commit/6045ce23d0bd5a51b1a65ed9c5aeb42ca9050312?format=markdown)

[Source at this commit](https://git.cafe/pingdotgg/t3code/tree/14a9306ea6ad4d11cb7e861952a79e5be477c679?format=markdown)
