Files
simonandClaude Opus 5.5 456f9816f4 Redesign the web app from a written design concept
Design concept and design system in docs/design/: principles (evidence
first, neutral, fair to the people shown, plain language, time as a
dimension, accessible and private), information architecture, core
patterns and a concept for every page; tokens with checked contrast,
component catalogue, content and accessibility rules.

web:
- neutral ink-indigo accent instead of flag red; party colours only as
  small markers next to the name; light/dark theme with a switcher
- stylesheets split into tokens, base, layout, components, print
- new header (search, filter count, language, theme, mobile menu) and
  footer; breadcrumbs, page headers, tabs with counts, filter bars that
  collapse on phones, pagination, notices and empty states
- claim cards with source meter, legal stage, innocence notice inside
  the card and a permalink; claim pages with citation (/angaben/{id})
- profiles with role timeline and key figures; party and organisation
  dashboards; vote list with position chips; calendar agenda on phones;
  tables that stack into cards; loading and error pages; favicon

backend:
- GET /api/v1/claims/{id} and MCP tool get_claim for permalinks
- parties list: evaluate person_status once instead of per party
  (30 s -> 1 s on the sample database, identical result)
- parliament calendar: HTML-decode titles ("84. Sitzung")

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 22:21:44 +01:00

100 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Politrack 🇦🇹
**What Austrian politicians do, with every claim linked to its sources.**
Politrack collects publicly available information about Austrian politicians and parties, from the EU and
federal level down to municipalities: mandates and functions, how factions and individuals voted, party
donations and finances, public contracts, government advertising, side jobs, lobby meetings, speeches,
questions and public posts, media reports, trips and meetings, and legal proceedings. Every fact is a
**claim** with one or more pieces of **evidence** (links), so readers can verify it and decide which
sources they trust.
* 🇩🇪 German UI by default (`/`), English at `/en`
* Users choose **which sources they trust** and **which topics they care about**
* Pages per **person**, **party** and **organisation**, a **money** explorer, **calendar** and **timeline**
* **Votes**: faction votes for every bill, **individual roll-call votes** with a dissent flag, and
"say vs. vote" (did the person speak on the item?)
* **Follow the money**: donations, party funding, loans and holdings, public contracts, government ads,
political ads – and the organisations a politician is connected to
* **Corroboration**: the same fact from independent sources becomes one claim with several sources
* **Former politicians**: what they are doing now
* Legal matters always carry the procedural stage and *"Es gilt die Unschuldsvermutung"*; automatically
detected ones need human review first
* **Agent-ready**: MCP server, typed REST/OpenAPI, read-only SQL role, pgvector chunks for RAG
* Runs as Docker containers on a homelab (Unraid); workers scale horizontally
* **Legal by construction**: robots.txt, rate limits, TDM reservations and storage rules are enforced in
the framework, not left to each scraper
## Documentation
| Doc | Contents |
|---|---|
| [docs/architecture/01-design-from-scratch.md](docs/architecture/01-design-from-scratch.md) | The architecture: quality goals, data model, adapter framework, serving, testing, guard-rails |
| [docs/architecture/02-comparison-and-decisions.md](docs/architecture/02-comparison-and-decisions.md) | Why it is built this way (decision records) |
| [docs/design/README.md](docs/design/README.md) | Design concept: principles, information architecture, core patterns, every page |
| [docs/design/design-system.md](docs/design/design-system.md) | Design system: tokens, components, content and accessibility rules |
| [docs/data-model.md](docs/data-model.md) | Tables, claim types, identifier schemes, views |
| [docs/sources.md](docs/sources.md) | Every source with access method, licence/ToS assessment, and what we deliberately don't collect (incl. Telegram/WhatsApp/Signal) |
| [docs/legal.md](docs/legal.md) | Copyright/TDM, GDPR, MedienG §7b (presumption of innocence), defamation |
| [docs/deployment-unraid.md](docs/deployment-unraid.md) | Step-by-step Unraid setup, backups, exposure |
| [docs/investigative-data.md](docs/investigative-data.md) | Data points for investigative work and the correlations they enable |
| [docs/market-research.md](docs/market-research.md) | Existing services and the gaps Politrack fills |
| [docs/roadmap.md](docs/roadmap.md) | What's done and what comes next |
| [CONTRIBUTING.md](CONTRIBUTING.md) | How to contribute: adapters, enrichers, API, frontend, tests |
## Quick start
```bash
cp .env.example .env # set passwords and a real contact address for the crawler
docker compose up -d --build # db, migrate, api, web, mcp, workers
docker compose exec api politrack sources list # all adapters/enrichers and their schedules
docker compose exec api politrack run parlament.persons # members, mandates, side jobs, speeches
docker compose exec api politrack run wikidata.politicians # state/local offices, parties, careers, social handles
docker compose exec api politrack run parlament.items # votes, roll calls, immunity, questions, hearings
docker compose exec api politrack run rechnungshof.donations # party donations
docker compose exec api politrack enrich # linking, events, legal detection, corroboration
docker compose exec api politrack review # approve/reject automatically detected legal matters
docker compose exec api politrack status # recent runs with stats and errors
```
The workers then keep everything fresh on their own: each adapter declares its cron schedule and queue.
* Web: http://localhost:3000
* API docs: http://localhost:8000/api/docs
* MCP (streamable HTTP): http://localhost:8001/mcp
* SQL (read-only): `postgresql://politrack_reader:<POLITRACK_READER_PASSWORD>@localhost:5433/politrack`
## Repository layout
```
backend/ Python package `politrack` (one image for API, workers, MCP)
migrations/ SQL schema (commented for agents) + seed (chambers, parties, topics)
config/ feeds.yaml, social_accounts.yaml, ip_ranges.yaml, meta_pages.yaml
politrack/
core/ the framework: SourceSpec, Adapter/Enricher, Request/Response, Fetcher
(policy + archive), records, Resolver, Loader, registry, runner
sources/ one module per publisher (parlament/, wikidata, rechnungshof, bundesregierung,
procurement, rtr, eu, wikipedia, political_ads, justiz, news, gdelt, social)
enrich/ linker, events, legal, topics, maintenance, corroborate, embed, curated
queries/ read queries shared by API and MCP
api/ FastAPI app + Pydantic response models
mcp_server.py MCP tools for agents
worker.py Procrastinate tasks generated from the registry
tests/ unit tests + golden fixtures
web/ Next.js 15 + next-intl frontend (types generated from the API)
docs/
docker-compose.yml
```
## Contributing
Adding a source is one module with a `SourceSpec`, `start()` and a pure `parse()` – see
[docs/contributing/adapters.md](docs/contributing/adapters.md) and [CONTRIBUTING.md](CONTRIBUTING.md).
## Data licence & attribution
Data from the Austrian Parliament: © Parlamentsdirektion, CC BY 4.0. Wikidata: CC0. Rechnungshof,
Bundeskanzleramt and WKStA publications are official works (§7 UrhG). Open government data from
data.gv.at and RTR under their respective licences (mostly CC BY 4.0). Media content is linked, not
reproduced.