{"$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":"D11","name":"Test Reliability","shortDescription":{"text":"Test Reliability"},"helpUri":"https://codehealth.canine.dev/dimensions/D11"},{"id":"D12","name":"Dependency Hygiene","shortDescription":{"text":"Dependency Hygiene"},"helpUri":"https://codehealth.canine.dev/dimensions/D12"},{"id":"D13","name":"Secret Scanning","shortDescription":{"text":"Secret Scanning"},"helpUri":"https://codehealth.canine.dev/dimensions/D13","relationships":[{"target":{"id":"CWE-798","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"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":"D21","name":"Naming Consistency","shortDescription":{"text":"Naming Consistency"},"helpUri":"https://codehealth.canine.dev/dimensions/D21"},{"id":"D22","name":"Internal API Consistency","shortDescription":{"text":"Internal API Consistency"},"helpUri":"https://codehealth.canine.dev/dimensions/D22"},{"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":"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":"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":"AC3","name":"Page structure","shortDescription":{"text":"Page structure"},"helpUri":"https://codehealth.canine.dev/dimensions/AC3"},{"id":"AC7","name":"A11y enforcement","shortDescription":{"text":"A11y enforcement"},"helpUri":"https://codehealth.canine.dev/dimensions/AC7"},{"id":"AX10","name":"Code composition","shortDescription":{"text":"Code composition"},"helpUri":"https://codehealth.canine.dev/dimensions/AX10"},{"id":"AXB2","name":"Runtime readiness","shortDescription":{"text":"Runtime readiness"},"helpUri":"https://codehealth.canine.dev/dimensions/AXB2"},{"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":"P3","name":"Security \u0026 performance tooling","shortDescription":{"text":"Security \u0026 performance tooling"},"helpUri":"https://codehealth.canine.dev/dimensions/P3"},{"id":"P6","name":"Release Hygiene","shortDescription":{"text":"Release Hygiene"},"helpUri":"https://codehealth.canine.dev/dimensions/P6"},{"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":"Mapper.devise_for (cyclomatic 20): Mapper.devise_for has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"lib/devise/rails/routes.rb"},"region":{"startLine":226}}}],"partialFingerprints":{"codehealthFindingId/v1":"2e67c9066bdf38f91d58a09ae5e55bf6a2bfdaf96b96c7fb571d8e2e726cb997"}},{"ruleId":"D2","level":"warning","message":{"text":"Mapper.devise_for (cognitive 24): Mapper.devise_for has cognitive complexity 24 (threshold 15). Drivers by points: if/else 9 (13 pts), boolean chains 8, error handling 2 (3 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"lib/devise/rails/routes.rb"},"region":{"startLine":226}}}],"partialFingerprints":{"codehealthFindingId/v1":"0773f91df99ec01d20807433337f5d5be6b628af2fa7c50297bc8e3399797838"}},{"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: app/controllers/devise/registrations_controller.rb, app/controllers/devise/passwords_controller.rb. Pair on, review, or document these before any departure."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d202c3cac4602bff40253a08267f391df672aca83230fb72b66a3b5bf300399f"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: use \u0060error_status\u0060 when the default changes to \u0060:unprocessable_entity\u0060 / \u0060:unprocessable_content\u0060. \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":"app/controllers/devise/unlocks_controller.rb"},"region":{"startLine":32}}}],"partialFingerprints":{"codehealthFindingId/v1":"ffa0de40eed680642aaea432a919d57c389853ede609a8912672c2653f094601"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: use \u0060error_status\u0060 when the default changes to \u0060:unprocessable_entity\u0060 / \u0060:unprocessable_content\u0060. \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":"app/controllers/devise/confirmations_controller.rb"},"region":{"startLine":30}}}],"partialFingerprints":{"codehealthFindingId/v1":"ab045e9ecd107a1eca141074607acee1805f94d84b729b8eaa3523aedd362ad1"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: Remove AS::Dependencies usage when dropping support to Rails \u003C 7. \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":"lib/devise.rb"},"region":{"startLine":327}}}],"partialFingerprints":{"codehealthFindingId/v1":"396bedbda077818a2364c69b317c95fd311e39e541f546079ddd7495e5b5c677"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: Remove AS::Dependencies usage when dropping support to Rails \u003C 7. \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":"lib/devise.rb"},"region":{"startLine":337}}}],"partialFingerprints":{"codehealthFindingId/v1":"a4149dab077ecc19155d6cc8b4cd93f906e25e261bb4f6bd678e0fa2b1d35122"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: Remove the fallback and just use \u0060downcase_first\u0060 once we drop support for Rails 7.0. \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":"lib/devise/failure_app.rb"},"region":{"startLine":115}}}],"partialFingerprints":{"codehealthFindingId/v1":"d0a5e9533404615898e62de7a563e057a70082fe9199eb15c6544073623cf330"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: remove this support for older Rails versions, which aren\u0027t supported by Turbo \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":"lib/devise/controllers/responder.rb"},"region":{"startLine":12}}}],"partialFingerprints":{"codehealthFindingId/v1":"d9690cdca37e18f1fd81ffe607f17c50a0d0c285a58e7de7c183e02d91f61868"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: Normalize the JSON type coercion along with the Timeoutable hook \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":"lib/devise/models/rememberable.rb"},"region":{"startLine":104}}}],"partialFingerprints":{"codehealthFindingId/v1":"66db0fdbdbdb6907cfd7d64a1a07dbd69fa59414ffa9d128807730f147db7964"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: replace above lines with \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":"lib/devise/models/confirmable.rb"},"region":{"startLine":350}}}],"partialFingerprints":{"codehealthFindingId/v1":"f6014b18cfeb7d9e0fe0b728cff9a9f472b2754bd47f4bfe9a83efd610bb4fc1"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: # TODO: remove conditional/else when supporting only responders 3.1\u002B \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/failure_app_test.rb"},"region":{"startLine":415}}}],"partialFingerprints":{"codehealthFindingId/v1":"d85d40fa18dd454c73ea52a5739b9b112b9c0d1631bba78736adef1409ccdf62"}},{"ruleId":"D22","level":"warning","message":{"text":"Ambiguous naming: \u0027resend\u0027 implies re-sending an existing token or retrying a failed send, while \u0027send\u0027 implies initial generation and sending. However, in the context of Confirmable, both often trigger the same underlying mailer action (confirmation_instructions) but may differ in whether they reset the confirmation token or just re-send. The distinction is not immediately obvious from the names alone, and \u0027resend\u0027 is often a user-facing alias for \u0027send again\u0027.: Clarify intent: If \u0027resend\u0027 is strictly for re-sending without token reset, keep both but ensure documentation is clear. If they are functionally identical in most use cases, consider unifying or naming one \u0027send_confirmation\u0027 and the other \u0027resend_confirmation_with_new_token\u0027 if that is the differentiator. Currently, the distinction is subtle and relies on internal state (confirmed? vs unconfirmed?). A clearer name for the initial send might be \u0027send_confirmation_instructions\u0027 and for the retry \u0027resend_confirmation_instructions\u0027, which is what is done, but the overlap in purpose (triggering the email) is high. (signatures: Devise.Models.Confirmable.send_confirmation_instructions() | Devise.Models.Confirmable.resend_confirmation_instructions())"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"2ffff0b95c2866a4434d21a215c15a201040322553ce47edcce6a9bcd15572fb"}},{"ruleId":"D22","level":"warning","message":{"text":"Same ambiguity as Confirmable. \u0027send\u0027 vs \u0027resend\u0027 for unlock instructions. Does \u0027resend\u0027 generate a new token? If so, it should be explicit. If not, it\u0027s just a re-send. The naming convention mirrors Confirmable, which is consistent internally, but the semantic difference between \u0027send\u0027 (initial) and \u0027resend\u0027 (retry) is often blurred in user interfaces.: Ensure that \u0027resend_unlock_instructions\u0027 explicitly handles the case of a user who didn\u0027t receive the email, potentially generating a new token if the old one expired, whereas \u0027send_unlock_instructions\u0027 might be for the initial lockout notification. If the behavior is identical, consider if one is redundant. (signatures: Devise.Models.Lockable.send_unlock_instructions() | Devise.Models.Lockable.resend_unlock_instructions())"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"dfa268ff45292a752b42e9459012209b33c720eeae311f9ca87a3d49b67cf14f"}},{"ruleId":"D22","level":"warning","message":{"text":"Standard Ruby bang/non-bang convention is used, but in the context of a library API, exposing both can be confusing if the side effects are not strictly about exception handling vs silent failure. Here, it likely refers to whether the update raises an error or returns false on failure. This is a minor inconsistency in naming style compared to other methods like \u0027reset_failed_attempts!\u0027 which only has the bang version.: Consistent use of bang for destructive/raising operations is good. However, if \u0027update_tracked_fields\u0027 is the primary method, the non-bang version might be redundant if the operation is expected to always succeed or if errors are handled elsewhere. Check if \u0027reset_failed_attempts!\u0027 having only a bang version is a pattern that should be applied here for consistency. (signatures: Devise.Models.Trackable.update_tracked_fields(request) | Devise.Models.Trackable.update_tracked_fields!(request))"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"904e0a0e102b862d589aed9cf5dadfb2a35802e46684014c701b3d5e495de36c"}},{"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":"b1535dbb4f3c7d83630f184781af7ca0ba64e48fa2a3c54344b49b1f68ab53d3"},"properties":{"commitSha":"06ebf038e43a777d8e165695ff04c22d4a23d7d9"}},{"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":"d5b8f11381d61a58459ffc7c595fd52d09c03c711894a63a9578043d2338412b"},"taxa":[{"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":"b923d2a6d4bf9f3d17a069114b8d29dce8e6bc49ce4ae2931de0efd9a515de40"},"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":"29068f285a03a274639a391082e8260a1b64df1648d27b887eef44a9ed181603"},"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":"a08337b4da98081f46be7a08c2444a0bcd3444c75e0c97702af5a4068b9d1ca4"},"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":"c7bb6cae27fbea76aa95ac0015e227a051fb9f5975f3cbaffedb1f69946709e3"},"taxa":[{"id":"CWE-601","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":"deb911a12a09f81c10689d338b93e5862f327db3576cd7f69d623a7291538d0b"},"taxa":[{"id":"CWE-601","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":"ec9d5a37f37d11912afc203616cde3f4e3e0192c27dbe4d039f995f2c884db92"},"taxa":[{"id":"CWE-200","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":"7223583a419aaa0ffcea2163558f141608ea2c61edca5d71b4b48a423f0ff470"},"taxa":[{"id":"CWE-200","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":"4af621f9da620d327766c7706fef6c0f1f331422e01a259df45264bf794086b4"},"taxa":[{"id":"CWE-352","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":"86ded1138186bb431f111db86f31199ed3bb7f1ffd5c202eea6a8a8251306826"},"taxa":[{"id":"CWE-650","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":"ae461819b072d908948ee956b74f480a40346bad7474b6a541710c36b71d9573"},"taxa":[{"id":"CWE-396","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-544","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":"15f86022fff30a9c7c158222e9bfe0355a8719d17fdc8b1be06d8196f969848a"},"taxa":[{"id":"CWE-561","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},{"id":"CWE-705","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":"c794c06329725441317ad83b6bfde287f0cb74fa41eb07b9cca567a0b598e50e"}},{"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":"83c4e672988cf61dd0a5ca8608ad3eee293ea388ec09b355ce03ae0ecbdd1507"}},{"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":"16e0a9f8a96f33a3a4bc5d6b2ad8e8b87107a8d4f12df2e0119d16975aeaaed7"}},{"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":"62d2299b66fccf83afe539550f2d9374dc640d95dfd2ce189bdb64fd7898bb9f"}},{"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":"9e842a8521a9d898666a1d5a419a43a27e416322915c05bcbc38ca2d85f70dcd"}},{"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":"2671d2dc5243d2844e58ece392cfd92899b5067cc5e636d13daa8bfc4cef5229"}},{"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":"b4f18185713dadd589204e18b34092146a8b2179a66ccd2fb3a402e5063d4e95"}},{"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":"833a7185174858706a151949e08a56b5367b07ea17a6c5b8941f64f85991be16"}},{"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":"e6a4976e16596ea9bdc6eb7c3e5c192c882e3decfdddc3eed800d0f51839bf28"}},{"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":"e09fed0e38e2bc52024cd0d65bcffa57fef97181f8ca4cf65aef4931c4e653e7"}},{"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":"8a59ecb5c2922e4f2df93f937bfeea94bfa9c447e3a4302954f5e36669dc0003"}},{"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":"177ab06f66e93b6ab2aa6366fd0d2bd6d98cc6a9ba811e56bf86dfbda4bbcbc1"}},{"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":"e656ac3284a0fa24890c64b7c0643e7fcd7e036b129501ad9e081835e4c29bf7"}},{"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":"96451b363cfd080aa2bc1287f88cdf7656fc30267aa0b034ef2fd01fc430ec81"}},{"ruleId":"D30","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":"1f56e8c64a5a07409b219f9d064e24b32d3838f9d390845e64c1914b98d0078c"}},{"ruleId":"D30","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":"a04b349ced306ce5538f8142a6cbe1d3a14d4b9faec1377747a8b8a371eaf2ce"}},{"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":"lib/devise/rails/routes.rb"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"dc2fa76f381c5831e5fb025161fb664d401921b2860dae2d849a241a607333c5"}},{"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: lib/devise/models/authenticatable.rb, lib/devise/models/lockable.rb, lib/devise/strategies/authenticatable.rb, lib/devise/parameter_sanitizer.rb, lib/devise/mapping.rb, lib/generators/devise/views_generator.rb, app/controllers/devise_controller.rb, lib/generators/active_record/devise_generator.rb (and 2 more) (11 orphaned of 24 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; 24 of the 77 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":"AC7","level":"warning","message":{"text":"Accessibility enforcement below the top rung: No accessibility enforcement found \u2014 no automated accessibility check runs over the HTML your app renders. Assert the accessibility invariants over that HTML in the test suite you already have (parse the output and assert, or drive a browser), and gate that test in CI so a regression blocks the merge. What was searched, so you can tell an absence from a miss: the 20 markup file(s) this pass actually assessed, the linter configuration checked in beside them, and this repository\u0027s test and CI files \u2014 matched by name against the accessibility checkers this dimension carries. An audit run outside the repository, a hosted scanner, or a check whose name is not one of those, is not seen here."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d46019b86eff5ddad9db289e6802ac158899e980df54c34f67722442787ead62"}},{"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":"M2","level":"note","message":{"text":"No architecture diagram/doc: No C4/Structurizr/PlantUML/Mermaid/Graphviz/D2 diagram, no drawn diagram named for the architecture, no file named \u0060architecture\u0060 or \u0060design\u0060 in any markup this check reads, and nothing in the README, docs or contributor guides that announces the shape \u2014 no \u0060## Architecture\u0060 heading, no \u0022architecture overview\u0022/\u0022high-level design\u0022 phrasing, no \u0022the architecture is \u2026\u0022 introduction, no guided code tour. A shape laid out in prose that never names itself as the architecture is not visible to this check, and neither is one kept outside the repository, so this row reports the absence of a re-findable shape document \u2014 not evidence that nobody wrote the shape down."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"0c190e7c159d1850ee706c3ac4486e151e8a4fe169de4bf61436b9f399654f06"}},{"ruleId":"M4","level":"note","message":{"text":"README/code drift: README advertises a RAG / ML engine, but no ML/RAG code or dependency exists \u2014 searched for: \u0060rag\u0060, \u0060langchain\u0060, \u0060llamaindex\u0060, \u0060pinecone\u0060, \u0060weaviate\u0060, \u0060qdrant\u0060, \u0060embeddings\u0060. Each was matched case- and separator-insensitively against file and directory NAMES anywhere in the tree, and against the CONTENTS of manifest files (package.json, *.csproj, *.props, *.slnx, *.yml, Dockerfile); the README\u0027s own prose never counts, so a claim is never refuted by merely being made. Nothing outside that search was read \u2014 a footprint living only in a submodule, in a file type not listed here, or under a name none of those terms matches is not seen, and this row is then wrong."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"343bbbd51ceb8de7a9ff88d79f7c797abf9b5921f8727b67b4d0f4f8a22c5e49"}},{"ruleId":"P1","level":"note","message":{"text":"CI build step not evidenced: A CI pipeline exists but no build step was matched \u2014 changes may merge without the build ever running. A build step may be invoked directly as a command, or declared as a task that a runner named in the pipeline resolves."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"251015acef1a259fcc13b7c60660cc8917ccb3ae8056cb5165ae03312dd586e8"}}],"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-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-200","guid":"b0ce3b1d-7a29-fe50-8aab-9aba899d2988","name":"Exposure of Sensitive Information to an Unauthorized Actor","shortDescription":{"text":"Exposure of Sensitive Information to an Unauthorized Actor"},"helpUri":"https://cwe.mitre.org/data/definitions/200.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-352","guid":"2afe7bdb-7330-195f-b3bf-8cf5b789b3ae","name":"CWE-352","shortDescription":{"text":"CWE-352"},"helpUri":"https://cwe.mitre.org/data/definitions/352.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-396","guid":"1aca74af-8f6d-a556-b3d8-57c64fdee5b0","name":"CWE-396","shortDescription":{"text":"CWE-396"},"helpUri":"https://cwe.mitre.org/data/definitions/396.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-544","guid":"37ab2b26-65e9-e25a-9c05-3171ce2ea46c","name":"CWE-544","shortDescription":{"text":"CWE-544"},"helpUri":"https://cwe.mitre.org/data/definitions/544.html"},{"id":"CWE-561","guid":"522a7ba7-45e9-ab53-9088-45d86e04b53a","name":"CWE-561","shortDescription":{"text":"CWE-561"},"helpUri":"https://cwe.mitre.org/data/definitions/561.html"},{"id":"CWE-601","guid":"9b8963d5-129b-475c-90cf-2d1766e66f2f","name":"CWE-601","shortDescription":{"text":"CWE-601"},"helpUri":"https://cwe.mitre.org/data/definitions/601.html"},{"id":"CWE-650","guid":"2e043a74-5f64-ea50-844b-f5163400750d","name":"CWE-650","shortDescription":{"text":"CWE-650"},"helpUri":"https://cwe.mitre.org/data/definitions/650.html"},{"id":"CWE-705","guid":"bfa22244-2156-5e5a-a6f6-2fbbc9d8a328","name":"CWE-705","shortDescription":{"text":"CWE-705"},"helpUri":"https://cwe.mitre.org/data/definitions/705.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":30,"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."]}]}