Spread scheduled scan policies without time_window on SaaS

What does this MR do and why?

Scheduled scan execution policy rules authored directly in YAML without a time_window start with no delay, while the policy editor already sets a time window on new schedules by default. This applies a default delay (1 hour, randomly distributed, capped to the next cron run) to rules that omit one, behind a SaaS-only feature and a gitlab_com_derisk feature flag.

Security::OrchestrationPolicyRuleSchedule#time_window_seconds now falls back to 3600 seconds (1 hour, randomly distributed) when the rule has no time_window. The existing effective_time_window still caps that value to the time left until the next cron run, so short-cadence schedules are never delayed past their own next run. #time_window is unchanged and still returns only the user-configured value, because it feeds an analytics property that means "the user set a time window." Security::ScanExecutionProjectSchedule now delegates time_window_seconds to the rule schedule instead of aliasing it to time_window, so it picks up the same default.

Every scheduling path gets its delay from time_window_seconds via effective_time_window: the legacy enqueue in RuleScheduleService, per-project schedule creation in CreateProjectSchedulesService, the self-healing path, and rescheduling of ScanExecutionProjectSchedule. Changing the one method covers all of them.

The new default is gated by a SaaS-only feature, scheduled_scan_default_time_window (self-managed and Dedicated never get it), and a gitlab_com_derisk feature flag, scan_execution_policy_default_time_window, off by default. The flag actor is the policy configuration source's root namespace, so it can be rolled out one top-level group at a time. No changelog entry, since the flag is off by default.

Reviewable LOC: 39 (plus 40 in tests)

Context for LLM agents

Rejected alternatives:

  • Jitter only inside the existing 15-minute cron run: too short compared with the windows used by rules that set one (the policy editor defaults to 10 hours).
  • Changing #time_window itself instead of overriding #time_window_seconds (previously an alias of it): would change the meaning of the existing analytics property that reads it as "user configured a time window."
  • A Gitlab.com? check instead of a SaaS feature: GitLab's EE principles require a SaaS feature for new SaaS-only behavior, not a hardcoded environment check.
  • Gating on the feature flag alone, with no SaaS feature: self-managed instances would inherit the default once the flag is eventually removed.

Invariants to preserve in follow-up work:

  • time_window must keep returning only the user-configured value.
  • The default value must stay capped by effective_time_window (never delay a pipeline past its own next scheduled run).
  • The policy editor already sets a time window on new schedules by default, so this default only affects rules authored directly in YAML that omit time_window.

References

Resolves https://gitlab.com/gitlab-org/gitlab/-/work_items/631141

Screenshots or screen recordings

Not applicable. Backend-only change, no UI.

How to set up and validate locally

  1. Open a Rails console with GITLAB_SIMULATE_SAAS=1.
  2. Enable the flag: Feature.enable(:scan_execution_policy_default_time_window).
  3. Take a Security::OrchestrationPolicyRuleSchedule whose rule has no time_window and call effective_time_window. It returns 3600, or the time until the next cron run if that's shorter.
  4. With the flag disabled, or without GITLAB_SIMULATE_SAAS=1, the same call returns nil.

Covered by specs in ee/spec/models/security/orchestration_policy_rule_schedule_spec.rb: no time window off SaaS (nil), no time window on SaaS with the flag on (3600), no time window with the flag off (nil), and an explicit time_window taking precedence over the default on SaaS.

Owed elsewhere

  • Feature flag rollout issue: TBD.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Alan (Maciej) Paruszewski

Merge request reports

Loading
Loading