Dosu LogoDosu Logo
Ask
Join our Discord
Organization avatar
HashHivePublic
EvilBit Labs LLC
DocumentsHashHive
160-login-project-selection-ui
160-login-project-selection-ui
Type
External
Status
Published
Created
Jul 18, 2026
Updated
Jul 18, 2026
Source
docs/residual-review-findings/160-login-project-selection-ui.md

Residual Review Findings — issue #160#

Branch: 160-featoperator-console-implement-login-page-project-selection-ui-phase-1-step-611
Head: f44d7c5
Review run: 20260527-220426-53590818 (autofix mode, 10 reviewers)
Verdict: Ready with fixes — all #160 ACs covered, 2 safe_auto fixes applied; 14 findings remain.

This file durably records the residual review findings from the autofix pass. When a PR is opened for this branch, the same content is intended to live in the PR body under ## Residual Review Findings.

Applied (safe_auto, 2) — already in commit f44d7c5#

  • #6 [P2] packages/frontend/src/hooks/use-select-project.ts — Import SelectProjectRequest from @hashhive/shared per AGENTS.md wire-shape rule. Cross-reviewer agreement (project-standards + api-contract).
  • #13 [P3] packages/frontend/src/hooks/use-logout.ts — Trim 4-line mechanics-only comment on void navigate(). (maintainability)

Residual#

P1 — High (5)#

  • #1 [P1][manual] packages/frontend/src/components/features/sidebar.tsx:92-100 — Sidebar useSelectProject called with no onError callback. Mutation failures produce no toast/log; UI state drifts from server state. Add an onError callback that surfaces via toast or inline banner. (reliability, c75)
  • #2 [P1][gated_auto] packages/frontend/src/hooks/use-select-project.ts:38 + sidebar.tsx — Rapid sidebar switching can desync UI scope from server scope. Three POSTs in flight; last-write-wins server but client cache can end up with project B's data under project C's key. Fix: disable the dropdown while selectProject.isPending, or treat the POST response's echoed projectId as authoritative rather than the request value. (adversarial, c75)
  • #3 [P1][manual] packages/frontend/src/pages/login.tsx:55-77 — LoginPage.onSubmit has no error handling for fetchProjects() rejection. A failed /me call leaves the user staring at the form with no feedback. Add a try/catch around fetchProjects() that calls setError(...). (reliability, c80)
  • #4 [P1][manual] packages/frontend/tests/stores/ui.test.ts:42-72 — useUiStore persist tests verify localStorage writes but never rehydration from a fresh store. The load-bearing "remember next login" contract is unverified end-to-end. Add a test that pre-seeds localStorage['hashhive.ui.v1'] and asserts a fresh hook reads back the persisted values. (testing, c80)
  • #5 [P1][manual] packages/frontend/e2e/smoke.spec.ts:19-26 (impact of e2e/setup/seed-data.ts) — Smoke e2e always hits the multi-project selector branch now that seed has 2 projects. Single-project auto-select happy path lost all e2e coverage. Either seed a second user with one membership and add an e2e for that user, or parameterize seed-data to vary by test file. (testing, c90)

P2 — Moderate (8)#

  • #7 [P2][manual] packages/frontend/src/hooks/use-logout.ts:20-26 — useLogout swallows signOut() errors with no log. Orphan server session possible; visibility matters for diagnosing recurring transient logouts. Add console.error in the catch. 4-reviewer agreement (correctness + reliability + project-standards + adversarial), promoted to confidence 75.
  • #8 [P2][manual] packages/frontend/src/hooks/use-select-project.ts:36-39 — qc.invalidateQueries() with no filter is coarse, races with in-flight requests, and triggers thundering-herd refetch on rapid switching. Tag project-scoped query keys and invalidate by predicate. 4-reviewer agreement (correctness + maintainability + reliability + adversarial), promoted to confidence 100.
  • #9 [P2][manual] packages/frontend/tests/components/sidebar.test.tsx:39-83 — Sidebar useSelectProject mutation-failure path not tested. Silent-failure UX is undefined and unverified. Add a 4xx case mirroring the selector page's error test. (testing, c80)
  • #10 [P2][manual] packages/frontend/tests/hooks/use-logout.test.tsx:52-87 — Call-order test asserts exact ['signOut','clearAuth'] order via shared mock side-effect. Brittle to intentional refactors. Loosen to assert final state and the navigate('/login', {replace:true}) invocation, not the strict sequence. (testing, c75)
  • #11 [P2][manual] packages/frontend/src/stores/ui.ts — useUiStore mixes persisted UX prefs (rememberLastProject, lastProjectId, sidebarOpen) with server-mirrored scope (selectedProjectId) and ephemeral UI (mobileSidebarOpen). Split into useUiPrefsStore (persisted) + useUiSessionStore (in-memory). Eliminates the partialize whitelist as the only thing keeping server state out of localStorage. (maintainability, c75)
  • #12 [P2][manual] packages/frontend/src/pages/login.tsx — LoginPage.onSubmit now carries three concerns (signIn, fetchProjects, remember-last fast-path) with cross-store getState() coupling. Extract a useRestoreLastProject hook. (maintainability, c75)
  • #14 [P2][gated_auto] packages/frontend/src/components/features/sidebar.tsx:104-127 — "All Projects" dropdown option is a silent no-op. Falsely implies global scope is achievable when the server requires a concrete projectId. Remove the option entirely or replace with a disabled placeholder. (correctness, c80)

P3 — Low (2)#

  • #15 [P3][manual] packages/frontend/src/stores/ui.ts — persist middleware silently falls back to in-memory when localStorage is unavailable (private browsing, quota exceeded). Breaks remember-last with no signal. Detect via onRehydrateStorage callback and surface a one-time console.warn. (adversarial, c75)
  • #16 [P3][manual] packages/frontend/e2e/select-project.spec.ts:17-34 — waitForURL('/') followed by immediate aside assertion is racy under lazy-loaded chunks. Lacks explicit waitForResponse after the waitForRequest capture. (adversarial + reliability, c75)

Coverage notes#

  • 11 findings suppressed by confidence gate (<75): 4 at anchor 50, 2 at anchor 60, 3 at anchor 65, 2 at anchor 70.
  • Mode-aware demotion: 0 (testing findings were classified as manual not advisory).
  • Validator pass (Stage 5b): skipped — autofix mode does not run independent validation.
  • 10/10 reviewers returned. No failures.

Past learnings flagged (ce-learnings-researcher)#

Three prior docs in docs/solutions/ applied to this work:

  • conventions/bun-test-mock-module-import-order.md — new tests correctly follow Pattern A.
  • conventions/shared-zod-openapi-wire-contract-mirror-2026-05-25.md — basis for the applied fix #6.
  • conventions/form-submit-payload-null-checks-2026-05-19.md — remember-last code correctly uses != null.

Researcher recommends capturing future learnings via /ce-compound on: BetterAuth client gotchas, Zustand persist hydration timing, TanStack invalidateQueries cancellation, and WS reconnect coordination with project switches — none have prior solutions docs.

Run artifact#

/tmp/compound-engineering/ce-code-review/20260527-220426-53590818/

Documents
.impeccable
0001-agent-enrollment-two-token-exchange
0002-docker-supervision-over-pm2
0003-bind-agent-to-enrollment-token
0004-agent-api-revisable-until-1.0
0005-version-public-api-after-1.0
0006-seaweedfs-over-minio
0007-three-api-surfaces
0008-betterauth-over-handrolled-jwt
0009-postgres-task-store-bullmq-orchestration
0010-schema-first-drizzle-zod
0011-pull-advisory-notify-task-distribution
0012-in-memory-websocket-v1-redis-deferred
0013-route-as-spec-hono-zod-openapi
0014-turborepo-bun-over-nx
0015-append-only-telemetry-timescaledb-rrd
0016-server-fanout-bus
0017-adaptive-task-sizing-lease
0018-real-db-integration-test-lane
0019-campaign-archiving-immutable-lifecycle
155-ac-traceability-matrix
155-task-distribution-assignment-spec
156-ac-traceability-matrix
156-object-storage-file-management-spec
160-login-project-selection-ui
2026-05-25-websocket-realtime-infrastructure-requirements
2026-05-29-dashboard-stats-and-read-endpoint-contract-requirements
2026-05-31-openapi-auto-generation-migration-requirements
2026-06-08-results-analysis-export-ui-requirements
2026-06-19-task-distribution-architecture
2026-06-20-campaign-archiving-requirements
2026-06-30-hash-export-import-search-requirements
227-spa-deep-link-refresh-redirect-spec
94-p0-cracker-binary-management-agent-auto-update
96-keyspace-task-distribution-spec
97-task-preemption-spec
99-attack-complexity-state-machine-spec
AGENTS
AGENTS
AI_POLICY
AI_POLICY
ARCHITECTURE
ARCHITECTURE
Agent_Authentication_&_Authorization
Agent_Heartbeat_&_Error_Handling
Agent_List_&_Detail_UI
Base Model Schema System
BullMQ_Queue_Architecture_&_Redis_Integration
CLAUDE
CONTRIBUTING
CONTRIBUTING
Campaign_Creation_Wizard_UI
Campaign_List_&_Detail_UI
Campaign_Orchestration_API
Code Quality Automation with Husky and Kiro Hooks
Core_Flows__HashHive_User_Journeys
Dashboard_&_Real-Time_Monitoring_UI
Dashboard_Stats_API_Endpoint_(GET__api_v1_dashboard_stats)
Development Workflow and Tooling Integration
ESLint and Formatting Configuration
Epic_Brief__HashHive_-_Modern_Distributed_Password_Cracking_Platform
GOTCHAS
GOTCHAS
Health Check Endpoint Enhancements
Login_&_Project_Selection_UI
MERN_proposal
Mixed Hash Type Detection & Automatic Campaign Splitting (#202)
MongoDB Connection Management
Object_Storage_&_File_Management
Project_Selection_&_User_Authentication_API
README
README
README
README
README
README
Real-Time_Events_&_WebSocket_Infrastructure
Resource_Management_API
Resource_Management_UI
Results_API_&_CSV_Export_(Dashboard_Backend)
Results_Analysis_&_Export_UI
SECURITY
SECURITY
STRATEGY
Task_Distribution_&_Assignment
Tech_Plan__HashHive_Architecture
Testing Strategy for Database and Models
advanced_task_scheduler
agent
agent-resource-protocol
agent-server-collaboration-vision
agent-token-rotation
agent_notes
agent_sync_extensions
agent_v1_contract_violations
allow_hybrid_hash_lists
attack
attack_notes
authentication_cleanup
back-compat-credential-format-migration
barrel-plus-subdir-service-split
brute_force_attack_editor
bullmq-jobid-dedup-requires-eviction
bun-test-mock-module-import-order
campaign_list_view
campaign_notes
campaigns
ci_check.prompt
code_review.prompt
contract-test-mocks-mirror-service-not-schema
copilot-instructions
core_algorithm_implementation_guide
crackable_uploads_plan
dashboard-read-endpoint-contract
dashboard-ux
default_config_suggestions
development
development
feat-agent-list-detail-ui
feat-betterauth-project-selection-rbac
feat-campaign-list-detail-ui
feat-masklist-keyspace
form-submit-payload-null-checks-2026-05-19
full_testing_architecture
getbytext-collision-waitfor-timeout
hard_password_attack_strategies
hash_hive_gap_analysis
health_status_screen
implementation_plan
learned_rules_parser_plan
llmstxt.prompt
markov_autogen_plan
new_dictionary_attack_editor
new_mask_attack_editor
openldap-testcontainer-bootstrap-race
performance_tuning.prompt
phase-1-core-infrastructure
phase-2-api-implementation
phase-2-api-implementation-part-1
phase-2-api-implementation-part-2
phase-2-api-implementation-part-3
phase-2b-resource-management
phase-2c-refactor-cleanup
phase-3-e2e-test-coverage-plan
phase-3-step-1
phase-3-step-2
phase-3-step-3
phase-3-step-4
phase-3-step-5
phase-3-web-ui-foundation
phase-4-containerization-deployment
phase-5-task-distribution
phase-6-monitoring-testing-documentation
playwright-shared-seed-user-last-project-id-flake
playwright-visual-baselines
pre-prod-wire-rename-and-schema-version-bump
previous_password_dictionary_attack_editor
projection-narrows-zrecord-wire-shape
psycopg_migration
radix-roving-focus-preventdefault-breaks-keyboard-nav
reactflow-position-by-array-index-2026-05-19
rule_explanation
salvage_templates
security_hardening.prompt
shadcn-radix-non-destructive-add-on-tailwind-v4
shared-zod-openapi-wire-contract-mirror-2026-05-25
spa_to_ssr
summary
template
test-coverage-plan
testcontainers_minio_support
testing
testing
user_flows_notes
v2-upgrade-overview
v2_agent_api_removal
work_next_task.prompt