Decisions, lessons, blockers. Append-only. Update as we go.
Decided
git3.techno-world.net/lrosales/broad-announce (private).companies.fcm_shared).info | warning | critical | inminent_colapse.
Only inminent_colapse bypasses quiet hours.(source_id, dedupe_key), attach
dedupe_count so user sees "×N in 60s" not N pushes.Open (was) → Resolved 2026-06-13
individuals row + generates one-time invite code;
user runs /start <invite_code> in the Telegram bot; bot
matches the code, links telegram_chat_id to the
pre-existing individual, and burns the code. Stricter path:
prevents drive-by bot self-registration, keeps
individuals auditable.title/body strings (or use the locale on the
subscription to key into their own lookup table before
calling our API). Alert schema carries locale and
title/body already-resolved. We can add a translation
layer in v2 if customers ask.Lessons (already)
alerts.<company_id> is fine; alerts.<company_id>.<source_id>
would let us scale router consumer groups per source. Locked
in §6 of ARCHITECTURE.md.2026-06-13 — added gRPC ingest (option a)
buf generate build step.StreamAlerts(Alert) → Ack carries the same dedupe_count
contract as HTTP/WS/MQTT.proto/broadannounce/v1/ingest.proto; server
stub in internal/grpcserver/, reusable client in
internal/grpcclient/. Auth = API key in metadata + optional
mTLS. Per-stream rate limit + 256 in-flight cap = natural
backpressure.2026-06-13 — M10 split: option C
loadgen/ tool is the new home for that.2026-06-13 — three open questions resolved
testfakes/). M10 must not burn 50k FCM credits.deliverd binary in the bench profile, not a NATS
subject drop. More realistic: we exercise the real broker +
router + the message shape deliverd would consume.loadgen ships as a single Docker image with all
four binaries; entrypoint picks one via the image's
command: field in the compose / k8s spec.2026-06-13 — Source protection (throttling) is in
rate_limit_per_sec, max_payload_bytes,
max_concurrent_connections, quarantine_*).2026-06-13 — M0 shipped (12 commits, 2888 LoC)
What landed:
cmd/{ingestd,routerd,deliverd,admind}/ — four Go service mainscmd/ingestd/http.go — HTTP POST handler implementing
SPEC §22 layers 1, 3, 4, 5 + Stripe-style HMAC authinternal/alert — Alert v1 type + Validate() (183 LoC + 103
LoC tests)internal/broker — NATS JetStream wrapper, three streams
(ALERTS/DELIVERIES/DLQ) auto-createdinternal/dedupe — 60s SET NX EX + INCR (Redis-required tests
pass against a host-local Redis)internal/ratelimit — per-second INCR bucket (Redis-required
tests pass)internal/observability — slog + Prometheus registry, the
IngestdMetrics struct matches SPEC §22 metric namesinternal/httpserver — shared /health + /metrics scaffoldinternal/config — env-driven Common + Ingestdloadgen/cmd/http/ — loadgen-http with --mode normal,
HMAC signing, 70/25/4/1 severity mix, dedupe-pct knobloadgen/go.mod — separate module per SPEC §21, replace
directive points at the parent moduledocker-compose.yml + Dockerfile — single-host stack, all
5 binaries in one imageM0_VERIFICATION.md — 8-step smoke testdeploy/prometheus/prometheus.yml — scrapes all 5 servicesWhat's NOT in M0 (and not supposed to be):
Module path: git3.techno-world.net/lrosales/broad-announce.
Loadgen module path: git3.techno-world.net/lrosales/broad-announce/loadgen.
All pushed: 7cd922c..49b2dba on master.