Skip to content

feat: surface cron windows in webapp, cli, sdk - #4572

Draft
carderne wants to merge 1 commit into
feat/cron-windowsfrom
feat/cron-windows-surface
Draft

feat: surface cron windows in webapp, cli, sdk#4572
carderne wants to merge 1 commit into
feat/cron-windowsfrom
feat/cron-windows-surface

Conversation

@carderne

Copy link
Copy Markdown
Collaborator

Summary

Adds execution-window product surfaces for both declarative and imperative schedules.

  • Declarative schedules can set window through schedules.task(), with support for whole-minute, hour, day, and percentage values.
  • Imperative schedules can create, update, clear, and inspect windows through the API and dashboard.
  • Schedule API responses preserve nextRun as the nominal CRON time and expose nextRunEffectiveAt as the stable assigned time.
  • The dashboard displays configured windows alongside nominal and assigned upcoming-run times.
  • Deploy output summarizes declarative schedules and suggests adding a wider window when the default 60-second placement range is used.

Design

Window validation remains authoritative on the server and ensures each window is compatible with the schedule cadence. Omitting a window uses the default 60-second range, while explicit zero-duration windows remain supported.

Deployment summaries are derived from the deployment's stored task metadata, so they reflect the declarations associated with that deployment.

@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eb8c3af

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 27 packages
Name Type
@trigger.dev/core Patch
@trigger.dev/sdk Patch
trigger.dev Patch
@trigger.dev/build Patch
@trigger.dev/python Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@internal/cache Patch
@internal/clickhouse Patch
@internal/llm-model-catalog Patch
@internal/metrics-pipeline Patch
@trigger.dev/rbac Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/run-store Patch
@internal/schedule-engine Patch
@trigger.dev/sso Patch
@internal/testcontainers Patch
@internal/tracing Patch
@internal/tsql Patch
@internal/dashboard-agent Patch
@internal/sdk-compat-tests Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ac8e567-3f4c-4fcf-b2aa-62378a3b3b3d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The change adds configurable duration and percentage windows to scheduled tasks. The schedule engine calculates deterministic effective execution times while preserving nominal CRON timestamps. Database models store window configuration and schedule phases. APIs, deployment output, dashboard views, and forms expose the window and both timestamps. Queue and ClickHouse records now preserve effective queue timestamps. Tests cover timing, persistence, validation, API lifecycle, deployment output, and queue behavior.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description explains the feature and design, but it omits the required issue reference, checklist, testing, changelog, and screenshots sections. Add the required template sections, including the issue reference, completed checklist, testing steps, changelog entry, and screenshots or an explicit reason they are not applicable.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: exposing cron execution windows across the webapp, CLI, and SDK.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cron-windows-surface

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

}

const input = JSON.stringify(["cron-phase-v1", environmentId, deduplicationKey]);
const digest = createHmac("sha256", secret).update(input).digest();

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
.server-changes/schedule-windows.md (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Describe the user-visible capability.

Replace “server support” with what users can configure and see. This file is published as dashboard-facing release notes.

Proposed text
- Add server support for stable execution windows on scheduled tasks while preserving each occurrence's nominal timestamp.
+ Configure stable execution windows for scheduled tasks while preserving each occurrence's nominal CRON time.

Based on learnings, .server-changes entries are published verbatim as dashboard-facing release notes and must state user-visible behavior.

Source: Learnings


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 85def57d-c643-48eb-9cca-1e2488cf029d

📥 Commits

Reviewing files that changed from the base of the PR and between 4569657 and 2ba481a.

📒 Files selected for processing (53)
  • .changeset/smooth-schedule-windows.md
  • .server-changes/schedule-windows.md
  • apps/webapp/app/components/schedules/ScheduleInspector.tsx
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/presenters/v3/EditSchedulePresenter.server.ts
  • apps/webapp/app/presenters/v3/ScheduleListPresenter.server.ts
  • apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.tasks.scheduled.$taskParam/route.tsx
  • apps/webapp/app/routes/api.v1.deployments.$deploymentId.ts
  • apps/webapp/app/routes/api.v1.schedules.$scheduleId.activate.ts
  • apps/webapp/app/routes/api.v1.schedules.$scheduleId.deactivate.ts
  • apps/webapp/app/routes/api.v1.schedules.$scheduleId.ts
  • apps/webapp/app/routes/api.v1.schedules.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.new/route.tsx
  • apps/webapp/app/services/runsReplicationService.server.ts
  • apps/webapp/app/v3/scheduleEngine.server.ts
  • apps/webapp/app/v3/scheduleWindow.server.ts
  • apps/webapp/app/v3/schedules.ts
  • apps/webapp/app/v3/services/checkSchedule.server.ts
  • apps/webapp/app/v3/services/createBackgroundWorker.server.ts
  • apps/webapp/app/v3/services/upsertTaskSchedule.server.ts
  • apps/webapp/test/engine/triggerTask.test.ts
  • apps/webapp/test/runsReplicationService.part1.test.ts
  • apps/webapp/test/scheduleWindow.test.ts
  • apps/webapp/test/schedules-api.e2e.full.test.ts
  • internal-packages/clickhouse/schema/037_add_queue_timestamp_to_task_runs_v2.sql
  • internal-packages/clickhouse/src/taskRuns.test.ts
  • internal-packages/clickhouse/src/taskRuns.ts
  • internal-packages/database/prisma/migrations/20260810130446_add_cron_spread_fields/migration.sql
  • internal-packages/database/prisma/schema.prisma
  • internal-packages/run-engine/src/engine/systems/dequeueSystem.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/run-engine/src/run-queue/tests/enqueueMessage.test.ts
  • internal-packages/schedule-engine/src/engine/distributedScheduling.ts
  • internal-packages/schedule-engine/src/engine/index.ts
  • internal-packages/schedule-engine/src/engine/scheduleCalculation.test.ts
  • internal-packages/schedule-engine/src/engine/scheduleCalculation.ts
  • internal-packages/schedule-engine/src/engine/scheduleTiming.test.ts
  • internal-packages/schedule-engine/src/engine/scheduleTiming.ts
  • internal-packages/schedule-engine/src/engine/types.ts
  • internal-packages/schedule-engine/src/engine/workerCatalog.test.ts
  • internal-packages/schedule-engine/src/engine/workerCatalog.ts
  • internal-packages/schedule-engine/src/index.ts
  • internal-packages/schedule-engine/test/scheduleEngine.test.ts
  • internal-packages/schedule-engine/test/scheduleEngine2.test.ts
  • internal-packages/schedule-engine/test/scheduleRecovery.test.ts
  • packages/cli-v3/src/commands/deploy.ts
  • packages/cli-v3/src/deploy/schedules.test.ts
  • packages/cli-v3/src/deploy/schedules.ts
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/schemas/schemas.ts
  • packages/trigger-sdk/src/v3/schedules/index.test.ts
  • packages/trigger-sdk/src/v3/schedules/index.ts

"trigger.dev": patch
---

Define stable execution windows on declarative scheduled tasks. Schedule API responses now expose both the nominal CRON time and its assigned time, while deploy output and the dashboard show configured windows and upcoming assignments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document imperative schedule windows.

Line 7 limits execution windows to declarative schedules. This PR also adds imperative schedule window support through the API. Include both paths in the package release note.

Proposed text
- Define stable execution windows on declarative scheduled tasks.
+ Define stable execution windows on declarative scheduled tasks and imperative schedules.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Define stable execution windows on declarative scheduled tasks. Schedule API responses now expose both the nominal CRON time and its assigned time, while deploy output and the dashboard show configured windows and upcoming assignments.
Define stable execution windows on declarative scheduled tasks and imperative schedules. Schedule API responses now expose both the nominal CRON time and its assigned time, while deploy output and the dashboard show configured windows and upcoming assignments.

Comment on lines +71 to +89
const windowFields = normalizeScheduleWindow(task.schedule.window);
const [nextRun] = calculateNextScheduleRunTimes({
cron: task.schedule.cron,
timezone: task.schedule.timezone,
deduplicationKey: task.id,
environmentId: authenticatedEnv.id,
schedulePhase: null,
phaseSecret: env.ENCRYPTION_KEY,
...windowFields,
});

return [
{
task: task.id,
cron: task.schedule.cron,
timezone: task.schedule.timezone,
window: task.schedule.window,
nextRun: nextRun.nominalAt,
nextRunEffectiveAt: nextRun.effectiveAt,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline apps/webapp/app/v3/scheduleWindow.server.ts --items all
ast-grep outline apps/webapp/app/v3/services/createBackgroundWorker.server.ts --items all
ast-grep outline apps/webapp/app/routes/api.v1.deployments.\$deploymentId.ts --items all

rg -n -C 5 \
  'deduplicationKey|schedulePhase|calculateNextScheduleRunTimes|registerNextTaskScheduleInstance' \
  apps/webapp/app/v3/scheduleWindow.server.ts \
  apps/webapp/app/v3/services/createBackgroundWorker.server.ts \
  apps/webapp/app/routes/api.v1.deployments.\$deploymentId.ts \
  internal-packages/database/prisma/schema.prisma

Repository: triggerdotdev/trigger.dev

Length of output: 16698


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- route ---'
cat -n 'apps/webapp/app/routes/api.v1.deployments.$deploymentId.ts' | sed -n '1,125p'

printf '%s\n' '--- declarative schedule sync ---'
cat -n apps/webapp/app/v3/services/createBackgroundWorker.server.ts | sed -n '643,780p'

printf '%s\n' '--- schedule models and creation/update paths ---'
rg -n -C 8 \
  'model TaskSchedule|model TaskScheduleInstance|schedulePhase|deduplicationKey|TaskScheduleInstance' \
  internal-packages/database/prisma/schema.prisma \
  apps/webapp/app/v3 apps/webapp/app/services apps/webapp/app/models \
  -g '*.ts' -g '*.tsx' -g '*.prisma'

printf '%s\n' '--- registration implementation ---'
rg -n -C 12 \
  'registerNextTaskScheduleInstance|nextRunEffectiveAt|effectiveAt|nominalAt' \
  apps/webapp/app/v3 -g '*.ts'

Repository: triggerdotdev/trigger.dev

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- schedule engine registration ---'
rg -n -C 18 \
  'registerNextTaskScheduleInstance|schedulePhase|deduplicationKey|calculateNextScheduleRunTimes|calculateEffectiveScheduleTime' \
  apps/webapp/app/v3/scheduleEngine.server.ts \
  apps/webapp/app/v3 -g '*.ts' \
  | sed -n '1,260p'

printf '%s\n' '--- schedule-phase helpers and tests ---'
rg -n -C 12 \
  'function calculateSchedulePhase|calculateSchedulePhase|calculateEffectiveScheduleTime|effectiveAt' \
  apps packages internal-packages -g '*.ts' -g '*.tsx' -g '*.test.*' -g '*.spec.*' \
  | sed -n '1,300p'

printf '%s\n' '--- exact declarative schedule lookup and route callers ---'
rg -n -C 10 \
  'taskIdentifier.*task\.id|taskIdentifier.*taskIdentifier|environmentId.*authenticatedEnv|taskSchedule\.find|taskScheduleInstance\.find' \
  apps/webapp/app -g '*.ts' -g '*.tsx' \
  | sed -n '1,260p'

Repository: triggerdotdev/trigger.dev

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- phase algorithm ---'
cat -n internal-packages/schedule-engine/src/engine/scheduleTiming.ts | sed -n '168,225p'

printf '%s\n' '--- registration definitions ---'
rg -l 'registerNextTaskScheduleInstance' . -g '*.ts' -g '*.tsx' | while read -r file; do
  printf '%s\n' "--- $file"
  rg -n -C 20 'registerNextTaskScheduleInstance' "$file" | sed -n '1,100p'
done

printf '%s\n' '--- declarative schedule tests ---'
rg -n -C 10 \
  'syncDeclarativeSchedules|DECLARATIVE|nextRunEffectiveAt|schedulePhase' \
  apps/webapp -g '*.test.*' -g '*.spec.*' -g '*.ts' \
  | sed -n '1,260p'

printf '%s\n' '--- static invariant check ---'
python3 - <<'PY'
from pathlib import Path
route = Path("apps/webapp/app/routes/api.v1.deployments.$deploymentId.ts").read_text()
sync = Path("apps/webapp/app/v3/services/createBackgroundWorker.server.ts").read_text()
upsert = Path("apps/webapp/app/v3/services/upsertTaskSchedule.server.ts").read_text()

checks = {
    "route uses task.id as deduplicationKey": "deduplicationKey: task.id" in route,
    "route passes null schedulePhase": "schedulePhase: null" in route,
    "declarative create omits deduplicationKey": "const newSchedule = await prisma.taskSchedule.create" in sync
        and "deduplicationKey" not in sync[sync.index("const newSchedule = await prisma.taskSchedule.create"):
            sync.index("const newSchedule = await prisma.taskSchedule.create") + 1800],
    "declarative instance is registered": "registerNextTaskScheduleInstance({ instanceId: instance.id })" in sync,
    "canonical API calculation uses persisted values": "deduplicationKey: taskSchedule.deduplicationKey" in upsert
        and "schedulePhase: instance.schedulePhase" in upsert,
}
for name, result in checks.items():
    print(f"{name}: {'PASS' if result else 'FAIL'}")
PY

Repository: triggerdotdev/trigger.dev

Length of output: 46376


Use the persisted schedule identity for nextRunEffectiveAt.

The declarative schedule uses a generated deduplicationKey, not task.id. Query the matching TaskSchedule and TaskScheduleInstance for authenticatedEnv.id, then pass their deduplicationKey and schedulePhase values to calculateNextScheduleRunTimes. Add coverage against the registered schedule instance.

Comment on lines +369 to +372
<Hint>
Assigns each run a stable time after its CRON time. Use minutes, hours, days, or a
percentage of the interval. Schedules always use at least a 60-second placement
range.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the default-window guidance.

The hint says every schedule uses a 60-second placement range. Explicit 0m and 0% windows are supported and assign the effective time at the nominal CRON time. State that 60 seconds is the default only when the window is omitted.

Proposed text
- percentage of the interval. Schedules always use at least a 60-second placement
- range.
+ percentage of the interval. If omitted, the window defaults to a 60-second placement
+ range. Use `0m` or `0%` to assign the CRON time.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Hint>
Assigns each run a stable time after its CRON time. Use minutes, hours, days, or a
percentage of the interval. Schedules always use at least a 60-second placement
range.
<Hint>
Assigns each run a stable time after its CRON time. Use minutes, hours, days, or a
percentage of the interval. If omitted, the window defaults to a 60-second placement
range. Use `0m` or `0%` to assign the CRON time.

Comment on lines +228 to +240
const {
effectiveAt: candidateEffectiveAt,
effectiveRangeMs,
windowMs,
offsetMs: candidateDelayMs,
rangeWasClamped,
} = calculateEffectiveScheduleTime({
nominalAt,
nextNominalAt,
schedulePhase,
window: scheduleWindow,
});
const effectiveAt = this.options.cronSpreadEnabled ? candidateEffectiveAt : nominalAt;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard the effective-time calculation so a disabled feature flag cannot break registration.

calculateEffectiveScheduleTime runs before the cronSpreadEnabled check. The function throws a RangeError when intervalMs is not a positive integer or when a date is invalid. If cronSpreadEnabled is false, registration must behave as it did before this change, but it now fails for any generator expression whose next two nominal timestamps are not strictly increasing.

Skip the calculation when the flag is off, or wrap it so a failure falls back to nominalAt.

🛡️ Proposed fallback that keeps the flag-off path on the previous behavior
-        const {
-          effectiveAt: candidateEffectiveAt,
-          effectiveRangeMs,
-          windowMs,
-          offsetMs: candidateDelayMs,
-          rangeWasClamped,
-        } = calculateEffectiveScheduleTime({
-          nominalAt,
-          nextNominalAt,
-          schedulePhase,
-          window: scheduleWindow,
-        });
-        const effectiveAt = this.options.cronSpreadEnabled ? candidateEffectiveAt : nominalAt;
+        const [timingError, timing] = await tryCatch(
+          Promise.resolve().then(() =>
+            calculateEffectiveScheduleTime({
+              nominalAt,
+              nextNominalAt,
+              schedulePhase,
+              window: scheduleWindow,
+            })
+          )
+        );
+
+        if (timingError) {
+          this.logger.error("Failed to calculate the effective schedule time", {
+            instanceId: params.instanceId,
+            error: timingError instanceof Error ? timingError.message : String(timingError),
+          });
+          span.setAttribute("effective_schedule_time_error", true);
+        }
+
+        const candidateEffectiveAt = timing?.effectiveAt ?? nominalAt;
+        const effectiveRangeMs = timing?.effectiveRangeMs ?? 0;
+        const windowMs = timing?.windowMs ?? 0;
+        const candidateDelayMs = timing?.offsetMs ?? 0;
+        const rangeWasClamped = timing?.rangeWasClamped ?? false;
+        const effectiveAt =
+          this.options.cronSpreadEnabled && timing ? candidateEffectiveAt : nominalAt;

Comment on lines +182 to +190
export const ScheduleWindow = z.string().min(1);

export type ScheduleWindow = `${bigint}${"m" | "h" | "d" | "%"}`;

export const ScheduleMetadata = z.object({
cron: z.string(),
timezone: z.string(),
environments: z.array(EnvironmentType).optional(),
window: ScheduleWindow.optional(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the schema definition and all public contracts inferred from it.
rg -n -C 3 \
  'export const ScheduleWindow|export type ScheduleWindow|ScheduleWindow\.optional|z\.infer<typeof (CreateScheduleOptions|ScheduleObject)' \
  packages/core/src/v3/schemas/schemas.ts \
  packages/core/src/v3/schemas/api.ts

Repository: triggerdotdev/trigger.dev

Length of output: 3438


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- schema definitions and documentation ---'
sed -n '165,198p' packages/core/src/v3/schemas/schemas.ts
printf '%s\n' '--- API schedule schemas ---'
sed -n '805,838p;1045,1110p' packages/core/src/v3/schemas/api.ts
printf '%s\n' '--- Zod dependency declarations ---'
rg -n '"zod"|zod@' package.json packages/*/package.json pnpm-lock.yaml yarn.lock package-lock.json 2>/dev/null || true
printf '%s\n' '--- ScheduleWindow references ---'
rg -n 'ScheduleWindow|window:\s*ScheduleWindow' packages/core/src packages/core 2>/dev/null | head -80

printf '%s\n' '--- deterministic contract probe ---'
python3 - <<'PY'
from pathlib import Path
import re

schema = Path("packages/core/src/v3/schemas/schemas.ts").read_text()
api = Path("packages/core/src/v3/schemas/api.ts").read_text()

assert re.search(r'export const ScheduleWindow\s*=\s*z\.string\(\)\.min\(1\)', schema)
assert re.search(r'export type ScheduleWindow\s*=\s*`\$\{bigint\}\$\{"m" \| "h" \| "d" \| "%"\}`', schema)

for name in ("ScheduleMetadata",):
    assert re.search(rf'export const {name}\s*=\s*z\.object\([\s\S]*?window:\s*ScheduleWindow\.optional\(\)', schema)

for name in ("CreateScheduleOptions", "ScheduleObject"):
    assert re.search(rf'window:\s*ScheduleWindow\.optional\(\)', api)
    assert re.search(rf'export type {name}\s*=\s*z\.infer<typeof {name}>', api)

print("ScheduleWindow runtime schema: non-empty string")
print("ScheduleWindow declared TypeScript type: `${bigint}${'m'|'h'|'d'|'%'}`")
print("ScheduleMetadata, CreateScheduleOptions, and ScheduleObject infer window from the Zod schema")
print('The runtime schema accepts "30s": non-empty string')
print("The declared ScheduleWindow type excludes the suffix 's'")
PY

Repository: triggerdotdev/trigger.dev

Length of output: 11616


Preserve ScheduleWindow in inferred public types.

z.string().min(1) infers string, so callers can pass unsupported values such as "30s" to ScheduleMetadata, CreateScheduleOptions, and ScheduleObject. Type the schema output as ScheduleWindow while retaining the non-empty-string runtime validation.

@carderne
carderne changed the base branch from main to feat/cron-windows August 11, 2026 19:34
@carderne
carderne force-pushed the feat/cron-windows-surface branch from 2ba481a to eb8c3af Compare August 11, 2026 19:40
@github-actions

Copy link
Copy Markdown
Contributor

Observability map

As of eb8c3af.

19/100 over 417 measured of 433 entry points (base 18, up 1)

What this PR changed

route base head now failing
/api/v1/dashboard-agent/eval-policy (suppressed: request-context) new 0
/api/v1/projects/:projectRef/init new 0 error-classification, request-context
/_app/orgs/new 0 50

FIX FIRST

  • /api/v1/projects/:projectRef/envvars (sensitive) - auth-boundary, request-context
  • /auth/sso (sensitive) - auth-boundary, request-context
  • /_app/orgs/:organizationSlug/settings/team (sensitive) - error-classification, auth-scope, request-context

AUDIT 3 of 50 sensitive mutations record an actor. 47 without one.
CONTEXT 14 of 417 entry points name a tenant on a failure path. 325 appear only here, 39 of them sensitive, in the JSON rather than the fix list.

What the score is made of
CHECKS
  error-classification  171 applicable,  96 pass,   0 sole, global without it 10
  auth-boundary          62 applicable,  57 pass,   0 sole, global without it 15
  auth-scope             19 applicable,  17 pass,   0 sole, global without it 18
  request-context       417 applicable,  14 pass, 224 sole, global without it 64
  audit-trail            50 applicable,   3 pass,   0 sole, not in the score

The score and findings here are report-only and never gate the merge. Separately, a required test suite keeps this tool's symbol and route lists in sync with the code they name, and can fail a pull request that renames or removes a symbol they reference, or that adds the first route with a segment they anticipate. Each failure names the list to edit. The rules and their reasons: internal-packages/observability-map/README.md.

@pkg-pr-new

pkg-pr-new Bot commented Aug 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@trigger.dev/build

npm i https://pkg.pr.new/@trigger.dev/build@eb8c3af

trigger.dev

npm i https://pkg.pr.new/trigger.dev@eb8c3af

@trigger.dev/core

npm i https://pkg.pr.new/@trigger.dev/core@eb8c3af

@trigger.dev/python

npm i https://pkg.pr.new/@trigger.dev/python@eb8c3af

@trigger.dev/react-hooks

npm i https://pkg.pr.new/@trigger.dev/react-hooks@eb8c3af

@trigger.dev/redis-worker

npm i https://pkg.pr.new/@trigger.dev/redis-worker@eb8c3af

@trigger.dev/rsc

npm i https://pkg.pr.new/@trigger.dev/rsc@eb8c3af

@trigger.dev/schema-to-json

npm i https://pkg.pr.new/@trigger.dev/schema-to-json@eb8c3af

@trigger.dev/sdk

npm i https://pkg.pr.new/@trigger.dev/sdk@eb8c3af

commit: eb8c3af

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants