Files

1.8 KiB

Why

The product needs cost protection and the 2014 paid-gating model, but a payment gateway (Stripe) is explicitly deferred. This change delivers the mechanism without the gateway: alerts only fire for tags whose linked order is paid (the 2014 is_paid/late_payment suspension), plus hard per-tag daily alert caps and a per-IP rate limit — all pure app logic on the existing schema. Stripe/Paddle plugs in later (Phase 5 full) by just setting orders.status.

What Changes

  • Paid-gating (sms-alerting): if a tag has a linked order (order_id set) and that order's status is not paid, scans are recorded but no SMS is sent (owner sees "payments suspended" behaviour). No order yet → alerts allowed (transitional until sales flow exists).
  • Per-tag daily alert cap: a tag can alert at most N times per 24 h (configurable constant, e.g. 5) — protects SMS cost against heavy repeated scanning.
  • Per-IP rate limit: a scanner IP can trigger at most M alerts per hour (configurable) — guards against automation (works alongside the existing fingerprint block).
  • Admin visibility: TagResource already links orders; the order status drives the gating — no new admin UI needed.

Capabilities

New Capabilities

  • alert-limits: per-tag daily cap + per-IP hourly rate limit.

Modified Capabilities

  • sms-alerting: ADDED — paid-order gating (no order = allowed, transitional; non-paid order = blocked).
  • database: no schema change required (orders.status + tag.order_id already exist).

Impact

  • Go: internal/handlers/scan.go (shouldAlert gains paid-gating + cap checks), internal/db/queries.sql (2 new count queries), regenerated sqlc.
  • Constants: maxAlertsPerTagDay, maxAlertsPerIPHour (env-overridable via ALERT_* vars).
  • No external services; no Stripe; no schema migration.