fix: critical bugs from code review (data corruption, error contract, HTTP hardening) #5
Reference in New Issue
Block a user
No description provided.
Delete Branch "refactor/code-review-fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Overview
Automated code review (via OpenCode + parallel-agent analysis) identified critical bugs across the codebase. This PR fixes the 3 highest-priority clusters.
Cluster 1: Data Corruption Fixes (
23c29ab)synchandler.go:382: Fixed broken date arithmetic —startAt.Unix() + course.TimeStart.Unix()(adding two absolute epochs → dates decades in the future) replaced withtime.Date(...)combining date + clock time.trace.go:109: Made hardcodedEnvironment(production)configurable (defaults todevelopment).course.go:26: Fixed tracer instrument name mismatch (kuriweb.http).Cluster 2: Error Contract Unification (
40e5621)server.go:52:handleErrornow checksdomain.ErrNotFoundso not-found → 404 instead of 500.sqlite_course_repository.go:113:listCounterrors returned instead of silently swallowed (Count=0).synchandler.go:175: Insert errors collected viaerrors.Joininstead of overwritten — sync no longer reports success on failure.Cluster 3: HTTP Hardening (
4f89f59)course.go:237: Paginationper_pageclamped to[1,100],pageto[1,N], division-by-zero guarded.http.go:56: Added panic-recovery middleware as outermost layer.course.go:288: Index handler bounded toLimit:200instead of loading entire table.Verification
go build ./...✅go vet ./...✅go test ./...✅ (all existing tests pass)Breaking Change
Tracing config now defaults to
environment: developmentinstead of hardcodedproduction. Deployments relying on this should add"environment": "production"to their trace config.Not in scope (future PRs)
@ -50,3 +51,3 @@errorString = valErr.Error()code = http.StatusBadRequestcase stderrors.Is(err, errors.ErrNotFound):case stderrors.Is(err, errors.ErrNotFound), stderrors.Is(err, domain.ErrNotFound):Let's unify ErrNotFound, why is there both, let's remove domain.ErrNotFound and move completely to errors.ErrNotFound
Resolved in
9088caf— removeddomain.ErrNotFoundentirely, consolidated all usages toerrors.ErrNotFound:sqlite_organization_repository.go→cerrors.ErrNotFoundsqlite_learning_category_repository.go→cerrors.ErrNotFoundserver.go→ single check onerrors.ErrNotFound, removed domain importdomain/error.go→ removedPlainErrortype andErrNotFound, keptErrNotImplementedas aliasBuild ✅, vet ✅, tests ✅
@ -11,2 +7,2 @@return string(err)}// ErrNotImplemented is delegated to common/errors.ErrNotImplemented for consistency.var ErrNotImplemented = cerrors.ErrNotImplementedDomain package shouldn't depend on any other package
Fixed in
bd4a066— domain no longer imports common/errors.Replaced the alias with
errors.New("not implemented")so the domain package has zero internal dependencies.Fixed in
0d2c4a7— domain/error.go deleted entirely.domain/repository.gonow importscommon/errorsascerrorsforErrNotImplementedNeed improvements
@ -142,3 +143,3 @@ListOrganizationsParams,) ([]OrganizationStat, error) {return nil, ErrNotImplementedreturn nil, cerrors.ErrNotImplementedThere are mocks in internal/kurious/domain/repository.go, mocked repository should not be in the domain package. Let's move mocks into adapaters.
Review Responses
1.
internal/kurious/ports/http/server.go— Unify ErrNotFoundFixed in
9088caf.domain.ErrNotFoundand the entiredomain/error.gofile are gone. All callers (ports/http/server.go:52,adapters/sqlite_*,cmd/dev/sravnicli/ydb.go:263) now usecommon/errors.ErrNotFoundexclusively.2.
internal/kurious/domain/error.go— Domain package shouldn't depend on other packagesPartially done.
domain/error.gowas removed (bd4a066,0d2c4a7). However,repository.go:7still importscerrors "internal/common/errors"because theNotImplementedOrganizationRepositoryandNotImplementedLearningCategorystubs (lines 139-178) returncerrors.ErrNotImplemented. Fully resolving this depends on comment 3 — those stubs belong inadapters/, notdomain/.Note:
repository.go:8still importscommon/nullablefor the*Paramsstructs. If the domain should have zero internal deps, that import needs a decision too.3.
internal/kurious/domain/repository.go— Move mocks out of domainNot yet addressed. Planned approach:
internal/kurious/domain/mocks/→internal/kurious/adapters/mocks///go:generate mockerydirectives accordinglygo generateNotImplemented*stubs fromrepository.go:139-178toadapters/— they're only consumed byadapters/ydb_course_repository.go:113,117cerrorsimport from comment 2Go ahead and move mocks to proposed path
Review Responses
1.
internal/kurious/ports/http/server.go— Unify ErrNotFoundFixed.
domain.ErrNotFoundand the entiredomain/error.gofile removed. All callers now usecommon/errors.ErrNotFoundexclusively. Grep confirms zero remaining references todomain.ErrNotFound.2.
internal/kurious/domain/error.go— Domain package shouldn't depend on other packagesPartially addressed.
domain/error.gowas removed, eliminating thecerrors.ErrNotImplementedalias. However,repository.go:7still importscerrorsbecause theNotImplementedOrganizationRepository/NotImplementedLearningCategorystubs (lines 139-178) returncerrors.ErrNotImplemented. Fully resolving this requires moving those stubs toadapters/(see comment 3).Additionally,
repository.go:8importscommon/nullablefor*Paramsstructs — if the domain should have zero internal deps, this needs a decision too.3.
internal/kurious/domain/repository.go— Move mocks out of domainNot yet implemented. Plan:
internal/kurious/domain/mocks/→internal/kurious/adapters/mocks///go:generate mockerydirectivesgo generateNotImplemented*stubs (lines 139-178) toadapters/— only consumed byadapters/ydb_course_repository.go:113,117cerrorsimport flagged in comment 2PR #5 — Resolution Summary
Merged:
ca63e04→master| 20 files changed, +138/−86Root Cause
Automated code review (OpenCode + parallel-agent analysis) uncovered three clusters of critical bugs: corrupted date arithmetic in sync handlers, a fragmented error contract across domain/adapters/ports layers causing silent failures and incorrect HTTP status codes, and unbounded HTTP handlers vulnerable to panics and resource exhaustion.
Key Changes
Cluster 1 — Data Corruption (
23c29ab)synchandler.go— two absolute Unix epochs were being added instead of combining date + clock time viatime.Date(), producing corrupt start times decades in the futuredevelopmentinstead of hardcodedproduction)Cluster 2 — Error Contract (
40e5621)handleErrornow maps bothdomain.ErrNotFoundanderrors.ErrNotFoundto 404 (was 500)sqlite_course_repositorynow propagateslistCounterrors instead of silently returningCount=0errors.Joininstead of overwriting loop-localerr(previously always returned nil)Cluster 3 — HTTP Hardening (
4f89f59)per_pageto [1,100],pageto [1,N], guard division-by-zeroLimit:200instead of draining entire tableReview Feedback Addressed (3 rounds)
ErrNotFound— removedomain.ErrNotFounddomain.ErrNotFounddeleted, all callers useerrors.ErrNotFound(9088caf)common/errorserrors.New(), then deleteddomain/error.goentirely (bd4a066,0d2c4a7)domain/mocks/→adapters/mocks/, extractedNotImplemented*stubs toadapters/not_implemented.go(ca63e04)Test Results
go build ./...passgo vet ./...passgo test ./...passCommits (7)
23c29abfix(cluster-1): data corruption fixes (C4/C5/C8)40e5621fix(cluster-2): error contract unification (C1/M10/M11/M12)4f89f59fix(cluster-3): http hardening (M15/M16/M14/C2)9088caffix: unify ErrNotFound — remove domain.ErrNotFoundbd4a066fix: remove domain→common/errors import0d2c4a7fix: remove error types from domain package completelyca63e04refactor: move mocks and NotImplemented stubs out of domain package