Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-26 09:42 UTC

Swatto / promtotwilio

Send text messages for Prometheus alerts using Twilio

Go · ShellMIT★ 35 estrellas⑂ 18 forksdesde mar 2016Ver en GitHub ↗

Swatto/promtotwilio tiene un índice de salud de 59 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (76/100) y la más baja, Security (46/100). Se actualizó por última vez hace 2 días. Una sola persona concentra la mayor parte del trabajo reciente.

59
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.

59
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

Gael GillardCuenta personal
25 seguidores27 repositorios públicosdesde jul 2011McKinsey & Company

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
Gogithub.com/swatto/promtotwiliov1.10.2-12hace 18 días

Métricas por categoría

Vitalidad

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

76Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 2 días
5.5/36Cadencia de commits — 8/52 semanas con commits
17.6/18Volumen de commits — 91 commits en el último año
7/10OpenSSF Scorecard: Maintained — 9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
Datos de entrada utilizados
commits_last_year91
human_commit_share0,87
days_since_last_push2
active_weeks_last_year8
Cómo se puntúa
27/27Publica versiones — 13 versiones publicadas
36/36Recencia de las versiones — última versión hace 18 días
27/27Cadencia de publicación — una versión cada ~20 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count13
latest_release_tagv1.10.2
releases_from_tagsno
days_since_latest_release18
mean_days_between_releases20

Comunidad y Adopción

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

51Moderado · 18% del índice global
Cómo se puntúa
24.8/60Estrellas — 35 estrellas
10.3/25Forks — 18 forks
0/15Observadores — 2 observadores
Datos de entrada utilizados
forks18
stars35
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
18/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_contributing
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?

55Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0.2/22.5Distribución de commits — el principal contribuyente firma el 99% de los commits
2.7/13.5Amplitud de contribuyentes — 2 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled2
top_contributor_share0,991
Cómo se puntúa
46.8/46.8Resolución de issues — 100% de issues cerradas
22.4/38.3Aceptación de PR — 17/29 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/14 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs17
open_issues0
closed_issues5
issue_closed_ratio1
closed_unmerged_prs12
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
10.2/25Alcance del propietario — 25 seguidores de Swatto
22.5/25Trayectoria — 27 repos públicos, cuenta de ~15 años
Datos de entrada utilizados
followers25
owner_typeUser
is_verified
owner_loginSwatto
public_repos27
account_age_days5501
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en go
35/35Recencia de publicación — última publicación hace 18 días
20/20Historial de versiones — 12 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/swatto/promtotwilio
ecosystemsgo
any_deprecatedno
min_days_since_publish18

Calidad de Ingeniería

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

64Moderado · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 1 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
6.4/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfig
has_linter_configno
has_precommit_configno

Documentación

50Moderado
Cómo se puntúa
30/30README
0/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
10/10Topics — 5 topics
0/10Wiki
Datos de entrada utilizados
topicsprometheus, twilio, alert, prometheus-alert, alertmanager
has_wikino
homepage
has_readme
has_docs_dirno
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?

46En riesgo · 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 — 8 out of 8 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/14 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
5.2/7.5Maintained — 9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
5/5Packaging — packaging workflow detected
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
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate4,6

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.

69Moderado · 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 — 74 de 87 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,851
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
18/18Arranque con un solo comando — Makefile
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — Dockerfile
10/10Práctica demostrada con agentes — 10 de los últimos 100 commits con autoría o crédito de agente
8/8Mantenimiento automatizado — 13 de los últimos 100 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
lockfiles
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0,1
toolchain_manifestsgo.mod, test/mock-exporter/go.mod, test/mock-twilio/go.mod
dependency_bot_commit_share0,13
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/22 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes30.140
source_files_sampled22
oversized_source_files0

Datos clave

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

Advertencias de recopilación de datos

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

Más detalle

Historial de estrellas y forks 0 ★ / 18 ⇿
0Estrellas
18Forks
2Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

0481216201712016-032020-052024-06
Mayor 0Menor 1Parche 0

Cada punto abarca 8 días.

OpenSSF Scorecard 4.6 / 10
4.6agregado

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-26 09:42 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests8 out of 8 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/14 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
7Maintained9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Todas las dependencias 0

Conjunto completo de dependencias resueltas según el grafo de dependencias de GitHub: 0 paquetes directos y 0 indirectos (transitivos). El cierre transitivo es completo cuando el repositorio incluye un lockfile.

RegistroPaqueteVersiónRelación
Avisos de dependencias sin evaluar

El cotejo de avisos no pudo ejecutarse para este informe: No resolved dependencies to assess

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "prometheus",
        "twilio",
        "alert",
        "prometheus-alert",
        "alertmanager"
      ],
      "is_fork": false,
      "size_kb": 1217,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 112986,
        "Shell": 24505,
        "Makefile": 4174,
        "Dockerfile": 1606
      },
      "pushed_at": "2026-07-24T08:22:21Z",
      "created_at": "2016-03-21T10:41:02Z",
      "owner_type": "User",
      "updated_at": "2026-07-24T08:23:47Z",
      "description": "Send text messages for Prometheus alerts using Twilio",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go",
        "Shell"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Gael Gillard",
      "type": "User",
      "login": "Swatto",
      "company": "McKinsey & Company",
      "location": "Andenne, Belgium",
      "followers": 25,
      "avatar_url": "https://avatars.githubusercontent.com/u/892951?v=4",
      "created_at": "2011-07-04T07:39:30Z",
      "is_verified": null,
      "public_repos": 27,
      "account_age_days": 5501
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.10.2",
          "kind": "patch",
          "published_at": "2026-07-08T07:31:05Z"
        },
        {
          "tag": "v1.10.1",
          "kind": "patch",
          "published_at": "2026-02-18T16:16:18Z"
        },
        {
          "tag": "v1.10.0",
          "kind": "minor",
          "published_at": "2026-02-18T15:32:24Z"
        },
        {
          "tag": "v1.9.0",
          "kind": "minor",
          "published_at": "2026-02-18T12:47:06Z"
        },
        {
          "tag": "v1.8.1",
          "kind": "patch",
          "published_at": "2026-02-18T09:50:06Z"
        },
        {
          "tag": "v1.8.0",
          "kind": "minor",
          "published_at": "2026-01-10T14:44:40Z"
        },
        {
          "tag": "v1.7.1",
          "kind": "patch",
          "published_at": "2026-01-09T18:04:14Z"
        },
        {
          "tag": "v1.7.0",
          "kind": "minor",
          "published_at": "2026-01-09T17:10:47Z"
        },
        {
          "tag": "v1.6.2",
          "kind": "patch",
          "published_at": "2026-01-09T11:32:06Z"
        },
        {
          "tag": "v1.6.1",
          "kind": "patch",
          "published_at": "2026-01-09T10:54:26Z"
        },
        {
          "tag": "v1.6.0",
          "kind": "minor",
          "published_at": "2026-01-09T10:05:36Z"
        },
        {
          "tag": "v1.5.0",
          "kind": "minor",
          "published_at": "2019-11-05T09:42:18Z"
        },
        {
          "tag": "1.2",
          "kind": "other",
          "published_at": "2018-01-31T09:34:59Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "3abdfda200ce8caa0040ad7965c0fa61798fbf6a",
          "body": "…setup-go-7\n\ndeps(actions): bump actions/setup-go from 6 to 7",
          "is_bot": false,
          "headline": "Merge pull request #34 from Swatto/dependabot/github_actions/actions/…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-07-24T08:22:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8ff15bf3a5f8ba28dddce2b0ccd896cba49ff76",
          "body": "Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6 to 7.\n- [Release notes](https://github.com/actions/setup-go/releases)\n- [Commits](https://github.com/actions/setup-go/compare/v6...v7)\n\n---\nupdated-dependencies:\n- dependency-name: actions/setup-go\n  dependency-version: '7'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump actions/setup-go from 6 to 7",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-20T11:12:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1334ddc6999563199315d02e19be92f82dfb1d44",
          "body": null,
          "is_bot": false,
          "headline": "deps(docker): update Go version in Dockerfile to 1.26.5-alpine3.24",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-07-08T07:17:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f72e1383646d8813b59af8f344d56e9fed8f641d",
          "body": "…rvices\n\nBumps the Go version from 1.26-alpine to 1.26.5-alpine3.24 and updates Alpine from 3.21 to 3.24 in the mock-exporter and mock-twilio Dockerfiles.",
          "is_bot": false,
          "headline": "deps(docker): update Go and Alpine versions in Dockerfiles for E2E se…",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-07-08T07:17:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74aac9cb340227a8a9e5a943094418f16128b828",
          "body": "Bumps the images for Alertmanager from v0.31.1 to v0.33.0 and Prometheus from v3.5.1 to v3.13.0 in the docker-compose.e2e.yml file.",
          "is_bot": false,
          "headline": "deps(docker): update Alertmanager and Prometheus images for E2E",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-07-08T07:17:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d3fa5479f577b273fbbe5125787ca243db67c4d",
          "body": "…checkout-7\n\ndeps(actions): bump actions/checkout from 6 to 7",
          "is_bot": false,
          "headline": "Merge pull request #33 from Swatto/dependabot/github_actions/actions/…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-06-23T06:07:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25250c1452424c186cdfbc3ff77f811104005a91",
          "body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.\n- [Release notes](https://github.com/actions/checkout/releases)\n- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/actions/checkout/compare/v6...v7)\n\n---\nupdated-dependenc\n[…]\n:\n- dependency-name: actions/checkout\n  dependency-version: '7'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump actions/checkout from 6 to 7",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-22T11:14:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ab7616cf6535de72809dd33b4e03b1ca3d857ed3",
          "body": "…3.24\n\ndeps(docker): bump alpine from 3.23 to 3.24 in /test/e2e",
          "is_bot": false,
          "headline": "Merge pull request #32 from Swatto/dependabot/docker/test/e2e/alpine-…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-06-19T10:57:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9abbe1aa5f2a64894e678546cec2d9094cdb6cae",
          "body": "Bumps alpine from 3.23 to 3.24.\n\n---\nupdated-dependencies:\n- dependency-name: alpine\n  dependency-version: '3.24'\n  dependency-type: direct:production\n  update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(docker): bump alpine from 3.23 to 3.24 in /test/e2e",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-15T11:14:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26e96114b0b91ffed1ce3ce4639e98c62f502922",
          "body": "…etadata-action-6\n\ndeps(actions): bump docker/metadata-action from 5 to 6",
          "is_bot": false,
          "headline": "Merge pull request #31 from Swatto/dependabot/github_actions/docker/m…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-03-16T10:55:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff153618e4f90cbc006853179ec4bc655aee13fe",
          "body": "…uild-push-action-7\n\ndeps(actions): bump docker/build-push-action from 6 to 7",
          "is_bot": false,
          "headline": "Merge pull request #30 from Swatto/dependabot/github_actions/docker/b…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-03-16T10:55:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "14c1ddac146e7aa3eef10afe7b9cdb40b139b3b2",
          "body": "…etup-buildx-action-4\n\ndeps(actions): bump docker/setup-buildx-action from 3 to 4",
          "is_bot": false,
          "headline": "Merge pull request #29 from Swatto/dependabot/github_actions/docker/s…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-03-16T10:55:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "12ce574033c9273be5e9ab88f2b1ddb8ad878021",
          "body": "…etup-qemu-action-4\n\ndeps(actions): bump docker/setup-qemu-action from 3 to 4",
          "is_bot": false,
          "headline": "Merge pull request #28 from Swatto/dependabot/github_actions/docker/s…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-03-16T10:55:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64feda22a1a287ac8faac8641c6a1c243b31fbd6",
          "body": "…ogin-action-4\n\ndeps(actions): bump docker/login-action from 3 to 4",
          "is_bot": false,
          "headline": "Merge pull request #27 from Swatto/dependabot/github_actions/docker/l…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-03-16T10:54:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e565fa2781a11ffdb4fd835f24deb52e91eb1ef0",
          "body": "Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.\n- [Release notes](https://github.com/docker/metadata-action/releases)\n- [Commits](https://github.com/docker/metadata-action/compare/v5...v6)\n\n---\nupdated-dependencies:\n- dependency-name: docker/metadata-action\n  dependency-version: '6'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump docker/metadata-action from 5 to 6",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-03-09T11:53:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a65bc5fe529790268f283f57dd80a9f09ce59fb",
          "body": "Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.\n- [Release notes](https://github.com/docker/build-push-action/releases)\n- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)\n\n---\nupdated-dependencies:\n- dependency-name: docker/build-push-action\n  dependency-version: '7'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump docker/build-push-action from 6 to 7",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-03-09T11:53:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3896ea8741c074b476035e76eec087456a55663c",
          "body": "Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.\n- [Release notes](https://github.com/docker/setup-buildx-action/releases)\n- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)\n\n---\nupdated-dependencies:\n- dependency-name: docker/setup-buildx-action\n  dependency-version: '4'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump docker/setup-buildx-action from 3 to 4",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-03-09T11:53:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6190f681c1871469801bb74a282f564f5d366efc",
          "body": "Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.\n- [Release notes](https://github.com/docker/setup-qemu-action/releases)\n- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)\n\n---\nupdated-dependencies:\n- dependency-name: docker/setup-qemu-action\n  dependency-version: '4'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump docker/setup-qemu-action from 3 to 4",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-03-09T11:53:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c70e9bf9c9e284192bff1b90001dc8e59d04163e",
          "body": "Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.\n- [Release notes](https://github.com/docker/login-action/releases)\n- [Commits](https://github.com/docker/login-action/compare/v3...v4)\n\n---\nupdated-dependencies:\n- dependency-name: docker/login-action\n  dependency-version: '4'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump docker/login-action from 3 to 4",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-03-09T11:53:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "33e1d0565e7a30350addb8823e500dfdc439da82",
          "body": null,
          "is_bot": false,
          "headline": "Upgrade E2E version of Prometheus and Alertmanager to LTS",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T16:00:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ece44db6c7c0dbbb2599a5cf6cfaf8cc390ac355",
          "body": null,
          "is_bot": false,
          "headline": "Code organization for banner and better vertical alignements",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T15:54:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cad9e474da45f8e991b0663df9bd4b9ca324f1c4",
          "body": "- Renamed the 'test' job to 'check' for clarity.\n- Integrated linting into the 'check' job, removing the separate 'lint' job.\n- Updated test result processing to utilize JSON output for improved coverage reporting.\n- Adjusted job dependencies in the CI workflow to reflect the changes.",
          "is_bot": false,
          "headline": "refactor: consolidate CI jobs and enhance linting process",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T14:35:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a8b2a60b69779cc090c50ccc3ddd3567b5dba84",
          "body": "- Introduced `WEBHOOK_SECRET` to require Bearer token for POST requests to `/send`, enhancing security.\n- Added `DRY_RUN` option to log messages instead of sending SMS, useful for testing without side effects.\n- Updated configuration loading and metrics handling to support new features.\n- Enhanced documentation to reflect changes in environment variables and API behavior.",
          "is_bot": false,
          "headline": "feat: add webhook authentication and dry run functionality",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T14:19:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "428eacf8c51e44af5c38675f845cff25c2225b2d",
          "body": null,
          "is_bot": false,
          "headline": "Restore QEMU and Buildx setup steps in Docker CI job",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:36:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "56198ff18b04eab3b3cedc64ce05a4d55b3a439e",
          "body": null,
          "is_bot": false,
          "headline": "E2E: improve waiting time",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:35:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad291264c79cf6c58045763fc70ccd3be660e7d6",
          "body": "Without any dependencies, this is a useless usage",
          "is_bot": false,
          "headline": "refactor: remove the caching concept of our docker images in CI",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:27:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b706b52d43ed5357af4fe6897d14f449268b00d",
          "body": "Updated test cases in main_test.go to properly handle errors when closing response bodies and other resources. This change improves error handling and ensures that potential issues are logged without causing test failures.",
          "is_bot": false,
          "headline": "fix: handle unchecked errors in test cleanup and response body closure",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:17:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6a25880dcddb756f21612d6a3dd6c0a0644746f",
          "body": "- Introduced comprehensive unit tests for loading configuration from environment variables, covering default values, custom settings, and validation.\n- Added tests for application lifecycle management, including server startup, shutdown, and error handling.\n- Ensured coverage for various scenarios, including invalid configurations and port conflicts, to enhance reliability and maintainability of the application.",
          "is_bot": false,
          "headline": "test: add unit tests for configuration loading and application lifecycle",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:11:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea80ef324ba87a9af7c6c5db77892bd12510a93f",
          "body": "…ependencies\n\nUpdated the CI workflow to disable caching for the Go setup in all job configurations, ensuring a fresh environment for each run.",
          "is_bot": false,
          "headline": "chore: disable caching in CI workflow for Go setup, since we use no d…",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:00:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70e355a447ab225a3c7f9fb4c8efa281ecd8d24d",
          "body": "Updated the LogRequests middleware to check for errors when writing to the access log. Added error logging to capture any failures during the write operation.",
          "is_bot": false,
          "headline": "fix: handle error from LogRequests access log write",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T12:00:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ac29b0ba80b654c63be474b122f474a74b38302",
          "body": "- Added concurrency settings to the CI workflow to manage job execution.\n- Updated test execution steps to capture detailed test results in JSON format.\n- Implemented a summary step for both unit and E2E tests, providing clear pass/fail output and coverage details.\n- Included cleanup steps for E2E tests to ensure a clean environment after execution.",
          "is_bot": false,
          "headline": "chore: enhance CI workflow with improved test summaries and concurrency",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T11:56:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9491cef6e9cbc67530ffcdf63e4f53f73cb1c11a",
          "body": "…ject",
          "is_bot": false,
          "headline": "Go back to a state where golangci-lint is not a dependency on the pro…",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T11:29:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "649894ab39d20529a22d75a95105b328e6dd35e8",
          "body": "Enable RATE_LIMIT=30 on the E2E promtotwilio service and add two tests\nthat verify 429 responses are returned when the limit is exceeded.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "test: add E2E rate limiting tests",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:44:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0e74d04197fecbbd4b33b41d4be59b064bdf7df0",
          "body": "Co-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "fix: handle unchecked Write return values in middleware tests",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:44:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "81997a8e651f1588887b1d6bcffa60fd4ad9011e",
          "body": "Add RATE_LIMIT and LOG_FORMAT to the README configuration table.\nAdd a Log Formats section with real captured output examples for both\nsimple and nginx formats. Update .env.example with RATE_LIMIT.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "docs: document RATE_LIMIT and LOG_FORMAT configuration",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:36:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bc45b0dfc05f5818f139c001907a3a1a3046876b",
          "body": "Add LogRequests middleware with two formats selectable via LOG_FORMAT:\n- \"simple\" (default): structured slog output with method, path, status,\n  bytes, and duration\n- \"nginx\": nginx combined log format with remote addr, user agent,\n  referer, and X-Forwarded-For\n\nIncludes responseRecorder that track\n[…]\n RATE_LIMIT is exceeded. Both are validated in\nConfig.Validate(). Tested with unit tests for both formats, the rate\nlimiter, and the response recorder.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "feat: add request logging middleware with configurable format",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:36:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7216b3d10c55b5713095ed1b2e395bc0f5761975",
          "body": "Replace 14 individual test functions with a single table-driven test\ncovering 11 cases plus 2 standalone tests for unique flows (MixedStatus,\nBodySizeLimitEnforced). Reduces test file from ~500 to ~220 lines while\nmaintaining full coverage.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "refactor: convert send_request_test.go to table-driven subtests",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:36:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "59233347d542aad6a5d06e5b739fe47e8d793b2a",
          "body": "Move config validation from main.go into a Config.Validate() method\nwith table-driven tests. Add 30s client-level timeout on the Twilio\nHTTP client as defense-in-depth alongside the per-request context\ntimeout. Fix banner text centering.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "refactor: extract Config.Validate() and add HTTP client timeout",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:36:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b8fc7a6d07756cf28ef22ffd976d950aca00589d",
          "body": "Fix READNE.md -> README.md typo. Add .editorconfig, .github/, test/,\nbuild-plan/, dist/, coverage files, and other dev artifacts to reduce\nDocker build context size.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "fix: correct .dockerignore typo and add missing exclusions",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T10:36:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4754a85d44c55d390446e3fd2c0e89169a225eaf",
          "body": "Chore/upgrade go",
          "is_bot": false,
          "headline": "Merge pull request #24 from Swatto/chore/upgrade-go",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T08:54:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd0dcd0f1463944627e224a70bc247566efcf322",
          "body": "Add explicit return after t.Fatal(\"expected handler, got nil\") so\nstaticcheck no longer flags subsequent field accesses as possible\nnil pointer dereferences. Behavior is unchanged since t.Fatal already\nstops the test.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "fix: resolve staticcheck SA5011 in test nil-check patterns",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T08:49:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bb27b6059427d63e183c654c0ed4369b1383e942",
          "body": "Replace the wg.Add(1)/go func(){defer wg.Done(); ...}() pattern with\nwg.Go(func(){...}), available since Go 1.25. This is safer and more\nconcise as it eliminates the risk of forgetting Done() or miscounting Add().\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "refactor: use sync.WaitGroup.Go() for goroutine dispatch",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T08:49:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "272805580bc4024a000dffbfb94c43a04a2d087a",
          "body": "…y-build-deps\n\n- Bump go directive to 1.26 in all go.mod files\n- Update all Dockerfiles to golang:1.26-alpine\n- Update CI workflow go-version to 1.26\n- Add golangci-lint as a go.mod tool dependency (Go 1.24+)\n- Switch CI and Makefile to use `go tool golangci-lint run`\n- Add `make verify-build-deps` \n[…]\nrget to ensure tool deps stay out of the binary\n- Add verify-build-deps step in CI build job\n- Update README and CONTRIBUTING with Go 1.26+ requirement\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "chore: upgrade Go to 1.26, add golangci-lint tool directive and verif…",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-02-18T08:49:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d723dcf59a998e094182795c5dd750bf704e6306",
          "body": "Port the E2E test phase from the CI workflow to the Makefile for\nconsistency between local development and CI environments.\n\nChanges:\n- Add e2e target to Makefile with build, run, logs on failure, and cleanup\n- Simplify CI workflow to use make e2e instead of manual docker compose steps\n- Add make e2e to README commands documentation",
          "is_bot": false,
          "headline": "build: add make e2e target and use it in CI workflow",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-10T14:37:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a97e3f629541d7367386ee70723321ff13c7e30f",
          "body": "Add support for Twilio API Key authentication as a more secure\nalternative to Account SID/Auth Token authentication.\n\nChanges:\n- Add APIKey and APIKeySecret fields to Config struct\n- Refactor TwilioHTTPClient to separate account SID from auth credentials\n- Add API_KEY and API_KEY_SECRET environment \n[…]\nup banner\n- Update README with authentication documentation\n- Add comprehensive tests for API Key authentication\n\nBackwards compatible: existing deployments using SID/TOKEN continue\nto work unchanged.",
          "is_bot": false,
          "headline": "feat: add Twilio API Key authentication support",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-10T14:28:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1d20c2fed29184e98e3eca54b2fc5fb4eaab8ec1",
          "body": "- Remove github.com/buger/jsonparser dependency\n- Use encoding/json with typed structs for AlertManager payload\n- Add internal/handler/types.go with Alert and AlertManagerPayload structs\n- Update handler, format, and utils to work with typed Alert struct\n- Update Dockerfile to handle missing go.sum (no external deps)\n- Update README to highlight zero external dependencies",
          "is_bot": false,
          "headline": "refactor: replace jsonparser with standard library",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T17:38:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b5a2de6d2e33d01afbb046da391e4eaaac75dfc",
          "body": "- Add build-all target for cross-platform builds\n- Update CI to use make build, make coverage\n- Release job now uses make build-all\n- Clean target removes dist/ folder",
          "is_bot": false,
          "headline": "build: use make commands in CI for consistency",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T17:22:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5fd50c04a0e253bb7b9bc5473bb23af5057c5b1",
          "body": "- Add badges, flow diagram, and table of contents\n- Add Quick Start section at the top\n- Use tables for configuration options\n- Condense examples and development sections\n- Move release process to CONTRIBUTING.md",
          "is_bot": false,
          "headline": "docs: rewrite README with modern structure",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T17:22:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac4386f879b8fc0177db0cdee277a5fa5ddfd1aa",
          "body": null,
          "is_bot": false,
          "headline": "style: format code with go fmt",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T17:21:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "514177ba73d60b11a93452e04a9f8947cb8db419",
          "body": "- Add mock-exporter service with controllable /metrics endpoint\n  - /control endpoint to toggle test_alert_trigger metric (0/1)\n  - /status endpoint to check current state\n  - /health endpoint for readiness checks\n\n- Add Prometheus configuration\n  - 5s scrape interval targeting mock-exporter\n  - Ale\n[…]\n> Prometheus -> AlertManager -> SMS\n  - Test resolved alert: resolve metric -> resolved SMS with RESOLVED prefix\n  - Verify mock-exporter /metrics endpoint\n  - Verify Prometheus has scraped the metric",
          "is_bot": false,
          "headline": "feat(e2e): add full Prometheus alert cycle tests",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:59:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5c66aac87bf7a701ee72e6232f8120b9c3ca1282",
          "body": "- Display ASCII banner with application name and description\n- Show version, Go version, and OS/architecture info\n- Print configuration summary (port, sender, receivers, etc.)\n- Add AppName and AppDescription constants",
          "is_bot": false,
          "headline": "feat: add startup banner with application info and configuration",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:47:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "250453b58053f8eb59666f8e433aba8dce90decc",
          "body": "- Rename message.go to format.go (describes formatting functionality)\n- Rename message_formatting_test.go to format_test.go (matches source file)\n- Move maxBodySize constant from utils.go to handler.go (near usage)\n- Delete unused version.go (Version var was never referenced)\n- Split handler_test.go\n[…]\nt.go: message formatting tests\n  - send_request_test.go: SendRequest handler tests\n  - handler_test.go: Ping/Health handler tests\n  - mock_test.go: test mocks\n  - utils_test.go: utility function tests",
          "is_bot": false,
          "headline": "refactor(handler): reorganize package following Go best practices",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:37:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2653cc2f9e954c1325047b90e07e83892a7f3a43",
          "body": "- Add MESSAGE_PREFIX configuration option to prepend custom text to all messages\n- Prefix is added before alert name and resolved status\n- Handle empty prefix gracefully for backward compatibility\n- Add comprehensive tests for prefix functionality including truncation\n- Update README with MESSAGE_PREFIX documentation and message format examples",
          "is_bot": false,
          "headline": "feat: add custom message prefix support",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:14:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eaad885dbf9e275deedc8d002cf35a6394525254",
          "body": "- Extract alert name from labels.alertname (always present per AlertManager spec)\n- Prepend alert name in [AlertName] format to messages\n- Handle missing/empty alertname gracefully for backward compatibility\n- Add comprehensive tests for alert name functionality\n- Update README with new message format documentation",
          "is_bot": false,
          "headline": "feat: add alert name to message from labels.alertname",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:11:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cfacf1e214f71951c9234be898d78f9b8f247fa6",
          "body": "- Use description annotation as fallback when summary is missing or empty\n- Prefer summary over description when both are present\n- Handle whitespace-only summary as empty\n- Update error message to mention both summary and description\n- Add comprehensive tests for description fallback scenarios\n- Update README to reflect new behavior",
          "is_bot": false,
          "headline": "feat: add description field fallback when summary is missing",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:08:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "193301989fb84b0f953767dc6d66b31b872d3ef1",
          "body": "- Add MAX_MESSAGE_LENGTH configuration option (default: 150)\n- Implement truncateMessage helper function\n- Truncate messages after all formatting is complete\n- Add comprehensive tests for truncation functionality\n- Update README with MAX_MESSAGE_LENGTH documentation",
          "is_bot": false,
          "headline": "feat: add message truncation support",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:03:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af9f562abab7c40191f9c925848bb7c03ff55e25",
          "body": "- Add SEND_RESOLVED configuration option to enable resolved alert notifications\n- Update SendRequest to process resolved alerts when enabled\n- Add RESOLVED: prefix to resolved alert messages\n- Add comprehensive tests for resolved alert functionality\n- Add e2e tests for resolved alerts with SEND_RESOLVED enabled\n- Update README with SEND_RESOLVED documentation",
          "is_bot": false,
          "headline": "feat: add support for resolved alerts",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T16:00:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "609827a12689e5b76c33c847cb45d7c74d01b20a",
          "body": "The default golangci-lint configuration is sufficient for this project.",
          "is_bot": false,
          "headline": "chore: remove custom golangci-lint config to use defaults",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:28:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "369b406749399d9e649980efed9b596dd27ac8dc",
          "body": "- Add 'startup:' prefix for initialization errors\n- Add 'shutdown:' prefix for graceful shutdown errors\n- Makes it clearer which phase of the application lifecycle failed",
          "is_bot": false,
          "headline": "refactor(main): improve startup and shutdown error messages",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:27:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "84203cd81c37ee2cb4bfd634df1cf4d60c5dabe2",
          "body": "- Add proper error handling for r.Body.Close() to satisfy errcheck linter\n- Add stage prefixes (ping:, health:, send:, twilio:) to all error messages\n- Add missing slog.Error calls before HTTP error responses\n- Improves debugging by clearly identifying which stage failed",
          "is_bot": false,
          "headline": "fix(handler): handle request body close error and improve error messages",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:27:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "62b7a5aae5efb2f15f8ddde335d975b79c8d2285",
          "body": "- Add proper error handling for resp.Body.Close() to satisfy errcheck linter\n- Add 'twilio:' prefix to all error messages for better debugging\n- Import log/slog for error logging",
          "is_bot": false,
          "headline": "fix(twilio): handle response body close error and improve error messages",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:27:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35a4663a4211185a79eddcd6197ea80f2dd707c9",
          "body": "The --generate-notes flag produced empty descriptions when there\nwere no merged PRs. This change generates release notes from git\ncommit history, ensuring releases always have meaningful content.",
          "is_bot": false,
          "headline": "fix: generate release notes from git commits",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:09:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de1bf7dbce4ea14e39c36a429ef1f018806aa923",
          "body": "- Handle jsonparser errors explicitly in sendMessage instead of ignoring\n- Use scoped variables for optional startsAt field parsing\n- Add test cases for field presence and format validation:\n  - Missing/empty summary annotation\n  - Missing/invalid startsAt timestamp\n  - Missing annotations field entirely",
          "is_bot": false,
          "headline": "refactor(handler): remove nolint annotations with proper error handling",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T11:04:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0f1234279d4ec3dbcb88da9b2c26d869164b1f8",
          "body": "- Update SENDER documentation to specify full phone number with '+'\n  and country code (e.g., +15551234567)\n- Add example Prometheus alert rule showing required summary annotation\n- Note that summary annotation is required\n\nIncorporates documentation improvements from PR #9",
          "is_bot": false,
          "headline": "docs: clarify SENDER format and add example alert rule",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:44:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5daa7fad3a58657be560cafd1be9c223f7a1626d",
          "body": "Replace fmt.Fprint with io.WriteString and properly log any write\nerrors. This follows Go best practices of not ignoring errors.\n\nFixes: Ignored error from fmt.Fprint",
          "is_bot": false,
          "headline": "fix: handle error from io.WriteString in Ping endpoint",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:40:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7f52dd0f8d3bd2b5b562114cc1b1c0cc6e5a201",
          "body": "Use case-insensitive prefix matching for Content-Type header to accept\nvariations like 'Application/JSON' and 'application/json; charset=utf-8'.\n\nIncludes tests for charset and case variations.\n\nFixes: Case-sensitive Content-Type check",
          "is_bot": false,
          "headline": "fix: make Content-Type check case-insensitive and allow charset",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:38:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40130bdf3438c63a6fc7242c520d4da365209bc6",
          "body": "Return 400 Bad Request when the alerts array cannot be parsed instead\nof silently continuing with 0 messages sent. This makes debugging\neasier and provides clear feedback to clients.\n\nIncludes test for invalid alerts format.\n\nFixes: Silent JSON parsing failure",
          "is_bot": false,
          "headline": "fix: return error for invalid alerts JSON format",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:36:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6bcf5c1b4ed57623520393f32a4b90f773d8fa9",
          "body": "Place defer statement before the read operation to ensure the request\nbody is always closed, even if ReadAll fails and returns early.\n\nFixes: defer r.Body.Close() placed after potential return",
          "is_bot": false,
          "headline": "fix: move defer r.Body.Close() before io.ReadAll",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:34:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7e3328cc1c96effcd9ecf25fc359ba59d576406e",
          "body": "Remove the 30-second timeout from http.Client since request-level\ncontext timeout is already set in SendMessage. This eliminates\nredundant configuration and follows the more flexible context-based\ntimeout approach.\n\nFixes: Redundant timeout configuration",
          "is_bot": false,
          "headline": "refactor: remove redundant HTTP client timeout",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:33:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80db4e6a72d31481427698079d56caa290b5c174",
          "body": "Replace os.Exit(1) call from goroutine with channel-based error\ncommunication. Server startup errors are now properly handled in\nthe main goroutine using a select statement.\n\nThis prevents potential race conditions and ensures proper cleanup\nwhen the server fails to start.\n\nFixes: os.Exit(1) called from goroutine",
          "is_bot": false,
          "headline": "fix: handle server startup errors properly in main goroutine",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:31:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4180e84de9b4eb92259872c87d6bc583a39892b3",
          "body": "Add a 5 MB limit on request body size using io.LimitReader to prevent\ndenial-of-service attacks via large request bodies.\n\nIncludes test to verify the body size limit is enforced.\n\nFixes: No request body size limit (DoS vulnerability)",
          "is_bot": false,
          "headline": "security: add request body size limit to prevent DoS",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:29:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9671e8aede359f9ee8501088340091c18bd7b7f3",
          "body": "Move regex compilation from FindAndReplaceLabels function to package\nlevel variable. This avoids expensive regex compilation on every call.\n\nFixes: Regex compiled on every request",
          "is_bot": false,
          "headline": "perf: compile regex once at package level",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:27:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d2e8ffcc0d09ff8d94f625c5a33fd64235550d6",
          "body": "…b Actions workflow",
          "is_bot": false,
          "headline": "docs: update release process documentation to reflect automated GitHu…",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T10:10:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e95eed352915284e5b81eaa561692860559f4ca4",
          "body": "- Update CI workflow to only reference main branch\n- Remove master branch references from workflow triggers",
          "is_bot": false,
          "headline": "Rename branch from master to main",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T09:53:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16de97bb5d5148944d06ec8e40fd6a461b556da6",
          "body": "- Update golangci/golangci-lint-action from v6 to v9 in CI workflow\n- Migrate .golangci.yml configuration to v2 format using golangci-lint migrate\n- Move formatters (gofmt, goimports) to separate formatters section\n- Update configuration structure: linters-settings -> settings, exclude-rules -> excl\n[…]\n\n- Add version field and exclusions presets for v2 compatibility\n\nThis fixes the 'unsupported version of the configuration' error that was\noccurring when dependabot tried to update the action version.",
          "is_bot": false,
          "headline": "Update golangci-lint-action to v9 and migrate config to v2",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-09T09:52:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e59092fdf830563e209ed5bb8cf0856c39a2ff8f",
          "body": "…setup-go-6\n\ndeps(actions): bump actions/setup-go from 5 to 6",
          "is_bot": false,
          "headline": "Merge pull request #17 from Swatto/dependabot/github_actions/actions/…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:59:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92a49ec1f098982214eeba892b18244dd3efc840",
          "body": "…checkout-6\n\ndeps(actions): bump actions/checkout from 4 to 6",
          "is_bot": false,
          "headline": "Merge pull request #16 from Swatto/dependabot/github_actions/actions/…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:59:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5094fd6b900b13f92b8e0f41f98f7bea4ab6614",
          "body": "…3.23\n\ndeps(docker): bump alpine from 3.20 to 3.23 in /test/e2e",
          "is_bot": false,
          "headline": "Merge pull request #19 from Swatto/dependabot/docker/test/e2e/alpine-…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:59:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06ef3f5f0a39c228c07e3ba78f17f810552eaa8a",
          "body": "…/golang-1.25-alpine\n\ndeps(docker): bump golang from 1.23-alpine to 1.25-alpine in /test/mock-twilio",
          "is_bot": false,
          "headline": "Merge pull request #20 from Swatto/dependabot/docker/test/mock-twilio…",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:59:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6f0b44b11d1397e7d95ba831b12915c5a0cf147d",
          "body": "deps(docker): bump golang from 1.23-alpine to 1.25-alpine",
          "is_bot": false,
          "headline": "Merge pull request #21 from Swatto/dependabot/docker/golang-1.25-alpine",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:58:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "743d3345b20d546791576b708ff65882ca67e174",
          "body": "Bumps golang from 1.23-alpine to 1.25-alpine.\n\n---\nupdated-dependencies:\n- dependency-name: golang\n  dependency-version: 1.25-alpine\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(docker): bump golang from 1.23-alpine to 1.25-alpine",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-01-08T16:49:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a62d5adf3ca84e5b55d99898eeee8a09c0452a82",
          "body": "Bumps golang from 1.23-alpine to 1.25-alpine.\n\n---\nupdated-dependencies:\n- dependency-name: golang\n  dependency-version: 1.25-alpine\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(docker): bump golang in /test/mock-twilio",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-01-08T16:49:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57881d355edf1bbd611f117dbaf582f99c0dba37",
          "body": "Bumps alpine from 3.20 to 3.23.\n\n---\nupdated-dependencies:\n- dependency-name: alpine\n  dependency-version: '3.23'\n  dependency-type: direct:production\n  update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(docker): bump alpine from 3.20 to 3.23 in /test/e2e",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-01-08T16:49:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6a0aaed713d66f3cfdecfdc83d8726e2eb5f699a",
          "body": "Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.\n- [Release notes](https://github.com/actions/setup-go/releases)\n- [Commits](https://github.com/actions/setup-go/compare/v5...v6)\n\n---\nupdated-dependencies:\n- dependency-name: actions/setup-go\n  dependency-version: '6'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump actions/setup-go from 5 to 6",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-01-08T16:48:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5032cc9bf69f4ead0afbcae9960109d243d2aa50",
          "body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.\n- [Release notes](https://github.com/actions/checkout/releases)\n- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/actions/checkout/compare/v4...v6)\n\n---\nupdated-dependenc\n[…]\n:\n- dependency-name: actions/checkout\n  dependency-version: '6'\n  dependency-type: direct:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>",
          "is_bot": true,
          "headline": "deps(actions): bump actions/checkout from 4 to 6",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-01-08T16:48:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7844d79306ac7d7d19b7a91d7689a9d33d1016fa",
          "body": "Rework project structure and CI pipeline",
          "is_bot": false,
          "headline": "Merge pull request #15 from Swatto/rework",
          "author_name": "Gael Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:48:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "65423945a244c915296167c088cd7f0c1f44f82d",
          "body": null,
          "is_bot": false,
          "headline": "fix: align ldflags version variable with main.go (main.Version)",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:46:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f37dca65012a49896acfda265949fdbac33b8621",
          "body": "- Add workflow_dispatch trigger for manual releases with version input\n- Add release job that creates git tag, builds cross-platform binaries, and creates GitHub Release with auto-generated changelog\n- Update docker job to push prerelease images on main/master push\n- Update docker job to push official release images on workflow_dispatch\n- Skip docker push for pull requests (only run test/lint/build/e2e)",
          "is_bot": false,
          "headline": "feat: add release automation workflow",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:44:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ece982a75db48c8169d65bba5ba99ee2930cb07b",
          "body": "The minor memory optimization isn't worth reduced code readability",
          "is_bot": false,
          "headline": "Disable fieldalignment check in golangci config",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:30:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46e9b30b43aae7ce078e26a3099fbff74fec5083",
          "body": "- Fix .gitignore to not exclude cmd/promtotwilio directory\n- Add main.go entry point\n- Fix fieldalignment lint error in Config struct",
          "is_bot": false,
          "headline": "Fix: add missing cmd/promtotwilio/main.go and fix lint issues",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:25:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc2d716dcea5c6574d56ea2192185ffcc2943f03",
          "body": "- Restructure code into internal/handler package\n- Add new CI workflow with linting, testing, and e2e tests\n- Add docker-compose for e2e testing with mock Twilio server\n- Add golangci-lint configuration\n- Add dependabot for dependency updates\n- Remove legacy docker_image workflow\n- Update Dockerfile and Makefile",
          "is_bot": false,
          "headline": "Rework project structure and CI pipeline",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2026-01-08T16:20:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b373d8e4f1e9eb55423bc7f45636ca9b6e448d83",
          "body": null,
          "is_bot": false,
          "headline": "Fix YAML indentation",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:43:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23e6aa242ee035cc73eea3193806084fb948b282",
          "body": "Build are done using actions so no need of it anymore here.\nReleases will follow git tags done",
          "is_bot": false,
          "headline": "Remove the notion of version in the makefile",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:37:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6dc6128bb78781e78d237aec1b65910e67816d76",
          "body": null,
          "is_bot": false,
          "headline": "Follow tag names for automatic releases",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:35:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "32e0c6f4a5cb6d9dc44fa4e6496f6f4945b5b887",
          "body": null,
          "is_bot": false,
          "headline": "Setup github action to publish",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:29:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2af8e1130a1b73b49e17fd782b445ac11c08dbaa",
          "body": null,
          "is_bot": false,
          "headline": "Update golang builder image to 1.13",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:09:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b1d7b365be635dbe54bdfc0734413ac7c11f280",
          "body": "Copy options struct instead of pointer",
          "is_bot": false,
          "headline": "Merge pull request #7 from prestonvanloon/master",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-11-05T09:04:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e6bef879860815dc22fbec885325883a033a982",
          "body": null,
          "is_bot": false,
          "headline": "copy struct instead of pointer",
          "author_name": "Preston Van Loon",
          "author_login": "prestonvanloon",
          "committed_at": "2019-10-23T14:27:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc5c273ee7890504d1b9fc8e51cfbd76830a49fa",
          "body": null,
          "is_bot": false,
          "headline": "CHange README to reflect the size of the image",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-03-11T16:16:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1567c0a7846f5ba2115db20c3f47214a1c1899bc",
          "body": null,
          "is_bot": false,
          "headline": "V1.4",
          "author_name": "Gaël Gillard",
          "author_login": "Swatto",
          "committed_at": "2019-03-11T16:14:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 13,
      "commits_last_year": 91,
      "latest_release_at": "2026-07-08T07:31:05Z",
      "latest_release_tag": "v1.10.2",
      "releases_from_tags": false,
      "days_since_last_push": 2,
      "active_weeks_last_year": 8,
      "days_since_latest_release": 18,
      "mean_days_between_releases": 20
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/swatto/promtotwilio",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/swatto/promtotwilio",
          "is_deprecated": false,
          "latest_version": "v1.10.2",
          "repository_url": "https://github.com/swatto/promtotwilio",
          "versions_count": 12,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-08T07:17:51Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 18
        }
      ]
    },
    "popularity": {
      "forks": 18,
      "stars": 35,
      "watchers": 2,
      "fork_history": {
        "days": [
          {
            "date": "2016-03-23",
            "count": 1
          },
          {
            "date": "2017-10-08",
            "count": 1
          },
          {
            "date": "2018-01-30",
            "count": 1
          },
          {
            "date": "2018-03-20",
            "count": 1
          },
          {
            "date": "2019-05-18",
            "count": 1
          },
          {
            "date": "2019-10-23",
            "count": 1
          },
          {
            "date": "2020-02-27",
            "count": 1
          },
          {
            "date": "2020-03-08",
            "count": 1
          },
          {
            "date": "2020-08-03",
            "count": 1
          },
          {
            "date": "2020-10-28",
            "count": 1
          },
          {
            "date": "2021-06-27",
            "count": 1
          },
          {
            "date": "2023-01-31",
            "count": 1
          },
          {
            "date": "2023-02-26",
            "count": 1
          },
          {
            "date": "2023-03-16",
            "count": 1
          },
          {
            "date": "2023-11-01",
            "count": 1
          },
          {
            "date": "2024-02-24",
            "count": 1
          },
          {
            "date": "2024-06-23",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 17,
        "total_forks": 18
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod",
        "test/mock-exporter/go.mod",
        "test/mock-twilio/go.mod"
      ],
      "largest_source_bytes": 30140,
      "source_files_sampled": 22,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": "No resolved dependencies to assess",
        "scope": "repository_graph",
        "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": [],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [],
        "collected": true,
        "truncated": false,
        "total_count": 0,
        "direct_count": 0,
        "indirect_count": 0
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 17,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 5,
        "closed_unmerged_prs": 12
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "Swatto",
          "commits": 113,
          "avatar_url": "https://avatars.githubusercontent.com/u/892951?v=4"
        },
        {
          "type": "User",
          "login": "prestonvanloon",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/7246818?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.991
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": true,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "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": "8 out of 8 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/14 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": 7,
            "reason": "9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "3abdfda200ce8caa0040ad7965c0fa61798fbf6a",
        "ran_at": "2026-07-26T09:42:47Z",
        "aggregate_score": 4.6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T08:27:23Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-24T08:22:13Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Swatto/promtotwilio",
    "host": "github.com",
    "name": "promtotwilio",
    "owner": "Swatto"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 59,
      "inputs": {
        "security": 46,
        "vitality": 76,
        "community": 51,
        "governance": 55,
        "engineering": 64
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 76,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 66,
            "inputs": {
              "commits_last_year": 91,
              "human_commit_share": 0.87,
              "days_since_last_push": 2,
              "active_weeks_last_year": 8
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "8/52 weeks with commits",
                "points": 5.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "91 commits in the last year",
                "points": 17.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 91
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7",
                "points": 7,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 13,
              "latest_release_tag": "v1.10.2",
              "releases_from_tags": false,
              "days_since_latest_release": 18,
              "mean_days_between_releases": 20
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "13 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 18 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 18
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~20 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 20
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 2,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 2 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 51,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 35,
            "inputs": {
              "forks": 18,
              "stars": 35,
              "watchers": 2,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "35 stars",
                "points": 24.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 35
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "18 forks",
                "points": 10.3,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "2 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "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 (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 55,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 15,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.991
            },
            "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 99% of commits",
                "points": 0.2,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 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": 69,
            "inputs": {
              "merged_prs": 17,
              "open_issues": 0,
              "closed_issues": 5,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 12
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "17/29 decided PRs merged",
                "points": 22.4,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 17,
                      "decided": 29
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/14 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 53,
            "inputs": {
              "followers": 25,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "Swatto",
              "public_repos": 27,
              "account_age_days": 5501
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "25 followers of Swatto",
                "points": 10.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 25,
                      "login": "Swatto"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "27 public repos, account ~15 yr old",
                "points": 22.5,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 27
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/swatto/promtotwilio"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 18
            },
            "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 18 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 18
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "12 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 64,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [
                "prometheus",
                "twilio",
                "alert",
                "prometheus-alert",
                "alertmanager"
              ],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "5 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 46,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 46,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 4.6
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 8 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/14 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": "9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "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": 4
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 69,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.851,
              "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": "74 of 87 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 74,
                      "sampled": 87
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.1,
              "toolchain_manifests": [
                "go.mod",
                "test/mock-exporter/go.mod",
                "test/mock-twilio/go.mod"
              ],
              "dependency_bot_commit_share": 0.13
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "10 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 10,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "13 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 13,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 30140,
              "source_files_sampled": 22,
              "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/22 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 22,
                      "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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-26T09:42:59.154977Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/Swatto/promtotwilio.svg",
  "full_name": "Swatto/promtotwilio",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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.