{"$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":"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"]},{"target":{"id":"CWE-259","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-798","CWE-259"]}},{"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":"D16","name":"Bus Factor","shortDescription":{"text":"Bus Factor"},"helpUri":"https://codehealth.canine.dev/dimensions/D16"},{"id":"D17","name":"Explicit Debt","shortDescription":{"text":"Explicit Debt"},"helpUri":"https://codehealth.canine.dev/dimensions/D17"},{"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":"D26","name":"Project Cohesion","shortDescription":{"text":"Project Cohesion"},"helpUri":"https://codehealth.canine.dev/dimensions/D26"},{"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"]},{"target":{"id":"CWE-259","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-798","CWE-259"]}},{"id":"D29","name":"Static Analysis (SAST)","shortDescription":{"text":"Static Analysis (SAST)"},"helpUri":"https://codehealth.canine.dev/dimensions/D29","relationships":[{"target":{"id":"CWE-79","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-89","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-78","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-94","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-77","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-79","CWE-89","CWE-78","CWE-94","CWE-77"]}},{"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"]},{"target":{"id":"CWE-937","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-1395","CWE-937"]}},{"id":"D31","name":"IaC \u0026 Container Security","shortDescription":{"text":"IaC \u0026 Container Security"},"helpUri":"https://codehealth.canine.dev/dimensions/D31","relationships":[{"target":{"id":"CWE-1032","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-732","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-16","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-1032","CWE-732","CWE-16"]}},{"id":"D34","name":"Knowledge Freshness","shortDescription":{"text":"Knowledge Freshness"},"helpUri":"https://codehealth.canine.dev/dimensions/D34"},{"id":"D35","name":"Change Coupling","shortDescription":{"text":"Change Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D35"},{"id":"D36","name":"Supply-chain Provenance \u0026 Signing","shortDescription":{"text":"Supply-chain Provenance \u0026 Signing"},"helpUri":"https://codehealth.canine.dev/dimensions/D36","relationships":[{"target":{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-494","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-1357","CWE-494"]}},{"id":"D43","name":"Malicious Dependencies","shortDescription":{"text":"Malicious Dependencies"},"helpUri":"https://codehealth.canine.dev/dimensions/D43","relationships":[{"target":{"id":"CWE-506","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-506"]}},{"id":"AX10","name":"Code composition","shortDescription":{"text":"Code composition"},"helpUri":"https://codehealth.canine.dev/dimensions/AX10"},{"id":"AX3","name":"Project dependency cycles","shortDescription":{"text":"Project dependency cycles"},"helpUri":"https://codehealth.canine.dev/dimensions/AX3"},{"id":"AX4","name":"Dependency direction","shortDescription":{"text":"Dependency direction"},"helpUri":"https://codehealth.canine.dev/dimensions/AX4"},{"id":"AX9","name":"CQS / query purity","shortDescription":{"text":"CQS / query purity"},"helpUri":"https://codehealth.canine.dev/dimensions/AX9"},{"id":"AXB2","name":"Runtime readiness","shortDescription":{"text":"Runtime readiness"},"helpUri":"https://codehealth.canine.dev/dimensions/AXB2"},{"id":"ED1","name":"Handler temporal coupling","shortDescription":{"text":"Handler temporal coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/ED1"},{"id":"ED2","name":"Event/command shape","shortDescription":{"text":"Event/command shape"},"helpUri":"https://codehealth.canine.dev/dimensions/ED2"},{"id":"M1","name":"Documentation (README)","shortDescription":{"text":"Documentation (README)"},"helpUri":"https://codehealth.canine.dev/dimensions/M1"},{"id":"M2","name":"Architecture documentation","shortDescription":{"text":"Architecture documentation"},"helpUri":"https://codehealth.canine.dev/dimensions/M2"},{"id":"M3","name":"Folder \u0026 project structure","shortDescription":{"text":"Folder \u0026 project structure"},"helpUri":"https://codehealth.canine.dev/dimensions/M3"},{"id":"M4","name":"Documentation accuracy","shortDescription":{"text":"Documentation accuracy"},"helpUri":"https://codehealth.canine.dev/dimensions/M4"},{"id":"P1","name":"CI/CD gates","shortDescription":{"text":"CI/CD gates"},"helpUri":"https://codehealth.canine.dev/dimensions/P1"},{"id":"P12","name":"CI test-gate honesty","shortDescription":{"text":"CI test-gate honesty"},"helpUri":"https://codehealth.canine.dev/dimensions/P12"},{"id":"P2","name":"Observability","shortDescription":{"text":"Observability"},"helpUri":"https://codehealth.canine.dev/dimensions/P2"},{"id":"P3","name":"Security \u0026 performance tooling","shortDescription":{"text":"Security \u0026 performance tooling"},"helpUri":"https://codehealth.canine.dev/dimensions/P3"},{"id":"P4","name":"Deployment \u0026 Rollback","shortDescription":{"text":"Deployment \u0026 Rollback"},"helpUri":"https://codehealth.canine.dev/dimensions/P4"},{"id":"P6","name":"Release Hygiene","shortDescription":{"text":"Release Hygiene"},"helpUri":"https://codehealth.canine.dev/dimensions/P6"},{"id":"P7","name":"Outbound HTTP resilience","shortDescription":{"text":"Outbound HTTP resilience"},"helpUri":"https://codehealth.canine.dev/dimensions/P7"},{"id":"X10","name":"Duplicated predicate","shortDescription":{"text":"Duplicated predicate"},"helpUri":"https://codehealth.canine.dev/dimensions/X10"},{"id":"X26","name":"Unsynchronised callback handoff","shortDescription":{"text":"Unsynchronised callback handoff"},"helpUri":"https://codehealth.canine.dev/dimensions/X26"},{"id":"X31","name":"Test-only surface in a production module","shortDescription":{"text":"Test-only surface in a production module"},"helpUri":"https://codehealth.canine.dev/dimensions/X31"},{"id":"X32","name":"Type resolved by simple name across every loaded assembly","shortDescription":{"text":"Type resolved by simple name across every loaded assembly"},"helpUri":"https://codehealth.canine.dev/dimensions/X32"},{"id":"X9","name":"Subsumed condition operand","shortDescription":{"text":"Subsumed condition operand"},"helpUri":"https://codehealth.canine.dev/dimensions/X9"}]}},"results":[{"ruleId":"D1","level":"warning","message":{"text":"router_device_worker.handle_cast (cyclomatic 69): router_device_worker.handle_cast has cyclomatic complexity 69 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":333}}}],"partialFingerprints":{"codehealthFindingId/v1":"2298d0a8a55785d3b20745904b84f3f714b05faefb2915d65aa5f9d3408cc06d"}},{"ruleId":"D1","level":"warning","message":{"text":"router_console_ws_worker.handle_info (cyclomatic 36): router_console_ws_worker.handle_info has cyclomatic complexity 36 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"6e04066f8815de0cdcc6a9ed85c25904aafbe23a3e08cd7a0a809396cbbb3c40"}},{"ruleId":"D1","level":"warning","message":{"text":"router_xor_filter_worker.handle_call (cyclomatic 28): router_xor_filter_worker.handle_call has cyclomatic complexity 28 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_xor_filter_worker.erl"},"region":{"startLine":184}}}],"partialFingerprints":{"codehealthFindingId/v1":"f0e99d0488da34dba4b3bbcf392ea7185e17f65aeb385750a80ce2b281cc0d09"}},{"ruleId":"D1","level":"warning","message":{"text":"router_console_ws_worker.update_device_record (cyclomatic 27): router_console_ws_worker.update_device_record has cyclomatic complexity 27 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":402}}}],"partialFingerprints":{"codehealthFindingId/v1":"fcc318bf535e8cc5851a4c6d93edc3a7c4e1f32e6a527bd9c3bc2da66ff1fbab"}},{"ruleId":"D1","level":"warning","message":{"text":"router_device_channels_worker.handle_info (cyclomatic 26): router_device_channels_worker.handle_info has cyclomatic complexity 26 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":347}}}],"partialFingerprints":{"codehealthFindingId/v1":"40c201547ae205b799c7889963a981d9c102a67e89fc00aec6f69bc6b85e2d45"}},{"ruleId":"D1","level":"warning","message":{"text":"router_device_channels_worker.handle_cast (cyclomatic 24): router_device_channels_worker.handle_cast has cyclomatic complexity 24 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":202}}}],"partialFingerprints":{"codehealthFindingId/v1":"981b2ab7fc989690658eb2799022bd2bfa5b2adfce29d52aaedad9ee57ccc25b"}},{"ruleId":"D1","level":"warning","message":{"text":"router_xor_filter_worker.handle_info (cyclomatic 24): router_xor_filter_worker.handle_info has cyclomatic complexity 24 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_xor_filter_worker.erl"},"region":{"startLine":355}}}],"partialFingerprints":{"codehealthFindingId/v1":"00ed2ab8ce29171d88158680e1c0e6ce3e4a32d9960f590ea3e0abf9e3e2e3cd"}},{"ruleId":"D1","level":"warning","message":{"text":"router_mqtt_channel.handle_info (cyclomatic 23): router_mqtt_channel.handle_info has cyclomatic complexity 23 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_mqtt_channel.erl"},"region":{"startLine":123}}}],"partialFingerprints":{"codehealthFindingId/v1":"84d6cf326fcfe3e0785c867a2d2f5f099e8999957d1c682f543219e03223bff8"}},{"ruleId":"D1","level":"warning","message":{"text":"router_cli_xor_filter.report_device (cyclomatic 21): router_cli_xor_filter.report_device has cyclomatic complexity 21 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/cli/router_cli_xor_filter.erl"},"region":{"startLine":331}}}],"partialFingerprints":{"codehealthFindingId/v1":"3f353dfaafbfbc22cec15e068bc64261e6600ed7a263c89137cf80266c3fbef7"}},{"ruleId":"D1","level":"warning","message":{"text":"router_console_api.event (cyclomatic 20): router_console_api.event has cyclomatic complexity 20 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":277}}}],"partialFingerprints":{"codehealthFindingId/v1":"e8225051d0e9e573e64e9e5a4b5e5ded33780596c9e43964bf8793c7b7107c6c"}},{"ruleId":"D1","level":"warning","message":{"text":"router_device_worker.handle_info (cyclomatic 17): router_device_worker.handle_info has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1001}}}],"partialFingerprints":{"codehealthFindingId/v1":"e1e62b0b4b0eaa9f7017032b8fb7e9855621afc0f547129a7e951f8a751ae359"}},{"ruleId":"D1","level":"warning","message":{"text":"router_device_worker.validate_frame (cyclomatic 16): router_device_worker.validate_frame has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1491}}}],"partialFingerprints":{"codehealthFindingId/v1":"573d4504eb3cedb8d353a809ffebe4be9962bf3426e41eb5248443f1aaa3f5c6"}},{"ruleId":"D1","level":"warning","message":{"text":"router_sc_worker.handle_info (cyclomatic 16): router_sc_worker.handle_info has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_sc_worker.erl"},"region":{"startLine":164}}}],"partialFingerprints":{"codehealthFindingId/v1":"f7879976c4920900309186ef3ea94f344e95165f809e6822ce11b6dfa4bd60cc"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device_worker.handle_cast (cognitive 90): router_device_worker.handle_cast has cognitive complexity 90 (threshold 15). Drivers by points: error handling 14 (47 pts), match/switch 25 (43 pts) (nesting depth added 51). The drivers above price the dispatch low by construction \u2014 a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full \u2014 so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":333}}}],"partialFingerprints":{"codehealthFindingId/v1":"da064f65473ef8fcb92c37036a8eec3a5a3db355a4e1d1bf2f59b05d150bbc5e"}},{"ruleId":"D2","level":"warning","message":{"text":"router_console_ws_worker.update_device_record (cognitive 51): router_console_ws_worker.update_device_record has cognitive complexity 51 (threshold 15). Drivers by points: error handling 10 (33 pts), match/switch 11 (18 pts) (nesting depth added 30). The drivers above price the dispatch low by construction \u2014 a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full \u2014 so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":402}}}],"partialFingerprints":{"codehealthFindingId/v1":"01fbc1310461b5198532d554f7969d650df3b5ac91694fe56b0771f448e8a54d"}},{"ruleId":"D2","level":"warning","message":{"text":"router_cli_xor_filter.report_device (cognitive 25): router_cli_xor_filter.report_device has cognitive complexity 25 (threshold 15). Drivers by points: match/switch 12 (15 pts), if/else 2 (6 pts), loops 2 (4 pts) (nesting depth added 9). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/cli/router_cli_xor_filter.erl"},"region":{"startLine":331}}}],"partialFingerprints":{"codehealthFindingId/v1":"368914900a754860014f39bd16bca1f124db60b4a3b5555b7ed8a064432582b9"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device_channels_worker.downlink_decode (cognitive 22): router_device_channels_worker.downlink_decode has cognitive complexity 22 (threshold 15). Drivers by points: match/switch 12 (18 pts), error handling 2 (3 pts), boolean chains 1 (nesting depth added 7). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":537}}}],"partialFingerprints":{"codehealthFindingId/v1":"0338bf4aaeb42febf3c3bf0d89ceb776b6d3d1160c9c062d94e6bb5add90a697"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device_channels_worker.handle_info (cognitive 21): router_device_channels_worker.handle_info has cognitive complexity 21 (threshold 15). Drivers by points: match/switch 13 (20 pts), boolean chains 1 (nesting depth added 7). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":347}}}],"partialFingerprints":{"codehealthFindingId/v1":"213d326e8404dee55e1d8e9bd63a30b76b3f370ea8a0025b54777b263466c7c7"}},{"ruleId":"D2","level":"warning","message":{"text":"router_console_ws_worker.handle_info (cognitive 18): router_console_ws_worker.handle_info has cognitive complexity 18 (threshold 15). Drivers by points: match/switch 11, error handling 4 (6 pts), boolean chains 1 (nesting depth added 2). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"83add250c0ad8643c56d8c7d7648d7a3442f63dc8edada51998a6092a1395cbe"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device_routing.send_to_device_worker (cognitive 18): router_device_routing.send_to_device_worker has cognitive complexity 18 (threshold 15). Drivers by points: match/switch 10 (18 pts) (nesting depth added 8). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_routing.erl"},"region":{"startLine":1024}}}],"partialFingerprints":{"codehealthFindingId/v1":"021d58f386d17118a4c58c80e208e4dd4776c5c1c87a5822a921e537681f098b"}},{"ruleId":"D2","level":"warning","message":{"text":"router_console_api.event (cognitive 17): router_console_api.event has cognitive complexity 17 (threshold 15). Drivers by points: match/switch 8 (13 pts), boolean chains 4 (nesting depth added 5). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":277}}}],"partialFingerprints":{"codehealthFindingId/v1":"c8f8eb6e46560ff342055bed888ca27a56015836cc45e2974c5553580cb7f1aa"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device.deserialize (cognitive 16): router_device.deserialize has cognitive complexity 16 (threshold 15). Drivers by points: match/switch 11 (16 pts) (nesting depth added 5). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device.erl"},"region":{"startLine":318}}}],"partialFingerprints":{"codehealthFindingId/v1":"c21f86962bd5f9eaaddb989a2314293adae77555873141984c12cb2e5a1f2f32"}},{"ruleId":"D2","level":"warning","message":{"text":"router_device_routing.packet_offer_ (cognitive 16): router_device_routing.packet_offer_ has cognitive complexity 16 (threshold 15). Drivers by points: match/switch 6 (16 pts) (nesting depth added 10). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_routing.erl"},"region":{"startLine":618}}}],"partialFingerprints":{"codehealthFindingId/v1":"7e5dee50a2baa600c17b9f16b30e3599a1036a1412569442adc05945a41086fe"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: device/router_device_worker.erl: FileTooLong \u2014 2006 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 49 functions. The bar is 500 significant lines; this is 1506 over it, 4.01\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"29bab00a8cb25c086e159c269b2261359f66f3e416aff5dae76dddecee715ddd"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: device/router_device_routing.erl: FileTooLong \u2014 1305 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 52 functions. The bar is 500 significant lines; this is 805 over it, 2.61\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_routing.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"63483f8698e8d83f2eeb14c2ef3f577f4b44c13763443c124a2c84fde34029fe"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: src/router_xor_filter_worker.erl: FileTooLong \u2014 1223 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 59 functions. The bar is 500 significant lines; this is 723 over it, 2.45\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_xor_filter_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"771d5c169ecfe0e8c67cdd122a0ed7ecd2105b1f1167705a864921ef01951cef"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: apis/router_console_api.erl: FileTooLong \u2014 1138 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 47 functions. The bar is 500 significant lines; this is 638 over it, 2.28\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ad63f67c40685edee529bff5e418b53f9e2374c86f29987fc666d24e5d796efe"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: src/router_utils.erl: FileTooLong \u2014 862 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 42 functions. The bar is 500 significant lines; this is 362 over it, 1.72\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_utils.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"e1e72af8fe5ee64fcb65d3f5255da804dc62bcd56af2b94fa9aa6ff04ea15142"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: device/router_device.erl: FileTooLong \u2014 752 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 62 functions. The bar is 500 significant lines; this is 252 over it, 1.50\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"b7cebf8954130df5205a0c44ca79d9b981eb60dd3b673d26a1c41a2235b4880b"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: device/router_device_channels_worker.erl: FileTooLong \u2014 750 significant lines (blank, comment-only and punctuation-only lines excluded), declaring 34 functions. The bar is 500 significant lines; this is 250 over it, 1.50\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"7757d3d20adc0988589eaef1d1dc79cf4a17ff1ba0ee757c39a521b693ee5acf"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyFunctions: router_ics_skf_worker: TooManyFunctions \u2014 35 functions. The bar is 30 functions; this is 5 over it, 1.17\u00D7 the bar. The counted members are a module\u0027s functions \u2014 a module holds no instance state, so there is no shared data to group them by and no type to move them onto. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no single module carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_skf_worker.erl"},"region":{"startLine":6}}}],"partialFingerprints":{"codehealthFindingId/v1":"510749225ec4a444bf5a4fd753ebb0948507803f9517d61be97296559a1bbec3"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: channels/router_aws_channel.erl: FileTooLong \u2014 563 significant lines (blank, comment-only and punctuation-only lines excluded). The bar is 500 significant lines; this is 63 over it, 1.13\u00D7 the bar. In this language a module is exactly one source file, so its length cannot be moved into sibling files of the same module. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no one module has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"129a799bca926e0da5e2fa406a9d0d96f68f35b7dbe8a7c05400c867898707f0"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyFunctions: router_cli_device_worker: TooManyFunctions \u2014 33 functions. The bar is 30 functions; this is 3 over it, 1.10\u00D7 the bar. The counted members are a module\u0027s functions \u2014 a module holds no instance state, so there is no shared data to group them by and no type to move them onto. To reduce it, extract each cohesive family of functions into a new module of its own and have this one delegate to it, so no single module carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/cli/router_cli_device_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"0eca2f095c6258c4ca8f038af9936397c9750568b2e8eeec0e3aee1a0d31ecac"}},{"ruleId":"D4","level":"warning","message":{"text":"Members sharing a duplicated core (7 members, 50\u002B identical tokens): src/channels/router_aws_channel.erl:78-90 | src/channels/router_console_channel.erl:36-48 | src/channels/router_http_channel.erl:55-67 | src/channels/router_iot_central_channel.erl:58-70 | src/channels/router_iot_hub_channel.erl:57-69 | src/channels/router_mqtt_channel.erl:70-82 | src/channels/router_no_channel.erl:36-48 \u2014 These 7 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below \u2014 it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 7 times. The repair is at the members\u0027 grain \u2014 factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 7 times."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":78}}}],"partialFingerprints":{"codehealthFindingId/v1":"df343b3585089dbe30b16f9ef67f24d42479b243d8785e141a6b90ba08a996a7"}},{"ruleId":"D4","level":"warning","message":{"text":"Members sharing a duplicated core (4 members, 50\u002B identical tokens): src/channels/router_aws_channel.erl:263-299 | src/channels/router_iot_central_channel.erl:227-251 | src/channels/router_iot_hub_channel.erl:223-247 | src/channels/router_mqtt_channel.erl:374-410 \u2014 These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below \u2014 it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members\u0027 grain \u2014 factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":263}}}],"partialFingerprints":{"codehealthFindingId/v1":"ec03756f104fe6a27561080bc3a5242b5d2217a01839b3c5da440aaeaeb27138"}},{"ruleId":"D4","level":"warning","message":{"text":"Members sharing a duplicated core (4 members, 50\u002B identical tokens): src/channels/router_aws_channel.erl:302-335 | src/channels/router_iot_central_channel.erl:254-287 | src/channels/router_iot_hub_channel.erl:250-283 | src/channels/router_mqtt_channel.erl:413-446 \u2014 These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below \u2014 it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members\u0027 grain \u2014 factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":302}}}],"partialFingerprints":{"codehealthFindingId/v1":"b2d29745355e5546bcaf1b550788e9cb01f0fdfdb7701bb65c0ffe0cf483e0f1"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (36 lines \u00D7 2): src/apis/router_console_ws_worker.erl:463-498 | src/device/router_device_worker.erl:420-455 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":463}}}],"partialFingerprints":{"codehealthFindingId/v1":"29a41e4eabf14037c6d8fb5fae7a07aeda42f61e4fd9d4373d40e609b95b6f2a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (29 lines \u00D7 2): src/channels/router_aws_channel.erl:263-291 | src/channels/router_mqtt_channel.erl:374-402 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":263}}}],"partialFingerprints":{"codehealthFindingId/v1":"5abe11f4366b2604918a7af36b190a85081290b051471128ba9deb95fd3caa71"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (25 lines \u00D7 4): src/channels/router_aws_channel.erl:302-326 | src/channels/router_iot_central_channel.erl:254-278 | src/channels/router_iot_hub_channel.erl:250-274 | src/channels/router_mqtt_channel.erl:413-437 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":302}}}],"partialFingerprints":{"codehealthFindingId/v1":"998fd4179c46a4fb5561ecfc73e1b5b3ec621016ba23be2d16ce1638d64550d1"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (23 lines \u00D7 2): src/channels/router_iot_central_channel.erl:83-105 | src/channels/router_iot_hub_channel.erl:82-104 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_channel.erl\u0060 and \u0060src/channels/router_iot_hub_channel.erl\u0060 as WHOLE FILES: this scan already matched 11 separate duplicated blocks between them, totalling at least 146 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":83}}}],"partialFingerprints":{"codehealthFindingId/v1":"bbe507b9afe2d5a89d93cb8b5b7af8f658f250fcd057f166bdc7acf61ebcfee8"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (21\u201322 lines \u00D7 2): src/router_xor_filter_worker.erl:284-305 | src/router_xor_filter_worker.erl:318-338 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_xor_filter_worker.erl"},"region":{"startLine":284}}}],"partialFingerprints":{"codehealthFindingId/v1":"751c963482b2fcd07f0d0e00d86e3344b1dd968686305a5e001fc85c572fa412"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (21 lines \u00D7 2): src/channels/router_iot_central_channel.erl:227-247 | src/channels/router_iot_hub_channel.erl:223-243 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_channel.erl\u0060 and \u0060src/channels/router_iot_hub_channel.erl\u0060 as WHOLE FILES: this scan already matched 11 separate duplicated blocks between them, totalling at least 146 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":227}}}],"partialFingerprints":{"codehealthFindingId/v1":"05477732b921bd3719eae45443e1aa0f766e3a80d6cd4b0d158af873262ce987"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (21 lines \u00D7 2): src/device/router_device_worker.erl:1667-1687 | src/device/router_device_worker.erl:1718-1738 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1667}}}],"partialFingerprints":{"codehealthFindingId/v1":"1ff056c64ed5b5a3fc2d4eccaa068bb199e21a79aba338c0507f349a08bfd800"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (19\u201320 lines \u00D7 5): src/apis/router_console_api.erl:778-796 | src/apis/router_console_api.erl:809-828 | src/apis/router_console_api.erl:838-856 | src/apis/router_console_api.erl:874-893 | src/apis/router_console_api.erl:910-928 \u2014 all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":778}}}],"partialFingerprints":{"codehealthFindingId/v1":"7dd7cf21264ba10edcad1939ef0383313517355c0089deded318d426aac36013"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14\u201320 lines \u00D7 2): src/device/router_device_worker.erl:294-313 | src/device/router_device_worker.erl:1314-1327 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":294}}}],"partialFingerprints":{"codehealthFindingId/v1":"589c733403047f735b7d0f4e3a5e1c8721d7a9bd39baa903ca08827d6653df72"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14\u201319 lines \u00D7 2): src/channels/router_aws_channel.erl:202-215 | src/channels/router_mqtt_channel.erl:297-315 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":202}}}],"partialFingerprints":{"codehealthFindingId/v1":"aa8a92d23cbd49dc993cee9ceb9a7985e9201dc396056ddb0a000de6b3e683be"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (17 lines \u00D7 2): src/channels/router_iot_central_channel.erl:143-159 | src/channels/router_iot_hub_channel.erl:142-158 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_channel.erl\u0060 and \u0060src/channels/router_iot_hub_channel.erl\u0060 as WHOLE FILES: this scan already matched 11 separate duplicated blocks between them, totalling at least 146 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":143}}}],"partialFingerprints":{"codehealthFindingId/v1":"ab5ba96204c6e982873577066dc0708b1cfd31b50326b56013070b14daad117b"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15\u201316 lines \u00D7 2): src/channels/router_mqtt_channel.erl:153-168 | src/channels/router_mqtt_channel.erl:209-223 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_mqtt_channel.erl"},"region":{"startLine":153}}}],"partialFingerprints":{"codehealthFindingId/v1":"c131d05e7a945ecb33403d8e4a2fc8e7bcc14bf4495f6cd3f60c8c255568aed2"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15\u201316 lines \u00D7 2): src/router_sc_worker.erl:173-187 | src/router_sc_worker.erl:205-220 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_sc_worker.erl"},"region":{"startLine":173}}}],"partialFingerprints":{"codehealthFindingId/v1":"1b03cedfe5e9c6adf1202e70b32a8c718e5a98f3852fe6872a322e818d86d1ed"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15 lines \u00D7 2): src/channels/router_iot_central_channel.erl:185-199 | src/channels/router_iot_hub_channel.erl:184-198 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_channel.erl\u0060 and \u0060src/channels/router_iot_hub_channel.erl\u0060 as WHOLE FILES: this scan already matched 11 separate duplicated blocks between them, totalling at least 146 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":185}}}],"partialFingerprints":{"codehealthFindingId/v1":"3e0715e9b06612a2eedd49024c26772d61677fe7876a224a90b00b13fc244aa0"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (12\u201314 lines \u00D7 2): src/channels/router_aws_channel.erl:218-229 | src/channels/router_mqtt_channel.erl:328-341 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":218}}}],"partialFingerprints":{"codehealthFindingId/v1":"1c930abfb32bc856b39b9e5142e168b89f3969f368d67ae64c4947a177eea784"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): src/apis/router_console_ws_worker.erl:437-449 | src/device/router_device_worker.erl:392-404 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":437}}}],"partialFingerprints":{"codehealthFindingId/v1":"f520b48bc2a6855f96288e0628a1631ae6ea0bb0b961a7dae3bf5acee08ec4ef"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): src/channels/router_aws_channel.erl:116-128 | src/channels/router_mqtt_channel.erl:186-198 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":116}}}],"partialFingerprints":{"codehealthFindingId/v1":"2804a8987f55d9ba71a2454edea6e3eafc262a759f6a14779699b94f16ce67e0"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): src/channels/router_aws_channel.erl:168-180 | src/channels/router_mqtt_channel.erl:259-271 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":168}}}],"partialFingerprints":{"codehealthFindingId/v1":"f87dbe1d954141a4a54de4c19cb41dbba16380a5f0e4c6e05071b191def11bc8"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 3): src/channels/router_aws_channel.erl:287-297 | src/channels/router_iot_central_channel.erl:239-249 | src/channels/router_iot_hub_channel.erl:235-245 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":287}}}],"partialFingerprints":{"codehealthFindingId/v1":"fcefc409c12f0a079dbe592ad6e7f9cc20074c9c514905f168b440d4a935f612"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 2): src/apis/router_console_api.erl:322-332 | src/apis/router_console_api.erl:338-348 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":322}}}],"partialFingerprints":{"codehealthFindingId/v1":"fe02d8efa26383f3f3f25a122d042d9c6bd644f9ee49ab09b2e12ed2b2fd6e03"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 2): src/device/router_device_worker.erl:1811-1821 | src/device/router_device_worker.erl:1897-1907 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1811}}}],"partialFingerprints":{"codehealthFindingId/v1":"c8844a5858216c9746a0fb01c9569875bf27b1e5cf43eaa83245320c7f6d8111"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9\u201310 lines \u00D7 2): src/channels/router_iot_central_connection.erl:291-299 | src/channels/router_iot_central_connection.erl:344-353 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":291}}}],"partialFingerprints":{"codehealthFindingId/v1":"fef357f8988b023d0f591c0e721b167a8a3e86a6c26dd624885cb8145a39f25a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): src/device/router_device_routing.erl:391-400 | src/device/router_device_routing.erl:415-424 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_routing.erl"},"region":{"startLine":391}}}],"partialFingerprints":{"codehealthFindingId/v1":"3e0dd49ab3baedb89b9330c852f4dbcf91a0ff5292a5bcf55251427a979b0441"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 6): src/channels/router_aws_channel.erl:79-87 | src/channels/router_console_channel.erl:37-45 | src/channels/router_iot_central_channel.erl:59-67 | src/channels/router_iot_hub_channel.erl:58-66 | src/channels/router_mqtt_channel.erl:71-79 | src/channels/router_no_channel.erl:37-45 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":79}}}],"partialFingerprints":{"codehealthFindingId/v1":"7d8509b045bef26570d268edf4d4e338555ca5bb3cc1cdf400d54c6a710d9f40"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 3): src/router_utils.erl:404-412 | src/router_utils.erl:454-462 | src/router_utils.erl:480-488 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_utils.erl"},"region":{"startLine":404}}}],"partialFingerprints":{"codehealthFindingId/v1":"56126b3b710960d82f483bf324d32dcd42540246b65cac43ef56e6e46b4990b0"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8\u20139 lines \u00D7 2): src/apis/router_console_api.erl:385-393 | src/apis/router_console_api.erl:398-405 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":385}}}],"partialFingerprints":{"codehealthFindingId/v1":"50098b898ac1c1bbccddd01680730c9406056ae423c2ed7359970612d9cb8bdb"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): src/channels/router_mqtt_channel.erl:133-141 | src/channels/router_mqtt_channel.erl:178-186 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_mqtt_channel.erl"},"region":{"startLine":133}}}],"partialFingerprints":{"codehealthFindingId/v1":"310ae417668f9fade5d31312db8780d927166e797e615f31cc94378dfea1605b"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): src/device/router_device_devaddr.erl:262-270 | src/grpc/router_ics_eui_worker.erl:269-277 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_devaddr.erl"},"region":{"startLine":262}}}],"partialFingerprints":{"codehealthFindingId/v1":"6c6bd1b7ae1e2753e364e01ae43bdb312de9fc5ef83fc2aa1f8a2ece2f51810e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6\u20138 lines \u00D7 2): src/channels/router_iot_central_connection.erl:538-545 | src/channels/router_iot_hub_connection.erl:333-338 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_connection.erl\u0060 and \u0060src/channels/router_iot_hub_connection.erl\u0060 as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":538}}}],"partialFingerprints":{"codehealthFindingId/v1":"9d2dfa1421fb57d1397acf1581d81c9482298628b4ffd517ce2e7496d1f44419"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): src/grpc/router_ics_eui_worker.erl:186-193 | src/grpc/router_ics_eui_worker.erl:207-214 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_eui_worker.erl"},"region":{"startLine":186}}}],"partialFingerprints":{"codehealthFindingId/v1":"16f5a6266e3a74486540e6f372358fbc4b892f8046352928c176a1be5b2fa0bc"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7\u20138 lines \u00D7 2): src/grpc/router_ics_eui_worker.erl:482-489 | src/grpc/router_ics_eui_worker.erl:500-506 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_eui_worker.erl"},"region":{"startLine":482}}}],"partialFingerprints":{"codehealthFindingId/v1":"c28bc38f600da3714d02ff377af261d6f628d7878ee1c1eda73335b2015bd160"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 7): src/channels/router_aws_channel.erl:78-84 | src/channels/router_console_channel.erl:36-42 | src/channels/router_http_channel.erl:55-61 | src/channels/router_iot_central_channel.erl:58-64 | src/channels/router_iot_hub_channel.erl:57-63 | src/channels/router_mqtt_channel.erl:70-76 | src/channels/router_no_channel.erl:36-42 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":78}}}],"partialFingerprints":{"codehealthFindingId/v1":"395ab141a0b6adf27519bdb6803139393b88f9abed70a91ff3985ea9dcbc947b"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 4): src/router_utils.erl:376-382 | src/router_utils.erl:403-409 | src/router_utils.erl:453-459 | src/router_utils.erl:479-485 \u2014 all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_utils.erl"},"region":{"startLine":376}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac9e6edcb446fe9ee4ec130a8f433fd6657ecc496268c073d82a54d0820170cd"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 3): src/router_utils.erl:409-415 | src/router_utils.erl:433-439 | src/router_utils.erl:459-465 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_utils.erl"},"region":{"startLine":409}}}],"partialFingerprints":{"codehealthFindingId/v1":"7836c57772e37c9ac786916c7be1d434c846b5f98e6b5db781c0d28b91633970"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/channels/router_aws_channel.erl:248-254 | src/channels/router_mqtt_channel.erl:359-365 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_mqtt_channel.erl\u0060 as WHOLE FILES: this scan already matched 10 separate duplicated blocks between them, totalling at least 142 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":248}}}],"partialFingerprints":{"codehealthFindingId/v1":"f7ebcbf7e40c04007e61d1c824fad686e17f307ebeca4f9a86ae22f3186d95c2"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/channels/router_iot_central_connection.erl:427-433 | src/channels/router_iot_central_connection.erl:463-469 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":427}}}],"partialFingerprints":{"codehealthFindingId/v1":"7dbf588e3a598dbd3d996d938c2b3482c4a864ece9185de0a8f4b3978a363e40"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/cli/router_cli_xor_filter.erl:168-178 | src/cli/router_cli_xor_filter.erl:196-202 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/cli/router_cli_xor_filter.erl"},"region":{"startLine":168}}}],"partialFingerprints":{"codehealthFindingId/v1":"31344e72bcf6191e27537481f9dc15ecc1ec63be80c721768ee2026e735daad5"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/device/router_device_channels_worker.erl:853-859 | src/router_utils.erl:840-846 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":853}}}],"partialFingerprints":{"codehealthFindingId/v1":"105f848e1824779411699872ff3ef6acb70fb06c48435daf9bf61b0202d96f3a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 4): src/channels/router_aws_channel.erl:294-299 | src/channels/router_iot_central_channel.erl:246-251 | src/channels/router_iot_hub_channel.erl:242-247 | src/channels/router_mqtt_channel.erl:405-410 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":294}}}],"partialFingerprints":{"codehealthFindingId/v1":"a36b9058acdf946a7092e96ece72dfcec200e756fd2395a9b58ce106900f1b12"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 3): src/apis/router_console_api.erl:320-325 | src/apis/router_console_api.erl:335-341 | src/apis/router_console_api.erl:414-420 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":320}}}],"partialFingerprints":{"codehealthFindingId/v1":"2ac961a6c54a834891f3bdd8e587e1d73fd70449c20164cbe4ada15b96563f88"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 3): src/apis/router_console_api.erl:1032-1037 | src/apis/router_console_api.erl:1067-1072 | src/apis/router_console_api.erl:1105-1110 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":1032}}}],"partialFingerprints":{"codehealthFindingId/v1":"d7396a4afd9470d80353934d857b1c848f0a87ce75d31312cf72db7054a9b8a4"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 2): src/device/router_device_channels_worker.erl:862-867 | src/router_utils.erl:847-853 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":862}}}],"partialFingerprints":{"codehealthFindingId/v1":"b17fc2d379bf1a93eecbce5d70c3114127e2bbbaa2b208972d3f97df42bdc86d"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 2): src/apis/router_console_api.erl:684-688 | src/apis/router_console_api.erl:722-726 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":684}}}],"partialFingerprints":{"codehealthFindingId/v1":"661df7845303613d9f30b6ab4f1f3f16b798bf30f9d9261ac0fc3dfe4a08c28c"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 2): src/device/router_device.erl:626-630 | src/router_xor_filter_worker.erl:684-688 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device.erl"},"region":{"startLine":626}}}],"partialFingerprints":{"codehealthFindingId/v1":"23d79fec96adc3d5c5fedaaf63ba3a33e45e16a8a7e844258fd4c2e7a0d99176"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 2): src/cli/router_cli_info.erl:25-29 | src/cli/router_cli_migration.erl:26-30 \u2014 the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach \u2014 a file they already depend on, or a new one alongside them \u2014 and call it from both call sites, so a change lands once."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/cli/router_cli_info.erl"},"region":{"startLine":25}}}],"partialFingerprints":{"codehealthFindingId/v1":"c9b18515736d4637c793620872d5cf04f512de8ca1d79fd80efe2e46c08b1668"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 2): src/channels/router_iot_central_connection.erl:236-243 | src/channels/router_iot_hub_connection.erl:197-201 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_connection.erl\u0060 and \u0060src/channels/router_iot_hub_connection.erl\u0060 as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":236}}}],"partialFingerprints":{"codehealthFindingId/v1":"c9f27225589e0fca404a583e913e8ef8ec909d01578c9335760b0add0b8e7983"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): src/channels/router_iot_central_connection.erl:252-260 | src/channels/router_iot_hub_connection.erl:210-218 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_connection.erl\u0060 and \u0060src/channels/router_iot_hub_connection.erl\u0060 as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":252}}}],"partialFingerprints":{"codehealthFindingId/v1":"a766f3695e6b55509d7729cbf157c3d57ea30940531359dff93bb1b18cf0a7e8"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (12 lines \u00D7 2): src/device/router_device_channels_worker.erl:284-296 | src/device/router_device_channels_worker.erl:312-323 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":284}}}],"partialFingerprints":{"codehealthFindingId/v1":"1b7b7f59ff659f1c8b1f31434798fbd4da0f01253789f39c7cc7ce8568fcc470"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): src/grpc/router_ics_eui_worker.erl:64-73 | src/grpc/router_ics_skf_worker.erl:91-100 \u2014 the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach \u2014 a file they already depend on, or a new one alongside them \u2014 and call it from both call sites, so a change lands once."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_eui_worker.erl"},"region":{"startLine":64}}}],"partialFingerprints":{"codehealthFindingId/v1":"6ced2c58a2f02de45895a3e82f99ec2fa52162384f928e15acff49e373d022ff"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): src/router_utils.erl:229-238 | src/router_utils.erl:251-260 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_utils.erl"},"region":{"startLine":229}}}],"partialFingerprints":{"codehealthFindingId/v1":"dd517e43ee16e78d6919667dcf164eb68ef2fbdc63b48e3268abfe1518ca099e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 3): src/apis/router_console_ws_worker.erl:157-165 | src/apis/router_console_ws_worker.erl:166-172 | src/apis/router_console_ws_worker.erl:173-179 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_ws_worker.erl"},"region":{"startLine":157}}}],"partialFingerprints":{"codehealthFindingId/v1":"9c47685e2bccf405466923826b39097767a8ebd4ef9e747f44a1ab3da09835e2"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): src/device/router_device_channels_worker.erl:698-705 | src/device/router_device_channels_worker.erl:721-728 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":698}}}],"partialFingerprints":{"codehealthFindingId/v1":"893c7936821d9f83247fdeed7d611d3c99ae4e7c1cac192707c7e86a9537496b"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): src/channels/router_iot_central_connection.erl:222-229 | src/channels/router_iot_hub_connection.erl:186-193 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_connection.erl\u0060 and \u0060src/channels/router_iot_hub_connection.erl\u0060 as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":222}}}],"partialFingerprints":{"codehealthFindingId/v1":"f8c8c9cb637f7d766c7df5a147b0427f433266cda5bbda514a83db3fd2c3142e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): src/channels/router_aws_channel.erl:442-449 | src/channels/router_aws_channel.erl:463-470 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":442}}}],"partialFingerprints":{"codehealthFindingId/v1":"d4c8699843c8e4f3222c3e14097cbbe1101d4f18e22aa1881654c6176793db88"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/channels/router_iot_central_channel.erl:110-116 | src/channels/router_iot_hub_channel.erl:109-115 \u2014 before extracting anything, compare \u0060src/channels/router_iot_central_channel.erl\u0060 and \u0060src/channels/router_iot_hub_channel.erl\u0060 as WHOLE FILES: this scan already matched 11 separate duplicated blocks between them, totalling at least 146 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":110}}}],"partialFingerprints":{"codehealthFindingId/v1":"2cf689eeb983c369cfef409024074b95db0ce480a15bd52dd10c746e46ba0452"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 2): src/apis/router_console_api.erl:442-448 | src/apis/router_console_api.erl:1314-1320 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":442}}}],"partialFingerprints":{"codehealthFindingId/v1":"acd0271543b74f27c96473fa408562735cd6f26196b7dc61fc72395e96144cd7"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 2): src/device/router_device_channels_worker.erl:690-695 | src/device/router_device_channels_worker.erl:713-718 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_channels_worker.erl"},"region":{"startLine":690}}}],"partialFingerprints":{"codehealthFindingId/v1":"2c627572093d91a921465ea02a048b1036f9054e56e70de817fd0d1981a93d42"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 3): src/channels/router_aws_channel.erl:92-96 | src/channels/router_iot_central_channel.erl:72-76 | src/channels/router_iot_hub_channel.erl:71-75 \u2014 before extracting anything, compare \u0060src/channels/router_aws_channel.erl\u0060 and \u0060src/channels/router_iot_central_channel.erl\u0060 as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 63 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together \u2014 extracting one helper per block leaves the fork in place."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"ede9164f59c73ae73dd489c115d8a6b6ab6a274714f866dac3c78c9a8aae3afb"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 2): src/device/router_device.erl:648-653 | src/router_xor_filter_worker.erl:705-710 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device.erl"},"region":{"startLine":648}}}],"partialFingerprints":{"codehealthFindingId/v1":"c13e45cd3e87693c0ea35393b6ef26997d3d0eac583f658b80da154dbc185ed5"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: clique: Runtime dependency \u0060clique\u0060 is fetched from source in rebar.config and tracks branch \u0060develop\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"f608079e3ee83e3e4f5cb5cf78a90917576739c356b03cf425c02652f7f1b548"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: erlang_lorawan: Runtime dependency \u0060erlang_lorawan\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"6a6971744cf21a6bdb5771519ce7638d7a181d030af39e3e6265aa5d54d31f91"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: router_utils: Runtime dependency \u0060router_utils\u0060 is fetched from source in rebar.config and tracks branch \u0060main\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"aa73ddd5c94e7e543b53cfe115757bc4ecc27544b2945d661fc582301522b425"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: httpc_aws: Runtime dependency \u0060httpc_aws\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"e85390e0620633456501187687bb7d3beef827eb465e9af48502b15417acea82"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: erlang_v8: Runtime dependency \u0060erlang_v8\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"a1f642d63a7afbb51631bad000bb77a7b423b44b426a7352002e8cf9c91c9369"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: bbmustache: Runtime dependency \u0060bbmustache\u0060 is fetched from source in rebar.config and tracks branch \u0060data-fun\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"f6e120b127dfdd2eef453891078d6c226a4ab9daf1d2dac94303da595d3ab757"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: iso8601: Runtime dependency \u0060iso8601\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"2a120583f4a5f93992c2718440f2d3a8be74a6debcadd028fa8bcb1d009b34bd"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: grpcbox: Runtime dependency \u0060grpcbox\u0060 is fetched from source in rebar.config and tracks branch \u0060adt/immediate-sends\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"755804b9c8c971017a443d53908b507bb8694cc2e595197071d78460c9049087"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: e2qc: Runtime dependency \u0060e2qc\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"517088f4e369e9314942fd5fd4d5089c1eab4b74e4488083eed3093699eace40"}},{"ruleId":"D12","level":"warning","message":{"text":"Floating source dependency: helium_proto: Runtime dependency \u0060helium_proto\u0060 is fetched from source in rebar.config and tracks branch \u0060master\u0060 \u2014 the declaration pins no immutable revision, so \u0060rebar3 upgrade\u0060 moves this dependency to code nobody reviewed. Pin it with \u0060{tag, \u0022v1.2.3\u0022}\u0060 or \u0060{ref, \u0022\u003Cfull commit SHA\u003E\u0022}\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"fbd26ebbf37bbf25cfbfb6a44c1482d427b7bfde9e6e520d3c7eada55dad8928"}},{"ruleId":"D16","level":"note","message":{"text":"Off-boarding risk: anonymized user #1: If anonymized user #1 becomes unavailable, 2 significant file(s) lose their only recent owner: src/channels/router_aws_channel.erl, src/grpc/helium_packet_service.erl. Pair on, review, or document these before any departure."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"fb7beceaa7555e61d81467d051a8476dbbdfcbc52de487572f1fe3c1768a0ffd"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Fix force open nonce \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_sc_worker.erl"},"region":{"startLine":84}}}],"partialFingerprints":{"codehealthFindingId/v1":"e03801704da165ff8413b9d9a64666a21b1aa08d33052f94d52e6cae543e4785"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Not really sure where exactly to install this handler at tbh... \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_sc_worker.erl"},"region":{"startLine":142}}}],"partialFingerprints":{"codehealthFindingId/v1":"35a4d326148e1902c6286398bd349d35f74539fece323f795e38f7ad1b661a54"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: join_request guard never applies; see prev arm \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":409}}}],"partialFingerprints":{"codehealthFindingId/v1":"87d21cf80d1386ecd1cbe8cb67cbb3929e4fce868a9b4599c392326f0931b178"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Replace with \u0060uri_string:quote/1\u0027 when it get\u0027s released. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_hub_connection.erl"},"region":{"startLine":12}}}],"partialFingerprints":{"codehealthFindingId/v1":"739fadb84d5566f208a2d8dee35951b9b826152fd5f975f175b25587f668249f"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Replace with \u0060uri_string:quote/1\u0027 when it get\u0027s released. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_hub_connection.erl"},"region":{"startLine":328}}}],"partialFingerprints":{"codehealthFindingId/v1":"f58f6a3309f515d56d269ccd90b566f79615b2a488c2a33739c5838d48b3b903"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Replace with \u0060uri_string:quote/1\u0027 when it get\u0027s released. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":14}}}],"partialFingerprints":{"codehealthFindingId/v1":"a68c1d265b304db6034044de84210b64a31556e55f0a019f0c2477ea291dcfdb"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Replace with \u0060uri_string:quote/1\u0027 when it get\u0027s released. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":535}}}],"partialFingerprints":{"codehealthFindingId/v1":"134ad628851f7a4875d884b46c56df37c22cc0a3c425cf6de5775f05df6e8bcb"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: log more of the errors \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":234}}}],"partialFingerprints":{"codehealthFindingId/v1":"a13b93f6f4c18f8e40d802082fc10ff667915d70a1d4a5293837f3df9fa37f1d"}},{"ruleId":"D17","level":"warning","message":{"text":"FixmeComment: %% FIXME: Bringing back the retry mechanism for decoding until we have the \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_custom_worker.erl"},"region":{"startLine":167}}}],"partialFingerprints":{"codehealthFindingId/v1":"ef7d2fbc303980fb75cc326b31cd1727163a1c1c9c59c06856e0f58133aac827"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO this eliminates any tolerance for intermittent \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_custom_worker.erl"},"region":{"startLine":223}}}],"partialFingerprints":{"codehealthFindingId/v1":"4e28f0b1ccb78a1f29e02fdad18eef093900220d69aaf51c1678876aea5d8e19"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO this should be 0 or 1 \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":57}}}],"partialFingerprints":{"codehealthFindingId/v1":"d716b7cdea2607426b626525fd8d49a35e08527570485410186d014b454a338c"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO this should be 0 or 1 \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":66}}}],"partialFingerprints":{"codehealthFindingId/v1":"abf7fcd9f21844c6cb4aff2d731bb03dc060b0673e50b9cd1f5af744e53ce133"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO is the value MSB or LSB \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":75}}}],"partialFingerprints":{"codehealthFindingId/v1":"0a538c39fcf7e3f7d8d174bd91111d84d1a76f585a3314804d64b3f35275f1c9"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO is the value MSB or LSB \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":84}}}],"partialFingerprints":{"codehealthFindingId/v1":"7b5225cb5962f290f6bc84aa0c095d28036cc85a6d43f9a917b4da2c17993e62"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO is the value MSB or LSB \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":103}}}],"partialFingerprints":{"codehealthFindingId/v1":"5729da903150c4b22a2982c6fc1cc4cea16afff455befa4fb937dc71195abd49"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO value is 0 or 1 \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/decoders/router_decoder_cayenne.erl"},"region":{"startLine":112}}}],"partialFingerprints":{"codehealthFindingId/v1":"5d78ffb111ccde3c05ce4dea533524ac41f75786bf3f740c879599236d2a38bc"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO we should really just call this once per join nonce \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":565}}}],"partialFingerprints":{"codehealthFindingId/v1":"b2723007848e8ecac094484bb2b45baa31721ec32e7d207531125b85f721951b"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: we need \u0060link_adr_answer\u0027 for ADR. Suggest refactoring this. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1957}}}],"partialFingerprints":{"codehealthFindingId/v1":"362ac7f801a8bbcb79db725b2d972e2fb3b651c0cc7de42bba3ea19f4c476f89"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: with ADR implemented, this function, or at least its name, \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":1995}}}],"partialFingerprints":{"codehealthFindingId/v1":"ca56f4624b99a45f48366c00f6b4038dc8e69784ba004dd7379aa322986389a1"}},{"ruleId":"D17","level":"warning","message":{"text":"XxxComment: %% XXX we should get this to report_status somehow, but it\u0027s a bit tricky right now \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":2015}}}],"partialFingerprints":{"codehealthFindingId/v1":"a6aac370461b571a87a19750a76d00bf6d2a03451e275007495fa993a0bd4d5e"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: when purchasing multiple packets, is the best SNR/RSSI \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":2321}}}],"partialFingerprints":{"codehealthFindingId/v1":"55f02cb2fe500792d4708e2b3ffd06c7e78b9fea650782484faf153a7dd16595"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% ToDo: Our goal is for Plan data to be retrieved from chain var \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_worker.erl"},"region":{"startLine":2345}}}],"partialFingerprints":{"codehealthFindingId/v1":"61d631258347a1cf4198328d8ae699125ef0dc62540322fe8c2ee69cbf46f196"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: % TODO: I dont think we should be doing this? let the device worker decide \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_routing.erl"},"region":{"startLine":1120}}}],"partialFingerprints":{"codehealthFindingId/v1":"b230796457ad0685d6886eaa0b1b4b908c98f23464a0c329978ef13275cefca4"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Maybe make this a ets table to avoid lookups all the time \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_devaddr.erl"},"region":{"startLine":113}}}],"partialFingerprints":{"codehealthFindingId/v1":"e25843c138023d32a1d34e5752c0980bb47ceb232a376ba5c535649aa7faf11d"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: improve this maybe? \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device_cache.erl"},"region":{"startLine":138}}}],"partialFingerprints":{"codehealthFindingId/v1":"e60b565659f4bf7e127905dae90e694c08f14547e4c24c4cc306158365d2b901"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO promote \u0060rx_delay\u0027 out of \u0060metadata\u0027, so metadata can \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/device/router_device.erl"},"region":{"startLine":320}}}],"partialFingerprints":{"codehealthFindingId/v1":"01e26df54cf5031c9b40fe20eb9dc4100fd1ef67b150f458070d3387c9eed29c"}},{"ruleId":"D17","level":"warning","message":{"text":"XxxComment: %% XXX assume AS923 form \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_lorawan_handler_test.erl"},"region":{"startLine":232}}}],"partialFingerprints":{"codehealthFindingId/v1":"45c3d624947608c6a2166d9077b0c20794f67272d4eb9e5b93524ea2863a3417"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO: Kill single grpcbox server rather than entire app. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_ics_eui_worker_SUITE.erl"},"region":{"startLine":701}}}],"partialFingerprints":{"codehealthFindingId/v1":"554eeaf982cfc48f10bb93db3e182dae5c82cb7e48b2eb34fafca25ddcc353f7"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_channel_aws_SUITE.erl"},"region":{"startLine":53}}}],"partialFingerprints":{"codehealthFindingId/v1":"c7b873a3032a5fac644d459ae87ef8b5e335bdfdd708eedd7f38b4f3a9d6ddb0"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO uncomment if testing against other regions. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_SUITE.erl"},"region":{"startLine":2933}}}],"partialFingerprints":{"codehealthFindingId/v1":"c56b25024aa0abc192f07556c1a8662e2afc6c862e2f70c47813b0465a86477f"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO uncomment if testing against other regions. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_SUITE.erl"},"region":{"startLine":3041}}}],"partialFingerprints":{"codehealthFindingId/v1":"41a64d78b324bf322fcbe89c8cd07b523ce497c1914a03fb8399fd62b1702943"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO uncomment if testing against other regions. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_SUITE.erl"},"region":{"startLine":3123}}}],"partialFingerprints":{"codehealthFindingId/v1":"674b851e1ee3cd0c77e1103be1568bb45a1d503375c20e9b1faf4652abe7efb1"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO uncomment if testing against other regions. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_SUITE.erl"},"region":{"startLine":3187}}}],"partialFingerprints":{"codehealthFindingId/v1":"326b6cc8b45aa3eec0b32c959dc058a99125fa47fb00cdbaccd29e9a8127b9ca"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: %% TODO uncomment if testing against other regions. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060% REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"test/router_SUITE.erl"},"region":{"startLine":3301}}}],"partialFingerprints":{"codehealthFindingId/v1":"a0aad5402890c8ee22f8ad0a31b24f0719f7098c0d818772d16e6d8f409fca5d"}},{"ruleId":"D20","level":"note","message":{"text":"No ADRs found: No ADRs found. No recognised ADR directory (\u0060docs/adr/\u0060, \u0060docs/decisions/\u0060, \u0060adr/\u0060, \u0060docs/rfcs/\u0060, an \u0060ADR0001/\u0060 folder, or their siblings) exists anywhere in this tree. What was searched, so you can tell an empty log from a search that missed one: every directory under the tree (build output, dependencies and VCS metadata excepted), for a document that is either any non-index page inside a recognised ADR directory, whatever its name and however deeply nested (\u0060docs/adr/use-postgres.md\u0060, \u0060docs/adr/2024/0001-x.md\u0060); or a file anywhere whose name is ADR-shaped (\u00600001-use-postgres.md\u0060, \u0060adr-012-caching.md\u0060); or, when neither turned anything up, a document carrying the decision-record signature (an \u0022Architecture Decision Record\u0022 heading, or Status / Context / Decision / Consequences as section headings). A decision log that clears none of these \u2014 unnumbered files outside any recognised directory, without those headings \u2014 is not seen by this check and this row is then wrong. If that is your case, say so rather than renaming anything; otherwise, consider recording architectural decisions in \u0060docs/adr/\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d2bea044ff79d7d275f5a91a6e2f548586178eaf480274c33960ad020c854631"}},{"ruleId":"D26","level":"note","message":{"text":"Projects may be oversized for their cohesion: 1 of 1 project(s) overshoot their size bounds, lowering Project Cohesion to 0.0/10. The most over is \u0060(repository root)\u0060 (22076 LoC, 536 public types across 9 directories). Review these for cohesion \u2014 draw the boundary inside the module first (group each responsibility into its own package or directory and keep the cross-boundary members non-public), since splitting a published package moves types between packages and breaks consumers."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d5a94650dc74886a0f1f08eb9fb6775f1fc395279ef7e901c970c9d26f767a72"}},{"ruleId":"D28","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"2766b276434652c32f376ba507a0c858f6f8948f8edc18e9457086a1a1e15e01"},"properties":{"commitSha":"9c53847c577ac4220cc14658f35463c9864ef3d2"}},{"ruleId":"D28","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"bac747558c395bf543044c854a14f5b0780c38e7926fa99b7b55389c0f1d36b2"}},{"ruleId":"D28","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3cdfd7beb31b791ae18dcb425e21eb157c842e7bbcd522cc330573c1a6538db1"}},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"1542ac657294a7960a3ca68607ef7a17d9ed3d2457fb06dcd777067445c6a3cf"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"899d3700ebd8b85e804fcd7e38cb97e700f4fa8388214641b42213c781137375"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"85b18aba1ee67c8d876d9a65fefa6d7c721aa6c1118d89c488f9b202b95f0b4d"},"taxa":[{"id":"CWE-522","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-829","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a821222cd3b5d13eda72de3afee13229183f297095c7cb07f672e42ed68a3c1a"},"taxa":[{"id":"CWE-522","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-829","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"85dc2f68e5ffaefd67351e32b297c2b197d9d13b2cf8bc10f26f46851e53b956"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3bf89289f27397dd08adfd9858b2ff5c0e64d138d9ef5ccce80d9c648073154d"},"taxa":[{"id":"CWE-522","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-829","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3072005c439a50b4d15e4eb101ec2233c2ca5714442dd8e49a3bf34e4890f93e"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"dc188d5fc5e4f77555a7588b11bffa6824b7e6929f587ec28829d7b08db9e319"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"c0b3d3f0fa6bd7e02ab481cc571853652a33ece93ae0d6f759303aaeed7af084"},"taxa":[{"id":"CWE-522","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-829","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a945f2f47fd4ecdb4891703f683a196ef6cca329b4c0ff5cc3acb6848ae2df51"},"taxa":[{"id":"CWE-522","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-829","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a62949cf620a632128feb4dfe7cd6c02658f5b2871d461ae1ea976f6cffcaab9"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0c9b7062ff2570529693c7a6c6b3652920b327bf1ddb4553a1781d2ac0dedca7"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"30437bf4ec951a56485af00fc53f232eaca9823354f3702d3ea10136e8dc1c94"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0e742b38d338045bbd7cefeb5c0d2e5574e74ca8989bb119bf76df69899c4a9e"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"c98b9b97919003d5f61034eb9b717e6ea89253211b430c2cfcf2ec6aef2c8ab9"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"9e94e76097395cbb5fb0d23d5d5895349ad2104371f50bf7b07c7ef7416b91a5"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"73137bc9d7aa8441788812001343243ba9e8b9c855276a3ffb8ea2a92a96305f"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"45a7a3c296d604d089618ecc3c420a6686670e223d2fb39fcf9d29e5da0b6980"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"bc6fca571a2716cf11b412514510a6374238c183bfffcba3af59cd030d44e675"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"1bd559ab645f128cc7d06706045b5de42a0f78c2801f5b81a530047e036b61b0"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a064487a051e6e65048327c180326f5e316a0c57faf50afc3e5a0b8e3bec933c"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0c9340a68977f04b4bb4a8a41cad77aa687c39bb01aaa400ad818e3784168712"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"b98cbb8f083f720b982911a0578b63b23762e12929c81ab96af22d37fcc4642a"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"f3cd19f8c41613e5c876e7aae5f130878e8ef49928da95d098e878e9c8208b65"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"c3e24534085ed87ce1423fb5b2c749e17f719d3abe8d0590e70dffefc9ca0369"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"6cd6644e20b2073c6faf89ecc367a0f9ea12b814297962bb869834c9898c2d63"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"2023e577000973fecdfda812fd5d39d8d264da1aab2188383c7c68c34bee1aa1"},"taxa":[{"id":"CWE-1104","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-1329","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"b52f2cc8fd96cefabc3fd530a76a221078a58d54272af2d0d4560aa878709b64"},"taxa":[{"id":"CWE-1104","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-1329","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"d22c02299a6b4de3a6d31ab8c105771a164ec609593ba8930a2a2e01d4bac387"},"taxa":[{"id":"CWE-1104","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-1329","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D30","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"f08f839e9efa15ab6ae49efa55f0ddf14878887eb78c293fc4d01a5c0254634d"},"properties":{"dependency":{"package":"cowlib","version":"2.11.0","advisory":"[GHSA redacted]","aliases":["[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","[GHSA redacted]","[GHSA redacted]","[GHSA redacted]","[GHSA redacted]"],"reachability":{"kind":"unknown"}}}},{"ruleId":"D30","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a9e4b689384b6f8bcfac83dad0238182def3cdb7d6c8e5e23915756d30f52343"},"properties":{"dependency":{"package":"hackney","version":"1.18.1","advisory":"[GHSA redacted]","aliases":["[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","EEF-[CVE redacted]","[GHSA redacted]","[GHSA redacted]","[GHSA redacted]","[GHSA redacted]","[GHSA redacted]"],"reachability":{"kind":"unknown"}}}},{"ruleId":"D30","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"d0644a58ea4c9b9ccc706d004691ecaef1c14e2778efa12f7f34fcd82153e5b5"},"properties":{"dependency":{"package":"gun","version":"e1b5e14139e2a936ad6561bf960f70f1e80b81e2","advisory":"[GHSA redacted]","aliases":["[CVE redacted]","EEF-[CVE redacted]"],"reachability":{"kind":"unknown"}}}},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"fe2d688610b51e0a5a02c7c5dd1724a4986e40f2689fb84510e2ec0164c27d6a"}},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"dc76998bbb35e6722b3ee754f17cc853871edf73a71346c027ccae34c86b00a6"}},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"6c9bd328f1425e4185802e2cb388fc5dec17b2da92bc5227fa43622d89e747d7"}},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"be9c57e2fb625c43c271d051f76b97f27b6976f4ec358ef8fea1d9cb5205f460"},"taxa":[{"id":"CWE-494","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"78bca5db63bd94de44fa71ba81c3511aea03a6f3943bb925ab0d3538996f33df"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"93b1d17dad2208d2221d8563ad4cf4134c1bd546b8934ab343eb1cca3ac90cc2"},"taxa":[{"id":"CWE-494","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"797e008ba8139007f7b20e9f0d894779d890eed6d72aaef7150e6b7eca0d7b0c"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"09851e203c020987e5f9f32b211981acc9f24d0fca24ce7570df088beae23b3c"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"ebf688b9c6aeee54200b70b6126d1e69abbc4acbb56f79d05a0f4e308e3aec76"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"ea1710c4aaffef54d0746bdf8ceb13467fc1bc4265440e2f4eee1a9fe2c02675"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"fba361726bb541a9806b2bc175923665c63e5adf68e9f1792cb2021a0ab4aaa1"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"71cf9d39ff7b5b45700ec1dbf61e8c7c93ff10ae677bc44aecfad12f7334d5fb"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"8c1f6fa5ddb9c8baa15e4daa8cc7d82357b45d2982086717b7ce108453472cc9"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"c8c91bc0af5e8b7d9f0c4696adccc6dedbd781820fea01f0988e584a35ea8cd8"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"98c5616b11be6616a7f53d6c2e5ce1fb71f8de376ff93756bbb4f083e581aa33"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"ab4efbb332ca40b9942e6ede3f68315c359c9ca9a3bcd1ce282fb856dcb7f445"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3023303e151b1b62b71da70aacf4e01cf206d45c3d2075885b1a50d55a06fc00"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0df5ced7ef41150e25c39f7074f9f096fd763fa7ee1c88ed58e27457584d6571"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"12f9847fb5ebcbd0cf33055a5441d5ea566a804fa18429f27cee424b026a53e2"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"error","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"c7cbf63c0e90ef7ba5d8c7e30fbafbf372999f7899bf4ae0b7ad604c6e203310"},"taxa":[{"id":"CWE-250","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-653","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"5cfed0ee4e80785ce23c7083cffdead9acc6c64f9dce56a00ca7178bd3d7bee5"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"2ff21f85a8c15f83be96620f915e546555901991b73838dd545e4016636ad9a4"}},{"ruleId":"D31","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"47538c0ee4a44718440a488054e5bf59aa52af08d70ef0165f7965b015a3869a"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"282bb84b27a7c0ccaa12b25714ed2545fa75c8702c171dd8b9d34d649b2fbc22"},"taxa":[{"id":"CWE-1357","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-353","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"4da9ce95cb4e3fb935016a4ccaede62426c7c621b68503a3a5b747b35c3b2d0d"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0299a4102dab078d6d0cc91d9a4530c0b5155f31d096ec3f0fdaf797f35cb79a"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"a4ded31401cb44f8cf8186b390b44ba2d706550881c6cbc3249c10aedaf4a524"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"33788730a47f5a9203d379a4b1193638992bd9addb315e20f95830dd69747d72"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3b64f2dd9bac8ea4c3c2b9b6f006fe2ffe01675b9b035fee425e49ee015e8d84"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"8f2c190d14216b2beb114c8d139304c7541edf1469962dbc923224ddc647cc4f"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"035f940d017b214a3f968b76ef93705944bd6279a2b27cb6900c943f0cc716af"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"808fa2bc9894e1eb95bbd6ab30978cae88069c09f3a11162f63ed7ea546cd73c"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"3bc74027d57f7f73a7ad400018409e4f881737ba050e885d5e1814930c7b37b5"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"5ed67d4debf5bd78f64f6e65a8ab23455e9443da9b3aec654fb8405e99b219ab"}},{"ruleId":"D31","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"5c2e423879aef415b630be67f2119a08bc93d234b5d59a604e1522e24fa9149e"}},{"ruleId":"D34","level":"error","message":{"text":"Orphaned knowledge: No living knowledge remains for this large file \u2014 its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/router_xor_filter_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"e6099b559a8fefeee84d2ddf45106b861a97b2afbd0bf75f254b644e3822b023"}},{"ruleId":"D34","level":"error","message":{"text":"Orphaned knowledge: No living knowledge remains for this large file \u2014 its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_skf_worker.erl"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"3a38db3af994b43e951c36339d3d0c7a7f67f1af438215a3b496f2edc7091d99"}},{"ruleId":"D34","level":"note","message":{"text":"Further orphaned files (smaller): 10 smaller file(s) also have no living knowledge \u2014 folded into the freshness score and metrics rather than raised one row each \u2014 most significant first: src/channels/router_iot_central_connection.erl, src/cli/router_cli_device_worker.erl, src/channels/router_channel_utils.erl, src/cli/router_cli_xor_filter.erl, src/channels/router_iot_hub_connection.erl, src/channels/router_iot_central_channel.erl, src/channels/router_iot_hub_channel.erl, src/lora/lorawan_rxdelay.erl (and 2 more) (12 orphaned of 54 analysed files in total, counted over production source files of roughly 2,400 bytes or more, excluding vendored, generated and example/demo trees and test files identified by path convention, largest first; 54 of the 72 production source files in this repository met that bar). Attach the read to the next change that touches one of them: have a second person review that change, and leave behind a short comment or test recording what the file is for, so the knowledge comes back at the cost of a change you were making anyway."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"ce861fd78f6935114d3a342cb90ad25870f984e1042954fcbbe27c0e23be3658"}},{"ruleId":"D36","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"1b213f6eedd4b140d0bc37bdf1496f72811a643f34064f12518b32e9e83bcfc7"}},{"ruleId":"D36","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0e17f71490e4d120a48b2b2881ab866c93b272bef2febb673a3e8e42b2c288ab"}},{"ruleId":"D36","level":"note","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"eb00976a698a5d68999b7ee6d27206fd374e916853e7ff1ead5eed42386f043f"}},{"ruleId":"D36","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"90f83b4fa27db32740afe9540c905f3c0499caed87f61049a8a903ecc95b41c3"}},{"ruleId":"D36","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"9658270ba49f37ed04e99ab1263b6393cd42aed8bdfb7aafd9fa1070f5491895"}},{"ruleId":"ED1","level":"warning","message":{"text":"Handler temporal coupling: router_console_api clause \u0060handle_info/2#643\u0060: \u0060router_console_api\u0060 clause \u0060handle_info/2#643\u0060 blocks the process on a synchronous outbound I/O client call (a remote HTTP request, a socket receive, or a blocking pool checkout) awaited inline while handling a message \u2014 the process is blocked (holding its mailbox) until a peer replies or the sleep elapses. That couples this handler in real time to another process being up and fast, and a mutual call can DEADLOCK. To decouple, issue the request off the hot path \u2014 reply asynchronously and do the I/O in a throwaway spawned worker (or use the async client API), so the process keeps serving its mailbox."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":998}}}],"partialFingerprints":{"codehealthFindingId/v1":"b7cc73ba6388510c69522ce3c49cb42147088aa9ea0fab16604292639c910f47"}},{"ruleId":"ED1","level":"warning","message":{"text":"Handler temporal coupling: router_http_channel clause \u0060handle_event/2#55\u0060: \u0060router_http_channel\u0060 clause \u0060handle_event/2#55\u0060 blocks the process on a synchronous outbound I/O client call (a remote HTTP request, a socket receive, or a blocking pool checkout) awaited inline while handling a message \u2014 the process is blocked (holding its mailbox) until a peer replies or the sleep elapses. That couples this handler in real time to another process being up and fast, and a mutual call can DEADLOCK. To decouple, issue the request off the hot path \u2014 reply asynchronously and do the I/O in a throwaway spawned worker (or use the async client API), so the process keeps serving its mailbox."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_http_channel.erl"},"region":{"startLine":164}}}],"partialFingerprints":{"codehealthFindingId/v1":"f733ebfe5e8976758832b593f89f84447f113146b5900cdf673ce6daa5625605"}},{"ruleId":"ED1","level":"warning","message":{"text":"Handler temporal coupling: router_http_channel clause \u0060handle_event/2#62\u0060: \u0060router_http_channel\u0060 clause \u0060handle_event/2#62\u0060 blocks the process on a synchronous outbound I/O client call (a remote HTTP request, a socket receive, or a blocking pool checkout) awaited inline while handling a message \u2014 the process is blocked (holding its mailbox) until a peer replies or the sleep elapses. That couples this handler in real time to another process being up and fast, and a mutual call can DEADLOCK. To decouple, issue the request off the hot path \u2014 reply asynchronously and do the I/O in a throwaway spawned worker (or use the async client API), so the process keeps serving its mailbox."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_http_channel.erl"},"region":{"startLine":164}}}],"partialFingerprints":{"codehealthFindingId/v1":"0c87a2ac36efb1f4215bb7f9d13eae0ce6a5f96919a153bebe0c3f90e4103082"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_aws_channel.erl"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"30852d6a3d00833f22ba2332e9dc36b09cd8d72ec5df0018984d4c7d1cf515f9"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_http_channel.erl"},"region":{"startLine":69}}}],"partialFingerprints":{"codehealthFindingId/v1":"e7e8cbb7821e9e76068914d33021c11ceacaf5fffa0f4b55f4935d0f41e1eade"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_channel.erl"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"27038e1beacdb3c275227f1843e0a959a85b06c8c76381e5e97e53bd6b489a30"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_hub_channel.erl"},"region":{"startLine":71}}}],"partialFingerprints":{"codehealthFindingId/v1":"6794f11663897ecf56420f01f73cfea9722d303758936ec8cf7d81119637ce24"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_mqtt_channel.erl"},"region":{"startLine":84}}}],"partialFingerprints":{"codehealthFindingId/v1":"77f1ca47c1124966ca1e79696ddd6759672131e5d665c42e3a2fcc6cff52d94b"}},{"ruleId":"ED2","level":"warning","message":{"text":"Command with competing owners: update: \u0060update\u0060 is shaped like a command (one imperative intent) but is handled synchronously by more than one module \u2014 a command should have exactly one owning handler. Split the responsibilities, or raise an EVENT after the command and let the others subscribe."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/grpc/router_ics_eui_worker.erl"},"region":{"startLine":144}}}],"partialFingerprints":{"codehealthFindingId/v1":"120431bae33517f6bbbfda20e9343c34b64fe4fb165cb596b49f0e01064335bd"}},{"ruleId":"M2","level":"note","message":{"text":"No ADRs: No Architecture Decision Records found \u2014 no conventional ADR directory, no numbered \u0060NNNN-title\u0060 documents in any markup this check reads, and nothing ADR-shaped by content. Design rationale recorded elsewhere (a design-notes tree, a mailing list, pull-request discussion) is not visible to this check and is not re-findable per decision, so a future maintainer cannot ask why one choice was made and get an answer."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"670b3d6e36a756d63097d0dfbf90afd5fc761308800b9354894a07c3f4e4aa14"}},{"ruleId":"P4","level":"note","message":{"text":"No rollback/health safety: Deployment is orchestrated by compose, but no service declares a \u0060healthcheck:\u0060 and nothing pins a previous image to fall back to \u2014 the runtime can tell that the container is up, not that it is serving, so a bad release is harder to detect and reverse."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"db6bab8a28a2145f47e5a4e6683cda39d2ba0296c723238e8057da979ae1c706"}},{"ruleId":"P6","level":"note","message":{"text":"No changelog: No CHANGELOG/HISTORY/RELEASES file \u2014 what shipped when isn\u0027t easy to reconstruct for support or audit. (Versioning/tagging makes releases traceable, but a changelog records the what.)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"dda5aa5aed8cbb292c3ef2b733bc138f614293ae6426c85e98bf31ef330d9415"}},{"ruleId":"P7","level":"warning","message":{"text":"Outbound HTTP without resilience: \u0060hackney:post(\u0060 makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service\u0027s request, thread or connection until the call gives up on its own \u2014 or never, for a client with no default timeout. 3 of the 4 files that make outbound calls are unbounded; the first 3 are listed."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/apis/router_console_api.erl"},"region":{"startLine":229}}}],"partialFingerprints":{"codehealthFindingId/v1":"6151b1b179c9baa759b38f17e425e1201c94041e01c522e730d5c483e8c93eff"}},{"ruleId":"P7","level":"warning","message":{"text":"Outbound HTTP without resilience: \u0060hackney:get(\u0060 makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service\u0027s request, thread or connection until the call gives up on its own \u2014 or never, for a client with no default timeout."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_central_connection.erl"},"region":{"startLine":299}}}],"partialFingerprints":{"codehealthFindingId/v1":"d2bde05a70b5d83c7e54f46acce183ea9f7e3772b0aa0e835fe3fa3c8491b1be"}},{"ruleId":"P7","level":"warning","message":{"text":"Outbound HTTP without resilience: \u0060hackney:get(\u0060 makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service\u0027s request, thread or connection until the call gives up on its own \u2014 or never, for a client with no default timeout."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/channels/router_iot_hub_connection.erl"},"region":{"startLine":243}}}],"partialFingerprints":{"codehealthFindingId/v1":"a01601219d8aa20d5ee5a934bf0f7808410be9199fb1ee0288332ebfe116c130"}}],"taxonomies":[{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d","organization":"MITRE","informationUri":"https://cwe.mitre.org/","isComprehensive":false,"shortDescription":{"text":"The MITRE Common Weakness Enumeration (CWE)."},"taxa":[{"id":"CWE-1032","guid":"5f21e517-68aa-a650-9a25-5771ef024637","name":"OWASP Top Ten \u2014 Security Misconfiguration category","shortDescription":{"text":"OWASP Top Ten \u2014 Security Misconfiguration category"},"helpUri":"https://cwe.mitre.org/data/definitions/1032.html"},{"id":"CWE-1104","guid":"4c918cb5-b2a6-6c55-9963-a44ee464305e","name":"CWE-1104","shortDescription":{"text":"CWE-1104"},"helpUri":"https://cwe.mitre.org/data/definitions/1104.html"},{"id":"CWE-1329","guid":"f70f1c3f-4ccf-cb5e-bdd3-03ba4868d36d","name":"CWE-1329","shortDescription":{"text":"CWE-1329"},"helpUri":"https://cwe.mitre.org/data/definitions/1329.html"},{"id":"CWE-1357","guid":"e4d2e772-757e-0a5c-bd7d-77052949d866","name":"Reliance on Insufficiently Trustworthy Component","shortDescription":{"text":"Reliance on Insufficiently Trustworthy Component"},"helpUri":"https://cwe.mitre.org/data/definitions/1357.html"},{"id":"CWE-1395","guid":"800e09e7-c11a-8654-9fa6-86f398995fed","name":"Dependency on Vulnerable Third-Party Component","shortDescription":{"text":"Dependency on Vulnerable Third-Party Component"},"helpUri":"https://cwe.mitre.org/data/definitions/1395.html"},{"id":"CWE-16","guid":"659db3ea-affc-8453-8add-c1218fbfcb92","name":"Configuration","shortDescription":{"text":"Configuration"},"helpUri":"https://cwe.mitre.org/data/definitions/16.html"},{"id":"CWE-250","guid":"52ee12e8-390a-7351-b1e6-388afa694e54","name":"CWE-250","shortDescription":{"text":"CWE-250"},"helpUri":"https://cwe.mitre.org/data/definitions/250.html"},{"id":"CWE-259","guid":"ae9ad959-fbb6-9d5e-892d-3dca66da0b69","name":"Use of Hard-coded Password","shortDescription":{"text":"Use of Hard-coded Password"},"helpUri":"https://cwe.mitre.org/data/definitions/259.html"},{"id":"CWE-353","guid":"09d7e902-d4ee-f05d-ae6c-0a1554d0c18f","name":"CWE-353","shortDescription":{"text":"CWE-353"},"helpUri":"https://cwe.mitre.org/data/definitions/353.html"},{"id":"CWE-494","guid":"b8a65e0d-e459-4a55-a931-fc1136482375","name":"Download of Code Without Integrity Check","shortDescription":{"text":"Download of Code Without Integrity Check"},"helpUri":"https://cwe.mitre.org/data/definitions/494.html"},{"id":"CWE-506","guid":"401d6455-56e3-0552-9a39-f77461673e3f","name":"CWE-506","shortDescription":{"text":"CWE-506"},"helpUri":"https://cwe.mitre.org/data/definitions/506.html"},{"id":"CWE-522","guid":"71fb233e-ce6a-ae57-9419-ef8373540b09","name":"CWE-522","shortDescription":{"text":"CWE-522"},"helpUri":"https://cwe.mitre.org/data/definitions/522.html"},{"id":"CWE-653","guid":"aa3e371b-590e-225d-a56c-cd490a1dca63","name":"CWE-653","shortDescription":{"text":"CWE-653"},"helpUri":"https://cwe.mitre.org/data/definitions/653.html"},{"id":"CWE-732","guid":"1da27e8f-b330-7650-ab63-bd61953eae5d","name":"Incorrect Permission Assignment for Critical Resource","shortDescription":{"text":"Incorrect Permission Assignment for Critical Resource"},"helpUri":"https://cwe.mitre.org/data/definitions/732.html"},{"id":"CWE-77","guid":"332c8ade-6612-9f56-a06b-d8d90b1a8750","name":"Command Injection","shortDescription":{"text":"Command Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/77.html"},{"id":"CWE-78","guid":"2e31ceaf-c7ae-2e5e-9661-cfb1362789cf","name":"OS Command Injection","shortDescription":{"text":"OS Command Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/78.html"},{"id":"CWE-79","guid":"fd45580b-e8c4-fc5e-8c2f-aa8fab0b4dbf","name":"Cross-site Scripting (XSS)","shortDescription":{"text":"Cross-site Scripting (XSS)"},"helpUri":"https://cwe.mitre.org/data/definitions/79.html"},{"id":"CWE-798","guid":"5e8f057d-fee3-995a-a0cb-9fc5b0d174d1","name":"Use of Hard-coded Credentials","shortDescription":{"text":"Use of Hard-coded Credentials"},"helpUri":"https://cwe.mitre.org/data/definitions/798.html"},{"id":"CWE-829","guid":"13c33925-97fb-5a5e-b40c-56d328b8a4d7","name":"CWE-829","shortDescription":{"text":"CWE-829"},"helpUri":"https://cwe.mitre.org/data/definitions/829.html"},{"id":"CWE-89","guid":"6d08fdad-37eb-c150-bbf0-d7d946863407","name":"SQL Injection","shortDescription":{"text":"SQL Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/89.html"},{"id":"CWE-937","guid":"16f316ae-415c-b354-a59b-1f7905f756e9","name":"Using Components with Known Vulnerabilities","shortDescription":{"text":"Using Components with Known Vulnerabilities"},"helpUri":"https://cwe.mitre.org/data/definitions/937.html"},{"id":"CWE-94","guid":"75e7f50c-6c2f-dd52-bf40-bf6c52b861fd","name":"Code Injection","shortDescription":{"text":"Code Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/94.html"}]}],"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":75,"secretScannerRunsExcluded":0}},"redactionTokens":["A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."]}]}