Skip to content

scheduling: offering capability and prerequisite lists are unbounded in the authoring check but bounded at the request edge #1253

Description

@jeremi

Found during review of #1092.

The authoring check bounds some offering collections and not others

In SchedulingPolicy's offering check in crates/registry-scheduling-core/src/policy.rs,
reminders gets the shared bound:

check_collection_bound(&offering.reminders, &format!("{path}.reminders"), findings);

The two collections immediately after it do not. Both loops validate each entry and
never bound the list:

for capability in &offering.requires_capabilities { if !valid_identifier(capability) { ... } }
for prerequisite in &offering.prerequisites { if !valid_reference(prerequisite) { ... } }

check_collection_bound is otherwise applied to services, offerings,
holidaySets, openings, hooks, reminders, and windows, so these two are the
exception rather than the rule.

The request edge does bound them

bounded_references in crates/registry-scheduling/src/http.rs refuses any admission
request whose list exceeds MAXIMUM_COLLECTION_ENTRIES (256), and
an_admission_request_is_bounded_before_it_reaches_the_store covers both
capabilities and prerequisites at MAXIMUM_COLLECTION_ENTRIES + 1.

Both offering requirements are satisfied from the request, not from deployment state:

offering.prerequisites.iter().filter(|wanted| !request.prerequisites.contains(wanted))
offering.requires_capabilities.iter().all(|wanted| request.capabilities.contains(wanted))

Result

An offering declaring 257 distinct capabilities or prerequisites passes
schedulingctl check, passes startup validation, and is published. Satisfying it
requires a request listing all 257, which the edge refuses as request.invalid. The
offering is therefore permanently unbookable while every authoring signal says it is
well formed, and the caller is told their own request is at fault.

Fix

Apply check_collection_bound to offering.requires_capabilities and
offering.prerequisites alongside the existing reminders bound, so the authoring
grammar refuses at authoring time what the request edge will refuse at runtime.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions