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
+12 -12
View File
@@ -171,7 +171,7 @@ func TestFileHandler_Upload(t *testing.T) {
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusCreated, rec.Body.String())
}
var info service.FileInfo
var info fileInfoResponse
if err := json.Unmarshal(rec.Body.Bytes(), &info); err != nil {
t.Fatalf("unmarshal: %v", err)
}
@@ -318,7 +318,7 @@ func TestFileHandler_CreateDir(t *testing.T) {
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusCreated, rec.Body.String())
}
var info service.FileInfo
var info fileInfoResponse
if err := json.Unmarshal(rec.Body.Bytes(), &info); err != nil {
t.Fatalf("unmarshal: %v", err)
}
@@ -353,7 +353,7 @@ func TestFileHandler_List(t *testing.T) {
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusOK, rec.Body.String())
}
var list service.FileList
var list fileListResponse
if err := json.Unmarshal(rec.Body.Bytes(), &list); err != nil {
t.Fatalf("unmarshal: %v", err)
}
@@ -378,7 +378,7 @@ func TestFileHandler_Get(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
// Get metadata.
@@ -391,7 +391,7 @@ func TestFileHandler_Get(t *testing.T) {
t.Errorf("status = %d, want %d", rec.Code, http.StatusOK)
}
var info service.FileInfo
var info fileInfoResponse
if err := json.Unmarshal(rec.Body.Bytes(), &info); err != nil {
t.Fatalf("unmarshal: %v", err)
}
@@ -430,7 +430,7 @@ func TestFileHandler_Download(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
// Download.
@@ -466,7 +466,7 @@ func TestFileHandler_DownloadReadErrorAfterResponseStarted(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
if err := json.Unmarshal(rec.Body.Bytes(), &uploaded); err != nil {
t.Fatalf("unmarshal upload: %v", err)
}
@@ -502,7 +502,7 @@ func TestFileHandler_Update(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
// Rename.
@@ -517,7 +517,7 @@ func TestFileHandler_Update(t *testing.T) {
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusOK, rec.Body.String())
}
var updated service.FileInfo
var updated fileInfoResponse
if err := json.Unmarshal(rec.Body.Bytes(), &updated); err != nil {
t.Fatalf("unmarshal: %v", err)
}
@@ -542,7 +542,7 @@ func TestFileHandler_UpdateNoFields(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
updateBody, _ := json.Marshal(gin.H{})
@@ -573,7 +573,7 @@ func TestFileHandler_Delete(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
// Delete.
@@ -613,7 +613,7 @@ func TestFileHandler_ForbiddenAccess(t *testing.T) {
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
var uploaded service.FileInfo
var uploaded fileInfoResponse
json.Unmarshal(rec.Body.Bytes(), &uploaded)
// Try to access as user2.