Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [
"bubbletea",
"certificates",
"charm",
"cli",
"developer-tools",
"golang",
"pki",
"ssl",
"terminal",
"tls",
"tui",
"x509"
],
"is_fork": false,
"size_kb": 43679,
"has_wiki": true,
"homepage": null,
"languages": {
"Go": 258520,
"Ruby": 30,
"Shell": 1935,
"Makefile": 3334
},
"pushed_at": "2026-07-20T02:00:29Z",
"created_at": "2025-05-24T08:40:58Z",
"owner_type": "User",
"updated_at": "2026-07-20T02:00:35Z",
"description": "A terminal user interface (TUI) tool for viewing and analyzing X.509 certificate chains",
"is_archived": false,
"is_disabled": false,
"license_spdx": "Apache-2.0",
"default_branch": "main",
"license_spdx_raw": "Apache-2.0",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": "https://kanywst.github.io/",
"name": "kt",
"type": "User",
"login": "kanywst",
"company": null,
"location": null,
"followers": 8,
"avatar_url": "https://avatars.githubusercontent.com/u/45947799?v=4",
"created_at": "2018-12-17T17:39:10Z",
"is_verified": null,
"public_repos": 42,
"account_age_days": 2773
},
"license": {
"state": "standard",
"spdx_id": "Apache-2.0",
"raw_spdx": "Apache-2.0",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v1.0.0",
"kind": "major",
"published_at": "2026-07-17T14:38:48Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-06-20T09:44:49Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-06-18T16:23:58Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-06-18T10:47:08Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-06-14T15:21:45Z"
},
{
"tag": "v0.8.2",
"kind": "patch",
"published_at": "2026-06-08T11:32:37Z"
},
{
"tag": "v0.8.1",
"kind": "patch",
"published_at": "2026-05-02T07:26:44Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-05-02T07:08:43Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-04-18T06:53:11Z"
},
{
"tag": "v0.6.2",
"kind": "patch",
"published_at": "2026-03-27T18:18:46Z"
},
{
"tag": "v0.6.1",
"kind": "patch",
"published_at": "2026-03-27T15:18:23Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-03-27T15:15:57Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-01-18T12:42:27Z"
},
{
"tag": "v0.4.1",
"kind": "patch",
"published_at": "2026-01-05T04:48:05Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-01-05T04:45:23Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2025-06-19T15:33:03Z"
},
{
"tag": "v0.2.0",
"kind": "minor",
"published_at": "2025-06-08T07:06:24Z"
},
{
"tag": "v0.0.1",
"kind": "patch",
"published_at": "2025-05-24T22:53:49Z"
}
],
"recent_commits": [
{
"oid": "67d8e74c286e641a6feac25d37fd3f81f7eba167",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-20T02:00:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f5ee39f6a5998064f7b86cbf6012fa21d4a0838b",
"body": "Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6 to 7.\n- [Commits](https://github.com/actions/setup-go/compare/v6...v7)\n\n---\nupdated-dependencies:\n- dependency-name: actions/setup-go\n dependency-version: '7'\n dependency-type: direct:production\n update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"is_bot": true,
"headline": "chore(deps): bump actions/setup-go from 6 to 7",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-07-20T01:57:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3de22b454716277faef1dc4da1225b9fa69c6549",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-17T15:21:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "139bef97ca591782994c794fef1e73e8373f9d39",
"body": null,
"is_bot": false,
"headline": "fix(demo): quote $PWD in the PATH export so a path with spaces works",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T15:19:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a20671c0ad9ff10b1bd6b2089b7d1bd91e2bf34d",
"body": "The tape's hidden setup block used fixed Sleeps after go run / go build. On\na cold module cache the first go command downloads every dependency, which\ntakes far longer than the 1-2s allotted, so the download log was still\nprinting when the recording resumed and spilled into the visible frames.\n\nWait\n[…]\nth quotes (\"TAPE\"\"_x\") so it\nonly appears in the command's output, never in the typed command line --\notherwise Wait would match the moment it was typed, before the command ran.\n\nRegenerated demo.gif.",
"is_bot": false,
"headline": "fix(demo): stop the build log from leaking into demo.gif",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T15:19:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "58533c702f7cf30379cc390897b4758460cd68ba",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-17T14:21:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7030c9227e1447eb03c50af084dfa79d3e421508",
"body": "AnalyzeChain set report.Sent to the original argument and only then dropped\nnil entries into a local copy. Sent therefore still held any nils, which a\ncaller iterating it would dereference. Compact first, so Sent references\nthe cleaned slice.",
"is_bot": false,
"headline": "fix(certificate): strip nils before ChainReport keeps the slice",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "71fd9e7aa9559b4b0dcba8cfac63f8bfba0edd8e",
"body": "…ned cases\n\nTwo edges in the presentation analysis:\n\nA lone self-signed certificate was reported as a redundant root. On its own\nit is the leaf -- a self-signed server certificate the client must receive\nto connect -- not a root the sender should have left out. Only flag a\nredundant root when there \n[…]\n early, masking a missing issuer further up; and the name-only\nparent lookup could follow the wrong link. Key the visited set on the\nfingerprint, and pick the parent whose signature actually verifies.",
"is_bot": false,
"headline": "fix(certificate): harden chain analysis for self-signed and cross-sig…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6daad31c617debfd24a79e594656993508d66cbf",
"body": "The pairwise \"has any neighbour\" test had two failures. It flagged the\nprimary leaf as unrelated whenever its issuer was not sent -- reporting the\nvalidation target itself as baggage on top of the missing-issuer finding.\nAnd it missed a whole disjoint second chain, because each of its members\nhad a \n[…]\nd. Anything reachable by issuer/subject\nlinks is part of its chain; everything else is unrelated. The leaf is the\nstarting point, so it is never unrelated, and a disjoint chain is unrelated\nas a unit.",
"is_bot": false,
"headline": "fix(certificate): find unrelated certs by reachability from the leaf",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f165b4efcdd4df669331436752aa832ec7bc4b1d",
"body": "Two copies of the same certificate are not each other's issuer, so\nunrelatedIn flagged a duplicated leaf as unrelated -- once per copy -- on\ntop of the duplicate finding it already carried. Collapse duplicates by\nfingerprint before looking for unrelated certificates.\n\nAnalyzeChain is also exported, so it now drops nil entries up front rather\nthan dereferencing them.",
"is_bot": false,
"headline": "fix(certificate): do not report a duplicated certificate as unrelated",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4ea5a8f237ee18263467c04246c36ba888327a6c",
"body": "AnalyzeChain sorts the chain on its way through, and validate then sorted\nthe same certificates all over again. Carry the result, and the sort error\nwith it, so the caller can take them.\n\nAlso only report an ordering problem when the chain sorted cleanly. If\nSortChain ever fails, the sorted slice need not hold the same certificates,\nand comparing against it would report an out-of-order chain that is really\na sorting failure.",
"is_bot": false,
"headline": "refactor(certificate): carry the sorted chain on the report",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ddb595d9a33ca3ed46eaa98394b07467dc6862c4",
"body": "Verifying a chain and serving it correctly are different questions. A\nserver can present a chain that browsers accept and that curl refuses,\nbecause browsers chase the AIA URL to fetch a missing intermediate and\ncurl, Go and Java do not. It is the classic \"works in Chrome, breaks in\ncurl\" bug, and n\n[…]\nss-signed\nroot is that a chain must terminate at a CA. GTS Root R1, which google.com\nsends, has an absent issuer (GlobalSign) and must not be flagged; a leaf\nwhose intermediate was never sent must be.",
"is_bot": false,
"headline": "feat(certificate): report how the chain was served",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:19:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c23e57cb62c1a5afc34ca3ae24f521c8504436de",
"body": "The container check accepted any complete ASN.1 SEQUENCE, so a valid\ncertificate that x509 rejected -- an unsupported signature algorithm, say\n-- was reported as a PKCS#7/#12 bundle, since a certificate is also a\nSEQUENCE.\n\nLook at the first element instead: a certificate opens with the\ntbsCertifica\n[…]\ne SEQUENCE, PKCS#7 with a contentType OID, PKCS#12 with a\nversion INTEGER. Only an OID or INTEGER first element is called a\ncontainer; a cert-shaped SEQUENCE is reported as an unparseable\ncertificate.",
"is_bot": false,
"headline": "fix(certificate): tell a broken certificate apart from a PKCS container",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a66055f10c4bd9d8d53c1af12df5aaaea621ab01",
"body": "The unreadable-input branch decided \"this is a PKCS#7/#12 bundle\" from\ndata[0] == 0x30 alone, so any text starting with '0' (also 0x30) was\nreported as a container. It also logged the parse failure at Error, which\nis noise: failing to parse is the ordinary outcome for non-certificate\ninput.\n\nConfirm\n[…]\nne complete ASN.1 SEQUENCE before naming\na container. Input that begins like DER but does not is reported as an\nunparseable certificate; anything else as neither PEM nor DER. Log the\nfailure at debug.",
"is_bot": false,
"headline": "fix(certificate): detect a DER container by parsing, not the first byte",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "997ad1bfd8efb6e41a8ca10c14e4d9f68c8dd744",
"body": "Every DER certificate begins with the SEQUENCE tag, so a truncated or\ncorrupt one took the same branch as a PKCS#7/#12 bundle and was reported\nas \"DER but not a certificate\", which is a confident and wrong diagnosis.\n\nSay it could not be parsed as a certificate, and mention the containers as\nthe likely cause rather than the certain one.",
"is_bot": false,
"headline": "fix(certificate): do not claim a corrupt certificate is a PKCS container",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f334ecb880f0173811babacf4677fa89ce1f9733",
"body": "ParseCertificates only ran pem.Decode, so a raw DER file loaded as\n\"no certificates found in input\". CLAUDE.md has claimed the package \"loads\nPEM/DER from a file or stdin\" the whole time; it did not.\n\nDER is what Windows and most CAs hand out as .der / .cer, and -- more\nawkwardly -- it is what y509'\n[…]\nwhich is still unsupported) now say what they actually are.\n\nNote that x509.ParseCertificates accepts empty input and returns neither\ncertificates nor an error, so the empty case is caught explicitly.",
"is_bot": false,
"headline": "feat(certificate): accept DER input",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d1f5d5eafc69ff48bd4cec257063f62fe65d4992",
"body": "GoReleaser publishes y509 as a Homebrew cask, so `brew bundle` needs\n`cask \"y509\"`, not `brew \"y509\"`, to find it in the tap.",
"is_bot": false,
"headline": "docs: install y509 from the tap as a cask in the Brewfile",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "61674325760b8c986a8888581f7840e28037100a",
"body": "deb and rpm are Linux formats; the previous wording implied macOS got them\ntoo. Binaries are built for both.",
"is_bot": false,
"headline": "docs: say which packages are Linux only",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "530308f4e22bff000201d3c7b725dbe17e6e9b7e",
"body": "Both `make release-homebrew` and scripts/release.sh sed-edit Formula/y509.rb.\nThat directory does not exist and has not for some time: GoReleaser\npublishes the cask to kanywst/homebrew-tap now. Running either would fail\nor silently do nothing.\n\nThe checked-in Casks/y509.rb goes with them. It is a generated artifact\npinned to 0.8.1, it carries a DO NOT EDIT header, and it is not the file\nGoReleaser writes to -- it only existed to mislead anyone who tapped this\nrepository directly.",
"is_bot": false,
"headline": "chore: drop the pre-GoReleaser homebrew scripts",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5cd7031ae7b45ed10a7f1bf1fd968bd8eca41a12",
"body": "Neither documented way to install y509 worked.\n\ngo install: there is no main package at the module root -- it lives in\n./cmd/y509 -- so `go install github.com/kanywst/y509@latest` fails with\n\"not a main package\".\n\nHomebrew: the README taps this repository, whose Casks/y509.rb is pinned\nto 0.8.1. Tha\n[…]\nis at 0.12.0. Anyone following\nthe README got a binary four minor versions old.\n\nPoint at kanywst/tap, drop the checked-in cask, and mention the binary,\ndeb and rpm channels the release already ships.",
"is_bot": false,
"headline": "docs: fix both install channels",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "43fe541905897461a45f7d193032f4b7b072dff3",
"body": "If the build info carried a vcs.revision or vcs.time setting with an empty\nvalue, it replaced the \"unknown\" default with \"\", which renders as\n\"y509 version dev ()\". Only take a non-empty value.",
"is_bot": false,
"headline": "fix(version): do not let an empty VCS value overwrite \"unknown\"",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "45ed3505ea3b49157a8ca2e4dd4886ecc4c6811d",
"body": "Returning early when Version was already set meant a build that supplied\nonly Version through -ldflags would skip the VCS revision and build time\nthe toolchain had recorded, and report \"unknown\" for both. Let each value\nfall back on its own.",
"is_bot": false,
"headline": "fix(version): fall back on each build value independently",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "de88d242a3c61ad2119a7ddfe8dae2145fba9685",
"body": "The version variables are populated by -ldflags at release time, but a\n`go install` build gets no ldflags and reported itself as \"dev\" forever.\nThe toolchain has already stamped the module version and the VCS revision\ninto the binary, so read them back out of debug.ReadBuildInfo when ldflags\ndid not\n[…]\n y509 version v0.12.1-0.20260706091141-6f91c879576a\n Build: ... (6f91c87) built on 2026-07-06T09:11:41Z\n\nAn -ldflags build still wins: the fallback only runs while Version is\nstill \"dev\".",
"is_bot": false,
"headline": "fix(version): report the real version on a go install build",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "17ef176c0a1d2874e26fb0d2b8610024f3c9201b",
"body": "Execute called SetVersionTemplate but never set RootCmd.Version, and cobra\nonly registers the --version flag when Version is non-empty. So the\ntemplate was dead code and both --version and -v failed:\n\n $ y509 --version\n Error: unknown flag: --version\n\nThe man page, both shell completions, and scripts/brew-test.sh all\nadvertise --version, so this was the documented interface and it did not\nexist. Only the version subcommand worked.",
"is_bot": false,
"headline": "fix(cmd): register the --version flag",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T14:18:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a78878402e68b1af0e05ee045f4809dabe44382",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-17T13:57:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a0332bd7e7f09d556dd7f8b38fe8f32742866485",
"body": "go.mod pinned go 1.26.4, and CI builds with the toolchain that directive\nselects. govulncheck flags a crypto/tls vulnerability there, reachable\nthrough FetchChain's tls.Conn.HandshakeContext call. It is fixed in Go\n1.26.5, so raise the directive; the CI vulnerability check passes with the\npatched toolchain.",
"is_bot": false,
"headline": "fix: build against Go 1.26.5 to clear the crypto/tls advisory",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e1f93ecd22a7741450cf3f7bd16a045e74178bd3",
"body": "…s.Is\n\nThe deferred close warned on any non-nil error, but an already-closed\nconnection is expected: the cancellation watcher closes it, and a failed\nhandshake or remote hang-up can too. Skip the warning on net.ErrClosed\nrather than only on context cancellation.\n\nMatch the stat error with errors.Is(err, os.ErrNotExist) so a wrapped\nerror is handled correctly.",
"is_bot": false,
"headline": "fix: quiet an already-closed connection, match ErrNotExist with error…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4a091c81d708ca4ce5a5f03263ffc0327ff75498",
"body": "…arning\n\nSupplying both --connect and a positional argument silently ignored the\nargument, since --connect won. Reject the combination with a clear message\ninstead.\n\nWhen the context is cancelled, the watcher closes the connection, so the\ndeferred close then returns \"use of closed network connection\". That is\nexpected; only warn when the context is still live.",
"is_bot": false,
"headline": "fix: error on --connect with an argument, quiet the cancelled-close w…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a79f56113f7dc122db44b71b2cae083cbeb704ac",
"body": "…ur ctx during STARTTLS\n\nThree edges in the live-connect path:\n\nA missing file with a certificate extension went to the network:\n\"y509 chian.pem\" (a typo) contains a dot and no separator, so looksLikeHost\ntook it for a host and answered with a DNS failure instead of \"no such\nfile\". Any .pem/.crt/.ce\n[…]\ns synchronously and did not watch the context.\nThe deadline bounded it, but an early cancellation waited the deadline out.\nClose the connection when the context is done so those reads unblock at\nonce.",
"is_bot": false,
"headline": "fix: treat cert-extension paths as files, default an empty port, hono…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "667897c5a9d361cc8020b878341c4a7d270c275d",
"body": "localhost is the obvious target for local development, but it carries\nneither a dot nor a colon, so looksLikeHost took it for a filename and\nnever connected. Special-case it.\n\nRead the Postgres SSLRequest reply with io.ReadFull rather than a bare\nconn.Read: the single byte is guaranteed, not merely attempted.\n\nStop the timeout test from leaking a goroutine that outlived it by 30s --\nblock on a read until the client closes instead of sleeping.",
"is_bot": false,
"headline": "fix: treat localhost as a host, read the Postgres reply with io.ReadFull",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cbeb37e691fcb9c60ef595ba6cd2afcbb1d531be",
"body": "…esses\n\nThe STARTTLS preludes only worked against the simplest servers.\n\nSMTP replies may span several lines: RFC 5321 marks a continuation with a\nhyphen in column four and the last line with anything else. Reading only\nthe first line left the rest in the buffer, where it was read back as the\nanswer\n[…]\n it was answered with a failed DNS lookup rather than\n\"no such file\". Anything shaped like a path is now a path, and a stat error\nthat is not \"not exist\" means the file is there and the user meant it.",
"is_bot": false,
"headline": "fix(certificate): handle real SMTP and IMAP replies, and awkward addr…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fa864ebb2e6760952d21224848bbe119588f8d56",
"body": "y509 could only read certificates from a file or stdin. The README\ndocumented the workaround itself -- pipe openssl s_client into it -- which\nis a fair sign the feature was missing rather than unwanted. certigo,\nstep and tlsx all connect; y509 did not.\n\n y509 example.com:443\n y509 --connect 10\n[…]\n do by hand with openssl. An unknown protocol is rejected\nbefore dialling, so a typo does not surface as a connection error.\n\nThe connect flags are persistent, so validate and export can use them too.",
"is_bot": false,
"headline": "feat: fetch the chain from a live server",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5a1d5b296b40b6f890dbe5713b76d2adf41d0791",
"body": "When the trust-store pass fails and the self-anchored retry also fails, the\nresult carried the trust-store error (\"certificate signed by unknown\nauthority\") rather than the retry's error. But a chain with a self-signed\nanchor present should have built; that it did not is a structural fault --\nexpiry\n[…]\name constraint -- and the retry error names it.\nAn expired chain now reports expiry rather than \"unknown authority\".\n\nAlso fall back to the full subject in anchorName when the root has no\ncommon name.",
"is_bot": false,
"headline": "fix(certificate): report the structural reason a chain is broken",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "93b7719a816ebd1e0f8d478e97c6b69e84754f58",
"body": "time.Now().UnixNano() collides when certificates are minted in quick\nsuccession, which a tight test loop does, and worse on low-resolution\nclocks. Use a random 128-bit serial. A duplicate serial does not affect\nthese tests today, but it is a latent flake and cheap to remove.",
"is_bot": false,
"headline": "test(certificate): give test certificates random serials",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ba94f63348699f1e199b76286127c8f832be47a2",
"body": "x509.CertPool.AddCert panics on a nil certificate, and SystemCertPool is\ndocumented to return a nil pool with no error where no system store is\navailable -- which would then panic on the very next AddCert.\n\nVerifyChain is an exported entry point, so it does not get to assume a\nwell-formed slice. Reject a nil leaf, skip nil intermediates and nil extra\nroots, and only take the system pool when there is one.",
"is_bot": false,
"headline": "fix(certificate): guard the exported verification path against nil",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "133535247694e4bbafa78721ef0dccbe97b96b05",
"body": "No command set SilenceUsage, and Execute printed the error that cobra had\nalready printed itself. A missing file produced the error twice with the\nfull usage text wedged in between.\n\nSilence both on the root command and let Execute be the single printer.\nCobra still reports genuine usage errors, such as an unknown flag.",
"is_bot": false,
"headline": "fix(cmd): print runtime errors once, without the usage dump",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c99d0649ccd9f7579727974f80bb4a4f1e0e87a",
"body": "ValidateChain took the last certificate of its input and put it in the\nroot pool, so every chain trusted itself. Nothing ever consulted the\nsystem trust store. A lone self-signed certificate, or a bundle missing\nits root, reported \"Certificate chain is valid\" and exited 0. For a tool\nwhose job is in\n[…]\nhe subcommand, so the two can\nno longer disagree. Drop KeyUsages: ExtKeyUsageAny, which disabled EKU\nchecking and further overstated the result.\n\nAdd --roots, --no-system-roots and --host to validate.",
"is_bot": false,
"headline": "fix(certificate): verify chains against a real trust store",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-17T13:54:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ce30ad62d01380197d15271fc99ca89eed6277aa",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-16T14:47:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e0a9b934aa536d54c3792f1e6469bf279f698c9e",
"body": "The pump expanded a tea.BatchMsg one level deep, but a batched command can\nitself return a batch. Update does not understand a BatchMsg, so a nested\none was delivered to it and silently dropped. Flatten recursively to any\ndepth instead.",
"is_bot": false,
"headline": "test(model): flatten nested batches in the test pump",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-16T14:44:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f5c330b0ab31800d1b57f9f0b0674955274bf8fd",
"body": "t.Chdir changes the process working directory, which makes the test unsafe\nto run in parallel and needs Go 1.24. The chdir only existed to keep the\ntyped filename short, since each keystroke pays the cursor-blink settle.\n\nEnter the whole absolute path in a single paste instead. It is faster than\ntyping character by character, and it keeps the test off the process\nworking directory.",
"is_bot": false,
"headline": "test(model): drop t.Chdir from the export test",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-16T14:44:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "31b6c955f042fd4c6e52cf15b140fb376689b31b",
"body": "updateExportForm only handled StateCompleted, so a form that reached\nStateAborted would sit on screen, unresponsive, with no way out but esc.\ny509 intercepts ctrl+c before it reaches the form, so nothing triggers the\nabort today, but the guard is a one-liner and keeps a future abort path\nfrom stranding the UI.",
"is_bot": false,
"headline": "fix(model): dismiss the export popup if the form aborts",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-16T14:44:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c93e0e654a526f876cc6e6a69d7d73ddcdb39aa6",
"body": "The splash is dismissed by any key press, but the 500ms timer message is\nstill in flight when that happens and retired the view unconditionally.\nAnything the user opened in the first half-second -- a search, a filter,\nthe export form -- was torn down when it landed, taking their input with\nit.\n\nOnly let SplashDoneMsg retire the splash.\n\nAlso bail out of updateExportForm when huh hands back something that is not\na Form, rather than reading State off the copy we no longer hold.",
"is_bot": false,
"headline": "fix(model): stop a late splash timer from closing an open popup",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-16T14:44:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "46176ac5fefc832cf54f581fb5171082070c7ee6",
"body": "Update only handed tea.KeyPressMsg to the export form, and huh advances\nthrough messages it emits as commands: pressing enter in a field produces\na nextFieldMsg, and Form.Update only reaches StateCompleted once it\nreceives a nextGroupMsg. Those came back into Update as plain tea.Msg\nvalues, matched \n[…]\n.\n\nThe existing export tests call handleExportCommand directly, so they\npassed throughout. Add one that drives the real key path instead, pumping\ncommands back through Update the way the runtime does.",
"is_bot": false,
"headline": "fix(model): route huh's own messages so the export popup can submit",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-16T14:44:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c14bb6f2316723162151a1d98010d75acfe3a041",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-15T16:21:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "193e5de3977416732f7ca17fc373709883c0f9cb",
"body": "CLAUDE.md was swept into this branch by a careless `git add -A`. It has\nnothing to do with removing test artifacts, and whether to track it is a\nseparate decision.\n\nShadow the model inside the export subtest rather than reassigning the one\nthe sibling subtests share, and assert the exported file is non-empty --\nan empty file is exactly what this branch is cleaning up, so a zero-byte\nexport must not read as success.",
"is_bot": false,
"headline": "chore: drop CLAUDE.md from this branch, and isolate the export subtest",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-15T16:19:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "482d63710452d8dd21aa08f3d16e081f2ea887a4",
"body": "pkg/certificate/der, /pem and /invalid are tracked, zero-byte files. They\nare leftovers from an older ExportCertificate test that passed the format\nstring as the filename, so it wrote \"pem\", \"der\" and \"invalid\" into the\npackage directory. The test has since moved to temp files, but the\nartifacts wer\n[…]\n/model on every\nrun. It is gitignored, so it never got committed, but it is the same\nmistake and it would eventually make the same mess. Point it at t.TempDir\nand assert the file actually lands there.",
"is_bot": false,
"headline": "chore: remove stray test artifacts from the source tree",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-15T16:19:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a1477b2eb72124e610a8deb41c07391e79502bfe",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-14T14:21:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "199e71da4a44a84726cc7e2b83df9d8e9beb2920",
"body": "ParseCertificates incremented index for every PEM block it decoded, not\nevery certificate it kept. A bundle that also carries a private key, DH\nparameters, or a CRL -- a plain fullchain.pem with the key concatenated is\nthe common case -- therefore had those blocks consume a number.\n\nThe first certif\n[…]\nr matched the slice position, which the rest of the\npackage relies on. The parse error also reported a block number rather\nthan a certificate number.\n\nMove the increment inside the CERTIFICATE branch.",
"is_bot": false,
"headline": "fix(certificate): number certificates, not PEM blocks",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-14T14:18:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8a99b6efc059c120bf03f978ccf26e9e9a7ea918",
"body": "filterCertificates raises a PopupAlert for an unknown filter type, but the\nenter handler set popupType back to PopupNone right after calling it. That\ncleared the alert while leaving viewMode at ViewPopup, so renderPopup fell\nthrough to its default branch and drew an empty, title-less box over the\nUI. The error message it had just built was discarded.\n\nDismiss the input popup before dispatching, so a handler that raises its\nown alert keeps it.",
"is_bot": false,
"headline": "fix(model): keep the alert popup when a filter is rejected",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-07-14T14:18:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6f91c879576aad0ad2dc9d372de1e68f987091ad",
"body": "Bumps the go-minor-patch group with 3 updates: [charm.land/bubbles/v2](https://github.com/charmbracelet/bubbles), [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) and [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss).\n\n\nUpdates `charm.land/bubbles/v2` from 2.1.\n[…]\n\n dependency-version: 2.0.5\n dependency-type: direct:production\n update-type: version-update:semver-patch\n dependency-group: go-minor-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"is_bot": true,
"headline": "chore(deps): bump the go-minor-patch group with 3 updates",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-07-06T09:11:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "818e1669bc22345912885fb5ead7c255ffaf0d61",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-22T10:18:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e02e632e535cb09655f31bf548b4390908212ab1",
"body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.\n- [Release notes](https://github.com/actions/checkout/releases)\n- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/actions/checkout/compare/v6...v7)\n\n---\nupdated-dependenc\n[…]\n:\n- dependency-name: actions/checkout\n dependency-version: '7'\n dependency-type: direct:production\n update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"is_bot": true,
"headline": "chore(deps): bump actions/checkout from 6 to 7",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-22T10:15:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e5aad3706ee135bd731131c9c72c6d120358c100",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-20T10:14:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f58863e80788c19bd16ada4e25730b03b1275f19",
"body": "An empty (e.g. half-generated) certs.pem reads without error but yields no\ncertificates; treat zero-length data the same as a missing file.",
"is_bot": false,
"headline": "test(certificate): fall back when the demo cert is empty too",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T10:11:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d0f05da039fed7f1d419922de54ee2462339ce31",
"body": "ParseCertificates takes []byte, so skip the temp-file round-trip and\nhand it the generated PEM directly.",
"is_bot": false,
"headline": "test(certificate): parse the fallback chain bytes directly",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T10:11:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "499982f738bdfb90580626e74cbf11bae509fa54",
"body": "Make the file-based parse test self-sufficient under a plain `go test`\nby building a chain into a temp dir when the generated demo file is\nabsent, and remove testdata/demo/certs.pem in `make clean`.",
"is_bot": false,
"headline": "test(certificate): generate a fallback chain and clean the demo cert",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T10:11:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75d992bd9b4804293df16134f8b4814ff4e00a4b",
"body": "The committed testdata/demo/certs.pem has baked-in dates, so over time\nits \"expiring\" leaf becomes expired and the demo (and demo.gif) no longer\nshows the expiring-soon state. Untrack it, ignore it, and regenerate it\nfrom gen_demo_certs.go as a prerequisite of the test/run/demo targets so\nit is always fresh.",
"is_bot": false,
"headline": "chore(demo): stop tracking the generated demo certificate",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T10:11:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "13dc48363912fdc441fc9f0cf2dcfbbd738a22a2",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-20T09:44:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ce8c249c623eca41fe83f7b3708424ffd5ea0c28",
"body": "Drop the optional hints first, then quit and help, so the bar fits even\non very narrow terminals instead of overflowing. Split the test into a\nno-overflow check across widths down to 20 and a separate check that\nquit/help show when there's room.",
"is_bot": false,
"headline": "fix(model): keep the status bar within any width",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:42:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0f11045502d3b074e3f979d7b58ccd53094c6a6e",
"body": "…lowing\n\nThe status bar never advertised export, copy, or quit. Add them, always\nkeep q quit and ? help visible, and drop the optional hints from the end\nwhen the row is too narrow. The gap filler was also rendered with the\npadded status-bar style, which pushed the row two cells past the terminal\nwidth; render it unpadded.",
"is_bot": false,
"headline": "fix(model): show quit/export/copy hints and stop the status bar overf…",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:42:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a872db6c8e23558dbb95ceab1b642052f8172159",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-20T09:35:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "362f14668e3c87c74250ad8a73fa22edee797cba",
"body": "Clamp the key column so key+value never exceed the pane width even on\nultra-narrow panes, and route key-less lines through kv(\"\", line) instead\nof duplicating its layout.",
"is_bot": false,
"headline": "fix(model): keep key+value within width and dedup key-less rows",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:32:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e6a5dae81dc8338f459ab951d67cd38c6f6da1db",
"body": "Shrink the key column when the pane is too narrow so key + value don't\noverflow, and align key-less public-key lines under the value column\ninstead of the left margin.",
"is_bot": false,
"headline": "fix(model): keep detail rows within narrow panes",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:32:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4a00ec36caa4e446624763ceaf83b6b84677a3a8",
"body": "Check that the selected slice element itself is non-nil before\ndereferencing its Certificate field.",
"is_bot": false,
"headline": "fix(model): guard against a nil certificate entry too",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:32:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "782fd3208fed995f8181d9f01d46be71d3743e60",
"body": "Bail out of renderTabContent if the selected index is out of range or the\ncertificate is nil, wrap key-less public-key lines to the column width so\nthey don't run to the margin, and preallocate the grouped-hex builder.",
"is_bot": false,
"headline": "fix(model): guard renderTabContent and tidy detail helpers",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:32:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "817a5f1513966c8d6699b539cea2af32bb26818c",
"body": "Long values (the SHA-256 fingerprint, long DNS names) wrapped back to the\nleft margin, so the label looked value-less and the text ran together.\nWrap values inside the value column instead, group the fingerprint into\nAA:BB:CC bytes, render the public key through the same aligned key/value\nhelper, and relabel the validity lines (Lifetime / days left) so the\ntotal and the remaining time aren't confused.",
"is_bot": false,
"headline": "fix(model): keep detail values aligned and readable",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-20T09:32:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f6e66939ab84321f488e244a75f407aebcfa0103",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-19T19:26:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "34e6fd743e0bd87c1adf5ce2c534d3c9fc15e291",
"body": "Drop the init() in favour of a package var initialized by a named\nconstructor, which keeps RoundedBorder reuse without an IIFE or init.",
"is_bot": false,
"headline": "refactor(model): initialize the seam border via a named function",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:23:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1f3a8a75c5975886b0fa2fcaa9e2fea2bdb2cffe",
"body": "Replace the IIFE with a plain init that copies RoundedBorder and sets the\ntwo T-junction corners.",
"is_bot": false,
"headline": "refactor(model): build the seam border in init",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:23:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9df64891413b4d57a1252b0cd44d40536d465319",
"body": "View runs every frame, so build the right pane's T-junction border at\npackage init instead of recreating it on each render.",
"is_bot": false,
"headline": "perf(model): build the seam border once",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:23:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "edcb5bdc9a0d6a159f809fa3641350c4e52d3946",
"body": "The seam between the panes showed two rounded corners butting together\n(╭…╭ at the top, ╰…╰ at the bottom) because each pane drew its own box.\nGive the right pane's shared left edge T-junction corners so the divider\nmeets the top and bottom rules cleanly.",
"is_bot": false,
"headline": "fix(model): join the two panes with T-junctions",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:23:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c72620b094a855730c2b4be65ab2b093466565a8",
"body": "Return a plain run of spaces for the fits-on-screen case instead of\nrendering an empty styled string.",
"is_bot": false,
"headline": "refactor(model): simplify the blank scroll footer",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:22:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4574ece8df897748f56406aa5ae4c7911f9d89ba",
"body": "Sizing inner widths with PaneBorderHeight read as if a height were being\nsubtracted from a width. Add PaneBorderWidth (= 2, both side borders) and\nuse it for the viewport and scroll-footer width math.",
"is_bot": false,
"headline": "refactor(model): use a width-named constant for pane border width",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:22:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "11a106644ca47de627f65c05623875919145c6d4",
"body": "The footer width didn't account for the pane's two border columns, so it\nwas two cells wider than the content above it. Subtract the border width\nso the footer matches the rest of the pane.",
"is_bot": false,
"headline": "fix(model): size the scroll footer to the pane inner width",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:22:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "19e5865c9711ffbbf5399ce2c508c5a98e5d5454",
"body": "The right pane silently clipped anything taller than the viewport (for\nexample the bottom of the chain table on the Misc tab) with no sign there\nwas more to see. Reserve a one-row footer that shows up/down arrows and a\nscroll percentage whenever the content doesn't fit.",
"is_bot": false,
"headline": "feat(model): show a scroll indicator when detail content overflows",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:22:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "48da3eb8d3edf0ef88cedfc0954393679f154183",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-19T19:19:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1f28d7d28392ffe330709e85ff7eef546c45af2e",
"body": "Bail out when there are no tabs and clamp the active index so the strip\nand compact fallback can't panic.",
"is_bot": false,
"headline": "fix(model): guard renderTabs against empty or out-of-range tabs",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:17:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "06f406815af2fb3caf7ee080bbad0cdcfd8be1ab",
"body": "The centered underline floated under the middle of the whole compact\nlabel. Left-align it and offset by the prefix so the rule sits under the\nactive tab name.",
"is_bot": false,
"headline": "fix(model): align the compact tab underline with the active name",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:17:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "227d029f1e8717183d5882b8be30f1e59d5c34f4",
"body": "When the budget was non-positive the code returned the full strip, which\nis exactly the case where it can't fit. Fall through to the compact form\nin that case.",
"is_bot": false,
"headline": "fix(model): use compact tabs at ultra-narrow widths too",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:17:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "95a7e30d8500cc46924c24d3c0e93c610c75381b",
"body": "On narrow terminals the full Subject/Issuer/Validity/SANs/Misc strip\nwrapped onto a second line, which pushed the right pane taller than the\nleft and misaligned their bottom borders. Fall back to a compact\n\"‹ Active › i/n\" indicator when the full strip is wider than the pane.",
"is_bot": false,
"headline": "fix(model): collapse the tab strip when it doesn't fit",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T19:17:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5375e3d4a5762a0baf5133ee922c17de40ddeedd",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-19T15:28:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4c95900ff96fdc702369930f692ad447f11c4dfc",
"body": "The chain table drew its own rounded box inside the already-bordered\ndetail pane, so it read as a heavy border-in-border. Drop the outer box\nand keep only a thin rule under the header.",
"is_bot": false,
"headline": "fix(model): lighten the chain position table",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T15:25:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6d528d0a92ce52445e40392bb1897bb4e0fc475d",
"body": "Avoid time.Duration overflow on far-future NotAfter dates (the\n9999-12-31 no-expiry convention) and keep the ratio accurate for\nsub-day lifetimes by working in Unix seconds instead of hours/days.",
"is_bot": false,
"headline": "fix(model): compute the validity bar in Unix seconds",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T15:24:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1daf6523819df0d98c9bc01ac03ba05595d3f3b8",
"body": "The list's mini bar filled with the time remaining (full = healthy) while\nthe Validity tab's bar filled with the time elapsed (full = old), so the\nsame glyphs meant opposite things. Switch the Validity bar to show the\nfraction of lifetime left so both read the same way.",
"is_bot": false,
"headline": "fix(model): make both expiry bars fill in the same direction",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-19T15:24:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "aefdc6e108a69a66b1c1bf852b7ecfc801784ac0",
"body": null,
"is_bot": true,
"headline": "chore(demo): refresh demo.gif",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-18T16:26:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "022d033c994a7701baa157b173f488e291ef4112",
"body": "The medium and large splash branches used byte-identical ASCII art and\nonly the subtitle differed. Pull the two art variants out as constants\nand keep the size branching to the subtitle.",
"is_bot": false,
"headline": "refactor(model): de-duplicate splash ASCII art",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:21:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1cfacfd1ccd509b02e460eb266d3c14153fd0a47",
"body": "Add cases for a negative width and width exactly three.",
"is_bot": false,
"headline": "test(model): cover negative and boundary widths for truncateText",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:20:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2ba722761a94a8fc05be59386ab522c940172bbe",
"body": "truncateText and the certificate label truncation sliced raw bytes, so a\nmultibyte common name (CJK, IDN) could be cut in the middle of a rune and\nrender as garbage. Count and slice runes instead.",
"is_bot": false,
"headline": "fix(model): truncate names by rune, not byte",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:20:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "00b6520ab8d49be334041c44d29e9c0f0d784d96",
"body": "For a search, display the query rather than the \"search: ...\" filter\nlabel, and assert it appears in the rendered empty state.",
"is_bot": false,
"headline": "fix(model): show the search query itself in the empty state",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:19:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "949aafe9811d3a5bd3243f69d85ab599b0e6366a",
"body": "Use the right word depending on whether a search query or a named filter\nis active.",
"is_bot": false,
"headline": "fix(model): say search or filter in the empty-state hint",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:19:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "15d845788c54339e04190f8ee09bad01943ba504",
"body": "Guard against a negative height when the terminal is shorter than the\nheader plus status bar.",
"is_bot": false,
"headline": "fix(model): clamp empty-state body height to zero",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:19:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "642e0ae9d34696cf16f2e9dcefce129fe26438d3",
"body": "A filter or search that matched no certificates replaced the entire view\nwith a bare \"No certificates found.\" line, dropping the header and status\nbar. There was no hint that Esc clears the filter, so it looked like the\napp had lost its data.\n\nRender an empty state that keeps the header and status bar and tells the\nuser to press Esc.",
"is_bot": false,
"headline": "fix(model): keep the frame when a filter matches nothing",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:19:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a150018b8682b13e504f369d276c96bfbc7ceda1",
"body": "When ValidationStatus wasn't computed, an expired certificate fell\nthrough to the valid/expiring branch. Check expiry by date first so it\ngets the expired icon.",
"is_bot": false,
"headline": "fix(model): show the expired icon for expired certs in the fallback path",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:18:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4b1301ae1095726cd5add8b609e7df9b10734f4b",
"body": "Return early from the delegate when the wrapped Info or its Certificate\nis nil, and treat a nil Info in getStatusIconAndStyle as no icon, so a\nmalformed item can't panic the renderer.",
"is_bot": false,
"headline": "fix(model): guard against nil cert info in the list delegate",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:18:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d3d38a88e36f680ac7417611ca3f6d5690cb5a99",
"body": "Avoid depending on a local .y509 config for the warning threshold.",
"is_bot": false,
"headline": "test(model): use a fixed expiry window in the status icon test",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:18:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "de52059a586a6592b6fd116e425594c9cfe7cd8e",
"body": "The list status icon only knew about expired, not-yet-valid, and broken\nchain links, so a certificate expiring within the warning window still\nshowed the green valid dot while its expiry bar and the Validity tab\nbadge were already yellow. Flag the same window in the icon so the three\nagree.",
"is_bot": false,
"headline": "fix(model): show expiring-soon in the list status icon",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:18:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d688be3bb36752e220cbe2c1bdf3951442910082",
"body": "Hold the logger in an atomic.Pointer so SetLogger can run concurrently\nwith the logging calls without a data race.",
"is_bot": false,
"headline": "fix(certificate): make the package logger swap race-free",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:17:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "81f130e7cf696ea3ba51d4d086f710466f703b71",
"body": "Let callers disable logging explicitly by passing nil instead of keeping\nwhatever logger was set before.",
"is_bot": false,
"headline": "fix(certificate): reset to no-op logger when SetLogger gets nil",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:17:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f9330b1276272d4d8bc9c97f7fb6d311067b1de0",
"body": "The package built its own zap.NewProduction() logger in init(), which\nwrites to stderr and ignores the --log-file/--debug flags. Stray writes\nduring the TUI session could corrupt the screen, and the output never\nreached the configured log file.\n\nDefault to a no-op logger and let the app inject the shared logger with\nSetLogger.",
"is_bot": false,
"headline": "fix(certificate): stop the package logging to stderr on its own",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:17:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "94a6f6d925440967f448ca528b4a94644e408e77",
"body": "Guard against an empty cert.Raw (a manually built certificate that was\nnever marshaled) and list cert alongside the other accepted formats in\nthe export command help.",
"is_bot": false,
"headline": "fix(export): reject certs with no raw data and mention cert in help",
"author_name": "kanywst",
"author_login": "kanywst",
"committed_at": "2026-06-18T16:16:27Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 18,
"commits_last_year": 197,
"latest_release_at": "2026-07-17T14:38:48Z",
"latest_release_tag": "v1.0.0",
"releases_from_tags": false,
"days_since_last_push": 2,
"active_weeks_last_year": 12,
"days_since_latest_release": 4,
"mean_days_between_releases": 12.4
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 42,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "github.com/kanywst/y509",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/kanywst/y509",
"is_deprecated": false,
"latest_version": "v1.0.0",
"repository_url": "https://github.com/kanywst/y509",
"versions_count": 18,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-17T14:19:11Z",
"latest_version_yanked": null,
"days_since_latest_publish": 4
}
]
},
"popularity": {
"forks": 1,
"stars": 2,
"watchers": 1,
"fork_history": {
"days": [
{
"date": "2026-06-12",
"count": 1
}
],
"complete": true,
"collected": 1,
"total_forks": 1
},
"star_history": {
"days": [
{
"date": "2026-04-20",
"count": 1
},
{
"date": "2026-05-11",
"count": 1
}
],
"complete": true,
"collected": 2,
"total_stars": 2
},
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 25072,
"source_files_sampled": 36,
"oversized_source_files": 0,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"go.mod"
],
"advisories": {
"error": null,
"scope": "repository_graph",
"source": "osv",
"findings": [
{
"name": "golang.org/x/text",
"direct": false,
"version": "v0.36.0",
"severity": "unknown",
"ecosystem": "go",
"cvss_score": null,
"advisory_ids": [
"GO-2026-5970"
],
"fixed_version": "0.39.0",
"advisory_count": 1,
"oldest_advisory_days": 7
}
],
"collected": true,
"malicious": [],
"truncated": false,
"by_severity": {
"unknown": 1
},
"advisory_count": 1,
"affected_count": 1,
"assessed_count": 218,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go"
],
"dependencies": [
{
"name": "charm.land/bubbles/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.1.1"
},
{
"name": "charm.land/bubbletea/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.8"
},
{
"name": "charm.land/huh/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.3"
},
{
"name": "charm.land/lipgloss/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.5"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/spf13/viper",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.21.0"
},
{
"name": "go.uber.org/zap",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.28.0"
}
],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "charm.land/bubbles/v2",
"direct": true,
"version": "v2.1.1",
"ecosystem": "go"
},
{
"name": "charm.land/bubbletea/v2",
"direct": true,
"version": "v2.0.8",
"ecosystem": "go"
},
{
"name": "charm.land/huh/v2",
"direct": true,
"version": "v2.0.3",
"ecosystem": "go"
},
{
"name": "charm.land/lipgloss/v2",
"direct": true,
"version": "v2.0.5",
"ecosystem": "go"
},
{
"name": "github.com/spf13/cobra",
"direct": true,
"version": "v1.10.2",
"ecosystem": "go"
},
{
"name": "github.com/spf13/viper",
"direct": true,
"version": "v1.21.0",
"ecosystem": "go"
},
{
"name": "go.uber.org/zap",
"direct": true,
"version": "v1.28.0",
"ecosystem": "go"
},
{
"name": "4d63.com/gocheckcompilerdirectives",
"direct": false,
"version": "v1.3.0",
"ecosystem": "go"
},
{
"name": "4d63.com/gochecknoglobals",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "codeberg.org/chavacava/garif",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "codeberg.org/polyfloyd/go-errorlint",
"direct": false,
"version": "v1.9.0",
"ecosystem": "go"
},
{
"name": "dev.gaijin.team/go/exhaustruct/v4",
"direct": false,
"version": "v4.0.0",
"ecosystem": "go"
},
{
"name": "dev.gaijin.team/go/golib",
"direct": false,
"version": "v0.6.0",
"ecosystem": "go"
},
{
"name": "github.com/4meepo/tagalign",
"direct": false,
"version": "v1.4.3",
"ecosystem": "go"
},
{
"name": "github.com/abirdcfly/dupword",
"direct": false,
"version": "v0.1.7",
"ecosystem": "go"
},
{
"name": "github.com/adminbenni/iota-mixing",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/alecthomas/chroma/v2",
"direct": false,
"version": "v2.24.1",
"ecosystem": "go"
},
{
"name": "github.com/alecthomas/go-check-sumtype",
"direct": false,
"version": "v0.3.1",
"ecosystem": "go"
},
{
"name": "github.com/alexkohler/nakedret/v2",
"direct": false,
"version": "v2.0.6",
"ecosystem": "go"
},
{
"name": "github.com/alexkohler/prealloc",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/alfatraining/structtag",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/alingse/asasalint",
"direct": false,
"version": "v0.0.11",
"ecosystem": "go"
},
{
"name": "github.com/alingse/nilnesserr",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/alwxsin/noinlineerr",
"direct": false,
"version": "v1.0.5",
"ecosystem": "go"
},
{
"name": "github.com/antonboom/errname",
"direct": false,
"version": "v1.1.1",
"ecosystem": "go"
},
{
"name": "github.com/antonboom/nilnil",
"direct": false,
"version": "v1.1.1",
"ecosystem": "go"
},
{
"name": "github.com/antonboom/testifylint",
"direct": false,
"version": "v1.6.4",
"ecosystem": "go"
},
{
"name": "github.com/ashanbrown/forbidigo/v2",
"direct": false,
"version": "v2.3.1",
"ecosystem": "go"
},
{
"name": "github.com/ashanbrown/makezero/v2",
"direct": false,
"version": "v2.2.1",
"ecosystem": "go"
},
{
"name": "github.com/atotto/clipboard",
"direct": false,
"version": "v0.1.4",
"ecosystem": "go"
},
{
"name": "github.com/beorn7/perks",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/bkielbasa/cyclop",
"direct": false,
"version": "v1.2.3",
"ecosystem": "go"
},
{
"name": "github.com/blizzy78/varnamelen",
"direct": false,
"version": "v0.8.0",
"ecosystem": "go"
},
{
"name": "github.com/bombsimon/wsl/v4",
"direct": false,
"version": "v4.7.0",
"ecosystem": "go"
},
{
"name": "github.com/bombsimon/wsl/v5",
"direct": false,
"version": "v5.8.0",
"ecosystem": "go"
},
{
"name": "github.com/breml/bidichk",
"direct": false,
"version": "v0.3.3",
"ecosystem": "go"
},
{
"name": "github.com/breml/errchkjson",
"direct": false,
"version": "v0.4.1",
"ecosystem": "go"
},
{
"name": "github.com/burntsushi/toml",
"direct": false,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/butuzov/ireturn",
"direct": false,
"version": "v0.4.1",
"ecosystem": "go"
},
{
"name": "github.com/butuzov/mirror",
"direct": false,
"version": "v1.3.0",
"ecosystem": "go"
},
{
"name": "github.com/catenacyber/perfsprint",
"direct": false,
"version": "v0.10.1",
"ecosystem": "go"
},
{
"name": "github.com/catppuccin/go",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/ccojocar/zxcvbn-go",
"direct": false,
"version": "v1.0.4",
"ecosystem": "go"
},
{
"name": "github.com/cespare/xxhash/v2",
"direct": false,
"version": "v2.3.0",
"ecosystem": "go"
},
{
"name": "github.com/charithe/durationcheck",
"direct": false,
"version": "v0.0.11",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/colorprofile",
"direct": false,
"version": "v0.4.3",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/ultraviolet",
"direct": false,
"version": "v0.0.0-20260703014108-f5a850f9c2b7",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/ansi",
"direct": false,
"version": "v0.11.7",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/ordered",
"direct": false,
"version": "v0.1.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/strings",
"direct": false,
"version": "v0.0.0-20240722160745-212f7b056ed0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/term",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/termios",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/windows",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/ckaznocha/intrange",
"direct": false,
"version": "v0.3.1",
"ecosystem": "go"
},
{
"name": "github.com/clickhouse/clickhouse-go-linter",
"direct": false,
"version": "v1.2.0",
"ecosystem": "go"
},
{
"name": "github.com/clipperhouse/displaywidth",
"direct": false,
"version": "v0.11.0",
"ecosystem": "go"
},
{
"name": "github.com/clipperhouse/uax29/v2",
"direct": false,
"version": "v2.7.0",
"ecosystem": "go"
},
{
"name": "github.com/curioswitch/go-reassign",
"direct": false,
"version": "v0.3.0",
"ecosystem": "go"
},
{
"name": "github.com/daixiang0/gci",
"direct": false,
"version": "v0.13.7",
"ecosystem": "go"
},
{
"name": "github.com/dave/dst",
"direct": false,
"version": "v0.27.3",
"ecosystem": "go"
},
{
"name": "github.com/davecgh/go-spew",
"direct": false,
"version": "v1.1.1",
"ecosystem": "go"
},
{
"name": "github.com/denis-tingaikin/go-header",
"direct": false,
"version": "v0.5.0",
"ecosystem": "go"
},
{
"name": "github.com/djarvur/go-err113",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/dlclark/regexp2",
"direct": false,
"version": "v1.12.0",
"ecosystem": "go"
},
{
"name": "github.com/dustin/go-humanize",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/ettle/strcase",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/fatih/color",
"direct": false,
"version": "v1.19.0",
"ecosystem": "go"
},
{
"name": "github.com/fatih/structtag",
"direct": false,
"version": "v1.2.0",
"ecosystem": "go"
},
{
"name": "github.com/firefart/nonamedreturns",
"direct": false,
"version": "v1.0.6",
"ecosystem": "go"
},
{
"name": "github.com/fsnotify/fsnotify",
"direct": false,
"version": "v1.9.0",
"ecosystem": "go"
},
{
"name": "github.com/fzipp/gocyclo",
"direct": false,
"version": "v0.6.0",
"ecosystem": "go"
},
{
"name": "github.com/ghostiam/protogetter",
"direct": false,
"version": "v0.3.20",
"ecosystem": "go"
},
{
"name": "github.com/go-critic/go-critic",
"direct": false,
"version": "v0.14.3",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/astcast",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/astcopy",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/astequal",
"direct": false,
"version": "v1.2.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/astfmt",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/astp",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/strparse",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-toolsmith/typep",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/go-viper/mapstructure/v2",
"direct": false,
"version": "v2.5.0",
"ecosystem": "go"
},
{
"name": "github.com/go-xmlfmt/xmlfmt",
"direct": false,
"version": "v1.1.3",
"ecosystem": "go"
},
{
"name": "github.com/gobwas/glob",
"direct": false,
"version": "v0.2.3",
"ecosystem": "go"
},
{
"name": "github.com/godoc-lint/godoc-lint",
"direct": false,
"version": "v0.11.2",
"ecosystem": "go"
},
{
"name": "github.com/gofrs/flock",
"direct": false,
"version": "v0.13.0",
"ecosystem": "go"
},
{
"name": "github.com/golang/protobuf",
"direct": false,
"version": "v1.5.3",
"ecosystem": "go"
},
{
"name": "github.com/golangci/asciicheck",
"direct": false,
"version": "v0.5.0",
"ecosystem": "go"
},
{
"name": "github.com/golangci/dupl",
"direct": false,
"version": "v0.0.0-20260401084720-c99c5cf5c202",
"ecosystem": "go"
},
{
"name": "github.com/golangci/go-printf-func-name",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/golangci/gofmt",
"direct": false,
"version": "v0.0.0-20250106114630-d62b90e6713d",
"ecosystem": "go"
},
{
"name": "github.com/golangci/golangci-lint/v2",
"direct": false,
"version": "v2.12.2",
"ecosystem": "go"
},
{
"name": "github.com/golangci/golines",
"direct": false,
"version": "v0.15.0",
"ecosystem": "go"
},
{
"name": "github.com/golangci/misspell",
"direct": false,
"version": "v0.8.0",
"ecosystem": "go"
},
{
"name": "github.com/golangci/plugin-module-register",
"direct": false,
"version": "v0.1.2",
"ecosystem": "go"
},
{
"name": "github.com/golangci/revgrep",
"direct": false,
"version": "v0.8.0",
"ecosystem": "go"
},
{
"name": "github.com/golangci/rowserrcheck",
"direct": false,
"version": "v0.0.0-20260419091836-c5f79b8a11ba",
"ecosystem": "go"
},
{
"name": "github.com/golangci/swaggoswag",
"direct": false,
"version": "v0.0.0-20250504205917-77f2aca3143e",
"ecosystem": "go"
},
{
"name": "github.com/golangci/unconvert",
"direct": false,
"version": "v0.0.0-20250410112200-a129a6e6413e",
"ecosystem": "go"
},
{
"name": "github.com/google/go-cmp",
"direct": false,
"version": "v0.7.0",
"ecosystem": "go"
},
{
"name": "github.com/gordonklaus/ineffassign",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/gostaticanalysis/analysisutil",
"direct": false,
"version": "v0.7.1",
"ecosystem": "go"
},
{
"name": "github.com/gostaticanalysis/comment",
"direct": false,
"version": "v1.5.0",
"ecosystem": "go"
},
{
"name": "github.com/gostaticanalysis/forcetypeassert",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/gostaticanalysis/nilerr",
"direct": false,
"version": "v0.1.2",
"ecosystem": "go"
},
{
"name": "github.com/hashicorp/go-immutable-radix/v2",
"direct": false,
"version": "v2.1.0",
"ecosystem": "go"
},
{
"name": "github.com/hashicorp/go-version",
"direct": false,
"version": "v1.9.0",
"ecosystem": "go"
},
{
"name": "github.com/hashicorp/golang-lru/v2",
"direct": false,
"version": "v2.0.7",
"ecosystem": "go"
},
{
"name": "github.com/hexops/gotextdiff",
"direct": false,
"version": "v1.0.3",
"ecosystem": "go"
},
{
"name": "github.com/inconshreveable/mousetrap",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/jgautheron/goconst",
"direct": false,
"version": "v1.10.0",
"ecosystem": "go"
},
{
"name": "github.com/jjti/go-spancheck",
"direct": false,
"version": "v0.6.5",
"ecosystem": "go"
},
{
"name": "github.com/julz/importas",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/karamaru-alpha/copyloopvar",
"direct": false,
"version": "v1.2.2",
"ecosystem": "go"
},
{
"name": "github.com/kisielk/errcheck",
"direct": false,
"version": "v1.10.0",
"ecosystem": "go"
},
{
"name": "github.com/kkhaike/contextcheck",
"direct": false,
"version": "v1.1.6",
"ecosystem": "go"
},
{
"name": "github.com/kulti/thelper",
"direct": false,
"version": "v0.7.1",
"ecosystem": "go"
},
{
"name": "github.com/kunwardeep/paralleltest",
"direct": false,
"version": "v1.0.15",
"ecosystem": "go"
},
{
"name": "github.com/lasiar/canonicalheader",
"direct": false,
"version": "v1.1.2",
"ecosystem": "go"
},
{
"name": "github.com/ldez/exptostd",
"direct": false,
"version": "v0.4.5",
"ecosystem": "go"
},
{
"name": "github.com/ldez/gomoddirectives",
"direct": false,
"version": "v0.8.0",
"ecosystem": "go"
},
{
"name": "github.com/ldez/grignotin",
"direct": false,
"version": "v0.10.1",
"ecosystem": "go"
},
{
"name": "github.com/ldez/structtags",
"direct": false,
"version": "v0.6.1",
"ecosystem": "go"
},
{
"name": "github.com/ldez/tagliatelle",
"direct": false,
"version": "v0.7.2",
"ecosystem": "go"
},
{
"name": "github.com/ldez/usetesting",
"direct": false,
"version": "v0.5.0",
"ecosystem": "go"
},
{
"name": "github.com/leonklingele/grouper",
"direct": false,
"version": "v1.1.2",
"ecosystem": "go"
},
{
"name": "github.com/lucasb-eyer/go-colorful",
"direct": false,
"version": "v1.4.0",
"ecosystem": "go"
},
{
"name": "github.com/macabu/inamedparam",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/manuelarte/embeddedstructfieldcheck",
"direct": false,
"version": "v0.4.0",
"ecosystem": "go"
},
{
"name": "github.com/manuelarte/funcorder",
"direct": false,
"version": "v0.6.0",
"ecosystem": "go"
},
{
"name": "github.com/maratori/testableexamples",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/maratori/testpackage",
"direct": false,
"version": "v1.1.2",
"ecosystem": "go"
},
{
"name": "github.com/masterminds/semver/v3",
"direct": false,
"version": "v3.5.0",
"ecosystem": "go"
},
{
"name": "github.com/matoous/godox",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-colorable",
"direct": false,
"version": "v0.1.14",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-isatty",
"direct": false,
"version": "v0.0.20",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-runewidth",
"direct": false,
"version": "v0.0.24",
"ecosystem": "go"
},
{
"name": "github.com/matttproud/golang_protobuf_extensions",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/mgechev/revive",
"direct": false,
"version": "v1.15.0",
"ecosystem": "go"
},
{
"name": "github.com/mirrexone/unqueryvet",
"direct": false,
"version": "v1.5.4",
"ecosystem": "go"
},
{
"name": "github.com/mitchellh/go-homedir",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/mitchellh/hashstructure/v2",
"direct": false,
"version": "v2.0.2",
"ecosystem": "go"
},
{
"name": "github.com/moricho/tparallel",
"direct": false,
"version": "v0.3.2",
"ecosystem": "go"
},
{
"name": "github.com/muesli/cancelreader",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/nakabonne/nestif",
"direct": false,
"version": "v0.3.1",
"ecosystem": "go"
},
{
"name": "github.com/nishanths/exhaustive",
"direct": false,
"version": "v0.12.0",
"ecosystem": "go"
},
{
"name": "github.com/nishanths/predeclared",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/nunnatsa/ginkgolinter",
"direct": false,
"version": "v0.23.0",
"ecosystem": "go"
},
{
"name": "github.com/openpeedeep/depguard/v2",
"direct": false,
"version": "v2.2.1",
"ecosystem": "go"
},
{
"name": "github.com/pelletier/go-toml/v2",
"direct": false,
"version": "v2.3.1",
"ecosystem": "go"
},
{
"name": "github.com/pmezard/go-difflib",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/prometheus/client_golang",
"direct": false,
"version": "v1.12.1",
"ecosystem": "go"
},
{
"name": "github.com/prometheus/client_model",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/prometheus/common",
"direct": false,
"version": "v0.32.1",
"ecosystem": "go"
},
{
"name": "github.com/prometheus/procfs",
"direct": false,
"version": "v0.7.3",
"ecosystem": "go"
},
{
"name": "github.com/quasilyte/go-ruleguard",
"direct": false,
"version": "v0.4.5",
"ecosystem": "go"
},
{
"name": "github.com/quasilyte/go-ruleguard/dsl",
"direct": false,
"version": "v0.3.23",
"ecosystem": "go"
},
{
"name": "github.com/quasilyte/gogrep",
"direct": false,
"version": "v0.5.0",
"ecosystem": "go"
},
{
"name": "github.com/quasilyte/regex/syntax",
"direct": false,
"version": "v0.0.0-20210819130434-b3f0c404a727",
"ecosystem": "go"
},
{
"name": "github.com/quasilyte/stdinfo",
"direct": false,
"version": "v0.0.0-20220114132959-f7386bf02567",
"ecosystem": "go"
},
{
"name": "github.com/raeperd/recvcheck",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/rivo/uniseg",
"direct": false,
"version": "v0.4.7",
"ecosystem": "go"
},
{
"name": "github.com/rogpeppe/go-internal",
"direct": false,
"version": "v1.14.1",
"ecosystem": "go"
},
{
"name": "github.com/ryancurrah/gomodguard",
"direct": false,
"version": "v1.4.1",
"ecosystem": "go"
},
{
"name": "github.com/ryancurrah/gomodguard/v2",
"direct": false,
"version": "v2.1.3",
"ecosystem": "go"
},
{
"name": "github.com/ryanrolds/sqlclosecheck",
"direct": false,
"version": "v0.6.0",
"ecosystem": "go"
},
{
"name": "github.com/sagikazarmark/locafero",
"direct": false,
"version": "v0.12.0",
"ecosystem": "go"
},
{
"name": "github.com/sahilm/fuzzy",
"direct": false,
"version": "v0.1.3",
"ecosystem": "go"
},
{
"name": "github.com/sanposhiho/wastedassign/v2",
"direct": false,
"version": "v2.1.0",
"ecosystem": "go"
},
{
"name": "github.com/santhosh-tekuri/jsonschema/v6",
"direct": false,
"version": "v6.0.2",
"ecosystem": "go"
},
{
"name": "github.com/sashamelentyev/interfacebloat",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/sashamelentyev/usestdlibvars",
"direct": false,
"version": "v1.29.0",
"ecosystem": "go"
},
{
"name": "github.com/securego/gosec/v2",
"direct": false,
"version": "v2.26.1",
"ecosystem": "go"
},
{
"name": "github.com/sirupsen/logrus",
"direct": false,
"version": "v1.9.4",
"ecosystem": "go"
},
{
"name": "github.com/sivchari/containedctx",
"direct": false,
"version": "v1.0.3",
"ecosystem": "go"
},
{
"name": "github.com/sonatard/noctx",
"direct": false,
"version": "v0.5.1",
"ecosystem": "go"
},
{
"name": "github.com/sourcegraph/go-diff",
"direct": false,
"version": "v0.8.0",
"ecosystem": "go"
},
{
"name": "github.com/spf13/afero",
"direct": false,
"version": "v1.15.0",
"ecosystem": "go"
},
{
"name": "github.com/spf13/cast",
"direct": false,
"version": "v1.10.0",
"ecosystem": "go"
},
{
"name": "github.com/spf13/pflag",
"direct": false,
"version": "v1.0.10",
"ecosystem": "go"
},
{
"name": "github.com/ssgreg/nlreturn/v2",
"direct": false,
"version": "v2.2.1",
"ecosystem": "go"
},
{
"name": "github.com/stbenjam/no-sprintf-host-port",
"direct": false,
"version": "v0.3.1",
"ecosystem": "go"
},
{
"name": "github.com/stretchr/objx",
"direct": false,
"version": "v0.5.2",
"ecosystem": "go"
},
{
"name": "github.com/stretchr/testify",
"direct": false,
"version": "v1.11.1",
"ecosystem": "go"
},
{
"name": "github.com/subosito/gotenv",
"direct": false,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/tetafro/godot",
"direct": false,
"version": "v1.5.6",
"ecosystem": "go"
},
{
"name": "github.com/timakin/bodyclose",
"direct": false,
"version": "v0.0.0-20260129054331-73d1f95b84b4",
"ecosystem": "go"
},
{
"name": "github.com/timonwong/loggercheck",
"direct": false,
"version": "v0.11.0",
"ecosystem": "go"
},
{
"name": "github.com/tomarrell/wrapcheck/v2",
"direct": false,
"version": "v2.12.0",
"ecosystem": "go"
},
{
"name": "github.com/tommy-muehle/go-mnd/v2",
"direct": false,
"version": "v2.5.1",
"ecosystem": "go"
},
{
"name": "github.com/ultraware/funlen",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/ultraware/whitespace",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/uudashr/gocognit",
"direct": false,
"version": "v1.2.1",
"ecosystem": "go"
},
{
"name": "github.com/uudashr/iface",
"direct": false,
"version": "v1.4.2",
"ecosystem": "go"
},
{
"name": "github.com/xen0n/gosmopolitan",
"direct": false,
"version": "v1.3.0",
"ecosystem": "go"
},
{
"name": "github.com/xo/terminfo",
"direct": false,
"version": "v0.0.0-20220910002029-abceb7e1c41e",
"ecosystem": "go"
},
{
"name": "github.com/yagipy/maintidx",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/yeya24/promlinter",
"direct": false,
"version": "v0.3.0",
"ecosystem": "go"
},
{
"name": "github.com/ykadowak/zerologlint",
"direct": false,
"version": "v0.1.5",
"ecosystem": "go"
},
{
"name": "gitlab.com/bosi/decorder",
"direct": false,
"version": "v0.4.2",
"ecosystem": "go"
},
{
"name": "go-simpler.org/musttag",
"direct": false,
"version": "v0.14.0",
"ecosystem": "go"
},
{
"name": "go-simpler.org/sloglint",
"direct": false,
"version": "v0.12.0",
"ecosystem": "go"
},
{
"name": "go.augendre.info/arangolint",
"direct": false,
"version": "v0.4.0",
"ecosystem": "go"
},
{
"name": "go.augendre.info/fatcontext",
"direct": false,
"version": "v0.9.0",
"ecosystem": "go"
},
{
"name": "go.uber.org/multierr",
"direct": false,
"version": "v1.11.0",
"ecosystem": "go"
},
{
"name": "go.yaml.in/yaml/v3",
"direct": false,
"version": "v3.0.4",
"ecosystem": "go"
},
{
"name": "golang.org/x/exp/typeparams",
"direct": false,
"version": "v0.0.0-20260209203927-2842357ff358",
"ecosystem": "go"
},
{
"name": "golang.org/x/mod",
"direct": false,
"version": "v0.35.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/sync",
"direct": false,
"version": "v0.21.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/sys",
"direct": false,
"version": "v0.46.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/telemetry",
"direct": false,
"version": "v0.0.0-20260409153401-be6f6cb8b1fa",
"ecosystem": "go"
},
{
"name": "golang.org/x/text",
"direct": false,
"version": "v0.36.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/tools",
"direct": false,
"version": "v0.44.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/vuln",
"direct": false,
"version": "v1.1.4",
"ecosystem": "go"
},
{
"name": "google.golang.org/protobuf",
"direct": false,
"version": "v1.36.10",
"ecosystem": "go"
},
{
"name": "gopkg.in/yaml.v3",
"direct": false,
"version": "v3.0.1",
"ecosystem": "go"
},
{
"name": "honnef.co/go/tools",
"direct": false,
"version": "v0.7.0",
"ecosystem": "go"
},
{
"name": "mvdan.cc/gofumpt",
"direct": false,
"version": "v0.9.2",
"ecosystem": "go"
},
{
"name": "mvdan.cc/unparam",
"direct": false,
"version": "v0.0.0-20251027182757-5beb8c8f8f15",
"ecosystem": "go"
}
],
"collected": true,
"truncated": false,
"total_count": 218,
"direct_count": 7,
"indirect_count": 211
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 59,
"open_issues": 0,
"closed_ratio": 1,
"closed_issues": 2,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 2,
"top_contributors": [
{
"type": "User",
"login": "kanywst",
"commits": 172,
"avatar_url": "https://avatars.githubusercontent.com/u/45947799?v=4"
},
{
"type": "User",
"login": "goreleaserbot",
"commits": 8,
"avatar_url": "https://avatars.githubusercontent.com/u/29843943?v=4"
}
],
"contributors_sampled": 2,
"top_contributor_share": 0.956
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"demo.yml",
"release.yml",
"test.yml"
],
"has_docs_dir": false,
"linter_configs": [
".golangci.yml"
],
"has_editorconfig": false,
"has_linter_config": true,
"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": 3,
"reason": "branch protection is not maximal on development and all release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/10 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 6,
"reason": "project has 2 contributing companies or organizations -- score normalized to 6",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 10,
"reason": "update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 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": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 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": 8,
"reason": "5 out of the last 5 releases have a total of 5 signed artifacts.",
"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": 9,
"reason": "1 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "67d8e74c286e641a6feac25d37fd3f81f7eba167",
"ran_at": "2026-07-22T02:37:54Z",
"aggregate_score": 5.6,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": true
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-20T02:00:31Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2026-07-20T01:57:42Z",
"ci_last_conclusion": null,
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/kanywst/y509",
"host": "github.com",
"name": "y509",
"owner": "kanywst"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 62,
"inputs": {
"security": 65,
"vitality": 82,
"community": 24,
"governance": 60,
"engineering": 74
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 82,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 72,
"inputs": {
"commits_last_year": 197,
"human_commit_share": 0.82,
"days_since_last_push": 2,
"active_weeks_last_year": 12
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 2 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 2
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "12/52 weeks with commits",
"points": 8.3,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 12
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "197 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 197
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 98,
"inputs": {
"releases_count": 18,
"latest_release_tag": "v1.0.0",
"releases_from_tags": false,
"days_since_latest_release": 4,
"mean_days_between_releases": 12.4
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "18 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 18
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 4 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 4
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~12.4 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 12.4
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
"points": 8,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"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": 4,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "last human commit 4 days ago",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_maintained",
"params": {
"days": 4
}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 24,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 1,
"stars": 2,
"watchers": 1,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "below_threshold"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "2 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 2
}
}
],
"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": "1 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 1
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"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": "recognized license (Apache-2.0)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "Apache-2.0"
}
}
],
"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": 60,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 19,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 2,
"top_contributor_share": 0.956
},
"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 96% of commits",
"points": 1,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 96
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "2 contributors",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 2
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 2 contributing companies or organizations -- score normalized to 6",
"points": 6,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "excellent",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"merged_prs": 59,
"open_issues": 0,
"closed_issues": 2,
"issue_closed_ratio": 1,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "100% of issues closed",
"points": 46.8,
"status": "met",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 100
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "59/59 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 59,
"decided": 59
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/10 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 51,
"inputs": {
"followers": 8,
"owner_type": "User",
"is_verified": null,
"owner_login": "kanywst",
"public_repos": 42,
"account_age_days": 2773
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "8 followers of kanywst",
"points": 6.9,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 8,
"login": "kanywst"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "42 public repos, account ~7 yr old",
"points": 23.9,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 42
}
},
{
"code": "account_age_years",
"params": {
"years": 7
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/kanywst/y509"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 4
},
"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 4 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 4
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "18 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 18
}
}
],
"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": "good",
"name": "Engineering Quality",
"value": 74,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 84,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "3 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 3
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": ".golangci.yml",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"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": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"topics": [
"bubbletea",
"certificates",
"charm",
"cli",
"developer-tools",
"golang",
"pki",
"ssl",
"terminal",
"tls",
"tui",
"x509"
],
"has_wiki": true,
"homepage": null,
"has_readme": true,
"has_docs_dir": false,
"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": 0,
"status": "missed",
"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": "12 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 12
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "moderate",
"name": "Security",
"value": 65,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"name": "Security posture",
"note": null,
"notes": [],
"value": 56,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 18,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 0,
"scorecard_aggregate": 5.6
},
"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 is not maximal on development and all release branches",
"points": 2.2,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/10 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 2 contributing companies or organizations -- score normalized to 6",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "update tool detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
"points": 6,
"status": "partial",
"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": "1 existing vulnerabilities detected",
"points": 6.8,
"status": "partial",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "dependency_advisories",
"band": "excellent",
"name": "Dependency advisories",
"note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 218 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",
"no_advisories_left_outstanding"
]
}
},
{
"code": "weights_renormalized",
"params": {}
},
{
"code": "advisories_scope_repository",
"params": {
"assessed": 218
}
},
{
"code": "advisories_repo_graph_caveat",
"params": {}
},
{
"code": "advisories_reachability",
"params": {}
}
],
"value": 100,
"inputs": {
"source": "osv",
"advisories": 1,
"affected_packages": 1,
"assessed_packages": 218,
"unassessed_packages": 0,
"affected_by_severity": "unknown 1",
"direct_affected_packages": 0
},
"components": [
{
"key": "direct_dependencies_free_of_known_advisories",
"name": "Direct dependencies free of known advisories",
"detail": "no direct dependency carries a known advisory",
"points": 35,
"status": "met",
"details": [
{
"code": "no_direct_advisories",
"params": {}
}
],
"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 carries a publication date",
"points": 0,
"status": "excluded",
"details": [
{
"code": "advisories_no_publication_date",
"params": {}
}
],
"max_points": 40
}
]
},
{
"key": "malicious_dependencies",
"band": "excellent",
"name": "Malicious dependencies",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"source": "osv",
"meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
"packages": [],
"red_flag": false,
"assessed_packages": 218,
"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": "excellent",
"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"
],
"review_only_matches": 0,
"assessed_self_published_locations": 1
},
"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": "moderate",
"name": "AI Readiness",
"value": 69,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"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": "82 of 82 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 82,
"sampled": 82
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 80,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": true,
"typecheck_configs": [],
"agent_commit_share": 0,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0.03
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": ".golangci.yml",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"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": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "3 of the last 100 commits are automated dependency updates",
"points": 8,
"status": "met",
"details": [
{
"code": "dependency_bot_commits",
"params": {
"count": 3,
"sampled": 100
}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 25072,
"source_files_sampled": 36,
"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/36 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 36,
"oversized": 0
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [],
"report_type": "repository",
"generated_at": "2026-07-22T02:38:10.056585Z",
"schema_version": "0.26.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/k/kanywst/y509.svg",
"full_name": "kanywst/y509",
"license_state": "standard",
"license_spdx": "Apache-2.0"
}