Skip to content

feat(helix-loader): allow managing trust from configuration#15602

Draft
maribu wants to merge 4 commits intohelix-editor:masterfrom
maribu:workspace-trust-via-config
Draft

feat(helix-loader): allow managing trust from configuration#15602
maribu wants to merge 4 commits intohelix-editor:masterfrom
maribu:workspace-trust-via-config

Conversation

@maribu
Copy link
Copy Markdown
Contributor

@maribu maribu commented Apr 7, 2026

Note

This depends on #15590 and includes all its commits. Only the last commit is added on top of #15590

This allows managing trust via the config.toml via the paths vector in the [editor.trust] section. The path of the workspace is matched against the entries in the path array while expanding globbing (a * matches a single unspecified path component, a ** matches all
subdirectories) and supporting a leading ~/ as shorthand for the home directory. Prefixing a path with ! can be used to deny trust. The last matching entry wins.

For the following example:

[editor.trust]
paths = [
  "~/repos/helix",
  "~/repos/foo/*",
  "~/repos/bar/**",
  "!~/repos/bar/untrusted"
]

This would result in the following trust levels assuming the home directory /home/user:

Path Trust Decision
/home/user/foobar undecided
/home/user/repos/helix trusted
/home/other/repos/helix undecided
/home/user/repos/helix/branch_a undecided
/home/user/repos/foo undecided
/home/user/repos/foo/branch_a trusted
/home/user/repos/foo/remote_a/branch_a undecided
/home/user/repos/bar/branch_a trusted
/home/user/repos/bar/remote_a/branch_a trusted
/home/user/repos/bar/untrusted untrusted

In case the configuration does not decide to trust or untrust a given working directory, the existing trust mechanism to prompt the user for each new working directory and storing the decision in an internal database is used.

In other words: Users that don't want to make use of the new interface and only use the old model can just leave the config.toml unchanged and will never be bothered with this. On the other hand users only wanting to use the configuration can do so using:

[editor.trust]
paths = [
  "!**",
  "~/repos/helix",
  ...
]

Since the first item (!**) matches every work space and denies trust, this configuration will deny trust to all workspaces unless later items override this.

The insecure configuration from the editor has been removed, as the same result can be achieved with:

[editor.trust]
paths= [ "**" ]

In the workspace trust code, the code to search a path in a file was
copy-pasted three times. This splits it out into a helper function.
Comment thread book/src/workspace-trust.md Outdated
Comment thread helix-loader/src/workspace_trust.rs
Comment thread helix-loader/src/workspace_trust.rs
@senekor
Copy link
Copy Markdown
Contributor

senekor commented Apr 7, 2026

I'm a little sceptical about the amount of features here. Do we need / want full globbing support? Maybe it's enough to parse the suffix /** ourselves, without allowing globbing in the middle of the path. Do we really need the !-prefix syntax and order-dependent conflict resolution? Why not just a list of trusted paths? The ability to change the default behavior from "prompt" to "untrust" seems like a separate concern to me. We can always add features in a later step, if the need becomes apparent. Just some thoughts.

@maribu
Copy link
Copy Markdown
Contributor Author

maribu commented Apr 8, 2026

Do we really need the !-prefix syntax and order-dependent conflict resolution?

I opened #15607 to collect the requirements voiced so far.

There are alternative approaches (like using regexes and negative lookahead instead of globbing) to implement an "trust all git worktrees in folder X except for those external branches with following naming pattern".

IMO using the .gitignore style configuration format is the better fit for the task, though.

The ability to change the default behavior from "prompt" to "untrust" seems like a separate concern to me. We can always add features in a later step, if the need becomes apparent. Just some thoughts.

I do generally agree that this is a separate concern.

However, being able to prevent the pop ups for good without blindly trusting all work spaces is a hard requirement for some users (I cannot express how much I'm annoyed by pop ups - and others will certainly be, too). And since we need the negation anyway, why not just solve two issues for the cost of one?

@maribu maribu force-pushed the workspace-trust-via-config branch from 2b982cd to 18d66c0 Compare April 8, 2026 07:19
@senekor
Copy link
Copy Markdown
Contributor

senekor commented Apr 8, 2026

And since we need the negation anyway, why not just solve two issues for the cost of one?

I agree there needs to be some way to default-untrust all workspaces to avoid the popups entirely. I don't agree that this solves two issues for the cost of one, though. Stuffing extra syntax into a string value doesn't keep the cost constant. In the below example, I find version (2) to be simpler.

# (1)
trust-paths = ["!/**", "~/my-trusted-repos/**"]

# (2)
default-trust = "no" # instead of "prompt"
trusted-paths = ["~/my-trusted-repos/**"]

@maribu
Copy link
Copy Markdown
Contributor Author

maribu commented Apr 8, 2026

That is simpler, but it cannot be used to express:

  1. Trust everything in ~/repos/helix/*
  2. Except for ~/repos/helix/ext-*

@senekor
Copy link
Copy Markdown
Contributor

senekor commented Apr 8, 2026

True. I question whether that complexity is needed. I think your example represents a git worktree where an external PR (untrusted) is checked out. That could be covered by putting all worktrees either in helix/int/ or helix/ext/. Then you can configure the trusted paths:

  • ~/repos/helix (main worktree)
  • ~/repos/helix/int/* (internal worktrees)

I understand there's a tradeoff here between more complexity in Helix and asking users to adjust their workflows to compensate for the lacking flexibility of Helix. But adding features later is easier than removing them, so I suggest adding features conservatively.

@maribu
Copy link
Copy Markdown
Contributor Author

maribu commented Apr 8, 2026

Just to be sure: Have looked at the code already? It's like three lines of code needed to implement the negation. I'd argue calling that complexity is a bit of a misnomer.

maribu and others added 3 commits April 18, 2026 17:20
When the workspace trust files become large, using a BufReader can
increase performance, as it won't block until the whole file is loaded
into RAM.
…RKSPACES

Since `quick_query_workspace()` and
`quick_query_workspace_with_explicit_untrust()` are currently called
seven times on startup, it makes sense to cache the result for the
currently used workspace. With this in place, the previous cache for
prompted workspaces could be merged into this.

Co-authored-by: xe_nul <iamxenul@gmail.com>
This allows managing trust via the `config.toml` via the `paths` vector
in the `[editor.trust]` section. The path of the workspace is matched
against the entries in the `path` array while expanding globbing (a
`*` matches a single unspecified path component, a `**` matches all
subdirectories) and supporting a leading `~/` as shorthand for the home
directory. Prefixing a path with `!` can be used to deny trust. The last
matching entry wins.

For the following example:

```toml
[editor.trust]
paths = [
  "~/repos/helix",
  "~/repos/foo/*",
  "~/repos/bar/**",
  "!~/repos/bar/untrusted"
]
```

This would result in the following trust levels assuming the home
directory `/home/user`:

| Path                                            | Decision            |
|:----------------------------------------------- |:------------------- |
| `/home/user/foobar`                             | undecided           |
| `/home/user/repos/helix`                        | trusted             |
| `/home/other/repos/helix`                       | undecided           |
| `/home/user/repos/helix/branch_a`               | undecided           |
| `/home/user/repos/foo`                          | undecided           |
| `/home/user/repos/foo/branch_a`                 | trusted             |
| `/home/user/repos/foo/remote_a/branch_a`        | undecided           |
| `/home/user/repos/bar/branch_a`                 | trusted             |
| `/home/user/repos/bar/remote_a/branch_a`        | trusted             |
| `/home/user/repos/bar/untrusted`                | untrusted           |

In case the configuration does not decide to trust or untrust a given
working directory, the existing trust mechanism to prompt the user for
each new working directory and storing the decision in an internal
database is used.

In other words: Users that don't want to make use of the new interface
and only use the old model can just leave the `config.toml` unchanged
and will never be bothered with this. On the other hand users only
wanting to use the configuration can do so using:

```toml
[editor.trust]
paths = [
  "!**",
  "~/repos/helix",
  ...
]
```

Since the first item (`!**`) matches every work space and denies trust,
this configuration will deny trust to all workspaces unless later items
override this.

The `insecure` configuration from the editor has been removed, as the
same result can be achieved with:

```toml
[editor.trust]
paths= [ "**" ]
```
@maribu maribu force-pushed the workspace-trust-via-config branch from be4caf5 to da77e64 Compare April 27, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants