Plugin assemblies loaded via PluginHost into isolated AssemblyLoadContexts produce distinct types even from the same DLL. When AppDomain.GetAssemblies() returns both Default and plugin-ALC copies, DI registration and IOptions<T> resolution silently fail (e.g. ValkeyTransportOptions defaulting to localhost). Applied AssemblyLoadContext.Default filter to all 7 assembly discovery sites: - MessagingServiceCollectionExtensions (transport plugin scan) - StellaRouterIntegrationHelper (transport plugin loader) - Gateway.WebService Program.cs (startup transport scan) - GeneratedEndpointDiscoveryProvider (endpoint provider scan) - ReflectionEndpointDiscoveryProvider (endpoint attribute scan) - ServiceCollectionExtensions (schema provider scan) - MigrationModulePluginDiscovery (migration plugin scan) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.2 KiB
Advisory Lens Architecture
Status: Production (Shared Library). AdvisoryLens is a standalone deterministic library at
src/__Libraries/StellaOps.AdvisoryLens/, not merged into AdvisoryAI. The two modules serve different purposes: AdvisoryLens provides pattern-based case matching without AI inference; AdvisoryAI provides LLM-powered advisory analysis with guardrails. They can be composed together but are architecturally independent. The library is currently available for integration but not yet referenced from any WebServiceProgram.cs.
Purpose
StellaOps.AdvisoryLens is a deterministic, offline-first library for semantic case matching of vulnerability advisories. It produces ranked suggestions and contextual hints without AI/LLM inference.
Scope
- Working directory:
src/__Libraries/StellaOps.AdvisoryLens/ - Tests:
src/__Libraries/__Tests/StellaOps.AdvisoryLens.Tests/ - Integration entry point:
services.AddAdvisoryLens(...)
Models
| Type | Purpose |
|---|---|
AdvisoryCase |
Advisory input including CVE, PURL, severity, and metadata |
LensContext |
Evaluation envelope (advisory case, tenant id, evidence refs, optional timestamp) |
CasePattern |
Matching rule with severity/ecosystem/CVE conditions and default suggestion payload |
LensSuggestion |
Ranked operator-facing recommendation with confidence and action |
LensHint |
Contextual evidence hint grouped by deterministic categories |
LensResult |
Evaluation output containing suggestions, hints, matched pattern ids, timestamp, and input hash |
Matching Algorithm
CaseMatcherevaluates eachCasePatternagainst the inputAdvisoryCase- Scoring factors are severity range match, PURL ecosystem match, and CVE pattern match
- Disqualifying mismatches (severity out of range, wrong ecosystem) return score
0.0 - If no factors are configured for a pattern, score defaults to
0.5 - Positive-score matches are sorted by score descending, then
PatternIdascending for deterministic tie-breaking AdvisoryLensServicemaps sorted matches into suggestions with rank = position + 1
Hint Generation
Hints are derived from LensContext and sorted by category ordinal then text:
- Severity:
HighorCriticaladvisories emit a priority remediation hint - Reachability: non-empty reachability evidence emits code-path guidance
- VEX: non-empty VEX references emit a count-based hint
- Policy: non-empty policy traces emit a count-based hint
Integration
services.AddAdvisoryLens(patterns, timeProvider);
- Registers
IAdvisoryLensServiceas a singleton - Uses empty patterns when none are provided
- Uses
TimeProvider.Systemwhen no provider is injected
Determinism Guarantees
- Stable ordering for matches and hints
- Input hash computed as
sha256:+ SHA-256 over canonical JSON (camelCase, no indentation, nulls ignored) - Timestamp comes from
LensContext.EvaluationTimestampUtcor injectedTimeProvider - Identical inputs and clock source produce identical
LensResult
Offline Posture
- No network dependencies in library behavior
- In-process, side-effect-free evaluation and scoring
- Tests validate execution with no HTTP or external service setup