{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-4+qual-2+sec-2","generated_at":"2026-11-14T00:03:09.825087Z","repo":{"ref":{"host":"github.com","owner":"caru-ini","name":"stack-diagram"},"default_branch":"main","clone_url":"https://github.com/caru-ini/stack-diagram.git","html_url":"https://github.com/caru-ini/stack-diagram","description":"Agent skill: describe your stack in a sentence, get an architecture diagram with official logos","stars":2481,"forks":134,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":3446,"primary_language":"TypeScript","license_spdx":"MIT","created_at":"2026-11-01T05:35:12Z","pushed_at":"2026-11-13T07:38:10Z","security_policy_url":null,"distribution":{"owner_created_at":"2024-04-13T05:49:40Z","owner_type":"User","release_assets":[{"name":"stack-diagram.zip","size":105397,"download_count":15,"release_tag":"v0.6.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.6.0/stack-diagram.zip"},{"name":"stack-diagram.zip","size":103760,"download_count":19,"release_tag":"v0.5.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.5.0/stack-diagram.zip"},{"name":"stack-diagram.zip","size":103760,"download_count":280,"release_tag":"v0.4.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.4.0/stack-diagram.zip"},{"name":"stack-diagram.zip","size":98628,"download_count":77,"release_tag":"v0.3.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.3.0/stack-diagram.zip"},{"name":"stack-diagram.zip","size":93155,"download_count":33,"release_tag":"v0.2.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.2.0/stack-diagram.zip"},{"name":"stack-diagram.zip","size":90283,"download_count":10,"release_tag":"v0.1.0","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.1.0/stack-diagram.zip"}]}},"commit_sha":"9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3","profile":{"lines_by_language":{"TypeScript":23574,"Python":845,"SQL":67},"files_by_category":{"source":126,"other":51,"test":23,"binary":20,"docs":11,"config":10,"generated":2},"source_lines":22952,"test_lines":1534},"pillars":{"ai_provenance":{"score":98.3,"confidence":0.78,"coverage":1.0,"label":"explicit","breakdown":{"attributed_share":0.983,"suspected_share":0.0,"estimated_share":0.983,"ai_artifacts":1.0,"flagged_work_units":0.0,"flagged_releases":0.0},"summary":"Explicit AI attribution on 98% of first-party code added; an estimated 98% including velocity signals."},"quality":{"score":72.4,"confidence":0.9,"coverage":1.0,"label":"adequate","breakdown":{"complexity":87.9,"duplication":44.6,"lint":87.7,"testing":65.4,"docs":65.0,"type_safety":97.8,"process":null},"summary":"Code quality is adequate: test-to-source ratio 0.07, CI runs tests; 4% of function code in complex or long functions; 13% duplicated lines. Weakest area: duplication."},"security":{"score":74.1,"confidence":0.85,"coverage":1.0,"label":"adequate","breakdown":{"secrets":100.0,"sast":98.5,"dependencies":81.9,"ci_actions":24.3,"posture":20.0,"scorecard":null},"summary":"Security posture is adequate: 4 known vulnerabilities in 4 dependencies; 7 high-severity workflow issues. Weakest area: posture."}},"analyzer_results":[{"analyzer":"sec-scorecard","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":"no published OpenSSF Scorecard result for this repo"},{"analyzer":"sec-registry","pillar":"security","status":"ok","tool_version":null,"metrics":{"declared":28.0,"checked":28.0,"missing":0.0,"recent":0.0,"lookup_errors":0.0},"findings":[],"evidence":[],"data":{"phantom":false},"error":null},{"analyzer":"ai-attribution","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"commits":31.0,"attributed_commits":27.0,"attributed_commit_share":0.8709677419354839,"effective_loc":24764.0,"attributed_loc":24342.0,"attributed_loc_share":0.9829591342271039,"tools_detected":1.0},"findings":[],"evidence":[{"kind":"attribution-summary","description":"Claude Code: 27 attributed commits, 24,342 lines added","ref":null,"url":null,"weight":1.0},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"5af3b095fff7109c905c5284dc510dc06588bade","url":"https://github.com/caru-ini/stack-diagram/commit/5af3b095fff7109c905c5284dc510dc06588bade","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"1ed53e3e9525364ae5d82e0430f2bb3f7ef4c838","url":"https://github.com/caru-ini/stack-diagram/commit/1ed53e3e9525364ae5d82e0430f2bb3f7ef4c838","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"30cbbb76d3089298a95bcdc9dbd2f227e02de267","url":"https://github.com/caru-ini/stack-diagram/commit/30cbbb76d3089298a95bcdc9dbd2f227e02de267","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"9e90a3b286baa6eef9700ca01abb80dbf0ad1514","url":"https://github.com/caru-ini/stack-diagram/commit/9e90a3b286baa6eef9700ca01abb80dbf0ad1514","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"9413ef2b611bb695cb969913c829beda828affaf","url":"https://github.com/caru-ini/stack-diagram/commit/9413ef2b611bb695cb969913c829beda828affaf","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"aa06ba71333cddbd4db30df81de896fe26294f65","url":"https://github.com/caru-ini/stack-diagram/commit/aa06ba71333cddbd4db30df81de896fe26294f65","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"b5d3f57cc49f358d14dba2577c9e14de5769e3cc","url":"https://github.com/caru-ini/stack-diagram/commit/b5d3f57cc49f358d14dba2577c9e14de5769e3cc","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"2801faea2b15fe271c40659b2422d2a1e9994b06","url":"https://github.com/caru-ini/stack-diagram/commit/2801faea2b15fe271c40659b2422d2a1e9994b06","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"12f1e07bbeda008a130857a7208bb455ab262f80","url":"https://github.com/caru-ini/stack-diagram/commit/12f1e07bbeda008a130857a7208bb455ab262f80","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"c01b08ccd30cc4a97481cfe94f5c37fda17fc758","url":"https://github.com/caru-ini/stack-diagram/commit/c01b08ccd30cc4a97481cfe94f5c37fda17fc758","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"b3087832df1b809e64fae2f82b1ca17496016704","url":"https://github.com/caru-ini/stack-diagram/commit/b3087832df1b809e64fae2f82b1ca17496016704","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"05dfbee0f59b11f53f076003ae49a4590638fb92","url":"https://github.com/caru-ini/stack-diagram/commit/05dfbee0f59b11f53f076003ae49a4590638fb92","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"222a87f625b61a3fe559bc7ec5a6240d06e5d197","url":"https://github.com/caru-ini/stack-diagram/commit/222a87f625b61a3fe559bc7ec5a6240d06e5d197","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"0ac006d7d532798b15f80621a5f523cf8ffa890e","url":"https://github.com/caru-ini/stack-diagram/commit/0ac006d7d532798b15f80621a5f523cf8ffa890e","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"a65fbd071e8b4a83b52fc9f6d58b62a14c4301a4","url":"https://github.com/caru-ini/stack-diagram/commit/a65fbd071e8b4a83b52fc9f6d58b62a14c4301a4","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"fe2e3456ef172388c6ea83e14641b57278a56590","url":"https://github.com/caru-ini/stack-diagram/commit/fe2e3456ef172388c6ea83e14641b57278a56590","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"0b095b0ce05cf47971c9a835cf002a6e48e5bb46","url":"https://github.com/caru-ini/stack-diagram/commit/0b095b0ce05cf47971c9a835cf002a6e48e5bb46","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"616873a3c96cf32effc3f7ff5d5be85a072555dd","url":"https://github.com/caru-ini/stack-diagram/commit/616873a3c96cf32effc3f7ff5d5be85a072555dd","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"c57131e4d6931559eb80922d49c179d666d18d86","url":"https://github.com/caru-ini/stack-diagram/commit/c57131e4d6931559eb80922d49c179d666d18d86","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"c9024fc9d5e95f1372a0a049a7445feb112f77a0","url":"https://github.com/caru-ini/stack-diagram/commit/c9024fc9d5e95f1372a0a049a7445feb112f77a0","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"7c5c99cd8124c06c867abd3ee1d4690596377bed","url":"https://github.com/caru-ini/stack-diagram/commit/7c5c99cd8124c06c867abd3ee1d4690596377bed","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"f333b47160442dc28f10b6e3c026ecbdac181ff8","url":"https://github.com/caru-ini/stack-diagram/commit/f333b47160442dc28f10b6e3c026ecbdac181ff8","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"75dbd3e3c6fe28844322e6064d3a947b870a6c61","url":"https://github.com/caru-ini/stack-diagram/commit/75dbd3e3c6fe28844322e6064d3a947b870a6c61","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"188f43b7c4f1725a0948feef8b94a199d07e6e0d","url":"https://github.com/caru-ini/stack-diagram/commit/188f43b7c4f1725a0948feef8b94a199d07e6e0d","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"8b35cb956851ed7c2679ea3faab3ddf676bd3aaa","url":"https://github.com/caru-ini/stack-diagram/commit/8b35cb956851ed7c2679ea3faab3ddf676bd3aaa","weight":0.9}],"data":{"attributed_loc_by_commit":{"b59c2eade69cf0322e09141b5cf06bd665d8d8d9":0,"8b35cb956851ed7c2679ea3faab3ddf676bd3aaa":0,"a75afef158c16e3a1635f33ac174d8ab62b89608":0,"188f43b7c4f1725a0948feef8b94a199d07e6e0d":0,"75dbd3e3c6fe28844322e6064d3a947b870a6c61":75,"616873a3c96cf32effc3f7ff5d5be85a072555dd":0,"c57131e4d6931559eb80922d49c179d666d18d86":0,"c9024fc9d5e95f1372a0a049a7445feb112f77a0":218,"7c5c99cd8124c06c867abd3ee1d4690596377bed":23710,"f333b47160442dc28f10b6e3c026ecbdac181ff8":0,"0b095b0ce05cf47971c9a835cf002a6e48e5bb46":0,"fe2e3456ef172388c6ea83e14641b57278a56590":4,"a65fbd071e8b4a83b52fc9f6d58b62a14c4301a4":6,"0ac006d7d532798b15f80621a5f523cf8ffa890e":0,"05dfbee0f59b11f53f076003ae49a4590638fb92":74,"222a87f625b61a3fe559bc7ec5a6240d06e5d197":9,"b3087832df1b809e64fae2f82b1ca17496016704":3,"c01b08ccd30cc4a97481cfe94f5c37fda17fc758":1,"12f1e07bbeda008a130857a7208bb455ab262f80":0,"b5d3f57cc49f358d14dba2577c9e14de5769e3cc":14,"2801faea2b15fe271c40659b2422d2a1e9994b06":8,"aa06ba71333cddbd4db30df81de896fe26294f65":27,"9413ef2b611bb695cb969913c829beda828affaf":0,"9e90a3b286baa6eef9700ca01abb80dbf0ad1514":13,"30cbbb76d3089298a95bcdc9dbd2f227e02de267":180,"1ed53e3e9525364ae5d82e0430f2bb3f7ef4c838":0,"5af3b095fff7109c905c5284dc510dc06588bade":0},"tools":{"claude-code":{"name":"Claude Code","commits":27,"loc":24342,"first_seen":1793512682,"last_seen":1794204022}},"monthly":{"2026-11":{"loc":24764,"attributed_loc":24342}}},"error":null},{"analyzer":"ai-artifacts","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"artifacts":1.0,"workflow_agents":0.0,"tools_configured":1.0,"earliest_adoption":1793555797.0},"findings":[],"evidence":[{"kind":"ai-artifact","description":"site/AGENTS.md (generic-agent configuration)","ref":"site/AGENTS.md","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/AGENTS.md","weight":0.5}],"data":{"artifacts":[{"tool":"generic-agent","path":"site/AGENTS.md","added_at":1793555797}],"workflows":[],"tools":["generic-agent"]},"error":null},{"analyzer":"ai-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"work_units":9.0,"flagged_units":0.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":0.0,"pre_ai_era_burst_loc":0.0,"measured_loc":1054.0,"flagged_loc":0.0,"flagged_loc_share":0.0,"max_loc_per_hour":78.0,"median_loc_per_hour":52.31536357419649,"pr_timed_units":2.0,"excluded_import_loc":23512.0},"findings":[],"evidence":[],"data":{"flagged_loc_by_commit":{},"excluded_import_commits":["7c5c99cd8124c06c867abd3ee1d4690596377bed"]},"error":null},{"analyzer":"ai-release-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"releases":5.0,"flagged_releases":0.0,"max_loc_per_day":453.3},"findings":[],"evidence":[],"data":{"releases":[{"from":"v0.1.0","to":"v0.2.0","loc":75,"days":0.35,"loc_per_day":216.3,"flagged":false},{"from":"v0.2.0","to":"v0.3.0","loc":315,"days":0.69,"loc_per_day":453.3,"flagged":false},{"from":"v0.3.0","to":"v0.4.0","loc":242,"days":0.86,"loc_per_day":280.2,"flagged":false},{"from":"v0.4.0","to":"v0.5.0","loc":33,"days":9.1,"loc_per_day":3.6,"flagged":false},{"from":"v0.5.0","to":"v0.6.0","loc":77,"days":1.07,"loc_per_day":72.2,"flagged":false}]},"error":null},{"analyzer":"ai-stylometry","pillar":"ai_provenance","status":"ok","tool_version":null,"metrics":{"lines_scanned":6659.0,"index":0.0,"count:narrated_steps":0.0,"per_kloc:narrated_steps":0.0,"files:narrated_steps":0.0,"count:placeholder":0.0,"per_kloc:placeholder":0.0,"files:placeholder":0.0,"count:emoji_in_code":0.0,"per_kloc:emoji_in_code":0.0,"files:emoji_in_code":0.0,"count:assistant_voice":0.0,"per_kloc:assistant_voice":0.0,"files:assistant_voice":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-secrets","pillar":"security","status":"ok","tool_version":"gitleaks 8.30.1","metrics":{"secrets_current":0.0,"secrets_history":0.0,"secrets_nonprod":0.0,"secrets_low_confidence":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-sast","pillar":"security","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":4.0,"findings_high":0.0,"findings_medium":4.0,"findings_low":0.0,"weighted_findings":1.0,"scanned_lines":22885.0,"parse_errors":0.0},"findings":[{"rule_id":"opengrep/javascript.lang.security.audit.unsafe-dynamic-method","severity":"medium","message":"Using non-static data to retrieve and run functions from the object is dangerous. If the data is user-controlled, it may allow executing arbitrary code. [confidence low]","path":"site/src/features/admin/moderation.ts","line":21,"fingerprint":"javascript.lang.security.audit.unsafe-dynamic-method:site/src/features/admin/moderation.ts:21"},{"rule_id":"opengrep/javascript.lang.security.audit.detect-non-literal-regexp","severity":"medium","message":"RegExp() called with a `name` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled [confidence low]","path":"site/src/features/submit/server/icons.ts","line":60,"fingerprint":"javascript.lang.security.audit.detect-non-literal-regexp:site/src/features/submit/server/icons.ts:60"},{"rule_id":"opengrep/python.lang.security.audit.dynamic-urllib-use-detected","severity":"medium","message":"Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead. [confidence low]","path":"skills/stack-diagram/scripts/fetch_icons.py","line":203,"fingerprint":"python.lang.security.audit.dynamic-urllib-use-detected:skills/stack-diagram/scripts/fetch_icons.py:203"},{"rule_id":"opengrep/python.lang.security.audit.dynamic-urllib-use-detected","severity":"medium","message":"Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead. [confidence low]","path":"skills/stack-diagram/scripts/share.py","line":41,"fingerprint":"python.lang.security.audit.dynamic-urllib-use-detected:skills/stack-diagram/scripts/share.py:41"}],"evidence":[],"data":{"rulesets":["typescript","javascript","python"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"ok","tool_version":"osv-scanner version: 2.7.1","metrics":{"vulnerable_packages":4.0,"vulnerabilities":4.0,"vulns_critical":0.0,"vulns_high":0.0,"vulns_medium":4.0,"vulns_low":0.0,"vulns_unknown":0.0,"penalty":12.0},"findings":[{"rule_id":"osv/GHSA-67mh-4wv8-2f99","severity":"medium","message":"esbuild@0.18.20 (npm) is affected by GHSA-67mh-4wv8-2f99","path":"site/pnpm-lock.yaml","line":null,"fingerprint":"esbuild@0.18.20 (npm):GHSA-67mh-4wv8-2f99"},{"rule_id":"osv/GHSA-3g3m-2fjr-6pw4","severity":"medium","message":"glob@10.5.0 (npm) is affected by GHSA-3g3m-2fjr-6pw4","path":"site/pnpm-lock.yaml","line":null,"fingerprint":"glob@10.5.0 (npm):GHSA-3g3m-2fjr-6pw4"},{"rule_id":"osv/GHSA-g3hv-75wg-m249","severity":"medium","message":"minimatch@9.0.9 (npm) is affected by GHSA-g3hv-75wg-m249","path":"site/pnpm-lock.yaml","line":null,"fingerprint":"minimatch@9.0.9 (npm):GHSA-g3hv-75wg-m249"},{"rule_id":"osv/GHSA-wx4j-mvgx-mqwp","severity":"medium","message":"satori@0.32.0 (npm) is affected by GHSA-wx4j-mvgx-mqwp","path":"site/pnpm-lock.yaml","line":null,"fingerprint":"satori@0.32.0 (npm):GHSA-wx4j-mvgx-mqwp"}],"evidence":[],"data":{"ecosystems":["npm"]},"error":null},{"analyzer":"sec-actions","pillar":"security","status":"ok","tool_version":"zizmor 1.32.0","metrics":{"workflows":2.0,"findings":10.0,"findings_high":7.0,"findings_medium":0.0,"findings_low":3.0,"penalty":84.9},"findings":[{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/release.yml","line":14,"fingerprint":"unpinned-uses:.github/workflows/release.yml:14"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":21,"fingerprint":"unpinned-uses:.github/workflows/site.yml:21"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":22,"fingerprint":"unpinned-uses:.github/workflows/site.yml:22"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":25,"fingerprint":"unpinned-uses:.github/workflows/site.yml:25"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":46,"fingerprint":"unpinned-uses:.github/workflows/site.yml:46"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":47,"fingerprint":"unpinned-uses:.github/workflows/site.yml:47"},{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/site.yml","line":50,"fingerprint":"unpinned-uses:.github/workflows/site.yml:50"},{"rule_id":"zizmor/artipacked","severity":"low","message":"credential persistence through GitHub Actions artifacts [confidence low]","path":".github/workflows/release.yml","line":14,"fingerprint":"artipacked:.github/workflows/release.yml:14"},{"rule_id":"zizmor/artipacked","severity":"low","message":"credential persistence through GitHub Actions artifacts [confidence low]","path":".github/workflows/site.yml","line":21,"fingerprint":"artipacked:.github/workflows/site.yml:21"},{"rule_id":"zizmor/artipacked","severity":"low","message":"credential persistence through GitHub Actions artifacts [confidence low]","path":".github/workflows/site.yml","line":46,"fingerprint":"artipacked:.github/workflows/site.yml:46"}],"evidence":[],"data":{},"error":null},{"analyzer":"sec-posture","pillar":"security","status":"ok","tool_version":null,"metrics":{"check:security_policy":0.0,"check:dependency_updates":0.0,"check:signed_commits":1.0,"check:lockfiles":1.0,"signed_commit_share":1.0,"unpinned_manifests":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-distribution","pillar":"security","status":"ok","tool_version":null,"metrics":{"signals":2.0,"binary_assets":6.0,"suspicious":0.0},"findings":[],"evidence":[{"kind":"binary-release-asset","description":"release v0.6.0 ships stack-diagram.zip (15 downloads)","ref":"stack-diagram.zip","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.6.0/stack-diagram.zip","weight":0.0},{"kind":"binary-release-asset","description":"release v0.5.0 ships stack-diagram.zip (19 downloads)","ref":"stack-diagram.zip","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.5.0/stack-diagram.zip","weight":0.0},{"kind":"binary-release-asset","description":"release v0.4.0 ships stack-diagram.zip (280 downloads)","ref":"stack-diagram.zip","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.4.0/stack-diagram.zip","weight":0.0},{"kind":"binary-release-asset","description":"release v0.3.0 ships stack-diagram.zip (77 downloads)","ref":"stack-diagram.zip","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.3.0/stack-diagram.zip","weight":0.0},{"kind":"binary-release-asset","description":"release v0.2.0 ships stack-diagram.zip (33 downloads)","ref":"stack-diagram.zip","url":"https://github.com/caru-ini/stack-diagram/releases/download/v0.2.0/stack-diagram.zip","weight":0.0},{"kind":"star-burst","description":"2481 stars in 13 days (194/day)","ref":null,"url":null,"weight":0.0}],"data":{"signals":["binary-release-assets","star-burst"],"suspicious":false,"unusual_traction":false,"metadata":true},"error":null},{"analyzer":"qual-complexity","pillar":"quality","status":"ok","tool_version":"lizard 1.25.1","metrics":{"functions":914.0,"function_nloc":4867.0,"mean_ccn":1.76,"p90_ccn":4.0,"complex_functions":4.0,"long_functions":0.0,"many_param_functions":0.0,"risky_nloc_share":0.0429},"findings":[],"evidence":[{"kind":"complex-function","description":"main in skills/stack-diagram/scripts/fetch_icons.py: complexity 25, 64 lines","ref":"skills/stack-diagram/scripts/fetch_icons.py","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/skills/stack-diagram/scripts/fetch_icons.py#L411","weight":0.4166666666666667},{"kind":"complex-function","description":"submit in skills/stack-diagram/scripts/share.py: complexity 21, 43 lines","ref":"skills/stack-diagram/scripts/share.py","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/skills/stack-diagram/scripts/share.py#L140","weight":0.35},{"kind":"complex-function","description":"intake in site/src/features/submit/server/intake.ts: complexity 20, 75 lines","ref":"site/src/features/submit/server/intake.ts","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/features/submit/server/intake.ts#L36","weight":0.3333333333333333},{"kind":"complex-function","description":"stack_items in skills/stack-diagram/scripts/share.py: complexity 16, 27 lines","ref":"skills/stack-diagram/scripts/share.py","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/skills/stack-diagram/scripts/share.py#L105","weight":0.26666666666666666}],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":15530.0,"duplicated_lines":2088.0,"duplicated_share":0.1344,"files":126.0},"findings":[],"evidence":[{"kind":"duplicate-code","description":"6+ duplicated lines: site/src/components/stack-card.tsx:18 and site/src/components/stack-row.tsx:36","ref":"site/src/components/stack-card.tsx","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/components/stack-card.tsx#L18","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: site/src/components/stack-card.tsx:40 and site/src/features/stack/stack-page.tsx:53","ref":"site/src/components/stack-card.tsx","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/components/stack-card.tsx#L40","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: site/src/features/account/components/post-row.tsx:25 and site/src/features/admin/components/moderation-row.tsx:64","ref":"site/src/features/account/components/post-row.tsx","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/features/account/components/post-row.tsx#L25","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: site/src/features/gallery/server/gallery.ts:15 and site/src/features/stack/server/stack.ts:54","ref":"site/src/features/gallery/server/gallery.ts","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/features/gallery/server/gallery.ts#L15","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: site/src/features/gallery/server/params.ts:95 and site/src/features/stack/server/input.ts:6","ref":"site/src/features/gallery/server/params.ts","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/src/features/gallery/server/params.ts#L95","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: site/worker-configuration.d.ts:613 and site/worker-configuration.d.ts:626","ref":"site/worker-configuration.d.ts","url":"https://github.com/caru-ini/stack-diagram/blob/9175bde8449cc8f5390d6eb72ecc2e1f5bfe21f3/site/worker-configuration.d.ts#L613","weight":0.3}],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":12.0,"weighted_findings":12.0,"scanned_lines":22885.0,"category:best-practice":5.0,"category:correctness":7.0},"findings":[{"rule_id":"opengrep/typescript.react.best-practice.react-props-spreading","severity":"medium","message":"It's best practice to explicitly pass props to an HTML component rather than use the spread operator. The spread operator risks passing invalid HTML props to an HTML element, which can cause console warnings or worse, give malicious actors a way to inject unexpected attributes.","path":"site/src/components/brand-marks.tsx","line":8,"fingerprint":"typescript.react.best-practice.react-props-spreading:site/src/components/brand-marks.tsx:8"},{"rule_id":"opengrep/typescript.react.best-practice.react-props-spreading","severity":"medium","message":"It's best practice to explicitly pass props to an HTML component rather than use the spread operator. The spread operator risks passing invalid HTML props to an HTML element, which can cause console warnings or worse, give malicious actors a way to inject unexpected attributes.","path":"site/src/components/brand-marks.tsx","line":17,"fingerprint":"typescript.react.best-practice.react-props-spreading:site/src/components/brand-marks.tsx:17"},{"rule_id":"opengrep/typescript.react.best-practice.react-props-spreading","severity":"medium","message":"It's best practice to explicitly pass props to an HTML component rather than use the spread operator. The spread operator risks passing invalid HTML props to an HTML element, which can cause console warnings or worse, give malicious actors a way to inject unexpected attributes.","path":"site/src/components/button.tsx","line":27,"fingerprint":"typescript.react.best-practice.react-props-spreading:site/src/components/button.tsx:27"},{"rule_id":"opengrep/javascript.lang.best-practice.javascript-confirm","severity":"medium","message":"found confirm() call; should this be in production code?","path":"site/src/components/confirm-dialog.tsx","line":80,"fingerprint":"javascript.lang.best-practice.javascript-confirm:site/src/components/confirm-dialog.tsx:80"},{"rule_id":"opengrep/typescript.react.best-practice.react-props-spreading","severity":"medium","message":"It's best practice to explicitly pass props to an HTML component rather than use the spread operator. The spread operator risks passing invalid HTML props to an HTML element, which can cause console warnings or worse, give malicious actors a way to inject unexpected attributes.","path":"site/src/components/menu.tsx","line":23,"fingerprint":"typescript.react.best-practice.react-props-spreading:site/src/components/menu.tsx:23"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/features/gallery/server/params.ts","line":26,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/features/gallery/server/params.ts:26"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/features/gallery/server/params.ts","line":26,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/features/gallery/server/params.ts:26"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/features/gallery/server/params.ts","line":33,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/features/gallery/server/params.ts:33"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/features/gallery/server/params.ts","line":33,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/features/gallery/server/params.ts:33"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/features/og/server/images.tsx","line":238,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/features/og/server/images.tsx:238"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/lib/crypto.ts","line":23,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/lib/crypto.ts:23"},{"rule_id":"opengrep/javascript.lang.correctness.no-replaceall","severity":"medium","message":"The string method replaceAll is not supported in all versions of javascript, and is not supported by older browser versions. Consider using replace() with a regex as the first argument instead like mystring.replace(/bad/g, \"good\") instead of mystring.replaceAll(\"bad\", \"good\") (https://discourse.thre","path":"site/src/lib/crypto.ts","line":23,"fingerprint":"javascript.lang.correctness.no-replaceall:site/src/lib/crypto.ts:23"}],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":1.0,"check:test_ratio":0.1337,"check:ci_present":1.0,"check:ci_runs_tests":1.0,"check:ci_runs_lint":0.0,"check:tests_cochange":0.7059,"test_lines":1534.0,"source_lines":22952.0,"test_ratio":0.0668,"ci_files":2.0,"cochange_share":0.1765,"cochange_commits":17.0},"findings":[],"evidence":[{"kind":"ci","description":"CI config: .github/workflows/release.yml","ref":".github/workflows/release.yml","url":null,"weight":0.0},{"kind":"ci","description":"CI config: .github/workflows/site.yml","ref":".github/workflows/site.yml","url":null,"weight":0.0},{"kind":"ci","description":"CI runs tests (npm test, pnpm test)","ref":null,"url":null,"weight":0.0}],"data":{"test_commands":["npm test","pnpm test"],"lint_commands":[]},"error":null},{"analyzer":"qual-docs","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:readme":1.0,"check:license":1.0,"check:contributing":0.0,"check:changelog":0.0,"readme_lines":92.0},"findings":[],"evidence":[{"kind":"docs","description":"README.md","ref":"README.md","url":null,"weight":0.0},{"kind":"docs","description":"LICENSE","ref":"LICENSE","url":null,"weight":0.0}],"data":{},"error":null},{"analyzer":"qual-type-safety","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:strict_config":0.9631,"check:low_escape_density":1.0,"escapes":104.0,"escapes_per_kloc":4.544},"findings":[],"evidence":[{"kind":"typing","description":"TypeScript strict type checking: site/tsconfig.json","ref":"site/tsconfig.json","url":null,"weight":0.0}],"data":{},"error":null},{"analyzer":"x-blame","pillar":"ai_provenance","status":"ok","tool_version":"git-blame","metrics":{"ai_lines":22566.0,"other_lines":386.0,"files_blamed":126.0,"blame_failures":0.0,"quality:ai_findings":12.0,"quality:ai_per_kloc":0.532,"quality:other_findings":0.0,"quality:other_per_kloc":0.0,"security:ai_findings":3.0,"security:ai_per_kloc":0.133,"security:other_findings":1.0,"security:other_per_kloc":2.591},"findings":[],"evidence":[],"data":{"sampled":false,"comparable":false},"error":null}],"flags":[]}