//! Expiry + retention sweeps for tables that would otherwise grow unbounded. //! Security-relevant rows (expired auth sessions, stale oauth states) are //! deleted as soon as they're overdue; audit/journal tables get a generous //! retention window. Each fn returns the number of rows removed. //! //! This is the row-level analogue of the durable-run `requeue_stale` sweep and //! the sandbox reaper — driven on an interval by `cm_api::cleanup_sweeper`. use sqlx::PgPool; use crate::DbError; /// Delete auth sessions past their `expires_at` (a revoked/expired bearer token /// must not linger). Security-relevant — no grace window. pub async fn expire_auth_sessions(pool: &PgPool) -> Result { let r = sqlx::query!("DELETE FROM auth_sessions WHERE expires_at < now()") .execute(pool) .await?; Ok(r.rows_affected()) } /// Delete OAuth CSRF states past their `expires_at` (abandoned flows). pub async fn expire_oauth_states(pool: &PgPool) -> Result { let r = sqlx::query!("DELETE FROM oauth_states WHERE expires_at < now()") .execute(pool) .await?; Ok(r.rows_affected()) } /// Prune successfully-sent outbox rows older than `days` (failed rows are kept /// for inspection). pub async fn prune_sent_outbox(pool: &PgPool, days: i32) -> Result { let r = sqlx::query!( "DELETE FROM outbox WHERE status = 'sent' AND created_at < now() - make_interval(days => $1)", days, ) .execute(pool) .await?; Ok(r.rows_affected()) } /// Prune the SSE run-event journal older than `days` (beyond the live-replay /// window). Removes events for long-finished runs. pub async fn prune_run_events(pool: &PgPool, days: i32) -> Result { let r = sqlx::query!( "DELETE FROM run_events WHERE created_at < now() - make_interval(days => $1)", days, ) .execute(pool) .await?; Ok(r.rows_affected()) } /// Prune routine-run history older than `days`. pub async fn prune_routine_runs(pool: &PgPool, days: i32) -> Result { let r = sqlx::query!( "DELETE FROM routine_runs WHERE started_at < now() - make_interval(days => $1)", days, ) .execute(pool) .await?; Ok(r.rows_affected()) } /// Prune terminal topology runs older than `days` (user-visible run history — /// keep a generous window). pub async fn prune_topology_runs(pool: &PgPool, days: i32) -> Result { let r = sqlx::query!( "DELETE FROM topology_runs WHERE status IN ('completed', 'failed', 'cancelled') AND finished_at IS NOT NULL AND finished_at < now() - make_interval(days => $1)", days, ) .execute(pool) .await?; Ok(r.rows_affected()) } /// Prune consumed single-use execution grants older than `days`. pub async fn prune_consumed_grants(pool: &PgPool, days: i32) -> Result { let r = sqlx::query!( "DELETE FROM execution_grants WHERE consumed = true AND consumed_at < now() - make_interval(days => $1)", days, ) .execute(pool) .await?; Ok(r.rows_affected()) }