Module 8: walk through GitHub PAT setup, link SSH as optional (#106)
CI / check (pull_request) Successful in 7s

Add a concrete "Set up GitHub authentication" subsection to the Module 8
lab, before Part A. It walks the PAT/HTTPS path step by step on GitHub as
the worked example (fine-grained token, Contents: Read and write scope,
copy-once, paste-at-password-prompt), links GitHub's official SSH docs as
the optional alternative, and gives a pros/cons table so the learner can
choose deliberately. Extend the Verify-before-publish checklist with the
GitHub-specific menu path and scope labels, since those drift.

Closes #106

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014strzwARMpFSrdSV3wi4Ns
This commit is contained in:
2026-06-23 20:26:05 -04:00
parent 7f439212ac
commit 2165122232
+87
View File
@@ -323,6 +323,88 @@ WSL, or Git Bash on Windows. Continues the `tasks-app` repo from Module 2.
*direct the agent* to do the git work (add the remote, push, clone, fetch, pull) and you verify
each result yourself. You don't type the git commands by hand.
### Set up GitHub authentication (do this first)
This is the one part you do by hand in the web UI, and it's failure mode #1 above: the single most
common first-push wall. Set it up *before* Part A so the push just works. You have two paths; do
**one**. This lab walks the **PAT / HTTPS** path step by step on GitHub as the worked example,
because it's all in the browser and needs no command-line setup. SSH is the optional alternative,
linked below.
> **Other host?** These are GitHub's exact menu paths as the worked example. On GitLab, Bitbucket,
> Codeberg, or your own Forgejo/Gitea the *shape* is identical (see the "Getting a credential" callout
> in the lesson) but the menu names drift; find your host's "access tokens" or "SSH keys" settings.
**Path 1: Personal access token (PAT) over HTTPS.** Generate a token in GitHub's web UI, then paste
it once when Git asks for a password.
1. On GitHub, go to your avatar (top right) → **Settings** → **Developer settings** (bottom of the
left sidebar) → **Personal access tokens**. GitHub offers two token types:
- **Fine-grained tokens** (recommended): scoped to a single repository, with explicit permissions.
This lab uses fine-grained.
- **Tokens (classic)**: older, broader; access is controlled by a coarse `repo` scope that grants
all your repos at once.
Pick **Fine-grained tokens** → **Generate new token**.
2. Fill in the token:
- **Token name:** anything memorable, e.g. `tasks-app-push`.
- **Expiration:** pick a real expiry (30 to 90 days is fine for the lab). Tokens expire by design;
that's a rotation cost you accept for the convenience.
- **Repository access:** choose **Only select repositories** and select your `tasks-app` repo. If
you haven't created the empty remote yet (Part A step 1), come back and select it after, or
create the repo first and then make the token. The token only needs to *reach* a repo that
exists.
- **Permissions → Repository permissions → Contents:** set it to **Read and write**. This is the
write scope, and it is *the* gotcha: a token without it authenticates fine and then `403`s on
push (failure mode #1's scope trap). GitHub auto-adds **Metadata: Read** when you do this; leave
it.
3. Click **Generate token** and **copy the value immediately.** GitHub shows it exactly once. If you
lose it, you generate a new one rather than recover the old.
4. At the first push (Part A step 2), Git prompts for a **username** and **password**:
- **Username:** your GitHub username.
- **Password:** paste the **token** (not your GitHub account password; password auth over HTTPS
was removed years ago). Most terminals show *nothing* while you paste a secret; that's normal,
not a hang. Press Enter.
A **credential helper** caches it after the first success (`git config --global credential.helper`,
set to `osxkeychain` on macOS, `manager` on Windows, or `store`/`cache` on Linux), so you paste the
token *once*, not on every push.
> **Verify-before-publish:** GitHub's menu wording, token-type names, and the **Contents: Read and
> write** permission label drift. Re-confirm the path **Settings → Developer settings → Personal
> access tokens → Fine-grained tokens** and the Contents scope before relying on these exact names.
**Path 2: SSH key (optional alternative).** A key you add to your account skips passwords entirely.
It's more upfront setup (generate a keypair, load the ssh-agent, paste the *public* key into GitHub),
but then there's no token to scope, expire, or cache. Follow GitHub's official docs, in order:
- [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
- [Adding a new SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)
- [Testing your SSH connection](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection)
If you go SSH, use the **SSH** URL (`git@github.com:…`) when you create the remote in Part A, not the
HTTPS one.
**Which should you pick?**
| | **PAT / HTTPS** | **SSH key** |
|---|---|---|
| **Setup** | Fast, all in the web UI; nothing to install | More upfront: keygen, ssh-agent, add the public key |
| **After setup** | Credential helper caches the token; otherwise re-paste | No prompts ever; nothing to cache |
| **Network** | Port 443; sails through corporate proxies/firewalls | Port 22; sometimes blocked on locked-down networks |
| **Maintenance** | Expires; needs rotation; the write-scope `403` trap; shown once | No expiry by default; no scope to misconfigure |
| **Risk to manage** | A leaked token until it expires/is revoked | A private key + passphrase on your disk |
Short version: **PAT** is the faster start and the friendlier path behind a corporate firewall;
**SSH** is the lower-friction *long-term* setup once you're past the initial keygen. Either one
satisfies the lab. If you're unsure, do the PAT.
### Part A: Create the empty remote and push
1. On your host's web UI, create a **new, empty** repository named `tasks-app`. Do **not** add a
@@ -514,4 +596,9 @@ tables, and update the "as of" date when you do.
- [ ] **Credential/token UI**: the "Getting a credential" callout names menu paths and the
write-scope label (`repo` / "read and write") generically; confirm the current wording and
scope name on the default-example host before publishing.
- [ ] **GitHub PAT walkthrough** (lab "Set up GitHub authentication"): confirm the menu path
**Settings → Developer settings → Personal access tokens → Fine-grained tokens**, the two token
types (**fine-grained** vs **classic**/`repo`), and that the write scope is **Repository
permissions → Contents: Read and write** (with **Metadata: Read** auto-added). These are
volatile GitHub UI labels; also re-confirm the three linked SSH docs URLs still resolve.
- [ ] Update the comparison's **"as of" date** to the build date.