- add util.Go with panic recovery for background goroutines
- add util.EscapeLike and explicit ESCAPE clause for SQL LIKE queries
- add DummyCheckPassword and subtle.ConstantTimeCompare against timing attacks
- enforce session ID rotation upon login/oauth callback to prevent session fixation
- add sliding window login failure rate limiting and oauth state rate limiting
- fix redis client capture race in pubsub listeners and wait on stop channel
- adjust global --primary to oklch(51.1% 0.262 276.966) for WCAG AA contrast
- fix semantic heading levels and missing aria-labels across UI components
- document security, concurrency, and a11y standards in AGENTS.md
Pusher.Send now returns the upstream response body alongside the error,
so the push task handler can print what the webhook actually replied
(custom channel e.g. {"errcode":0,"errmsg":"ok"} or a rejection
like {"errcode":93000,...}) into the task log on both success and
failure. Other pushers (lark/telegram/email) return an empty string,
keeping their behavior unchanged.
fix(push): surface webhook business errors in custom channel audit
CustomPusher.Send only checked the HTTP status code. WeChat Work /
DingTalk webhooks return HTTP 200 with a non-zero errcode in the body
even when the message is rejected (e.g. template_card requires
card_action.url when type=1), so rejected pushes were recorded as
'success' in the notification history. Parse the response body and
return an error when errcode is non-zero, matching the Lark pusher.
Move process wiring, technical adapters, and cross-cutting contracts out of flat internal/ packages so new code has a clear home without changing business layout.
Introduce internal/repository for data access and cache-backed system
config reads. Move business logic into logics.go across admin push,
user, template, cache, system_config, and upload/handler packages.
Remove Gin from internal/util by relocating request-scoped helpers to
oauth/gin_context.go. Propagate request context for config lookups in
user flows. Slim model entities and delete model-level DB/cache helpers.
Wire handlers to logics/repository so targeted packages no longer call
db.DB directly. Update admin router tests to use ErrorHandlerMiddleware.
- Add middleware_test.go covering ErrorHandlerMiddleware and Abort helpers
- Switch router test setups to testhelper.NewTestGinEngine for error JSON
- Fix OAuth provider cache to use mock HTTP client and normalize issuer URLs
- Add ResetInitRuntimeOnceForTest to make bootstrap tests hermetic under -count
- Update admin/task test imports for upload/task package move
Resolve user package conflicts by keeping main's service-layer logics and
applying Abort* error handling in routers. Align oauth callback with
listener.EmitAdminLoggedIn from main.
Replace c.JSON(200, response.Err) and middleware gin.H bypasses with
response.Abort* helpers so errors flow through Gin Error chain and
ErrorHandlerMiddleware for OTel trace correlation.
Split oauth/sources.go into domain-focused files and decompose upload
into handler/filesrv/stats/task/cache/storage/util subpackages with a
root facade preserving existing import paths.
- Register tasks in admin/task test setup after init() removal
- Strengthen bootstrap test: RegisterPushDomainEvents before Init
- Add admin_login auth→push listener integration test
- Update AGENTS.md and push/new-async-task/new-api skills for
bootstrap composition root, listener domain events, and explicit
test wiring conventions introduced since 50c45db5
Introduce internal/bootstrap as the composition root with sync.Once
guards for task handler registration and push listener wiring. Replace
the single OnTaskCompleted global hook with multi-subscriber handlers
and remove init()-driven side effects from worker, admin task, and push.
Introduce internal/listener as a domain event bus so oauth and user
modules emit AdminLoggedIn without depending on admin/push. Register
push handlers explicitly at the router composition root, replacing
init() side-effect registration and blank imports.
- Implement cached queries in GetActivePushEventByKey and GetActivePushChannelByName.
- Set TTL for cached items to 24 hours via activePushEventCacheTTL and activePushChannelCacheTTL constants.
- Implement GORM hooks (AfterSave and AfterDelete) on PushEvent and PushChannel to auto-evict Redis caches, guaranteeing cache consistency.
- Evict Redis caches manually inside API handlers for Create/Update/Delete/Toggle event/channel endpoints.
- Update events.go to query models through the new caching methods.
- Reject toggling an event to enabled in ToggleEvent handler if channels list is empty.
- Add model-level validation in PushEvent.Validate() to prevent enabling events without channels during creation/updates.
- Update TestPushRouters/toggle_event_status unit test to cover this verification.
- Relocated generic HTTP response helpers (Response, OK, Err, etc.) from internal/util/ to a dedicated internal/common/response/ package.
- Renamed ResponseAny to Any to resolve revive stuttering warnings.
- Moved session building options and cookie headers logic from internal/util/ to internal/apps/oauth/.
- Removed all direct imports of Gin/Sessions/HTTP frameworks from internal/util/ to keep general utilities 100% pure.
- Regenerated Swagger API documentation via make swagger.
- All tests and make code-check compile and pass with 0 issues.
- Add task_type to w_push_events table and GORM models.
- Implement OnTaskCompleted callback hook in task executor to avoid circular dependencies.
- Implement task listener in push package to trigger notifications on task completion.
- Automatically resolve User objects from payload and results.
- Enhance UI to select task completed events and preview default templates.
- Update Swagger documentation.