Addresses errcheck, gosec, revive, staticcheck, and unused findings
across the codebase (unchecked error returns, unsafe file inclusion
warnings on operator/test-controlled paths, missing package comments,
unused parameters, deprecated API usage). Also fixes two suppression
comments that were silently no-ops due to wrong syntax (#nosec needs
a leading '#', nolint reasons need '//' not '--').
With the backlog clear, drop continue-on-error from the CI lint job
per the plan left in b4b4806.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Store SHA-256 digests (key_hash + key_preview) instead of raw keys, in
both the in-memory store and Postgres; migrate legacy plaintext rows in
place and drop the plaintext column.
- Fix TEXT[] scans that failed at runtime (missing pq.Array) in
GetKey/ListKeys/LoadAllKeys.
- Load persisted keys at startup (InitializeFromDatabase was never called)
and fall back to the database on cache miss, so issued keys survive
restarts.
- Make HybridKeyStore.CreateKey genuinely write-through: cache is only
updated after a successful DB write.
- Guard nil database backend (auth enabled without DB previously panicked
on key creation) and degrade to in-memory operation.
- Persist bootstrap admin keys when a database is configured.
- Record real audit-log details as JSON and log audit failures instead of
silently dropping them; add DB pool limits and ping timeout.
- Sentinel errors matched with errors.Is; unit tests for hashing,
write-through ordering, DB fallback, and nil-DB operation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Use typed context key for auth context to prevent collisions (auth.go)
- Eliminate nested locking in CheckRateLimit to prevent potential deadlock (auth.go)
- Add 1MB request body size limit middleware to prevent DoS (router.go)
- Return proper gRPC status codes instead of nil errors on failures (handler.go)
- Use key name instead of raw API key in admin URL paths to prevent secret leakage (keys.go, router.go, keystore_db.go, keystore_hybrid.go)
- Enforce RBAC authorization in service Send/SendBatch for both REST and gRPC (service.go)
- Pin runtime Docker image to alpine:3.21 for reproducible builds (Dockerfile)
- Enable readOnlyRootFilesystem with /tmp emptyDir in k8s deployment (deployment.yaml)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change IsAuthorized() to use deny-by-default when RBAC is enabled
- If ANY authorization rules are configured, only notifiers with explicit allowed_roles are accessible
- Notifiers without rules are denied access when RBAC is active
- If NO rules are configured, maintain open access for backward compatibility
- Add HasRules() helper method to check if RBAC is enabled
This fixes the issue where notifiers WITHOUT allowed_roles were being returned instead of
the notifiers WITH matching allowed_roles. Now when RBAC is configured:
- Only notifiers with explicit rules that match the user's roles are returned
- All other notifiers are hidden from the client
Example: If only email has allowed_roles=['admin'] and user has role 'admin':
- OLD: email ✓, stdout ✓ (WRONG - stdout should be hidden)
- NEW: email ✓, stdout ✗ (CORRECT - only email is returned)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>