Commit Graph
3 Commits
Author SHA1 Message Date
KrisandClaude Opus 4.8 6082bceee6 fix(cron): close three MED cron-job defects
1. once-rearm on edit: editing any field of a finished one-time job reset
   completedOnce, silently resurrecting it. Now only a SCHEDULE edit
   (scheduleType/runAt/interval/daily/weekly) re-arms a completed once job;
   cosmetic edits (rename/notes) leave completedOnce intact.

2. update-validation gap: CronJobUpdateSchema = .partial() drops the cross-field
   superRefine, so a PUT switching scheduleType without its dependent field
   produced a dead enabled job (nextRunAt:null). updateJob now re-validates the
   MERGED job against the full CronJobSchema and throws 400 on inconsistency,
   leaving the stored job untouched.

3. concurrency-skip silent starvation: skip_if_same_agent_running advanced the
   schedule but wrote no run record, so a perpetually-skipped job had empty
   history. Now records a 'skipped' run (new CronJobRunStatus) + lastStatus.

Tests updated/added in cron-service.test.ts (37 pass): once non-schedule edit
preserves completedOnce, schedule edit re-arms, inconsistent partial update is
rejected with the stored job untouched, and the skip path records a skipped run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PmvZR12aX2v8K7YhqxPUAU
2026-06-29 11:50:42 +05:30
KrisandClaude Opus 4.8 40e26c5422 fix(cron): confine cron prompt-file reads to block sensitive paths
A cron job's promptFilePath is user-supplied via the API and was read with an
unconfined readFile of any absolute path, so a hostile job config could exfil
arbitrary host files (e.g. /etc/passwd, SSH keys) into a Claude session.

Guard the read in resolvePrompt by mirroring the attachment-serving guard
(resolveServableAttachmentPath in file-routes): realpath-resolve the path, then
reject via the shared blocklist (/etc, /root, secret locations) plus the
optional workspace-confinement toggle before reading.

Regression tests in cron-service.test.ts: blocks /etc/passwd (the live repro)
and /root/*, fails cleanly on a missing file, and still allows an ordinary
prompt file outside the blocklist.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PmvZR12aX2v8K7YhqxPUAU
2026-06-29 11:38:51 +05:30
KrisandClaude Opus 4.8 9feaa0d6e5 refactor(cron): rename scheduler feature to cron
Rename the recurring-jobs feature scheduler->cron to disambiguate from the
legacy ScheduledRun system (/api/scheduled), which is left untouched:

- ScheduledJob->CronJob, SchedulerService->CronService
- /api/scheduler/jobs -> /api/cron/jobs; SSE scheduler:* -> cron:*
- state keys cronJobs/cronJobRuns
- files moved to src/cron/, cron-routes.ts, cron-port.ts, types/cron.ts
- frontend cron-ui.js, #cronModal, menu "Cron"
- docs moved to docs/cron-discovery.md + docs/cron-build-brief.md, README guides
- new tests: cron-service.test.ts, cron-time.test.ts

Green: tsc, lint, frontend-syntax, format, 30 cron + 9 legacy scheduled-runs tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PmvZR12aX2v8K7YhqxPUAU
2026-06-29 11:35:56 +05:30