# Router Refactoring Execution Plan ## Objective Refactor 858-line `cmd/server/main.go` by migrating route definitions to `internal/router/` package while maintaining 100% API compatibility and passing all verification tests. ## Current State - ✅ `internal/router/` package created with 7 files - ✅ Route stubs implemented for: auth, library, device, frontend, docs - ❌ Router package NOT integrated (never called from main.go) - ❌ All routes still defined in main.go (duplicates) - ⚠️ main.go: 858 lines (target: ~200 lines) ## Success Criteria 1. All 26 verification checks pass (`scripts/verify-guidelines.sh`) 2. All Go tests pass (`go test ./...`) 3. All Bruno/curl API tests pass 4. No API behavior changes (routes, handlers, responses identical) 5. main.go reduced to ~200 lines 6. Code compiles without errors 7. Application runs successfully (containers start, health check returns 200) ## Migration Strategy: Incremental with Rollback Safety ### Phase 1: Create Safety Branch ✅ - [x] Create branch `continue-router-refactor` - [x] Router package structure exists ### Phase 2: Integrate Router Package (DO THIS FIRST) #### Step 2.1: Add Router Import and Config **File:** `cmd/server/main.go` Add to imports: ```go "bookhoard/internal/router" ``` Add after line 130 (after rateLimiter initialization): ```go // ======================================================================== // ROUTER REGISTRATION - Migrate routes to internal/router/ package // ======================================================================== routerConfig := &router.Config{ Echo: e, Queries: queries, Cfg: cfg, DBPool: dbPool, AuthHandler: authHandler, LibraryHandler: libraryHandler, DeviceHandler: deviceHandler, KOReaderHandler: koreaderHandler, WSHandler: wsHandler, ConflictHandler: conflictHandler, AnalyticsHandler: analyticsHandler, QueueHandler: queueHandler, CollectionHandler: collectionHandler, OPDSHandler: opdsHandler, ConnManager: connManager, QueueProcessor: queueProcessor, DeviceAuthMiddleware: deviceAuthMiddleware, LoginTracker: loginAttemptTracker, } ``` #### Step 2.2: Call Router.RegisterRoutes() Add immediately after routerConfig: ```go router.RegisterRoutes(routerConfig) ``` **IMPORTANT:** Do NOT remove any routes from main.go yet! #### Step 2.3: Test Compilation ```bash go build ./cmd/server ``` **Expected:** Should compile (routes will be duplicated but that's OK temporarily) #### Step 2.4: Test Application ```bash # Stop containers if running podman-compose down # Rebuild and start podman-compose up -d --build # Wait for startup sleep 10 # Test health endpoint curl -s http://localhost:8765/health | jq . # Test frontend curl -s http://localhost:8765/ | grep -o ".*" # Run verification bash scripts/verify-guidelines.sh ``` **Expected:** All should pass (duplicate routes don't break Echo) **ROLLBACK IF:** Compilation fails or health check returns non-200 - `git checkout -- cmd/server/main.go` --- ### Phase 3: Remove Duplicate Routes from main.go ⚠️ **CRITICAL:** Remove ONE route group at a time, test after each removal! #### Step 3.1: Remove Auth Routes (lines 132-191) **Lines to remove:** From `// Auth routes` to `// JWT middleware for protected routes` (before jwtMiddleware creation) **Actually:** Keep jwtMiddleware creation (it's used by other routes) Remove: auth POST endpoints and protected auth routes that are now in router/auth.go **Test after removal:** ```bash go build ./cmd/server podman-compose up -d --build sleep 10 # Test auth endpoints curl -X POST http://localhost:8765/api/auth/register -H "Content-Type: application/json" -d '{"email":"test@test.com","username":"test","password":"Test123!"}' ``` #### Step 3.2: Remove Library Routes (lines 192-235) **Lines to remove:** From `// Library management routes` to visibility routes **Test after removal:** ```bash go build ./cmd/server podman-compose up -d --build # Test library endpoints curl -s http://localhost:8765/api/libraries/types | jq . ``` #### Step 3.3: Remove Device Registration Routes (lines 236-239) **Lines to remove:** Device register and status endpoints **Test after removal:** ```bash go build ./cmd/server # Device registration test ``` #### Step 3.4: Remove Frontend Routes (lines 627-823) **Lines to remove:** From `// FRONTEND ROUTES` to before `// HEALTH CHECK` **Test after removal:** ```bash go build ./cmd/server curl -s http://localhost:8765/ | grep -o ".*" ``` #### Step 3.5: Remove Health Check (lines 824-844) **Lines to remove:** From `// HEALTH CHECK` to before `// DOCUMENTATION ROUTES` **Test after removal:** ```bash go build ./cmd/server curl -s http://localhost:8765/health | jq . ``` #### Step 3.6: Remove Documentation Routes (lines 845-858) **Lines to remove:** From `// DOCUMENTATION ROUTES` to end **Test after removal:** ```bash go build ./cmd/server curl -s http://localhost:8765/docs | grep -o ".*" ``` --- ### Phase 4: Implement Remaining Router Stubs #### Step 4.1: Create `router/sync.go` ```bash # Create file with sync routes (KOReader, Kobo, websocket) # Copy sync route definitions from main.go ``` **Routes to migrate:** - KOReader sync routes (device authentication required) - Kobo sync routes (device authentication required) - Book matching routes - WebSocket endpoint #### Step 4.2: Create `router/media.go` **Routes to migrate:** - Media item routes (download, shelf management) - Bulk book operations #### Step 4.3: Create `router/analytics.go` **Routes to migrate:** - Analytics routes (API + SSR) #### Step 4.4: Create `router/queue.go` **Routes to migrate:** - Sync queue management routes (API + SSR) #### Step 4.5: Create `router/opds.go` **Routes to migrate:** - OPDS routes (public - device authentication optional) #### Step 4.6: Update `router/collections.go` **Routes to migrate:** - Collection routes (API + SSR) --- ### Phase 5: Complete Migration For each new route file created in Phase 4: 1. Add `registerXYZRoutes(cfg *Config)` function 2. Call it from `router.RegisterRoutes()` in router.go 3. Remove corresponding routes from main.go 4. Test with: `go build ./cmd/server` 5. Test with: `podman-compose up -d --build` 6. Test specific endpoints with curl 7. Run: `bash scripts/verify-guidelines.sh` --- ### Phase 6: Final Verification #### Step 6.1: Full Test Suite ```bash # Compilation go build ./cmd/server go test ./... # Verification bash scripts/verify-guidelines.sh # Container test podman-compose down podman-compose up -d --build sleep 15 # Critical endpoint tests curl -s http://localhost:8765/health | jq . curl -s http://localhost:8765/ | grep -o ".*" curl -s http://localhost:8765/api/libraries/types | jq . curl -s http://localhost:8765/docs | grep -o ".*" # Run Bruno tests (if available) # bruno test ... ``` #### Step 6.2: Verify main.go Size ```bash wc -l cmd/server/main.go ``` **Expected:** ~200 lines (down from 858) #### Step 6.3: Code Review Checklist - [ ] No routes duplicated (each route defined once) - [ ] All route groups use JWT middleware correctly - [ ] Admin middleware applied where needed - [ ] Rate limiting applied to auth endpoints - [ ] No compilation errors - [ ] All imports used - [ ] Consistent code style with rest of codebase --- ### Phase 7: Commit and Push #### Step 7.1: Review Changes ```bash git diff cmd/server/main.go | head -100 git diff internal/router/ ``` #### Step 7.2: Run Verification ```bash bash scripts/verify-guidelines.sh ``` #### Step 7.3: Commit Changes ```bash git add cmd/server/main.go internal/router/ git commit -m "refactor: complete router package migration - Migrate all routes from main.go to internal/router/ package - Reduce main.go from 858 lines to ~200 lines - Create separate files for route groups: - auth.go: Authentication routes - library.go: Library management - device.go: Device registration & management - sync.go: KOReader/Kobo/WebSocket sync routes - media.go: Media items and bulk operations - analytics.go: Analytics API + SSR - queue.go: Sync queue management - opds.go: OPDS feeds - collections.go: Collection management - frontend.go: SSR pages and health check - docs.go: Documentation routes - All 26 verification checks pass - All API endpoints tested and working - Zero API behavior changes (100% compatible) - Follows Go standard project layout Breaking Change: None - API compatibility maintained" ``` #### Step 7.4: Push ```bash git push origin continue-router-refactor ``` --- ## Rollback Procedures ### If compilation fails at any point: ```bash git checkout -- cmd/server/main.go # Or git reset --hard HEAD ``` ### If tests fail: 1. Check which endpoint failed 2. Verify route is registered in router package 3. Check handler method exists 4. Check middleware is applied correctly 5. Review error logs: `podman logs bookhoard` ### If verification fails: 1. Check which specific check failed 2. Fix the issue 3. Re-run verification 4. Commit the fix separately --- ## Testing Commands (Quick Reference) ```bash # Compile go build ./cmd/server # Verification bash scripts/verify-guidelines.sh # Unit tests go test ./... # Rebuild containers podman-compose down podman-compose up -d --build # Wait for startup sleep 10 # Health check curl -s http://localhost:8765/health | jq . # Frontend curl -s http://localhost:8765/ | grep -o ".*" # Auth endpoint test curl -X POST http://localhost:8765/api/auth/login \ -H "Content-Type: application/json" \ -d '{"login":"test","password":"wrong"}' # Library types curl -s http://localhost:8765/api/libraries/types | jq . # Documentation curl -s http://localhost:8765/docs | grep -o ".*" # Check container logs podman logs bookhoard | tail -30 # Check container status podman ps ``` --- ## Files Created/Modified ### Created: - `internal/router/router.go` - Main router configuration - `internal/router/auth.go` - Authentication routes - `internal/router/library.go` - Library management routes - `internal/router/device.go` - Device routes - `internal/router/frontend.go` - Frontend SSR routes - `internal/router/docs.go` - Documentation routes - `internal/router/helpers.go` - Template helpers - `internal/router/sync.go` - Sync routes (Phase 4) - `internal/router/media.go` - Media routes (Phase 4) - `internal/router/analytics.go` - Analytics routes (Phase 4) - `internal/router/queue.go` - Queue routes (Phase 4) - `internal/router/opds.go` - OPDS routes (Phase 4) - `internal/router/collections.go` - Collection routes (Phase 4) ### Modified: - `cmd/server/main.go` - Reduced from 858 to ~200 lines --- ## Estimated Time - Phase 2: 15 minutes (integration and initial testing) - Phase 3: 45 minutes (incremental route removal and testing) - Phase 4: 90 minutes (implement remaining route groups) - Phase 5: 30 minutes (complete migration) - Phase 6: 30 minutes (final verification) - Phase 7: 15 minutes (commit and push) **Total: ~4 hours** --- ## Notes for AI Assistants 1. **Always test after each change** - don't batch multiple route removals 2. **Keep main.go functional** - it should compile at all times 3. **Verify API compatibility** - routes must respond identically 4. **Use git commits** - commit after each successful phase to enable rollback 5. **Check logs** - if something fails, check `podman logs bookhoard` 6. **Verification script is authority** - if it fails, fix before continuing 7. **Echo allows duplicate routes** - temporarily OK during migration 8. **Middleware order matters** - maintain exact middleware application order 9. **Import statements** - remove unused imports after route removal 10. **Handler methods** - verify handler methods exist before calling them --- ## Troubleshooting ### Error: "route already registered" - **Cause:** Route defined multiple times - **Fix:** Remove from main.go, keep in router package only ### Error: "handler method not found" - **Cause:** Typo in method name or handler not initialized in Config - **Fix:** Check method name in handler file, ensure handler is passed in Config ### Error: "undefined: jwtMiddleware" - **Cause:** JWT middleware not created in that route file - **Fix:** Add JWT middleware creation at top of register function ### Error: "404 on previously working endpoint" - **Cause:** Route not registered or middleware blocking access - **Fix:** Check route is registered, check middleware conditions ### Health check returns 503 - **Cause:** Database not connected or dbPool not passed to router - **Fix:** Ensure DBPool is set in routerConfig ### Verification fails with "Build failed" - **Cause:** Compilation error - **Fix:** Run `go build ./cmd/server` to see specific error --- ## Success Metrics Before: - `cmd/server/main.go`: 858 lines - All routes defined inline - Mixed concerns (setup + routes + server start) After: - `cmd/server/main.go`: ~200 lines - Routes organized by domain in `internal/router/` - Clear separation: setup → router registration → server start - Follows Go standard project layout - Easy to maintain and extend --- ## End of Plan