Saltar al contenido principal

Approval queues and expiry

In plain English: some actions on AlphaSwarm are too consequential to happen automatically — placing certain orders, promoting a strategy to live trading, or ingesting a new data source. Those actions go into an approval queue where a human must explicitly say yes. Since August 2026, every queued request also carries an expiry time: if nobody decides within the window, the request lapses instead of waiting around indefinitely. That matters because a "yes" given three days ago may no longer be safe today — markets move, and an approval should describe the world it was granted in.

Which queues exist​

QueueWhat waits in itDecide surface
Order approvalsOrder intents that exceed automatic risk thresholdsOperator UI approvals inbox, /accounts routes
Promotion approvalsResearch → money-plane crossingsPromotion Gates API, step-up MFA + four-eyes
Ingestion approvalsNew data-source onboarding actionsData connector control plane

All three share the same HITL (human-in-the-loop) mechanics: a request row with pending status, an audited decision, and — new — a TTL.

How expiry works​

Three cooperating mechanisms, so expiry holds even if one lags:

  1. Enqueue TTL stamp — every new approval row gets expires_at populated from the queue's TTL setting (order_approval_ttl_seconds, mirroring promotion_approval_ttl_seconds).
  2. Beat sweeper — a guarded Celery beat task (alphaswarm/tasks/approval_expiry_tasks.py) periodically flips overdue pending → expired across all three queues under an advisory lock, emitting one audit event per queue sweep and an order.approval_expired lifecycle fact per order.
  3. Decide-time guards — even if the sweeper hasn't run yet, the approve/reject endpoints check expires_at at decision time and return HTTP 410 Gone for stale requests; PromotionService.approve refuses equivalently.

Backwards compatibility​

Rows created before the feature (with NULL expires_at) are never default-expired — no data migration re-stamps them. Expiry only applies to requests enqueued while the feature is active.

Rollout and flags​

SettingDefaultEffect
approval_expiry_enforcement_enabledoffMaster switch for TTL stamping, sweeping, and decide-time guards.
order_approval_ttl_secondsper deploymentTTL for order approvals.
promotion_approval_ttl_secondsper deploymentTTL for promotion approvals.

The sweeper is registered in the Celery beat ownership manifest (configs/celery_beat_ownership.json), so beat-owner drift is caught by CI rather than at runtime.

Relationship to four-eyes approval​

Expiry answers "how long is a pending request decidable?". The four-eyes rule answers "who may decide?" — the approver must be a different person from the requester, and privileged control-plane actions additionally require two distinct approvers recorded in the asctl four-eyes approvals ledger. The two mechanisms compose: a request must be decided by the right people and within its window.

See also​