# Cross-Analyzer Identity Safety Contract ## Module Scanner ## Status IMPLEMENTED ## Description Formal contract enforcing PURL vs explicit-key identity rules across all language analyzers, ensuring consistent component identification regardless of analyzer source. ## Implementation Details - **Core Identity Types**: - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/Core/LanguageExplicitKey.cs` - Explicit key identity model for non-PURL components - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/Core/LanguageComponentRecord.cs` - Component record enforcing PURL or explicit-key identity - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/Core/LanguageAnalyzerResult.cs` - Analyzer result with identity-safe component records - **Language Analyzers** (all enforce the identity contract): - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/DotNetLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Java/JavaLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Node/NodeLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python/PythonLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Go/GoLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Rust/RustLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Ruby/RubyLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Php/PhpLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Bun/BunLanguageAnalyzer.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Deno/DenoLanguageAnalyzer.cs` ## E2E Test Plan - [ ] Scan an image with packages from multiple ecosystems (npm, pip, NuGet, Maven) and verify all components have either a valid PURL or explicit-key identity - [ ] Verify no component has both PURL and explicit-key set simultaneously (mutual exclusion) - [ ] Verify components from the same package across different analyzers produce the same identity - [ ] Verify PURL normalization is consistent (lowercase scheme, correct type mapping) - [ ] Scan with a package that has no PURL mapping and verify explicit-key is used as fallback - [ ] Verify the identity contract is enforced in SBOM output (all components have valid identifiers)