feat(repository): refactor query/mutation ports with capability-safe

interfaces

- refactor: split UserRepository into AuthUserRepository and
  AdminUserRepository capabilities
- refactor: split SessionRepository into AuthSessionRepository and
  repository-owned CLI/admin methods
- refactor: replace generic Repository Update/Delete with
  operation-specific params and ownership predicates
- refactor: replace CredentialRepository generic CRUD with
  passkey-specific methods
- refactor: replace FileRepository generic Create/Update/Delete with
  UploadedFileParams, DirectoryParams, and owned soft-delete
- refactor: remove repository fields from WebApp struct; repositories
  are now composition-time wiring only
- feat: add domain error kinds ErrParentNotFound, ErrParentNotDir,
  ErrDirectoryNotEmpty, ErrInvalidMove
- feat: add CredentialTypeAppPasskey constant
- feat: add testutil.SetUserAdmin for test fixture setup that bypasses
  production service ports
- test: add architecture test banning GORM Save in repository package
- test: add capability interface contract tests ensuring each service
  receives the minimal interface
- test: add blockingStorage helper for concurrent promotion tests
- test: add preserved DSN parameter test for sqliteImmediateDSN
- docs: update architecture decisions with repository write rules and
  capability separation
- docs: update roadmap to clarify atomic single-use refresh sessions
- docs: add -race test target to development docs
This commit is contained in:
2026-07-16 12:24:36 +08:00
parent 6604ecb026
commit a18f96912d
30 changed files with 1259 additions and 394 deletions
+19 -35
View File
@@ -17,15 +17,11 @@ type WebApp struct {
Config *config.Config
Version string
DB *gorm.DB
UserRepo repository.UserRepository
SessionRepo repository.SessionRepository
FileRepo repository.FileRepository
CredentialRepo repository.CredentialRepository
AuthService *service.AuthService
AdminService *service.AdminService
FileService *service.FileService
Storage storage.StorageBackend
DB *gorm.DB
AuthService *service.AuthService
AdminService *service.AdminService
FileService *service.FileService
Storage storage.StorageBackend
}
// Bootstrap creates a fully initialized WebApp from config.
@@ -62,43 +58,31 @@ func Bootstrap(cfg *config.Config) (*WebApp, error) {
adminService := service.NewAdminService(userRepo)
return &WebApp{
Config: cfg,
Version: AppVersion,
DB: db,
UserRepo: userRepo,
SessionRepo: sessionRepo,
FileRepo: fileRepo,
CredentialRepo: credentialRepo,
AuthService: authService,
AdminService: adminService,
FileService: fileService,
Storage: store,
Config: cfg,
Version: AppVersion,
DB: db,
AuthService: authService,
AdminService: adminService,
FileService: fileService,
Storage: store,
}, nil
}
// NewWebApp creates a WebApp with pre-built dependencies (useful for testing).
func NewWebApp(cfg *config.Config, db *gorm.DB,
userRepo repository.UserRepository,
sessionRepo repository.SessionRepository,
fileRepo repository.FileRepository,
credentialRepo repository.CredentialRepository,
authService *service.AuthService,
adminService *service.AdminService,
fileService *service.FileService,
store storage.StorageBackend,
) *WebApp {
return &WebApp{
Config: cfg,
Version: AppVersion,
DB: db,
UserRepo: userRepo,
SessionRepo: sessionRepo,
FileRepo: fileRepo,
CredentialRepo: credentialRepo,
AuthService: authService,
AdminService: adminService,
FileService: fileService,
Storage: store,
Config: cfg,
Version: AppVersion,
DB: db,
AuthService: authService,
AdminService: adminService,
FileService: fileService,
Storage: store,
}
}