#157: convert forge worktree origins to SSH #177

Merged
ltms merged 3 commits from worker/fleetd-157-remote-url-5d7e49-5 into main 2026-08-28 01:10:38 +02:00
Member

Fixes #157. Provisioning changes the LTMS forge origin from HTTPS to SSH before it creates a linked worktree, so a credential cannot remain in the shared git config. Tests: mvn clean install (BUILD SUCCESS; 971 tests).

Fixes #157. Provisioning changes the LTMS forge origin from HTTPS to SSH before it creates a linked worktree, so a credential cannot remain in the shared git config. Tests: mvn clean install (BUILD SUCCESS; 971 tests).
agent added 1 commit 2026-08-28 00:54:38 +02:00
#157: convert forge worktree origins to SSH
CI / contract (pull_request) Successful in 1m10s
CI / build (pull_request) Successful in 1m11s
bcb402b688
Owner

Not merging this shape. Recording why, because "why not just use SSH remotes?" will be asked again.

#157 lists SSH remotes as option 1 and I briefed it as the default. That was wrong, for a reason that is only visible from outside this PR:

  1. A parallel change turns on memberCredentials.policy: allow-list. Under it, SSH_AUTH_SOCK is deliberately blocked for members even though the name is in the allow: list. It is a live agent handle, not a value — allowing it hands a member every key the operator's agent holds (see #110).

  2. On this host ~/.ssh holds no private key file at all — only authorized_keys, config and known_hosts. The git.ltms.dev identity exists solely inside the ssh-agent.

So an ssh:// origin can authenticate only through the agent, and the agent is about to be unreachable from members. This change would convert a working HTTPS origin into an SSH origin that a member cannot push with — a leaky-but-working setup traded for a secure-but-broken one, silently, for exactly the repos #157 is about.

The push in this PR succeeded because the fleetd repo's origin was already SSH and the agent is still reachable today. That proves SSH works now. It does not prove it works after the allow-list lands.

Going with option 2 instead: a git credential helper that supplies WORKER_GITEA_TOKEN at call time. That name stays allowed under allow-list, so it composes with the credential scrub rather than fighting it, and the origin stays HTTPS and clean — which is all #157 actually requires.

Two further changes requested on the same branch:

  • FORGE_HOST / FORGE_SSH_PORT are hardcoded. Config already carries gitHostEnv: GITEA_HOST. A security control that silently does nothing for any other forge host has a hole in it.
  • Add a post-provision check that reads the worktree's actual remote.origin.url and refuses to provision if user info is still present. Setting a value and never confirming it took is the same shape as #175.

Kept from this revision: provisioning-time placement, and aProvisionedWorktreeUsesTheForgeSshOrigin reading the worktree's real remote.origin.url rather than a formatter — that is the right test shape, and it should survive the rewrite with a new assertion.

Not merging this shape. Recording why, because "why not just use SSH remotes?" will be asked again. #157 lists SSH remotes as option 1 and I briefed it as the default. That was wrong, for a reason that is only visible from outside this PR: 1. A parallel change turns on `memberCredentials.policy: allow-list`. Under it, **`SSH_AUTH_SOCK` is deliberately blocked** for members even though the name is in the `allow:` list. It is a live agent handle, not a value — allowing it hands a member every key the operator's agent holds (see #110). 2. On this host `~/.ssh` holds **no private key file at all** — only `authorized_keys`, `config` and `known_hosts`. The `git.ltms.dev` identity exists solely inside the ssh-agent. So an `ssh://` origin can authenticate only through the agent, and the agent is about to be unreachable from members. This change would convert a working HTTPS origin into an SSH origin that a member cannot push with — a leaky-but-working setup traded for a secure-but-broken one, silently, for exactly the repos #157 is about. The push in this PR succeeded because the `fleetd` repo's origin was **already** SSH and the agent is still reachable today. That proves SSH works now. It does not prove it works after the allow-list lands. Going with option 2 instead: a **git credential helper** that supplies `WORKER_GITEA_TOKEN` at call time. That name stays allowed under `allow-list`, so it composes with the credential scrub rather than fighting it, and the origin stays HTTPS and clean — which is all #157 actually requires. Two further changes requested on the same branch: - `FORGE_HOST` / `FORGE_SSH_PORT` are hardcoded. Config already carries `gitHostEnv: GITEA_HOST`. A security control that silently does nothing for any other forge host has a hole in it. - Add a post-provision check that reads the worktree's actual `remote.origin.url` and refuses to provision if user info is still present. Setting a value and never confirming it took is the same shape as #175. Kept from this revision: provisioning-time placement, and `aProvisionedWorktreeUsesTheForgeSshOrigin` reading the worktree's real `remote.origin.url` rather than a formatter — that is the right test shape, and it should survive the rewrite with a new assertion.
ltms added 1 commit 2026-08-28 01:02:21 +02:00
#157: use environment git credential helper
CI / contract (pull_request) Successful in 1m3s
CI / build (pull_request) Successful in 1m37s
46ac6e4e38
ltms added 1 commit 2026-08-28 01:06:16 +02:00
#157: isolate worktree credential helpers
CI / contract (pull_request) Successful in 1m5s
CI / build (pull_request) Successful in 2m46s
ee8f570fd7
ltms merged commit 21c4c8cbef into main 2026-08-28 01:10:38 +02:00
ltms deleted branch worker/fleetd-157-remote-url-5d7e49-5 2026-08-28 01:10:38 +02:00
Owner

Correction to my own review reasoning on this PR (2026-08-28) — see #184.

While reviewing this I wrote that ~/.ssh holds no private key file and the forge identity lives only in the ssh-agent, and I used that to argue the change was urgent: block SSH_AUTH_SOCK and a member could not push at all.

That fact was wrong. I had looked only in ~/.ssh, which is four Include lines. ssh -G git.ltms.dev resolves a readable, passphrase-free IdentityFile elsewhere, and a live member with the socket blanked pushed over SSH fine.

The merged change is still correct — it takes the token out of git config, which was the real defect in #157, and it routes a member through its own scoped credential so its pushes are attributable and revocable. Only my urgency argument rested on the false fact. The javadoc on configureHttpsUrlRewriteForSshOrigin repeated the same claim and has been corrected on main.

**Correction to my own review reasoning on this PR (2026-08-28) — see #184.** While reviewing this I wrote that `~/.ssh` holds no private key file and the forge identity lives only in the ssh-agent, and I used that to argue the change was urgent: block `SSH_AUTH_SOCK` and a member could not push at all. That fact was wrong. I had looked only in `~/.ssh`, which is four `Include` lines. `ssh -G git.ltms.dev` resolves a readable, passphrase-free `IdentityFile` elsewhere, and a live member with the socket blanked pushed over SSH fine. **The merged change is still correct** — it takes the token out of git config, which was the real defect in #157, and it routes a member through its own scoped credential so its pushes are attributable and revocable. Only my urgency argument rested on the false fact. The javadoc on `configureHttpsUrlRewriteForSshOrigin` repeated the same claim and has been corrected on `main`.
Sign in to join this conversation.