Skip to content

v0.2.0 — i18n, UI, API keys, admin y métricas

Choose a tag to compare

@Gisus07 Gisus07 released this 19 May 22:39
· 18 commits to main since this release

Consolidación grande sobre v0.1.0. La API ya no es solo "ofrece datos" — ahora tiene gestión de keys, métricas por usuario, documentación bilingüe y un security tab completamente limpio.

🟢 En producción

✨ Lo nuevo

Documentación bilingüe

  • /docs — español por defecto
  • /docs/en — inglés
  • Auto-detect por Accept-Language (si tu navegador prefiere inglés, redirige automáticamente)
  • /openapi.json (ES) y /openapi-en.json (EN), este último traducido en runtime
  • Override manual con ?lang=es o ?lang=en

API Keys (tier Free)

  • POST /v1/keys/register — auto-registro público, instantáneo (email + nombre + propósito opcional)
  • GET /v1/keys/me — metadata de mi key
  • GET /v1/keys/me/usage?days=30 — histograma diario de uso (ideal para dashboards)
  • DELETE /v1/keys/me — auto-revoke
  • 300 req/min con key vs 30 req/min anonymous

Admin

  • GET /v1/admin/keys — listar todas las keys (activas + revocadas)
  • POST /v1/admin/keys/{id}/revoke — soft-delete por id
  • POST /v1/admin/trigger-ingest — disparar ingest manual (ya existía)

Shapes JSON limpios

La respuesta default es ultra-plana:

{ "date": "2026-05-14", "usd": 510.7873, "eur": 598.12171255 }

Cuando hay propagación, aparece propagated_currencies: ["USD", "EUR"]. Campos internos (source_file, fetched_at, currency_pair) ya no se exponen al consumidor.

Code samples embebidos

Cada endpoint trae snippets listos en curl, JavaScript (fetch), TypeScript, Python (requests), PHP (cURL), Go (net/http) — visibles como tabs en /docs.

UI de Scalar pulida

  • Theme purple con tipografías Inter + JetBrains Mono
  • Tags reorganizados (rates → keys → system → admin)
  • Ejemplos múltiples por endpoint (día normal, fin de semana, propagación parcial, pre-redenominación)
  • Server URL declarado en el spec (try-it desde docs funciona)

Errores unificados

Antes los errores de validación Zod devolvían un shape distinto a los AppError. Ahora todo usa el mismo envelope:

{
  "error": "Entrada inválida",
  "code": "VALIDATION_ERROR",
  "details": { "issues": [{ "path": "date", "message": "...", "code": "custom" }] }
}

🛡️ Seguridad

  • 0 alertas abiertas en Security tab (code scanning, secret scanning, dependabot)
  • CVE crítico de Drizzle (SQL injection en identifiers) parcheado: 0.36 → 0.45
  • Headers HTTP endurecidos: HSTS 1 año + preload, CSP estricto, Permissions-Policy denegando 8 features
  • Dependabot + GitHub Actions CodeQL + Secret Scanning + Push Protection: todo activado
  • Branch protection en main con required status checks

🧪 Tests

  • 93 tests pasando, 0 skipped (subimos de 71 + 8 skipped en v0.1.0)
  • Tests de DB migrados de pg-mem a @testcontainers/postgresql con Postgres real
  • Cada PR debe pasar el job typecheck + tests + build antes de mergear

📦 Datos

  • Total filas en DB: ~6,000+ (rates reales + propagaciones)
  • USD desde 2016-01-04 (2,500 registros reales)
  • EUR desde 2020-03-27 (~1,400 registros reales)

🗺️ Próximos pasos (planeados)

  • Dominio propio cuando haya presupuesto
  • Tier Pro con monetización (Stripe/Plisio/PayPal, por decidir)
  • Endpoint /metrics para observabilidad
  • Más ejemplos de SDK en el README

📄 Licencia

AGPL-3.0-or-later.

No estamos afiliados al Banco Central de Venezuela.