Mirror cscli alerts list: new /alerts endpoint hits LAPI machine auth
with since/ip/scenario/origin filters, renders ID, scope:value, reason,
country, AS, events, decisions, created_at.
Decisions table gains a Created column derived from until - duration
(LAPI does not expose created_at on /v1/decisions). Both views format
timestamps locally and append a relative "x ago" via Intl.RelativeTimeFormat,
refreshed every 30s on the decisions view.
Two new performance + UX wins:
- Server: /decisions now accepts reason (scenarios_containing), origin
(origins), and limit. Default 200, max 2000. Header shows current count
and warns when at the cap.
- Client: a "quick filter rows" input does substring match across all
visible columns instantly with no server round-trip. Useful when the
server-side result is small enough to scroll but you still want to find
one scenario fast.
- Bulk select-all now toggles only currently visible rows so you can
filter then bulk-unban.
Drops inline onclick handlers in favor of delegated change listeners to
keep per-row cost low at large limits.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds per-row checkboxes, a select-all toggle, a live "N selected" counter,
and an /unban-bulk endpoint that DELETEs each chosen decision id. Single-row
Unban buttons still work via hx-vals so they don't accidentally submit the
bulk form.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Flask + htmx mini-app to list and delete CrowdSec decisions from a browser,
gated behind Authentik. Talks to host LAPI via host.docker.internal:8080
using machine JWT auth (bouncer X-Api-Key is read-only).
Gitea Actions CI/CD on push to main: runner rebuilds image and brings the
stack up via docker compose on the host (same pattern as flight-radar).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>