POST /api/v1/weekly-report collects everything published in the last seven
days, groups it by project and posts one message. dry=1 returns the message
instead of sending it, no publications means no message, a missing webhook
answers 501 instead of failing quietly. scripts/cron.mjs runs the due
publishing first, then the digest.