v1.1.0 Phase 4: public-link console, rate limiting, retention, config I/O #97

Merged
claude-bot merged 1 commit from feat/v1.1.0-phase4a-publiclinks into main 2026-07-18 18:17:16 +00:00
Contributor

The final v1.1.0 slice — public-surface ops and data lifecycle.

Public surface

  • #7 — Public Link Admin Console: admin-only GET /api/public-tokens list endpoint (unions NWS-alert and SPC-outlook target types, with token/text/type/status/window filters) and a /public-links console page — per-row status, copy (resolved outbound URL via SHORT→PUBLIC→APP preference), open, and revoke (reuses the existing admin revoke endpoint). Admin nav link added.
  • #10/p/* rate limiting: in-process sliding-window limiter on /p/{token}, keyed by client IP (X-Forwarded-For aware), returning 429 + Retry-After. Configurable; per-process (a proxy/Redis limiter is noted for multi-instance).
  • #11 — Default SMS public links: SMS alerts include the public details link by default when public pages are enabled (SMS_DEFAULT_PUBLIC_LINKS=true), still subject to the SMS segment budget.

Data lifecycle

  • #52 — Data-retention cleanup: a daily job prunes cleared sent_alerts (90d), AI records (30d), SPC pages past retained_until+30d, snapshots (180d), and disabled public tokens (30d) — deliberately long defaults aligned with the v2.0.0 Historical Explorer (#22). MCD SentAlert rows now get a real 6h expiry (they previously never cleared/pruned), and SPC radar cache files are pruned by age (7d). Each table cleans in its own session/try-except; windows documented in README.
  • #79 — Config export/import: admin GET /api/config/export (locations, channels, subscriptions as JSON, full config for a complete DR restore — flagged as containing secrets) and POST /api/config/import (natural-key dedup, additive by default, replace flag gated, triggers NWS re-resolution for new locations), with a Settings-page backup/restore UI.

Config (added to .env.example)

SMS_DEFAULT_PUBLIC_LINKS, PUBLIC_RATE_LIMIT_ENABLED/REQUESTS/WINDOW_SECONDS, and six RETENTION_* / RADAR_CACHE_RETENTION_DAYS windows — all with safe defaults.

Testing

Full suite green on the dev server: 489 passed (38 new tests). Fixed one test-isolation issue: the rate-limiter dependency now reads settings via getattr (a v1.0.3 test patches get_settings with a partial stub) and is reset per-test via an autouse fixture.

Notes

  • No "public-location token" target type exists in the codebase — the console covers the two real types (NWS alert, SPC outlook); a future type slots in with one more outerjoin.
  • The limiter covers /p/* (the enumeration surface); the public SSE stream under /api/locations/* could optionally get the same guard later.
  • Config export includes channel secrets so restores are complete — it's admin-only and labeled as sensitive.

Closes #7, #10, #11, #52, #79

🤖 Generated with Claude Code

The final v1.1.0 slice — public-surface ops and data lifecycle. ## Public surface - **#7 — Public Link Admin Console**: admin-only `GET /api/public-tokens` list endpoint (unions NWS-alert and SPC-outlook target types, with token/text/type/status/window filters) and a `/public-links` console page — per-row status, copy (resolved outbound URL via SHORT→PUBLIC→APP preference), open, and revoke (reuses the existing admin revoke endpoint). Admin nav link added. - **#10 — `/p/*` rate limiting**: in-process sliding-window limiter on `/p/{token}`, keyed by client IP (X-Forwarded-For aware), returning 429 + `Retry-After`. Configurable; per-process (a proxy/Redis limiter is noted for multi-instance). - **#11 — Default SMS public links**: SMS alerts include the public details link by default when public pages are enabled (`SMS_DEFAULT_PUBLIC_LINKS=true`), still subject to the SMS segment budget. ## Data lifecycle - **#52 — Data-retention cleanup**: a daily job prunes cleared `sent_alerts` (90d), AI records (30d), SPC pages past `retained_until`+30d, snapshots (180d), and disabled public tokens (30d) — deliberately **long** defaults aligned with the v2.0.0 Historical Explorer (#22). MCD `SentAlert` rows now get a real 6h expiry (they previously never cleared/pruned), and SPC radar cache files are pruned by age (7d). Each table cleans in its own session/try-except; windows documented in README. - **#79 — Config export/import**: admin `GET /api/config/export` (locations, channels, subscriptions as JSON, full config for a complete DR restore — flagged as containing secrets) and `POST /api/config/import` (natural-key dedup, additive by default, `replace` flag gated, triggers NWS re-resolution for new locations), with a Settings-page backup/restore UI. ## Config (added to `.env.example`) `SMS_DEFAULT_PUBLIC_LINKS`, `PUBLIC_RATE_LIMIT_ENABLED/REQUESTS/WINDOW_SECONDS`, and six `RETENTION_*` / `RADAR_CACHE_RETENTION_DAYS` windows — all with safe defaults. ## Testing Full suite green on the dev server: **489 passed** (38 new tests). Fixed one test-isolation issue: the rate-limiter dependency now reads settings via `getattr` (a v1.0.3 test patches `get_settings` with a partial stub) and is reset per-test via an autouse fixture. ## Notes - No "public-location token" target type exists in the codebase — the console covers the two real types (NWS alert, SPC outlook); a future type slots in with one more outerjoin. - The limiter covers `/p/*` (the enumeration surface); the public SSE stream under `/api/locations/*` could optionally get the same guard later. - Config export includes channel secrets so restores are complete — it's admin-only and labeled as sensitive. Closes #7, #10, #11, #52, #79 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add public-link console, /p/* rate limiting, SMS links, retention, config I/O
All checks were successful
CI / test (pull_request) Successful in 7m16s
83edb752a6
Public surface (#7, #10, #11):
- Public Link Admin Console: an admin-only GET /api/public-tokens list endpoint
  (across NWS-alert and SPC-outlook target types, with filters) and a /public-links
  console page with copy/open/revoke per row (reuses the existing revoke endpoint).
- App-native rate limiting on the public /p/{token} routes: in-process sliding
  window keyed by client IP (X-Forwarded-For aware), 429 + Retry-After, configurable.
- SMS alerts include the public details link by default when public pages are
  enabled (SMS_DEFAULT_PUBLIC_LINKS), still subject to the segment budget.

Data lifecycle (#52, #79):
- Data-retention cleanup: a daily job prunes cleared sent_alerts, AI records,
  SPC pages past retained_until, old snapshots, and disabled public tokens with
  deliberately long, config-backed windows (aligned with the v2.0.0 explorer #22);
  MCD SentAlert rows now get a real expiry so they clear/prune; SPC radar cache
  files are pruned by age.
- Config export/import: admin GET /api/config/export (locations, channels,
  subscriptions as JSON) and POST /api/config/import (natural-key dedup, additive
  by default, replace flag gated), with a Settings-page backup/restore UI.

Rate limiter reads settings defensively (getattr) and is reset per-test to keep
suite isolation. Full suite green on the dev server: 489 passed.

Closes #7, #10, #11, #52, #79

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude-bot deleted branch feat/v1.1.0-phase4a-publiclinks 2026-07-18 18:17:16 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot!97
No description provided.