Skip to content

[architect] tech-debt: introduce handlers.Registrar + Deps to retire pkg/api/handlers _aliases.go shims (epic #23685 Phase 2) #23725

Description

@hivecommons-hive

Architecture Finding

Type: tech-debt / abstraction (follow-up to epic #23685)
Affected area: pkg/api/handlers/ + pkg/api/route_group_*.go

Follow-up to #23685. Phase 1 (domain subpackages) is landed against origin/main @ 40886a18e7:

  • 18 subpackages exist under pkg/api/handlers/ (admin/, k8s/, proxy/, persistence/, ops/, dashboards/, compliance/, mcp/, missions/, stellar/, workloads/, gitops/, rewards/, benchmarks/, feedback/, github/, auth/, internal/httputil/).
  • Root pkg/api/handlers/ now contains 22 files, of which 7 are pure re-export shims (admin_aliases.go, dashboards_aliases.go, k8s_aliases.go, ops_aliases.go, persistence_aliases.go, proxy_aliases.go, transport_aliases.go — 13–69 LOC each) plus small residuals (auth_compat, demo_data, shared_types, shared_utils, k8s_errors, validation) and their tests.
  • Route registration still goes through the root handlers.* symbols: route_group_api_core.go alone has 16 handlers.Foo call sites, route_group_public.go has 9, route_group_governance.go has 4, route_group_feedback.go has 1.

This is exactly the state where Phase 2 from the epic pays off. Filing it as a discrete carve-out so it can be picked up independently.

Impact

  • The _aliases.go shims are a permanent tax — every new/renamed handler in a subpackage requires a matching root re-export or the route group breaks, undermining the boundary the split was meant to establish.
  • Each route_group_*.go still hand-wires the same 8 dependencies (store, hub, k8sClient, config fields, notificationService, persistenceStore, failureTracker, githubToken) into every constructor. Adding a new dep means editing ~5 route-group files and every constructor call.
  • The subpackages have no shared registration contract, so tests can't drive route registration in isolation; today's tests either mount the whole route_group_* or reach past it.
  • New contributors still have to learn "call handlers.NewFooHandler(store, hub, k8sClient, …) here" per handler instead of "register the subpackage".

Recommendation

Land Phase 2 in three PR-sized slices; PRs stay ≤500 LOC each and preserve behavior.

Slice 2a — introduce handlers.Deps and a Registrar interface (new file, no moves)

pkg/api/handlers/registrar.go:

package handlers

import "github.com/gofiber/fiber/v2"

// Deps is the shared dependency set that every handler subpackage needs.
// Add new fields here, not new constructor parameters.
type Deps struct {
    Store               store.Store
    Hub                 *ws.Hub
    K8sClient           kubernetes.Interface
    PersistenceStore    persistence.Store
    NotificationService notify.Service
    FailureTracker      *failure.Tracker
    Config              *config.Config
    GitHubToken         string
}

// Registrar is implemented by each handler subpackage. Route groups call
// Register once per subpackage instead of constructing individual handlers.
type Registrar interface {
    Register(router fiber.Router, deps Deps)
}

No behavior change; all existing constructors continue to work.

Slice 2b — port ONE subpackage (proposal: admin/) to Registrar

  • Add admin.NewRegistrar() handlers.Registrar that internally builds AdminHandler/SettingsHandler/UserHandler/TeamHandler/RBACHandler and calls the same router.Get(…) lines currently duplicated across route_group_api_core.go and route_group_governance.go.
  • Replace those call sites with admin.NewRegistrar().Register(router, deps).
  • Delete admin_aliases.go if no other caller still uses the root re-exports (verify with go build ./...).

This slice is the template. Once it lands, the remaining 5 subpackages (k8s/, proxy/, ops/, dashboards/, persistence/) follow the same recipe and can each land as an independent PR.

Slice 2c — collapse route_group_*.go to a wire-up

Once every subpackage implements Registrar, route_group_api_core.go shrinks from ~234 LOC to a list:

for _, r := range []handlers.Registrar{
    admin.NewRegistrar(),
    k8s.NewRegistrar(),
    proxy.NewRegistrar(),
    ops.NewRegistrar(),
    dashboards.NewRegistrar(),
    persistence.NewRegistrar(),
} {
    r.Register(api, deps)
}

All 7 _aliases.go shims can then be deleted; the root handlers package becomes the Deps + Registrar contract only (~80 LOC).

Out of scope (deliberately)

  • Route path changes — pure structural refactor.
  • Moving auth middleware — that stays in the route group so cross-cutting policy remains centralized.
  • github/, feedback/, compliance/ subpackages that already import cleanly with no root re-exports — they can opt in later but aren't blocking.

Refs epic #23685 (Phase 2 slice — landable as 2a + one 2b template PR to prove out the pattern).


Filed by architect agent (ACMM L6 — full mode)

🐝 Hive Agent: architect | Instance: hosted-kubestellar-console-4vkt | SHA: unknown

— hive: agent=architect backend=copilot model=claude-opus-4.7 copilot=1.0.88

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/architectWork by the architect agentarchitecturehelp wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.hive/hosted-kubestellar-console-4vktHive instance hosted-kubestellar-console-4vkthive/likely-doneHive verified that a merged PR references or claims this issue; pending confirmationrun/specStart a Spektacular spec run for this issuetech-debt

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions