fix(module-8): fail-fast backup check, credential walkthrough, define forge, reconcile prices

- verify-backup.sh: GIT_TERMINAL_PROMPT=0 so fetch/clone fail fast (clear warn)
  instead of hanging on an interactive credential prompt.
- README: provider-neutral first-push credential walkthrough (write scope vs 403,
  token-shown-once, invisible paste, helpers, SSH); UI labels flagged Verify.
- README: define "forge" on first prose use.
- README: reconcile the hosting price table with its own Verify caveats
  (Bitbucket/SourceHut figures web-verified; tiers/caveats no longer contradict).

Closes #38
Closes #39
Closes #47
Closes #52

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
This commit is contained in:
2026-06-22 17:15:28 -04:00
parent 6d28567c12
commit 61f6b510d1
2 changed files with 60 additions and 16 deletions
+52 -16
View File
@@ -49,9 +49,10 @@ is a full, equal Git repo that happens to live on a server.
This is the fact the entire rest of the module rests on, so sit with it: **because a remote is just
another copy, the commands you use to talk to it are identical no matter who hosts it.** `git push`
to GitHub is byte-for-byte the same operation as `git push` to a forge you run yourself in a
locked-down rack. The provider is a logistics decision — uptime, price, who can see it, where the
servers sit — not a Git decision. We lean on GitHub as the worked example below *only* because it's
to GitHub is byte-for-byte the same operation as `git push` to a **forge** (a Git hosting platform —
GitHub, GitLab, Gitea, Forgejo, and the like) you run yourself in a locked-down rack. The provider is
a logistics decision — uptime, price, who can see it, where the servers sit — not a Git decision. We
lean on GitHub as the worked example below *only* because it's
the one you're most likely to hit first, not because the mechanics change anywhere else.
The local-to-remote vocabulary is small:
@@ -102,12 +103,36 @@ where to go.
Everyone hits at least one of these. Recognizing them by their error text saves an afternoon.
**1. Authentication fails.** You push and get `Authentication failed` or `Permission denied
(publickey)`. The cause is almost always that you tried to use an account password (dead) or haven't
set up a token / SSH key. Fix: for HTTPS, generate a personal access token in the host's settings and
use it as your password when prompted; for SSH, generate a key (`ssh-keygen`) and paste the public
half into the host's SSH-keys settings. This is host-specific UI but the *concept* is identical
everywhere.
**1. Authentication fails.** You push and get `Authentication failed`, `Permission denied
(publickey)`, or a `403`. Two different causes hide behind that wall, and they have different fixes.
The common one is *no usable credential at all* — you tried an account password (dead on every modern
host) or never set up a token / SSH key. The sneakier one is a credential that *exists but lacks the
right scope*: a token authenticates fine and then the push is refused with `403` because the token was
never granted write access to repositories. They look alike but you fix them differently — create a
credential vs. *edit the existing token's scopes* (don't regenerate it). For the no-credential case:
for HTTPS, generate a personal access token in the host's settings and use it as your password when
prompted; for SSH, generate a key (`ssh-keygen`) and paste the public half into the host's SSH-keys
settings. This is host-specific UI but the *concept* is identical everywhere — the callout below walks
the shape of getting one.
> ### Getting a credential (the shape)
>
> The exact menu names and scope labels drift per host, so treat these as the *shape*, not gospel
> (**Verify-before-publish** the specific UI wording for your forge):
>
> - **Scope is the gotcha — check it first.** In the host's **Settings → developer / access tokens →
> create token**, you must grant the token write access to repositories: usually a scope literally
> named `repo`, or a "read **and write**" toggle on the repositories resource. A token created
> *without* it authenticates and then `403`s on push — it looks like an auth failure, but the fix is
> to **edit the token's scopes**, not to delete and recreate it.
> - **The token is shown once.** Hosts reveal the value a single time at creation. Copy it the moment
> it appears; if you lose it you create a new one rather than recover the old.
> - **Pasting it is invisible, and only happens once.** When Git prompts for your "password," paste
> the token — most terminals show *nothing* as you paste a secret, which is normal, not a failure.
> A **credential helper** (`git config --global credential.helper …`, e.g. `store`, `cache`, or your
> OS keychain) remembers it after the first success so you aren't pasting it on every push.
> - **SSH is the alternative.** A key you've added to the host skips passwords entirely: more setup
> once, no token to scope or cache afterward.
**2. The remote isn't empty (non-fast-forward).** You let the host create the repo *with* a README,
then push, and get `! [rejected] ... (fetch first)` or `non-fast-forward`. The remote has a commit
@@ -163,10 +188,10 @@ the forge; you just use it) and **self-hosted** (you run the forge on your own i
|---|---|---|---|---|
| **GitHub** | Free; Team ~$4/user; Enterprise ~$21/user | GitHub Actions, built in (Free tier includes a monthly minutes allowance for private repos; unlimited for public) | **Deepest.** Most agents, MCP servers, and AI reviewers target GitHub first | Zero ops — pure SaaS |
| **GitLab** (SaaS) | Free (capped users/namespace, small CI allowance); Premium ~$29/user; Ultimate ~$99/user | GitLab CI/CD — among the most mature, deeply integrated pipelines | Strong; first-party AI assistant plus growing agent support | Zero ops as SaaS; also self-hostable (see below) |
| **Bitbucket** (Atlassian) | Free (≤5 users); Standard ~$3/user; Premium ~$6/user | Pipelines, built in (small free monthly build-minute allowance) | Growing; tightest value is deep Jira/Atlassian tie-in | Zero ops as SaaS; Data Center edition self-hostable (enterprise pricing) |
| **Bitbucket** (Atlassian) | Free (≤5 users); Standard ~$3.65/user; Premium ~$7.25/user | Pipelines, built in (small free monthly build-minute allowance) | Growing; tightest value is deep Jira/Atlassian tie-in | Zero ops as SaaS; Data Center edition self-hostable (enterprise pricing) |
| **Azure DevOps** | First 5 users free; Basic ~$6/user beyond; pipelines ~$40/parallel job after a free job | Azure Pipelines, built in (one free parallel job + monthly minutes) | Good within the Microsoft ecosystem; Copilot integration | Zero ops as SaaS; Azure DevOps Server self-hostable |
| **Codeberg** | Free (FOSS projects only; soft repo/storage caps) | Forgejo Actions (it runs Forgejo) | Via API/MCP; not a first-tier agent target | Zero ops; nonprofit-run, no commercial/closed-source hosting |
| **SourceHut** | Paid to host: ~$5 / $10 / $15 tiers (reduced ~$2); free to *contribute* | builds.sr.ht, built in | Minimal first-class AI tooling; reachable via API | Zero ops as SaaS; fully self-hostable (it's open source) |
| **SourceHut** | Paid to host: ~$5 / $10 / $15 (all tiers buy the *same* service — "pay what's fair"); reduced ~$2 rate / financial aid if the full price is a hardship; free to *contribute* | builds.sr.ht, built in | Minimal first-class AI tooling; reachable via API | Zero ops as SaaS; fully self-hostable (it's open source) |
**Self-hostable open-source forges (you run it):**
@@ -343,6 +368,12 @@ independent* copy, history and all — not a snapshot.
commit count as your local repo — i.e. the offsite copy is complete, not partial. Read its output;
the green line is your evidence that the backup is real.
> On the **HTTPS + token** path with a *private* repo, the clone check (c) needs your credential
> helper to have cached the token from your earlier push — otherwise it can't authenticate to clone.
> The script won't hang waiting for a prompt (it disables interactive credential prompts); it just
> reports a `NOTE` that it couldn't clone, and the push checks above still stand. SSH and public
> repos clone with no credential at all.
### Part C — The everyday loop
7. Edit the README in your *teammate* clone, commit, and push from there:
@@ -440,18 +471,23 @@ tables, and update the "as of" date when you do.
minutes allowance for private repos.
- [ ] **GitLab** tiers — Free (user/namespace caps, CI allowance), Premium, Ultimate per-user/month,
and the SaaS-vs-self-managed price split.
- [ ] **Bitbucket** tiers — Free user cap, Standard, Premium per-user/month, and free build-minute
allowance. (Sources disagreed between ~$23 and ~$56 at build time — re-confirm the exact
figures.)
- [ ] **Bitbucket** tiers — Free user cap, Standard (~$3.65), Premium (~$7.25) per-user/month, and
free build-minute allowance. (Reconciled against Atlassian's own pricing page on 2026-06-22;
stale third-party listings still quote ~$2/$5 — trust Atlassian's page, and re-confirm.)
- [ ] **Azure DevOps** — free-user count, Basic per-user/month, and the per-parallel-job pipeline
price plus free job/minutes.
- [ ] **Codeberg** — that it remains FOSS-only and free, and its current soft repo/storage caps.
- [ ] **SourceHut** — paid-to-host tiers ($5/$10/$15 and reduced rate were *proposed for 2026*;
confirm they're in effect and current).
- [ ] **SourceHut** — paid-to-host tiers ($5/$10/$15): the 2026 prices are now *in effect* for new
accounts (confirmed 2026-06-22), so they're no longer "proposed." Note all tiers buy the same
service ("pay what's fair"), with a reduced rate (~the earlier minimum) and financial aid for
hardship — re-confirm before relying on it.
- [ ] **Self-hosted forges** — that Forgejo/Gitea still ship GitHub-Actions-compatible CI, GitLab CE's
current minimum resource footprint, and whether OneDev/Gogs CI status has changed.
- [ ] **"GitHub integrates first" / AI-ecosystem maturity** — re-assess which forges are first-tier
agent and MCP targets; this gap narrows fast.
- [ ] **Self-host/hosted spans** — confirm GitLab still offers CE self-host, and Bitbucket/Azure DevOps
still offer their self-hostable editions, before describing either as spanning both camps.
- [ ] **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.
- [ ] Update the comparison's **"as of" date** to the build date.
@@ -15,6 +15,14 @@
set -u
# Fail fast instead of hanging. The clone and fetch below talk to the remote,
# and on the HTTPS+token path with no cached credential (a common fresh-Linux
# state) Git would stop to prompt for a username/password on the tty and block
# this check forever. Disabling interactive prompts turns that into a clean,
# non-zero failure that drops into the graceful warn branch below. SSH keys,
# public repos, and cached credential helpers are unaffected.
export GIT_TERMINAL_PROMPT=0
# --- tiny output helpers (fall back to plain text if no color) ---------------
if [ -t 1 ]; then
GREEN=$'\033[32m'; RED=$'\033[31m'; YELLOW=$'\033[33m'; BOLD=$'\033[1m'; RESET=$'\033[0m'