Repository navigation
Releases
RitterRadar v0.2.0
Added
- Open a matching market directly from an
/?event=...link, including a
deduplicated listing matched through any of its source URLs.
Fixed
- Center the initial map on the saved home location so nearby events are visible
without manually panning from the Germany-wide default. - Allow the first manual crawl trigger immediately after a fresh host boot;
subsequent triggers still observe the cooldown.
Container: ghcr.io/marcelpetrick/ritterradar:0.2.0 (linux/amd64 and linux/arm64).
RitterRadar v0.1.1
Fixed
- Restore OpenStreetMap tiles by sending only the application origin as the
browser Referer and using the provider's canonical tile hostname. Add an
offline browser regression for the outgoing Referer. - Keep links to every source when duplicate listings share one map marker, so
the Vehi Mercatus listing remains accessible for the Grafing market.
Container: ghcr.io/marcelpetrick/ritterradar:0.1.1 (linux/amd64 and linux/arm64).
RitterRadar v0.1.0
Security
- Add a Host allowlist, same-origin checks for mutations, and token-based
authentication for non-loopback clients. Add CSP and browser security headers. - Prevent stored home labels from being interpreted as HTML, validate event
links, and remove third-party font requests. - Validate crawler destinations before connections, pin approved DNS results,
restrict redirect targets, and bound response sizes and crawl duration. - Bound API and queue work; validate settings and adapter records; make crawl
failures visible and ensure job cleanup. - Store runtime data and logs with restrictive permissions, redact request
query strings from access logs, and add log rotation and privacy clearing.
Changed
- Require an authentication token for container deployments and harden the
container with a read-only filesystem, dropped capabilities, and resource
limits. - Add readiness reporting, single-database-instance ownership, periodic
crawling, offline mode, and paginated market responses. - Move geocoding to a bounded JSON POST request; replace interactive Swagger
and ReDoc consoles with a local API guide at the same routes. - Add runtime and development dependency inventories, CI security scan steps,
documentation to the quality gate, and separate container build and publish
jobs. - Update
soupsieveto 2.9.0 after the dependency audit flagged 2.8.4;
local runtime/developmentpip-auditand Bandit checks now pass. - Document the behavior changes, privacy boundaries, configuration, and the
review's remaining verification limits. - Raise the enforced line-coverage gate to 98% and add offline API, security,
crawler, and network failure-path regressions (319 tests; 98.65% coverage).
Compatibility
- API clients that geocode addresses must use
POST /api/settings/geocode. - Container users must set
RITTERRADAR_AUTH_TOKEN. Clients connecting from
another machine need credentials and an explicit allowed Host.
Container: ghcr.io/marcelpetrick/ritterradar:0.1.0 (linux/amd64 and linux/arm64).
RitterRadar v0.0.91
Added
scripts/local_pipeline.shruns the complete quality gate — lint, formatting,
strict typing, the offline test suite, the browser regression run and the
documentation build — and closes with a PASS/FAIL/SKIP summary.just cinow
calls it, so there is one local gate definition.- README project-status and versioning sections, a documentation map, and badge
rows for the pipelines, the pinned stack versions and the quality gate
(ruff, mypy strict, coverage gate, adapter count, release date, last commit).
Changed
- Document the quality gate and its requirements in one place instead of listing
the single commands only.
Container: ghcr.io/marcelpetrick/ritterradar:0.0.91 (linux/amd64 and linux/arm64).
v0.0.87
Dependency maintenance release.
- Uvicorn: 0.52.4 → 0.53.0
- SQLAlchemy: 2.0.52 → 2.0.54
- Ruff: 0.16.7 → 0.16.8
- Docker setup-qemu-action: v4.3.0 → v4.4.0
- Docker setup-buildx-action: v4.3.0 → v4.4.1
- Docker build-push-action: v7.3.0 → v7.4.0
Exact package versions and full commit SHA action pins are retained.
Validation: lint, formatting, strict typing, and all 193 tests pass on Python 3.12, 3.13, and 3.14, with 98.42–98.45% coverage. Wheel/sdist metadata checks and local Docker build/smoke tests pass. Sphinx retains four pre-existing autodoc import warnings.
The release workflow attaches the wheel and source distribution. The Docker workflow publishes ghcr.io/marcelpetrick/ritterradar:0.0.87 and :latest for amd64 and arm64.
Full changes: v0.0.86...v0.0.87
v0.0.86
✍️ Clean event names on Pfalzis Marktkalendarium
Fixed
- Glued event names — names spanning several lines on Pfalzis Marktkalendarium were joined without a space ("Mittelaltermeile
Altstadtfest" showed as "MittelaltermeileAltstadtfest"). The lines are now joined with a space. - No duplicates from corrected names — when a re-crawl delivers a name that differs from the stored one only in whitespace (same start date and source URL), the existing record is updated and takes the corrected name instead of a second entry being created.
After upgrading, the next crawl corrects the names of all upcoming Pfalzis events in place.
Container image
docker run -d --name ritterradar \
-p 127.0.0.1:8000:8000 \
-v ritterradar-data:/app/data \
-e RITTERRADAR_GEOCODER_EMAIL=your@email.example \
ghcr.io/marcelpetrick/ritterradar:0.0.86Full changelog: v0.0.84...v0.0.86
v0.0.84
🧭 Countries and compound place names
Follow-up to v0.0.79: fewer approximate markers and correct countries.
Fixed
- Countries on Mittelalterkalender.info — about 100 Austrian, Swiss, Dutch and other events were stored as German and geocoded inside Germany. The country is now read from each row (hidden in an HTML comment on the site), and re-crawls correct the country of existing records.
- Compound place names — "Mechernich-Satzvey", "Schwendi - Orsenhausen" or "Bornhagen OT Rimbach" are resolved via their parts (district first) and now land on the village itself instead of a postcode centroid elsewhere.
- Fyndling.de locations — Swiss canton suffixes ("Zofingen AG"), legacy country markers ("Campo di Trens (I)") and unusual postcode notations are cleaned up so these events can be geocoded.
After upgrading, the next crawl repairs existing records and markers automatically (geocoder cache moves to market-v4; affected entries are looked up once).
Container image
docker run -d --name ritterradar \
-p 127.0.0.1:8000:8000 \
-v ritterradar-data:/app/data \
-e RITTERRADAR_GEOCODER_EMAIL=your@email.example \
ghcr.io/marcelpetrick/ritterradar:0.0.84Full changelog: v0.0.79...v0.0.84
v0.0.79
📍 Properly geocoded markets and a 90% test gate
Fixed — "Ungefährer Ort" on most markers
Nearly every geocoded market was shown with an approximate location. Nominatim's town results carry no postcode, so they were rejected; the postcode centroids used instead never reached the importance threshold and were always flagged uncertain.
- Results that name the requested town are now accepted and treated as certain (country must match, a differing postcode is still rejected; country/state/county results stay uncertain).
- Cached lookups move to a new key version: entries that already name the town are upgraded without a network request, the others are looked up once again and keep their old coordinates if nothing better is found.
- Example: Elbingerode (Harz) and Eckelsheim now resolve to the towns themselves instead of neighbouring villages.
After upgrading, the next crawl repairs existing markers automatically.
Tests
- Coverage raised from 57% to 98% with 161 offline tests (all adapters, crawl worker and queue, HTTP client, geocoder, API).
- The coverage gate now enforces the project's 90% goal instead of 50%.
Container image
docker run -d --name ritterradar \
-p 127.0.0.1:8000:8000 \
-v ritterradar-data:/app/data \
-e RITTERRADAR_GEOCODER_EMAIL=your@email.example \
ghcr.io/marcelpetrick/ritterradar:0.0.79Full changelog: v0.0.70...v0.0.79
v0.0.70
🗺 Fresher source list: two new calendars, next year's dates back
All crawler sources were reviewed on 2026-09-13. RitterRadar now crawls 9 sources and returned ~4,000 events in the live check.
| Source | Events | Change |
|---|---|---|
| Mittelalterkalender.info | 937 | Fixed — 2027 list page was renamed; next-year events are back (42) |
| Fyndling.de | 1,323 | New — DE/AT/CH/LI/LU markets from the fyndling.de market list |
| Mittelaltermarkt-info.de | 324 | New — curated DE, AT and CH event lists |
| Mittelaltermarkt.online | 787 | — |
| Vehi Mercatus Marktkalender | 431 | — |
| Pfalzis Marktkalendarium | 169 | — |
| Taterman.at | 40 | — |
| Trollfelsen.de | 11 | — |
| Spectaculum.de | 8 | — |
Still disabled: mittelalterfeste.de (parked domain), schwerttanz.de and ritterschaft.de (broken TLS), mittelaltermarkt.com (domain for sale). Evaluated and not added: mittelalter-zeitreise.de, mittelalterkalender.at, eventgilde.com, mirimor.ch, carnica-spectaculi.de — reasons in documents/03_sources.md.
Container image
docker run -d --name ritterradar \
-p 127.0.0.1:8000:8000 \
-v ritterradar-data:/app/data \
-e RITTERRADAR_GEOCODER_EMAIL=your@email.example \
ghcr.io/marcelpetrick/ritterradar:0.0.70Note: the first crawl after upgrading geocodes the new events (Nominatim, ~1 request/s, cached), so markers for new sources appear gradually.
Fixed
mittelalterkalender_info0.2.0 discovers yearly list pages from homepage links instead of a fixed URL pattern.
Added
fyndlingandmittelaltermarkt_infoadapters with offline fixture tests; map tooltips name the new sources.
Documentation
- Source review, new source sections, disabled and rejected sources in
documents/03_sources.md; README and architecture overview list 9 adapters.
v0.0.67
🐳 RitterRadar is now available as a container image
docker run -d --name ritterradar \
-p 127.0.0.1:8000:8000 \
-v ritterradar-data:/app/data \
-e RITTERRADAR_GEOCODER_EMAIL=your@email.example \
ghcr.io/marcelpetrick/ritterradar:0.0.67Then open http://127.0.0.1:8000. Multi-arch (linux/amd64, linux/arm64), non-root, with healthcheck, SBOM and build provenance. See the README's Docker section for Compose and configuration.
Added
- Two-stage
Dockerfileonpython:3.14.7-slim-trixie(non-root UID 10001,/app/datavolume,/healthhealthcheck),.dockerignore,compose.yaml,just docker-build/docker-run. - Docker workflow: build → smoke test → publish to
ghcr.io/marcelpetrick/ritterradar(:edgefrom master;:X.Y.Z,:X.Y,:latestfrom release tags).
Changed
- Updated 13 dependencies to latest stable versions (fastapi 0.141.1, uvicorn 0.52.4, sqlmodel 0.0.42, sqlalchemy 2.0.52, alembic 1.20.0, pydantic-settings 2.15.0, lxml 6.1.3, geopy 2.5.0, anyio 4.15.1, icalendar 7.3.0, ruff 0.16.7, mypy 2.3.1, types-PyYAML 6.0.12.20260906); build requirements pinned exactly (setuptools 84.0.0, wheel 0.48.0).
- Package metadata uses the SPDX license expression
GPL-3.0-or-later. - CI runs on Python 3.12, 3.13 and 3.14; all GitHub Actions updated to their latest releases and pinned by commit SHA.
- Release workflow attaches the wheel and sdist to the GitHub release.
Documentation
- README Docker section and badge; architecture doc container deployment section.