Rule
Scheduled publish must run server-side and fire reliably without human intervention.
Why
Client-triggered publish depends on someone having the CMS open at the right time, which is unreliable.
Must
- Store the scheduled_at timestamp as UTC on the content item.
- Run a background job on an interval to publish all items where scheduled_at <= now.
- Idempotently process the publish job to avoid double publishing.
- Send a notification to the author when the item goes live.
Should
- Allow cancellation of a scheduled publish before it fires.
- Show the editor what content is scheduled and when in a calendar view.
Anti-patterns
- Triggering schedule publish only when an editor navigates to the content list.
- No idempotency guard on the publish job.
Test Cases
- Item with scheduled_at in the past is published on next job run.
- Running the job twice does not create duplicate publishes.
Telemetry
- scheduled_publish_fired
- scheduled_publish_skipped_already_published
- schedule_cancelled_before_fire