Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-28 03:22 UTC

infodancer / oidclient

OIDC relying party library for Go web applications

GoApache-2.0★ 0 estrellas⑂ 0 forksdesde mar 2026Ver en GitHub ↗

infodancer/oidclient tiene un índice de salud de 58 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Engineering Quality (80/100) y la más baja, Community & Adoption (24/100). Se actualizó por última vez hace 6 días. Una sola persona concentra la mayor parte del trabajo reciente.

58
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

58
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

infodancerOrganización
0 seguidores11 repositorios públicosdesde ene 2026

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
Gogithub.com/infodancer/oidclientv0.8.0-9hace 6 días

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

77Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 6 días
7.6/36Cadencia de commits — 11/52 semanas con commits
15.2/18Volumen de commits — 48 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year48
human_commit_share0,938
days_since_last_push6
active_weeks_last_year11
Cómo se puntúa
16.2/27Publica versiones — 9 etiquetas de versión (sin releases de GitHub)
36/36Recencia de las versiones — última versión hace 6 días
27/27Cadencia de publicación — una versión cada ~6,2 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count9
latest_release_tagv0.8.0
releases_from_tags
days_since_latest_release6
mean_days_between_releases6,2
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

24Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

50Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
31.2/46.8Resolución de issues — 67% de issues cerradas
36.2/38.3Aceptación de PR — 18/19 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs18
open_issues2
closed_issues4
issue_closed_ratio0,667
closed_unmerged_prs1
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
0/25Alcance del propietario — 0 seguidores de infodancer
8.9/25Trayectoria — 11 repos públicos, cuenta de ~0 años
Datos de entrada utilizados
followers0
owner_typeOrganization
is_verified
owner_logininfodancer
public_repos11
account_age_days190
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en go
35/35Recencia de publicación — última publicación hace 6 días
20/20Historial de versiones — 9 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/infodancer/oidclient
ecosystemsgo
any_deprecatedno
min_days_since_publish6

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

80Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — .golangci.yml
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 17 out of 17 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

55Moderado · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 17 out of 17 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/16 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — sin datos
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5,5
Excluidos de la puntuación (sin datos o no aplicable): packaging, signed_releases. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

72Bueno · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 44 de 45 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,978
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
12.6/18Arranque con un solo comando — go.mod (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
11/11Configuración de lint / formato — .golangci.yml
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 32 de los últimos 48 commits con autoría o crédito de agente
8/8Mantenimiento automatizado — 3 de los últimos 48 commits son actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0,667
toolchain_manifestsgo.mod
dependency_bot_commit_share0,062
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/20 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes27.503
source_files_sampled20
oversized_source_files0

Datos clave

0estrellas de GitHub
1contribuidores
48commits en los últimos 12 meses
6días desde el último push
9versiones publicadas
1factor bus
2issues abiertas
Goecosistemas de paquetes

Advertencias de recopilación de datos

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Más detalle

OpenSSF Scorecard 5.5 / 10
5.5agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-28 03:21 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests17 out of 17 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/16 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Dependencias directas 4
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/coreos/go-oidc/v3v3.20.0go.mod
Gogithub.com/golang-jwt/jwt/v5v5.3.1go.mod
Gogolang.org/x/oauth2v0.36.0go.mod
Gogolang.org/x/syncv0.22.0go.mod
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 133,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 147755
      },
      "pushed_at": "2026-07-21T10:35:42Z",
      "created_at": "2026-03-13T22:06:56Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T10:36:50Z",
      "description": "OIDC relying party library for Go web applications",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "master",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "http://infodancer.org/",
      "name": null,
      "type": "Organization",
      "login": "infodancer",
      "company": null,
      "location": "United States of America",
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/255623871?v=4",
      "created_at": "2026-01-18T03:50:57Z",
      "is_verified": null,
      "public_repos": 11,
      "account_age_days": 190
    },
    "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": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-07-21T07:24:06Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-18T07:07:35Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-06-17T02:14:06Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-06-16T04:46:25Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-06-15T03:32:44Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-06-12T20:09:58Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-06-11T22:49:07Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-06-11T21:36:03Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-06-02T02:30:59Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2d2f0b7b2f633494cd3570ef8897673efd028be0",
          "body": "… (#24)\n\nBumps the go-deps group with 2 updates in the / directory: [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) and [golang.org/x/sync](https://github.com/golang/sync).\n\n\nUpdates `github.com/coreos/go-oidc/v3` from 3.19.0 to 3.20.0\n- [Release notes](https://github.com/coreos/go\n[…]\npe: version-update:semver-minor\n  dependency-group: go-deps\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): Bump the go-deps group across 1 directory with 2 updates…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-21T10:35:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c7a644ca324a96bed00378b19246bba21807ef4b",
          "body": "Three sites (herald, osg, sf) each hand-rolled an identical open-redirect\nguard and an identical fail-open session-key constructor, kept in sync\nby convention rather than by the compiler. Both belong here: LocalPath\nis exactly CallbackOptions.SanitizeRedirect's signature, and\nNewKeyringFromBase64 is the base64/fail-open policy layer that was\nmissing next to the bare Keyring primitive. envVarName is a parameter\nsince each site's config source has a different name.",
          "is_bot": false,
          "headline": "Add LocalPath and session.NewKeyringFromBase64",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-07-21T07:24:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36e40460e05031e07666db2d0dc53c5e956d66ed",
          "body": "Shared baseline across the go-ci.yml@v0 fleet. Three //nolint:errcheck\ncomments in oidclient_test.go were already redundant -- the exclusions\nrule for _test.go already turns errcheck off there -- so nolintlint's\nunused-directive check caught dead suppressions and they're removed.",
          "is_bot": false,
          "headline": "lint: enable dupl and nolintlint",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-07-21T05:20:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "866429845628c941bc1e1b184a82d7525a53d452",
          "body": "* rpuser: add the audited claims -> local-user provisioning path\n\nExtract the post-login user-sync policy every RP site re-implements into\nan oidclient subpackage, per the revised spec on issue #10: Identity\nmirrors authz.Identity (no roles -- authorization is never claim-driven),\nusers key strictly\n[…]\nak (GO-2026-5856),\nreachable from this module's TLS use and fixed in 1.25.12.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "rpuser: audited claims -> local-user provisioning path (#25)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-07-18T07:07:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8f7e0206816c57e7514804a4d4257fb6bf57f64b",
          "body": "…#23)\n\nBumps the go-deps group with 1 update: [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc).\n\n\nUpdates `github.com/coreos/go-oidc/v3` from 3.18.0 to 3.19.0\n- [Release notes](https://github.com/coreos/go-oidc/releases)\n- [Commits](https://github.com/coreos/go-oidc/compare/v3.18.0.\n[…]\npe: version-update:semver-minor\n  dependency-group: go-deps\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): Bump github.com/coreos/go-oidc/v3 in the go-deps group (…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-05T12:56:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e2fd5eb8d141d3b8a7e4cc36c0b88125c2fc977a",
          "body": "feat: oidclient/session subpackage (server-side sessions + at-rest encryption)",
          "is_bot": false,
          "headline": "Merge pull request #22 from infodancer/session-package",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-17T02:14:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8abc937c378bc2efbdc0eaed1ea18da2960cc689",
          "body": "Wraps the Exchange/Refresh/Validate primitives into a full session lifecycle so\nrelying parties stop hand-rolling it (herald and sf each had a copy; osg lacked\none and hard-logged-out at the access-token TTL). The browser holds an opaque\nsession id; the access and rotating refresh tokens live server\n[…]\nesh-failure-is-a-real-error,\nCAS-loss-adopts-winner, keyring round-trip/AAD/rotation/tamper. Design doc in\ndocs/session-design.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add oidclient/session subpackage for server-side OIDC sessions",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-17T02:12:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5e7667e7f243febe842fe15b282c011a1d3f46d3",
          "body": "Design: oidclient/session subpackage (server-side sessions + token-at-rest encryption)",
          "is_bot": false,
          "headline": "Merge pull request #21 from infodancer/session-package-design",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-17T01:57:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5930d16fbb79bb139b6bf5d966bac1a3d72c68e5",
          "body": "Keyring is an explicit type (Add/SetActive); both token columns are encrypted;\nAbsoluteTTL defaults to 30d, overridable, since no data-handling requirement\ndrives a short idle timeout.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: resolve session-design open questions",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-17T01:49:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c958f4b5cfb542f384c91c7f9be1dd5929352cd7",
          "body": "Consolidates the server-side OIDC session lifecycle (start/authenticate/\nrenew/destroy/sweep) that herald and sf each hand-roll, and that osg still\nlacks -- plus token-at-rest encryption. Storage-agnostic via a Store interface\nthe app implements over its own DB; the package persists nothing. Subpack\n[…]\ntation CAS moves\nfrom the refresh-token value to a version counter, since encrypted token columns\nhave no stable value to compare.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: design proposal for an oidclient/session subpackage",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-17T01:44:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e1917183009d96f7211e7943044b30934141841b",
          "body": "feat: use discovered end_session_endpoint for LogoutURL",
          "is_bot": false,
          "headline": "Merge pull request #20 from infodancer/feature/end-session-logout",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-16T04:46:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c81a45706fcf6090199d630b25d72b0005ed3c72",
          "body": "LogoutURL() fabricated WebauthURL + \"/logout\", a guessed path that is not\nissuer/tenant-scoped and 404s on a provider that does not happen to serve it\n(webauth being exactly such a provider). Capture the end_session_endpoint from\nOIDC discovery and return that fully qualified, RP-initiated-logout UR\n[…]\nauth growing an end_session_endpoint; together they make\nRP-initiated logout actually reach the IdP and terminate the SSO session.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: use the discovered end_session_endpoint for LogoutURL",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-16T04:18:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "39d0ed7237d0a2ec8d6d453da3e2ffa8714ce4ec",
          "body": "ci: track shared go-ci at @v0",
          "is_bot": false,
          "headline": "Merge pull request #19 from infodancer/ci/track-v0",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T06:00:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "48d13f956134859a385241dffcbb5091ab6bd72b",
          "body": "Pin the shared Go CI to the moving major tag @v0 instead of an exact\npatch, so future infodancer/workflows releases are picked up\nautomatically. v0 currently resolves to v0.2.2 (self-hosted default).",
          "is_bot": false,
          "headline": "ci: track shared go-ci at @v0 (auto-version)",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T05:54:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0649f5e0611b938dd093ccfbdf3a5bac5cd008cd",
          "body": "Add refresh-token renewal and offline_access support",
          "is_bot": false,
          "headline": "Merge pull request #18 from infodancer/feature/16",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T03:32:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "61ae804bea236cf9e799eb929cca1f2e2c2a1257",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: document session renewal in README",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T03:09:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4158d5be80a94115abcb48aef7f771ee36ca8f44",
          "body": "Sessions could only be ended, never renewed: ExchangeCode obtained a\ntoken once at login and the sole recovery from an expired JWT was a full\ninteractive redirect. Add first-class renewal:\n\n- Config.OfflineAccess opts into the offline_access scope so the IdP\n  issues a refresh token. Off by default \n[…]\n response without an id_token falls\nback to validating the access token.\n\nCloses https://github.com/infodancer/oidclient/issues/16\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add refresh-token renewal and offline_access support",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T03:09:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b32969d832a541016f7e122996d13db30b089b85",
          "body": "Replace the in-repo test/vet/fmt/lint/govulncheck jobs with a thin caller of\nthe shared reusable workflow, so the definition (and its action pins) live once.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: use shared infodancer/workflows go-ci (#17)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-15T01:13:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1b6b2143e81fc7443f2c858e9807714a06a90de8",
          "body": "Add NewLazy: boot without the provider, retry discovery in background",
          "is_bot": false,
          "headline": "Merge pull request #15 from infodancer/feature/14",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-12T20:09:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b99548a880304e9d6c9c1f17ff621fb40c4b19a1",
          "body": "New() performs discovery and dynamic registration synchronously, so RPs\nthat treat its error as fatal crash-loop whenever the IdP is unreachable\nor misconfigured at startup -- the 2026-06-12 osg/sf outage mode. NewLazy\nreturns immediately and a background goroutine retries discovery with\nexponential\n[…]\nzeURL returns \"\", and\nCallbackHandler responds 503. New() keeps its eager fail-fast contract.\n\nhttps://github.com/infodancer/oidclient/issues/14\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add NewLazy: boot without the provider, retry discovery in background",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-12T20:08:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dbabfb6b3d7781fe0fc2b71fbbd8d8c4402228c9",
          "body": "…1a7eda9ac\n\nbuild(deps): Bump the go-deps group across 1 directory with 2 updates",
          "is_bot": false,
          "headline": "Merge pull request #5 from infodancer/dependabot/go_modules/go-deps-1…",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-11T22:49:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1a1147665404316b548429b952a811f278bd581",
          "body": "Add CallbackHandler: shared OIDC redirect-URI endpoint",
          "is_bot": false,
          "headline": "Merge pull request #13 from infodancer/feat/callback-handler",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-11T22:48:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de8f2b49f1fedec93a250dc57f40753e6012b37a",
          "body": "herald, sf, and osg each carry a near-identical handleCallback\n(upstream error check, state validation, PKCE exchange, session\ncookie, redirect). CallbackHandler centralizes that skeleton with\nhooks for the app-specific parts: OnAuthenticated for user\nprovisioning and a new-account default destinati\n[…]\ntricting the return path, and Finish for popup-style\ncompletions. Centralizing also gives the state-mismatch retry (#11)\na single place to land.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add CallbackHandler: shared OIDC redirect-URI endpoint",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-11T22:40:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "88d4660334e73e29eee2eb1696603165d4fb5a58",
          "body": "* Make OIDC flow cookies session cookies\n\nThe 5-minute MaxAge expired out from under any login form left open\nlonger than that at the IdP, so the callback arrived after the state\ncookie was gone and failed with a state mismatch. The state and\nverifier nonces derive no security from a fixed expiry --\n[…]\n new\nvalues when none is in progress, making concurrent redirects\nidempotent.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix state mismatch from expiring and racing flow cookies (#12)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-11T21:36:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1952ac51f18a387304e585226835b4537f1c257d",
          "body": "Bumps the go-deps group with 2 updates in the / directory: [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) and [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt).\n\n\nUpdates `github.com/coreos/go-oidc/v3` from 3.17.0 to 3.18.0\n- [Release notes](https://github.com/core\n[…]\n/jwt/v5\n  dependency-version: 5.3.1\n  dependency-type: direct:production\n  update-type: version-update:semver-minor\n  dependency-group: go-deps\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "build(deps): Bump the go-deps group across 1 directory with 2 updates",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-05T01:13:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61f051fdcb4864b5704df1282184eed501f284ad",
          "body": "CI hosts run several self-hosted runners; golangci-lint's default lock\ntrips when two lint jobs overlap on one host. Per-runner-home caches make\nparallel runs safe.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: allow parallel golangci-lint runners (#9)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-04T09:24:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8d09e85786886873fae6c10ef221a95856349e60",
          "body": "Part of a fleet-wide bump to Go 1.25.11, which patches disclosed crypto/x509\n(and related net/textproto, mime) stdlib advisories that govulncheck flags on\n1.25.x < .11.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "build: bump to go 1.25.11 for GO-2026-5037 crypto/x509 stdlib fix (#8)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-04T08:59:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "426626bf71d80b673ee80347ef455c6f28537d29",
          "body": "feat: static confidential clients (ClientID + ClientSecret)",
          "is_bot": false,
          "headline": "Merge pull request #7 from infodancer/feature/confidential-client",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-02T02:30:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b204f9490674813d5d8877c7af0cd2f640afa84",
          "body": "Add Config.ClientSecret for providers that issue a secret and don't support\nRFC 7591 dynamic registration — Google's \"Web application\" credential being the\nmotivating case. When set with a pre-registered ClientID (and no\nregistration_endpoint), the secret seeds the oauth2 config and is sent in the\nt\n[…]\nnfidential provider that records the presented client_secret asserts\nit is sent on exchange; a public client asserts none is sent.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: support static confidential clients (ClientID + ClientSecret)",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-06-02T02:20:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4fa4b1cfef7c75842fbaca688684984c73137eb6",
          "body": "Clears the JWE decryption panic advisory GO-2026-4945 (go-jose v4.1.3, fixed in\nv4.1.4) flagged by govulncheck.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "security: bump go-jose/v4 to v4.1.4 (GO-2026-4945) (#6)",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-29T21:12:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e7def6e0ae8364a167b1529c17bcf0be6c575aed",
          "body": "Make auto-registration RFC 7591 conformant",
          "is_bot": false,
          "headline": "Merge pull request #3 from infodancer/feature/2",
          "author_name": "Matthew",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-19T09:24:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90c556cc6d99ac26b0391216f2baaeec8d4c3fca",
          "body": "Refs: https://github.com/infodancer/oidclient/issues/2\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Document RFC 7591 dynamic client registration in README",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-19T09:21:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2e0fad3aafa909793dc09f0f7dc2de712e6ab29c",
          "body": "When the provider's discovery document advertises a registration_endpoint,\nNew() now performs RFC 7591 §3.1 dynamic client registration during startup\nand uses the server-assigned client_id (and client_secret, if any) for all\nsubsequent OAuth operations and ID-token audience validation.\n\nThe registr\n[…]\n fallback used when the provider does not advertise\nregistration_endpoint.\n\nRefs: https://github.com/infodancer/oidclient/issues/2\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add RFC 7591 dynamic client registration",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-19T09:21:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5db82bf4660d15eaab38390cdac02fc087efd666",
          "body": "CI / godoc / report card / license badges in the standard order, and\nthe License section now points at SECURITY.md alongside the LICENSE\nfile.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add badges and update license reference to Apache-2.0",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:31:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d17757631f906639ebb7193f9d6d6ad230f363a3",
          "body": "Mirrors the setup used in contact and newsletter: test (race)/vet/fmt/\nlint/govulncheck jobs, weekly dependabot for gomod and github-actions\ngrouped together, and an auto-merge workflow that squashes dependabot\nPRs once all checks pass.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: add CI, dependabot, and auto-merge workflows",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:31:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6d948346abcda7ec28fb95467ca9ab01fe2698d3",
          "body": "Standard GitHub private-vulnerability-reporting flow with email\nfallback. Scope spelled out so reporters know which paths I treat as\nin-bounds (token validation, PKCE, cookie defaults, dynamic client\nregistration) versus deferred to upstream go-oidc/go-jose.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add SECURITY.md",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:31:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f37047e896d511390b6c200e1d57bec41db25384",
          "body": "The dicta-derived config excludes errcheck in _test.go and on common\ndefer-Close patterns; that handles five of six golangci-lint v2 findings.\nThe remaining QF1003 in autoRegister is a real readability nit — the\nStatusCreated/StatusOK/StatusConflict dispatch reads cleaner as a switch.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "lint: add .golangci.yml and refactor if-chain to tagged switch",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:31:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6459daca509fb4f3cd6d72b6e19da3e41c2ad353",
          "body": "Matches dicta, contact, newsletter, and the other polished repos.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump go to 1.25.10",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:31:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ad74370baf0dff0a5e56ebe435095b9d98f7ecbc",
          "body": "Swapping to Apache-2.0 to match the standard adopted across the other\nsmall Go projects in my portfolio. Apache adds an explicit patent\ngrant and NOTICE-file handling, which is the right default for code\nthat exists to be consumed by other projects.\n\nThe previous MIT-licensed versions remain MIT under their tags in git\nhistory — this only affects future commits.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: relicense from MIT to Apache-2.0",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-05-17T04:30:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e22e14ec6f090aeaf418a50f4001de7b2ec349b7",
          "body": "After OIDC discovery, if the provider's discovery document includes\na registration_endpoint, the client registers itself with its\nclient_id and callback URL. Failures are logged but not fatal —\nthe client may already exist. This makes OIDC client registration\ndurable across database resets.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Auto-register with IdP via RFC 7591 on startup",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-22T03:29:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2e0962648dc49f4c98aff363f0884580ff5d916e",
          "body": "Webauth includes email_verified in both access and ID tokens.\nRelying parties need this to gate actions on verified email.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add EmailVerified field to Claims",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-22T03:19:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9be08a7f8fb78e17af8c3bd045a48baa5312b4ac",
          "body": "Allows relying parties to redirect users to the IdP's registration\npage with the same OIDC parameters used for login, so the callback\nflow is identical after signup.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add RegisterURL for IdP registration flow with PKCE",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-21T19:05:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b29019bedfa36f650c28455b7f6b293a503a9ded",
          "body": "Set AuthStyle to AuthStyleInParams so the oauth2 library sends client_id\nin the form body directly instead of probing with Basic auth first. The\nprobe consumes the auth code on providers that delete before validating\nclient_id, causing \"invalid or expired authorization code\" on the retry.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix oauth2 auth style probing consuming single-use auth codes",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-14T20:16:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ae7c7027172acabd05ad0682e910d084a48dbc14",
          "body": "Make it clear that oidclient contains no custom cryptography and is a\nconvenience layer over go-oidc and x/oauth2.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Update README to clarify thin-wrapper nature",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-14T13:32:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3c1acf028cfe58073dff2ff2bd9587cf739be000",
          "body": "Replace manual OIDC discovery, JWKS fetching, RSA key parsing, and JWT\nvalidation with battle-tested libraries:\n\n- coreos/go-oidc/v3 for discovery, JWKS caching, and token verification\n- golang.org/x/oauth2 for authorization code flow and PKCE\n\nAPI changes:\n- New() now takes a context (for discovery\n[…]\nown typed errors)\n\nDrops golang-jwt/jwt/v5 as a direct dependency (still used in tests to\nissue tokens against the fake provider).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Refactor to wrap go-oidc + x/oauth2 instead of hand-rolling",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-13T22:38:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ad92242384a009c384fd2714dfc0c977d5e9b545",
          "body": "- Add MIT LICENSE file\n- Add experimental/internal-use notice to README directing external\n  users to coreos/go-oidc instead\n- Add sentinel errors (ErrNoCookie, ErrTokenInvalid, ErrTokenExpired,\n  ErrIssuerMismatch, ErrMissingSub, ErrKeyNotFound) so consumers can\n  distinguish failure modes programm\n[…]\nument ExchangeCode's intentional discard of id_token/refresh_token\n- Clean up tests: use strings.Contains, remove dead assignments\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add LICENSE, sentinel errors, and experimental disclaimer",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-13T22:23:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c505ad08682fd5e465cfb5448a1a462be4e07759",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add README with usage examples",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-13T22:14:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2c68d1a4a15d46501d4df79a494b00e5468b1496",
          "body": "Extracted from Herald's internal/auth package into a standalone module\nfor reuse across infodancer web applications (Herald, SF, etc.).\n\n- OIDC autodiscovery with JWKS caching and key rotation\n- RS256 JWT validation with issuer checking\n- PKCE (S256) verifier/challenge generation\n- Authorization code flow: authorize URL construction and token exchange\n- Cookie helpers for OAuth flow state and JWT sessions\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Initial oidclient: shared OIDC relying party library",
          "author_name": "Matthew Hunter",
          "author_login": "matthewjhunter",
          "committed_at": "2026-03-13T22:05:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 9,
      "commits_last_year": 48,
      "latest_release_at": "2026-07-21T07:24:06Z",
      "latest_release_tag": "v0.8.0",
      "releases_from_tags": true,
      "days_since_last_push": 6,
      "active_weeks_last_year": 11,
      "days_since_latest_release": 6,
      "mean_days_between_releases": 6.2
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 62,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/infodancer/oidclient",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/infodancer/oidclient",
          "is_deprecated": false,
          "latest_version": "v0.8.0",
          "repository_url": "https://github.com/infodancer/oidclient",
          "versions_count": 9,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-21T07:24:06Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 6
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 2
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 27503,
      "source_files_sampled": 20,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/coreos/go-oidc/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.20.0"
        },
        {
          "name": "github.com/golang-jwt/jwt/v5",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v5.3.1"
        },
        {
          "name": "golang.org/x/oauth2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.36.0"
        },
        {
          "name": "golang.org/x/sync",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.22.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 18,
        "open_issues": 2,
        "closed_ratio": 0.667,
        "closed_issues": 4,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "matthewjhunter",
          "commits": 45,
          "avatar_url": "https://avatars.githubusercontent.com/u/56937361?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "dependabot-auto-merge.yml"
      ],
      "has_docs_dir": true,
      "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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "17 out of 17 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/16 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "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 0 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": null,
            "reason": "packaging workflow not 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": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2d2f0b7b2f633494cd3570ef8897673efd028be0",
        "ran_at": "2026-07-28T03:21:54Z",
        "aggregate_score": 5.5,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T01:14:02Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-21T10:35:41Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 4,
          "created_at": "2026-05-21T20:27:40Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 11,
          "created_at": "2026-06-11T21:27:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/infodancer/oidclient",
    "host": "github.com",
    "name": "oidclient",
    "owner": "infodancer"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 58,
      "inputs": {
        "security": 55,
        "vitality": 77,
        "community": 24,
        "governance": 50,
        "engineering": 80
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 77,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "commits_last_year": 48,
              "human_commit_share": 0.938,
              "days_since_last_push": 6,
              "active_weeks_last_year": 11
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "11/52 weeks with commits",
                "points": 7.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 11
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "48 commits in the last year",
                "points": 15.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 48
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 9,
              "latest_release_tag": "v0.8.0",
              "releases_from_tags": true,
              "days_since_latest_release": 6,
              "mean_days_between_releases": 6.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "9 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~6.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 6.2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "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": 50,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "merged_prs": 18,
              "open_issues": 2,
              "closed_issues": 4,
              "issue_closed_ratio": 0.667,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "67% of issues closed",
                "points": 31.2,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 67
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "18/19 decided PRs merged",
                "points": 36.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 18,
                      "decided": 19
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/16 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 39,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "infodancer",
              "public_repos": 11,
              "account_age_days": 190
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of infodancer",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "infodancer"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "11 public repos, account ~0 yr old",
                "points": 8.9,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 11
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/infodancer/oidclient"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 6
            },
            "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 6 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "9 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "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": 80,
        "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": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": ".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": "17 out of 17 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": 55,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 55,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.5
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "17 out of 17 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/16 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "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 0 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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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 detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "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": "good",
        "name": "AI Readiness",
        "value": 72,
        "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": 0.978,
              "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": "44 of 45 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 44,
                      "sampled": 45
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.667,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0.062
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "go.mod (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "go.mod"
                    }
                  }
                ],
                "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": "32 of the last 48 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 32,
                      "sampled": 48
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "3 of the last 48 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 3,
                      "sampled": 48
                    }
                  }
                ],
                "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": 27503,
              "source_files_sampled": 20,
              "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/20 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 20,
                      "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": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T03:22:08.250489Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/i/infodancer/oidclient.svg",
  "full_name": "infodancer/oidclient",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasGo.