## 1. Backend Schema Extraction - [ ] 1.1 Create `apps/api/src/schemas/__init__.py` with re-exports - [ ] 1.2 Extract `schemas/tool_type.py` from `api/tool_types.py` (ToolTypeCreate, ToolTypeUpdate, validation schemas) - [ ] 1.3 Extract `schemas/tool_instance.py` from `api/tool_instances.py` (CreateInstanceRequest, StartInstanceRequest, SessionItemResponse, SessionListResponse) - [ ] 1.4 Extract `schemas/config_profile.py` from `api/config_profiles.py` (ConfigProfileCreate, ConfigProfileUpdate, ConfigProfileResponse, DefaultProfilesUpdate, ValidateGitUrlRequest, ValidateGitUrlResponse, GitMountItem, MountItem) - [ ] 1.5 Extract `schemas/health.py` from `api/health.py` (DatabaseHealth, DiskHealth, HealthChecks, HealthResponse, DatabaseHealthResponse) - [ ] 1.6 Extract `schemas/user.py` from `api/users.py` (UserProfileResponse, UserProfileUpdate) - [ ] 1.7 Extract `schemas/user_config.py` from `api/user_config.py` (any request/response schemas) - [ ] 1.8 Extract `schemas/project.py` from `api/projects.py` (any request/response schemas) - [ ] 1.9 Extract `schemas/ssh_key.py` from `api/ssh_keys.py` (any request/response schemas) - [ ] 1.10 Extract `schemas/git_repository.py` from `api/git_repositories.py` (any request/response schemas) - [ ] 1.11 Update all API routers to import schemas from `src.schemas.*` instead of defining inline - [ ] 1.12 Verify `py_compile` and `ruff` pass on all schema files ## 2. Docker Service Package Split - [ ] 2.1 Create `apps/api/src/services/docker/__init__.py` with re-exports for backward compatibility - [ ] 2.2 Create `apps/api/src/services/docker/compose.py` from `services/docker.py`: - `render_compose_template`, `write_compose_file`, `_modify_compose_file`, `_ensure_container_name_in_compose`, `_ensure_web_bind_address`, `_ensure_backend_network_in_compose`, `_sanitize_compose_file`, `sort_volumes_by_specificity` - [ ] 2.3 Create `apps/api/src/services/docker/container.py` from `services/docker.py`: - `get_container_status`, `get_container_logs`, `get_container_id`, `wait_for_container_running`, `get_container_ip_on_network`, `is_container_on_network`, `connect_container_to_network`, `get_backend_network_name` - [ ] 2.4 Create `apps/api/src/services/docker/config_staging.py` from `services/docker.py`: - `write_env_file`, `write_config_files`, `ensure_instance_directory` - [ ] 2.5 Create `apps/api/src/services/docker/tunnel.py` from `services/tunnel.py`: - `extract_tunnel_url` (move tunnel URL regex extraction here), `start_tunnel`, `stop_tunnel`, `check_tunnel_health`, `recreate_tunnel` - [ ] 2.6 Remove `apps/api/src/services/docker.py` after verifying all imports updated - [ ] 2.7 Update `services/tunnel.py` to delegate URL extraction to `docker/tunnel.py` or remove if fully subsumed - [ ] 2.8 Update all consumers (`api/tool_instances.py`, `services/instance_lifecycle.py`, etc.) to import from `services.docker` package - [ ] 2.9 Verify `py_compile` and `ruff` pass ## 3. Instance Lifecycle Extraction - [ ] 3.1 Create `apps/api/src/services/instance_lifecycle.py`: - Extract `create_new_instance`, `start_existing_instance`, `stop_existing_instance`, `restart_existing_instance`, `delete_existing_instance` from `api/tool_instances.py` - Extract helper functions: `_prepare_manifest_instance`, `_modify_compose_file`, `_ensure_container_name_in_compose`, `_ensure_web_bind_address`, `_ensure_backend_network_in_compose`, `_sanitize_compose_file`, `_resolve_git_mounts`, `_clone_git_repo`, etc. - [ ] 3.2 Thin `api/tool_instances.py` to ~300 lines: - HTTP routing, auth validation, request parsing - Delegate to `instance_lifecycle.py` service functions - [ ] 3.3 Move `sessions_router` from `api/tool_instances.py` to `api/users.py` or keep as separate `api/sessions.py` (align with `b6f89f9` pattern) - [ ] 3.4 Verify all instance endpoints (create, start, stop, restart, delete, list, get) still work - [ ] 3.5 Verify `py_compile` and `ruff` pass ## 4. Config Profile Service Extraction - [ ] 4.1 Create `apps/api/src/services/config_profiles.py`: - Extract `get_owned_profile`, `check_duplicate_name`, `profile_to_dict`, `_validate_default_profiles`, `get_default_profiles`, `set_default_profiles`, `get_default_profile_for_tool_type`, `get_or_create_user_config`, `list_includes_for_profile`, `list_mounts_for_profile` from `api/config_profiles.py` - Add cycle detection helpers (`_detect_cycle`, `validate_includes_no_cycle`) - [ ] 4.2 Thin `api/config_profiles.py` to ~200 lines: - HTTP routing, request parsing - Delegate to `services/config_profiles.py` - [ ] 4.3 Verify all config profile endpoints (CRUD, includes, defaults, preview, validate-git-url) still work - [ ] 4.4 Verify `py_compile` and `ruff` pass ## 5. Auth Dependency Refactor - [ ] 5.1 Add `get_current_user` to `apps/api/src/auth/dependencies.py`: - Decode session cookie, look up user in DB, return `User` model - Raise 401 if missing/invalid session or user not found - [ ] 5.2 Migrate `api/users.py` to use `get_current_user` instead of `get_current_user_id` + `_get_user` - [ ] 5.3 Migrate `api/tool_instances.py` sessions_router to use `get_current_user` where appropriate - [ ] 5.4 Migrate other routers incrementally (dashboard, projects, etc.) where the full user object is needed - [ ] 5.5 Keep `get_current_user_id` for endpoints that only need the ID - [ ] 5.6 Verify `py_compile` and `ruff` pass ## 6. Frontend Reorganization - [ ] 6.1 Rename API files to kebab-case: - `tool_types.ts` → `tool-types.ts` - `ssh_keys.ts` → `ssh-keys.ts` - `git_repositories.ts` → `git-repositories.ts` - Update all imports in pages and components - [ ] 6.2 Rename page files to `*Page.tsx`: - `dashboard.tsx` → `DashboardPage.tsx` - `projects.tsx` → `ProjectsPage.tsx` - `sessions.tsx` → `SessionsPage.tsx` - `settings.tsx` → `SettingsPage.tsx` - `ssh-keys.tsx` → `SshKeysPage.tsx` - `terminal.tsx` → `TerminalPage.tsx` - `tool-workshop.tsx` → `ToolWorkshopPage.tsx` - `config-profiles.tsx` → `ConfigProfilesPage.tsx` - `git-repositories.tsx` → `GitRepositoriesPage.tsx` - `repo-workspace.tsx` → `RepoWorkspacePage.tsx` - `workspaces.tsx` → `WorkspacesPage.tsx` - `workspace-detail.tsx` → `WorkspaceDetailPage.tsx` - `profile.tsx` → `ProfilePage.tsx` - `project-settings.tsx` → `ProjectSettingsPage.tsx` - `git-history.tsx` → `GitHistoryPage.tsx` - Update `router.tsx` imports - [ ] 6.3 Move components into `features/` directories: - Create `components/features/git/` and move git-related components - Create `components/features/dashboard/` and move dashboard components - Create `components/features/project/` and move project components - Update all imports - [ ] 6.4 Verify `npm run typecheck` passes - [ ] 6.5 Verify `npm run build` passes ## 7. Integration and Verification - [ ] 7.1 Run backend tests: `docker exec hq-api pytest` - [ ] 7.2 Run backend typecheck: `pyright` or equivalent - [ ] 7.3 Run backend lint: `ruff check` - [ ] 7.4 Run frontend typecheck: `npm run typecheck` - [ ] 7.5 Run frontend build: `npm run build` - [ ] 7.6 Run `docker compose up --build` and verify API starts - [ ] 7.7 Verify key user flows manually: - Create a tool instance - Start/stop an instance - Create a config profile - Set a default config profile - View sessions list - Open terminal - [ ] 7.8 Verify no 404s or import errors in browser console ## 8. Documentation - [ ] 8.1 Update `AGENTS.md` or backend README with new module structure - [ ] 8.2 Document the `get_current_user` vs `get_current_user_id` pattern for future contributors