Files
LibreMail-Bug-Report-Ingest/wrangler.jsonc
T
JMR-devandClaude Opus 4.8 e650e5f161 #13 Cloudflare Cron Trigger: Friday 17:00 America/Chicago, DST-correct
Add a weekly Cron Trigger that fires at 17:00 America/Chicago (Central) every
Friday year-round, correct across the CST/CDT DST transition, and on fire lists
the pending reports (#10 Manager.ListPending) and hands their ids to the publish
step.

Cloudflare crons are UTC-only, and 17:00 Central is 22:00 UTC under CDT (summer)
and 23:00 UTC under CST (winter), so no single UTC cron expresses it. Register
BOTH Friday UTC hours in wrangler.jsonc (`0 22 * * 5` and `0 23 * * 5`) and gate
each fire: only the fire that is actually 17:00 Central does the work, so
publishing runs exactly once per Friday.

TinyGo/Wasm may lack the IANA tz database, so the gate does not call
time.LoadLocation. Instead internal/schedule computes the US Central DST rule
from first principles (CDT from the 2nd Sunday of March 02:00 to the 1st Sunday
of November 02:00, else CST) behind a pure func IsFriday1700Central(time.Time),
host-testable without TinyGo and cross-checked against the real America/Chicago
zone (via a test-only time/tzdata import) over a 20-year sweep.

- internal/schedule: pure DST gate + Run orchestrator; Publisher/PendingLister
  seams; LogPublisher no-op default (the seam #14 replaces).
- worker/scheduled_wasm.go: js/wasm-only adapter registering the scheduled task
  via init()+cron.ScheduleTaskNonBlock, wiring the R2-backed lifecycle Manager to
  schedule.Run. worker/main.go is untouched.
- wrangler.jsonc: add triggers.crons (only the triggers section changed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:52:39 -05:00

63 lines
2.8 KiB
JSON

{
// Cloudflare Worker config for local dev and deploy.
// Docs: https://developers.cloudflare.com/workers/wrangler/configuration/
"name": "libremail-bug-report-ingest",
// Entry module. The TinyGo build (see package.json "build") produces the Wasm
// binary at ./build/app.wasm and workers-assets-gen produces this shim, which
// instantiates the Wasm module. The ./build/ artifacts are git-ignored and are
// created by `pnpm run build` (which requires TinyGo).
"main": "./build/worker.mjs",
"compatibility_date": "2025-06-01",
// Wrangler runs this before dev/deploy to (re)build the Wasm + shim.
// Requires TinyGo locally; TinyGo is installed in CI.
"build": {
"command": "pnpm run build"
},
// R2 bucket for the encrypted-at-rest bug-report objects (ADR #5 / issue #9).
// The Worker encrypts each scrubbed report with AES-256-GCM before writing, so
// only ciphertext is ever stored here. "binding" is the JS var the Worker code
// reads (internal/storage.BucketBinding); "bucket_name" matches the bucket
// provisioned by infra/ (defaultR2BucketName = "libremail-bug-reports").
"r2_buckets": [
{
"binding": "REPORTS_BUCKET",
"bucket_name": "libremail-bug-reports"
}
],
// Cloudflare Secrets Store secret holding the versioned encryption keyring
// (ADR #5, Key custody): a single JSON secret {active, keys{ver: base64-32B}}.
// "binding" is read at runtime via env.BUGREPORT_ENC_KEYRING.get()
// (internal/storage.KeyringBinding). Replace "<store-id>" with the account's
// Secrets Store id at deploy time; it is not needed for `pnpm run build`
// (Wasm compile) or the devserver, so CI does not require it.
"secrets_store_secrets": [
{
"binding": "BUGREPORT_ENC_KEYRING",
"store_id": "<store-id>",
"secret_name": "bugreport-enc-keyring"
}
],
// Cron Triggers for the weekly publish job (#13): "Friday 17:00 America/Chicago
// (Central), DST-correct". Cloudflare evaluates crons in UTC only and has no
// timezone support, and 17:00 Central is a different UTC hour depending on DST:
// 22:00 UTC during Central Daylight Time (CDT, UTC-5, summer) and 23:00 UTC
// during Central Standard Time (CST, UTC-6, winter). A single UTC cron therefore
// cannot express it, so we register BOTH candidate Friday UTC hours below. The
// Worker's scheduled handler (worker/scheduled_wasm.go -> internal/schedule)
// gates each fire on the real America/Chicago rule, so exactly one of the two
// does the publish work on any given Friday and the other is a no-op. This makes
// the trigger fire at 17:00 Central year-round with no manual DST maintenance.
"triggers": {
"crons": [
"0 22 * * 5", // Fridays 22:00 UTC == 17:00 Central during CDT (summer)
"0 23 * * 5" // Fridays 23:00 UTC == 17:00 Central during CST (winter)
]
}
}