upload's four real background tasks (system cleanup, stats rebuild, storage
migration, image warmup) plus the admin and user stubs registered handlers
typed as func(ctx, *asynq.Task) error. Only the asynq worker accepts that
shape; the Redis-free in-process worker's invokeHandler rejects it with
'unsupported handler type', so none of those tasks could ever run in that
deployment mode. Take payload bytes instead, which both drivers support.
Adds architecture gate check 7 forbidding asynq imports from business and
infrastructure plugins. It deliberately does not cover robfig/cron: the admin
plugin uses cron.ParseStandard only to validate a user-entered spec, which is
a library call rather than a driver binding, and the in-process scheduler
already normalizes 5-field specs.
Authenticate, CreateAuthSource, UpdateAuthSource and ToggleAuthSource claimed
success with a nil record, so any test that reached them surfaced a nil
pointer dereference instead of the actual cause. Full suite confirms no test
relied on the silent behaviour.
EnsureCompressedImageCache passed the arriving caller's request context into
the singleflight body, which runs once for every concurrent requester of that
cache key. If the first client disconnected, gin canceled the context, the
shared generation aborted, and every follower received that failure and fell
back to the uncompressed original. Detach cancellation with
context.WithoutCancel so trace values still propagate but the shared work
outlives any single requester.
ServeFileByID and DownloadFile duplicated the lookup failure mapping and
each used an unchecked *strconv.NumError assertion that cannot match a
wrapped error. One helper now classifies 404 vs 400 via errors.As; each
endpoint keeps its own fallback for unclassified failures. ErrInvalidUploadID
became unused once both sites report ErrInvalidFileID for a malformed ID.
Five sites used == against sentinels (redis.Nil, ingest.ErrForbidden,
errs.ErrDatabaseUninitialized). The neighbouring not-found checks already
went through errors.Is helpers, so a wrapped error would silently downgrade
a 403 to a 400 and a 500 to a 400.
- Purify core micro-kernel by removing context hardcoded helpers and reverse dependencies
- Eliminate init() side effects in infra plugins with reversible lifecycle disposal
- Completely isolate plugins by removing cross-plugin imports and using core/contracts
- Introduce TaskService and RiskControlService contracts for unified cross-plugin APIs
- Regenerate Swagger documentation and update developer guide matrix
- Achieve 0 violations in check_cordis_architecture.sh and 100% test pass
- Relocated go.mod and go.sum into backend/ root directory
- Stripped redundant backend/ segments from all Go imports (github.com/Rain-kl/Wavelet/...)
- Unified Makefile, swagger, and build-test to execute in backend/ module context
- Ensured 100% build-test, code-check, format, and swagger pass