Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 2.3.1 · 2026-07-28 05:47 UTC

epithet-ssh / epithet

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

GoEigene Lizenz★ 15 Sterne⑂ 1 Forkseit Juli 2017Auf GitHub ansehen ↗

epithet-ssh/epithet erreicht einen Gesundheitsindex von 59 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei AI Readiness (78/100) ab, am schwächsten bei Community & Adoption (32/100). Zuletzt vor 8 Tagen aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

59
gesamt / 100
Mittel

Software-Gesundheitsindex

Metriken werden auf einer standardisierten Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr gewichtetes Mittel, kalibriert auf die Verteilung des öffentlichen Registers, sodass die Stufen Perzentilbedeutung tragen; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze Gefährdet von 34.

59
Außergewöhnlich93-100Die Spitzengruppe des Registers (≈ obere 5 %); erfüllt im Wesentlichen alle geprüften Kriterien
Exzellent80-92Durchgehend stark; geringfügige Lücken
Gut65-79Gesund; Lücken sind begrenzt und beherrschbar
Mittel50-64Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Schwach35-49Wesentliche Schwächen in mehreren Bereichen
Gefährdet20-34Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-19Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Der gewichtete Gesamtwert 56 wird auf der veröffentlichten Indexskala auf 59 kalibriert (Register-Kalibrierung 2026-08-02).

Eigentümerschaft

epithet-sshOrganisation
0 Follower11 öffentliche Reposseit Okt. 2019

Dieses Repository wird von einer Organisation getragen — geteilte, rechenschaftspflichtige Trägerschaft, die jeden einzelnen Maintainer überdauern kann.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
Gogithub.com/epithet-ssh/epithetv0.17.3-69vor 8 Tagen

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

77Gut · 21 % des Gesamtindex
Wie die Bewertung erfolgt
28.8/36Push-Aktualität — letzter Push vor 8 Tagen
17.3/36Commit-Rhythmus — 25/52 Wochen mit Commits
18/18Commit-Volumen — 231 Commits im letzten Jahr
4/10OpenSSF Scorecard: Maintained — 5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4
Verwendete Eingangsdaten
commits_last_year231
human_commit_share1
days_since_last_push8
active_weeks_last_year25
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 57 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 8 Tagen
27/27Release-Rhythmus — ein Release etwa alle 10,8 Tage
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Verwendete Eingangsdaten
releases_count57
latest_release_tagv0.17.3
releases_from_tagsnein
days_since_latest_release8
mean_days_between_releases10,8

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

32Gefährdet · 17 % des Gesamtindex
Wie die Bewertung erfolgt
18.6/60Stars — 15 Stars
0/25Forks — 1 Forks
2.7/15Watcher — 4 Watcher
Verwendete Eingangsdaten
forks1
stars15
watchers4
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
16.9/22.5Lizenz — Lizenzdatei vorhanden, keine anerkannte Lizenz
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
readme_badges
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
readme_badge_services
has_pull_request_templatenein

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

55Mittel · 23 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 100 % der Commits
1.4/13.5Breite der Beitragenden — 1 Beitragende
10/10OpenSSF Scorecard: Contributors — project has 3 contributing companies or organizations -- score normalized to 10
Verwendete Eingangsdaten
bus_factor1
contributors_sampled1
top_contributor_share1
Wie die Bewertung erfolgt
42/42Issue-Lösungsquote — 100 % der Issues geschlossen
15.6/30PR-Annahme — 13/25 entschiedene PRs gemergt
0/13Newcomer PR acceptance — kein PR eines Erstbeitragenden in 30 Tagen entschieden
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
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
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): newcomer_pr_acceptance. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
0/25Reichweite des Inhabers — 0 Follower von epithet-ssh
19.9/25Kontohistorie — 11 öffentliche Repos, Kontoalter ca. 6 Jahre
Verwendete Eingangsdaten
followers0
owner_typeOrganization
is_verified
owner_loginepithet-ssh
public_repos11
account_age_days2.467

Paketpflege

100Außergewöhnlich
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf go
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 8 Tagen
20/20Versionshistorie — 69 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesgithub.com/epithet-ssh/epithet
ecosystemsgo
any_deprecatednein
min_days_since_publish8

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

62Mittel · 19 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 2 Workflow(s)
24/24Tests vorhanden
0/16Linter-Konfiguration
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — keine Daten
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfignein
has_linter_confignein
has_precommit_confignein
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: CI-Tests. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
0/10Wiki
Verwendete Eingangsdaten
topics
has_wikinein
homepage
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

42Schwach · 16 % des Gesamtindex
Wie die Bewertung erfolgt
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 — keine Daten
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.5Lizenz — 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
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate3,7
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): ci_tests. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
5.4/35Direkte Abhängigkeiten ohne bekannte Advisories — 3 betroffen: 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/25Indirekte Abhängigkeiten ohne bekannte Advisories — transitive Menge in diesem Bereich nicht von Entwicklungs- und Test-Abhängigkeiten trennbar
40/40Keine offenen Advisories — kein Advisory ist länger als 90 Tage öffentlich
Verwendete Eingangsdaten
sourceosv
advisories44
affected_packages7
assessed_packages51
unassessed_packages0
affected_by_severitycritical 2, moderate 1, unknown 4
direct_affected_packages3
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Indirekte Abhängigkeiten ohne bekannte Advisories. Die verbleibenden Gewichte wurden renormalisiert. 51 aufgelöste Abhängigkeiten wurden mit OSV abgeglichen. Dieses Repository veröffentlicht kein Paket, das der Index auflöst; bewertet wurde daher der Abhängigkeitsgraph des Repositorys. Dieser Graph vermischt Entwicklungs- und Test-Pins mit ausgelieferten Abhängigkeiten, daher werden nur die deklarierten Laufzeit-Abhängigkeiten bewertet; transitive Befunde werden als Kontext ausgewiesen und fließen nicht in die Bewertung ein. Erreichbarkeit wird nicht analysiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Trägt ein bewusst kleines Gewicht (4 %): Agenten-Tooling ist ein echtes Pflegesignal, doch ein Repository ohne jedes Signal kann weiterhin 100/100 erreichen.

78Gut · 4 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — AGENTS.md, CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
39.5/40Lesbare Commit-Historie — 74 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,74
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes669
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile, contrib/freebsd/Makefile
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Go (statisch typisiert)
10/10Reproduzierbare Umgebung — Dockerfile, lockfile
4/10Belegte Agentenpraxis — 2 der letzten 100 Commits von Agenten verfasst oder ihnen zugeschrieben
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfilesgo.sum
has_dockerfileja
typed_languageja
bootstrap_filesMakefile, contrib/freebsd/Makefile
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0,02
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Go (statisch typisiert)
55/55Handhabbare Dateigrößen — 0/62 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageGo
largest_source_bytes29.428
source_files_sampled62
oversized_source_files0
Wie die Bewertung erfolgt
40/40API-Schema (OpenAPI/GraphQL/proto) — proto/brokerv1/broker.proto
0/20MCP-Server
40/40Lauffähige Beispiele — examples
Verwendete Eingangsdaten
example_dirsexamples
has_mcp_signalnein
api_schema_filesproto/brokerv1/broker.proto

Eckdaten

15GitHub-Sterne
1Mitwirkende
231Commits, letzte 12 Monate
8Tage seit letztem Push
57Releases
1Bus-Faktor
0offene Issues
GoPaket-Ökosysteme

Warnungen zur Datenerhebung

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

Weitere Details

OpenSSF Scorecard 3.7 / 10
3.7Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).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
k. A.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
Direkte Abhängigkeiten 20
RegistryPaketVersionsvorgabeManifest
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
Alle Abhängigkeiten 51

Vollständig aufgelöster Abhängigkeitssatz aus dem GitHub-Abhängigkeitsgraphen: 20 direkte und 31 indirekte (transitive) Pakete. Die transitive Hülle ist vollständig, wenn das Repository eine Lockfile eincheckt.

RegistryPaketVersionBeziehung
Gogithub.com/alecthomas/kongv1.15.0direkt
Gogithub.com/alecthomas/kong-yamlv0.2.0direkt
Gogithub.com/bmatcuk/doublestar/v4v4.10.0direkt
Gogithub.com/cbroglie/mustachev1.4.0direkt
Gogithub.com/coreos/go-oidc/v3v3.17.0direkt
Gogithub.com/go-chi/chi/v5v5.2.5direkt
Gogithub.com/gregjones/httpcachev0.0.0-20190611155906-901d90724c79direkt
Gogithub.com/int128/oauth2cliv1.18.0direkt
Gogithub.com/lmittmann/tintv1.1.3direkt
Gogithub.com/mikesmitty/edkeyv0.0.0-20170222072505-3356ea4e686adirekt
Gogithub.com/pkg/browserv0.0.0-20240102092130-5ac0b6a4141cdirekt
Gogithub.com/sony/gobreaker/v2v2.4.0direkt
Gogithub.com/stretchr/testifyv1.11.1direkt
Gogithub.com/yaronf/httpsignv0.5.1direkt
Gogolang.org/x/cryptov0.49.0direkt
Gogolang.org/x/oauth2v0.36.0direkt
Gogoogle.golang.org/grpcv1.80.0direkt
Gogoogle.golang.org/protobufv1.36.11direkt
Gogopkg.in/yaml.v3v3.0.1direkt
Gogotest.toolsv2.2.0+incompatibledirekt
Gogithub.com/davecgh/go-spewv1.1.2-0.20180830191138-d8f796af33ccindirekt
Gogithub.com/decred/dcrd/dcrec/secp256k1/v4v4.4.0indirekt
Gogithub.com/dunglas/httpsfvv1.0.2indirekt
Gogithub.com/go-jose/go-jose/v4v4.1.4indirekt
Gogithub.com/goccy/go-jsonv0.10.3indirekt
Gogithub.com/google/go-cmpv0.7.0indirekt
Gogithub.com/int128/listenerv1.3.0indirekt
Gogithub.com/kr/prettyv0.3.1indirekt
Gogithub.com/lestrrat-go/blackmagicv1.0.4indirekt
Gogithub.com/lestrrat-go/dsigv1.0.0indirekt
Gogithub.com/lestrrat-go/dsig-secp256k1v1.0.0indirekt
Gogithub.com/lestrrat-go/httpccv1.0.1indirekt
Gogithub.com/lestrrat-go/httprcv1.0.6indirekt
Gogithub.com/lestrrat-go/httprc/v3v3.0.1indirekt
Gogithub.com/lestrrat-go/iterv1.0.2indirekt
Gogithub.com/lestrrat-go/jwx/v2v2.1.2indirekt
Gogithub.com/lestrrat-go/jwx/v3v3.0.12indirekt
Gogithub.com/lestrrat-go/optionv1.0.1indirekt
Gogithub.com/lestrrat-go/option/v2v2.0.0indirekt
Gogithub.com/pkg/errorsv0.9.1indirekt
Gogithub.com/pmezard/go-difflibv1.0.1-0.20181226105442-5d4384ee4fb2indirekt
Gogithub.com/rogpeppe/go-internalv1.14.1indirekt
Gogithub.com/segmentio/asmv1.2.1indirekt
Gogithub.com/valyala/fastjsonv1.6.4indirekt
Gogo.opentelemetry.io/otelv1.41.0indirekt
Gogo.opentelemetry.io/otel/sdk/metricv1.41.0indirekt
Gogolang.org/x/netv0.52.0indirekt
Gogolang.org/x/syncv0.20.0indirekt
Gogolang.org/x/sysv0.42.0indirekt
Gogolang.org/x/textv0.35.0indirekt
Gogoogle.golang.org/genproto/googleapis/rpcv0.0.0-20260406210006-6f92a3bedf2dindirekt
Abhängigkeits-Advisories 7

Dieses Repository veröffentlicht kein vom Index auflösbares Paket, daher wurde sein eigener Abhängigkeitsgraph bewertet – 51 Pakete, darunter auch Entwicklungs- und Test-Pins, die nie ausgeliefert werden: 7 tragen bekannte Advisories, davon 3 direkte.

PaketVersionBeziehungSchweregradAdvisoriesBehoben in
golang.org/x/cryptov0.49.0direktkritisch270.52.0
google.golang.org/grpcv1.80.0direktkritisch21.82.1
golang.org/x/netv0.52.0indirektmittel91.26.3
github.com/go-chi/chi/v5v5.2.5direktunbekannt35.3.0
go.opentelemetry.io/otelv1.41.0indirektunbekannt11.44.0
golang.org/x/sysv0.42.0indirektunbekannt10.44.0
golang.org/x/textv0.35.0indirektunbekannt10.39.0

Ein Advisory bedeutet, dass die im Abhängigkeitsgraphen erfasste Version in den betroffenen Bereich eines Advisories fällt. Erreichbarkeit wird nicht analysiert, und der Graph enthält Entwicklungs- und Test-Pins — ein Fund kann das Werkzeug betreffen und nicht die ausgelieferte Software.

JSON-Rohbericht maschinenlesbar
{
  "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
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v2.3.1, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenGo.