Skip to content

[Gastown] GitHub App installation tokens (ghs_) expire every 1 hour with no auto-refresh — strands completed work repeatedly #4391

Description

@kilo-code-bot

What happened?

GitHub App installation tokens (ghs_ prefix) used by the Gastown integration have a hard-coded 1-hour expiry imposed by GitHub. Gastown does NOT auto-rotate these tokens before they expire, causing repeated authentication failures that strand completed work.

SYMPTOMS (this town has experienced 4+ occurrences across 2026-06-30 to 2026-07-03):

  1. Agent completes work, commits locally, attempts git push → HTTP 401 "Bad credentials" / "Invalid username or token"
  2. git ls-remote origin HEAD from mayor browse worktree also fails with 401
  3. The same expired token is baked into: the remote URL (origin), GH_TOKEN env var, GIT_TOKEN env var, and every /tmp/.git-credentials-* file
  4. There is NO fresh token available in the environment — agents have no way to obtain one
  5. Only a manual token refresh via Gastown Settings resolves it (temporary — expires again ~1h later)

ROOT CAUSE ANALYSIS:

  • Token type: ghs_ (GitHub App server-to-server installation access token)
  • Per GitHub docs: installation tokens expire 1 hour after creation. This TTL is hard-coded by GitHub and NOT configurable.
  • Gastown generates an installation token once and embeds it in: remote URLs, env vars (GH_TOKEN, GIT_TOKEN), and git credential store files
  • There is no background rotation/refresh mechanism — the token sits static until it expires, then ALL git operations fail
  • Token prefixes observed across this session: ghs_TYtH, ghs_dO4p, ghs_ChmZ, ghs_nZrB, ghs_KvQc — each lasted ~1h before 401

IMPACT:

  • 5+ stories stranded at the push stage (Story 1.1, 1.3, and others across convoys v2-v5)
  • Repeated high-severity escalations (6+ on the old rig, 1+ on MKII)
  • A v4 convoy with 16 beads entirely failed due to combined token expiry + quota exhaustion
  • A triage loop on the decommissioned rig (bf5ad67d) generating 100+ failed beads when patrol tried to process escalations it couldn't resolve
  • Significant lost productivity — agents complete full BMad story cycles only to be blocked at the final push step

REQUESTED FIX:
Option A (preferred): Auto-rotate the GitHub App installation token before it expires — e.g., generate a fresh installation token every 50 minutes and update all credential stores/env vars/remote URLs. GitHub App installation tokens are created via POST /app/installations/{id}/access_tokens using the app's JWT, so this can be automated.

Option B: Switch to a longer-lived token type — classic PAT (ghp_) or fine-grained PAT (github_pat_) with a custom expiry (up to 1 year). This eliminates the 1-hour expiry but requires manual rotation at the PAT's expiry.

Either fix would prevent the recurring "token expired" escalations that have plagued this town across multiple convoys.

Town: b1d2b62b-b236-48c0-8558-3b32057470be
Rigs affected: bf5ad67d (ForgetfulDrinker, decommissioned) and e29ba178 (ForgetfulDrinkerMKII, active)

Area

Container / Git

Context

  • Town ID: b1d2b62b-b236-48c0-8558-3b32057470be
  • Agent: Mayor (d0f9f7a6-3442-4cd2-bc2f-e6acf48d536a)
  • Rig ID: e29ba178-b878-499f-9b8f-a3d3f8bdcc88

Recent Errors

git ls-remote origin HEAD → "remote: Invalid username or token. Password authentication is not supported for Git operations. fatal: Authentication failed" (HTTP 401 Bad credentials) — occurred repeatedly across 2026-06-30 to 2026-07-03; token prefixes ghs_TYtH, ghs_dO4p, ghs_ChmZ, ghs_nZrB all expired within ~1h of generation

Filed automatically by the Mayor via gt_report_bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions