{"$schema":"https://json.schemastore.org/sarif-2.1.0.json","version":"2.1.0","runs":[{"tool":{"driver":{"name":"codehealth","informationUri":"https://codehealth.canine.dev","rules":[{"id":"D1","name":"Cyclomatic Complexity","shortDescription":{"text":"Cyclomatic Complexity"},"helpUri":"https://codehealth.canine.dev/dimensions/D1"},{"id":"D2","name":"Cognitive Complexity","shortDescription":{"text":"Cognitive Complexity"},"helpUri":"https://codehealth.canine.dev/dimensions/D2"},{"id":"D3","name":"God Classes","shortDescription":{"text":"God Classes"},"helpUri":"https://codehealth.canine.dev/dimensions/D3"},{"id":"D4","name":"Code Duplication","shortDescription":{"text":"Code Duplication"},"helpUri":"https://codehealth.canine.dev/dimensions/D4"},{"id":"D5","name":"Coupling","shortDescription":{"text":"Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D5"},{"id":"D6","name":"Cohesion (LCOM4)","shortDescription":{"text":"Cohesion (LCOM4)"},"helpUri":"https://codehealth.canine.dev/dimensions/D6"},{"id":"D8","name":"Code Coverage","shortDescription":{"text":"Code Coverage"},"helpUri":"https://codehealth.canine.dev/dimensions/D8"},{"id":"D9","name":"Test Distribution","shortDescription":{"text":"Test Distribution"},"helpUri":"https://codehealth.canine.dev/dimensions/D9"},{"id":"D10","name":"Test Quality","shortDescription":{"text":"Test Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D10"},{"id":"D11","name":"Test Reliability","shortDescription":{"text":"Test Reliability"},"helpUri":"https://codehealth.canine.dev/dimensions/D11"},{"id":"D12","name":"Dependency Hygiene","shortDescription":{"text":"Dependency Hygiene"},"helpUri":"https://codehealth.canine.dev/dimensions/D12"},{"id":"D13","name":"Secret Scanning","shortDescription":{"text":"Secret Scanning"},"helpUri":"https://codehealth.canine.dev/dimensions/D13","relationships":[{"target":{"id":"CWE-798","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}]},{"id":"D14","name":"License Compliance","shortDescription":{"text":"License Compliance"},"helpUri":"https://codehealth.canine.dev/dimensions/D14"},{"id":"D15","name":"Churn \u00D7 Complexity Hotspots","shortDescription":{"text":"Churn \u00D7 Complexity Hotspots"},"helpUri":"https://codehealth.canine.dev/dimensions/D15"},{"id":"D17","name":"Explicit Debt","shortDescription":{"text":"Explicit Debt"},"helpUri":"https://codehealth.canine.dev/dimensions/D17"},{"id":"D18","name":"Solution Shape","shortDescription":{"text":"Solution Shape"},"helpUri":"https://codehealth.canine.dev/dimensions/D18"},{"id":"D19","name":"Documentation Quality","shortDescription":{"text":"Documentation Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D19"},{"id":"D20","name":"ADR Quality","shortDescription":{"text":"ADR Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D20"},{"id":"D21","name":"Naming Consistency","shortDescription":{"text":"Naming Consistency"},"helpUri":"https://codehealth.canine.dev/dimensions/D21"},{"id":"D23","name":"Boundary Type-Coupling","shortDescription":{"text":"Boundary Type-Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D23"},{"id":"D24","name":"Comment Value","shortDescription":{"text":"Comment Value"},"helpUri":"https://codehealth.canine.dev/dimensions/D24"},{"id":"D26","name":"Project Cohesion","shortDescription":{"text":"Project Cohesion"},"helpUri":"https://codehealth.canine.dev/dimensions/D26"},{"id":"D27","name":"Navigability","shortDescription":{"text":"Navigability"},"helpUri":"https://codehealth.canine.dev/dimensions/D27"},{"id":"D28","name":"Secrets (history)","shortDescription":{"text":"Secrets (history)"},"helpUri":"https://codehealth.canine.dev/dimensions/D28","relationships":[{"target":{"id":"CWE-798","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}]},{"id":"D29","name":"Static Analysis (SAST)","shortDescription":{"text":"Static Analysis (SAST)"},"helpUri":"https://codehealth.canine.dev/dimensions/D29"},{"id":"D30","name":"Dependency Vulnerabilities","shortDescription":{"text":"Dependency Vulnerabilities"},"helpUri":"https://codehealth.canine.dev/dimensions/D30","relationships":[{"target":{"id":"CWE-1395","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}]},{"id":"D31","name":"IaC \u0026 Container Security","shortDescription":{"text":"IaC \u0026 Container Security"},"helpUri":"https://codehealth.canine.dev/dimensions/D31"},{"id":"D35","name":"Change Coupling","shortDescription":{"text":"Change Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D35"}]}},"results":[{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:302-315 | CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:357-370"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.UI.CA/Program.cs"},"region":{"startLine":302}}}],"partialFingerprints":{"codehealthFindingId/v1":"c658349850e52652ac7e00ade8ddc14cd5c68efef958e553873bcfc767ea9ca5"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 2): CryptoMonitor/CryptoMonitor.DAL/EF/Repository.cs:113-123 | CryptoMonitor/CryptoMonitor.DAL/InMemoryRepository.cs:89-97"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.DAL/EF/Repository.cs"},"region":{"startLine":113}}}],"partialFingerprints":{"codehealthFindingId/v1":"d46b9296e5b9b18ba3acd6251a8265c994ff7f5c19678443d557c206394b4d9e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:244-253 | CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:293-302"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.UI.CA/Program.cs"},"region":{"startLine":244}}}],"partialFingerprints":{"codehealthFindingId/v1":"8b33a0a4d5014495655eb12d92364410ee53e5438029953962a1bf18567db337"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:381-388 | CryptoMonitor/CryptoMonitor.UI.CA/Program.cs:425-432"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.UI.CA/Program.cs"},"region":{"startLine":381}}}],"partialFingerprints":{"codehealthFindingId/v1":"eb7c0740ba779a08ce9c39fe9981d70566c9b6634632e2b14c756ff3d8ad6b3b"}},{"ruleId":"D5","level":"warning","message":{"text":"Off the main sequence: CryptoMonitor.Domain: CryptoMonitor.Domain: abstractness 0.00, instability 0.00, distance 1.00 \u2014 zone of pain \u2014 concrete and heavily depended-on, so it\u0027s rigid to change."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"25fdddbb0ac420ec6247bf5fc2262caeb33f6fd567b436cc93a602d9f67fd601"}},{"ruleId":"D8","level":"warning","message":{"text":"Coverage not measured \u2014 test suite did not build: Coverage NOT MEASURED: the repo\u0027s own test suite did not build (a C#/MSBuild compiler error in the test code), so no coverage could be collected. It is excluded from the score rather than counted as a near-zero defect. Fix the test build, or commit the Cobertura/OpenCover/lcov report your CI already produces, and real coverage will be measured."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"8beb176c604706486df63d2215f767f50520c8d949b1d464345de14ded442c69"}},{"ruleId":"D19","level":"note","message":{"text":"The README is a single-page class-diagram walkthrough of four sprints with SQL queries; there is no prose describing what each model represents or how it connects to other models.: Add a short overview section explaining the purpose and relationships of each data model (Cryptocurrency, Exchange, UserReview) so readers understand the domain without reading the diagrams."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"README.md"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"36b5eeacc221598c887ff04b950a6f980243ca22083e51c29b28a556e23325fb"}},{"ruleId":"D20","level":"note","message":{"text":"No ADRs found: No ADRs found at common paths; consider documenting architectural decisions in Docs/ADL/ or similar."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d2bea044ff79d7d275f5a91a6e2f548586178eaf480274c33960ad020c854631"}},{"ruleId":"D21","level":"note","message":{"text":"Inconsistent naming for the same or related concepts: \u0027Cryptocurrency\u0027 vs \u0027Crypto\u0027. The domain model uses \u0027Cryptocurrency\u0027 while the type/enum uses \u0027CryptoType\u0027. This creates confusion between the full term and the abbreviation.: Standardize on either \u0027Cryptocurrency\u0027 or \u0027Crypto\u0027 across the domain model. Given the explicit \u0027CryptoMonitor\u0027 namespace, \u0027Crypto\u0027 might be acceptable, but \u0027Cryptocurrency\u0027 is more precise. Ensure \u0027CryptoType\u0027 is clearly distinct from \u0027Cryptocurrency\u0027. (symbols: CryptoMonitor.Domain.Cryptocurrency, CryptoMonitor.Domain.CryptoType)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"f7ff02d75311a96f73fca95fbc3e56012da88fd0bb068e0d1f347638ce5f2a26"}},{"ruleId":"D21","level":"note","message":{"text":"Confusingly similar names for distinct concepts: \u0027Exchange\u0027 vs \u0027ExchangeListing\u0027. \u0027Exchange\u0027 likely refers to the exchange entity itself, while \u0027ExchangeListing\u0027 seems to be a join table or a specific listing on an exchange. The shared prefix \u0027Exchange\u0027 might cause confusion about their relationship.: Rename \u0027ExchangeListing\u0027 to something more descriptive like \u0027ExchangeAsset\u0027 or \u0027ExchangeTicker\u0027 if it represents a cryptocurrency listed on an exchange, or keep \u0027ExchangeListing\u0027 but ensure the distinction from \u0027Exchange\u0027 is clear in documentation. (symbols: CryptoMonitor.Domain.Exchange, CryptoMonitor.Domain.ExchangeListing)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"7b35b9747033d33f2d815077242445fe0e8005c1a2ee467d9b00aae2484b6a49"}},{"ruleId":"D23","level":"note","message":{"text":"Bounded contexts not declared: At 1927 LoC across 6 projects the codebase is mid-range size and multi-module, so boundaries are warranted despite the absence of declared bounded contexts. Declare architecture.contexts (\u22652) in config to assess cross-boundary type coupling."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"1c7e276c9c682731f01819ed5378b90ca320cde1b583c90920172911598362b3"}},{"ruleId":"D24","level":"note","message":{"text":"redundant comment: \u0022HandleCookies = True  // this is the default\u0022 \u2014 delete - restates HandleCookies=True; only keep the link to MS Docs if it adds a real WHY"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.Tests/ExtendedWebApplicationFactory.cs"},"region":{"startLine":74}}}],"partialFingerprints":{"codehealthFindingId/v1":"c09279c49379ce0ecc64606782ac14505c172edb9622fe13a4b7f7dfbd6d88b3"}},{"ruleId":"D30","level":"error","message":{"text":"High CVE: SQLitePCLRaw.lib.e_sqlite3 2.1.10: SQLitePCLRaw.lib.e_sqlite3 2.1.10 (transitive) has a High advisory; affects 5 projects \u2014 one upgrade fixes all. https://github.com/advisories/[GHSA redacted]"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"4bb21bfe4dacebf32c74969b01bdfd4143dcc202111d99f8d1abd5eb6de9eec2"}},{"ruleId":"D30","level":"warning","message":{"text":"Medium CVE: OpenTelemetry.Api 1.9.0: OpenTelemetry.Api 1.9.0 (transitive) has a Medium advisory; affects 2 projects \u2014 one upgrade fixes all. https://github.com/advisories/[GHSA redacted]"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"1f603a8ebd694e4aeb9c309fc8133e250204b578e77f235b9a88211fb438737f"}},{"ruleId":"D31","level":"error","message":{"text":"High IaC: DS-0002: Image user should not be \u0027root\u0027"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"Dockerfile"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"fe2d688610b51e0a5a02c7c5dd1724a4986e40f2689fb84510e2ec0164c27d6a"}},{"ruleId":"D31","level":"note","message":{"text":"Low IaC: DS-0026: No HEALTHCHECK defined"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"Dockerfile"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"1f51a163f26d94ce6b6f473117dde579d091c8cbf9e59810475c94d9fc921120"}},{"ruleId":"D35","level":"warning","message":{"text":"Change coupling: CryptoManager.cs \u2194 InMemoryRepository.cs: \u0060CryptoMonitor/CryptoMonitor.BL/CryptoManager.cs\u0060 and \u0060CryptoMonitor/CryptoMonitor.DAL/InMemoryRepository.cs\u0060 change together 91% of the time (10 shared commits) with no explicit dependency \u2014 a hidden/logical coupling. If they belong together, co-locate them; if not, break the coupling."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"CryptoMonitor/CryptoMonitor.BL/CryptoManager.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"5d71365f79c28a124c3d1ddea02f283b042bb20da8b7d0e81a414d1acb8df377"}}],"taxonomies":[{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d","organization":"MITRE","shortDescription":{"text":"The MITRE Common Weakness Enumeration (CWE)."},"taxa":[{"id":"CWE-1395","name":"Dependency on Vulnerable Third-Party Component"},{"id":"CWE-798","name":"Use of Hard-coded Credentials"}]}],"properties":{"codehealthPublication":{"public":true,"notice":"This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings \u2014 which rule fired, in which file, on which line, and how to fix it \u2014 are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.","securityFindingsRedacted":0,"secretScannerRunsExcluded":0}}}]}