feat(wad-d): unblock daily cron via Railway-side HTTP trigger#73
Merged
Conversation
PR #70 staged the GitHub Actions workflow with the schedule commented out because the runner can't reach the bun:sqlite DB inside Railway's container filesystem. This patch ships the Option A path documented there: - POST /admin/jobs/daily-wad-d-aggregate on the server, gated by an ASHLR_ADMIN_TRIGGER_TOKEN bearer secret. 60s wallclock budget. Constant- time bearer compare. Returns 503 (NOT 401) when the token env var is unset so the surface is dark by default. - Mounts the router BEFORE adminRouter so the bearer-gated route isn't swallowed by the user-token admin middleware. - Workflow activates `schedule: 0 2 * * *` and replaces the local-CLI step with a curl-to-Railway call. Validates secrets up-front, asserts ok=true in the response, surfaces wad_d in the workflow summary. - 11 tests covering 401/503/200/500/400 paths + dryRun/date/thresholdDays propagation + redacted error leakage. Full server suite: 538 / 0. Endpoint is intentionally undiscoverable: no link from any user-facing admin dashboard, secret rotated independently from the dashboard auth. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced May 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the Option-A networking blocker called out in #70: ships a bearer-gated
POST /admin/jobs/daily-wad-d-aggregateendpoint so the GitHub Actions runner cancurlthe Railway-deployed server, which reaches the in-container bun:sqlite DB the runner cannot. Activates the daily 02:00 UTCschedule:that #70 left commented out.This completes the Q1 WAD-D plumbing:
daily_active_recordsheartbeat ingestion (PR Phase 1 Q1 — Genome 2.0 MVP + WAD-D instrumentation (client + backend) #67)wad_d_snapshotsschema + aggregator job (PR Phase 1 Q1 — Genome 2.0 MVP + WAD-D instrumentation (client + backend) #67)site/(sibling task release: v1.20.2 — status-line session counter (real fix) + bench methodology #20)What ships
server/src/routes/admin-jobs.ts—POST /admin/jobs/daily-wad-d-aggregate. Bearer auth viaASHLR_ADMIN_TRIGGER_TOKEN. 503 when the token env var is unset (NOT 401 — surface stays dark when not configured). 60s wallclock budget. Constant-time bearer compare viacrypto.timingSafeEqual. Internal error messages NEVER leaked — only{ error: "Aggregator failed", requestId }. Emitscron_start/cron_endstructured logs matching the weekly-digest shape.server/src/index.ts— mountsadminJobsRouterbeforeadminRouterso its bearer-gated routes aren't swallowed by the user-token admin middleware..github/workflows/daily-wad-d-aggregate.yml— schedule activated (0 2 * * *); local-CLI invocation replaced with acurl --fail-with-body --max-time 60call to the new endpoint; secrets validated up-front; assertsok=truein the response; surfaces the WAD-D value in the workflow run summary.server/tests/admin-jobs.test.ts— 11 tests covering 401/503/200/500/400 paths,dryRun/date/thresholdDayspropagation, and the leak-redaction assertion.Security posture
mock.module()deliberately not used in tests (leaks across files in bun:test); a tiny_setWadDAggregatorDI seam swaps the implementation instead.Required secrets
GitHub repo settings — Secrets and variables → Actions:
ASHLR_ADMIN_URL— e.g.https://api.ashlr.aiASHLR_ADMIN_TRIGGER_TOKEN— generate withopenssl rand -hex 32; same value goes in Railway envRailway env (ashlr-server service):
ASHLR_ADMIN_TRIGGER_TOKEN— matches the GitHub Actions secretUntil both are set, the workflow fails fast at the "Validate required secrets" step and the endpoint returns 503.
Test plan
bun test tests/admin-jobs.test.ts— 11 / 0bun test tests/daily-wad-d-aggregate.test.ts(real aggregator, regression check) — 5 / 0python3 yaml.safe_loadbunx tsc --noEmitcleanASHLR_ADMIN_TRIGGER_TOKENinto Railway env + repo secrets, thenworkflow_dispatchonce withdry_run=trueto confirm round-trip before tonight's 02:00 UTC schedule fires.🤖 Generated with Claude Code