1. Admin → Geheimnisse sub-tab lets you edit ANTHROPIC_API_KEY +
BERLIN_WOHNEN_USERNAME/PASSWORD at runtime. Migration v7 adds a
secrets(key,value,updated_at) table; startup seeds missing keys from
env (idempotent). web reads secrets DB-first (env fallback) via
llm._api_key(); alert fetches them from web /internal/secrets on each
scan, passes them into Scraper(). Rotating creds no longer needs a
redeploy.
Masked display: 6 leading + 4 trailing chars, "…" in the middle.
Blank form fields leave the stored value untouched.
2. Drop the max_morning_commute filter from UI + server + FILTER_KEYS +
filter summary (the underlying Maps.calculate_score code stays for
potential future re-enable).
3. /static/didi.webp wired as favicon via <link rel="icon"> in base.html.
4. apply.open_page wraps page.goto in try/except so a failed load still
produces a "goto.failed" step + screenshot instead of returning an
empty forensics blob. networkidle + post-submission sleep are also
made best-effort. The error ZIP export already writes screenshot+HTML
per step and final_html — with this change every apply run leaves a
reconstructable trail even when the listing is already offline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- App is now called "wohnungsdidi" everywhere user-facing (page title,
nav brand, login header, notification subjects, report filename,
FastAPI titles, log messages)
- Brand dot replaced with an image of Didi (web/static/didi.webp),
rendered as a round 2.25rem avatar in _layout + login
- "Programmiert für Annika ♥" footer now shows for every logged-in user,
not only Annika
- Count-up shows only seconds ("vor 73 s") regardless of age — no
rollover to minutes/hours
- Data continuity: DB file stays /data/lazyflat.sqlite and the Docker
volume stays lazyflat_data so the rename doesn't strand existing data
- Session cookie renamed to wohnungsdidi_session (one-time logout on
rollout)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /actions/apply now no-ops (returns fresh partial) when a running
application exists for this user+flat, or when a previous one succeeded.
The list button was already visually disabled; this closes the direct-POST
and double-click loopholes
- Drop the one-line error message under flat entries in the list
(bewerbung_detail still shows the full message + the forensic ZIP report)
- Strip "min morgens" commute chip from the list; alert._flat_payload sends
an empty connectivity dict so Maps.calculate_score is no longer called on
every flat. Maps.calculate_score + Flat.connectivity stay in the codebase
for easy re-enable (one-line swap in _flat_payload)
- List entry shows "vor 23 min" instead of "entdeckt vor 23 min"
- Bitwarden: rename profile email/immomio fields to opaque names
(contact_addr, immomio_login, immomio_secret) + add data-bwignore across
every settings form / input. Server-side update_profile maps the new
field names back to the existing DB columns
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* flats: new lat/lng columns (migration v3); alert geocodes every new flat
through googlemaps and ships coords in the payload
* web: CSP extended for unpkg (leaflet.css) + tile.openstreetmap.org
* Wohnungen tab: Liste/Karte view toggle (segmented, CSS-only via :has(),
selection persisted in localStorage). Karte shows passende flats as Pins
on an OSM tile map; Popup per Pin mit Adresse, Zimmer/m²/€ und Link
* Top-strip toggles are now proper iOS-style toggle switches (single
rounded knob sliding in a pill, red when on), no descriptive subtitle
* Alarm-Karte verlinkt jetzt auf /einstellungen/benachrichtigungen
(Filter-Karte bleibt /einstellungen/filter)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three isolated services (alert scraper, apply HTTP worker, web UI+DB)
with argon2 auth, signed cookies, CSRF, rate-limited login, kill switch,
apply circuit breaker, audit log, and strict CSP.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>