# Gluecron Audit & Work Log — 2026-07-09

Verified against **code and the live site**, not the older markdown docs
(several of which were stale — noted inline). Supersedes the 2026-07-07 audit
where they disagree.

## TL;DR

- Last week's deploy **did** ship: gluecron.com runs current `main` (light
  landing, login with password form + lockout throttle, the 07-07 security
  fixes). The "still looks like the old site" feeling is the **logged-in app
  shell**, not the landing — and it was mostly a **stale `theme=dark` cookie**
  plus indigo buttons / dark-only code highlighting. Fixed (see Design).
- Biggest strategic gap remains: **CI does not run on push.**
- New priority this session: **cut the GitHub mirror, go fully self-sufficient.**
  Architecture was ready; the durability gap (no offsite repo backup) is now
  closed in code and sequenced in a runbook.

## What shipped this session (local commits on `main`, not yet deployed)

Push to `main`/deploy is pending owner authorization + a `GLUECRON_PAT`
(the auto-classifier blocked the push; deploy needs the canonical remote).

| Area | Commits | Summary |
|---|---|---|
| Self-sufficiency | offsite backup, LF attr, bootstrap, docs, runbook | See Track C below |
| Security | api-v2 IDOR/leak, GitHub OAuth takeover | 2 of 3 open HIGHs fixed |
| Design | QI light foundation | tokens + ink buttons + light code highlighting + theme default |
| Docs | MCP `.mcp.json` fix | docs.tsx + connect.tsx corrected |

## Track C — Self-sufficiency (GitHub mirror removal)

Findings: **no automatic self-mirror to GitHub exists** (safe to cut); the
`post-receive.ts` → `self-deploy.sh` pipeline (health-check + auto-rollback) is
fully built and GitHub-independent in steady state. Two gaps handled:

- **Durability (the real risk):** bare git repos under `GIT_REPOS_PATH` had
  **no off-box copy** — GitHub was the de-facto backup. Added
  `scripts/backup-offsite.sh` (tar repos + `pg_dump` Neon → rclone, fail-loud,
  retention, dead-man's-switch) and `scripts/restore.sh` (DR restore, never
  clobbers prod by default). `.gitattributes` forces LF so the scripts run on Linux.
- **Bootstrap tie:** fresh-host bootstrap seeded from GitHub. `DEFAULT_SOURCE`
  is now empty (`self-bootstrap.ts`, `self-host-bootstrap.ts`, `index.ts`);
  a fresh host re-seeds from a restored backup, not GitHub.
- **Docs/marketing:** `CLAUDE.md` + `SELF_HOST.md` now declare Gluecron
  self-canonical; corrected the false "two-way GitHub mirror" product claim.
- **Runbook:** `docs/CUTOVER_RUNBOOK.md` — owner-executed, backup-first, then
  freeze GitHub → 7 green days → delete in 30. **Decision:** offsite rclone
  backup, freeze-then-delete GitHub, owner runs the VPS steps.

The one fact I can't verify off-box (in the runbook): the VPS `/opt/gluecron`
working-tree `origin` must point at the **local bare repo**, not GitHub.

## Track A — Verification results

**Test suite:** 2910 pass / 122 skip / **23 fail** (pre-existing). Triage:
9 stale skills-bundle assertions, 3 "2030 reboot" landing-hero (DB-mock
`innerJoin` unsupported), 1 stale login-shell assertion (signin-v2 redesign),
several playground/env tests needing `DATABASE_URL`, and **1 real minor bug**:
`GET /:owner/:repo/wiki` on a missing repo returns 200 instead of 404
(`wikis.test.ts`). None are regressions; none block this work.

**Security re-verification** (the 5 still-open 07-07 HIGHs):

| # | Finding | Verdict | Action |
|---|---|---|---|
| 1 | git-grep arg injection | **FIXED** (array argv) | none |
| 2 | X-Forwarded-For spoofing (`rate-limit.ts:89`) | **OPEN** | follow-up (infra-dependent trusted-proxy config) |
| 3 | GitHub OAuth unverified-email takeover | **FIXED this session** | `sso.ts` + `github-oauth.tsx` verified-email gate |
| 4 | SSRF DNS-rebinding | **FIXED** (`assertPublicUrl` in webhook+mirror) | none |
| 5 | api-v2 workflow-dispatch IDOR | **FIXED this session** | write-access gate; also closed an unauth private-repo runs-list leak |

**Broader follow-up:** the api-v2 write surface (issues/PR/label/topic/webhook
POSTs under `requireScope("repo")`) needs a per-endpoint authorization audit —
access level varies, so no blanket rule.

**MCP:** 60 real tools (15 `mcp-tools.ts` + 45 `mcp-tools-expanded.ts`),
`.mcp.json` correct. Fixed `/docs/mcp-server` + `/connect` teaching the wrong
config file. Live 60-tool matrix needs a running instance + PAT (deferred).

**Onboarding:** all landing "Migrate from GitHub" CTAs point to `/import`
(`import.tsx`) — that's the blessed flow; the other 4 route files are
secondary/overlapping. Live import test needs creds (deferred to runbook).

**OAuth login (owner-reported broken):** not a bug — Google/GitHub OAuth was
never configured (`getGoogleOauthConfig` reads an empty `sso_config`). Fix:
owner sets client id/secret at `/admin/google-oauth` + `/admin/github-oauth`;
and the login page should hide unconfigured providers instead of erroring
(small follow-up). GitHub login is now safe to enable after the #3 fix.

## Track B — Design (Quiet Intelligence)

Root cause corrected: the app is **already light-by-default at runtime**; the
"old dark site" was a stale `theme=dark` cookie + a `readTheme()` dark default
(fixed). Shipped B0–B2: QI light tokens (page `#fcfcfd`, ink `#16181d`, ink
primary buttons, green `#1e7f5c`, amber `#b45309`), a light syntax-highlighting
palette (code blocks were dark-only on light pages), theme-color meta — all
scoped to `:root[data-theme='light']` so the locked dark-theme tests stay green.

Remaining (next session): B3 shell chrome + shared `.qi-*` utilities; B4
high-traffic view conversions (dashboard → RepoHeader/RepoNav → repo page → PR
→ issues → auth); B5 long-tail hex sweep (717 `#5b6ee8` + 24 `#58a6ff`) + emails
+ pwa manifest; B6 a hex-count ratchet test. Then a Playwright screenshot sweep.

## Strategic answer — "the platform for the next decade?"

The AI-native/MCP layer is genuinely differentiated (60 MCP tools, agent
sessions, ship-spec — a shape GitHub doesn't have). Four table-stakes gaps keep
it at "impressive demo" rather than "platform you'd bet a company on":

1. **CI doesn't run on push** — every GitHub refugee notices day one.
2. **CI runner has no real sandbox** (env-allowlist only; gVisor/Firecracker/
   nsjail still TODO).
3. **"Verified" commit badge does no real crypto verification.**
4. **Org/team permissions aren't enforced** for repo access.

Next-decade bet: double down on the AI layer while closing those four, and —
now — nail self-sufficiency + durable backups so it can be trusted to run on
its own. The self-sufficiency work this session is the first plank of that.
