Relatório técnico de engenharia: ecossistema gghstats v1.5.1

1. Contexto e filosofia de design
Os dados de tráfego do GitHub (views e clones) só são retidos numa janela rolante de 14 dias. Sem captura própria, essa telemetria desaparece. gghstats persiste o histórico de tráfego em SQLite, com dashboard, API, CLI e métricas Prometheus, além do limite da API.

O design prioriza soberania de dados e minimalismo operacional: um binário Go + SQLite, sem base externa obrigatória, self-hosting em vez de SaaS que exige entregar um PAT a terceiros.
Separação de responsabilidades
| Repositório | Papel |
|---|---|
| gghstats (core) | Aplicação: sync GitHub → SQLite, serve, API/UI, CLI, Prometheus, alertas opt-in, imagem GHCR / binários. Vars de app como GGHSTATS_DB, GGHSTATS_TRUSTED_PROXIES, GGHSTATS_GITHUB_TOKEN, etc. |
| gghstats-selfhosted (deploy) | IaC do operador: Compose (minimal / Traefik TLS / observabilidade), Helm, layout GGHSTATS_HOST_DATA, pin de imagem, docs VPS. Não é o código do motor. |

Traefik, Helm, stacks Grafana/Prometheus/Loki e a convenção GGHSTATS_HOST_DATA pertencem ao selfhosted. O core só entrega o binário/imagem e a semântica das variáveis de aplicação (ex.: confiar em X-Forwarded-* via GGHSTATS_TRUSTED_PROXIES).
2. Instalação e deploy
Avaliação rápida (core)
| Método | Comando / ferramenta | Uso |
|---|---|---|
| Script | curl -fsSL https://get.gghstats.com/install.sh | sh |
Install rápido Linux/macOS (pin: VERSION=v1.5.1 …) |
| Homebrew | brew install hrodrig/gghstats/gghstats |
Workstations |
| Go | go install github.com/hrodrig/gghstats/cmd/gghstats@latest |
Fonte / bleeding-edge |
Modo demo: gghstats serve --demo (ou GGHSTATS_DEMO=true) — UI com dados sintéticos, sem PAT nem sync real.
Produção: o que vive onde
Core (aplicação):
- Persistência SQLite:
GGHSTATS_DB/--db(no contentor muitas vezes/data/gghstats.dbcom volume em/data). - Atrás de reverse proxy:
GGHSTATS_TRUSTED_PROXIES(CIDR/IP do peer que fala com o gghstats) para rate-limit / whitelist / access log usarem o cliente real viaX-Forwarded-For/X-Real-IP. Lista vazia = ignorar esses headers (default seguro). - Imagem:
ghcr.io/hrodrig/gghstatsemgcr.io/distroless/static-debian13:nonroot.
Selfhosted (manifestos): versão do repo ~0.1.58, pin da app GGHSTATS_VERSION=v1.5.1.
GGHSTATS_HOST_DATA: diretório no host (ex./home/gghstats/gghstats-data) com.env, SQLite montado em/data, e opcionalmente.env.observability/ CSS de tema. Compose com--env-file "${GGHSTATS_HOST_DATA}/.env".- Compose minimal: um serviço, porta no host (ex. 8080).
- Compose Traefik: HTTPS (80/443), Let’s Encrypt (
GGHSTATS_HOSTNAME,ACME_EMAIL). Rate-limit na borda + app;/metricsfora do router público (scrape interno). Authelia SSO opcional na redegghstats_edge. - Observability (opcional, precisa Traefik /
gghstats_edge): Prometheus, Grafana, Loki; projeto Compose-p gghstats-obs; overlay Traefik para Grafana no seu FQDN. - Helm: chart
gghstatsemhttps://hrodrig.github.io/gghstats-selfhosted(ou clone./run/kubernetes/helm/gghstats); token num Secret; PVC em/data. - Upgrade de imagem: mudar
GGHSTATS_VERSION→pull+up -d(restartnão chega). Helper:./run/scripts/compose-stack.sh.
Alertas (Slack / webhook / Loki / SMTP) são do core (GGHSTATS_ALERTS_*); o selfhosted só liga essas vars no Compose/Helm e documenta gghstats alert test.
3. Trajetória: v1.1.0 → v1.5.1
v1.1.0 — Pins + Featured (migração v6)
- CLI
gghstats repo/gghstats featured: pins unem-se ao conjunto de tráfego (FILTER ∪ pins); Featured é vitrine editorial sem tráfego em/. - Tabelas
pinsefeatured(migração v6). - Página
/featured(grelha neo-brutalista); link na nav só se o catálogo não estiver vazio.
v1.2.0 — UX Featured + números
- Formatação de contagens (separadores /
GGHSTATS_COMPACT_NUMBERS). /featured: paginação, pesquisa e ordenação (page,per_page,q,sort,dir) viaFilterFeatured.
v1.3.0 — Estatísticas do índice + JSONL
- Painel de estatísticas diárias de clones, rank/
# - %, linha Unique no chart do índice. - Export JSONL do índice (resumo + histórico + referrers/paths/stars por repo filtrado). Nasce aqui; schema da API/SQLite de tráfego inalterado.
v1.4.0 — UX uniques + JSON Featured + carimbo UTC
- U1: uniques como cifra principal; eventos de clones/views secundários.
GET /api/v1/featured+/featuredno sitemap (quando há entradas).- JSONL:
Content-Dispositioncom stamp UTCgghstats-export-YYYYMMDD-HHMM.jsonl(#23). Fixes Carlok #22–#25 (charts por locale, tooltips, Rank).
v1.5.0 — Cinco slices de reporting
| Slice | Conteúdo |
|---|---|
| F-fresh | Frescura / cobertura por métrica (views / clones). Statuses: fresh | delayed | missing | failed | never. Charts com buracos null (zero explícito ≠ dia omitido). Fetch views/clones independente. Migração v7 (traffic_metric_state, traffic_metric_coverage). |
| V-vis | github_visibility + report_policy (exclude > include > inherit); GGHSTATS_REPORT_PRIVATE; CLI repo report ls/set. Superfícies de relatório fail-closed (404 indistinguível). Coleção (filter/pins/INCLUDE_PRIVATE) separada do reporting. Migração v8. |
| V-json | gghstats repo report ls --json (+ filtros --visibility / --policy) para scripts pós-upgrade. |
| U-legend | Legenda i18n nos charts de detalhe: buraco/null = não reportado pelo GitHub; 0 = zero confirmado. |
| X-chart | Download JSON alinhado ao chart (/{owner}/{repo}/traffic.json); dogfood …/traffic?dense=1 (sparse por omissão inalterado). |
Operadores: após 1.5.0, linhas existentes → unknown + inherit até ao próximo sync (ou repo report set … include). O histórico SQLite não é apagado; dashboard/APIs/exports/badges podem parecer vazios até lá.
v1.5.1 — Fix Featured (#47)
Em 1.5.0, Featured foi tratado incorretamente como superfície de relatório: /featured, API, nav e sitemap exigiam uma linha repos recolhida e reportVisible. Isso parte a vitrine editorial (entrada Featured ≠ repo com tráfego).
1.5.1 restaura o catálogo: de novo FilterFeatured / FeaturedCount. A visibilidade de relatório continua só nas rotas de tráfego/dashboard. Não é preciso sync para a vitrine. Não é um relaxamento do fail-closed do dashboard; o bug era o scope errado do Featured.
4. Dados, segurança e supply chain
Migrações SQLite relevantes
| Versão | Conteúdo |
|---|---|
| v6 | pins, featured |
| v7 | Frescura / cobertura de tráfego |
| v8 | repos.github_visibility, repos.report_policy |
Abertura com WAL para leituras concorrentes (UI/API) enquanto o sync escreve.
Defesa em profundidade (core)
- Rate limiting token-bucket por IP; whitelist de IP opcional;
GGHSTATS_API_ONLY. GGHSTATS_TRUSTED_PROXIES(ver §2).- Cosign + SBOM nas releases; cobertura de testes ≥ 80 % no release-check.
- Imagem distroless nonroot.
Alertas
Opt-in (GGHSTATS_ALERTS_ENABLED): sinks Slack / webhook / Loki / SMTP; regras após sync; validação com gghstats alert test. Stacks Grafana/Loki do observability Compose são deploy selfhosted, distintos do sink Loki da app.
5. Encerramento
v1.5.1 consolida a linha 1.5: frescura honesta (cinco statuses + buracos null), visibilidade de relatório fail-closed com migrações v7/v8, e a correção de que Featured é um catálogo editorial, não report scope. O motor fica em gghstats; Traefik, Helm, GGHSTATS_HOST_DATA e observabilidade vivem em gghstats-selfhosted, com pin de imagem v1.5.1.
Referências: CHANGELOG · SPEC · README core · gghstats-selfhosted · install https://get.gghstats.com/install.sh