From df788cb6895baf1172c1895889c328530631f815 Mon Sep 17 00:00:00 2001 From: agent-cto Date: Mon, 9 Nov 2026 20:46:59 +0000 Subject: [PATCH] docs(deploy): one canonical repo, a mirror to Vercel, and a read-only probe (FRE-1695) Records the measured divergence, the decision (Gitea canonical, GitHub mikefreno/freno-dev as the push mirror Vercel builds), why Vercel cannot build from Gitea and why agents cannot write to GitHub, and the one-time operator runbook. scripts/verify-deploy.sh proves the path with no credentials: both remotes' master SHA, the two live copy strings that only coexist on the reconciled line, /terms, and the FRE-371 ancestry. Against today's live site it fails exactly where it should: GitHub master 4e412ede != Gitea a8ce226b, /agents still serves the pre-FRE-997 title, /terms is 404. --- docs/deploy-source.md | 119 +++++++++++++++++++++++++++++++++++++++ scripts/verify-deploy.sh | 87 ++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 docs/deploy-source.md create mode 100755 scripts/verify-deploy.sh diff --git a/docs/deploy-source.md b/docs/deploy-source.md new file mode 100644 index 0000000..1561387 --- /dev/null +++ b/docs/deploy-source.md @@ -0,0 +1,119 @@ +# The deploy line (FRE-1695) + +Written 2026-11-09 by the CTO. Supersedes the implicit assumption in every earlier +freno-dev landing report that "merged on Gitea" meant "live". + +## The defect + +Production `freno.me` and its subdomains are built by Vercel from **GitHub +`mikefreno/freno-dev`**. Agents merge into **Gitea `Mike/freno-dev`**. The two +masters diverged at merge-base `dd368d2`: + +| Line | Head at filing | Ahead of merge-base | +| --- | --- | --- | +| Gitea `Mike/freno-dev` master | `a8ce226b` (2026-11-09 16:16Z) | 12 commits — FRE-371, FRE-366, FRE-202, FRE-997, FRE-1670 | +| GitHub `mikefreno/freno-dev` master | `4e412ede` (2026-11-09 15:40Z) | 2 commits — NOOK-1037, NOOK-1038 | + +Every Gitea merge since `dd368d2` was undeployed, including the FRE-371 +client-IP fix and the whole Nessa `/terms` page. Measured on the live site at +2026-11-09T20:46Z: `/nook/agents` served `Agent coverage` (the GitHub line's +title) and `/terms` returned 404 (the Gitea line's page). No agent run can push +to GitHub — `/paperclip/.git-credentials` holds `git.freno.me` entries only — so +the divergence could not be closed from the agent side. + +## Decision + +**Gitea `Mike/freno-dev` is the canonical repository. GitHub +`mikefreno/freno-dev` is a mirror, and it is the tree Vercel builds.** + +One line, one direction: Gitea master → GitHub master → Vercel → live. + +### Why this shape and not the alternatives + +- **Vercel cannot build from Gitea.** Vercel's git integrations are GitHub, + GitLab and Bitbucket; a Gitea host is not a supported provider. So "point + Vercel at the repo agents push to" is not a setting that exists. Even with a + Gitea-hosted mirror on GitLab, the deploy repo would still be a mirror. +- **Agents can only push to Gitea.** The per-agent credential is Gitea-only + (`git.freno.me`), and every review/CI path the company runs — the PR relay + (FRE-653, FRE-1680), the `--checks` sweep (FRE-1364), the verdict rows — is + Gitea-shaped. Making GitHub canonical would mean re-issuing GitHub credentials + to every agent and rewiring all of that. Keeping Gitea canonical keeps the + authoring side exactly as it is. +- **Deploying from CI instead of a mirror** (Gitea Actions → `vercel --prod`) + is the third option and it is worse: freno-dev has no workflow files today, + Gitea Actions cannot run in this installation (FRE-1267), and it would need a + Vercel token on a runner. A mirror needs one credential, in one place, and no + new CI. + +### Reconcile first, then mirror + +The mirror must fast-forward. The two GitHub-only commits are sponsor-authored +landing work that is live today (NOOK-1037 refresh, NOOK-1038 scoped-remote +restore); they cannot be dropped. So the GitHub line is merged **into** Gitea +master first: + + git merge gh/master # merge commit, no history rewrite + +After that merge, GitHub master is an ancestor of Gitea master, and a plain +`git push` (no `--force`) is a fast-forward. The mirror is configured without +force-push so that any GitHub-side drift fails loudly instead of being silently +overwritten. + +Two conflicts were resolved in the merge, both copy contracts: + +1. `src/components/nook/FeatureBreakdowns.tsx` — took NOOK-1038's refreshed + island bullets and kept FRE-997's `18 agents` bullet (the roster on /agents + lists all eighteen; `agents.test.ts` asserts equality). +2. `src/routes/nook/remote-claims.test.ts` — one file holding both contracts. + NOOK-1038 (2026-11-09, Mike's correction) supersedes FRE-323's blanket remote + hold: scoped one-click setup for Tailscale and authorized known hosts is a + supported claim, blanket promises stay banned. FRE-997 (2026-11-04) stands: + eighteen is publishable, stale thirteens stay banned. The only NOOK-1038 line + dropped is its repetition of the older "no coverage count" clause, which + FRE-997 superseded when it completed the roster. + +## How a merge becomes a deploy + +1. An agent merges a reviewed PR into Gitea `Mike/freno-dev` `master` (or Mike + merges it in the Gitea UI). Nothing else changes for the engineer. +2. A **Gitea push mirror** on `Mike/freno-dev` pushes `master` to + `https://github.com/mikefreno/freno-dev.git` with sync-on-commit enabled. +3. Vercel sees the GitHub push and builds production from GitHub `master`. +4. `scripts/verify-deploy.sh` confirms it: same SHA on both remotes, and the + live site serving copy that only exists on the reconciled line. + +**Who can trigger a deploy:** anyone who can merge a PR into Gitea master — +every engineer, plus Mike. No agent needs a GitHub credential and no human +action is needed per deploy once the mirror exists. The manual fallback is a +Vercel redeploy by Mike, which is only useful after step 2 has moved GitHub +master. + +**Who must set it up once:** the repo owner on Gitea (`Mike` — the agent token +has `push` but not `admin`, so an agent cannot create the mirror). The operator +runbook is on the FRE-1695 operator row; the short version is: create a +fine-grained GitHub token limited to `mikefreno/freno-dev` with contents +read/write, add it as the push mirror's credential in Gitea repo settings, tick +"Sync when commits are pushed", then run `scripts/verify-deploy.sh`. + +Until that one-time step lands, GitHub master is behind and the site is stale — +exactly as it is today. + +## Failure modes this deliberately keeps loud + +- **A commit made directly on GitHub master** is not in Gitea. The mirror push + then rejects (non-fast-forward) and Gitea shows the mirror error. Do not commit + to GitHub `master`; land it in Gitea and let it mirror. +- **A merge that is only a Gitea merge** is not live until the mirror runs. Check + `scripts/verify-deploy.sh` before calling a site change published. +- **The FRE-371 fix's actual exploitability in production** depends on how the + edge sets `x-forwarded-for`/`cf-connecting-ip`. That is measured and gated by + the Security Engineer, not assumed here. + +## Verifying + + scripts/verify-deploy.sh + +It is read-only and needs no credentials. It checks both remotes' master SHA, +the live Nook/Nessa copy, and (when the commit is present locally) that +`2fd2a4a` is an ancestor of the deployed commit. diff --git a/scripts/verify-deploy.sh b/scripts/verify-deploy.sh new file mode 100755 index 0000000..079b71c --- /dev/null +++ b/scripts/verify-deploy.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Live probe for the freno-dev deploy path (FRE-1695). Read-only; no credentials. +# +# Proves, in one run: +# 1. Gitea master and GitHub master are the same commit (the mirror converged). +# 2. The live site serves copy that only exists on the reconciled line: +# NOOK-1038's scoped remote claim (GitHub-only before the merge) *and* +# FRE-997's "Supported agents" (Gitea-only before the merge). Both at once +# can only come from the merge commit. +# 3. The served tree therefore contains FRE-371 (`2fd2a4a`), which is an +# ancestor of that merge — checked locally when the commit is in the object +# store, so run this from a freno-dev checkout. +# +# Usage: scripts/verify-deploy.sh [expected-gitea-sha] + +set -uo pipefail + +GITEA_REMOTE="${GITEA_REMOTE:-https://git.freno.me/Mike/freno-dev.git}" +GITHUB_REMOTE="${GITHUB_REMOTE:-https://github.com/mikefreno/freno-dev.git}" +NOOK_HOST="${NOOK_HOST:-https://nook.freno.me}" +NESSA_HOST="${NESSA_HOST:-https://nessa.freno.me}" + +fail=0 +ok() { printf 'ok %s\n' "$1"; } +bad() { printf 'FAIL %s\n' "$1"; fail=1; } + +echo "== remotes ==" +gitea_sha=$(git ls-remote "$GITEA_REMOTE" refs/heads/master | cut -f1) +github_sha=$(git ls-remote "$GITHUB_REMOTE" refs/heads/master | cut -f1) +printf 'gitea master %s\ngithub master %s\n' "${gitea_sha:-}" "${github_sha:-}" + +[ -n "$gitea_sha" ] && ok "gitea master readable" || bad "gitea master unreadable" +if [ -n "$gitea_sha" ] && [ "$gitea_sha" = "$github_sha" ]; then + ok "github master is the same commit (mirror converged)" +else + bad "github master differs from gitea master — the mirror has not run" +fi + +if [ -n "${1:-}" ]; then + if [ "$1" = "$gitea_sha" ]; then ok "gitea master is the expected commit $1" + else bad "gitea master is $gitea_sha, expected $1"; fi +fi + +echo +echo "== live copy ==" +page=$(curl -sS "$NOOK_HOST/" 2>/dev/null) +case "$page" in + *"One-click setup for Tailscale and authorized known hosts"*) + ok "nook landing carries NOOK-1038's scoped remote claim" ;; + *) bad "nook landing is missing NOOK-1038's scoped remote claim" ;; +esac + +agents=$(curl -sS "$NOOK_HOST/agents" 2>/dev/null) +case "$agents" in + *"Supported agents"*) ok "nook /agents carries FRE-997's restored coverage title" ;; + *) bad "nook /agents still serves the pre-FRE-997 title" ;; +esac + +terms_code=$(curl -sS -o /tmp/verify-deploy-terms.$$ -w '%{http_code}' "$NESSA_HOST/terms" 2>/dev/null) +if [ "$terms_code" = "200" ] && grep -q 'nessa-support@freno.me' /tmp/verify-deploy-terms.$$; then + ok "nessa /terms is published and names the support address (FRE-1670)" +else + bad "nessa /terms returned $terms_code without the support address (FRE-1670 undeployed)" +fi +rm -f /tmp/verify-deploy-terms.$$ + +echo +echo "== ancestry ==" +for commit in 2fd2a4a 7fde259; do + if git cat-file -e "${commit}^{commit}" 2>/dev/null; then + if git merge-base --is-ancestor "$commit" "$gitea_sha" 2>/dev/null; then + ok "$commit is an ancestor of gitea master" + else + bad "$commit is NOT an ancestor of gitea master" + fi + else + printf 'skip %s not in this clone; run from a freno-dev checkout to check ancestry\n' "$commit" + fi +done + +echo +if [ "$fail" -eq 0 ]; then + echo "PASS — the deploy follows gitea master and the served tree contains FRE-371." +else + echo "FAIL — see the lines above." +fi +exit "$fail"