Skip to content

Validation reports problems by severity, and names the IScopedProvider misuse it used to swallow - #64

Merged
shellicar merged 19 commits into
mainfrom
fix/missing-sp-target
Jul 29, 2026
Merged

Validation reports problems by severity, and names the IScopedProvider misuse it used to swallow#64
shellicar merged 19 commits into
mainfrom
fix/missing-sp-target

Conversation

@shellicar

@shellicar shellicar commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • validate() no longer reports the tokens the engine binds itself (IServiceProvider, IScopedProvider, IResolutionScope) as missing targets.
  • The report separates errors from warnings, each problem carrying its severity, and only errors make a report invalid or block a build. ValidationError carries the same two lists.
  • A captive dependency is an error under CaptivePolicy.Strict and a warning under CaptivePolicy.Disposal.
  • A dependency on IScopedProvider is reported as a scope mismatch, on everything a singleton can reach as well as on the singleton itself: an error where no boundary can ever serve it, a warning where only the root cannot.
  • Asking the root for IScopedProvider now throws ScopeMismatchError rather than silently handing over the root provider, and the root's resolve no longer accepts the token at all.
  • A singleton resolves at the root whichever boundary asked for it, and in a resolution pass of its own, so neither the caller nor prebaking can change what it holds.
  • validate() warns when a singleton holds a scoped or resolve dependency, which is shared more narrowly than the singleton itself.
  • resolveAll answers a surface token with the one surface its reach allows, instead of an empty list.

Background

A surface token now declares how far it reaches: root is always the root surface, nearest is the boundary being resolved from with the root counting as one, and scope is the boundary being resolved from with the root excluded. One kind previously meant both of the last two, which is why the root answered for IScopedProvider at all.

The two reports on a singleton's dependencies answer different questions and are deliberately independent. SharingMismatch asks which instance you get, and is reported whatever CaptivePolicy says. CaptiveDependency asks whether it is disposed underneath you, and stays governed by the policy. A scoped dependency in a singleton is both.

resolveAll keeps its own contract rather than borrowing the single door's. It answers "how many are there", so an empty list where a reach allows nothing is the same answer it already gives for a token with no registrations, and only resolve refuses.

The engine spec composes all three reaches against tokens nothing else uses, so each is proven through both doors under both resolution strategies.

@shellicar
shellicar marked this pull request as ready for review July 27, 2026 15:57
@shellicar shellicar changed the title validate() no longer flags engine-bound surface tokens as missing targets Validation reports problems by severity, and names the IScopedProvider misuse it used to swallow Jul 29, 2026
@shellicar
shellicar merged commit a0dd6cd into main Jul 29, 2026
16 checks passed
@shellicar
shellicar deleted the fix/missing-sp-target branch July 29, 2026 16:16
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.

1 participant