Architecture map — polit-media-radar (er)🔗
Living Architecture Map — pilot. This page is the single entry point to the visual architecture of the project: the modules, how they depend on each other, and which module writes which table.
This map has two layers (Living Documentation terminology):
- Reference layer (generated, cannot lie). Produced mechanically from the code and the live database — it drifts only when the code/schema drift, and a drift gate catches that. → module graph, ER: legacy, ER: SocialScan, ER: context bridge.
- Evergreen layer (curated, holds intent). Written by a human/agent to explain why — the seams and this overview. → seams: module → table, this file.
Single source of truth + reference. Generated facts are never re-typed into prose here; they are linked. If a number or an edge matters, follow the link to the diagram that owns it.
1. Introduction & Goals🔗
polit-media-radar monitors political-media activity (Telegram, VK) for a set of tracked candidates: it ingests posts ("articles"), comments, reactions and forwards, then layers SocialScan pulls and LLM classification on top to produce the weekly "narodnaya" analytics reports. (Product context: concept-doc-2026-05-06.md; current-state audit: audit-2026-05-19.md — both in docs/architecture/, outside this showcase build.)
Goal of this map: let a reader see the architecture at a glance — modules, modularity, and the seams between modules and the database — without holding it all in their head or reading the code.
2. Building Block View🔗
The codebase is 12 top-level packages under polit_media_radar (import root src/). The dependency graph — generated by tach from real imports — is in diagrams/modules.md. Read it there; the shape in one sentence: cli is the composition root that wires everything; domain, security, config are leaf/utility layers; ingestion and reports sit on top of persistence. There is one honest cli ↔ scheduler cycle.
3. Runtime & Deployment View🔗
The system runs as two Docker Compose services — postgres (schema radar) and app — plus scheduled jobs (Forgejo/GitHub Actions). The ingestion pipeline (ingestion) pulls sources, persists through the repository layer (persistence), and the reporting modules (reports, services) read back to build the weekly report. The database is a single PostgreSQL 16 container (C4 nomenclature: the DB is a Container; the ER diagrams below detail it).
4. Data View — the database container🔗
The 34 base tables of schema radar split into two bounded contexts, drawn separately so neither becomes an unreadable tangle:
- Legacy context (
radar.*, 13 tables) — the original ingestion model. → diagrams/db/legacy.md - SocialScan context (
radar.ss_*+weekly_corpus_summary, 21 tables) — the analytics overlay. → diagrams/db/socialscan.md - Context bridge — the foreign keys that cross from SocialScan back into the legacy spine. → diagrams/db/context-bridge.md
How SocialScan attaches to the spine (the split would otherwise hide this): two legacy tables — candidates (the actor) and fetch_runs (one ingestion run) — are the shared spine. ss_snapshots anchors a SocialScan pull to an ingestion run via source_run_id → fetch_runs.id; the per-actor SocialScan leaf tables carry candidate_id → candidates.id directly. Full edge list: context-bridge.md.
5. Cross-cutting Concepts🔗
- The spine.
candidatesandfetch_runsare referenced from both contexts; they are the integration backbone. They appear (styled) in both ER diagrams by design. - Writer-pending skeletons. Four repositories exist as
NotImplementedErrorskeletons — their tables are in the schema but nothing writes them yet (ss_themes,ss_recommendations,ss_judge_results,ss_wave_runs). They are marked, not drawn as live seams, in seams.md. - Writes that bypass the repository layer. Two tables (
ss_post_tonality,weekly_corpus_summary) are written directly from modules, andarticle_restrictionshas no writer at all. These deviations from the cleanmodule → repository → tablepattern are listed in seams.md and accepted as exceptions with criteria in ADR-0018. (ss_channel_followers_weeklywas the one real erosion — two writers + a reader — and was refactored behindSqlAlchemySsChannelFollowersWeeklyRepository.) - Live schema vs. ORM. The ER diagrams come from the live database, not the ORM, so
ss_trends_daily(a raw-SQL table with no ORM model) appears — an ORM-only tool would miss it.
6. Architecture Decisions🔗
The "why" behind structural choices lives in docs/adr/ and the dated decisions-log-*.md files in this directory — not duplicated here.
How to read this map — the go/no-go trace (SC-001)🔗
Follow one seam end to end without opening any code:
ingestion→SqlAlchemyArticleRepository→articles
- Open modules.md:
ingestionis a module, and it depends onpersistence(where repositories live). - Open seams.md: the
ingestion → articlesedge is labelledArticleRepository(a writer, solid arrow). The exhaustive table confirmsArticleRepositorywritesarticlesand readsarticle_revisions. - Open db/legacy.md:
articlesis there, withcandidate_id → candidates(the spine) — so you can see what an article connects to.
Three clicks, module to table, no source code. That chain is the pilot's success criterion.
Pilot run: 2026-06-22. Scope: project er only. Generated by tach + tbls against the live schema; see arch-map-pilot-run-2026-06-22.md (in docs/architecture/) for the pilot run report.
Productionized 2026-06-22: the generated layer is now protected by a CI drift gate (.forgejo/workflows/arch-drift.yml + scripts/arch_map.py), surfaced as a MkDocs Material showcase (root mkdocs.yml, deploy via .forgejo/workflows/docs.yml), and regenerable via the arch-map skill. The one real erosion (ss_channel_followers_weekly) was refactored behind a repository; skeleton repos and the remaining bypasses are accepted exceptions in ADR-0018. Full report: arch-map-prod-run-2026-06-22.md.
Re-homed 2026-06-24: the showcase moved off the deprecated delphi.antopkin.ru/docs/ placeholder onto the dedicated docs hub docs.antopkin.ru — this map lives at docs.antopkin.ru/polit-media-radar/, the first tenant of a per-project sub-path hub. Hosting/deploy details: docs/ops/docs-site-deploy.md; full report: docs-hub-run-2026-06-24.md.