Skip to content

fix: keep local archive available during GitHub outages - #932

Open
mariusvniekerk wants to merge 5 commits into
mainfrom
fix/github-outage-local-archive
Open

fix: keep local archive available during GitHub outages#932
mariusvniekerk wants to merge 5 commits into
mainfrom
fix/github-outage-local-archive

Conversation

@mariusvniekerk

Copy link
Copy Markdown
Collaborator

Forge is a local-first console, but startup previously required GitHub credential and identity lookups to succeed before it served archived data. A temporary GitHub outage could therefore make the existing local archive unavailable.

This change treats only temporary network, timeout, rate-limit, and GitHub server failures as degraded startup. Forge preserves configured routes and normal scheduled sync, while using conservative host-level personal access token accounting until the next restart. Missing credentials, invalid configuration, and permanent authentication failures still stop startup.

The live daemon was not restarted during verification. The startup decision is covered by focused tests with injected upstream failures.

Validation
  • make test-short — 6,559 tests passed; 226 skipped.
  • make lint-check — zero issues.

generated by a clanker

wesm and others added 2 commits August 17, 2026 09:05
Forge's LaunchAgent previously treated GitHub token and identity bootstrap errors as daemon-fatal. A transient GitHub API outage therefore caused launchd to restart the process and Caddy to return 502 instead of serving cached local data.

Keep provider startup best-effort when sync is enabled. Fall back to an empty provider registry and preserve the SQLite-backed UI until the provider is available again. Explicit no-sync startup errors remain fatal.

Generated with Codex
Co-authored-by: Codex <noreply@openai.com>
Forge resolved GitHub credentials and account identity before it could serve archived data. A transient provider outage could therefore block the local-first console from starting at all.

Degrade only for temporary network, timeout, rate-limit, and server failures. Keep configured routes and scheduled sync active so normal cadence recovers automatically. Permanent authentication and configuration failures still stop startup.

Generated with Codex
Co-authored-by: Codex <noreply@openai.com>
@roborev-ci

roborev-ci Bot commented Aug 18, 2026

Copy link
Copy Markdown

roborev: Combined Review (96c0284)

High-severity issue remains: degraded GitHub startup can still block archive availability.

High

  • cmd/kenn-forge/main.go:573resolveStartupRepos immediately retries GitHub for every configured repository before activating the real server. App credentials are reminted per repository, while PAT requests lack an operation deadline and may stall indefinitely, leaving archive APIs on the startup 503 handler. Propagate degraded GitHub hosts from provider startup and resolve their repositories from SQLite or synthetic fallback; defer network retries to scheduled sync.

Reviewers: 2 done | Synthesis: codex, 6s | Total: 3m58s

@wesm

wesm commented Aug 18, 2026

Copy link
Copy Markdown
Member

This overlaps with #928, i will let you reconcile

@mariusvniekerk mariusvniekerk self-assigned this Aug 18, 2026
PR #928 and this branch both kept the local archive available when GitHub startup failed. Keeping separate implementations would leave two fallback policies that disagree about permanent authentication and configuration errors.

Retain this branch's transient-only fallback and scheduled recovery behavior while merging PR #928's history into the replacement change.

Generated with Codex
Co-authored-by: Codex <noreply@openai.com>
@roborev-ci

roborev-ci Bot commented Aug 18, 2026

Copy link
Copy Markdown

roborev: Combined Review (91f2504)

Startup resilience is improved, but one medium-severity rate-limit case still blocks degraded startup.

Medium

  • cmd/kenn-forge/provider_startup_fallback.go:103 — GitHub App rate limits may return HTTP 403, but githubapp.StatusError treats only 429 as transient. A 403 rate-limit response can therefore still prevent startup, and current tests cover only 429. Preserve response headers in githubapp.StatusError, detect 403 rate limits using X-RateLimit-Remaining or Retry-After, and add behavioral coverage.

Reviewers: 2 done | Synthesis: codex, 14s | Total: 4m23s

@wesm

wesm commented Aug 19, 2026

Copy link
Copy Markdown
Member

looking

GitHub App token minting can report exhausted primary or secondary rate limits as HTTP 403. Treating every 403 as permanent still prevented the local archive from starting during those rate-limit windows.

Preserve response headers and use GitHub's rate-limit signals to distinguish temporary 403 responses from ordinary forbidden failures. Non-rate-limit 403 responses remain fatal.

Generated with Codex
Co-authored-by: Codex <noreply@openai.com>
@roborev-ci

roborev-ci Bot commented Aug 19, 2026

Copy link
Copy Markdown

roborev: Combined Review (bb292f0)

High-severity startup reliability issue remains, along with two medium-severity error-classification gaps.

High

  • cmd/kenn-forge/main.go:544 — Degraded startup is not communicated to the caller, so resolveStartupRepos can still make synchronous, serial GitHub requests before the full server replaces the startup handler. A hanging upstream may leave archive APIs returning 503 indefinitely.
    • Fix: Return degraded host state and resolve those repositories exclusively from SQLite/config during startup, deferring network resolution to background sync. Add a test using a blocking repository reader.

Medium

  • cmd/kenn-forge/provider_startup_fallback.go:105 — A GitHub App secondary-rate-limit response can be HTTP 403 without Retry-After or an exhausted primary-rate-limit header. The response body identifies the secondary limit, but the code classifies it as permanent and aborts startup.

    • Fix: Parse the structured error body to recognize secondary limits while keeping unrelated 403 responses fatal. Cover the headerless response shape.
  • cmd/kenn-forge/provider_startup_fallback.go:42 — The first transient credential failure switches every GitHub route to the synthetic resolver, preventing later routes from exposing permanent errors such as 401. This violates the invariant that permanent authentication failures remain fatal.

    • Fix: Resolve and degrade routes or hosts independently, continuing validation so permanent failures take precedence. Add mixed transient/permanent coverage.

Reviewers: 2 done | Synthesis: codex, 7s | Total: 4m48s

Transient GitHub bootstrap failures could still block archive APIs while startup resolved configured repositories. A transient route could also hide a later permanent credential failure.

Use SQLite and config only when expanding repositories for a degraded provider-host. Validate credential routes independently so permanent errors still stop startup, and recognize structured secondary-rate-limit responses when headers are absent.

Generated with Codex
Co-authored-by: Codex <noreply@openai.com>
@roborev-ci

roborev-ci Bot commented Aug 19, 2026

Copy link
Copy Markdown

roborev: Combined Review (e06048a)

High-risk concurrency issue found, plus a medium-risk retry flaw.

High

  • cmd/kenn-forge/provider_startup_fallback.go:50BindSourceIdentity allows the fallback resolver to escape startup. Concurrent token revalidation can write to the shared, unsynchronized degradedProviderHosts map, causing a concurrent-map-write crash.
    • Fix: Restrict the fallback resolver to initial discovery and bind live sources to the primary resolver, or synchronize and freeze degraded-host state after startup.

Medium

  • cmd/kenn-forge/provider_startup.go:289 — Transient App-token mint failures retain no retry window. Immediate parallel repository syncs can repeatedly retry minting and hammer a rate-limited endpoint.
    • Fix: Single-flight failed App mints and cache a bounded retry deadline based on Retry-After or X-RateLimit-Reset.

Reviewers: 2 done | Synthesis: codex, 9s | Total: 6m38s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants