公开记录
软件健康报告模式 0.27.0 · 指标 2.3.1 · 2026-07-28 05:47 UTC

epithet-ssh / epithet

Secure and easy ssh certs via an ssh-agent and CA

Go自定义许可证★ 15 星标⑂ 1 复刻始于 2017年7月在 GitHub 上查看 ↗
类型如何判定

epithet-ssh/epithet 的健康指数为 100 分中的 59 分,处于「中等」区间。 其得分最高的类别是AI Readiness(78/100),最低的是Community & Adoption(32/100)。 最近一次更新在 8 天前。 近期的大部分工作由 1 位贡献者完成。

59
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均,再依据公开记录的分布进行校准,使各等级具有百分位含义;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 34(存在风险)的上限。

59
卓越93-100公开记录中的最高层级(约前 5%);基本满足所有检验标准
优秀80-92各方面均表现强劲;仅有少量不足
良好65-79健康;不足之处有限且可控
中等50-64可接受,但存在明显不足;建议进行审查
薄弱35-49多个领域存在实质性薄弱环节
存在风险20-34存在重大薄弱环节;采用时应保持审慎
危急1-19问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

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

加权总体分 56 经校准后在公布的指数量表上为 59(记录校准 2026-08-02)。

所有权

0 关注者11 个公开仓库始于 2019年10月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/epithet-ssh/epithetv0.17.3-698 天前

按类别列示的指标

活力

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

77良好 · 占总体的 21%
评分方式
28.8/36推送新近度 — 最近一次推送于 8 天前
17.3/36提交节奏 — 52 周中有 25 周有提交
18/18提交量 — 最近一年 231 次提交
4/10OpenSSF Scorecard:Maintained — 5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4
所用输入
commits_last_year231
human_commit_share1
days_since_last_push8
active_weeks_last_year25

发布纪律

90优秀
评分方式
27/27有发布版本 — 已发布 57 个发布版本
36/36发布时效 — 最近一次发布版本于 8 天前
27/27发布节奏 — 约每 10.8 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — Project has not signed or included provenance with any releases.
所用输入
releases_count57
latest_release_tagv0.17.3
releases_from_tags
days_since_latest_release8
mean_days_between_releases10.8

社区与采用

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

32存在风险 · 占总体的 17%

流行度与采用

21存在风险
评分方式
18.6/60星标 — 15 个星标
0/25复刻 — 1 个复刻
2.7/15关注者 — 4 位关注者
所用输入
forks1
stars15
watchers4
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

44薄弱
评分方式
22.5/22.5README
16.9/22.5许可证 — 存在许可证文件,但不是可识别的许可证
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
readme_badges
has_contributing
has_issue_template
has_code_of_conduct
readme_badge_services
has_pull_request_template

可持续性与治理

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

55中等 · 占总体的 23%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
42/42议题解决 — 100% 的议题已关闭
15.6/30PR 接受 — 已裁定的 PR 中 13/25 已合并
0/13Newcomer PR acceptance — 30 天内没有首次贡献者的 PR 得到裁决
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs13
open_issues0
closed_issues3
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio1
closed_unmerged_prs12
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
已排除计分(无数据或不适用):newcomer_pr_acceptance。 其余权重已重新归一化。
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
0/25所有者影响力 — epithet-ssh 有 0 位关注者
19.9/25既往记录 — 11 个公开仓库,账户约 6 年
所用输入
followers0
owner_typeOrganization
is_verified
owner_loginepithet-ssh
public_repos11
account_age_days2,467
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 8 天前
20/20版本历史 — 69 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/epithet-ssh/epithet
ecosystemsgo
any_deprecated
min_days_since_publish8

工程质量

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

62中等 · 占总体的 19%

工程实践

60中等
评分方式
24/24CI 工作流 — 2 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

65良好
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

42薄弱 · 占总体的 16%

安全态势

37薄弱
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.2/2.5许可证 — license file detected
3/7.5Maintained — 5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 29 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate3.7
已排除计分(无数据或不适用):ci_tests。 其余权重已重新归一化。
评分方式
5.4/35直接依赖不含已知公告 — 3 个受影响:golang.org/x/crypto v0.49.0 (critical 10.0), google.golang.org/grpc v1.80.0 (critical 9.1), github.com/go-chi/chi/v5 v5.2.5 (unknown)
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories44
affected_packages7
assessed_packages51
unassessed_packages0
affected_by_severitycritical 2, moderate 1, unknown 4
direct_affected_packages3
已排除计分(无数据或不适用):间接依赖不含已知公告。 其余权重已重新归一化。 已将 51 个已解析依赖与 OSV 比对。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?权重刻意设小(4%):代理工具链是一项真实的维护信号,但完全不具备的仓库仍可达到 100/100。

78良好 · 占总体的 4%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
39.5/40可读的提交历史 — 100 次人类提交中有 74 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.74
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes669
评分方式
18/18一条命令的引导启动 — Makefile, contrib/freebsd/Makefile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — Dockerfile, lockfile
4/10已体现的代理实践 — 最近 100 次提交中有 2 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile, contrib/freebsd/Makefile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.02
toolchain_manifestsgo.mod
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 62 个源文件中有 0 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes29,428
source_files_sampled62
oversized_source_files0
评分方式
40/40API 模式(OpenAPI/GraphQL/proto) — proto/brokerv1/broker.proto
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_filesproto/brokerv1/broker.proto

关键数据

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

数据采集警告

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

更多细节

OpenSSF Scorecard 3.7 / 10
3.7综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
4Maintained5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities29 existing vulnerabilities detected
直接依赖 20
注册表软件包版本约束清单文件
Gogithub.com/alecthomas/kongv1.15.0go.mod
Gogithub.com/cbroglie/mustachev1.4.0go.mod
Gogithub.com/coreos/go-oidc/v3v3.17.0go.mod
Gogithub.com/go-chi/chi/v5v5.2.5go.mod
Gogithub.com/int128/oauth2cliv1.18.0go.mod
Gogithub.com/lmittmann/tintv1.1.3go.mod
Gogithub.com/mikesmitty/edkeyv0.0.0-20170222072505-3356ea4e686ago.mod
Gogithub.com/pkg/browserv0.0.0-20240102092130-5ac0b6a4141cgo.mod
Gogithub.com/stretchr/testifyv1.11.1go.mod
Gogolang.org/x/cryptov0.49.0go.mod
Gogolang.org/x/oauth2v0.36.0go.mod
Gogotest.toolsv2.2.0+incompatiblego.mod
Gogithub.com/alecthomas/kong-yamlv0.2.0go.mod
Gogithub.com/bmatcuk/doublestar/v4v4.10.0go.mod
Gogithub.com/gregjones/httpcachev0.0.0-20190611155906-901d90724c79go.mod
Gogithub.com/sony/gobreaker/v2v2.4.0go.mod
Gogithub.com/yaronf/httpsignv0.5.1go.mod
Gogoogle.golang.org/grpcv1.80.0go.mod
Gogoogle.golang.org/protobufv1.36.11go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
全部依赖 51

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

注册表软件包版本关系
Gogithub.com/alecthomas/kongv1.15.0直接
Gogithub.com/alecthomas/kong-yamlv0.2.0直接
Gogithub.com/bmatcuk/doublestar/v4v4.10.0直接
Gogithub.com/cbroglie/mustachev1.4.0直接
Gogithub.com/coreos/go-oidc/v3v3.17.0直接
Gogithub.com/go-chi/chi/v5v5.2.5直接
Gogithub.com/gregjones/httpcachev0.0.0-20190611155906-901d90724c79直接
Gogithub.com/int128/oauth2cliv1.18.0直接
Gogithub.com/lmittmann/tintv1.1.3直接
Gogithub.com/mikesmitty/edkeyv0.0.0-20170222072505-3356ea4e686a直接
Gogithub.com/pkg/browserv0.0.0-20240102092130-5ac0b6a4141c直接
Gogithub.com/sony/gobreaker/v2v2.4.0直接
Gogithub.com/stretchr/testifyv1.11.1直接
Gogithub.com/yaronf/httpsignv0.5.1直接
Gogolang.org/x/cryptov0.49.0直接
Gogolang.org/x/oauth2v0.36.0直接
Gogoogle.golang.org/grpcv1.80.0直接
Gogoogle.golang.org/protobufv1.36.11直接
Gogopkg.in/yaml.v3v3.0.1直接
Gogotest.toolsv2.2.0+incompatible直接
Gogithub.com/davecgh/go-spewv1.1.2-0.20180830191138-d8f796af33cc间接
Gogithub.com/decred/dcrd/dcrec/secp256k1/v4v4.4.0间接
Gogithub.com/dunglas/httpsfvv1.0.2间接
Gogithub.com/go-jose/go-jose/v4v4.1.4间接
Gogithub.com/goccy/go-jsonv0.10.3间接
Gogithub.com/google/go-cmpv0.7.0间接
Gogithub.com/int128/listenerv1.3.0间接
Gogithub.com/kr/prettyv0.3.1间接
Gogithub.com/lestrrat-go/blackmagicv1.0.4间接
Gogithub.com/lestrrat-go/dsigv1.0.0间接
Gogithub.com/lestrrat-go/dsig-secp256k1v1.0.0间接
Gogithub.com/lestrrat-go/httpccv1.0.1间接
Gogithub.com/lestrrat-go/httprcv1.0.6间接
Gogithub.com/lestrrat-go/httprc/v3v3.0.1间接
Gogithub.com/lestrrat-go/iterv1.0.2间接
Gogithub.com/lestrrat-go/jwx/v2v2.1.2间接
Gogithub.com/lestrrat-go/jwx/v3v3.0.12间接
Gogithub.com/lestrrat-go/optionv1.0.1间接
Gogithub.com/lestrrat-go/option/v2v2.0.0间接
Gogithub.com/pkg/errorsv0.9.1间接
Gogithub.com/pmezard/go-difflibv1.0.1-0.20181226105442-5d4384ee4fb2间接
Gogithub.com/rogpeppe/go-internalv1.14.1间接
Gogithub.com/segmentio/asmv1.2.1间接
Gogithub.com/valyala/fastjsonv1.6.4间接
Gogo.opentelemetry.io/otelv1.41.0间接
Gogo.opentelemetry.io/otel/sdk/metricv1.41.0间接
Gogolang.org/x/netv0.52.0间接
Gogolang.org/x/syncv0.20.0间接
Gogolang.org/x/sysv0.42.0间接
Gogolang.org/x/textv0.35.0间接
Gogoogle.golang.org/genproto/googleapis/rpcv0.0.0-20260406210006-6f92a3bedf2d间接
依赖安全公告 7

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

软件包版本关系严重程度公告数修复版本
golang.org/x/cryptov0.49.0直接严重270.52.0
google.golang.org/grpcv1.80.0直接严重21.82.1
golang.org/x/netv0.52.0间接91.26.3
github.com/go-chi/chi/v5v5.2.5直接未知35.3.0
go.opentelemetry.io/otelv1.41.0间接未知11.44.0
golang.org/x/sysv0.42.0间接未知10.44.0
golang.org/x/textv0.35.0间接未知10.39.0

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 4914,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 423112,
        "Shell": 1196,
        "Makefile": 3529,
        "Go Template": 323
      },
      "pushed_at": "2026-07-19T22:42:10Z",
      "created_at": "2017-07-02T00:23:45Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-19T22:41:42Z",
      "description": "Secure and easy ssh certs via an ssh-agent and CA ",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": null,
      "type": "Organization",
      "login": "epithet-ssh",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/57017967?v=4",
      "created_at": "2019-10-25T20:01:51Z",
      "is_verified": null,
      "public_repos": 11,
      "account_age_days": 2467
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.17.3",
          "kind": "patch",
          "published_at": "2026-07-19T22:44:03Z"
        },
        {
          "tag": "v0.17.2",
          "kind": "patch",
          "published_at": "2026-07-19T22:40:24Z"
        },
        {
          "tag": "v0.17.1",
          "kind": "patch",
          "published_at": "2026-04-14T06:46:23Z"
        },
        {
          "tag": "v0.17.0",
          "kind": "minor",
          "published_at": "2026-04-13T18:52:31Z"
        },
        {
          "tag": "v0.16.1",
          "kind": "patch",
          "published_at": "2026-04-13T16:34:10Z"
        },
        {
          "tag": "v0.16.0",
          "kind": "minor",
          "published_at": "2026-04-13T09:31:01Z"
        },
        {
          "tag": "v0.15.1",
          "kind": "patch",
          "published_at": "2026-04-13T09:17:34Z"
        },
        {
          "tag": "v0.15.0",
          "kind": "minor",
          "published_at": "2026-04-13T09:08:05Z"
        },
        {
          "tag": "v0.14.2",
          "kind": "patch",
          "published_at": "2026-04-13T08:51:37Z"
        },
        {
          "tag": "v0.14.1",
          "kind": "patch",
          "published_at": "2026-04-13T08:40:03Z"
        },
        {
          "tag": "v0.14.0",
          "kind": "minor",
          "published_at": "2026-04-12T19:08:39Z"
        },
        {
          "tag": "v0.13.7",
          "kind": "patch",
          "published_at": "2026-04-12T02:13:16Z"
        },
        {
          "tag": "v0.13.6",
          "kind": "patch",
          "published_at": "2026-04-12T02:10:13Z"
        },
        {
          "tag": "v0.13.5",
          "kind": "patch",
          "published_at": "2026-04-12T01:14:22Z"
        },
        {
          "tag": "v0.13.4",
          "kind": "patch",
          "published_at": "2026-04-12T01:10:50Z"
        },
        {
          "tag": "v0.13.3",
          "kind": "patch",
          "published_at": "2026-04-12T00:46:52Z"
        },
        {
          "tag": "v0.13.2",
          "kind": "patch",
          "published_at": "2026-04-12T00:30:52Z"
        },
        {
          "tag": "v0.13.1",
          "kind": "patch",
          "published_at": "2026-04-12T00:25:43Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-04-12T00:19:44Z"
        },
        {
          "tag": "v0.12.2",
          "kind": "patch",
          "published_at": "2026-03-25T16:49:20Z"
        },
        {
          "tag": "v0.12.0",
          "kind": "minor",
          "published_at": "2026-03-13T02:52:31Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-02-16T23:09:44Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-01-31T22:21:51Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-01-31T22:13:56Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-01-31T19:02:00Z"
        },
        {
          "tag": "v0.6.3",
          "kind": "patch",
          "published_at": "2026-01-28T03:57:53Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-01-08T04:55:00Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-01-08T04:42:34Z"
        },
        {
          "tag": "v0.5.2",
          "kind": "patch",
          "published_at": "2026-01-03T02:29:19Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-01-03T02:18:42Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-01-03T01:25:11Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2025-12-28T00:25:09Z"
        },
        {
          "tag": "v0.3.5",
          "kind": "patch",
          "published_at": "2025-12-28T00:00:56Z"
        },
        {
          "tag": "v0.3.4",
          "kind": "patch",
          "published_at": "2025-12-26T03:59:00Z"
        },
        {
          "tag": "v0.3.3",
          "kind": "patch",
          "published_at": "2025-12-26T03:36:28Z"
        },
        {
          "tag": "v0.3.2",
          "kind": "patch",
          "published_at": "2025-12-26T01:44:01Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2025-12-26T01:38:12Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2025-12-26T01:37:42Z"
        },
        {
          "tag": "v0.2.11",
          "kind": "patch",
          "published_at": "2025-12-07T00:16:07Z"
        },
        {
          "tag": "v0.2.10",
          "kind": "patch",
          "published_at": "2025-12-06T05:29:33Z"
        },
        {
          "tag": "v0.2.9",
          "kind": "patch",
          "published_at": "2025-12-06T03:58:10Z"
        },
        {
          "tag": "v0.2.8",
          "kind": "patch",
          "published_at": "2025-12-05T05:25:22Z"
        },
        {
          "tag": "v0.2.6",
          "kind": "patch",
          "published_at": "2025-12-05T05:21:11Z"
        },
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2025-12-05T05:20:36Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2025-12-05T05:17:57Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2025-12-05T05:13:57Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2025-12-05T05:02:57Z"
        },
        {
          "tag": "v0.0.12",
          "kind": "patch",
          "published_at": "2021-04-16T19:50:48Z"
        },
        {
          "tag": "v0.0.11",
          "kind": "patch",
          "published_at": "2020-10-09T21:40:26Z"
        },
        {
          "tag": "v0.0.10",
          "kind": "patch",
          "published_at": "2020-05-27T17:21:22Z"
        },
        {
          "tag": "v0.0.8",
          "kind": "patch",
          "published_at": "2020-03-25T15:13:56Z"
        },
        {
          "tag": "0.0.8",
          "kind": "patch",
          "published_at": "2020-03-18T01:18:43Z"
        },
        {
          "tag": "0.0.7",
          "kind": "patch",
          "published_at": "2020-03-03T20:35:25Z"
        },
        {
          "tag": "0.0.6",
          "kind": "patch",
          "published_at": "2020-03-03T19:09:45Z"
        },
        {
          "tag": "0.0.5",
          "kind": "patch",
          "published_at": "2020-01-16T04:07:55Z"
        },
        {
          "tag": "0.0.4",
          "kind": "patch",
          "published_at": "2020-01-15T22:08:17Z"
        },
        {
          "tag": "0.0.3",
          "kind": "patch",
          "published_at": "2020-01-15T22:06:06Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "ba27e29688043cdf2adc08f8ea470c82837c2c1c",
          "body": null,
          "is_bot": false,
          "headline": "chore: minor readme edit",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-07-19T22:41:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff19e47cd4374cf5829c041aaa7aa84c3619c887",
          "body": null,
          "is_bot": false,
          "headline": "chore: document release",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-07-19T22:37:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bf590cff8f0a5fb5d8ff38038301406f57fd7e93",
          "body": null,
          "is_bot": false,
          "headline": "chore: clean up AGENTS.md",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-07-13T17:56:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a4123fd9e7b40e14094b44d711eb7c618e21ab6",
          "body": "…ned flows\n\nAn abandoned OIDC browser flow (browser closed without completing) held\nthe auth mutex for the plugin's full 5-minute timeout, silently blocking\nevery subsequent ssh session behind it.\n\n* Coalesce concurrent Auth.Run calls into a shared flight: joiners get\n  the pending user output (auth\n[…]\nnt matches can actually share the flight\n* Always emit the auth URL on fd 4 from the OIDC plugin so joining\n  sessions see where to authenticate\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: share in-flight auth attempt across ssh sessions and kill abando…",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-07-13T17:39:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5f6581470eb7f8ce36b7ad996bc3dd2ebf244720",
          "body": null,
          "is_bot": false,
          "headline": "several security related tasks",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-06-23T18:33:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80051ac7057c08573aa89c0be5848ee10cab4844",
          "body": "Remove sections that restate default Claude/Go behavior (communication\nstyle, debugging philosophy, documentation conventions, camelCase). Remove\nstale maxStateSizeBytes constant reference. Delete stale worktree CLAUDE.md.",
          "is_bot": false,
          "headline": "chore: trim AGENTS.md to remove generic guidance",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-18T01:09:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8bcb0d82b7e3fd9f77792e56d989da69d0012aa1",
          "body": "…tExpiration\n\nUse key/value format for CA endpoint status in inspect output to match\nthe style of other sections (agents, certificates).\n\nRemove unused DefaultExpiration field from discovery responses — it was\nplumbed through policy server and CA but never consumed.",
          "is_bot": false,
          "headline": "fix: clean up inspect CA endpoint display and remove vestigial Defaul…",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-14T06:41:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "404b6951ec1bd4f3b53e4259a9c281cd2ebf5fb2",
          "body": "When all circuit breakers are open, bypass them and try entries directly\ninstead of returning AllUnavailableError immediately. This fixes the case\nwhere a transient outage (e.g., no network) trips all breakers, locking\nout all CAs for the full 10-minute cooldown even after recovery.\n\nAlso expose per-CA-endpoint circuit breaker state (healthy/broken) in\n`epithet agent inspect` output, both human-readable and JSON.",
          "is_bot": false,
          "headline": "feat: add breakerpool all-down fallback and expose CA status in inspect",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T18:44:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c5f250ae6e76669437b21fc784ad4a6c0d11800",
          "body": "When the auth token expires, getDiscoveryPatterns would call Hello with\nthe stale token, get a 401, and treat it as a terminal error. This\ncaused match to fail at the discovery step without ever attempting cert\nrenewal. Handle InvalidTokenError from Hello the same way the cert\nrequest loop does: clear the token, re-run auth, and retry.",
          "is_bot": false,
          "headline": "fix: re-authenticate on 401 during discovery Hello",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T16:29:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3227d08c8e9e6b04ca892954fb66571c1a62249d",
          "body": "The cert fingerprint matches what 'epithet agent inspect' displays,\nenabling direct correlation. The connection hash (%C) is not meaningful\non the CA side so it is removed from the log output.",
          "is_bot": false,
          "headline": "feat: add cert fingerprint to issuance log, remove connection hash",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T09:28:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb2fcf34182418fa0254ff1f8fdc2b5a957d6d23",
          "body": "Enables correlating inspect output with CA issuance logs, which log\nthe serial as the primary certificate identifier.",
          "is_bot": false,
          "headline": "feat: show certificate serial number in agent inspect output",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T09:25:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9e0ab4f764e2d0f41fb3b072805d633e1eddb83",
          "body": "The cert audit logger used slog.Info but the default log level is Warn,\nso certificate issuance events were silently dropped unless -v was passed.\nWrap the handler to force Info-level minimum for audit logging.",
          "is_bot": false,
          "headline": "fix: always log certificate issuance regardless of verbosity level",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T09:14:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1112d5634644b54b7667f537bbe23ccc1b1c7401",
          "body": "Previously only GetCert used the breakerpool for priority-based failover\nand circuit breaking. Hello and GetPublicKey iterated endpoints in\ninsertion order, ignoring priority, and had no circuit breaker support.\n\nChange the pool type from Pool[*CertResponse, string] to Pool[any, string]\nso all three methods share the same pool. This gives Hello and GetPublicKey\nproper priority ordering, round-robin within tiers, and shared circuit\nbreaker state across all request types.",
          "is_bot": false,
          "headline": "fix: route Hello and GetPublicKey through breakerpool",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T09:05:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4377bfecda0ef87cf6bf4a04a1cec97c5182f569",
          "body": null,
          "is_bot": false,
          "headline": "chore: switch to formula from cask",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T08:48:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a12d2c2a0ddb499a60f8cacc642a3ca9f5dfe966",
          "body": null,
          "is_bot": false,
          "headline": "move homebrew formula back to ci",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-13T08:37:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e7e3f5bd16243e970641117883424e0505cd8873",
          "body": "Replace the old rekor-based Bearer signature scheme with RFC 9421 HTTP\nMessage Signatures for CA-to-policy-server authentication. The CA now\nowns the /discovery endpoint and proxies to the policy server, removing\nthe broken Link header relay that failed behind reverse proxies.\n\nKey changes:\n- New pk\n[…]\n config public, match patterns\n  require valid Bearer token validated via policy server hello)\n- Combined mode simplified: no reverse proxy mux, CA listens directly\n- Removed sigstore/rekor dependency",
          "is_bot": false,
          "headline": "feat: implement RFC 9421 discovery protocol and CA-to-policy auth",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T18:54:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5018758c3653ab2c76cc9a5ccd48e8f4019b9bbb",
          "body": null,
          "is_bot": false,
          "headline": "a plan to clean up bootstrapping",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T05:11:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d24db78b58fe545b0826df6e9ee101c817d4437",
          "body": "The CA was deriving the discovery URL from the internal policy socket\npath (unix:///tmp/.../policy.sock/discovery) which is meaningless to\nexternal clients. Fall back to /discovery (relative) instead, which\nthe client resolves against the CA URL it's already talking to.",
          "is_bot": false,
          "headline": "fix: use relative discovery URL in CA pubkey response",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T02:19:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "761491f5019929e9fd0857c05ff176618dddea17",
          "body": "Remove explicit procname so rc.subr defaults to command (/usr/sbin/daemon),\nmatching the supervisor PID stored by -P. Fixes status reporting and\nclean shutdown.",
          "is_bot": false,
          "headline": "fix: align rc.d procname with daemon -P pidfile",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T02:10:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ef52636b239380b091334539be34be983cfa6e7",
          "body": "parseLinkHeader now resolves relative URLs against the request's\nbase URL. Previously /discovery resolved to http://localhost/discovery\nwhich broke clients behind a reverse proxy. The server can now use\nrelative Link headers and the client resolves them correctly.\n\nAlso fix sample config to use client-id instead of audience, create\nlog file in pre-install script so the epithet user can write to it.",
          "is_bot": false,
          "headline": "fix: resolve relative discovery URLs in Link header",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T02:07:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c90607bc4cce992bad1ce1358f48823aa4e3d73b",
          "body": "rc.subr interprets ${name}_user as a magic variable and runs the\nentire command as that user before daemon(8) gets invoked. This\ncaused daemon to fail writing the pidfile to /var/run/. Rename to\nepithet_server_runas so daemon starts as root, writes the pidfile,\nthen drops to the epithet user via -u.",
          "is_bot": false,
          "headline": "fix: rename rc.conf user variable to avoid rc.subr conflict",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T01:24:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "811de25ff503e3d4f3747623ef07429aa084ff8b",
          "body": "Remove ca-key and listen tunables from rc.d script and add them to\nthe sample YAML config instead. The rc.d script now only handles\nprocess management (config path, user, logfile). Server behavior\nis configured in one place.",
          "is_bot": false,
          "headline": "refactor: move server settings from rc.conf to config file",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T01:11:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b791361180c59b93c0bb1d87e36b72a24543a5ee",
          "body": "Plain HTTP should not be exposed to the network. Default to\n127.0.0.1:8080 so a TLS-terminating reverse proxy is required\nfor external access.",
          "is_bot": false,
          "headline": "fix: default listen address to localhost only",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T01:10:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "491529989793617010e02e948984b5c5674f9269",
          "body": "daemon(8) -p writes the pidfile as the -u user, which can't write\nto /var/run/. Switch to -P which writes the supervisor pidfile as\nroot before dropping privileges.",
          "is_bot": false,
          "headline": "fix: use daemon -P for pidfile to avoid permission denied",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T01:08:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03e52275231434e6e9c4b8e13e0a2be058f1df25",
          "body": "Add pre-install script to +MANIFEST that creates the epithet user\nvia pw(8) if it doesn't already exist. Tested on FreeBSD 15.0.",
          "is_bot": false,
          "headline": "feat: create epithet service user automatically on pkg install",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T00:44:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77d6bb85492978ec39a99f31bdcd3f006353c7f0",
          "body": "pkg(8) stamps the ABI from the build host OS, so building in a\nFreeBSD 14 VM produced packages that FreeBSD 15 rejected. Add an\nABI variable (default FreeBSD:15:amd64) to the Makefile and\nsubstitute it into the manifest template. The binary is statically\nlinked so the ABI is purely metadata.",
          "is_bot": false,
          "headline": "fix: set explicit ABI in FreeBSD package manifest",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T00:27:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ed51351a1c80b077a7c7353f7524a536cd1e89d",
          "body": "checkout v4→v6, setup-go v5→v6, goreleaser-action v6→v7.\nNode.js 20 actions are deprecated and will stop working Sep 2026.",
          "is_bot": false,
          "headline": "chore: bump GitHub Actions to Node.js 24 versions",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T00:22:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "088700b7a5c5562b1491e12522d54d73593b0193",
          "body": "Add release.yml workflow triggered on v* tag push that runs goreleaser\nand builds a FreeBSD .pkg via vmactions/freebsd-vm. Tests run before\nrelease to prevent publishing broken artifacts.\n\nSimplify local make release to only create the tag, with CI handling\nthe actual build and publish. Modernize build.yml action versions and\nskip tag pushes to avoid duplicate runs.",
          "is_bot": false,
          "headline": "feat: move release builds to GitHub Actions CI",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T00:15:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "816b21ade14070fa74cbc471718906766c75baef",
          "body": "Add contrib/freebsd/ with Makefile, +MANIFEST, rc.d service script,\nsample config, and plist for building FreeBSD packages via pkg create.\nTested on FreeBSD 15.0-RELEASE/amd64.",
          "is_bot": false,
          "headline": "feat: add FreeBSD pkg packaging to contrib/",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-12T00:04:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1ac41b6400406f096a851c68b484612255b018ff",
          "body": "Fix issues found by Codex code review:\n- Use oidc.client_id instead of oidc.audience in policy server docs\n- Use defaults.expiration instead of default_expiration\n- Point Google Workspace prereqs to policy server guide instead of quick-start",
          "is_bot": false,
          "headline": "docs: fix incorrect config field names and broken links",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-11T00:08:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff7970579229971efa3337782cf1cb64940bd5b9",
          "body": "Remove cuelang.org/go, kongcue, and ~10 transitive CUE dependencies\n(OCI registry, protobuf parser, arbitrary-precision math). Replace with\nkong-yaml for CLI config resolution and direct yaml.v3/json unmarshaling\nfor policy data.\n\nTwo clean config paths replace the single CUE-unified approach:\n- Sca\n[…]\ny from YAML via\n  config.LoadSection()\n\nConfig keys now use kebab-case to match CLI flag names (ca-pubkey not\nca_pubkey). The applyOverrides methods are removed since Kong handles\nprecedence natively.",
          "is_bot": false,
          "headline": "refactor: replace CUE config with kong-yaml and direct YAML parsing",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-10T23:27:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce728049d9e7916f249062c14a15b15a37213cb5",
          "body": null,
          "is_bot": false,
          "headline": "chore: update dependencies",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-04-07T20:05:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c197b4036cd570c5b6e02f2f0324f8fcc905e822",
          "body": "Replace the two-tier content-addressed discovery system (redirect at\n/d/current to immutable /d/{hash} URLs) with a single /discovery\nendpoint that serves content directly using Vary: Authorization for\nHTTP cache discrimination.\n\n- Remove content-addressed hash computation (ComputeUnauthDiscoveryHas\n[…]\nand all hash-based routing\n- Replace DiscoveryHash config field with DiscoveryEnabled bool\n- Rename endpoint from /d/current to /discovery\n- Client caching still works via RFC 7234 Vary header support",
          "is_bot": false,
          "headline": "refactor: simplify discovery to single /discovery endpoint",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-27T02:23:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "781e278a9db514f507c590fa77f406004f06e2ce",
          "body": null,
          "is_bot": false,
          "headline": "chore:update docs",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T04:22:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e2e6df316fe8b5c8d6c0af3864fa18232d02217",
          "body": "Delete stale docs (alternatives.md, ideas/bastion.md, development-tools.md,\npolicy-config-design.md). Simplify README by removing inaccurate sections\n(wrong config format, nonexistent --match/--broker flags) and moving detail\nto docs/. Fix --match flag references across oidc-setup.md and\nauthentication.md. Fix commands table (add server, fix inspect).",
          "is_bot": false,
          "headline": "docs: audit and simplify documentation",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T03:05:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f35ba5008e6e1a6602270d8960d4bfb70e63938a",
          "body": null,
          "is_bot": false,
          "headline": "still fighting the makefile",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T02:51:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0609ff574065c6e8c83b4fbbf344691808b25582",
          "body": null,
          "is_bot": false,
          "headline": "chore:clean up release machinery",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T02:49:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5aea1b22054d44395ec1a612923bd4d0054f0c29",
          "body": null,
          "is_bot": false,
          "headline": "chore:svu includes the v",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T02:48:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9cf01837a859d016ff6043edd9fe9aa711d83cd4",
          "body": null,
          "is_bot": false,
          "headline": "chore:clean up release machinery",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-13T02:46:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4c03cd41ec14168c43251d72313223493c32fcd8",
          "body": null,
          "is_bot": false,
          "headline": "task for a frebsd pkg",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-03-09T03:10:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a4028d810a7b4e2aba9f9255b7c974ab86a1f4a5",
          "body": "Use a local httptest server serving openid-configuration and empty JWKS\ninstead of hitting accounts.google.com. Tests no longer need network\naccess or -short skip guards.",
          "is_bot": false,
          "headline": "test: replace real OIDC provider with mock in unit tests",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-21T22:54:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a1e2b45ec18f066ff39037dec307fc8a9d10acad",
          "body": "… subprocesses\n\nAdds a combined server command that starts CA and policy as subprocesses\nbehind a single reverse proxy, simplifying deployment to a single process\nand port. The proxy routes /d/* to the policy server and everything else\nto the CA.\n\nKey changes:\n- cmd/epithet/server.go: supervisor tha\n[…]\nre flag\n- test/server/server_test.go: integration test with mock OIDC server\n  verifying proxy routing, discovery redirects, and clean shutdown\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add `epithet server` command to run CA and policy as supervised…",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-21T22:50:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "37d33014e1c7db0ea52295155a109bb619d4dcfd",
          "body": "Merge the bootstrap (unauthenticated auth config) and discovery\n(authenticated match patterns) flows into a single /d/current endpoint\nthat routes by Authorization header presence:\n\n- Unauthenticated: returns Discovery{Auth: ...}\n- Authenticated: returns Discovery{Auth: ..., MatchPatterns: [...]}\n\nR\n[…]\ne BootstrapHash()/DiscoveryHash()\nmethods with standalone ComputeUnauthDiscoveryHash() and\nComputeAuthDiscoveryHash() functions. The redirect handler sets\nVary: Authorization for correct HTTP caching.",
          "is_bot": false,
          "headline": "refactor: unify bootstrap and discovery into single auth-aware endpoint",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-16T23:08:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b6f62360c03caad7dac1840b8a6909e3468ff905",
          "body": "getDiscoveryPatterns was calling auth.Run with nil userOutput,\ndiscarding fd 4 output during the initial auth triggered by\nshouldHandle. Add e2e gRPC streaming test that caught this.",
          "is_bot": false,
          "headline": "fix: thread userOutput through discovery auth path",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-16T22:34:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9f73c406c9e6b112e79f3addccdeab17c589c60",
          "body": null,
          "is_bot": false,
          "headline": "chore: cleaning up agent instructions",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-15T02:13:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d557e76ee2d5017598fc46b7a591a9987b5497de",
          "body": "Plan to detect remote SSH sessions (via SSH_CLIENT/SSH_CONNECTION env vars)\nand use Device Authorization Grant (RFC 8628) instead of browser-based auth\nwhen users are SSH'd in. Also includes doc improvements for policy server\nconfiguration modes (inline vs dynamic policy source).",
          "is_bot": false,
          "headline": "Add yatl task for SSH session detection in OIDC auth",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-02-01T04:17:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aba4747e5c62300a31dc7696b66960115883fb8b",
          "body": "- rekor v1.4.3 → v1.5.0 (fixes SSRF and nil pointer deref)\n- sigstore v1.10.3 → v1.10.4 (fixes TUF path traversal)\n\nResolves Dependabot alerts #43, #44, #45.",
          "is_bot": false,
          "headline": "fix: upgrade sigstore packages to fix security vulnerabilities",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-31T22:07:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dd70cf17bf7484b0eb3f1f3e56df69126d1aaa40",
          "body": "Separate policy data (users, hosts, defaults) from server config,\nallowing policy to be loaded from a URL per-request. This enables\npolicy updates without redeploying the server.\n\n- Add PolicyLoader with support for CUE, YAML, JSON formats\n- Add PolicyProvider interface for static and dynamic policy\n[…]\n:// URL)\n- HTTP caching via httpcache respecting Cache-Control headers\n- File caching via mtime to avoid re-parsing unchanged files\n- Backwards compatible: inline config still works when no source set",
          "is_bot": false,
          "headline": "feat: add dynamic policy loading via --policy-source",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-31T22:06:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3a0f016560fa367c6806c1c80e0e9c2596173dac",
          "body": "- Merge Run() and RunWithStderr() into single Run(attrs, userOutput) method\n- Change stderr callback to io.Writer for simpler, standard interface\n- Add fd 4 for user-visible progress output (e.g., OIDC device codes)\n- Keep stderr (fd 2) solely for error messages included in failures\n- Rename MatchWi\n[…]\nerr field to user_output\n\nAuth command protocol is now:\n- fd 1 (stdout): token\n- fd 2 (stderr): errors (captured for error messages)\n- fd 3: state blob\n- fd 4: user-visible progress (streamed to user)",
          "is_bot": false,
          "headline": "refactor: simplify auth command interface and add fd 4 for user output",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-31T19:01:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f3247de7d400f01b48d602973c23084efaa8cc6c",
          "body": "Replace the broker's internal RPC mechanism with gRPC to enable:\n- Server streaming for auth plugin stderr (visible to user during OIDC flows)\n- Cross-platform client generation (Swift/macOS, C#/.NET)\n\nKey changes:\n- Add proto/brokerv1/broker.proto with streaming Match and unary Inspect RPCs\n- Add b\n[…]\nupport stderr streaming callback\n- Add Broker.MatchWithStderr() as the core implementation\n- Update match.go and inspect.go CLI commands to use gRPC client\n- Update all broker tests to use gRPC client",
          "is_bot": false,
          "headline": "feat: migrate broker RPC from net/rpc+GOB to gRPC",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T16:59:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "19ee6211a63016ff2b0a132ee9c1221e43b62fba",
          "body": "Non-matching hosts are not errors - they just mean epithet doesn't\nhandle this connection. The match command now exits with code 1\nsilently, letting SSH fall through to normal authentication.",
          "is_bot": false,
          "headline": "fix: exit silently when host doesn't match discovery patterns",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T15:45:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d4912b924aa351a262528e32edb2d7378794c93a",
          "body": "Remove informational messages that printed to stderr during successful\nOIDC authentication. This was confusing when match failed because a host\ndidn't match discovery patterns - users would see auth messages only to\nlearn the connection wasn't handled by epithet.\n\nKeep error messages (browser failed to open) since those require user action.",
          "is_bot": false,
          "headline": "fix: remove verbose OIDC login output during match",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T15:39:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "817bf446dec3d2c74ba54a03a814bc12f6ffc7d0",
          "body": "Remove unnecessary options (PubkeyAuthentication, PasswordAuthentication,\nKbdInteractiveAuthentication, GSSAPIAuthentication, PreferredAuthentications,\nIdentityFile) from the generated SSH config block. This allows natural\nfallback to ~/.ssh/id_* keys and password auth when epithet certificates\naren't available, which is important for production failure recovery.",
          "is_bot": false,
          "headline": "fix: simplify generated SSH config to just IdentityAgent",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T15:37:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d63e0a915d12cef2b3238aeecabd89c37eaeaff2",
          "body": "Move architecture documentation to docs/architecture.md (~310 lines) and\nkeep only Claude-specific guidance in CLAUDE.md (~170 lines, down from 461).\n\nThis separation provides:\n- Smaller context for Claude sessions (most tasks only need behavior guidance)\n- Human-readable architecture docs for all developers\n- Single canonical location for architecture changes",
          "is_bot": false,
          "headline": "docs: split CLAUDE.md into focused modules",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T15:11:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d1334710bd03daa92bfe4a3665fbcc614b07755",
          "body": "Reduce CLAUDE.md from 862 to 461 lines (~46% reduction) by:\n- Replace auth protocol examples with reference to docs/authentication.md\n- Replace policy server protocol details with reference to docs/policy-server.md\n- Condense Broker → CA protocol section\n- Remove redundant SSH config examples (reference examples/ dir)\n- Replace detailed implementation checklist with brief status summary\n- Remove duplicate \"Integration with OpenSSH\" section",
          "is_bot": false,
          "headline": "docs: shrink CLAUDE.md by replacing duplicated content with references",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-28T14:56:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "171340e3608aa10b740599df32a15d7c2703637a",
          "body": null,
          "is_bot": false,
          "headline": "docs: add releases section pointing to packaging repo",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-08T05:05:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7b572ce62d0f95fc6986841a84c1b9f95f93b55d",
          "body": null,
          "is_bot": false,
          "headline": "chore: remove CI release workflow (using local releases)",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-08T05:00:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "334ef883f3dd8701c600945cb36ff680e31b4782",
          "body": null,
          "is_bot": false,
          "headline": "fix: add missing period to expandPath comment",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-08T04:53:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da43ff0d82127340d349dbc0ae355ac2e8de799b",
          "body": null,
          "is_bot": false,
          "headline": "working on release machienry",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-08T04:41:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1e38cc54531dbb88fa0522d5e2c0200ce2de585f",
          "body": "The cgo requirement made this incompatible with cross-compiled\nCI releases. Will revisit with a different approach later.",
          "is_bot": false,
          "headline": "Revert --native-log flag for Apple Unified Logging",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-05T21:19:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b91454a362bf1a047f5ebcbb2e10993e62bfb904",
          "body": "Add macOS-specific slog.Handler that writes to os_log via cgo,\nenabling logs to appear in Console.app with subsystem dev.epithet.\n\nOn non-Darwin platforms, the flag falls back to console logging\nwith a warning.",
          "is_bot": false,
          "headline": "Add --native-log flag for Apple Unified Logging support",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-05T21:08:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a747f61dff584071bcfc17607004e49bee26238f",
          "body": "Allow the policy server to accept an OIDC client secret via CLI flag\n(--oidc-client-secret) or config file (policy.oidc.client_secret).\nThe secret is included in the bootstrap response so clients can use it\nfor authentication with confidential OIDC clients.",
          "is_bot": false,
          "headline": "Add OIDC client secret support to policy server",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-03T02:26:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18f077337d0604834a9a9410b77a65947e2752ee",
          "body": "The CA now extracts the bootstrap URL from the policy server's Link header\ninstead of deriving it from the policy URL. This allows the policy server\nto control the exact URL for CDN caching scenarios.\n\nChanges:\n- Rename extractDiscoveryURL to extractLinkURLs to parse multiple link values\n- Extract a\n[…]\nserver uses cached bootstrap URL with fallback to derived URL\n- Policy server includes both discovery and bootstrap in Link headers\n- Make --auth optional on epithet agent (discover from CA bootstrap)",
          "is_bot": false,
          "headline": "Learn bootstrap URL from policy server Link header",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-03T02:15:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a60ce7d225e93756a18f4744a6de095aa535df2d",
          "body": "Implement content-addressable discovery URLs with two tiers:\n- Bootstrap (/d/bootstrap → /d/<hash>): no auth, returns OIDC config\n- Discovery (/d/current → /d/<hash>): requires auth, returns match patterns\n\nChanges:\n- Rename OIDCConfig.Audience to ClientID (breaking config change)\n- Add BootstrapAut\n[…]\n- Add GetPublicKey/GetBootstrap to caclient for bootstrap flow\n- Add AuthConfigToCommand to convert bootstrap config to auth command\n\nIncludes comprehensive unit tests and end-to-end integration test.",
          "is_bot": false,
          "headline": "Add two-tier discovery: public bootstrap and authenticated endpoints",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2026-01-03T01:20:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a35fd5c5e0fedc31bbebf05f4cb379aaf612fce",
          "body": null,
          "is_bot": false,
          "headline": "",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-28T00:21:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "69951f562da0edfcf817c444905199acbf5cb62d",
          "body": "Enables serving discovery URLs through a CDN by allowing the policy server\nto return absolute URLs instead of relative ones. When set, both the Link\nheader and redirect Location use the configured base URL.",
          "is_bot": false,
          "headline": "Add --discovery-base-url flag to policy server",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-28T00:21:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ed83619639d8e00ea505b36a414451527eb4f727",
          "body": null,
          "is_bot": false,
          "headline": "",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-27T19:50:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3cdad5887aac4237ceac25c17064d5ff6b624d30",
          "body": "Introduce /d/current endpoint that redirects (302) to the content-addressed\n/d/{hash} endpoint. This enables proper HTTP cache invalidation:\n\n- /d/current: cached 5 minutes, temporary redirect to content-addressed URL\n- /d/{hash}: cached forever (immutable)\n\nUses 302 Found (temporary) rather than 30\n[…]\n new discovery\nURL after their cached redirect expires. The CA/policy server Link header\nnow always points to /d/current.\n\nIncludes test verifying caclient follows redirects with Authorization header.",
          "is_bot": false,
          "headline": "Add discovery URL redirect pattern for HTTP caching",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-27T19:29:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a2e1937f53efdd79ca8fd631e871b8481052a7d3",
          "body": "Replace time.Sleep() calls with proper synchronization using a new\nReady() channel on Broker that is closed when the listener is ready.\n\nChanges:\n- Add ready channel to Broker struct, closed after listener starts\n- Add Ready() method returning the channel for callers to wait on\n- Replace all time.Sl\n[…]\nfor concurrent execution\n- Add shortTempDir() helper to avoid Unix socket path length limits\n  (macOS has ~104 byte limit, t.TempDir() paths can exceed this)\n\nTests now complete in ~2.4s consistently.",
          "is_bot": false,
          "headline": "Remove arbitrary time.Sleep waits from broker tests",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-27T18:48:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "901c1bb434b644868400bf5951db9faacb0d1a7d",
          "body": null,
          "is_bot": false,
          "headline": "Cleaning up tasks",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-27T00:52:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2c99173bd84ee5eacf65e481ef9530a02252d767",
          "body": "The broker base64url-encodes tokens for binary safety, but the discovery\nhandler was passing the encoded token directly to the OIDC validator.\nThis caused \"malformed jwt\" errors since the validator expected a raw JWT.\n\nAdd base64url decoding in discovery handler to match the policy handler\nbehavior. Update tests to use properly encoded tokens.",
          "is_bot": false,
          "headline": "Fix discovery handler to decode base64url tokens",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:55:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4849e06decdc3635c9f4273e2894b96a2867f5fb",
          "body": "Verifies that patterns like badb{,.home} correctly match both\nshort hostnames (badb) and FQDNs (badb.home).",
          "is_bot": false,
          "headline": "Add test for brace expansion pattern matching",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:28:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a41f5a6af03150b7fe6d52488e46f88a238c65b",
          "body": null,
          "is_bot": false,
          "headline": "cleanup deps",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:26:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a0e659a68c93cf41c4405a2397e6896e7565ee1",
          "body": "Replace filepath.Match with doublestar.Match in all host pattern matching\nlocations to enable brace expansion syntax like `badb{,.home}` for matching\nboth short hostnames and FQDNs with a single pattern.\n\nAffected files:\n- pkg/policy/policy.go\n- pkg/policyserver/evaluator/evaluator.go  \n- pkg/broker/broker.go",
          "is_bot": false,
          "headline": "Switch host pattern matching to doublestar for brace expansion",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:24:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f62ab78b8d24023d777059d99ffd81e93bba003c",
          "body": "Previously, defaults.Allow created a wildcard '*' pattern that matched\nany host. This meant users could get certificates for hosts not explicitly\nlisted in the Hosts config.\n\nNow, a host must match an explicit pattern in Hosts before authorization\nis granted. defaults.Allow is merged into each host \n[…]\n- Expiration/extensions use pattern matching (not exact key lookup)\n\nExample: With hosts: {\"v*\": {...}, \"badb\": {}} and defaults.allow,\nconnecting to 'wobble' now fails, while 'v1' and 'badb' succeed.",
          "is_bot": false,
          "headline": "Policy server: require host pattern match before defaults apply",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:14:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "47df486be369810d8039dd166a0f6f86628bdb84",
          "body": null,
          "is_bot": false,
          "headline": "reuire user match at least one host to do a HELLO",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T03:04:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "724a02c1a5d8359657b628db0a47b85e05322bfe",
          "body": "- pkg/caclient: Add timing to doRequest, doHello, fetchDiscovery\n- pkg/ca: Add logger field and WithLogger option, log policy requests\n- cmd/epithet/ca: Wire up logger to CA\n- cmd/epithet/policy: Add logging to resolveCAPubkey URL fetches\n\nLogs method, URL, body_size, duration_ms, and status at DEBUG level.\nDoes not log sensitive data (tokens, body content).",
          "is_bot": false,
          "headline": "Add DEBUG level logging for all HTTP requests",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T02:56:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d88bf2d936e66161c03ef12abb58266f1eeea2b7",
          "body": "Use #!/bin/bash instead of #!/bin/sh in the test script. On Linux,\n/bin/sh is typically dash, which doesn't support \\x hex escapes in\nprintf - it outputs them as literal characters instead of binary bytes.",
          "is_bot": false,
          "headline": "Fix TestAuth_Run_BinaryTokenPreservation on Linux CI",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T01:40:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ecb0617824279037c5f4ee19ec8fde5227e9fb5",
          "body": null,
          "is_bot": false,
          "headline": "discovery end to end I think",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-26T01:35:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7cca30706a8dce135e0ade860b34f0b1f4c2601",
          "body": "GetDiscovery() now uses a cached discovery URL instead of making hello\nrequests to the CA. The URL is learned from cert response Link headers\nand cached in the Client struct.\n\nThis avoids unnecessary network calls when checking host patterns in\nshouldHandle() - if no discovery URL is cached yet, it \n[…]\nached URL instead of making hello requests\n- GetCert() caches the discovery URL from Link header\n- Add SetDiscoveryURL() for testing\n- Remove unused doHelloRequest()\n- Update caclient and broker tests",
          "is_bot": false,
          "headline": "caclient: Cache discovery URL to short-circuit pattern checks",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-25T03:38:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c65455b9e4ef798ab72690e7e5d3abe49ca5f3a3",
          "body": "Add GET /d/<hash> discovery endpoint that returns match patterns with\nCache-Control: immutable header for HTTP caching.\n\nRefactor to separate authentication from authorization:\n- Add TokenValidator interface for token validation (extracts identity)\n- Change PolicyEvaluator.Evaluate to take identity \n[…]\nscovery endpoint\n- pkg/policyserver/policyserver.go: Add TokenValidator interface\n- pkg/policyserver/oidc/validator.go: Implement ValidateAndExtractIdentity\n- cmd/epithet/policy.go: Wire up /d/* route",
          "is_bot": false,
          "headline": "Policy server: Add discovery endpoint and separate auth from authz",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-24T23:47:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "58862c77e57c0f650d4110e56ff6584420b94f6c",
          "body": null,
          "is_bot": false,
          "headline": "WIP on discovery handling",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-24T23:27:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0ad8c231f2d20b909a711ba01f7b3f23d346d208",
          "body": "- Add Discovery type with MatchPatterns\n- Add CertResponse type wrapping certificate, policy, and discovery URL\n- Add parseLinkHeader() internal function for RFC 8288 Link header parsing\n- Update GetCert to return CertResponse with discovery URL\n- Replace Hello with GetDiscovery that validates token and fetches discovery\n- Update broker to use CertResponse\n- Add tests for GetDiscovery and GetCert with discovery URL",
          "is_bot": false,
          "headline": "CA client: Link header parsing and GetDiscovery",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-24T23:07:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4f3ba02be52a99b2c24e75cb538b6b461e0aa8b",
          "body": null,
          "is_bot": false,
          "headline": "bt -> yatl",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-24T04:33:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e8f0ee469c106e2a7ab4a1fc38d9b20cb622bd61",
          "body": "Read Link header from policy server responses, resolve relative URLs\nagainst the policy server URL using url.URL.ResolveReference (RFC 3986),\nand set the resolved Link header on CA server responses.\n\nChanges:\n- Add DiscoveryURL field to PolicyResponse and PolicyError\n- Add extractDiscoveryURL() help\n[…]\nLink headers\n- Set Link header on all CA responses (success, errors, hello)\n\nTests:\n- Unit tests for extractDiscoveryURL (relative, absolute, malformed)\n- Integration tests for Link header passthrough",
          "is_bot": false,
          "headline": "CA server: Pass through Link header from policy server",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-19T05:03:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b28b76e8dbd994c088fedd6f39ea25c5859d32ef",
          "body": "Add Link header to all policy server responses containing a relative\ndiscovery URL: </d/hash>; rel=\"discovery\"\n\n- Add DiscoveryHash() method to PolicyRulesConfig that computes a\n  content-addressable 12-char SHA256 hash of the policy rules (hosts\n  and defaults.allow keys, sorted for determinism)\n- \n[…]\nh in cmd/epithet/policy.go with logging\n\nThe relative URL allows the CA to rewrite it to absolute using its\nknown policy server URL. The hash is extensible for future matching\nattributes beyond hosts.",
          "is_bot": false,
          "headline": "Policy server: Add Discovery Link header",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-19T04:34:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42522109d5a591d34a72928585190e276e7cf753",
          "body": null,
          "is_bot": false,
          "headline": "Cleanup tasks whch are done",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-18T06:09:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f89891c99c50ce93fc8c04209eeef32139eacd17",
          "body": "  Add Hello(ctx, token) method to validate a token with the CA server without\n  requesting a certificate. Sends empty body {} with Authorization: Bearer header.\n\n  - Returns nil on success (200), or appropriate error type (InvalidTokenError,\n    PolicyDeniedError, CAUnavailableError, etc.)\n  - Tries endpoints in priority order, fails over to next CA on 5xx errors\n  - Auth/policy errors (401, 403) return immediately without failover",
          "is_bot": false,
          "headline": "Add Hello() method for token validation",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-18T06:06:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6937f60a0699a01f1a4b4052b2d6d4dac0d479b",
          "body": "  Protocol changes for Broker→CA and CA→Policy communication:\n\n  Broker→CA:\n  - Token sent in Authorization: Bearer header (not request body)\n  - CreateCertRequest fields are now pointers for shape-based routing\n\n  CA→Policy:\n  - Signature sent in Authorization: Bearer header (not request body)\n  - \n[…]\nuting in CA server:\n  - Empty body (both fields nil) = hello request, validates token, returns 200\n  - Both fields present = certificate request (existing flow)\n  - One field present = 400 Bad Request",
          "is_bot": false,
          "headline": "Move tokens and signatures to Authorization headers; add hello requests",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-18T05:58:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "97e40f97af8a9299534551bb1c496a1f780e62bc",
          "body": null,
          "is_bot": false,
          "headline": "need to switch broker control socket protocol",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-15T05:22:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1522063a54e4e16bf1edd2df8cf2b73041c30d17",
          "body": null,
          "is_bot": false,
          "headline": "clean up tasks",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T20:16:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25114a46e330bcf25f9293b06c898d62cb6c04ba",
          "body": null,
          "is_bot": false,
          "headline": "clean up task names",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T17:41:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7797d9067893f7ae11b51ce614f164bc5d9decc",
          "body": null,
          "is_bot": false,
          "headline": "more design work to get efficient match",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T17:37:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9bf43336751745d885b2520ce1008e3ec48ed03",
          "body": "Tokens from auth plugins may contain arbitrary bytes (invalid UTF-8).\nPreviously, raw bytes were cast to string then JSON encoded, which\ncorrupts invalid UTF-8 (replaced with U+FFFD).\n\nNow tokens are:\n- Base64url encoded immediately upon receipt from auth plugin (broker)\n- Passed through CA unchange\n[…]\nkg/broker/auth_test.go: update expected values, add binary token test\n- pkg/policyserver/policyserver.go: decode token before evaluation\n- pkg/policyserver/policyserver_test.go: encode tokens in tests",
          "is_bot": false,
          "headline": "Fix token encoding: base64url encode at broker, decode at policy server",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T17:10:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8d7eac1691f6c719b178cf480f8650eef95075ce",
          "body": null,
          "is_bot": false,
          "headline": "more protocol work",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T16:37:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c75a17856915a996dfb256a33b6628f5223f32b3",
          "body": "Added task 6v9zryht to explore mckoss/dawg packed-trie format for\nefficient host encoding when there are thousands of hosts without\nnice glob patterns. Uses ARPA-style reversed hostnames for better\nsuffix compression.\n\nBlocked on basic discovery implementation (xd0v5v9j).",
          "is_bot": false,
          "headline": "Discovery protocol design: Add packed trie (DAWG) exploration task",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T06:00:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e7f879fc37fb0a7cc3abffa5ec4d89fe07465ac",
          "body": "…hanges\n\nProtocol changes:\n- Bearer auth in Authorization header (base64url encoded tokens)\n- Single CA endpoint with shape-based routing (hello vs cert requests)\n- Policy server returns Link header with discovery URL\n- CA passes through Link header unchanged\n- Broker caches discovery, short-circuit\n[…]\nserver pass through link header\n- xh: CA client hello request\n- sd: Policy server discovery endpoint\n- ca: CA client link header parsing\n- 18: Broker discovery caching\n- xd: Broker match short-circuit",
          "is_bot": false,
          "headline": "Discovery protocol design: Add bt tasks for CA/broker/policy server c…",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T05:21:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cfb60d8fef394e333e4c94698c7fcc1fdf24bb58",
          "body": "When a CA/policy server cannot or is unwilling to handle a connection,\nit can now return HTTP 422. This is distinct from:\n- 401 (token invalid) - triggers retry with fresh token\n- 403 (policy denied) - authorized but not allowed\n- 422 (not handled) - this CA doesn't serve this connection\n\nThe broker\n[…]\nn policyserver\n- Add broker error handling (no retry, fail match)\n- 422 does not trip circuit breaker (not infrastructure issue)\n- Add tests for caclient, policyserver\n- Update CLAUDE.md documentation",
          "is_bot": false,
          "headline": "Add 422 Unprocessable Content handling for CA/policy server",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T04:23:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7e37faf1837d304bb293f44c2a9a11b5eaba8784",
          "body": null,
          "is_bot": false,
          "headline": "task to clean up ssh block",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-14T00:02:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f409cb7f1bcdb9370a2119d7d74eba2981ed5d23",
          "body": null,
          "is_bot": false,
          "headline": "adding metric tasks and some task cleanup",
          "author_name": "Brian McCallister",
          "author_login": "brianm",
          "committed_at": "2025-12-11T19:14:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 57,
      "commits_last_year": 231,
      "latest_release_at": "2026-07-19T22:44:03Z",
      "latest_release_tag": "v0.17.3",
      "releases_from_tags": false,
      "days_since_last_push": 8,
      "active_weeks_last_year": 25,
      "days_since_latest_release": 8,
      "mean_days_between_releases": 10.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/epithet-ssh/epithet",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/epithet-ssh/epithet",
          "is_deprecated": false,
          "latest_version": "v0.17.3",
          "repository_url": "https://github.com/epithet-ssh/epithet",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-19T22:37:40Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 8
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 15,
      "watchers": 4,
      "fork_history": {
        "days": [
          {
            "date": "2021-02-01",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile",
        "contrib/freebsd/Makefile"
      ],
      "api_schema_files": [
        "proto/brokerv1/broker.proto"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 29428,
      "source_files_sampled": 62,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 669
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "golang.org/x/crypto",
            "direct": true,
            "version": "v0.49.0",
            "severity": "critical",
            "ecosystem": "go",
            "cvss_score": 10,
            "advisory_ids": [
              "GHSA-45gg-vh54-h5m9",
              "GHSA-5cgq-3rg8-m6cv",
              "GHSA-78mq-xcr3-xm33",
              "GHSA-89gr-r52h-f8rx",
              "GHSA-9m57-25v3-79x9",
              "GHSA-f5wc-c3c7-36mc",
              "GHSA-jppx-rxg9-jmrx",
              "GHSA-q4h4-gmj2-qvw2",
              "GHSA-qpw4-5x99-6vjp",
              "GHSA-rm3j-f69w-wqmq"
            ],
            "fixed_version": "0.52.0",
            "advisory_count": 27,
            "oldest_advisory_days": 67
          },
          {
            "name": "google.golang.org/grpc",
            "direct": true,
            "version": "v1.80.0",
            "severity": "critical",
            "ecosystem": "go",
            "cvss_score": 9.1,
            "advisory_ids": [
              "GHSA-hrxh-6v49-42gf",
              "GO-2026-6061"
            ],
            "fixed_version": "1.82.1",
            "advisory_count": 2,
            "oldest_advisory_days": 6
          },
          {
            "name": "golang.org/x/net",
            "direct": false,
            "version": "v0.52.0",
            "severity": "moderate",
            "ecosystem": "go",
            "cvss_score": 6.5,
            "advisory_ids": [
              "GHSA-5cv4-jp36-h3mw",
              "GO-2026-4918",
              "GO-2026-5025",
              "GO-2026-5026",
              "GO-2026-5027",
              "GO-2026-5028",
              "GO-2026-5029",
              "GO-2026-5030",
              "GO-2026-5942"
            ],
            "fixed_version": "1.26.3",
            "advisory_count": 9,
            "oldest_advisory_days": 81
          },
          {
            "name": "github.com/go-chi/chi/v5",
            "direct": true,
            "version": "v5.2.5",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5774",
              "GO-2026-5775",
              "GO-2026-5777"
            ],
            "fixed_version": "5.3.0",
            "advisory_count": 3,
            "oldest_advisory_days": 3
          },
          {
            "name": "go.opentelemetry.io/otel",
            "direct": false,
            "version": "v1.41.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5158"
            ],
            "fixed_version": "1.44.0",
            "advisory_count": 1,
            "oldest_advisory_days": 3
          },
          {
            "name": "golang.org/x/sys",
            "direct": false,
            "version": "v0.42.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5024"
            ],
            "fixed_version": "0.44.0",
            "advisory_count": 1,
            "oldest_advisory_days": 66
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.35.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5970"
            ],
            "fixed_version": "0.39.0",
            "advisory_count": 1,
            "oldest_advisory_days": 13
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "unknown": 4,
          "critical": 2,
          "moderate": 1
        },
        "advisory_count": 44,
        "affected_count": 7,
        "assessed_count": 51,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 3
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/alecthomas/kong",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.15.0"
        },
        {
          "name": "github.com/cbroglie/mustache",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.4.0"
        },
        {
          "name": "github.com/coreos/go-oidc/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.17.0"
        },
        {
          "name": "github.com/go-chi/chi/v5",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v5.2.5"
        },
        {
          "name": "github.com/int128/oauth2cli",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.18.0"
        },
        {
          "name": "github.com/lmittmann/tint",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.3"
        },
        {
          "name": "github.com/mikesmitty/edkey",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20170222072505-3356ea4e686a"
        },
        {
          "name": "github.com/pkg/browser",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20240102092130-5ac0b6a4141c"
        },
        {
          "name": "github.com/stretchr/testify",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.11.1"
        },
        {
          "name": "golang.org/x/crypto",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.49.0"
        },
        {
          "name": "golang.org/x/oauth2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.36.0"
        },
        {
          "name": "gotest.tools",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.2.0+incompatible"
        },
        {
          "name": "github.com/alecthomas/kong-yaml",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.2.0"
        },
        {
          "name": "github.com/bmatcuk/doublestar/v4",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v4.10.0"
        },
        {
          "name": "github.com/gregjones/httpcache",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20190611155906-901d90724c79"
        },
        {
          "name": "github.com/sony/gobreaker/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.4.0"
        },
        {
          "name": "github.com/yaronf/httpsign",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.5.1"
        },
        {
          "name": "google.golang.org/grpc",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.80.0"
        },
        {
          "name": "google.golang.org/protobuf",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.36.11"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/alecthomas/kong",
            "direct": true,
            "version": "v1.15.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/alecthomas/kong-yaml",
            "direct": true,
            "version": "v0.2.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/bmatcuk/doublestar/v4",
            "direct": true,
            "version": "v4.10.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cbroglie/mustache",
            "direct": true,
            "version": "v1.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/coreos/go-oidc/v3",
            "direct": true,
            "version": "v3.17.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-chi/chi/v5",
            "direct": true,
            "version": "v5.2.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gregjones/httpcache",
            "direct": true,
            "version": "v0.0.0-20190611155906-901d90724c79",
            "ecosystem": "go"
          },
          {
            "name": "github.com/int128/oauth2cli",
            "direct": true,
            "version": "v1.18.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lmittmann/tint",
            "direct": true,
            "version": "v1.1.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mikesmitty/edkey",
            "direct": true,
            "version": "v0.0.0-20170222072505-3356ea4e686a",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pkg/browser",
            "direct": true,
            "version": "v0.0.0-20240102092130-5ac0b6a4141c",
            "ecosystem": "go"
          },
          {
            "name": "github.com/sony/gobreaker/v2",
            "direct": true,
            "version": "v2.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/stretchr/testify",
            "direct": true,
            "version": "v1.11.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yaronf/httpsign",
            "direct": true,
            "version": "v0.5.1",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/crypto",
            "direct": true,
            "version": "v0.49.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/oauth2",
            "direct": true,
            "version": "v0.36.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/grpc",
            "direct": true,
            "version": "v1.80.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/protobuf",
            "direct": true,
            "version": "v1.36.11",
            "ecosystem": "go"
          },
          {
            "name": "gopkg.in/yaml.v3",
            "direct": true,
            "version": "v3.0.1",
            "ecosystem": "go"
          },
          {
            "name": "gotest.tools",
            "direct": true,
            "version": "v2.2.0+incompatible",
            "ecosystem": "go"
          },
          {
            "name": "github.com/davecgh/go-spew",
            "direct": false,
            "version": "v1.1.2-0.20180830191138-d8f796af33cc",
            "ecosystem": "go"
          },
          {
            "name": "github.com/decred/dcrd/dcrec/secp256k1/v4",
            "direct": false,
            "version": "v4.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dunglas/httpsfv",
            "direct": false,
            "version": "v1.0.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-jose/go-jose/v4",
            "direct": false,
            "version": "v4.1.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/goccy/go-json",
            "direct": false,
            "version": "v0.10.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/go-cmp",
            "direct": false,
            "version": "v0.7.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/int128/listener",
            "direct": false,
            "version": "v1.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/kr/pretty",
            "direct": false,
            "version": "v0.3.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/blackmagic",
            "direct": false,
            "version": "v1.0.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/dsig",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/dsig-secp256k1",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/httpcc",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/httprc",
            "direct": false,
            "version": "v1.0.6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/httprc/v3",
            "direct": false,
            "version": "v3.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/iter",
            "direct": false,
            "version": "v1.0.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/jwx/v2",
            "direct": false,
            "version": "v2.1.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/jwx/v3",
            "direct": false,
            "version": "v3.0.12",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/option",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lestrrat-go/option/v2",
            "direct": false,
            "version": "v2.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pkg/errors",
            "direct": false,
            "version": "v0.9.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pmezard/go-difflib",
            "direct": false,
            "version": "v1.0.1-0.20181226105442-5d4384ee4fb2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/rogpeppe/go-internal",
            "direct": false,
            "version": "v1.14.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/segmentio/asm",
            "direct": false,
            "version": "v1.2.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/valyala/fastjson",
            "direct": false,
            "version": "v1.6.4",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel",
            "direct": false,
            "version": "v1.41.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/sdk/metric",
            "direct": false,
            "version": "v1.41.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/net",
            "direct": false,
            "version": "v0.52.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sync",
            "direct": false,
            "version": "v0.20.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": false,
            "version": "v0.42.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.35.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/genproto/googleapis/rpc",
            "direct": false,
            "version": "v0.0.0-20260406210006-6f92a3bedf2d",
            "ecosystem": "go"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 51,
        "direct_count": 20,
        "indirect_count": 31
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 1,
        "merged_prs": 13,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 3,
        "closed_unmerged_prs": 12
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "brianm",
          "commits": 272,
          "avatar_url": "https://avatars.githubusercontent.com/u/1291?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "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/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "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": 9,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 4,
            "reason": "5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4",
            "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": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "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": 0,
            "reason": "29 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "ba27e29688043cdf2adc08f8ea470c82837c2c1c",
        "ran_at": "2026-07-28T05:46:54Z",
        "aggregate_score": 3.7,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-21T15:44:57Z",
      "oldest_open_prs": [
        {
          "number": 29,
          "created_at": "2026-04-18T22:30:38Z",
          "last_comment_at": "2026-07-19T22:43:30Z",
          "last_comment_author": "brianm"
        }
      ],
      "last_merged_pr_at": "2026-02-21T22:50:17Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/epithet-ssh/epithet",
    "host": "github.com",
    "name": "epithet",
    "owner": "epithet-ssh"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": "The weighted overall 56 is calibrated to 59 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 56,
            "calibrated": 59,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 59,
      "inputs": {
        "security": 42,
        "vitality": 77,
        "community": 32,
        "governance": 55,
        "calibration": "2026-08-02",
        "engineering": 62,
        "ai_readiness": 78,
        "weighted_overall_raw": 56
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 77,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "commits_last_year": 231,
              "human_commit_share": 1,
              "days_since_last_push": 8,
              "active_weeks_last_year": 25
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 8 days ago",
                "points": 28.8,
                "status": "partial",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "25/52 weeks with commits",
                "points": 17.3,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 25
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "231 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 231
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4",
                "points": 4,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 57,
              "latest_release_tag": "v0.17.3",
              "releases_from_tags": false,
              "days_since_latest_release": 8,
              "mean_days_between_releases": 10.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "57 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 57
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 8 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~10.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 10.8
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 14,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 14 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 14
                    }
                  }
                ],
                "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": 32,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 21,
            "inputs": {
              "forks": 1,
              "stars": 15,
              "watchers": 4,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "15 stars",
                "points": 18.6,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 15
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "4 watchers",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "weak",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 55,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 20,
            "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 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 66,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 0,
              "closed_issues": 3,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 12,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 42,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/25 decided PRs merged",
                "points": 15.6,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 25
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "epithet-ssh",
              "public_repos": 11,
              "account_age_days": 2467
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of epithet-ssh",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "epithet-ssh"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "11 public repos, account ~6 yr old",
                "points": 19.9,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 11
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/epithet-ssh/epithet"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 8
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 8 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 8
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "69 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 69
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 62,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "weak",
        "name": "Security",
        "value": 42,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "weak",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 37,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 3.7
            },
            "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": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "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.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4",
                "points": 3,
                "status": "partial",
                "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 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "29 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "moderate",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories. Remaining weights renormalized. Matched 51 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": 51
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 61,
            "inputs": {
              "source": "osv",
              "advisories": 44,
              "affected_packages": 7,
              "assessed_packages": 51,
              "unassessed_packages": 0,
              "affected_by_severity": "critical 2, moderate 1, unknown 4",
              "direct_affected_packages": 3
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "3 affected: golang.org/x/crypto v0.49.0 (critical 10.0), google.golang.org/grpc v1.80.0 (critical 9.1), github.com/go-chi/chi/v5 v5.2.5 (unknown)",
                "points": 5.4,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 3,
                      "packages": "golang.org/x/crypto v0.49.0 (critical 10.0), google.golang.org/grpc v1.80.0 (critical 9.1), github.com/go-chi/chi/v5 v5.2.5 (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": "exceptional",
            "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": 51,
              "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
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "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": 78,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.74,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 669
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, 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": "74 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 39.5,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 74,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile",
                "contrib/freebsd/Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.02,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile, contrib/freebsd/Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile, contrib/freebsd/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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "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": "2 of the last 100 commits agent-authored or agent-credited",
                "points": 4,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 2,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "exceptional",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 29428,
              "source_files_sampled": 62,
              "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/62 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 62,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "excellent",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": [
                "proto/brokerv1/broker.proto"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "proto/brokerv1/broker.proto",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "proto/brokerv1/broker.proto"
                    }
                  }
                ],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "labels": [
        "library"
      ],
      "scores": {
        "library": 6,
        "network-service": 3
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:go",
          "weight": 6
        },
        {
          "tier": "structure",
          "label": "network-service",
          "source": "api_schema",
          "weight": 3
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.3.1"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T05:47:00.252466Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/e/epithet-ssh/epithet.svg",
  "full_name": "epithet-ssh/epithet",
  "license_state": "custom",
  "license_spdx": null
}

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

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

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