Skip to content

About

Full-stack congressional accountability app: Rust Axum API and Next.js UI over legislators, bills, trades, finance

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Congress-Tracker

CongressTracker is a full-stack congressional accountability app. It tracks Congress as a political-economic system: legislators, bills, committees, lobbying filings, elections, campaign finance, stock disclosures where available, portfolio-style disclosure summaries, influence networks, and global search. The backend is Rust on Axum backed by PostgreSQL, and the frontend is Next.js. The records that matter live in a dozen separate government systems, so the app pulls them into one normalized database and cross-references them. It never presents mock data as real data: missing source keys or empty ingests render as honest empty and setup states.

Status

Active. Under steady development as of August 2026.

Features

  • Browse legislators with terms, committees, and identifiers from the unitedstates/congress-legislators dataset
  • Follow bills with sponsors, actions, and official source URLs from the Congress.gov API
  • Track member stock trades from House Clerk periodic transaction reports, with portfolio summaries and net-worth pages
  • Flag potential conflicts of interest by matching traded securities against committee jurisdictions
  • Read lobbying filings, clients, and issue codes from the Senate lobbying disclosure API
  • Explore campaign finance: FEC receipts, committees, leadership PACs, and outside spending from FEC bulk files and OpenFEC
  • Compare election candidates in dossier pages built from FEC data
  • Map influence networks that link members, organizations, and financial records
  • Search every entity from one global search endpoint
  • Show per-source coverage and freshness so missing data is always visible

Screenshots

Member trades page listing canonical stock disclosure records with committee oversight conflict flags

Stack

Layer Choice
Backend Rust (stable toolchain), Axum, Tokio, SQLx
Database PostgreSQL 16, schema managed by versioned migrations in intel_backend
Frontend Next.js 14, React 18, TypeScript, Tailwind CSS, Radix UI
Charts Recharts, D3
Ingest clients congress_api, openfec_api, lobbying_client, civiq_client, capitoltrades_api (legacy)
Analysis ticker_resolver, trade_enricher, committee_detector, anomaly_scorer
CI GitHub Actions

Requirements

  • Linux or macOS. The deployment target is Linux with systemd.
  • Rust stable toolchain
  • Node.js 20 with pnpm 9
  • PostgreSQL 16
  • Free API keys: Congress.gov and OpenFEC (both issue through api.data.gov), plus a Senate LDA registration for lobbying data

Install

From a clone of this repository:

cp .env.example .env
# Edit .env and fill in CONGRESS_GOV_API_KEY, OPENFEC_API_KEY, and SENATE_LDA_API_KEY
psql -c "CREATE USER congress_tracker WITH PASSWORD 'congress_tracker';"
psql -c "CREATE DATABASE congress_tracker OWNER congress_tracker;"
cd frontend && pnpm install && cd ..

Configuration

Backend variables load from .env at the repo root. .env.example documents every key with placeholders.

Variable Used by Meaning Default
DATABASE_URL intel_backend, intel_worker Postgres connection string required
CONGRESS_GOV_API_KEY congress_api Bills, members, votes, amendments required for ingest
OPENFEC_API_KEY FEC ingest Receipts, committees, outside spending required for FEC ingest
SENATE_LDA_API_KEY Lobbying ingest Filings, clients, registrants optional; without it the source reports auth_missing
PORT intel_backend API listen port 4020
INTEL_CACHE_TTL_SECONDS intel_backend API response cache TTL in seconds 300
NEXT_PUBLIC_BACKEND_URL frontend Backend base URL at build and dev time http://localhost:4020
SENATE_EFD_ACCEPT_TERMS intel_worker Set to 1 only after accepting the Senate eFD terms; otherwise Senate discovery is skipped unset
WORKER_STORAGE_DIR intel_worker Storage root for FEC archives and Senate eFD downloads ./worker_storage under the backend working directory
LOG_DIR backend logging Log directory ./log

Worker diagnostics accept further knobs (FEC_CYCLES, FEC_ARCHIVE_DIR, FEC_MIN_FREE_BYTES, WORKER_RESOURCE_PROFILE, INGEST_CONTINUE_ON_ERROR, JOB_LEASE_RENEW_SECONDS, SEC_USER_AGENT); defaults live next to their use sites in backend/crates/intel_backend/src.

Run

./run_all.sh

The script checks that Postgres is reachable, frees ports 3000 and 4020, then starts the API on http://localhost:4020, the ingest worker, and the Next.js dev server on http://localhost:3000. The worker owns normal freshness for members, bills, votes, FEC, House disclosures, and derived relationships. Manual ingest subcommands remain diagnostics and targeted repair tools.

Examples

curl http://127.0.0.1:4020/api/health
curl http://127.0.0.1:4020/api/sources/status
curl 'http://127.0.0.1:4020/api/fec/receipts?cycle=2026&page=1&per_page=10'
curl 'http://127.0.0.1:4020/api/search?q=health&limit=5'

Architecture

Browser
  |
  v
Next.js frontend (:3000)
  | REST
  v
intel_backend (Axum API, :4020)  <-->  PostgreSQL 16
  ^
  |
intel_worker (scheduled ingest and freshness)
  |
  +- Congress.gov API (bills, members, votes, amendments)
  +- unitedstates/congress-legislators (members, committees)
  +- FEC bulk files + OpenFEC API (receipts, committees, spending)
  +- Senate LDA API (lobbying filings)
  +- House Clerk disclosure indexes and PDFs
  +- Internet Archive (PDF preservation fallback)
  +- Senate eFD (terms-gated discovery, incomplete)

Backend crates under backend/crates/:

  • intel_backend: canonical HTTP API, migrations, read models
  • intel_worker: scheduled ingestion and freshness jobs
  • congress_api, openfec_api, lobbying_client: source API clients
  • civiq_client: client for CIV.IQ, a no-key alternative source for member, vote, and bill data
  • capitoltrades_api: legacy CapitolTrades adapter kept as a compatibility boundary
  • ticker_resolver, trade_enricher: ticker to sector and industry resolution, then trade enrichment
  • committee_detector: committee jurisdiction conflict flags
  • anomaly_scorer: weighted anomaly scoring for trading activity
  • backend_server: older backend kept for reference; new page features target intel_backend

The worker pulls official sources into normalized tables through versioned migrations. The API serves only canonical relational rows. Pages render missing records as unavailable; they never infer content from search or fixtures.

Testing

scripts/self-test runs the full local gate: plan lint, backend format, clippy, check, and deterministic tests, then the frontend pnpm verify (unit tests, typecheck, ESLint, oxlint, build).

CI (.github/workflows/ci.yml) runs the same commands against Postgres 16 and adds database-backed contract suites:

cd backend
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace --exclude civiq_client --lib --bins
cargo test -p civiq_client test_query_builder
cd ../frontend
pnpm test:unit && pnpm typecheck && pnpm lint && pnpm lint:ox:ci && pnpm build

Migration and pipeline suites need a reachable DATABASE_URL:

scripts/verify-migrations
cd backend && cargo test -p intel_backend --test fec_bulk_pipeline_test
cd backend && cargo test -p intel_backend --test influence_financials_test

Integration tests skip themselves when DATABASE_URL is unset, so the deterministic suite runs anywhere.

Deploy

The app runs on a single Linux host. cd backend && make build produces release binaries. The user units in deploy/systemd/ run the backend, frontend, and Caddy (congress-backend.service, congress-frontend.service, congress-caddy.service), and congress-backup.timer schedules database backups through scripts/db-backup. Units load secrets from the repo-root .env via EnvironmentFile; no secrets live in unit files or git. The Caddyfile in deploy/caddy/ handles TLS and reverse proxying.

Known limits

  • House PTR ingestion and annual asset and liability parsing are live; income, gifts, and positions parsing still need production coverage.
  • Scanned-document OCR is implemented, but representative accuracy and failure recovery need live verification.
  • Senate eFD discovery is staged and terms-gated; download, versioning, parsing, and member normalization are incomplete.
  • FEC receipt browsing works, but the configured three-cycle window is not complete until every required cycle reaches a terminal source state.
  • Member vote and sponsorship pages read only canonical relational records; missing rows show as unavailable.
  • Voteview and Wikidata are registered sources but are not required for the core dataset.
  • The visualizations route sits outside the required tab set and awaits a cleanup pass.

Credits

CREDITS.md documents every adapted open-source project, including poli-ticker, yfinance, FinanceDatabase, lobbyR, lobby, and CongressWatch. Data comes from the unitedstates/congress-legislators dataset, the Congress.gov API, FEC bulk files and OpenFEC, the Senate LDA API, House Clerk disclosure indexes, and the Internet Archive.

License

MIT.

About

Full-stack congressional accountability app: Rust Axum API and Next.js UI over legislators, bills, trades, finance

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages