release: v1.16.0 — offer live pricing, bot health telemetry, edge blocklist #247
Reference in New Issue
Block a user
Delete Branch "development"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Promote
development→masterfor release v1.16.0. Three features since v1.15.0, all additive (no breaking change, no schema migration):/offer/moves to the render sidecar; §4.4 is generated from the live catalog (sorted, grouped, right-aligned), title escaping hardened; landing feedback link; admin catalog list ordered to match.bot_tg_*metrics +botlink_connected_bots; Grafana alerts + dashboard. Additivebotlink/v1proto → rolling-safe, but both prod hosts deploy (main + bot).PROD_GATEWAY_BLOCKLIST_*).Deploy notes
v1.16.0on master, then manualprod-deploydispatch (confirm=deploy).CI on this PR is test-only (unit + integration + ui); the deploy is the separate manual step.
The bot runs on its own host and exports no telemetry (otelcol is unreachable from there), so it was a monitoring blind spot. Observe its Bot API health centrally by wrapping the HTTP client — one place, no per-call-site instrumentation — and relay it up the existing bot-link as a periodic Health message the gateway turns into its own metrics. - proto: add Health (delta connect / api / 429 counters + a last-ok stamp) to the FromBot oneof (additive, backward-compatible). - bot: platform/telegram/internal/health wraps the Bot API HTTP client — it stamps liveness on any 2xx (so the getUpdates long-poll keeps it fresh even when idle), classifies transport/5xx failures (getUpdates vs other) and 429s, and honours a 429's Retry-After (bounded) so the bot backs off; a 4xx other than 429 is a normal per-request outcome and is not counted. - bot-link client: flush the reporter as a Health message every 30s over a single-sender loop (a gRPC stream forbids concurrent Send). - gateway: fold each report into bot_tg_errors_total{kind} and the bot_tg_last_ok_unix liveness gauge. - grafana: alerts (bot disconnected, bot not reaching the Bot API, sustained 429s) routed to the operator email — which does not go through the bot — plus a Telegram-bot dashboard. - docs (ARCHITECTURE, compose comments); unit tests (observer classification, Retry-After, snapshot/commit, hub last-ok monotonicity).Refuse a client whose IP is in a curated CIDR feed with 403 in the same abuseGuard, before the fail2ban ban. Prod-only (keys by real client IP), off by default. - ratelimit.Blocklist: a sorted-range IPv4 matcher (binary search) with an allowlist checked first; ParseDROP reads the feed; ApplyRefresh keeps the last-good feed on a transient fetch failure and drops it fail-open once stale (better to under-block than block a legitimate client on a frozen feed). A separate static CIDR set, not the per-IP fail2ban store. - gateway: a refresher goroutine re-fetches every few hours (bounded fetch + size cap); config GATEWAY_BLOCKLIST_{ENABLED,URL,ALLOW,REFRESH,MAX_STALENESS}. IPv6 is not matched (a v6 client is still covered by fail2ban / the honeypot). - observability: gateway_blocklist_blocked_total + entries/age gauges; a Grafana alert warns before the feed is dropped; service-overview panels. - deploy: compose env + write-prod-env.sh + prod-deploy/rollback wiring (opt-in via PROD_ vars). - docs (ARCHITECTURE, deploy/README); unit tests (match, allowlist, IPv6 skip, parser, fault-tolerance) + a 403 abuse-guard integration test.