4 months ago
c3c7bd7Tripwire becomes an app with accounts: sign-in gets a session, onboarding gets a repo, and every dashboard surface scopes to the user's ONE active repo. The repo dropdown on /rules and /workflows is gone. - schema (migration 0002): user_installations(user_id, forge, installation_id) UNIQUE on (forge, installation_id) — an installation belongs to exactly one user; user.active_repo_id FK → repos.id. all granted repos stay synced, only the active one scopes the dashboard (no switcher, MVP). - onboardingServices: linkUserInstallation / listUserRepos / getActiveRepo / setActiveRepo / getOnboardingState, with an integration test locking the ownership + must-be-yours invariants. - Setup URL callback /onboarding/setup links the installation to the SIGNED-IN user; the install `state` HMAC-binds that user (CSRF). /onboarding narrows: one granted repo auto-selects, more than one shows a picker. - gate: getSessionInfo gains `onboarded`; __root beforeLoad redirects a signed-in not-onboarded user to /onboarding, mirroring the /login redirect. - scoping: listActivityFeed / getHomeStats / listPendingItems take a repoFullName, resolved per session by a getActiveRepo helper (open-dev falls back to the first installed repo; a fresh repo yields honest zeros). replaced the /rules + /workflows dropdowns with the active repo; deleted the dead listRepoOptions. - documented GITHUB_APP_SLUG + the Setup URL in .env.example. spec §4/§10 updated. honest ledger: this scopes dashboard LISTS but does NOT authorize a run fetched directly by id — any signed-in session can still load any run by id. cross-user run authorization stays open (DECISIONS + spec §10). Checks: typecheck all, biome, boundaries, 204 tests, migration applied.
Parent62c52d0