Skip to content

refactor(backend): Phase 3 — decompose internal/api into feature-scoped handler packages#18

Merged
revtex merged 1 commit intodevfrom
restructure/phase-3-handler-packages
Apr 25, 2026
Merged

refactor(backend): Phase 3 — decompose internal/api into feature-scoped handler packages#18
revtex merged 1 commit intodevfrom
restructure/phase-3-handler-packages

Conversation

@revtex
Copy link
Copy Markdown
Owner

@revtex revtex commented Apr 25, 2026

Phase 3 of the directory restructure

Plan reference: docs/plans/directory-restructure-plan.md § Phase 3.

Breaks the monolithic backend/internal/api/ package into per-feature subpackages under backend/internal/handler/. Pure refactor — zero changes to route paths, HTTP methods, middleware ordering, response shapes, status codes, error strings, headers, or query parameters.

What moved

New package From
handler/routes/ api/routes.go (+ all integration tests)
handler/shared/ api/swagger_models.godto.go, api/content_disposition*.go, plus genuinely shared helpers (call_search.go, grants.go, resolve.go, settings.go)
handler/auth/ api/admin.go (mis-named — held auth/login/refresh/me/password/tg-selection) + auth/refresh tests
handler/calls/ api/calls.go + limiter
handler/bookmarks/ api/bookmarks.go
handler/share/ api/share.go + share-limiter test
handler/setup/ api/setup.go
handler/health/ api/health.go
handler/admin/imports/ api/import.go
handler/admin/radioreference/ api/radioreference.go
handler/admin/transcriptions/ api/crud.go (GetTranscriptionStatus)

backend/internal/api/ is gone — not stubbed.

Scope adjustment vs. the original plan

The plan was written before Phase 2 landed and assumed api/admin.go + api/crud.go defined ~14 admin REST handlers. After Phase 2, those 11 admin features (users/systems/talkgroups/tags/groups/units/api_keys/dirmonitors/downstreams/webhooks/logs) are WS-only and already live in internal/admin/ + internal/ws/. Only 3 admin REST handlers actually existed in internal/api/ (imports, radioreference, transcriptions status), so only those 3 admin subpackages were created. No empty placeholder packages.

Other changes

  • cmd/server/main.go imports internal/handler/routes instead of internal/api.
  • swag init invocations updated in backend/Makefile, .github/workflows/ci.yml, .github/workflows/codeql.yml, .github/workflows/release.yml to scan internal/handler instead of internal/api.
  • backend/.golangci.yml swagger-stubs path-include updated.
  • Each handler subpackage exposes type Handler struct, func New(...) *Handler, func (h *Handler) Register(r gin.IRouter). handler/routes/routes.go wires them all with the same middleware ordering as before.

Verification

  • cd backend && go build ./...
  • cd backend && go vet ./...
  • cd backend && go test ./... ✅ (50 test functions, exact parity with the old api/ tests)
  • cd frontend && npx tsc --noEmit
  • rg -n internal/api backend/ Makefile .github/workflows/ returns zero hits.

Audit results

Completeness audit confirmed:

  • All 18 REST routes + 3 WebSocket routes preserved 1:1 from the old routes.go
  • No stray Gin handlers outside internal/handler/ or internal/middleware/
  • All swagger annotations preserved
  • Test-function count parity per file (50 → 50)
  • Every symbol in handler/shared/ has ≥2 consumers across distinct packages

Stats

37 files changed, +695 / -580 — mostly renames; net deletions because thin handlers + the shared dedup add less than the old monolith spent on its in-package machinery.

Soak

Per the plan, this is a pause-and-review point before Phases 4-5 (frontend reorg). Recommend merging to dev and exercising the Admin UI / Scanner UI before continuing.

Changelog

Entry added under ### Changed.

Rollback

git revert the squash commit. Routes, methods, bodies preserved → clients can't observe the move.

… packages

- handler/{auth,calls,bookmarks,share,setup,health}/... for listener + auth routes
- handler/admin/{imports,radioreference,transcriptions}/... for the admin REST surface
  (11 WS-only admin features remain in internal/admin + internal/ws, already extracted in Phase 2)
- handler/shared/ for swagger DTOs and common helpers
- handler/routes/ owns route registration, including /ws and /api/ws
- internal/api/ removed
- Swag invocation in Makefile + 3 workflows updated to scan internal/handler
- Swagger regenerated
- No route, method, body, header, or middleware changes
@revtex revtex merged commit 9dff28f into dev Apr 25, 2026
7 checks passed
@revtex revtex deleted the restructure/phase-3-handler-packages branch April 25, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant