feat: add dashboard with github auth, onboarding and runs list#113
Merged
Conversation
AKogut
added a commit
that referenced
this pull request
Jul 21, 2026
## The problem `docker compose up` — the promise on the front page of the README — was broken. Replacing the placeholder web app with Next.js in #113 left the container wiring pointing at the old app, and I verified that work locally with `next start` instead of verifying the stack. That was the wrong check. ## What was broken - The `web` Docker target ran `node apps/web/dist/index.js`, a file deleted in #113. Next builds to `.next`, so the container exited immediately. - The `web` healthcheck probed `/health`, a route the Next app never had. - The `web` service had no auth environment, so even a running container could not sign anyone in. - The seed produced 24 runs, 1 org and **0 memberships** — the demo data belonged to nobody and was unreachable after signing in. - The worker was passed `HEARTBEAT_INTERVAL_MS`, left over from the placeholder; the real worker reads `POLL_INTERVAL_MS`. ## Fixes - `web` now builds with Next's `standalone` output and runs `server.js`; the Dockerfile copies only the standalone bundle and static assets. - Added a real `/health` route. - Compose passes `AUTH_SECRET` (required, with a message telling you how to generate one), the GitHub OAuth pair, `AUTH_URL` and `AUTH_TRUST_HOST`. - **First-account bootstrap**: the first account created on a fresh instance adopts orgs that have no members, so seeded demo data is reachable instead of orphaned. Orgs that already have a member are never touched, so this can never hand an existing team's data to a later signup. - README quickstart now generates `AUTH_SECRET` and explains the OAuth app and the bootstrap behaviour. ## Found only because the stack was actually started this time - **The API healthcheck was broken too**, and had been all along. `wget localhost` inside Alpine resolves `::1` first while the servers bind IPv4, so both services reported `unhealthy` forever. It went unnoticed because nothing depends on the API's health condition. Both healthchecks now use `127.0.0.1`. - **A flaky build.** `web#typecheck` ran concurrently with its own `build`, but the app's tsconfig includes the `.next/types` that `build` generates — so typecheck intermittently failed on a missing generated module. Reproduced in one run out of two. Fixed with a package-level turbo config making `typecheck` depend on `build`; verified with four consecutive clean runs after deleting `.next` each time. - **Turbo cached nothing for the web build** — the root config declared `outputs: ["dist/**"]` while Next writes `.next`. - Four more tracked build artifacts left behind by the deleted placeholder app. ## Verification Brought the whole stack up on a clean volume: every service reports **healthy**, and the containerized dashboard renders the seeded runs and the flaky board (scores 0.86 / 0.75 / 0.58). Four tests cover the adoption rule, including that it refuses an org someone already owns. 42/42 turbo tasks, 132 tests.
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.
Closes #55
Closes #56
Closes #23
Summary
Replaces the placeholder HTML server with a real Next.js dashboard: GitHub sign-in, workspace onboarding, ingest token management, and the runs list. This is the first time the platform is visible end to end — a run exported from CI now shows up in a UI.
Architecture
The read queries lived inside
apps/api, but the dashboard needs them too. They now live in a new internal package@flakemetry/queries, consumed by both:One query implementation, two authorization models, no duplication and no cross-service session plumbing.
Auth and multi-tenancy (#55)
Auth.js v5 with the GitHub provider and database sessions. The schema gains
User,Account,Session,VerificationTokenand aMembershipjoin table (user × orgwith a role), plus a migration.Authorization is deliberately split so it stays testable:
lib/session.ts— resolves the signed-in user (depends on next-auth)lib/tenant.ts— pure database-backed access checks (listAccessibleProjects,requireProjectAccess), no framework couplingEvery page resolves the user, then re-checks project membership before reading data. A project outside the user's orgs is never queried, it redirects.
Onboarding and tokens (#56)
ownerRuns list (#23)
Status counts per run (passed / failed / flaky / skipped), branch filter, cursor pagination, and an empty state that tells you how to start ingesting.
Verification
Built the stack and ran a real scenario rather than trusting compilation:
auth/logs inscored 0.85 withSAME_SHA_VARIANCE,PASS_ON_RERUN,HIGH_FLIP_RATE,FAIL_ISOLATION; stable tests scored 0.04 withSTABLEAccess control, verified by request:
307 → /307 → /sign-inFive automated tenant-isolation tests cover these so they cannot regress silently.
Testing