Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 1.13.0 · 2026-07-26 09:42 UTC

Swatto / promtotwilio

Send text messages for Prometheus alerts using Twilio

Go · ShellMIT★ 35 Sterne⑂ 18 Forksseit März 2016Auf GitHub ansehen ↗

Swatto/promtotwilio erreicht einen Gesundheitsindex von 59 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei Vitality (76/100) ab, am schwächsten bei Security (46/100). Zuletzt vor 2 Tagen aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

59
gesamt / 100
Mittel

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

59
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

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

Eigentümerschaft

Gael GillardPersönliches Konto
25 Follower27 öffentliche Reposseit Juli 2011McKinsey & Company

Dieses Repository gehört einem persönlichen Konto. Ein Projekt mit nur einem Eigentümer trägt ein höheres Kontinuitätsrisiko als ein organisationsgetragenes.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
Gogithub.com/swatto/promtotwiliov1.10.2-12vor 18 Tagen

Metriken nach Kategorie

Vitalität

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

76Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 2 Tagen
5.5/36Commit-Rhythmus — 8/52 Wochen mit Commits
17.6/18Commit-Volumen — 91 Commits im letzten Jahr
7/10OpenSSF Scorecard: Maintained — 9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
Verwendete Eingangsdaten
commits_last_year91
human_commit_share0,87
days_since_last_push2
active_weeks_last_year8
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 13 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 18 Tagen
27/27Release-Rhythmus — ein Release etwa alle 20 Tage
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Verwendete Eingangsdaten
releases_count13
latest_release_tagv1.10.2
releases_from_tagsnein
days_since_latest_release18
mean_days_between_releases20

Community & Verbreitung

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

51Mittel · 18 % des Gesamtindex
Wie die Bewertung erfolgt
24.8/60Stars — 35 Stars
10.3/25Forks — 18 Forks
0/15Watcher — 2 Watcher
Verwendete Eingangsdaten
forks18
stars35
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (MIT)
18/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingja
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templatenein

Nachhaltigkeit & Governance

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

55Mittel · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0.2/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 99 % der Commits
2.7/13.5Breite der Beitragenden — 2 Beitragende
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Verwendete Eingangsdaten
bus_factor1
contributors_sampled2
top_contributor_share0,991
Wie die Bewertung erfolgt
46.8/46.8Issue-Lösungsquote — 100 % der Issues geschlossen
22.4/38.3PR-Annahme — 17/29 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/14 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs17
open_issues0
closed_issues5
issue_closed_ratio1
closed_unmerged_prs12
Wie die Bewertung erfolgt
10/30Organisatorische Trägerschaft — persönliches (Nutzer-)Konto
0/20Verifizierte Domain — für Nutzerkonten nicht anwendbar
10.2/25Reichweite des Inhabers — 25 Follower von Swatto
22.5/25Kontohistorie — 27 öffentliche Repos, Kontoalter ca. 15 Jahre
Verwendete Eingangsdaten
followers25
owner_typeUser
is_verified
owner_loginSwatto
public_repos27
account_age_days5.501
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Paketpflege

100Exzellent
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf go
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 18 Tagen
20/20Versionshistorie — 12 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesgithub.com/swatto/promtotwilio
ecosystemsgo
any_deprecatednein
min_days_since_publish18

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

64Mittel · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 1 Workflow(s)
24/24Tests vorhanden
0/16Linter-Konfiguration
0/9.6Pre-Commit-Hooks
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
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfigja
has_linter_confignein
has_precommit_confignein
Wie die Bewertung erfolgt
30/30README
0/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
10/10Topics — 5 Topics
0/10Wiki
Verwendete Eingangsdaten
topicsprometheus, twilio, alert, prometheus-alert, alertmanager
has_wikinein
homepage
has_readmeja
has_docs_dirnein
has_descriptionja

Sicherheit

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

46Gefährdet · 16 % des Gesamtindex

Sicherheitslage

46Gefährdet
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
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.5Lizenz — 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
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate4,6

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

69Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
0/45Agentenanweisungen — keine CLAUDE.md / AGENTS.md / Editor-Regeln
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 74 von 87 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,851
agent_instruction_files
agent_instruction_max_bytes
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Go (statisch typisiert)
10/10Reproduzierbare Umgebung — Dockerfile
10/10Belegte Agentenpraxis — 10 der letzten 100 Commits von Agenten verfasst oder ihnen zugeschrieben
8/8Automatisierte Wartung — 13 der letzten 100 Commits sind automatisierte Abhängigkeits-Updates
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfiles
has_dockerfileja
typed_languageja
bootstrap_filesMakefile
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0,1
toolchain_manifestsgo.mod, test/mock-exporter/go.mod, test/mock-twilio/go.mod
dependency_bot_commit_share0,13
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Go (statisch typisiert)
55/55Handhabbare Dateigrößen — 0/22 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageGo
largest_source_bytes30.140
source_files_sampled22
oversized_source_files0

Eckdaten

35GitHub-Sterne
2Mitwirkende
91Commits, letzte 12 Monate
2Tage seit letztem Push
13Releases
1Bus-Faktor
0offene Issues
GoPaket-Ökosysteme

Warnungen zur Datenerhebung

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

Weitere Details

Stern- und Fork-Verlauf 0 ★ / 18 ⇿
0Sterne
18Forks
2Releases

Wann jeder Stern und Fork hinzugefügt wurde, von GitHub erfasst und nach Tagen gruppiert. Das kumulierte Wachstum steht direkt über den täglichen Zugängen, aus denen es besteht, sodass beide gegeneinander lesbar sind: stetiger organischer Zuwachs sieht ganz anders aus als ein abrupter, kurzlebiger Ausschlag. Wo dieser Unterschied messbar ist, wird er als Wachstumsauthentizität ausgewiesen.

0481216201712016-032020-052024-06
Major 0Minor 1Patch 0

Jeder Punkt umfasst 8 Tage.

OpenSSF Scorecard 4.6 / 10
4.6Gesamtwert

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

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

RegistryPaketVersionBeziehung
Abhängigkeits-Advisories nicht bewertet

Der Advisory-Abgleich konnte für diesen Bericht nicht ausgeführt werden: No resolved dependencies to assess

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

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

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

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenGo.