Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
claude/adoring-hopper-5x74bqclaude/affectionate-feynman-ykrf1hclaude/architecture-audit-design-wxprenclaude/build-status-update-3MXsfclaude/charming-meitner-mllb5rclaude/compare-gate-gluecron-s4mFQclaude/confident-faraday-tikcwbclaude/continue-work-XMTlIclaude/crontech-gluecron-deploy-7MIECclaude/crontech-platform-setup-SeKfwclaude/design-2026claude/ecstatic-ptolemy-jMdigclaude/enhance-github-integration-QNHdGclaude/fix-aa-loop-issue-PonMQclaude/fix-actions-and-processclaude/fix-desktop-errors-XqoW8claude/fix-red-workflowsclaude/fix-website-access-6FKJNclaude/gatetest-integration-hardeningclaude/github-audit-improvements-bDFr9claude/gluecron-launch-status-FoMRlclaude/hopeful-lamport-olfCTclaude/issue-to-pr-and-protectionsclaude/jolly-heisenberg-2sg1Qclaude/launch-preparation-QmTb6claude/new-session-xk1l7claude/plan-platform-architecture-kkN4yclaude/platform-analysis-roadmap-1nUGLclaude/platform-launch-assessment-8dWV8claude/polish-platform-release-AeDrUclaude/resume-previous-work-KzyLwclaude/review-crontech-handoff-qYEVqclaude/review-project-completeness-lHhS2claude/review-readme-docs-ulqPKclaude/serene-edison-rj87weclaude/setup-multi-repo-dev-BCwNQclaude/ship-fixes-and-tests-Jvz1cclaude/site-audit-competitive-pctlwgclaude/site-migration-vercel-XstpKclaude/standalone-product-repos-XHFTDcopilot/feat-smart-empty-states-keyboard-first-enhancementcopilot/feat-smart-morning-digest-review-context-restorecopilot/fix-and-process-workflowscopilot/update-ai-powered-code-reviewfeat/debt-mapfeat/push-policy-codeowners-hardeningfeat/smart-digest-contextfeat/stage-impactfeat/t1-secret-migrationfeat/u-polishfeat/w-self-hostfeat/w2-claude-configfix/agent-journey-orphan-sweepgatetest/auto-fix-1776586424172gatetest/auto-fix-1776586534814gatetest/auto-fix-1776590685143gatetest/auto-fix-1776590808199mainops/redeploy-retriggerstyle/dxt-cta-themeworktree-agent-a3377aad30d55da26worktree-agent-a7ef607b7ee1d6c74
AUDIT-2026-07-14.md6.5 KB · 123 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# AUDIT — 2026-07-14 — Public-readiness for external AI platforms

**Goal:** certify gluecron.com can receive PRs from external AI platforms
(MCP + git-over-HTTP), self-canonically, without defaulting to GitHub.

Legend: ✅ verified live   ⬜ pending   ⚠️ known gap

## Executive summary

The platform is **ready for external platforms to onboard via the OAuth
connector flow today**. One critical bug was found and fixed live during
this audit: the MCP surface never signaled `invalid_token`, so any client
whose access token aged past 1 hour got stuck in a permanent
"token expired" reconnect loop even though the server's refresh grant
worked. Fixed in `b5a7bb3`, deployed 2026-07-14 02:03 UTC, verified with
live requests. The remaining ⬜ items are operator-gated (PAT-authenticated
journey run, offsite backup arming) — commands are staged below.

## 1. The critical bug — MCP "token expired" reconnect loop (FIXED)

Root cause (three interacting defects):

1. `src/middleware/auth.ts` `softAuth`: an expired/revoked `glct_`/`glc_`
   bearer was silently downgraded to **anonymous** — nothing recorded that a
   token was presented and rejected.
2. `src/routes/mcp.ts`: the 401 challenge omitted RFC 6750
   `error="invalid_token"`, so clients could not distinguish "token died →
   refresh" from "never authenticated → first-time auth". The refresh_token
   grant (fully implemented, with rotation) sat unused.
3. The MCP handshake (`initialize`/`tools/list`/`ping`) was fully open, so a
   client reconnect **falsely succeeded** on a dead token, then looped on
   `tools/call`.

Fix (`b5a7bb3`, locked-file edit to `auth.ts` owner-approved 2026-07-14):
`softAuth` now flags `bearerInvalid`; `/mcp` answers **every** method —
including the handshake — with `401` +
`WWW-Authenticate: Bearer error="invalid_token", …` when a dead bearer is
presented. Anonymous discovery/handshake unchanged; anonymous `tools/call`
still gets the connector sign-in challenge (deliberately without `error=`).

Live verification (2026-07-14, prod):

- ✅ dead `glct_` on `initialize` → 401 + `error="invalid_token"` (loop-breaker)
- ✅ dead `glct_` on `tools/list` → 401 + `error="invalid_token"`
- ✅ anonymous `tools/call` → 401 challenge with `resource_metadata=`, **no** `error=`
- ✅ anonymous `initialize` → 200 (discovery open)
- ✅ regression tests: 125 pass (mcp/oauth/well-known), 83 pass (mcp-write/git-push-auth/api-tokens/push)

## 2. Doctor run (scripts/doctor.ts, new — `bun run doctor`)

First run against `https://gluecron.com` (anonymous sections): **ALL GREEN**.

-**a. Endpoint smoke** — 15/15 (healthz, readyz, version, login/register/
  landing/explore/demo/pricing/status, api-v2 health, mcp discovery,
  manifest, sw, dxt)
-**b. OAuth provider** — 8/8: AS metadata advertises `refresh_token` +
  `registration_endpoint`; protected-resource metadata (root + /mcp); **DCR
  round-trip returns a client_id (201)**; token endpoint: garbage code →
  `invalid_grant`, garbage refresh → `invalid_grant`, bogus grant_type →
  `unsupported_grant_type`
- ✅ **c. MCP anonymous + RFC 6750** — 5/5: initialize 200; **live tools/list
  exactly matches the local 60-tool manifest (zero drift)**; anonymous
  tools/call challenge correct; dead-bearer invalid_token on both
  handshake methods
- ⬜ **d. Authenticated MCP reads** — awaits `GLUECRON_PAT`
-**e. Read-only tool matrix (--full)** — awaits `GLUECRON_PAT`

## 3. External-platform PR journey (scripts/agent-journey.ts, new)

⬜ Awaits an admin-scope PAT. Simulates exactly what an external platform
does: PAT identity → scratch repo → git push over smart HTTP with token
basic-auth → `gluecron_create_branch`/`write_file`/`create_pr`/`comment_pr`
→ AI-review poll → `gluecron_merge_pr` + verify → activity feed →
guaranteed cleanup. Hard-guarded against ever touching the self-host repo.

## 4. Self-canonical / server-side state (verified on-box 2026-07-14)

- ✅ Deploys are cord-free from GitHub: `/opt/gluecron` `origin` = the
  box-local canonical bare repo (docker volume), NOT github.com. Pushes to
  `gluecron.com/ccantynz/Gluecron.com.git` main went live in ≤ ~2 min twice
  today (`b5a7bb3`, `2cecc08`).
-`gluecron-update.timer` firing every 60s.
-`gluecron-backup.timer` daily; last run 2026-07-14 00:00 UTC, exit 0,
  4.4M Neon dump.
-`gluecron-restore-drill.timer` weekly (first run Sun 2026-07-19 04:00 UTC).
-**Offsite backup NOT yet armed** — dumps stay on the VPS. Staged
  operator command appends `BACKUP_SCP_TARGET=root@100.89.227.39:/opt/backups/gluecron`
  (vapron-158) to `/opt/gluecron/.env` (with `.env` backup first) and
  fires a verification run. jarvis→vapron root SSH verified working.
- ⚠️ GitHub (`ccantynz-alt/Gluecron.com`) remains the emergency deploy
  source per CUTOVER_RUNBOOK Phase 4 (needs 7 green days + armed offsite
  before retirement). Do not archive yet.

## 5. How external platforms onboard (no PAT required)

1. `GET /.well-known/oauth-authorization-server` — discovery
2. `POST /oauth/register` — RFC 7591 DCR (verified live)
3. Authorization-code + PKCE → `POST /oauth/token` (1h access / 30d rotating refresh)
4. MCP at `POST /mcp`; expired tokens now get `error="invalid_token"` →
   client refreshes transparently
5. Git over smart HTTP with `Basic <user>:<token>` (PAT) or the web/API flows

## 6. Open items / known gaps

- ⬜ Run doctor sections d/e + agent-journey with an admin PAT (blocked on
  operator minting one; classifier reserves prod-DB writes for the operator).
- ⬜ Arm offsite backup (staged command above; operator-confirmed destination).
- ⚠️ `src/middleware/api-auth.ts` (API v2): 401s invalid bearers but sends no
  `WWW-Authenticate` header and rejects `glct_` OAuth tokens as unknown —
  additive parity pass recommended (out of scope today).
- ⚠️ `/api/version` reports `sha: "unknown"` on the compose/auto-update
  deploy path — BUILD_SHA pin only happens via self-deploy.sh; staleness
  checks rely on `builtAt`. Worth stamping in the docker build.
- ⚠️ DCR leaves `doctor-*` client rows (RFC 7592 delete not implemented) —
  cosmetic residue from each doctor run.
- ⚠️ No MCP create-repo tool — journey uses `POST /api/v2/repos`; consider
  adding `gluecron_create_repo` for full MCP-only agent flows.

## Session evidence

- Commits: `b5a7bb3` (fix + tests), `2cecc08` (doctor + journey + npm script).
- Fix verified live with curl transcripts (§1); doctor output (§2) from
  `bun scripts/doctor.ts` at 2026-07-14 ~02:1x UTC.