feat: full implementation of GitHub tracker dashboard#2
Merged
wgordon17 merged 60 commits intogordon-code:mainfrom Mar 23, 2026
Merged
feat: full implementation of GitHub tracker dashboard#2wgordon17 merged 60 commits intogordon-code:mainfrom
wgordon17 merged 60 commits intogordon-code:mainfrom
Conversation
- QA-001: fetchAllData reads userLogin from auth store (was hardcoded empty) - QA-002/003/004: DashboardPage uses static imports and passes props to all tabs - QA-005: ActionsTab error prop uses ApiError[] consistently - SEC-001: refreshAccessToken validates token before storing (SDR-013)
- PERF-003: adds onCleanup for MediaQueryList listener in SettingsPage
- ADV-007: uses Navigate component instead of window.location.replace - ADV-006: adds isRefreshing guard against concurrent poll fetches - ADV-011: fixes IDB eviction to use cursor instead of index keys - ADV-012: removes dead _previousData signal from DashboardPage
- ADV-001: adds global error store with dismissable banners in DashboardPage - ADV-009: adds Vary: Origin, Access-Control-Max-Age to CORS preflight - ADV-010: adds 30s tick signal to FilterBar for live Updated X ago - ADV-013: replaces startsWith URL check with proper hostname parsing - PERF-002: adds 2-min maxAge to check-status cache entries - PERF-005: wraps ActionsTab filteredRuns/repoGroups in createMemo - SEC-002: extracts isSafeGitHubUrl to shared lib, uses everywhere - SEC-003: adds ghr_ prefix regex validation for refresh tokens - removes dead exports (isItemIgnored), dead code (preChecked) - de-duplicates SortIcon, ErrorBannerList, PaginationControls, relativeTime - combines duplicate imports in config.ts, DashboardPage.tsx
Replaces per-repo API calls with batched Search API queries to dramatically reduce API call count (~85% reduction for 75 repos): - Issues: 225 calls to ~3 (batched search with involves qualifier) - PRs: 75 calls to ~6 search + N detail (involves + review-requested) - Workflow runs: ~450 calls to 75 (single /actions/runs per repo) Search API uses separate 30 req/min rate limit, preserving the core 5000/hr budget for PR details and check status.
Replaces 2N REST calls (commit status + check runs per PR) with one GraphQL query using statusCheckRollup.state, which combines both legacy status API and modern check runs into a single field. Uses parameterized GraphQL variables to prevent injection, batches at 50 PRs per call, and falls back to null on GraphQL errors.
- Errors from batch search, PR detail, and workflow run failures now surface through DashboardData.errors to the existing error banner UI - fetchWorkflowRuns paginates beyond 100 runs per repo - IDB cache evicts stale pr-detail: entries not in the active PR set - Adds API-level test gaps (Task 9b) to testing plan
- fixes 429 double-handling between plugin-retry and plugin-throttling - fixes onSecondaryRateLimit infinite retry by adding retryCount guard - adds If-Modified-Since/Last-Modified support alongside ETags in cache - adds notifications API gate to skip full fetch when nothing changed - adds created-since filter to workflow runs for smaller payloads - adds GraphQL rateLimit monitoring to check status queries - adds test for lastModified conditional header propagation
- fixes doNotRetry replacing default list instead of extending it - removes createdSince/updatedSince filters that break full-replace pattern - handles skipped flag in doFetch to prevent detectNewItems corruption - removes dead code (unused updatedSince params on fetchIssues/fetchPullRequests)
prevents dashboard from staying stale indefinitely when notifications do not cover all change types (workflow runs on unwatched repos, label changes). Forces full fetch after 10 minutes regardless of gate result.
- resets poll state on logout to prevent stale notifications gate across sessions - only sets _lastSuccessfulFetch when at least one fetch succeeded - removes updateRateLimitFromGraphQL to prevent overwriting REST rate limit signal - corrects misleading If-Modified-Since comment about token refresh
- auto-disables notifications gate after 403 to stop wasting rate limit tokens when app lacks notifications permission - adds lastModified: null to evictStaleEntries test entries to match CacheEntry interface
replaces direct import of resetPollState in auth.ts with onAuthCleared callback pattern. poll.ts registers its reset function at module load via onAuthCleared(resetPollState) — no circular import needed.
- removes data: from CSP img-src, relaxes OAuth code regex to [a-zA-Z0-9_-]{1,40}
- validates token BEFORE storing in OAuth callback (SDR-013 pre-flight)
- converts mutable metadata Maps to createMemo for SolidJS reactivity
- replaces Date object creation with string comparison for date sorting
- REST fallback fetches Check Runs API alongside Status API for full fidelity
- extracts extractRejectionError helper, uses IDBKeyRange in evictByPrefix
- exports filter field types from view store, migrates Settings Data to SettingRow
- adds 49 new tests: REST fallback branches, poll coordinator guards, cache eviction, worker refresh parity, auth edge cases, empty userLogin short-circuit
Security: adds AuthGuard on protected routes, moves refresh token to HttpOnly cookie (Worker sets/reads/clears via Set-Cookie), adds CSP hash CI verification, adds CORS credentials support, documents Worker API endpoints in DEPLOY.md. Correctness: fixes clearErrors wiping in-flight pushError calls, resets notification seen-sets on logout, fixes fork PR check status GraphQL lookup, adds try-catch around onAuthCleared callbacks, fixes formatDuration type. Performance: chunks PR detail fetches (batches of 10), memoizes selectedSet in RepoSelector, debounces view state persistence (200ms). Code quality: extracts SkeletonRows and ChevronIcon shared components, unifies ErrorBannerList with onDismiss, exports storage key constants, removes dead code. Tests: adds coverage for QuotaExceededError eviction, onAuthCleared callbacks, poll skipped path, cachedRequest If-Modified-Since fallback, worker regex boundaries, HttpOnly cookie refresh flow, and logout endpoint.
18fe8b6 to
f383a3f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary