Skip to content

fix(trust): route the interactive trust check through isDirectoryTrusted - #1355

Open
addyCooks wants to merge 2 commits into
Nano-Collective:mainfrom
addyCooks:fix/trust-check-shared-1339
Open

addyCooks wants to merge 2 commits into
Nano-Collective:mainfrom
addyCooks:fix/trust-check-shared-1339

Conversation

@addyCooks

Copy link
Copy Markdown
Contributor

Closes #1339

Description

isDirectoryTrusted is documented as shared by every trust-gated entry point (the TUI's useDirectoryTrust, --plain's runPlainShell, and the daemon boot path) so the resolution rule can't drift between them. That was true for --plain and the daemon but not the TUI: useDirectoryTrust still had its own inline path.resolve / trustedDirectories.some(...) comparison in checkTrustSync and handleConfirmTrust. Anyone hardening isDirectoryTrusted case-insensitive matching on Windows, realpath comparison against symlink tricks would have left the interactive path on the old rule.

Changes:

  • source/hooks/useDirectoryTrust.tsx: checkTrustSync and handleConfirmTrust now call isDirectoryTrusted. useDirectoryTrust is the only caller that also persists trust, so only the write side stays local. The docstring is now accurate as written. Behaviour is unchanged.
  • source/daemon/cli.spec.ts (fix(security): gate daemon start on directory-trust disclaimer #1259 nit): the two persistence assertions check isDirectoryTrusted(root, loadPreferences()) instead of trustedDirectories.includes(root), so they keep asserting "this directory is trusted" rather than one exact stored string if the rule is ever hardened.
  • source/cli.tsx (fix(security): gate daemon start on directory-trust disclaimer #1259 nit): the --trust-directory warning said it "only applies to non-interactive mode (nanocoder run ...)", stale since daemon start accepts it too. It now names both.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Changeset

  • Added a changeset (pnpm changeset) describing this change for the changelog

Testing

Automated Tests

  • New features include passing tests in .spec.ts/tsx files
  • All existing tests pass (pnpm test:all completes successfully)
  • Tests cover both success and error scenarios

Manual Testing

  • Tested with Ollama
  • Tested with OpenRouter
  • Tested with OpenAI-compatible API
  • Tested MCP integration (if applicable)

Checklist

  • If this was for an open issue, I was assigned to it
  • Code follows project style guidelines
  • Self-review completed
  • Documentation updated (if needed)
  • No breaking changes (or clearly documented)
  • Appropriate logging added using structured logging

useDirectoryTrust still carried its own path.resolve comparison in checkTrustSync and handleConfirmTrust, so the isDirectoryTrusted docstring's claim that every trust-gated entry point shares one resolution rule was false for the TUI. Both now call isDirectoryTrusted; only the write side stays local. Behaviour is unchanged. Also asserts persistence in daemon/cli.spec.ts through isDirectoryTrusted rather than an exact array match, and corrects the --trust-directory warning to name daemon start. Closes Nano-Collective#1339.
@github-actions

Copy link
Copy Markdown
Contributor

nc-review: comments — 1 important, 1 nit

@addyCooks — a few things worth a look, none blocking.

Routes the interactive trust check through the shared isDirectoryTrusted helper as the issue requested, picks up the two nc-review nits called out in the same issue's Proposed Fix, and adds a correctly-named changeset. The behavioural change is nil — checkTrustSync and handleConfirmTrust produce the same trust result they did before — and the underlying isDirectoryTrusted is already well-covered by preferences.spec.ts, so the consolidation is safe.

🟠 important · tests · source/hooks/useDirectoryTrust.tsx

There is no .spec.ts colocated with useDirectoryTrust.tsx, so neither checkTrustSync nor handleConfirmTrust is exercised directly. The PR is a refactor (delegation to isDirectoryTrusted, plus an array spread in handleConfirmTrust), and the underlying helper is covered in preferences.spec.ts, so this is not a regression introduced by the diff — but it is the gap that allowed the original duplication to ship. Adding a small spec that asserts (a) checkTrustSync returns trusted: true when isDirectoryTrusted says so and (b) handleConfirmTrust writes the normalized directory to preferences only when isDirectoryTrusted returns false would lock the consolidation in place so a future contributor can't quietly re-introduce an inline check.

⚪ nit · correctness · source/hooks/useDirectoryTrust.tsx:76

The pre-change code used preferences.trustedDirectories || []; the new code uses preferences.trustedDirectories ?? []. For this call site the difference is not observable ([...[]] is [] either way), so this is a harmless tightening, not a bug. Worth noting only because the old fallback also caught null, which ?? does too — so this is purely stylistic.


🔴 blocking · 🟠 a reviewer would ask for a change · ⚪ optional

Automated code review — correctness, security, design, tests, plus duplicates and scope. A human still decides; this is not a substitute for review and is not exhaustive. The required status checks separately cover lint, formatting, types, unused dependencies, the test suite and the build. This bot never merges. Maintainers can rerun with /re-review.

@github-actions github-actions Bot added the agent:comments nc-review left non-blocking findings label Sep 16, 2026
Adds a spec for useDirectoryTrust asserting that the hook reports trust exactly as isDirectoryTrusted does, and that handleConfirmTrust persists the normalized directory only when it is not already trusted - including when the stored entry is an un-normalized equivalent. Verified the spec fails if an inline exact-match check is reintroduced on either the read or the write side.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:comments nc-review left non-blocking findings area:tui Terminal UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] isDirectoryTrusted docstring claims the TUI shares it, but useDirectoryTrust still has its own copy of the check

1 participant