Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Plan 15

Seth Ford edited this page Feb 12, 2026 · 2 revisions

Let me write the plan directly. Here's the implementation plan:


Implementation Plan: Add Dashboard Authentication (GitHub OAuth) — Issue #15

Key Finding

The OAuth flow is already 90% implemented in dashboard/server.ts. The existing code includes: OAuth redirect, callback/token exchange, session cookies, auth gate, login page, PAT fallback, logout, and /api/me. This plan focuses on the security gaps and missing features.


Files to Modify

File Action Purpose
dashboard/server.ts Modify Add CSRF state param, developer auto-registration, secure cookie flag, heartbeat identity validation, admin vs. write distinction
dashboard/server-auth-test.ts Create Unit tests for auth flow

Implementation Steps

Step 1: Add OAuth CSRF state parameter protection

  • In handleAuthGitHub() (line 1922): Generate a random state token using crypto.randomUUID(), store it in a short-lived map with a 10-minute TTL
  • Add state to the OAuth authorize URL params
  • In handleAuthCallback() (line 1939): Validate the state parameter matches the stored value before exchanging the code

Step 2: Add Secure flag to session cookies in production

  • In sessionCookie() (line 214): Detect if running behind HTTPS (check DASHBOARD_SECURE env var or default to true when NODE_ENV=production) and add Secure flag conditionally
  • Update clearSessionCookie() (line 218) to match

Step 3: Distinguish admin vs. write permission

  • In handleAuthCallback() (line 1958-1959): Set isAdmin to true only for "admin" and "maintain" permissions. Users with "write"/"push" permission still get access but isAdmin = false
  • Same change in handlePatLogin() (line 2019-2020)
  • Update ALLOWED_PERMISSIONS (line 41) to include "maintain"

Step 4: Developer auto-registration on first OAuth login

  • After session creation in handleAuthCallback() (after line 1974): Register the user in the developer registry if not already present
  • Create a registerOAuthDeveloper(username, avatarUrl) helper that adds an entry to developerRegistry with developer_id set to the GitHub username, machine_name as "dashboard", and a current heartbeat timestamp
  • Same logic in handlePatLogin() after session creation

Step 5: Heartbeat endpoint validates developer identity

  • In the /api/connect/heartbeat handler (line 3764): When auth is enabled, check if the request has a valid session cookie. If it does, verify the developer_id in the body matches the session's githubUser
  • Allow existing invite-token auth as fallback for CLI-based heartbeats (which don't have browser sessions)
  • This means heartbeats can be authenticated via either: (a) session cookie (dashboard), or (b) invite token (CLI)

Step 6: Write auth tests

  • Create dashboard/server-auth-test.ts with Bun test runner
  • Test cases: OAuth state generation/validation, session creation/expiry, cookie flags, public vs. protected route access, developer auto-registration, admin vs. write distinction, heartbeat identity validation

Task Checklist

  • Task 1: Add OAuth state parameter to /auth/github redirect and validate in /auth/callback (CSRF protection)
  • Task 2: Add Secure cookie flag when serving over HTTPS (env-controlled)
  • Task 3: Distinguish admin (admin/maintain) vs. collaborator (write/push) permissions — both get access, only admin gets isAdmin: true
  • Task 4: Auto-register developers in the registry on first OAuth/PAT login
  • Task 5: Validate developer identity on heartbeat endpoint when auth is enabled
  • Task 6: Add ALLOWED_PERMISSIONS to include "maintain" and "push" for access (keep admin distinction separate)
  • Task 7: Write unit tests for the auth flow
  • Task 8: Update /api/me to return admin vs. collaborator role info
  • Task 9: Run existing test suite to ensure no regressions

Testing Approach

  1. Unit tests (dashboard/server-auth-test.ts): Test OAuth state generation/validation, session lifecycle, cookie flags, route protection, developer registration, permission mapping
  2. Existing test suite: Run npm test to verify no regressions in the 22 existing test suites
  3. Manual verification: Set GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, DASHBOARD_REPO env vars and test the full OAuth flow in a browser

Definition of Done

  • OAuth flow includes CSRF state parameter validation
  • Session cookies include Secure flag when configured for HTTPS
  • Public routes (/login, /auth/callback, /api/health) work without authentication
  • All other routes redirect to /login when no session exists
  • First-time OAuth login auto-registers developer in registry
  • Admin flag correctly distinguishes admin/maintain from write/push permissions
  • Heartbeat endpoint validates developer identity against session when auth is enabled
  • All existing tests pass (npm test)
  • New auth-specific tests pass

Shall I proceed with the implementation? The changes are concentrated in a single file (dashboard/server.ts) plus a new test file, making this well-suited for sequential work rather than a team.

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /