Found while implementing #10537 (out of scope there: that card is the REST route only).
What is true at head
packages/runtime/src/external-validation-plugin.ts — ExternalValidationPlugin.runDriftCheck(ctx, datasource) (:278-293) is armed per datasource by scheduleDriftChecks, one interval per datasource that declares external.validation.checkIntervalMs. Its body calls svc.validateAll() and then filters:
report=awaitsvc.validateAll();constdrifted=report.results.filter((r)=>!r.ok&&r.datasource===datasource);
validateAll() validates every federated object on every federated datasource, and per-object validation drives introspect(datasource) — a live remote-schema read. So a timer armed for datasource A performs live introspection against B and C as well, on every tick, and discards their rows.
This is the same defect class as #10537 (the REST route, fixed in PR #10960), one layer over: correct output, unscoped work. It is arguably worse here because it is periodic and unattended — the cost repeats on every interval of every armed datasource, and two datasources each armed at their own interval each sweep the whole farm.
Why it was not fixed as a rider on #10537
Different package, different consumer, its own verification surface (packages/runtime), and the dispatch for #10537 scoped that card to packages/rest. Filing rather than widening the diff.
A composed primitive now exists
PR #10960 added ExternalDatasourceService.validateDatasource(datasource) — the scoped twin of the sweep, composed from listObjects → filter → validateObject with the same federation predicate and the same per-object catch, returning row-for-row what validateAll() post-filtered to that datasource returned. If this card is taken, that is the primitive to call.
One wrinkle for whoever picks it up: this consumer types the service structurally as ExternalDatasourceServiceLike (:14) and probes svc?.validateAll before calling; validateDatasource is deliberately not on IExternalDatasourceService (#10537's triage ruled a contract expansion out of scope), so the same probe-or-degrade decision the REST registrar made has to be made here too — and the honest degradation for a background checker may not be the route's 503 answer.
Unassigned — filed for triage to level and route.
Generated by Claude Code
Found while implementing #10537 (out of scope there: that card is the REST route only).
What is true at head
packages/runtime/src/external-validation-plugin.ts—ExternalValidationPlugin.runDriftCheck(ctx, datasource)(:278-293) is armed per datasource byscheduleDriftChecks, one interval per datasource that declaresexternal.validation.checkIntervalMs. Its body callssvc.validateAll()and then filters:validateAll()validates every federated object on every federated datasource, and per-object validation drivesintrospect(datasource)— a live remote-schema read. So a timer armed for datasource A performs live introspection against B and C as well, on every tick, and discards their rows.This is the same defect class as #10537 (the REST route, fixed in PR #10960), one layer over: correct output, unscoped work. It is arguably worse here because it is periodic and unattended — the cost repeats on every interval of every armed datasource, and two datasources each armed at their own interval each sweep the whole farm.
Why it was not fixed as a rider on #10537
Different package, different consumer, its own verification surface (
packages/runtime), and the dispatch for #10537 scoped that card topackages/rest. Filing rather than widening the diff.A composed primitive now exists
PR #10960 added
ExternalDatasourceService.validateDatasource(datasource)— the scoped twin of the sweep, composed fromlistObjects→ filter →validateObjectwith the same federation predicate and the same per-object catch, returning row-for-row whatvalidateAll()post-filtered to that datasource returned. If this card is taken, that is the primitive to call.One wrinkle for whoever picks it up: this consumer types the service structurally as
ExternalDatasourceServiceLike(:14) and probessvc?.validateAllbefore calling;validateDatasourceis deliberately not onIExternalDatasourceService(#10537's triage ruled a contract expansion out of scope), so the same probe-or-degrade decision the REST registrar made has to be made here too — and the honest degradation for a background checker may not be the route's503answer.Unassigned — filed for triage to level and route.
Generated by Claude Code