refactor(api): enforce protocol-neutral service boundaries

- refactor: move HTTP status and DTO concerns out of model and service
  layers into API and handler code.
- feat: add admin service boundary and route auth through services
  instead of direct repository access.
- test: add architecture and error tests covering package boundaries,
  redaction, and service behavior.
- docs: record the protocol-neutral boundary decision and update
  architecture and roadmap notes.
This commit is contained in:
2026-07-05 23:30:17 +08:00
parent 28e17a5b08
commit 63ede5c237
34 changed files with 1028 additions and 438 deletions
+5 -4
View File
@@ -42,7 +42,8 @@ func setupAdminRouter(t *testing.T) (*gin.Engine, repository.UserRepository) {
)
authHandler := NewAuthHandler(authService)
adminHandler := NewAdminHandler(userRepo)
adminService := service.NewAdminService(userRepo)
adminHandler := NewAdminHandler(adminService)
gin.SetMode(gin.TestMode)
r := gin.New()
@@ -54,8 +55,8 @@ func setupAdminRouter(t *testing.T) (*gin.Engine, repository.UserRepository) {
}
admin := r.Group("/api/v1/admin")
admin.Use(middleware.AuthRequired(secret))
admin.Use(middleware.AdminRequired(userRepo))
admin.Use(middleware.AuthRequired(authService))
admin.Use(middleware.AdminRequired())
{
admin.GET("/users", adminHandler.ListUsers)
admin.GET("/users/:id", adminHandler.GetUser)
@@ -104,7 +105,7 @@ func loginHelper(t *testing.T, r *gin.Engine, email, password string) string {
t.Fatalf("login %s: status = %d, body = %s", email, rec.Code, rec.Body.String())
}
var pair service.TokenPair
var pair testTokenPairResponse
if err := json.Unmarshal(rec.Body.Bytes(), &pair); err != nil {
t.Fatalf("unmarshal login response: %v", err)
}