公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-24 13:18 UTC

buliwyf42 / shellyadmin

Self-hosted web app to discover, inventory, firmware-check, and provision Shelly Gen2+ devices on a trusted LAN. Single Go binary + Svelte UI, Docker-ready, with an opt-in MCP server.

Go · SvelteMIT★ 3 星标⑂ 0 复刻始于 2026年4月在 GitHub 上查看 ↗

buliwyf42/shellyadmin 的健康指数为 100 分中的 60 分,处于「中等」区间。 其得分最高的类别是Vitality(85/100),最低的是Sustainability & Governance(24/100)。 最近一次更新在 1 天前。 近期的大部分工作由 1 位贡献者完成。

60
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

60
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

Dominik Sennfelder个人账户
2 关注者4 个公开仓库始于 2013年6月

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

85优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 1 天前
11.1/36提交节奏 — 52 周中有 16 周有提交
18/18提交量 — 最近一年 325 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year325
human_commit_share0.75
days_since_last_push1
active_weeks_last_year16

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 70 个发布版本
36/36发布时效 — 最近一次发布版本于 1 天前
27/27发布节奏 — 约每 6.6 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count70
latest_release_tagv0.6.3
releases_from_tags
days_since_latest_release1
mean_days_between_releases6.6
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

46存在风险 · 占总体的 18%
评分方式
4.9/60星标 — 3 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars3
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

92优秀
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
18/18CONTRIBUTING 指南
13.5/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

24危急 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
0/10OpenSSF Scorecard:Contributors — project has 0 contributing companies or organizations -- score normalized to 0
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 0% 的议题已关闭
27.7/38.3PR 接受 — 已裁定的 PR 中 60/83 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/25 approved changesets -- score normalized to 0
所用输入
merged_prs60
open_issues1
closed_issues0
issue_closed_ratio0
closed_unmerged_prs23
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
3.4/25所有者影响力 — buliwyf42 有 2 位关注者
17.1/25既往记录 — 4 个公开仓库,账户约 13 年
所用输入
followers2
owner_typeUser
is_verified
owner_loginbuliwyf42
public_repos4
account_age_days4,792
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。

工程质量

基础的工程与文档实践是否到位?

84良好 · 占总体的 20%

工程实践

84良好
评分方式
24/24CI 工作流 — 3 个工作流
24/24存在测试
16/16Linter 配置 — .golangci.yml, eslint.config.js
0/9.6Pre-commit 钩子
0/6.4.editorconfig
20/20OpenSSF Scorecard:CI-Tests — 5 out of 5 merged PRs checked by a CI test -- score normalized to 10
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

85优秀
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
10/10主题标签 — 10 个主题标签
10/10Wiki
所用输入
topicsdocker, firmware-management, golang, home-automation, iot, mcp, self-hosted, shelly, smart-home, svelte
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

67中等 · 占总体的 16%

安全态势

61中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — 无数据
2.5/2.5CI-Tests — 5 out of 5 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/25 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
4.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 9
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
2/5Security-Policy — security policy file detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
6/7.5Vulnerabilities — 2 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate6.1
已排除计分(无数据或不适用):branch_protection, signed_releases。 其余权重已重新归一化。
评分方式
26.6/35直接依赖不含已知公告 — 1 个受影响:golang.org/x/crypto v0.54.0 (unknown)
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories2
affected_packages2
assessed_packages334
unassessed_packages0
affected_by_severityhigh 1, unknown 1
direct_affected_packages1
已排除计分(无数据或不适用):间接依赖不含已知公告。 其余权重已重新归一化。 已将 334 个已解析依赖与 OSV 比对。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

83良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 75 次人类提交中有 72 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.96
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes43,430
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
11/11Lint / 格式化配置 — .golangci.yml, eslint.config.js
11/11静态类型检查 — web/tsconfig.json
10/10可复现环境 — Dockerfile, lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 20 次由代理编写或署名代理
8/8自动化维护 — 最近 100 次提交中有 25 次为自动依赖更新
9/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 9
所用输入
has_nix
has_tests
lockfilesgo.sum, package-lock.json
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainer
has_linter_config
typecheck_configsweb/tsconfig.json
agent_commit_share0.2
toolchain_manifestsgo.mod
dependency_bot_commit_share0.25
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 209 个源文件中有 0 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes52,308
source_files_sampled209
oversized_source_files0
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
0/40可运行示例
所用输入
example_dirs
has_mcp_signal
api_schema_files

关键数据

3GitHub 星标
1贡献者
325最近 12 个月提交数
1距最近推送天数
70发布版本数
1巴士系数(bus factor)
1开放议题
Go, npm软件包生态系统数

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

更多细节

OpenSSF Scorecard 6.1 / 10
6.1综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-24 13:17 UTC

10Binary-Artifactsno binaries found in the repo
不适用Branch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests5 out of 5 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/25 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
9Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 9
0SASTSAST tool is not run on all commits -- score normalized to 0
4Security-Policysecurity policy file detected
不适用Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
8Vulnerabilities2 existing vulnerabilities detected
直接依赖 10
注册表软件包版本约束清单文件
Gogithub.com/gin-contrib/sessionsv1.1.0go.mod
Gogithub.com/gin-gonic/ginv1.12.0go.mod
Gogithub.com/modelcontextprotocol/go-sdkv1.6.1go.mod
Gogolang.org/x/cryptov0.54.0go.mod
Gogolang.org/x/modv0.38.0go.mod
Gogolang.org/x/netv0.57.0go.mod
Gogopkg.in/natefinch/lumberjack.v2v2.2.1go.mod
Gomodernc.org/sqlitev1.54.0go.mod
npmqrcode^1.5.4web/package.json
npmsvelte^5.56.6web/package.json
全部依赖 334

来自 GitHub 依赖图的完整解析依赖集合:10 个直接依赖与 324 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
Gogithub.com/gin-contrib/sessionsv1.1.0直接
Gogithub.com/gin-gonic/ginv1.12.0直接
Gogithub.com/modelcontextprotocol/go-sdkv1.6.1直接
Gogolang.org/x/cryptov0.54.0直接
Gogolang.org/x/modv0.38.0直接
Gogolang.org/x/netv0.57.0直接
Gogopkg.in/natefinch/lumberjack.v2v2.2.1直接
Gomodernc.org/sqlitev1.54.0直接
npmqrcode1.5.4直接
npmsvelte5.56.6直接
Gogithub.com/bytedance/gopkgv0.1.3间接
Gogithub.com/bytedance/sonicv1.15.0间接
Gogithub.com/bytedance/sonic/loaderv0.5.0间接
Gogithub.com/cloudwego/base64xv0.1.6间接
Gogithub.com/dustin/go-humanizev1.0.1间接
Gogithub.com/gabriel-vasile/mimetypev1.4.12间接
Gogithub.com/gin-contrib/ssev1.1.0间接
Gogithub.com/go-playground/localesv0.14.1间接
Gogithub.com/go-playground/universal-translatorv0.18.1间接
Gogithub.com/go-playground/validator/v10v10.30.1间接
Gogithub.com/goccy/go-jsonv0.10.5间接
Gogithub.com/goccy/go-yamlv1.19.2间接
Gogithub.com/google/jsonschema-gov0.4.3间接
Gogithub.com/google/uuidv1.6.0间接
Gogithub.com/gorilla/contextv1.1.2间接
Gogithub.com/gorilla/securecookiev1.1.2间接
Gogithub.com/gorilla/sessionsv1.4.0间接
Gogithub.com/json-iterator/gov1.1.12间接
Gogithub.com/klauspost/cpuid/v2v2.3.0间接
Gogithub.com/leodido/go-urnv1.4.0间接
Gogithub.com/mattn/go-isattyv0.0.20间接
Gogithub.com/modern-go/concurrentv0.0.0-20180306012644-bacd9c7ef1dd间接
Gogithub.com/modern-go/reflect2v1.0.2间接
Gogithub.com/ncruces/go-strftimev1.0.0间接
Gogithub.com/pelletier/go-toml/v2v2.2.4间接
Gogithub.com/quic-go/qpackv0.6.0间接
Gogithub.com/quic-go/quic-gov0.59.1间接
Gogithub.com/remyoudompheng/bigfftv0.0.0-20230129092748-24d4a6f8daec间接
Gogithub.com/segmentio/asmv1.1.3间接
Gogithub.com/segmentio/encodingv0.5.4间接
Gogithub.com/twitchyliquid64/golang-asmv0.15.1间接
Gogithub.com/ugorji/go/codecv1.3.1间接
Gogithub.com/yosida95/uritemplate/v3v3.0.2间接
Gogo.mongodb.org/mongo-driver/v2v2.5.0间接
Gogolang.org/x/archv0.22.0间接
Gogolang.org/x/oauth2v0.35.0间接
Gogolang.org/x/sysv0.47.0间接
Gogolang.org/x/textv0.40.0间接
Gogoogle.golang.org/protobufv1.36.10间接
Gomodernc.org/libcv1.74.1间接
Gomodernc.org/mathutilv1.7.1间接
Gomodernc.org/memoryv1.11.0间接
npm@asamuzakjp/css-color5.1.11间接
npm@asamuzakjp/dom-selector7.1.1间接
npm@asamuzakjp/generational-cache1.0.1间接
npm@asamuzakjp/nwsapi2.3.9间接
npm@babel/helper-string-parser7.29.7间接
npm@babel/helper-validator-identifier7.29.7间接
npm@babel/parser7.29.7间接
npm@babel/types7.29.7间接
npm@bcoe/v8-coverage1.0.2间接
npm@bramus/specificity2.4.2间接
npm@csstools/color-helpers6.0.2间接
npm@csstools/css-calc3.2.0间接
npm@csstools/css-color-parser4.1.0间接
npm@csstools/css-parser-algorithms4.0.0间接
npm@csstools/css-syntax-patches-for-csstree1.1.3间接
npm@csstools/css-tokenizer4.0.0间接
npm@emnapi/core1.11.1间接
npm@emnapi/runtime1.11.1间接
npm@emnapi/wasi-threads1.2.2间接
npm@eslint-community/eslint-utils4.9.1间接
npm@eslint-community/regexpp4.12.2间接
npm@eslint/config-array0.23.5间接
npm@eslint/config-helpers0.6.0间接
npm@eslint/core1.2.1间接
npm@eslint/js10.0.1间接
npm@eslint/object-schema3.0.5间接
npm@eslint/plugin-kit0.7.2间接
npm@exodus/bytes1.15.0间接
npm@humanfs/core0.19.2间接
npm@humanfs/node0.16.8间接
npm@humanfs/types0.15.0间接
npm@humanwhocodes/module-importer1.0.1间接
npm@humanwhocodes/retry0.4.3间接
npm@jridgewell/gen-mapping0.3.13间接
npm@jridgewell/remapping2.3.5间接
npm@jridgewell/resolve-uri3.1.2间接
npm@jridgewell/sourcemap-codec1.5.5间接
npm@jridgewell/trace-mapping0.3.31间接
npm@napi-rs/wasm-runtime1.1.6间接
npm@oxc-project/types0.138.0间接
npm@playwright/test1.61.1间接
npm@rolldown/binding-android-arm641.1.4间接
npm@rolldown/binding-darwin-arm641.1.4间接
npm@rolldown/binding-darwin-x641.1.4间接
npm@rolldown/binding-freebsd-x641.1.4间接
npm@rolldown/binding-linux-arm-gnueabihf1.1.4间接
npm@rolldown/binding-linux-arm64-gnu1.1.4间接
npm@rolldown/binding-linux-arm64-musl1.1.4间接
npm@rolldown/binding-linux-ppc64-gnu1.1.4间接
npm@rolldown/binding-linux-s390x-gnu1.1.4间接
npm@rolldown/binding-linux-x64-gnu1.1.4间接
npm@rolldown/binding-linux-x64-musl1.1.4间接
npm@rolldown/binding-openharmony-arm641.1.4间接
npm@rolldown/binding-wasm32-wasi1.1.4间接
npm@rolldown/binding-win32-arm64-msvc1.1.4间接
npm@rolldown/binding-win32-x64-msvc1.1.4间接
npm@rolldown/pluginutils1.0.1间接
npm@standard-schema/spec1.1.0间接
npm@sveltejs/acorn-typescript1.0.10间接
npm@sveltejs/vite-plugin-svelte7.1.3间接
npm@tybys/wasm-util0.10.3间接
npm@types/chai5.2.3间接
npm@types/deep-eql4.0.2间接
npm@types/esrecurse4.3.1间接
npm@types/estree1.0.9间接
npm@types/json-schema7.0.15间接
npm@types/node25.7.0间接
npm@types/qrcode1.5.6间接
npm@types/trusted-types2.0.7间接
npm@typescript-eslint/eslint-plugin8.62.1间接
npm@typescript-eslint/parser8.62.1间接
npm@typescript-eslint/project-service8.62.1间接
npm@typescript-eslint/scope-manager8.62.1间接
npm@typescript-eslint/tsconfig-utils8.62.1间接
npm@typescript-eslint/type-utils8.62.1间接
npm@typescript-eslint/types8.62.1间接
npm@typescript-eslint/typescript-estree8.62.1间接
npm@typescript-eslint/utils8.62.1间接
npm@typescript-eslint/visitor-keys8.62.1间接
npm@vitest/coverage-v84.1.10间接
npm@vitest/expect4.1.10间接
npm@vitest/mocker4.1.10间接
npm@vitest/pretty-format4.1.10间接
npm@vitest/runner4.1.10间接
npm@vitest/snapshot4.1.10间接
npm@vitest/spy4.1.10间接
npm@vitest/utils4.1.10间接
npmacorn8.16.0间接
npmacorn-jsx5.3.2间接
npmajv6.15.0间接
npmansi-regex5.0.1间接
npmansi-styles4.3.0间接
npmaria-query5.3.1间接
npmassertion-error2.0.1间接
npmast-v8-to-istanbul1.0.4间接
npmaxobject-query4.1.0间接
npmbalanced-match4.0.4间接
npmbidi-js1.0.3间接
npmbrace-expansion5.0.6间接
npmcamelcase5.3.1间接
npmchai6.2.2间接
npmcliui6.0.0间接
npmclsx2.1.1间接
npmcolor-convert2.0.1间接
npmcolor-name1.1.4间接
npmconvert-source-map2.0.0间接
npmcross-spawn7.0.6间接
npmcss-tree3.2.1间接
npmcssesc3.0.0间接
npmdata-urls7.0.0间接
npmdebug4.4.3间接
npmdecamelize1.2.0间接
npmdecimal.js10.6.0间接
npmdeep-is0.1.4间接
npmdeepmerge4.3.1间接
npmdetect-libc2.1.2间接
npmdevalue5.8.1间接
npmdijkstrajs1.0.3间接
npmemoji-regex8.0.0间接
npmentities8.0.0间接
npmes-module-lexer2.1.0间接
npmescape-string-regexp4.0.0间接
npmeslint10.6.0间接
npmeslint-config-prettier10.1.8间接
npmeslint-plugin-svelte3.20.0间接
npmeslint-scope8.4.0间接
npmeslint-scope9.1.2间接
npmeslint-visitor-keys3.4.3间接
npmeslint-visitor-keys4.2.1间接
npmeslint-visitor-keys5.0.1间接
npmesm-env1.2.2间接
npmespree10.4.0间接
npmespree11.2.0间接
npmesquery1.7.0间接
npmesrap2.2.13间接
npmesrecurse4.3.0间接
npmestraverse5.3.0间接
npmestree-walker3.0.3间接
npmesutils2.0.3间接
npmexpect-type1.3.0间接
npmfast-deep-equal3.1.3间接
npmfast-json-stable-stringify2.1.0间接
npmfast-levenshtein2.0.6间接
npmfdir6.5.0间接
npmfile-entry-cache8.0.0间接
npmfind-up4.1.0间接
npmfind-up5.0.0间接
npmflat-cache4.0.1间接
npmflatted3.4.2间接
npmfsevents2.3.2间接
npmfsevents2.3.3间接
npmget-caller-file2.0.5间接
npmglob-parent6.0.2间接
npmglobals16.5.0间接
npmhas-flag4.0.0间接
npmhtml-encoding-sniffer6.0.0间接
npmhtml-escaper2.0.2间接
npmignore5.3.2间接
npmignore7.0.5间接
npmimurmurhash0.1.4间接
npmis-extglob2.1.1间接
npmis-fullwidth-code-point3.0.0间接
npmis-glob4.0.3间接
npmis-potential-custom-element-name1.0.1间接
npmis-reference3.0.3间接
npmisexe2.0.0间接
npmistanbul-lib-coverage3.2.2间接
npmistanbul-lib-report3.0.1间接
npmistanbul-reports3.2.0间接
npmjs-tokens10.0.0间接
npmjsdom29.1.1间接
npmjson-buffer3.0.1间接
npmjson-schema-traverse0.4.1间接
npmjson-stable-stringify-without-jsonify1.0.1间接
npmkeyv4.5.4间接
npmknown-css-properties0.37.0间接
npmlevn0.4.1间接
npmlightningcss1.32.0间接
npmlightningcss-android-arm641.32.0间接
npmlightningcss-darwin-arm641.32.0间接
npmlightningcss-darwin-x641.32.0间接
npmlightningcss-freebsd-x641.32.0间接
npmlightningcss-linux-arm-gnueabihf1.32.0间接
npmlightningcss-linux-arm64-gnu1.32.0间接
npmlightningcss-linux-arm64-musl1.32.0间接
npmlightningcss-linux-x64-gnu1.32.0间接
npmlightningcss-linux-x64-musl1.32.0间接
npmlightningcss-win32-arm64-msvc1.32.0间接
npmlightningcss-win32-x64-msvc1.32.0间接
npmlilconfig2.1.0间接
npmlocate-character3.0.0间接
npmlocate-path5.0.0间接
npmlocate-path6.0.0间接
npmlru-cache11.3.6间接
npmmagic-string0.30.21间接
npmmagicast0.5.3间接
npmmake-dir4.0.0间接
npmmdn-data2.27.1间接
npmminimatch10.2.5间接
npmms2.1.3间接
npmnanoid3.3.12间接
npmnatural-compare1.4.0间接
npmobug2.1.1间接
npmoptionator0.9.4间接
npmp-limit2.3.0间接
npmp-limit3.1.0间接
npmp-locate4.1.0间接
npmp-locate5.0.0间接
npmp-try2.2.0间接
npmparse58.0.1间接
npmpath-exists4.0.0间接
npmpath-key3.1.1间接
npmpathe2.0.3间接
npmpicocolors1.1.1间接
npmpicomatch4.0.4间接
npmplaywright1.61.1间接
npmplaywright-core1.61.1间接
npmpngjs5.0.0间接
npmpostcss8.5.16间接
npmpostcss-load-config3.1.4间接
npmpostcss-safe-parser7.0.1间接
npmpostcss-scss4.0.9间接
npmpostcss-selector-parser7.1.1间接
npmprelude-ls1.2.1间接
npmprettier3.9.4间接
npmprettier-plugin-svelte4.1.1间接
npmpunycode2.3.1间接
npmrequire-directory2.1.1间接
npmrequire-from-string2.0.2间接
npmrequire-main-filename2.0.0间接
npmrolldown1.1.4间接
npmsaxes6.0.0间接
npmsemver7.8.0间接
npmset-blocking2.0.0间接
npmshebang-command2.0.0间接
npmshebang-regex3.0.0间接
npmsiginfo2.0.0间接
npmsource-map-js1.2.1间接
npmstackback0.0.2间接
npmstd-env4.1.0间接
npmstring-width4.2.3间接
npmstrip-ansi6.0.1间接
npmsupports-color7.2.0间接
npmsvelte-eslint-parser1.8.0间接
npmsymbol-tree3.2.4间接
npmtinybench2.9.0间接
npmtinyexec1.1.2间接
npmtinyglobby0.2.17间接
npmtinyrainbow3.1.0间接
npmtldts7.0.30间接
npmtldts-core7.0.30间接
npmtough-cookie6.0.1间接
npmtr466.0.0间接
npmts-api-utils2.5.0间接
npmtslib2.8.1间接
npmtype-check0.4.0间接
npmtypescript6.0.3间接
npmtypescript-eslint8.62.1间接
npmundici7.28.0间接
npmundici-types7.21.0间接
npmuri-js4.4.1间接
npmutil-deprecate1.0.2间接
npmvite8.1.3间接
npmvitefu1.1.3间接
npmvitest4.1.10间接
npmw3c-xmlserializer5.0.0间接
npmwebidl-conversions8.0.1间接
npmwhatwg-mimetype5.0.0间接
npmwhatwg-url16.0.1间接
npmwhich2.0.2间接
npmwhich-module2.0.1间接
npmwhy-is-node-running2.3.0间接
npmword-wrap1.2.5间接
npmwrap-ansi6.2.0间接
npmxml-name-validator5.0.0间接
npmxmlchars2.2.0间接
npmy18n4.0.3间接
npmyaml1.10.3间接
npmyargs15.4.1间接
npmyargs-parser18.1.3间接
npmyocto-queue0.1.0间接
npmzimmerframe1.1.4间接
依赖安全公告 2

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 334 个包,其中也包含从不交付的开发与测试版本固定:2 个存在已知公告,1 个为直接依赖。

软件包版本关系严重程度公告数修复版本
brace-expansion5.0.6间接15.0.7
golang.org/x/cryptov0.54.0直接未知1

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "docker",
        "firmware-management",
        "golang",
        "home-automation",
        "iot",
        "mcp",
        "self-hosted",
        "shelly",
        "smart-home",
        "svelte"
      ],
      "is_fork": false,
      "size_kb": 5932,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 1056708,
        "CSS": 29203,
        "HTML": 361,
        "Shell": 3057,
        "Svelte": 313750,
        "Makefile": 966,
        "Dockerfile": 2173,
        "JavaScript": 8176,
        "TypeScript": 145700
      },
      "pushed_at": "2026-07-23T06:11:23Z",
      "created_at": "2026-04-08T18:24:09Z",
      "owner_type": "User",
      "updated_at": "2026-07-23T06:08:12Z",
      "description": "Self-hosted web app to discover, inventory, firmware-check, and provision Shelly Gen2+ devices on a trusted LAN. Single Go binary + Svelte UI, Docker-ready, with an opt-in MCP server.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go",
        "Svelte"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Dominik Sennfelder",
      "type": "User",
      "login": "buliwyf42",
      "company": null,
      "location": null,
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/4658822?v=4",
      "created_at": "2013-06-10T07:17:51Z",
      "is_verified": null,
      "public_repos": 4,
      "account_age_days": 4792
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.6.3",
          "kind": "patch",
          "published_at": "2026-07-23T06:21:10Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-07-22T17:35:26Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-07-22T15:37:45Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-22T15:07:56Z"
        },
        {
          "tag": "v0.5.7",
          "kind": "patch",
          "published_at": "2026-07-17T10:07:05Z"
        },
        {
          "tag": "v0.5.5",
          "kind": "patch",
          "published_at": "2026-07-01T20:32:42Z"
        },
        {
          "tag": "v0.5.4",
          "kind": "patch",
          "published_at": "2026-07-01T19:39:55Z"
        },
        {
          "tag": "v0.5.3",
          "kind": "patch",
          "published_at": "2026-06-10T18:13:43Z"
        },
        {
          "tag": "v0.5.2",
          "kind": "patch",
          "published_at": "2026-05-29T07:20:28Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-05-24T19:11:09Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-05-23T09:09:49Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-05-20T16:37:54Z"
        },
        {
          "tag": "v0.3.6",
          "kind": "patch",
          "published_at": "2026-05-20T12:35:26Z"
        },
        {
          "tag": "v0.3.5",
          "kind": "patch",
          "published_at": "2026-05-20T10:20:33Z"
        },
        {
          "tag": "v0.3.4",
          "kind": "patch",
          "published_at": "2026-05-20T07:59:16Z"
        },
        {
          "tag": "v0.3.3",
          "kind": "patch",
          "published_at": "2026-05-12T08:54:13Z"
        },
        {
          "tag": "v0.3.2",
          "kind": "patch",
          "published_at": "2026-05-12T06:14:02Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-05-12T05:51:23Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-05-12T04:45:44Z"
        },
        {
          "tag": "v0.2.13",
          "kind": "patch",
          "published_at": "2026-05-11T14:28:44Z"
        },
        {
          "tag": "v0.2.12",
          "kind": "patch",
          "published_at": "2026-05-11T13:48:33Z"
        },
        {
          "tag": "v0.2.11",
          "kind": "patch",
          "published_at": "2026-05-11T12:30:49Z"
        },
        {
          "tag": "v0.2.10",
          "kind": "patch",
          "published_at": "2026-05-11T11:56:07Z"
        },
        {
          "tag": "v0.2.9",
          "kind": "patch",
          "published_at": "2026-05-11T09:27:25Z"
        },
        {
          "tag": "v0.2.8",
          "kind": "patch",
          "published_at": "2026-05-11T08:18:28Z"
        },
        {
          "tag": "v0.2.7",
          "kind": "patch",
          "published_at": "2026-05-11T05:07:56Z"
        },
        {
          "tag": "v0.2.6",
          "kind": "patch",
          "published_at": "2026-05-11T04:59:45Z"
        },
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2026-05-11T04:56:58Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-05-11T04:51:36Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-05-10T20:15:59Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-05-10T19:29:20Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-05-10T18:34:17Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-05-10T17:32:53Z"
        },
        {
          "tag": "v0.1.23",
          "kind": "patch",
          "published_at": "2026-05-10T06:57:46Z"
        },
        {
          "tag": "v0.1.22",
          "kind": "patch",
          "published_at": "2026-05-09T21:21:44Z"
        },
        {
          "tag": "v0.1.21",
          "kind": "patch",
          "published_at": "2026-05-09T20:41:54Z"
        },
        {
          "tag": "v0.1.20",
          "kind": "patch",
          "published_at": "2026-05-09T14:36:04Z"
        },
        {
          "tag": "v0.1.19",
          "kind": "patch",
          "published_at": "2026-05-09T13:40:52Z"
        },
        {
          "tag": "v0.1.18",
          "kind": "patch",
          "published_at": "2026-05-08T21:50:53Z"
        },
        {
          "tag": "v0.1.17",
          "kind": "patch",
          "published_at": "2026-05-08T21:41:31Z"
        },
        {
          "tag": "v0.1.16",
          "kind": "patch",
          "published_at": "2026-05-08T14:41:45Z"
        },
        {
          "tag": "v0.1.15",
          "kind": "patch",
          "published_at": "2026-05-08T14:29:24Z"
        },
        {
          "tag": "v0.1.13",
          "kind": "patch",
          "published_at": "2026-05-09T07:07:37Z"
        },
        {
          "tag": "v0.1.12",
          "kind": "patch",
          "published_at": "2026-05-07T13:19:49Z"
        },
        {
          "tag": "v0.1.11",
          "kind": "patch",
          "published_at": "2026-05-07T12:54:23Z"
        },
        {
          "tag": "v0.1.10",
          "kind": "patch",
          "published_at": "2026-05-07T12:26:16Z"
        },
        {
          "tag": "v0.1.9",
          "kind": "patch",
          "published_at": "2026-05-07T12:07:39Z"
        },
        {
          "tag": "v0.1.8",
          "kind": "patch",
          "published_at": "2026-05-07T11:56:19Z"
        },
        {
          "tag": "v0.1.7",
          "kind": "patch",
          "published_at": "2026-05-06T20:26:14Z"
        },
        {
          "tag": "v0.1.6",
          "kind": "patch",
          "published_at": "2026-05-06T13:54:38Z"
        },
        {
          "tag": "v0.1.5",
          "kind": "patch",
          "published_at": "2026-05-06T13:54:36Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-05-04T05:51:40Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-05-04T04:22:42Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-05-03T20:48:18Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-05-03T19:09:47Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-05-03T18:29:17Z"
        },
        {
          "tag": "v0.0.16",
          "kind": "patch",
          "published_at": "2026-04-24T09:04:05Z"
        },
        {
          "tag": "v0.0.15",
          "kind": "patch",
          "published_at": "2026-04-22T04:33:33Z"
        },
        {
          "tag": "v0.0.14",
          "kind": "patch",
          "published_at": "2026-04-21T15:15:45Z"
        },
        {
          "tag": "v0.0.13",
          "kind": "patch",
          "published_at": "2026-04-21T13:22:43Z"
        },
        {
          "tag": "v0.0.12",
          "kind": "patch",
          "published_at": "2026-04-21T11:47:52Z"
        },
        {
          "tag": "v0.0.11",
          "kind": "patch",
          "published_at": "2026-04-18T21:21:20Z"
        },
        {
          "tag": "v0.0.10",
          "kind": "patch",
          "published_at": "2026-04-18T10:05:26Z"
        },
        {
          "tag": "v0.0.9",
          "kind": "patch",
          "published_at": "2026-04-17T21:58:18Z"
        },
        {
          "tag": "v0.0.8",
          "kind": "patch",
          "published_at": "2026-04-16T14:59:41Z"
        },
        {
          "tag": "v0.0.7",
          "kind": "patch",
          "published_at": "2026-04-16T11:52:10Z"
        },
        {
          "tag": "v0.0.6",
          "kind": "patch",
          "published_at": "2026-04-16T10:27:37Z"
        },
        {
          "tag": "v0.0.5",
          "kind": "patch",
          "published_at": "2026-04-15T14:12:44Z"
        },
        {
          "tag": "v0.0.4",
          "kind": "patch",
          "published_at": "2026-04-14T06:55:27Z"
        },
        {
          "tag": "v0.0.3",
          "kind": "patch",
          "published_at": "2026-04-14T06:47:16Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "c580f1054f27a87e07bb176023a7aa42294cbd58",
          "body": "…eanup\n\nBundles everything since v0.6.2: the ponytail-audit dead-code removal\n(42ad598, bae92ee) and the Model-column app-vs-marketing-name precedence\nfix (db59dd9).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.6.3 — fix Model-column marketing name + ponytail-audit cl…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-23T06:07:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d00d219356e58dc61e6ecb3c88e743b426fefbde",
          "body": "42ad598 and bae92ee landed without a CHANGELOG entry. Documenting them\nnow so the v0.6.3 release notes cover everything since v0.6.2, not just\nthe Model-column precedence fix.",
          "is_bot": false,
          "headline": "docs: changelog entry for the ponytail-audit cleanup commits",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-23T06:05:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db59dd9c5041300046e1c16cdb7eff8f7f8bc9a6",
          "body": "Firmware.svelte and DeviceTable.svelte displayed `app || friendly || model`\nin the Model column. Shelly's own `app` field (e.g. \"Plus1\") is populated on\nvirtually every real device, so it always beat the marketing name added in\n0.6.1 — the friendly name only ever reached the tooltip, never the visible\ncell. Flipped to `friendly || app || model`.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: marketing name never showed — app code always won the precedence",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-23T06:02:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bae92ee64f55a9bbc58e508c6c8d960288acacbc",
          "body": "CI's Model schema drift check caught internal/models/schema.gen.json\nbeing stale after the TOTPRequired field removal — regenerated via\ngo run ./cmd/modelschema.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Regenerate model schema after removing TOTPRequired",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-23T05:57:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "42ad5984abec65d6e83980bdf3660c941dffff5c",
          "body": "Cuts dead code and refactor debris flagged by a repo-wide audit: unused\nTOTPRequired/JobID fields, a single-caller RequireAnyScope, hand-rolled\nlastIndexByte/jsonMarshal wrappers, MCPBuilder/MCPController aliases, the\nGroupSaver single-impl interface, duplicate request-ID sanitizers between\nmcp/serv\n[…]\napp_jobs.go's larger ~200-line forwarding shim is intentionally left in\nplace (~15 live call sites across api/mcp/cmd) as a separate follow-up.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remove over-engineering findings from ponytail-audit",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-23T05:51:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ffff54d2cf36999fd455b343404c53cdf22cb888",
          "body": "See 55b2325 for the implementation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.6.2 — configurable badge color for feature-frozen devices",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T17:21:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "55b2325ad0d091ea704c798dd2ef7506ffc81959",
          "body": "Extends the existing gen2/gen3/gen4 badge-color settings with a fourth,\ngen_frozen_badge_class (default amber/orange, matching gen2's), that\noverrides the generation badge for any device with fw_frozen=true,\nregardless of its actual gen. Shows as \"Gen N.x (frozen)\" on both the\nDevices table and the \n[…]\neded.\n\nRemoves the standalone \"frozen\" text badge from the Firmware page's\nModel column; the enhanced generation badge now carries that signal.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add configurable badge color for feature-frozen devices",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T17:19:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "72c03dade07d3c95641148214c3b308f49fb29da",
          "body": "CI's Go lint job (golangci-lint v2.12, staticcheck) started flagging 7\nsites in probe_clock_test.go/probe_strict_test.go as possible nil\ndereferences after \"if dev == nil { t.Fatal(...) }\" — a standard Go test\nidiom that relies on t.Fatal's runtime.Goexit() to halt the test. Not\nreproducible with th\n[…]\nss of whether the analyzer can prove\n*testing.T's method is non-returning, which is the standard fix for this\nstaticcheck false-positive class.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(lint): silence SA5011 false positive on t.Fatal(f) nil-guards",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T15:37:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c0b67323547c967ba1264f54e89087093497786",
          "body": "The Model column on the Firmware and Devices pages now shows the Shelly\nmarketing name alongside/instead of the raw SKU. See 4f7dfcb for the\nimplementation.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.6.1 — show Shelly marketing names next to model SKUs",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T15:08:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4f7dfcbcf30952f19b9e40a20f3e680ba4c8de91",
          "body": "The Model column on the Firmware and Devices pages only ever showed the\nraw SKU (SNSW-001X16EU) or Shelly's own app code (Plus1PM) - neither is\nthe name a user recognizes. modelName() in web/src/lib/shellyModels.ts\nresolves a SKU to its marketing name (\"Shelly Plus 1\") from a static\n144-entry table \n[…]\nnst.py MODEL_NAMES, the same\nsource already used for the feature-frozen allowlist. Frontend-only: pure\ndisplay formatting, no Go/DB/API change.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Show Shelly marketing names next to model SKUs",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T15:08:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1833c8555262c6f7d625f2f1442b74a780ab8308",
          "body": "CI's Go lint job caught this on the v0.6.0 push — my flag_frozen_firmware\nedit broke gofmt's column alignment for the surrounding fields.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: gofmt ComplianceRules struct alignment",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T14:59:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "94006567cd782d71ebc20cb9462970fcb59ac82b",
          "body": null,
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into main",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T14:48:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "379138af1ddb1597c7a67f2cb99c9554f673c69c",
          "body": "Devices on a Shelly firmware line that will never receive 2.0.0+ now get a\n\"frozen\" badge on the Firmware page, plus an opt-in compliance rule\n(flag_frozen_firmware). See d34d9ed for the implementation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.6.0 — flag feature-frozen Shelly firmware lines",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T14:48:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d34d9edf7649c596484eec01457c538a5615e16b",
          "body": "Devices on a Shelly firmware line that will never receive 2.0.0+ (Plus 1,\nPlus 1 Mini, Plus 1 PM, Plus 1 PM Mini, Plus 2 PM, Plus PM Mini, Plus i4,\nPlus Plug S/US, Plus H&T, Plus 0-10V Dimmer, BLU Gateway Gen2) now get a\n\"frozen\" badge on the Firmware page, and can optionally be surfaced as a\ncompli\n[…]\ned\nat GetDevices() time like FWAlt/Provisioning, no migration, no extra RPC.\nPurely informational per ADR-0002: never gates the install action.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Flag feature-frozen Shelly firmware lines (Firmware Update Policy)",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T14:46:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51e882a4befeafb8d8ab17649aa45d04119f0dc0",
          "body": "…settled\n\nCorrected the fleet count while at it (27, not 31, run 2.0.0 -- a\ncounting slip from the prior commit). Uptime dating shows nothing\nadopted 2.0.0 in the three days after release, and nothing has moved\nin five nights since the 2026-07-17 fleet OTA despite daily\nstage:stable polling -- consi\n[…]\nce) doesn't distinguish that from ordinary per-device\nbucketing. Left open pending an index snapshot over time rather than\nasserted either way.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: mark firmware-2.0.0-rollout-paused question as unresolved, not …",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T07:45:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d4c80e987a687f208dfd07e1b82f1b61a0b110db",
          "body": "…t shortcut a rollout\n\nContrary to the forum consensus that Gen2+ has no offline update path,\n`curl -k https://updates.shelly.cloud/update/<APP>` returns stable/beta\nwith a direct fwcdn URL (-k required: Allterco internal CA). Verified the\nCDN serves the ZIP to a LAN host.\n\nRecords the negative resu\n[…]\nthe open\n`premature end of data` failures, and the missing beta branch on\nPlus1/Plus2PM dates the Gen2 Plus EOL without trusting a vendor post.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: firmware index at updates.shelly.cloud — found, and why it can'…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-22T07:37:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cd1a365ff54fab7ef535442c9c98f23417dc07ce",
          "body": "…t a floor\n\nTwo traps hit while diagnosing why one of two identical S4PL-00416EU strips\nwas not offered 2.0.0:\n\n- The phased rollout is keyed per device id, so the same model can be offered\n  different stable versions in the same minute. Not a device fault.\n- Schedule stage \"beta\" installs only the beta slot; it never picks up a later\n  stable release. For a device parked ahead of its own stable channel,\n  \"stable\" is the correct setting.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Docs: firmware rollout is per device; auto-update stage is a slot, no…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-21T06:33:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "34a0399ad46b0a1e08f34276f7d3a5cc6972381f",
          "body": "Bumps the go-dependencies group with 2 updates: [golang.org/x/mod](https://github.com/golang/mod) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).\n\n\nUpdates `golang.org/x/mod` from 0.37.0 to 0.38.0\n- [Commits](https://github.com/golang/mod/compare/v0.37.0...v0.38.0)\n\nUpdates `modernc.org/s\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the go-dependencies group with 2 updates (#85)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-20T17:49:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c8af61910f3ecced8b44df0013948a680c017ff6",
          "body": "Bumps the npm-prod-dependencies group in /web with 1 update: [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte).\n\n\nUpdates `svelte` from 5.56.4 to 5.56.6\n- [Release notes](https://github.com/sveltejs/svelte/releases)\n- [Changelog](https://github.com/sveltejs/svelte/blob/main/pack\n[…]\ndate:semver-patch\n  dependency-group: npm-prod-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump svelte in /web in the npm-prod-dependencies group (#83)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-20T17:48:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b666a22b857991477c0079565c68d3afe090df60",
          "body": "…the image\n\nThe release path told operators to pull the image and then call start_stack\n(\"or restart_stack if already up\"). Neither recreates the container, so both\nleave the old image running while reporting success.\n\nVerified 2026-07-17 during the v0.5.7 deploy: pull_image + start_stack returned\n{\n[…]\nongside\nthe verification step that would have caught this: check the container's\nImageID and a version-specific API field, not the tool output.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: correct the deploy step — start_stack/restart_stack don't swap …",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-17T11:21:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6db037c10a5c422dfab36728e1bae8ee6976c532",
          "body": "v0.5.6 claimed firmware installs failed because ShellyAdmin polled the device\nduring the download, starving it. That claim was wrong and is withdrawn.\n\nIt rested on comparing two different devices — one unpolled that succeeded, one\npolled that failed — and crediting the difference to polling. The po\n[…]\nd 150s, so the persisted\n  and effective values diverged and the timeout floor under-sized the polling\n  window. Normalize now defaults it too.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.5.7 — retract v0.5.6's root cause; patch the build's Go",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-17T09:53:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "218400ee73ccad55dbe90d8386bf1ba4c35286a9",
          "body": "…period\n\nThe v0.5.6 release commit added AppSettings.FirmwareInstallQuietPeriod and the\nmatching web/src/lib/types.ts field, but left internal/models/schema.gen.json\nstale, so the \"Model schema drift check\" step of the Go tests job failed on main.\n\nThe snapshot is a CI drift guard only — it is never embedded or read at runtime,\nso the published v0.5.6 image is unaffected.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(models): regenerate schema snapshot for firmware_install_quiet_…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-17T07:13:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bdd17800451e9f86e3202e096c62091831d1fe4e",
          "body": "Firmware installs triggered from ShellyAdmin failed on every attempt, while\nthe same update applied fine from Shelly's cloud rollout or the device's own\nweb UI. The cause was ShellyAdmin itself.\n\ninstallOne began polling Shelly.GetDeviceInfo every 5s immediately after\ntriggering Shelly.Update. A dev\n[…]\nst firmware_check, so a device installing anything else was reported as\n\"unknown\" despite having updated. Any move off the original now counts.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v0.5.6 — stop starving the OTA we're waiting for",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-17T06:59:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "abcb6876542e9697290697a67eed2e9cb233f766",
          "body": "Bumps the go-dependencies group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/net](https://github.com/golang/net).\n\n\nUpdates `golang.org/x/crypto` from 0.53.0 to 0.54.0\n- [Commits](https://github.com/golang/crypto/compare/v0.53.0...v0.54.0)\n\nUpdates `golan\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the go-dependencies group with 2 updates (#81)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-13T17:53:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e80cde0ca1dbb3d9aa10913a5cd9f3d624ca078a",
          "body": "Bumps the npm-dev-dependencies group in /web with 5 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [@sveltejs/vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte/tree/HEAD/packages/vite-plugin-svelte) | `7.1.2` | `7.1.3` |\n| [@vitest/coverage-v8](https://github.com/vitest-dev\n[…]\npdate:semver-patch\n  dependency-group: npm-dev-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump the npm-dev-dependencies group (#80)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-06T17:49:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d0c03fcdfecf675ddf29508acbf4f1fec51011c8",
          "body": "Bumps the github-actions group with 5 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `4.1.0` | `4.2.0` |\n| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.1.0` | `4.2.0` |\n| [docker/lo\n[…]\nsion-update:semver-minor\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump the github-actions group with 5 updates (#79)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-06T17:48:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb7da0efdd0afe03c25b3aaa5fd6cdae57493882",
          "body": "Housekeeping roll-up, no runtime behaviour change:\n- Dependabot: Alpine runtime base 3.23→3.24 (CVE-clean, verified locally\n  with trivy: 0 HIGH/CRITICAL), node/golang build-stage digests, web dev-deps\n  (playwright/eslint/prettier/vitest/vite), CI actions (checkout v6→v7,\n  setup-go, golangci-lint)\n[…]\nonytail-audit dead-code removal (ProgressBar label prop, supportsWebSocket\n  placeholder, FirmwareUpdateResult type).\n\nBundles PRs #78, #77, #75 + the ponytail cleanup. Full changelog in\nCHANGELOG.md.",
          "is_bot": false,
          "headline": "release: v0.5.5",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T20:19:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f00efcf05735254886e0a9703254122334a539ad",
          "body": "…ates\n\nBumps the github-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/setup-go](https://github.com/actions/setup-go) and [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action).\n\n\nUpdates `actions/checkout\n[…]\n\n  dependency-version: 9.3.0\n  dependency-type: direct:production\n  update-type: version-update:semver-minor\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump the github-actions group across 1 directory with 3 upd…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-01T20:13:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "865978a90bacb9966c9ae98d90b8ef4f77ff954d",
          "body": "…y with 12 updates\n\nBumps the npm-dev-dependencies group with 10 updates in the /web directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [@playwright/test](https://github.com/microsoft/playwright) | `1.60.0` | `1.61.1` |\n| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint\n[…]\nndency-version: 4.1.9\n  dependency-type: direct:development\n  update-type: version-update:semver-patch\n  dependency-group: npm-dev-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump the npm-dev-dependencies group across 1 director…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-01T20:13:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a01b9862f9b9f25abb8e743e48389d1016829aeb",
          "body": "…h 3 updates\n\nBumps the docker-dependencies group with 3 updates in the /docker directory: node, golang and alpine.\n\n\nUpdates `node` from `144769e` to `725aeba`\n\nUpdates `golang` from `f23e8b2` to `3ad5730`\n\nUpdates `alpine` from 3.23 to 3.24\n\n---\nupdated-dependencies:\n- dependency-name: alpine\n  de\n[…]\npendencies\n- dependency-name: node\n  dependency-version: 26-alpine\n  dependency-type: direct:production\n  dependency-group: docker-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the docker-dependencies group across 1 directory wit…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-01T20:13:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dfaec4fbbeaea3c5eac1b5297fcef6b88a7ff6a7",
          "body": "Three verified-unused items (grep-confirmed zero references), net -37 lines:\n- ProgressBar `label` prop + both {#if label} branches + labelInside\n  reactive + .pb-label/.pb-label-below CSS — no caller ever passed label.\n- deviceFormatters.supportsWebSocket() — speculative placeholder, 0 callers.\n- t\n[…]\nt's other \"dead type\" hits (AltFirmwareVariant, FWResult,\nBulkActionTarget, ProvisionDeviceInfo/SectionResult) were false positives —\nall used via parent interfaces in api.ts — and were left in place.",
          "is_bot": false,
          "headline": "chore(web): remove dead code found by ponytail-audit",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T19:46:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "55b7117012705e9b8a304f345c84910c89e3e92d",
          "body": "The pinned digest carried libcrypto3/libssl3 3.5.6-r0 (openssl heap\nuse-after-free in PKCS7_verify, HIGH). Trivy gates publish-image.yml on\nHIGH/CRITICAL, blocking the v0.5.4 image release. Bumped to a newer\nalpine:3.23 point-in-time digest shipping 3.5.7-r0 (verified: same\nmulti-arch manifest list, amd64 included). Confirmed 0 vulns with a\nlocal build + trivy scan using the same severity/ignore-unfixed flags\nas CI before pushing.",
          "is_bot": false,
          "headline": "fix(docker): bump alpine 3.23 runtime base to clear CVE-2026-45447",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T19:26:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2c87b8a8a2c364540cfcceb37ace55f7c83dd0ea",
          "body": "…sioning\n\nThe v0.5.4 release commit failed CI: alt_firmware_test.go had two\nseparate import declarations instead of one grouped block (goimports),\nand schema.gen.json wasn't regenerated after adding FWAlt/Provisioning\nto models.Device (cmd/modelschema --check catches Go struct fields\nadded without an update to the tracked schema).",
          "is_bot": false,
          "headline": "fix(ci): goimports grouping + regenerate model schema for FWAlt/Provi…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T19:08:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "33fac53e3461b4c06c790e94368c22028b7bba3c",
          "body": "Shelly firmware 2.0.0-beta3 support: read-only visibility of alternative\nfirmware variants (sys.alt — Zigbee/Matter builds of the same hardware)\nand secure-provisioning status (sys.provisioning), surfaced on\n/api/devices, MCP get_device/list_devices, and the Firmware page. Purely\nadditive to the API/MCP surface; no install/auto-update capability added\n(Shelly.Update has no documented way to select alt firmware). Full\nchangelog in CHANGELOG.md.",
          "is_bot": false,
          "headline": "release: v0.5.4",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T18:57:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3adc8c9773a1822c9ca78eee66873582ccf30c75",
          "body": "…us (read-only)\n\nShelly firmware 2.0.0-beta3 adds an alt object (alternative firmware\nvariants, e.g. Zigbee/Matter builds of the same hardware) and a\nprovisioning object (secure-provisioning state) to Shelly.GetStatus's\nsys block. Both are derived from the already-cached RawStatus at\nGetDevices() ti\n[…]\nd> badge\non the Firmware page.\n\nRead-only by design: Shelly.Update has no stage:\"alt\" and the alt\nobject carries no url, so switching a device's firmware variant isn't\npossible via the documented API.",
          "is_bot": false,
          "headline": "feat(firmware): surface sys.alt firmware variants + provisioning stat…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-07-01T18:57:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "14925ffbb2631a2360fc94c59c569558a33ef8da",
          "body": "Bumps the npm-prod-dependencies group in /web with 1 update: [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte).\n\n\nUpdates `svelte` from 5.56.3 to 5.56.4\n- [Release notes](https://github.com/sveltejs/svelte/releases)\n- [Changelog](https://github.com/sveltejs/svelte/blob/main/pack\n[…]\ndate:semver-patch\n  dependency-group: npm-prod-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump svelte in /web in the npm-prod-dependencies group (#76)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-29T17:52:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "de84bdb9dbe9622b3038aa805950cf5be17637fe",
          "body": "Bumps the go-dependencies group with 1 update: [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).\n\n\nUpdates `modernc.org/sqlite` from 1.52.0 to 1.53.0\n- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)\n- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.52.0...v1.53.0)\n\n-\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump modernc.org/sqlite in the go-dependencies group (#73)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-22T17:49:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e24c2152ffd1403231887f2403546d47c236cb14",
          "body": "Transitive dev-only dependency via jsdom (test tooling); 7.28.0 stays\nwithin jsdom's ^7.25.0 range, so no jsdom bump needed. Clears the high\n-severity undici advisory cluster (TLS bypass via SOCKS5, cache\nwhitespace bypass, Set-Cookie injection, WS DoS, etc.). Not shipped in\nthe embedded SPA bundle \n[…]\n runtime impact, no release\nrequired. `npm audit` now reports 0 vulnerabilities.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(web): bump undici 7.25.0→7.28.0 to clear npm audit advisory (#72)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-20T16:35:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9124ae85c039c085f3b8e4a1ec2049db67c153de",
          "body": "Bumps [undici](https://github.com/nodejs/undici) from 7.25.0 to 7.28.0.\n- [Release notes](https://github.com/nodejs/undici/releases)\n- [Commits](https://github.com/nodejs/undici/compare/v7.25.0...v7.28.0)\n\n---\nupdated-dependencies:\n- dependency-name: undici\n  dependency-version: 7.28.0\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump undici from 7.25.0 to 7.28.0 in /web (#71)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-20T13:29:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a92002acd0314a78263020b1167bb5f407dde19f",
          "body": "Bumps the go-dependencies group with 1 update: [golang.org/x/net](https://github.com/golang/net).\n\n\nUpdates `golang.org/x/net` from 0.55.0 to 0.56.0\n- [Commits](https://github.com/golang/net/compare/v0.55.0...v0.56.0)\n\n---\nupdated-dependencies:\n- dependency-name: golang.org/x/net\n  dependency-versio\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump golang.org/x/net in the go-dependencies group (#69)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-15T17:51:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2759357a07f0f20ff603080d1c1c568968e49d77",
          "body": "services.GetSettings hands the tool the decrypted MCP token, so\nget_settings exposed it in plaintext over the MCP surface — the HTTP API\nGET handler has always masked it to services.MCPTokenRedacted (\"<set>\")\nbefore the SPA sees it. The comment above the tool even said AppSettings\ncarries no secret \n[…]\nact.go gains a redaction-inventory note so the next secret-bearing\ntool finds the pattern. Regression test asserts the placeholder comes\nback and the plaintext never appears in the structured content.",
          "is_bot": false,
          "headline": "fix(mcp): redact the MCP token in the get_settings tool",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T18:54:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d39b4ab8a9f9b59b8f73ad6328d78c01b4f466f1",
          "body": "…ardening summary\n\nThe German README's Status section had drifted: it named only the\nv0.4.0 UI/API baseline and never the current release, while the English\none carries both. Now mirrors README.md's v0.5.3 status.",
          "is_bot": false,
          "headline": "docs(readme.de): mirror the English status line — current release + h…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T18:32:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "acb644c56f8d3e359d974456c233405d648beb47",
          "body": "DEPLOYMENT.md's env table still said 'losing or rotating it orphans\nevery stored credential' — rotation is supported as of v0.5.3, only\nloss (or an unrotated swap) orphans. Both READMEs (en/de) get the same\ncorrection plus a pointer to the rotate-key procedure in\ndocs/SECURITY.md.",
          "is_bot": false,
          "headline": "docs: point key-loss warnings at shellyctl rotate-key",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T18:21:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c3bd5fbb26e88c3625f6231be8f701b6b53feaec",
          "body": "Hardening release — items 1–8 from the June 2026 architecture/security\nreview. Adds shellyctl rotate-key, template-section save-time validation,\nand the frontend coverage gate; hardens shellyclient (4 MiB response cap,\nJSON-RPC envelope validation); CI runs -race; internal/db split by domain;\nSECURITY.md refreshed (MCP token hygiene, encryption-at-rest rewrite, key\nrotation procedure). Full changelog in CHANGELOG.md.",
          "is_bot": false,
          "headline": "release: v0.5.3",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T18:12:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b52e3485c2522debc12c236e4f19970b6c83bf87",
          "body": "Review item 8, the last open item from the June 2026 architecture/\nsecurity review. Rotating SHELLYADMIN_ENCRYPTION_KEY used to require the\nmanual playbook documented in docs/SECURITY.md: export with secrets,\ndisable TOTP, clear the MCP token, delete every credential group while\nthe old key is still\n[…]\nleads\nwith the command; the manual playbook remains in git history as the\nfallback for older versions. CLAUDE.md notes the invariant: a new sealed\ncolumn anywhere must be added to RotateSealedColumns.",
          "is_bot": false,
          "headline": "feat(cli): shellyctl rotate-key — one-shot encryption-key rotation",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T18:12:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2b49aeec54645b7ed80deaa6b9fcadd24af05609",
          "body": "The Go side has had a 45% coverage floor since v0.3.0; the frontend\nunit tests ran without one (review item 7). vitest now runs with\n@vitest/coverage-v8 and a 30% statements/lines threshold\n(vitest.config.ts), measured 35.7%/37.1% at introduction — same\n~6-point regression-guard headroom as the Go g\n[…]\nets extracted into .ts\nmodules first (the navbar.ts / state.ts pattern).\n\nThe Frontend-build required check runs npm run test:coverage; the\ngenerated web/coverage/ output is git- and prettier-ignored.",
          "is_bot": false,
          "headline": "ci(web): add frontend unit-test coverage gate",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:49:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0325f4285c6c0a9d82afc91195a904b293ab29f9",
          "body": "db.go had grown to 1282 lines bundling connection lifecycle, schema\nmigration, and every query in the package — the single biggest\nchange-magnet in the backend (review item 6). It now keeps only\nOpen/Close, migrate, SnapshotTo, and the package-wide helpers\n(decryptCipher, now, boolToInt); the querie\n[…]\npersonal access token rows\n  runtimelock.go  single-instance lock rows\n\nPure move — no body changed, verified by the services.Store interface\ncompile assertion (108 methods) plus the full -race suite.",
          "is_bot": false,
          "headline": "refactor(db): split db.go into domain files",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:49:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce8da5be2499e598517f5c876cf8a5cc2073d08b",
          "body": "Unknown top-level template keys used to fall through to the\n<Capitalized>.SetConfig catch-all and only fail at the device — a typo\nlike \"syss\" surfaced as a silent 'skipped' section on every device of\na fleet provision run. validation.Template now checks each key against\nthe canonical section list (\n[…]\nn unchanged; the gate is\nsave-time only (templates UI, API, backup import).\n\nThe credential_ref existence check flagged in the review already\nexists in templates.Service.Save — no change needed there.",
          "is_bot": false,
          "headline": "feat(provision): reject unknown template sections at save time",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:49:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "706e65be46d1947b0c33254d89bf9906eead1e16",
          "body": "Two gaps from the architecture/security review, plus stale content\nfixed in passing:\n\n- New 'MCP Listener Token Hygiene' section: the path-segment auth form\n  writes the token into anything that logs request paths (proxy access\n  logs, container stdout aggregation, browser/shell history). Prefer\n  t\n[…]\nhen re-imports.\n\n- Stale claims fixed: 'external API tokens' removed from the\n  intentionally-not-included list (PATs shipped in v0.3.0);\n  Authentication section now mentions TOTP 2FA and PAT scopes.",
          "is_bot": false,
          "headline": "docs(security): MCP token hygiene + key backup and rotation playbook",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:24:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "89aab879b6a4227bac4359afd884ae6b84295761",
          "body": "RPC() discarded unmarshal errors, so a 200 with a garbage body (captive\nportal, HTML error page from a misbehaving LAN endpoint) returned\n(nil, nil) — success with an empty result, indistinguishable from a\nlegitimate response. Success statuses now require a parseable envelope:\nempty bodies and inval\n[…]\nare 200 and no body,\nwhich no real Shelly does; it now returns a minimal valid envelope.\nA null result ({\"id\":1,\"result\":null}, Shelly.Reboot and friends)\nkeeps working — covered by a regression test.",
          "is_bot": false,
          "headline": "fix(shellyclient): validate JSON-RPC response envelopes",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:24:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5f684f262edf788e945b368447bf209afbd6da6c",
          "body": "AppService guards shared state with several mutexes (mu, authMu,\njobSpawnMu) plus a WaitGroup; lock-discipline regressions are\ninvisible to plain tests but trip the race detector. -covermode=atomic\nwas already in place, so -race slots in without changing the coverage\ngate. Full suite verified race-clean locally; internal/api runs\nnoticeably slower under -race (~164s) but well within job limits.",
          "is_bot": false,
          "headline": "ci(test): run the Go test suite with -race",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:24:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47ce7bd88ed74fdf1cf9d3dd6d63c6242f167cd1",
          "body": "Probe() and RPC() read response bodies via io.ReadAll with no size\nlimit, so a single misbehaving or hostile LAN endpoint streaming a\nmulti-GB response could OOM the scan/refresh workers. Both paths now\ngo through readBodyLimited(), which reads at most 4 MiB and fails\nwith an explicit size error ins\n[…]\nnfusing JSON parse error downstream).\n\nReal Shelly payloads top out in the tens of KB, so 4 MiB is generous\nheadroom. Regression tests stream an oversized body against both the\n/shelly and /rpc paths.",
          "is_bot": false,
          "headline": "fix(shellyclient): cap device response bodies at 4 MiB",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-06-10T17:24:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "22cb59638c93359fb20767765a439992e620e972",
          "body": "…tes (#55)\n\nBumps the docker-dependencies group in /docker with 2 updates: node and golang.\n\n\nUpdates `node` from `e71ac5e` to `144769e`\n\nUpdates `golang` from `91eda97` to `f23e8b2`\n\n---\nupdated-dependencies:\n- dependency-name: node\n  dependency-version: 26-alpine\n  dependency-type: direct:producti\n[…]\n: direct:production\n  dependency-group: docker-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the docker-dependencies group in /docker with 2 upda…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-09T07:50:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "48308d71c63fe3baadd35333318ef1930aca4afa",
          "body": "Bumps the npm-dev-dependencies group in /web with 1 update: [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser).\n\n\nUpdates `svelte-eslint-parser` from 1.7.1 to 1.8.0\n- [Release notes](https://github.com/sveltejs/svelte-eslint-parser/releases)\n- [Changelog](https://github.com/sve\n[…]\npdate:semver-minor\n  dependency-group: npm-dev-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump svelte-eslint-parser (#61)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-08T17:48:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "95c280007c76884ab823db7262917cafe1e831c5",
          "body": "Bumps the npm-prod-dependencies group in /web with 1 update: [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte).\n\n\nUpdates `svelte` from 5.56.1 to 5.56.3\n- [Release notes](https://github.com/sveltejs/svelte/releases)\n- [Changelog](https://github.com/sveltejs/svelte/blob/main/pack\n[…]\ndate:semver-patch\n  dependency-group: npm-prod-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump svelte in /web in the npm-prod-dependencies group (#62)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-08T17:47:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "01848db8e5075edfae90546bc9b057e8b172c841",
          "body": "Bumps the go-dependencies group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).\n\n\nUpdates `golang.org/x/crypto` from 0.52.0 to 0.53.0\n- [Commits](https://github.com/golang/crypto/compare/v0.52.0...v0.53.0)\n\nUpdates `m\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the go-dependencies group with 2 updates (#60)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-08T17:47:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1ad9bb26c74a4192e69cdf96c0e05b83e213b40b",
          "body": "Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.59.0 to 0.59.1.\n- [Release notes](https://github.com/quic-go/quic-go/releases)\n- [Commits](https://github.com/quic-go/quic-go/compare/v0.59.0...v0.59.1)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/quic-go/quic\n[…]\ngo\n  dependency-version: 0.59.1\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump github.com/quic-go/quic-go from 0.59.0 to 0.59.1 (#59)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-03T21:22:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "db4baa43c432dc79803d70196f6da7e410907938",
          "body": "Bumps the npm-prod-dependencies group in /web with 1 update: [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte).\n\n\nUpdates `svelte` from 5.55.9 to 5.56.1\n- [Release notes](https://github.com/sveltejs/svelte/releases)\n- [Changelog](https://github.com/sveltejs/svelte/blob/main/pack\n[…]\ndate:semver-minor\n  dependency-group: npm-prod-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump svelte in /web in the npm-prod-dependencies group (#58)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-03T02:09:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "27ae0331f811dc8f0da08ee4d31de99224b319d6",
          "body": "Bumps the npm-dev-dependencies group in /web with 10 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.60.0` | `8.60.1` |\n| [@typescript-eslint/parser](https://githu\n[…]\npdate:semver-patch\n  dependency-group: npm-dev-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump the npm-dev-dependencies group (#57)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-03T02:09:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "28fa5e3f9adc7b76a78b94338670c7f06d9e5650",
          "body": "Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action).\n\n\nUpdates `actions/checkout` from 6.0.2 to 6.0.3\n- [Release notes](https://github.com/actions/checkout/releases)\n- [Chan\n[…]\nsion-update:semver-minor\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump the github-actions group with 2 updates (#56)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-03T02:08:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9ea5efdc713c56b132b2d6ee17fc0cb3d8624773",
          "body": "Bumps the go-dependencies group with 1 update: [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).\n\n\nUpdates `modernc.org/sqlite` from 1.50.1 to 1.51.0\n- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)\n- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.50.1...v1.51.0)\n\n-\n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump modernc.org/sqlite in the go-dependencies group (#54)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-03T02:07:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ac0524501401bee41d77aff3f1ab89c8fcd6ebf1",
          "body": "README Status line now states the current release (v0.5.2) while noting the\nUI/API baseline is unchanged since v0.4.0 (v0.5.x are launch/fix/refactor\nreleases). Roadmap \"Now\" bumped to v0.5.x and \"Recently shipped\" gains the\nv0.5.0–v0.5.2 entries.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: refresh version baseline + roadmap for v0.5.2 (#53)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-29T10:48:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a6b322b031e5faf0ea97880ab47a10bd97e085d",
          "body": "….2 (#52)\n\nReplace the StartScan MCP-field-clearing special case with a focused\nvalidation.ScanParams that validates only scan parameters (subnets,\ntimeouts, concurrency) and returns the target count. This also removes\nthe duplicate CIDR expansion StartScan recomputed after the old\nValidateSettings \n[…]\nthe raw DB row no longer blocks a scan\n(validation_test.go + scan_test.go).\n\nBump VERSION / web package / CHANGELOG / SECURITY to 0.5.2.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "refactor(scan): extract ScanParams validator + regression tests; v0.5…",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-29T07:18:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1035b6afc837c6e55d13875572af7507f482ff89",
          "body": "…-dev-dependencies-0a68a61dc3\n\ndeps(deps-dev): bump the npm-dev-dependencies group in /web with 7 updates",
          "is_bot": false,
          "headline": "Merge pull request #50 from buliwyf42/dependabot/npm_and_yarn/web/npm…",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-26T04:31:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dbbf1709174bcb0cf9ea64fd2444bc1e34bcb980",
          "body": "Bumps the npm-prod-dependencies group in /web with 1 update: [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte).\n\n\nUpdates `svelte` from 5.55.8 to 5.55.9\n- [Release notes](https://github.com/sveltejs/svelte/releases)\n- [Changelog](https://github.com/sveltejs/svelte/blob/main/pack\n[…]\ndate:semver-patch\n  dependency-group: npm-prod-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump svelte in /web in the npm-prod-dependencies group (#51)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-05-25T23:42:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "24d0f9bbc5e1ce21b511b8e4319503a1f78bb52f",
          "body": "Bumps the go-dependencies group with 3 updates: [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk), [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/net](https://github.com/golang/net).\n\n\nUpdates `github.com/modelcontextprotocol/go-sdk` \n[…]\nion-update:semver-minor\n  dependency-group: go-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps(deps): bump the go-dependencies group with 3 updates (#48)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-05-25T23:42:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ec03e4910ed8ded37048111944c30e80402d8237",
          "body": "Bumps the github-actions group with 5 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.0.0` | `4.1.0` |\n| [docker/login-action](https://github.com/docker/login-action) | `4.1.0` | `4.2.0` |\n| [docker/metadata-act\n[…]\nsion-update:semver-patch\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump the github-actions group with 5 updates (#49)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-05-25T23:41:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0fbac739edb6aff831ab185ffcb6f903c0796497",
          "body": "Bumps the npm-dev-dependencies group in /web with 7 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.59.4` | `8.60.0` |\n| [@typescript-eslint/parser](https://github\n[…]\nndency-version: 4.1.7\n  dependency-type: direct:development\n  update-type: version-update:semver-patch\n  dependency-group: npm-dev-dependencies\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(deps-dev): bump the npm-dev-dependencies group",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-05-25T23:40:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8961fe2ad035c347b080e81704c0282e1f5acd00",
          "body": "StartScan reads the raw DB row whose MCPToken is secretbox-encrypted\nciphertext, not plaintext. ValidateSettings then failed the URL-safe\nalphabet check against the ciphertext, blocking every scan when MCP\nwas enabled. Strip MCPToken/MCPEnabled from the local copy before the\nformat check — the token was already validated at save time and is\nirrelevant to scan-parameter validation.\n\nBumps to v0.5.1.",
          "is_bot": false,
          "headline": "fix(scan): skip encrypted MCP token when validating settings before scan",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-24T19:09:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b142610a82327caae589fffb29dc0293d2db2de6",
          "body": "The session cookie key and server-side session row were written with\nthe operator-supplied req.Username rather than the verified canonical\nadminUser from adminCredential(). Not exploitable today (ConstantTimeCompare\nguarantees byte identity at that point), but using the resolved value is\nthe correct invariant and removes any future risk if username comparison\nis ever loosened.",
          "is_bot": false,
          "headline": "fix(auth): store canonical adminUser in session, not req.Username",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T18:39:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e5543a9ad77f1516aa7d87d6f86f3a2fcd5908bd",
          "body": "ChangeAdminCredential now reads the old username before overwriting\nadmin_credentials, then renames the totp_state row to the new key so\nactive 2FA enrollment is not silently dropped when the operator\nrenames their account. sql.ErrNoRows (TOTP not enrolled) is a no-op;\nany other DB error aborts the \n[…]\nation and the no-op path.\n\nvite.config.ts: replace ?? with a ternary for VITE_ALLOWED_HOSTS so\nan empty-string value falls back to ['localhost'] rather than the\nuseless [''] produced by ''.split(',').",
          "is_bot": false,
          "headline": "fix(auth): migrate TOTP row on username rename; guard vite allowedHosts",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T18:31:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "96e253f8d385fd431d02a39193b976e887380f76",
          "body": "bug_report.yml: expanded from 5 fields to 11, with project-specific\ncontext that actually helps triage —\n\n  - pre-flight checklist (searched issues, not a security report,\n    checked CHANGELOG) gates the form so duplicates and misdirected\n    security reports drop sharply\n  - explicit redaction rem\n[…]\n\nrepo: NOT a public template (which would expose the vulnerability\nin the act of filing it), but a config.yml deflection that catches\npeople at the 'New issue' chooser before they pick the wrong path.",
          "is_bot": false,
          "headline": "docs: deepen issue templates + add config.yml for security routing",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T09:20:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ed4b0abc7d4504a57dbc6dce4b6f366105fde44a",
          "body": "Adds a full German translation of the landing-page README alongside\nthe English one, with reciprocal language-switcher links at the top\nof each file ('English | **Deutsch**' and inversely).\n\nThe English README stays primary (default landing page, SEO, GitHub\nauto-detection). README.de.md mirrors its\n[…]\nands, and image URLs\nare preserved verbatim. Technical product terms (Docker, MCP, GHCR,\nSQLite, Compose, Vite, SemVer) stay in English as is conventional in\nGerman technical writing.\n\nPrettier-clean.",
          "is_bot": false,
          "headline": "docs: add German README (README.de.md) with language switcher",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T09:14:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f311e6ec53eb1ee957ddff7058282c8be4b95bca",
          "body": "When the repo flipped from private to public for v0.5.0, GitHub\nsilently reset default_workflow_permissions to 'read'. The\npublish-image workflow declares job-level contents: write, which\nshould override the default, but the gh release create step still\nreturned 401 Bad credentials at the end of an \n[…]\nin docs/DEVELOPMENT.md > CI Gates & Branch Protection,\nwith the one-line API fix and the manual-Release fallback. Saves the\nnext maintainer (or me, on a different repo) from the same debugging\ndetour.",
          "is_bot": false,
          "headline": "docs: note the post-public-flip workflow-permissions gotcha",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T09:11:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7f9b4a71f65a3c522eeff93f95b46f05579d492f",
          "body": "This release captures the going-public hygiene pass — no behavior\nchanges, every diff is docs, build, or test fixtures. See\nCHANGELOG.md [0.5.0] for the full surface.\n\nVERSION + web/package.json + lockfile bumped from 0.4.0 to 0.5.0\ntogether. Frontend rebundled so the embedded SPA shows v0.5.0 in\nthe navbar.",
          "is_bot": false,
          "headline": "release: v0.5.0 — first public release",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:52:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27fb33755dfac75c9613f917eb5e0746956a2e14",
          "body": "Devices view (the rich fleet inventory) becomes the hero shot directly\nunder the intro paragraph — single highest-impact 'this is real\nsoftware' signal for the public landing page. The other four (Scan,\nFirmware, Provision, Compliance) live in a collapsed <details> block\nbelow so they don't bloat th\n[…]\nfleet, so they show realistic\nscale without leaking infrastructure detail.\n\ndocs/screenshots/: new directory, 5 PNGs (~4.4 MB total).\nREADME.md: placeholder HTML comment replaced with the real images.",
          "is_bot": false,
          "headline": "docs: add product screenshots to the README",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:43:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c2d538cfd86145fe50816e27e49c9809fa95beb",
          "body": "Now that the repo is public, the README is the front door. This pass\naddresses the gaps surfaced in review.\n\nAdded:\n- Five badges (CI status, MIT license, latest release, GHCR link,\n  Go Report Card) for credibility / quick-glance status\n- 'Why ShellyAdmin?' motivation paragraph explaining where the\n[…]\nks Today' section (duplicated Current Feature Set)\n- 'Not Production-Grade Yet' section (covered by Status > Intended\n  posture bullets)\n\nPrettier-clean.\n\nREADME: 300 -> 284 lines, content density up.",
          "is_bot": false,
          "headline": "docs: rewrite README for the public landing page",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:40:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b1225688d876621b38bb9389c72a11b3a308427c",
          "body": "Follow-up to commit 4d64f3d after a second pass surfaced six occurrences\nof mqtt.home.lan still in test fixtures and eleven historical references\nto /docker/shellyadmin, docker.home.lan, and 'Dockhand' in CHANGELOG.md.\n\nTest files: mqtt.home.lan -> mqtt.example.test (RFC 6761 reserved test\nTLD, obvi\n[…]\nainer manager' so the\nhistorical release notes stay accurate without leaking the maintainer's\nspecific tooling. Public readers no longer see references to a tool that\nappears nowhere else in the repo.",
          "is_bot": false,
          "headline": "chore: scrub residual personal hostnames and tool names",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:21:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dbf2570b5fba1bac0dc95143b9fd23c3702a4f10",
          "body": "…ENT.md\n\nCLAUDE.md is going public alongside the rest of the repo. Strip the\nthree ops-heavy sections that aren't code-adjacent and reattach them\nto docs/DEVELOPMENT.md, which is already the home for build/test/dev\ndocs.\n\nMoved:\n- Deployment Workflow (compose stack shape, release path, pre-deploy\n  \n[…]\nt branch\nprotection becomes free once the repo flips public; Pro is what made\nit enforceable while the repo was private.\n\nCLAUDE.md: 369 → 276 lines (~25% smaller)\ndocs/DEVELOPMENT.md: 183 → 273 lines",
          "is_bot": false,
          "headline": "docs: move deploy/release/CI sections from CLAUDE.md to docs/DEVELOPM…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:17:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7e769b459ed0cb51ed94ed5e70cc6fb1b9f967ca",
          "body": "The Dockerfile uses COPY . . in the backend stage, so without a\n.dockerignore a local 'docker build' from this repo ships the\nmaintainer's working-tree state (data/ live SQLite + encryption key\nfile, .devlogs/, .claude/, bin/, secrets/, web/node_modules, etc.)\ninto the build context. Published GHCR \n[…]\nrkdown (docs/, *.md, LICENSE, CHANGELOG)\n- test/coverage artifacts\n\nThe cmd/shellyctl/dist exclusion is safe because the Dockerfile\nalready overwrites it via COPY --from=frontend before go build runs.",
          "is_bot": false,
          "headline": "build: add .dockerignore to scope local rebuilds away from live state",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:14:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7334ade725234006a2f1f44883fba0e98c832164",
          "body": "…erated\n\ndocs/plans/README.md: move Phase-4b, Phase-4c, and v0.3.0 from Active to\nShipped (all landed in v0.3.x), remove pointer to the maintainer's local\nplan file, and reframe the folder as historical/archival reference.\n\n.gitattributes: mark cmd/shellyctl/dist/** as linguist-generated and\nsuppres\n[…]\niffs for it so the embedded SPA bundle (produced by the web\nbuild, checked in for //go:embed) doesn't dominate diffs or language\nstats on GitHub. Also pin LF endings for shell scripts and Dockerfiles.",
          "is_bot": false,
          "headline": "docs: archive shipped release plans + mark embedded SPA bundle as gen…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:04:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8715a456f6de919d5070c8fe2e8abee0be1dbf6a",
          "body": "Adds a short CODE_OF_CONDUCT.md pointing to the canonical Contributor\nCovenant v2.1 text, with a reporting channel (GitHub private security\nadvisory) and scope/enforcement notes. Closes the last gap in GitHub's\ncommunity profile checklist before flipping the repo public.",
          "is_bot": false,
          "headline": "docs: add Code of Conduct (Contributor Covenant v2.1)",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:03:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d64f3d0ee8aa55dc16f2dbc7d22d065e6389d05",
          "body": "Scrub personal/homelab specifics (docker.home.lan, devhost.home.lan,\n/docker/shellyadmin, mqtt.home.lan, \"buliwyf_iot\") and Dockhand-specific\nreferences from public-facing files. Replace with generic placeholders\n(`<data-dir>`, \"container manager\", env-driven config) so the repo\ndocumentation and sh\n[…]\nd v0.1.19) removed; docker/docker-compose.yml is the canonical example\n- web/vite.config.ts: allowedHosts now driven by VITE_ALLOWED_HOSTS env (defaults to localhost)\n- Rebundle of embedded SPA assets",
          "is_bot": false,
          "headline": "chore: generalize internal hostnames and paths for public release",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-23T08:00:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9342aa5731d2d8f55e6228818df156c134cc08ce",
          "body": "Sweep the remaining docs for the stale \"login is env-required, missing\nSHELLYADMIN_PASS_HASH panics at startup\" model:\n- SECURITY.md + docs/SECURITY.md: rewrite the admin-credential section for\n  first-run setup (DB-backed login, optional env import seed, reset-auth\n  recovery); fix the now-false pr\n[…]\nted, CLI writes optional);\n  add v0.4.0/v0.3.6/v0.3.5 to recently-shipped.\n- docs/adr/README.md: list ADR-0017.\n\nHistorical records (CHANGELOG, older ADRs, version-history rows) left as\npoint-in-time.",
          "is_bot": false,
          "headline": "docs: bring security/roadmap docs current with v0.4.0 first-run setup",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T18:45:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e6deb605f30d8da95eb8d2f41b0b6b8386842766",
          "body": "Record the same drop/skip reasoning applied to T2/T7:\n- T4 HSM/PKCS11 key provider — dropped (no value without HSM hardware; the\n  at-rest-key threat is already closed by S6/ADR-0013).\n- T9 external pen test — skip unless internet-exposed (self-run ZAP/nuclei is\n  the cheap substitute).\n- T12 standalone-binary signing — skip until binaries are distributed; the\n  Docker image is already cosign-signed in CI.\n\nLeaves the shellyctl write commands as the only live, genuinely-useful\nbacklog item.",
          "is_bot": false,
          "headline": "docs: triage T4/T9/T12 against the single-user/LAN/Docker reality",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T18:17:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f26043d22e48071048bf7095ce4f6cc338ca308e",
          "body": "Decided to defer the API version-prefix shim to the v1.0 cut rather than\nbuild it pre-1.0: it's pure plumbing with no payoff until a breaking\n/api/v2 exists, and a single-operator tool absorbs breaking changes by\nupdating the SPA + own scripts in lockstep. Record the rationale and the\nsizing (54 routes + ~51 client refs) next to the policy.",
          "is_bot": false,
          "headline": "docs: mark T7 (/api/v1 prefix) as explicitly v1.0-gated",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T18:02:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26ae1d6f20a39e0e878cb3a8e49726a0cd35f11c",
          "body": "WebAuthn needs a secure context (HTTPS); prod is trusted-LAN plain HTTP, so\npasskeys can't run without a TLS-proxy rebuild. For a single-operator internal\ntool the phishing-resistance payoff doesn't justify that — password (DB-backed\nsince v0.4.0) + TOTP + PATs already cover the threat model. Marked won't-do;\nrevisit only if the tool goes multi-user or internet-exposed.",
          "is_bot": false,
          "headline": "docs: drop T2 WebAuthn/passkeys from the roadmap",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T17:16:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e68c8d297c42043ecef2d7e0425805db21a6a54e",
          "body": "Bump VERSION, web/package.json, lockfile, and CHANGELOG for the v0.4.0\nfirst-run-setup release (operator login moves from env into the database;\nSHELLYADMIN_PASS_HASH is now an optional one-time import seed).",
          "is_bot": false,
          "headline": "release: v0.4.0 — first-run setup",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T16:16:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c44e8716c7cfa249f446677b40122542e5767ba",
          "body": "The operator login is no longer required via env (ADR-0017). Update the\nREADME quick-start, DEPLOYMENT env table, and both compose files to present\nSHELLYADMIN_PASS_HASH as an optional one-time import seed, point operators at\nthe first-run setup screen, and mention shellyctl reset-auth for recovery.\nThe root compose no longer hard-fails when the hash is unset.",
          "is_bot": false,
          "headline": "docs: reflect optional SHELLYADMIN_PASS_HASH + first-run setup",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T15:41:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ccb0b4de6e6f950e32533151dc0f8ab09059ff2",
          "body": "Move the operator login (username + argon2id hash) out of the\nSHELLYADMIN_PASS_HASH / SHELLYADMIN_USER env vars and into a dedicated\nadmin_credentials table (migration 031), so a fresh instance boots into a\nsetup screen instead of panicking on a missing hash. Existing deployments\nupgrade seamlessly:\n[…]\n clears the credential for forgotten-password\n  recovery, mirroring shellyctl unlock.\n- SPA: first-run setup page + Settings account card, gated on setup status.\n\nSee docs/adr/0017-first-run-setup.md.",
          "is_bot": false,
          "headline": "feat(auth): first-run setup — operator login in the DB",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T15:33:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b99310f10a5054ab5e518294b3213be830d0929",
          "body": "Extends the shellyctl CLI (ADR-0016) with two more read-only commands over\nthe existing /api surface:\n- `firmware`  -> GET /api/firmware/status: check state + per-device table\n  (current/stable/beta versions, which channel has an update, status/note).\n- `templates` -> GET /api/templates: provisionin\n[…]\n adding server surface.\n\nUnit tests for updateFlag + firmware-status decode; live-verified against a\nrunning instance with an admin PAT.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "feat(cli): add read-only firmware + templates commands (#47)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T14:51:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d5c2554bdee3854fe136bdcff5361b5bb2cf65b2",
          "body": "…y (#46)\n\nThe encryption key became mandatory in v0.3.0 (S6/ADR-0013 — the binary\nrefuses to start without it), but the deploy docs and the shipped compose\nfile still described it as optional/auto-generated. As a result the\nquick-start `docker run` examples and `docker compose up` would panic at\nsta\n[…]\nthat wrote random bytes (not an argon2id hash) as the password\n  and claimed plaintext SHELLYADMIN_PASS still works (removed in v0.2.0).\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: make deploy artifacts reflect the v0.3.0 required encryption ke…",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T14:47:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1112d4f389efed4135e8cc58f8aa5f47d6a55991",
          "body": null,
          "is_bot": false,
          "headline": "Release v0.3.6 — shellyctl CLI, E2E + unit tests, deploy/test tooling",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T12:14:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "981b075eda3d479142f7f7f66743008bdd531beb",
          "body": "Several docs linked with an absolute filesystem path\n(/Users/.../shellyadmin/...) that only resolved on one machine and leaked\na local home directory into the repo. Switch them to repo-relative links\nso they work for every reader and on GitHub.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: use relative markdown links instead of absolute local paths (#45)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T11:08:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bf91b2f2e81e1d44c51a5d4178aeace91482511",
          "body": "Stand up Playwright E2E (chromium) covering the flows verified by hand\nduring the responsive/a11y pass: login → shell, desktop horizontal nav\n(no hamburger), mobile hamburger drawer (open + link-click-closes), and\nthe single-leading-v version badge.\n\nAdds a non-required `E2E (Playwright)` CI job tha\n[…]\ncs against it. Kept off the required-checks list so an occasional E2E\nflake never blocks a merge while still surfacing real regressions.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test(e2e): Playwright smoke tests for login + responsive nav (T8) (#44)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T11:04:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fe107299f8e1f66cf0518ace3e4900efe56e6765",
          "body": "Adds an operator CLI that queries a running instance over /api with a\nPersonal Access Token: `devices` (list), `device <mac|ip|name>` (detail),\n`logs` (audit tail). Human tables by default, --json for raw payloads;\n--url/--token (or SHELLYADMIN_URL/SHELLYADMIN_TOKEN). main.go routes a\nmatching verb \n[…]\ngainst a live\ninstance (login → mint PAT → devices/logs/auth-failure) plus unit tests\nfor the transport, decode, and arg/format helpers.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "feat(cli): read-only shellyctl CLI (HTTP + PAT) — ADR-0016 (#43)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T10:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ef3214541bc9e9b853e7053572842cadc10ee904",
          "body": "Mirror the SortHeader pattern: pull the navbar's pure logic out of the\n.svelte component into navbar.ts so it can be unit-tested without\nrendering. Covers the version-badge leading-v strip (the vv0.3.x fix) and\nthe active-link detection (incl. Devices \"/\" owning /devices/:id routes).\nAdds navbar.test.ts (9 cases); Navbar.svelte now delegates to the module.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test(web): extract navbar logic to a unit-tested module (#42)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T10:46:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4cf55ec8776ee36b2953ae51f43fd847190d8e0f",
          "body": "Dockhand's exec_container can't write a snapshot file into the\nread-only-rootfs container, so the pre-deploy SQLite snapshot must run on\nthe host. Add scripts/snapshot-prod-db.sh (SSH-based, timestamped copy +\nrecent-snapshot listing) and document the pre-deploy step in\ndocs/DEPLOYMENT.md.\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "chore: add host-side pre-deploy DB snapshot script + docs (#41)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T10:42:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b3b7a44a19085785b84045f1f446a407c7ed4f1",
          "body": "…e-build gate",
          "is_bot": false,
          "headline": "Release v0.3.5 — Responsive nav + a11y, table-overflow fixes, CI imag…",
          "author_name": "buliwyf42",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T09:58:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6e742e1d8cb90de0cccb36606ee08906fc7612f",
          "body": "Small badge labels (0.67rem bold) with white text on the old --danger\n(#e04b5b, 3.94:1) and --success (#27b36a, 2.71:1) fell below the 4.5:1\nAA threshold for small text. Both tokens are only consumed by the\n.bg-danger/.bg-success badge backgrounds, so darkening them is contained:\n--danger -> #c93544 (5.15:1), --success -> #18804a (4.97:1).\n\nCo-authored-by: buliwyf42 <buliwyf42@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(web): darken --danger/--success so badge text meets WCAG AA (#40)",
          "author_name": "Dominik Sennfelder",
          "author_login": "buliwyf42",
          "committed_at": "2026-05-20T09:54:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 70,
      "commits_last_year": 325,
      "latest_release_at": "2026-07-23T06:21:10Z",
      "latest_release_tag": "v0.6.3",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 16,
      "days_since_latest_release": 1,
      "mean_days_between_releases": 6.6
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 100,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 0,
      "stars": 3,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 3
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "web/tsconfig.json"
      ],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 52308,
      "source_files_sampled": 209,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 43430
    },
    "dependencies": {
      "manifests": [
        "go.mod",
        "web/package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "brace-expansion",
            "direct": false,
            "version": "5.0.6",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-3jxr-9vmj-r5cp"
            ],
            "fixed_version": "5.0.7",
            "advisory_count": 1,
            "oldest_advisory_days": 3
          },
          {
            "name": "golang.org/x/crypto",
            "direct": true,
            "version": "v0.54.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5932"
            ],
            "fixed_version": null,
            "advisory_count": 1,
            "oldest_advisory_days": 16
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 1,
          "unknown": 1
        },
        "advisory_count": 2,
        "affected_count": 2,
        "assessed_count": 334,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "go",
        "npm"
      ],
      "dependencies": [
        {
          "name": "github.com/gin-contrib/sessions",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.0"
        },
        {
          "name": "github.com/gin-gonic/gin",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.12.0"
        },
        {
          "name": "github.com/modelcontextprotocol/go-sdk",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.1"
        },
        {
          "name": "golang.org/x/crypto",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.54.0"
        },
        {
          "name": "golang.org/x/mod",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.38.0"
        },
        {
          "name": "golang.org/x/net",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.57.0"
        },
        {
          "name": "gopkg.in/natefinch/lumberjack.v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.2.1"
        },
        {
          "name": "modernc.org/sqlite",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.54.0"
        },
        {
          "name": "qrcode",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.5.4"
        },
        {
          "name": "svelte",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.56.6"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/gin-contrib/sessions",
            "direct": true,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gin-gonic/gin",
            "direct": true,
            "version": "v1.12.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/modelcontextprotocol/go-sdk",
            "direct": true,
            "version": "v1.6.1",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/crypto",
            "direct": true,
            "version": "v0.54.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/mod",
            "direct": true,
            "version": "v0.38.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/net",
            "direct": true,
            "version": "v0.57.0",
            "ecosystem": "go"
          },
          {
            "name": "gopkg.in/natefinch/lumberjack.v2",
            "direct": true,
            "version": "v2.2.1",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/sqlite",
            "direct": true,
            "version": "v1.54.0",
            "ecosystem": "go"
          },
          {
            "name": "qrcode",
            "direct": true,
            "version": "1.5.4",
            "ecosystem": "npm"
          },
          {
            "name": "svelte",
            "direct": true,
            "version": "5.56.6",
            "ecosystem": "npm"
          },
          {
            "name": "github.com/bytedance/gopkg",
            "direct": false,
            "version": "v0.1.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/bytedance/sonic",
            "direct": false,
            "version": "v1.15.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/bytedance/sonic/loader",
            "direct": false,
            "version": "v0.5.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cloudwego/base64x",
            "direct": false,
            "version": "v0.1.6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dustin/go-humanize",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gabriel-vasile/mimetype",
            "direct": false,
            "version": "v1.4.12",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gin-contrib/sse",
            "direct": false,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-playground/locales",
            "direct": false,
            "version": "v0.14.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-playground/universal-translator",
            "direct": false,
            "version": "v0.18.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-playground/validator/v10",
            "direct": false,
            "version": "v10.30.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/goccy/go-json",
            "direct": false,
            "version": "v0.10.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/goccy/go-yaml",
            "direct": false,
            "version": "v1.19.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/jsonschema-go",
            "direct": false,
            "version": "v0.4.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/uuid",
            "direct": false,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/context",
            "direct": false,
            "version": "v1.1.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/securecookie",
            "direct": false,
            "version": "v1.1.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/sessions",
            "direct": false,
            "version": "v1.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/json-iterator/go",
            "direct": false,
            "version": "v1.1.12",
            "ecosystem": "go"
          },
          {
            "name": "github.com/klauspost/cpuid/v2",
            "direct": false,
            "version": "v2.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/leodido/go-urn",
            "direct": false,
            "version": "v1.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-isatty",
            "direct": false,
            "version": "v0.0.20",
            "ecosystem": "go"
          },
          {
            "name": "github.com/modern-go/concurrent",
            "direct": false,
            "version": "v0.0.0-20180306012644-bacd9c7ef1dd",
            "ecosystem": "go"
          },
          {
            "name": "github.com/modern-go/reflect2",
            "direct": false,
            "version": "v1.0.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ncruces/go-strftime",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pelletier/go-toml/v2",
            "direct": false,
            "version": "v2.2.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/quic-go/qpack",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/quic-go/quic-go",
            "direct": false,
            "version": "v0.59.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/remyoudompheng/bigfft",
            "direct": false,
            "version": "v0.0.0-20230129092748-24d4a6f8daec",
            "ecosystem": "go"
          },
          {
            "name": "github.com/segmentio/asm",
            "direct": false,
            "version": "v1.1.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/segmentio/encoding",
            "direct": false,
            "version": "v0.5.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/twitchyliquid64/golang-asm",
            "direct": false,
            "version": "v0.15.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ugorji/go/codec",
            "direct": false,
            "version": "v1.3.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yosida95/uritemplate/v3",
            "direct": false,
            "version": "v3.0.2",
            "ecosystem": "go"
          },
          {
            "name": "go.mongodb.org/mongo-driver/v2",
            "direct": false,
            "version": "v2.5.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/arch",
            "direct": false,
            "version": "v0.22.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/oauth2",
            "direct": false,
            "version": "v0.35.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": false,
            "version": "v0.47.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.40.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/protobuf",
            "direct": false,
            "version": "v1.36.10",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/libc",
            "direct": false,
            "version": "v1.74.1",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/mathutil",
            "direct": false,
            "version": "v1.7.1",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/memory",
            "direct": false,
            "version": "v1.11.0",
            "ecosystem": "go"
          },
          {
            "name": "@asamuzakjp/css-color",
            "direct": false,
            "version": "5.1.11",
            "ecosystem": "npm"
          },
          {
            "name": "@asamuzakjp/dom-selector",
            "direct": false,
            "version": "7.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@asamuzakjp/generational-cache",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "@asamuzakjp/nwsapi",
            "direct": false,
            "version": "2.3.9",
            "ecosystem": "npm"
          },
          {
            "name": "@babel/helper-string-parser",
            "direct": false,
            "version": "7.29.7",
            "ecosystem": "npm"
          },
          {
            "name": "@babel/helper-validator-identifier",
            "direct": false,
            "version": "7.29.7",
            "ecosystem": "npm"
          },
          {
            "name": "@babel/parser",
            "direct": false,
            "version": "7.29.7",
            "ecosystem": "npm"
          },
          {
            "name": "@babel/types",
            "direct": false,
            "version": "7.29.7",
            "ecosystem": "npm"
          },
          {
            "name": "@bcoe/v8-coverage",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@bramus/specificity",
            "direct": false,
            "version": "2.4.2",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/color-helpers",
            "direct": false,
            "version": "6.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/css-calc",
            "direct": false,
            "version": "3.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/css-color-parser",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/css-parser-algorithms",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/css-syntax-patches-for-csstree",
            "direct": false,
            "version": "1.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "@csstools/css-tokenizer",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@emnapi/core",
            "direct": false,
            "version": "1.11.1",
            "ecosystem": "npm"
          },
          {
            "name": "@emnapi/runtime",
            "direct": false,
            "version": "1.11.1",
            "ecosystem": "npm"
          },
          {
            "name": "@emnapi/wasi-threads",
            "direct": false,
            "version": "1.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint-community/eslint-utils",
            "direct": false,
            "version": "4.9.1",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint-community/regexpp",
            "direct": false,
            "version": "4.12.2",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/config-array",
            "direct": false,
            "version": "0.23.5",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/config-helpers",
            "direct": false,
            "version": "0.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/core",
            "direct": false,
            "version": "1.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/js",
            "direct": false,
            "version": "10.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/object-schema",
            "direct": false,
            "version": "3.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "@eslint/plugin-kit",
            "direct": false,
            "version": "0.7.2",
            "ecosystem": "npm"
          },
          {
            "name": "@exodus/bytes",
            "direct": false,
            "version": "1.15.0",
            "ecosystem": "npm"
          },
          {
            "name": "@humanfs/core",
            "direct": false,
            "version": "0.19.2",
            "ecosystem": "npm"
          },
          {
            "name": "@humanfs/node",
            "direct": false,
            "version": "0.16.8",
            "ecosystem": "npm"
          },
          {
            "name": "@humanfs/types",
            "direct": false,
            "version": "0.15.0",
            "ecosystem": "npm"
          },
          {
            "name": "@humanwhocodes/module-importer",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "@humanwhocodes/retry",
            "direct": false,
            "version": "0.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "@jridgewell/gen-mapping",
            "direct": false,
            "version": "0.3.13",
            "ecosystem": "npm"
          },
          {
            "name": "@jridgewell/remapping",
            "direct": false,
            "version": "2.3.5",
            "ecosystem": "npm"
          },
          {
            "name": "@jridgewell/resolve-uri",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "@jridgewell/sourcemap-codec",
            "direct": false,
            "version": "1.5.5",
            "ecosystem": "npm"
          },
          {
            "name": "@jridgewell/trace-mapping",
            "direct": false,
            "version": "0.3.31",
            "ecosystem": "npm"
          },
          {
            "name": "@napi-rs/wasm-runtime",
            "direct": false,
            "version": "1.1.6",
            "ecosystem": "npm"
          },
          {
            "name": "@oxc-project/types",
            "direct": false,
            "version": "0.138.0",
            "ecosystem": "npm"
          },
          {
            "name": "@playwright/test",
            "direct": false,
            "version": "1.61.1",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-android-arm64",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-darwin-arm64",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-darwin-x64",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-freebsd-x64",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-arm-gnueabihf",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-arm64-gnu",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-arm64-musl",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-ppc64-gnu",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-s390x-gnu",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-x64-gnu",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-linux-x64-musl",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-openharmony-arm64",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-wasm32-wasi",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-win32-arm64-msvc",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/binding-win32-x64-msvc",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "@rolldown/pluginutils",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "@standard-schema/spec",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "@sveltejs/acorn-typescript",
            "direct": false,
            "version": "1.0.10",
            "ecosystem": "npm"
          },
          {
            "name": "@sveltejs/vite-plugin-svelte",
            "direct": false,
            "version": "7.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "@tybys/wasm-util",
            "direct": false,
            "version": "0.10.3",
            "ecosystem": "npm"
          },
          {
            "name": "@types/chai",
            "direct": false,
            "version": "5.2.3",
            "ecosystem": "npm"
          },
          {
            "name": "@types/deep-eql",
            "direct": false,
            "version": "4.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@types/esrecurse",
            "direct": false,
            "version": "4.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "@types/estree",
            "direct": false,
            "version": "1.0.9",
            "ecosystem": "npm"
          },
          {
            "name": "@types/json-schema",
            "direct": false,
            "version": "7.0.15",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "25.7.0",
            "ecosystem": "npm"
          },
          {
            "name": "@types/qrcode",
            "direct": false,
            "version": "1.5.6",
            "ecosystem": "npm"
          },
          {
            "name": "@types/trusted-types",
            "direct": false,
            "version": "2.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/eslint-plugin",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/parser",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/project-service",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/scope-manager",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/tsconfig-utils",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/type-utils",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/types",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/typescript-estree",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/utils",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript-eslint/visitor-keys",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/coverage-v8",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/expect",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/mocker",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/pretty-format",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/runner",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/snapshot",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/spy",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@vitest/utils",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "acorn",
            "direct": false,
            "version": "8.16.0",
            "ecosystem": "npm"
          },
          {
            "name": "acorn-jsx",
            "direct": false,
            "version": "5.3.2",
            "ecosystem": "npm"
          },
          {
            "name": "ajv",
            "direct": false,
            "version": "6.15.0",
            "ecosystem": "npm"
          },
          {
            "name": "ansi-regex",
            "direct": false,
            "version": "5.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "ansi-styles",
            "direct": false,
            "version": "4.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "aria-query",
            "direct": false,
            "version": "5.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "assertion-error",
            "direct": false,
            "version": "2.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "ast-v8-to-istanbul",
            "direct": false,
            "version": "1.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "axobject-query",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "balanced-match",
            "direct": false,
            "version": "4.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "bidi-js",
            "direct": false,
            "version": "1.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "brace-expansion",
            "direct": false,
            "version": "5.0.6",
            "ecosystem": "npm"
          },
          {
            "name": "camelcase",
            "direct": false,
            "version": "5.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "chai",
            "direct": false,
            "version": "6.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "cliui",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "clsx",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "color-convert",
            "direct": false,
            "version": "2.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "color-name",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "convert-source-map",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "cross-spawn",
            "direct": false,
            "version": "7.0.6",
            "ecosystem": "npm"
          },
          {
            "name": "css-tree",
            "direct": false,
            "version": "3.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "cssesc",
            "direct": false,
            "version": "3.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "data-urls",
            "direct": false,
            "version": "7.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "debug",
            "direct": false,
            "version": "4.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "decamelize",
            "direct": false,
            "version": "1.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "decimal.js",
            "direct": false,
            "version": "10.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "deep-is",
            "direct": false,
            "version": "0.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "deepmerge",
            "direct": false,
            "version": "4.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "detect-libc",
            "direct": false,
            "version": "2.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "devalue",
            "direct": false,
            "version": "5.8.1",
            "ecosystem": "npm"
          },
          {
            "name": "dijkstrajs",
            "direct": false,
            "version": "1.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "emoji-regex",
            "direct": false,
            "version": "8.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "entities",
            "direct": false,
            "version": "8.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "es-module-lexer",
            "direct": false,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "escape-string-regexp",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "eslint",
            "direct": false,
            "version": "10.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-config-prettier",
            "direct": false,
            "version": "10.1.8",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-plugin-svelte",
            "direct": false,
            "version": "3.20.0",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-scope",
            "direct": false,
            "version": "8.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-scope",
            "direct": false,
            "version": "9.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-visitor-keys",
            "direct": false,
            "version": "3.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-visitor-keys",
            "direct": false,
            "version": "4.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "eslint-visitor-keys",
            "direct": false,
            "version": "5.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "esm-env",
            "direct": false,
            "version": "1.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "espree",
            "direct": false,
            "version": "10.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "espree",
            "direct": false,
            "version": "11.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "esquery",
            "direct": false,
            "version": "1.7.0",
            "ecosystem": "npm"
          },
          {
            "name": "esrap",
            "direct": false,
            "version": "2.2.13",
            "ecosystem": "npm"
          },
          {
            "name": "esrecurse",
            "direct": false,
            "version": "4.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "estraverse",
            "direct": false,
            "version": "5.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "estree-walker",
            "direct": false,
            "version": "3.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "esutils",
            "direct": false,
            "version": "2.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "expect-type",
            "direct": false,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "fast-deep-equal",
            "direct": false,
            "version": "3.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "fast-json-stable-stringify",
            "direct": false,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "fast-levenshtein",
            "direct": false,
            "version": "2.0.6",
            "ecosystem": "npm"
          },
          {
            "name": "fdir",
            "direct": false,
            "version": "6.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "file-entry-cache",
            "direct": false,
            "version": "8.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "find-up",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "find-up",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "flat-cache",
            "direct": false,
            "version": "4.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "flatted",
            "direct": false,
            "version": "3.4.2",
            "ecosystem": "npm"
          },
          {
            "name": "fsevents",
            "direct": false,
            "version": "2.3.2",
            "ecosystem": "npm"
          },
          {
            "name": "fsevents",
            "direct": false,
            "version": "2.3.3",
            "ecosystem": "npm"
          },
          {
            "name": "get-caller-file",
            "direct": false,
            "version": "2.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "glob-parent",
            "direct": false,
            "version": "6.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "globals",
            "direct": false,
            "version": "16.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "has-flag",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "html-encoding-sniffer",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "html-escaper",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "ignore",
            "direct": false,
            "version": "5.3.2",
            "ecosystem": "npm"
          },
          {
            "name": "ignore",
            "direct": false,
            "version": "7.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "imurmurhash",
            "direct": false,
            "version": "0.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "is-extglob",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "is-fullwidth-code-point",
            "direct": false,
            "version": "3.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "is-glob",
            "direct": false,
            "version": "4.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "is-potential-custom-element-name",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "is-reference",
            "direct": false,
            "version": "3.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "isexe",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "istanbul-lib-coverage",
            "direct": false,
            "version": "3.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "istanbul-lib-report",
            "direct": false,
            "version": "3.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "istanbul-reports",
            "direct": false,
            "version": "3.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "js-tokens",
            "direct": false,
            "version": "10.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "jsdom",
            "direct": false,
            "version": "29.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "json-buffer",
            "direct": false,
            "version": "3.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "json-schema-traverse",
            "direct": false,
            "version": "0.4.1",
            "ecosystem": "npm"
          },
          {
            "name": "json-stable-stringify-without-jsonify",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "keyv",
            "direct": false,
            "version": "4.5.4",
            "ecosystem": "npm"
          },
          {
            "name": "known-css-properties",
            "direct": false,
            "version": "0.37.0",
            "ecosystem": "npm"
          },
          {
            "name": "levn",
            "direct": false,
            "version": "0.4.1",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-android-arm64",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-darwin-arm64",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-darwin-x64",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-freebsd-x64",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-linux-arm-gnueabihf",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-linux-arm64-gnu",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-linux-arm64-musl",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-linux-x64-gnu",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-linux-x64-musl",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-win32-arm64-msvc",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lightningcss-win32-x64-msvc",
            "direct": false,
            "version": "1.32.0",
            "ecosystem": "npm"
          },
          {
            "name": "lilconfig",
            "direct": false,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "locate-character",
            "direct": false,
            "version": "3.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "locate-path",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "locate-path",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "lru-cache",
            "direct": false,
            "version": "11.3.6",
            "ecosystem": "npm"
          },
          {
            "name": "magic-string",
            "direct": false,
            "version": "0.30.21",
            "ecosystem": "npm"
          },
          {
            "name": "magicast",
            "direct": false,
            "version": "0.5.3",
            "ecosystem": "npm"
          },
          {
            "name": "make-dir",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "mdn-data",
            "direct": false,
            "version": "2.27.1",
            "ecosystem": "npm"
          },
          {
            "name": "minimatch",
            "direct": false,
            "version": "10.2.5",
            "ecosystem": "npm"
          },
          {
            "name": "ms",
            "direct": false,
            "version": "2.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "nanoid",
            "direct": false,
            "version": "3.3.12",
            "ecosystem": "npm"
          },
          {
            "name": "natural-compare",
            "direct": false,
            "version": "1.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "obug",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "optionator",
            "direct": false,
            "version": "0.9.4",
            "ecosystem": "npm"
          },
          {
            "name": "p-limit",
            "direct": false,
            "version": "2.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "p-limit",
            "direct": false,
            "version": "3.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "p-locate",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "p-locate",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "p-try",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "parse5",
            "direct": false,
            "version": "8.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "path-exists",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "path-key",
            "direct": false,
            "version": "3.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "pathe",
            "direct": false,
            "version": "2.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "picocolors",
            "direct": false,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "picomatch",
            "direct": false,
            "version": "4.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "playwright",
            "direct": false,
            "version": "1.61.1",
            "ecosystem": "npm"
          },
          {
            "name": "playwright-core",
            "direct": false,
            "version": "1.61.1",
            "ecosystem": "npm"
          },
          {
            "name": "pngjs",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "postcss",
            "direct": false,
            "version": "8.5.16",
            "ecosystem": "npm"
          },
          {
            "name": "postcss-load-config",
            "direct": false,
            "version": "3.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "postcss-safe-parser",
            "direct": false,
            "version": "7.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "postcss-scss",
            "direct": false,
            "version": "4.0.9",
            "ecosystem": "npm"
          },
          {
            "name": "postcss-selector-parser",
            "direct": false,
            "version": "7.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "prelude-ls",
            "direct": false,
            "version": "1.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "prettier",
            "direct": false,
            "version": "3.9.4",
            "ecosystem": "npm"
          },
          {
            "name": "prettier-plugin-svelte",
            "direct": false,
            "version": "4.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "punycode",
            "direct": false,
            "version": "2.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "require-directory",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "require-from-string",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "require-main-filename",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "rolldown",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          },
          {
            "name": "saxes",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "semver",
            "direct": false,
            "version": "7.8.0",
            "ecosystem": "npm"
          },
          {
            "name": "set-blocking",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "shebang-command",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "shebang-regex",
            "direct": false,
            "version": "3.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "siginfo",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "source-map-js",
            "direct": false,
            "version": "1.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "stackback",
            "direct": false,
            "version": "0.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "std-env",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "string-width",
            "direct": false,
            "version": "4.2.3",
            "ecosystem": "npm"
          },
          {
            "name": "strip-ansi",
            "direct": false,
            "version": "6.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "supports-color",
            "direct": false,
            "version": "7.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "svelte-eslint-parser",
            "direct": false,
            "version": "1.8.0",
            "ecosystem": "npm"
          },
          {
            "name": "symbol-tree",
            "direct": false,
            "version": "3.2.4",
            "ecosystem": "npm"
          },
          {
            "name": "tinybench",
            "direct": false,
            "version": "2.9.0",
            "ecosystem": "npm"
          },
          {
            "name": "tinyexec",
            "direct": false,
            "version": "1.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "tinyglobby",
            "direct": false,
            "version": "0.2.17",
            "ecosystem": "npm"
          },
          {
            "name": "tinyrainbow",
            "direct": false,
            "version": "3.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "tldts",
            "direct": false,
            "version": "7.0.30",
            "ecosystem": "npm"
          },
          {
            "name": "tldts-core",
            "direct": false,
            "version": "7.0.30",
            "ecosystem": "npm"
          },
          {
            "name": "tough-cookie",
            "direct": false,
            "version": "6.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "tr46",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "ts-api-utils",
            "direct": false,
            "version": "2.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "tslib",
            "direct": false,
            "version": "2.8.1",
            "ecosystem": "npm"
          },
          {
            "name": "type-check",
            "direct": false,
            "version": "0.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "6.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "typescript-eslint",
            "direct": false,
            "version": "8.62.1",
            "ecosystem": "npm"
          },
          {
            "name": "undici",
            "direct": false,
            "version": "7.28.0",
            "ecosystem": "npm"
          },
          {
            "name": "undici-types",
            "direct": false,
            "version": "7.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "uri-js",
            "direct": false,
            "version": "4.4.1",
            "ecosystem": "npm"
          },
          {
            "name": "util-deprecate",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "vite",
            "direct": false,
            "version": "8.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "vitefu",
            "direct": false,
            "version": "1.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "vitest",
            "direct": false,
            "version": "4.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "w3c-xmlserializer",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "webidl-conversions",
            "direct": false,
            "version": "8.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "whatwg-mimetype",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "whatwg-url",
            "direct": false,
            "version": "16.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "which",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "which-module",
            "direct": false,
            "version": "2.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "why-is-node-running",
            "direct": false,
            "version": "2.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "word-wrap",
            "direct": false,
            "version": "1.2.5",
            "ecosystem": "npm"
          },
          {
            "name": "wrap-ansi",
            "direct": false,
            "version": "6.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "xml-name-validator",
            "direct": false,
            "version": "5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "xmlchars",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "y18n",
            "direct": false,
            "version": "4.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "yaml",
            "direct": false,
            "version": "1.10.3",
            "ecosystem": "npm"
          },
          {
            "name": "yargs",
            "direct": false,
            "version": "15.4.1",
            "ecosystem": "npm"
          },
          {
            "name": "yargs-parser",
            "direct": false,
            "version": "18.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "yocto-queue",
            "direct": false,
            "version": "0.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "zimmerframe",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "npm"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 334,
        "direct_count": 10,
        "indirect_count": 324
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 2,
        "merged_prs": 60,
        "open_issues": 1,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 23
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "buliwyf42",
          "commits": 292,
          "avatar_url": "https://avatars.githubusercontent.com/u/4658822?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "dependabot-auto-merge.yml",
        "publish-image.yml",
        "test.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".golangci.yml",
        "eslint.config.js"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum",
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "5 out of 5 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/25 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 9,
            "reason": "dependency not pinned by hash detected -- score normalized to 9",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 4,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 8,
            "reason": "2 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "c580f1054f27a87e07bb176023a7aa42294cbd58",
        "ran_at": "2026-07-24T13:17:54Z",
        "aggregate_score": 6.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-23T06:11:24Z",
      "oldest_open_prs": [
        {
          "number": 84,
          "created_at": "2026-07-20T17:45:37Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 86,
          "created_at": "2026-07-20T17:46:46Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-20T17:49:19Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 13,
          "created_at": "2026-05-11T13:16:14Z",
          "last_comment_at": "2026-05-23T08:53:43Z",
          "last_comment_author": "buliwyf42"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/buliwyf42/shellyadmin",
    "host": "github.com",
    "name": "shellyadmin",
    "owner": "buliwyf42"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 60,
      "inputs": {
        "security": 67,
        "vitality": 85,
        "community": 46,
        "governance": 24,
        "engineering": 84
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 85,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "commits_last_year": 325,
              "human_commit_share": 0.75,
              "days_since_last_push": 1,
              "active_weeks_last_year": 16
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "16/52 weeks with commits",
                "points": 11.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 16
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "325 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 325
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 70,
              "latest_release_tag": "v0.6.3",
              "releases_from_tags": false,
              "days_since_latest_release": 1,
              "mean_days_between_releases": 6.6
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "70 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 70
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~6.6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 6.6
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 46,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 5,
            "inputs": {
              "forks": 0,
              "stars": 3,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "3 stars",
                "points": 4.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "critical",
        "name": "Sustainability & Governance",
        "value": 24,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 28,
            "inputs": {
              "merged_prs": 60,
              "open_issues": 1,
              "closed_issues": 0,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 23
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "60/83 decided PRs merged",
                "points": 27.7,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 60,
                      "decided": 83
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/25 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 38,
            "inputs": {
              "followers": 2,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "buliwyf42",
              "public_repos": 4,
              "account_age_days": 4792
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "2 followers of buliwyf42",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "buliwyf42"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "4 public repos, account ~13 yr old",
                "points": 17.1,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 4
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 84,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": ".golangci.yml, eslint.config.js",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml, eslint.config.js"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "5 out of 5 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "topics": [
                "docker",
                "firmware-management",
                "golang",
                "home-automation",
                "iot",
                "mcp",
                "self-hosted",
                "shelly",
                "smart-home",
                "svelte"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "10 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 67,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 61,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 6.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "5 out of 5 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/25 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 9",
                "points": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "2 existing vulnerabilities detected",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories. Remaining weights renormalized. Matched 334 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 334
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 89,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 2,
              "assessed_packages": 334,
              "unassessed_packages": 0,
              "affected_by_severity": "high 1, unknown 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: golang.org/x/crypto v0.54.0 (unknown)",
                "points": 26.6,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "golang.org/x/crypto v0.54.0 (unknown)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory has been public longer than 90 days",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_none_stale",
                    "params": {
                      "days": 90
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 334,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 83,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.96,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 43430
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "72 of 75 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 72,
                      "sampled": 75
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum",
                "package-lock.json"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "web/tsconfig.json"
              ],
              "agent_commit_share": 0.2,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0.25
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".golangci.yml, eslint.config.js",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml, eslint.config.js"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "web/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "web/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "20 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 20,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "25 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 25,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 9",
                "points": 9,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 52308,
              "source_files_sampled": 209,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/209 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 209,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "critical",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-24T13:18:04.092083Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/b/buliwyf42/shellyadmin.svg",
  "full_name": "buliwyf42/shellyadmin",
  "license_state": "standard",
  "license_spdx": "MIT"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计.