Commit Graph

6 Commits

Author SHA1 Message Date
Jack Levy
9633b4dcb8 feat: v1.0.0 — UX polish, security hardening, code quality
UI/UX:
- Bill detail page tab UI (Analysis / Timeline / Votes / Notes)
- Topic tag pills on bill detail and listing pages — filtered to known
  topics, clickable, properly labelled via shared lib/topics.ts
- Notes panel always-open in Notes tab; sign-in prompt for guests
- Collapsible sidebar with icon-only mode and localStorage persistence
- Bills page defaults to has-text filter enabled
- Follow mode dropdown transparency fix
- Favicon (Landmark icon, blue background)

Security:
- Fernet encryption for ntfy passwords at rest (app/core/crypto.py)
- Separate ENCRYPTION_SECRET_KEY env var; falls back to JWT derivation
- ntfy_password no longer returned in GET response — replaced with
  ntfy_password_set: bool; NotificationSettingsUpdate type for writes
- JWT_SECRET_KEY fail-fast on startup if using default placeholder
- get_optional_user catches (JWTError, ValueError) only, not Exception

Bug fixes & code quality:
- Dashboard N+1 topic query replaced with single OR query
- notification_utils.py topic follower N+1 replaced with batch query
- Note query in bill detail page gated on token (enabled: !!token)
- search.py max_length=500 guard against oversized queries
- CollectionCreate.validate_name wired up with @field_validator
- LLM_RATE_LIMIT_RPM default raised from 10 to 50

Authored by: Jack Levy
2026-03-15 01:10:31 -04:00
Jack Levy
247a874c8d feat: Discovery alert filters + notification reasons (v0.9.6)
- Add 4th "Discovery" tab in Alert Filters for member/topic follow notifications,
  with per-source enable toggle, independent event-type filters, and per-entity
  mute chips (mute specific members/topics without unfollowing)
- Enrich notification event payloads with follow_mode, matched_member_name,
  matched_member_id, and matched_topic so each event knows why it was created
- Dispatcher branches on payload.source for member_follow/topic_follow events,
  checking source-level enabled toggle, per-event-type filters, and muted_ids/muted_tags
- Add _build_reason helper; ntfy messages append a "why" line (📌/👤/🏷)
- EventRow in notification history shows a small italic reason line
- Update How It Works: fix stale member/topic paragraph, add Discovery alerts item

Authored-by: Jack Levy
2026-03-14 13:21:48 -04:00
Jack Levy
a39ae4ccba feat: granular per-mode alert filters (v0.9.3)
Replace coarse milestone/referral suppression with 8 named action
categories (vote, presidential, committee_report, calendar, procedural,
referral, new_document, new_amendment), each independently togglable
per follow mode (Follow / Pocket Veto / Pocket Boost).

- notification_utils: categorize_action() replaces is_milestone_action /
  is_referral_action; _build_payload stores action_category in payload
- congress_poller: use categorize_action() in _update_bill_if_changed
- notification_dispatcher: _should_dispatch() checks per-mode filter dict
  from notification_prefs; follow mode looked up before filter check
- schemas + api: alert_filters (nested dict) wired through settings
  GET/PUT endpoints; no DB migration required
- frontend: tabbed Alert Filters section (Follow / Pocket Veto /
  Pocket Boost), each with independent 8-toggle filter set, milestone
  parent checkbox (indeterminate-aware), Load defaults button, and
  per-tab Save button

Authored-By: Jack Levy
2026-03-02 19:05:24 -05:00
Jack Levy
48771287d3 feat: ZIP → rep lookup, member page redesign, letter improvements
ZIP lookup (GET /api/members/by-zip/{zip}):
- Two-step geocoding: Nominatim (ZIP → lat/lng) then Census TIGERweb
  Legislative identify (lat/lng → congressional district via GEOID)
- Handles at-large states (AK, DE, MT, ND, SD, VT, WY)
- Added rep_lookup health check to admin External API Health panel

congress_api.py fixes:
- parse_member_from_api: normalize state full name → 2-letter code
  (Congress.gov returns "Florida", DB expects "FL")
- parse_member_from_api: read district from top-level data field,
  not current_term (district is not inside the term object)

Celery beat: schedule sync_members daily at 1 AM UTC so chamber,
district, and contact info stay current without manual triggering

Members page redesign: photo avatars, party/state/chamber chips,
phone + website links, ZIP lookup form to find your reps

Draft letter improvements: pass rep_name from ZIP lookup so letter
opens with "Dear Representative Franklin," instead of generic salutation;
add has_document filter to bills list endpoint

UX additions: HelpTip component, How It Works page, "How it works"
sidebar nav link, collections page description copy

Authored-By: Jack Levy
2026-03-02 15:47:46 -05:00
Jack Levy
1e37c99599 feat(phase2): fact/inference labeling, change-driven alerts, admin cleanup
- Add label: cited_fact | inference to LLM brief schema (all 4 providers)
- Inferred badge in AIBriefCard for inference-labeled points
- backfill_brief_labels Celery task: classifies existing cited points in-place
- POST /api/admin/backfill-labels + unlabeled_briefs stat counter
- Expand milestone keywords: markup, conference
- Add is_referral_action() for committee referrals (referred to)
- Two-tier milestone notifications: progress tier (all follow modes) and
  referral tier (pocket_veto/boost only, neutral suppressed)
- Topic followers now receive bill_updated milestone notifications via
  latest brief topic_tags lookup in _update_bill_if_changed()
- Admin Manual Controls: collapsible Maintenance section for backfill tasks
- Update ARCHITECTURE.md and roadmap for Phase 2 completion

Co-Authored-By: Jack Levy
2026-03-01 17:34:45 -05:00
Jack Levy
73881b2404 feat(notifications): follow modes, milestone alerts, notification enhancements
Follow Modes (neutral / pocket_veto / pocket_boost):
- Alembic migration 0013 adds follow_mode column to follows table
- FollowButton rewritten as mode-aware dropdown for bills; simple toggle for members/topics
- PATCH /api/follows/{id}/mode endpoint with validation
- Dispatcher filters pocket_veto follows (suppress new_document/new_amendment events)
- Dispatcher adds ntfy Actions header for pocket_boost follows

Change-driven (milestone) Alerts:
- New notification_utils.py with shared emit helpers and 30-min dedup
- congress_poller emits bill_updated events on milestone action text
- llm_processor replaced with shared emit util (also notifies member/topic followers)

Notification Enhancements:
- ntfy priority levels (high for bill_updated, default for others)
- Quiet hours (UTC): dispatcher holds events outside allowed window
- Digest mode (daily/weekly): send_notification_digest Celery beat task
- Notification history endpoint + Recent Alerts UI section
- Enriched following page (bill titles, member photos/details via sub-components)
- Follow mode test buttons in admin settings panel

Infrastructure:
- nginx: switch upstream blocks to set $variable proxy_pass so Docker DNS
  re-resolves upstream IPs after container rebuilds (valid=10s)
- TROUBLESHOOTING.md documenting common Docker/nginx/postgres gotchas

Authored-By: Jack Levy
2026-03-01 15:09:13 -05:00