Follows #177. The GitHub copy needs a write credential. A fine-grained token can only be made by a person in the browser. A deploy key writes to exactly one repo, can be added through GitHub's API (from the Mac's gh), and is revoked in one click. So sync.py learns SSH:
The setting: a copy can name ssh_key (a secret holding an SSH private key) instead of token, for an ssh:// or git@host: URL.
The key on disk: written 0600 in the run's temp folder and gone with it. It is scrubbed from any message, like tokens.
Host keys: pinned. github.com's published keys are built in; another host needs its keys in the copy's known_hosts, or the copy fails. StrictHostKeyChecking=yes, so nothing is trusted on first use.
time/sync.json: the GitHub copy is now git@github.com:teahubxyz/time.git with ssh_key: GITHUB_MIRROR_KEY.
sync.yml: passes GITHUB_MIRROR_KEY and installs openssh-client if the job image lacks it. It's a workflow change.
Test 83 adds: host parsing; the key file at 0600 with the pinned github.com key; an unknown host refused without known_hosts; a copy over a key syncs and leaves no SSH environment behind; the key is scrubbed; a missing key secret skips the copy. test_time.py passes locally.
Follows #177. The GitHub copy needs a write credential. A fine-grained token can only be made by a person in the browser. A **deploy key** writes to exactly one repo, can be added through GitHub's API (from the Mac's `gh`), and is revoked in one click. So `sync.py` learns SSH:
- **The setting:** a copy can name `ssh_key` (a secret holding an SSH private key) instead of `token`, for an `ssh://` or `git@host:` URL.
- **The key on disk:** written 0600 in the run's temp folder and gone with it. It is scrubbed from any message, like tokens.
- **Host keys:** pinned. github.com's published keys are built in; another host needs its keys in the copy's `known_hosts`, or the copy fails. `StrictHostKeyChecking=yes`, so nothing is trusted on first use.
- **`time/sync.json`:** the GitHub copy is now `git@github.com:teahubxyz/time.git` with `ssh_key: GITHUB_MIRROR_KEY`.
- **`sync.yml`:** passes `GITHUB_MIRROR_KEY` and installs `openssh-client` if the job image lacks it. It's a workflow change.
**Test 83 adds:** host parsing; the key file at 0600 with the pinned github.com key; an unknown host refused without `known_hosts`; a copy over a key syncs and leaves no SSH environment behind; the key is scrubbed; a missing key secret skips the copy. `test_time.py` passes locally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_017K4vyY3yUD3GsvoZaAtKkD
A GitHub deploy key writes to one repo and nothing else, and GitHub's API can make one (a fine-grained token needs a
person in the browser). The key is written 0600 in the run's temp folder; github.com's published host keys are built
in and other hosts need theirs in known_hosts, so nothing is trusted on first use.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017K4vyY3yUD3GsvoZaAtKkD
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follows #177. The GitHub copy needs a write credential. A fine-grained token can only be made by a person in the browser. A deploy key writes to exactly one repo, can be added through GitHub's API (from the Mac's
gh), and is revoked in one click. Sosync.pylearns SSH:ssh_key(a secret holding an SSH private key) instead oftoken, for anssh://orgit@host:URL.known_hosts, or the copy fails.StrictHostKeyChecking=yes, so nothing is trusted on first use.time/sync.json: the GitHub copy is nowgit@github.com:teahubxyz/time.gitwithssh_key: GITHUB_MIRROR_KEY.sync.yml: passesGITHUB_MIRROR_KEYand installsopenssh-clientif the job image lacks it. It's a workflow change.Test 83 adds: host parsing; the key file at 0600 with the pinned github.com key; an unknown host refused without
known_hosts; a copy over a key syncs and leaves no SSH environment behind; the key is scrubbed; a missing key secret skips the copy.test_time.pypasses locally.🤖 Generated with Claude Code
https://claude.ai/code/session_017K4vyY3yUD3GsvoZaAtKkD