fix(asset-lifecycle): wire scheduler + dry-run worker + bound worker …#60
Merged
Conversation
…batches Phase 0 shipped the worker, cron controller, and HTTP handlers but none of them were actually connected in cmd/server. Three separate dead-code paths meant the feature compiled, passed tests, and produced no behavior whatsoever in production. Wiring - cmd/server/workers.go now constructs the AssetLifecycleWorker and registers AssetLifecycleController with the ControllerManager so the daily cron tick actually fires. Backward-safe: tenants that have not opted in are skipped inside the worker on the first check. - cmd/server/services.go wires AssetService.SetLifecycleRepository against the Postgres asset repo so the snooze endpoint can write lifecycle_paused_until. - cmd/server/handlers.go + main.go back-wire the worker instance into TenantHandler after workers.Start — because handlers are built first, we expose a package-level WireAssetLifecycleWorker hook instead of re-ordering initialisation (which would risk other services that depend on handler construction). Bounded batches - applyTransitions now runs UPDATE against a CTE-scoped LIMIT so a tenant with 10M stale candidates doesn't lock the table in one transaction. 5K rows per batch, loop until a batch returns fewer rows than the limit; hard cap at 50K transitions per tenant per cron tick so a mis-configured threshold can't saturate the database. Remainder rolls into tomorrow's run. Audit - Worker now emits one asset.lifecycle_run audit event per non-empty tenant run with transitioned_to_stale count, threshold, grace period, excluded source types, and a sample of up to 100 affected asset IDs. Zero-transition runs stay in structured logs only so the audit table doesn't grow daily rows of noise. - Worker keeps running when audit.LogEvent fails — audit outage should not break the security-relevant lifecycle transitions. Intentionally deferred - Per-snooze audit event: snooze endpoint still emits no audit entry because AssetHandler does not yet hold an AuditService reference. Batch worker audit covers the primary "what got demoted and when" question; follow-up to thread AuditService into AssetHandler for per-snooze traceability. - Rate limiting on snooze endpoint: admin-only action, low blast radius, low priority. Revisit if we see abuse. - Reconstitute wiring of lifecycle columns: still omitted from the main asset SELECT pipeline. UI can call the snooze endpoint but cannot yet display "currently snoozed until X" from a GET. Next follow-up when we surface lifecycle state in asset responses.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…batches
Phase 0 shipped the worker, cron controller, and HTTP handlers but none of them were actually connected in cmd/server. Three separate dead-code paths meant the feature compiled, passed tests, and produced no behavior whatsoever in production.
Wiring
Bounded batches
Audit
Intentionally deferred