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.
Found during review of #1092.
The authoring check bounds some offering collections and not others
In
SchedulingPolicy's offering check incrates/registry-scheduling-core/src/policy.rs,remindersgets the shared bound:The two collections immediately after it do not. Both loops validate each entry and
never bound the list:
check_collection_boundis otherwise applied toservices,offerings,holidaySets,openings,hooks,reminders, andwindows, so these two are theexception rather than the rule.
The request edge does bound them
bounded_referencesincrates/registry-scheduling/src/http.rsrefuses any admissionrequest whose list exceeds
MAXIMUM_COLLECTION_ENTRIES(256), andan_admission_request_is_bounded_before_it_reaches_the_storecovers bothcapabilitiesandprerequisitesatMAXIMUM_COLLECTION_ENTRIES + 1.Both offering requirements are satisfied from the request, not from deployment state:
Result
An offering declaring 257 distinct capabilities or prerequisites passes
schedulingctl check, passes startup validation, and is published. Satisfying itrequires a request listing all 257, which the edge refuses as
request.invalid. Theoffering 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_boundtooffering.requires_capabilitiesandoffering.prerequisitesalongside the existingremindersbound, so the authoringgrammar refuses at authoring time what the request edge will refuse at runtime.