diff --git a/workspace-server/internal/router/router.go b/workspace-server/internal/router/router.go index 7ce0c1834..4a63d100f 100644 --- a/workspace-server/internal/router/router.go +++ b/workspace-server/internal/router/router.go @@ -311,6 +311,24 @@ func Setup(hub *ws.Hub, broadcaster *events.Broadcaster, prov *provisioner.Provi wsAuth.PATCH("/agent", ah.Replace) wsAuth.DELETE("/agent", ah.Remove) wsAuth.POST("/agent/move", ah.Move) + + // Schedules (#1692). The handler + Temporal cron worker are + // implemented in workspace-server/internal/handlers/schedules.go + + // platform/internal/scheduler, but the HTTP routes were never + // mounted — every call returned 404 (Canvas "Schedule" tab + agent + // MCP set_schedule both silently failed). Mounting here puts the + // endpoints under WorkspaceAuth so the per-workspace bearer token + // scopes ownership, matching the IDOR-fix shape in handlers/schedules.go + // (Update/Delete/RunNow/History rebind to workspaceID before + // touching the row). + sch := handlers.NewScheduleHandler() + wsAuth.GET("/schedules", sch.List) + wsAuth.POST("/schedules", sch.Create) + wsAuth.PUT("/schedules/:scheduleId", sch.Update) + wsAuth.DELETE("/schedules/:scheduleId", sch.Delete) + wsAuth.POST("/schedules/:scheduleId/run", sch.RunNow) + wsAuth.GET("/schedules/:scheduleId/history", sch.History) + wsAuth.GET("/schedules/health", sch.Health) } // Registry