Skip to content

refactor: remove --untrusted - #18

Merged
bojieli merged 1 commit into
mainfrom
remove-untrusted-flag
Aug 22, 2026
Merged

refactor: remove --untrusted#18
bojieli merged 1 commit into
mainfrom
remove-untrusted-flag

Conversation

@bojieli

@bojieli bojieli commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Stacked on #17 (which is stacked on #16). Review those first; this PR's base is #17's branch.

What this changes

--untrusted promised three things and delivered one.

Two were already unconditional. No credential is sent to any target, and SSH agent forwarding is off for every target with no flag that turns it on (ForwardAgent: false, hardcoded). Printing those as one session's policy line implied the sessions without the flag were weaker — false in the direction that matters, because it understated the guarantee reach actually gives.

The third was real but nearly redundant. The helper tier — the only tier that writes to a target — was refused on such a session. But autonegotiation never selects that tier, so the flag could only fire against an operator who had typed --fileops=helper on the same line, and the refusal then told them to re-create the session without --untrusted. A speed bump with the detour signposted.

It also argued against reach's own posture. The premise everywhere else is that any target may be hostile — CONTRIBUTING.md says untrusted targets stay untrusted, docs/SECURITY.md says the target is not trusted. A flag called --untrusted implies the default is trusted, which is neither what reach does nor what those documents say.

So: removed, rather than renamed or reinforced.

  • Passing it fails with an explanation instead of the flag package's "flag provided but not defined" plus a usage dump — on both reach up and reach <target> <command>, and in the second form only before the command, since a flag after it belongs to the program being launched.
  • reach status loses its POLICY column, which would now always be -.
  • The docs that described the flag now describe what actually holds: nothing is written to a target unless the operator names --fileops=helper, and agent forwarding is off everywhere.
  • CONTRIBUTING.md's design rule is restated as every target is untrusted, and there is no flag that says otherwise.

Compatibility. Session files written by 0.1.0 and 0.1.1 still load. The untrusted field is ignored and SchemaVersion deliberately does not move for it: with no policy left for it to have meant, a document written by either build loads identically in the other, which is the condition that version guards.

Checklist

  • make check and make lint pass
  • make integration passes, if this touches transports or file operations — not run; tier selection is unchanged, only the removed refusal
  • Comments explain why where the code looks odd

If this changes what reach puts on a target:

  • It is opt-in, visible in reach doctor, and removable — unchanged: the helper tier is still opt-in by name, still listed by reach doctor, still removed by reach helper uninstall
  • Autonegotiation still cannot select it — this is now the only thing standing between an operator and a write, so the checklist item in PULL_REQUEST_TEMPLATE.md was rewritten to say that

Worth a maintainer's judgement: this leaves --fileops=helper as the sole gate on writing to a host. That was already true in practice, but it is now true without a second line of defence.

🤖 Generated with Claude Code

https://claude.ai/code/session_018WMXbmmHmEkyWWRc72uvPW

@bojieli
bojieli force-pushed the remove-untrusted-flag branch from 7565807 to 9103c33 Compare August 22, 2026 04:44
@bojieli
bojieli force-pushed the remove-untrusted-flag branch from 9103c33 to 3e66c6e Compare August 22, 2026 04:44
Base automatically changed from one-shot-target-form to main August 22, 2026 04:45
The flag promised three things and delivered one.

Two of them were already unconditional. No credential is sent to any
target, and SSH agent forwarding is off for every target with no flag
that turns it on. Printing those as one session's "policy" implied the
sessions without the flag were weaker, which is false in the direction
that matters: it understated the guarantee reach actually gives.

The third was real — the helper tier, the only tier that writes to a
target, was refused on such a session. But autonegotiation never selects
that tier, so the flag could only fire against an operator who had
typed --fileops=helper on the same line, and the refusal then told them
to re-create the session without --untrusted. A speed bump with the
detour signposted.

It also argued against reach's own posture. The premise everywhere else
is that any target may be hostile; a flag called --untrusted implies the
default is trusted, which is neither what reach does nor what
docs/SECURITY.md says it does.

Passing it now fails with an explanation rather than the flag package's
"flag provided but not defined" and a usage dump, on both `reach up` and
`reach <target> <command>` — and in the second form only before the
command, since a flag after it belongs to the program being launched.

Session files written by 0.1.0 still load. The field is ignored and the
schema version deliberately does not move for it: with no policy left
for it to have meant, a document written by either build loads
identically in the other, which is the condition that version guards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WMXbmmHmEkyWWRc72uvPW
@bojieli
bojieli force-pushed the remove-untrusted-flag branch from 3e66c6e to b9c4128 Compare August 22, 2026 04:45
@bojieli
bojieli merged commit 5c4ab11 into main Aug 22, 2026
22 of 23 checks passed
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.

1 participant