4.5 KiB
ADR-2026-07-20-explicit-local-repository-trust: Explicit Local Repository Trust
Status: accepted Date: 2026-07-20 Area: backend, frontend
Context
Kandev uses repositoryDiscovery.roots to bound automatic filesystem scans, defaulting to the
current user's home directory. The same roots were also reused to reject manually entered local
repository paths and later Git operations. Packaged Windows users could therefore browse to a valid
repository outside their home directory but could not add or use it, and the packaged runtime did
not provide a durable configuration-file location for widening the roots.
The existing product already treats an explicitly selected local folder as trusted by the local
user, and repository records persist an exact local_path. Automatic traversal and explicit
selection have different risk and lifecycle characteristics and should not share one boundary.
Decision
repositoryDiscovery.roots and repositoryDiscovery.maxDepth govern automatic repository
discovery only. They do not determine whether a user may explicitly select a repository.
An explicit local repository selection is validated and canonicalized by the backend before it is persisted. The resulting repository record, scoped to its workspace, is the durable trust grant for that exact repository path. The grant does not extend to the repository's parent directory, drive, or other repositories beneath the same parent.
Git metadata indirection must preserve that exact grant. A normal .git directory must not redirect
its common directory, and a file-based .git pointer is accepted only when the target metadata has
the reciprocal backpointer and common-directory placement created by git worktree. Saved
repository operations also require the path to resolve to the same canonical location recorded at
creation time. Unverifiable layouts such as arbitrary .git pointers or --separate-git-dir are
rejected rather than treated as linked worktrees.
Read-only pre-registration operations may inspect an explicitly supplied path so the UI can validate it and show repository status before saving. Fetches and destructive Git operations must resolve a persisted repository identity server-side instead of trusting a raw path from the request. Provider-backed repositories may remain pathless until Kandev materializes them. Workspace-qualified routes must additionally verify that the persisted repository belongs to the workspace named by the route before reading provider or filesystem state.
Containment checks that remain necessary for automatic scans or nested Git metadata use canonical filesystem paths and platform-correct comparisons. Windows drive-letter casing, separators, and UNC volume semantics must not be implemented with a raw string-prefix comparison.
Consequences
- Native Windows, macOS, and Linux users can add an exact repository anywhere the Kandev process can access without changing a global scan root.
- Automatic discovery remains bounded and does not start traversing whole drives or newly trusted parent trees.
- Repository creation and local-path updates become authoritative validation boundaries instead of relying on prior UI validation.
- Legitimate linked Git worktrees remain usable, while unverifiable external Git-metadata layouts require a separate product and security decision before support is added.
- Git operations increasingly require repository IDs, which narrows the impact of forged raw paths but requires migration of existing path-oriented service and handler calls.
- Deployments exposed to untrusted users still need an authentication and authorization policy; discovery roots are not a substitute for that policy.
Alternatives Considered
- Persist user-editable global discovery roots. Rejected because selecting one repository should not grant access to every sibling repository or make automatic scans traverse a wider tree.
- Trust all drives for native desktop or CLI launches. Rejected because launch-mode detection is not a durable security boundary and the behavior would diverge across packaging modes.
- Search
~/.kandev/config.yamlor expose--configonly. Rejected as the primary fix because it leaves the normal Add Local Repository workflow broken and requires users to understand backend configuration. - Use the launcher's original working directory as the default root. Rejected because it is session-dependent, does not help repositories on other drives, and conflates process startup location with durable repository trust.