No description
Find a file
2026-02-16 08:47:41 +01:00
backend Add roadmap and implement top UX improvements for score transparency and map selection 2026-02-16 08:47:41 +01:00
deploy feat: automate live import timer and add legal source attribution page 2026-02-15 15:55:04 +01:00
docs Add roadmap and implement top UX improvements for score transparency and map selection 2026-02-16 08:47:41 +01:00
src Add roadmap and implement top UX improvements for score transparency and map selection 2026-02-16 08:47:41 +01:00
.gitignore feat: implement StaySense MVP backend, frontend, imports, and deployment docs 2026-02-15 13:08:56 +01:00
README.md feat: add iOS-focused PWA shell with service worker and manifest 2026-02-15 16:12:04 +01:00

StaySense (MVP NRW)

StaySense bewertet fuer die Nacht (22:00-06:00) die voraussichtliche Ruhe eines Spots in NRW (Pilot: Kreis Mettmann).

MVP Status

Implementiert:

  • Night Safety Score (0-100) mit Ampel (green, yellow, red)
  • Begruendung mit Top-Faktoren (OSM-Typ, Distanz-POIs, Zeitlogik, Events, Community)
  • API: GET /spot/score, POST /spot/signal
  • Kartenwahl via OpenStreetMap (Leaflet), inkl. Klickauswahl und Ortssuche
  • API: GET /geocode/search (Nominatim-Proxy), GET /map/tile/{z}/{x}/{y}.png (OSM-Tile-Proxy)
  • PWA-Basis (Manifest, Service Worker, iOS-Standalone-Meta, Offline-Shell)
  • Admin-Bereich (Setup/Login, geschuetzt per User/Passwort + Session-Token)
  • Admin-API fuer Uebersicht und Event-Verwaltung (/admin/*)
  • Anti-Spam ohne Account: lokaler Token + serverseitiger HMAC-Hash
  • Quick Decision UI mit Signal-Buttons
  • Offline-First im Frontend: Score-Cache + Signal-Queue
  • Echter OSM-Import via Overpass (POIs, Landuse-Zonen, Highway-Typen)
  • OpenData-Connectoren (CSV/JSON aus URL oder Datei)
  • Automatischer Import-Job-Runner (once oder daemon)

Nicht im MVP:

  • Accounts/Login
  • Chat/Kommentare
  • Stellplatz-Portal
  • Routenplanung

Start

  1. Datenbank initialisieren:
    • cd StaySense/backend
    • python3 -c "from db import init_db; init_db()"
  2. OSM importieren (Pilot-BBox Mettmann):
    • python3 import_osm_overpass.py
  3. OpenData-Connectoren aus Konfig ausfuehren:
    • python3 run_import_jobs.py --config ../docs/open_data_sources.json --prune-legacy
  4. Optional: periodische Imports (alle 6h) inkl. OSM:
    • python3 run_import_jobs.py --config ../docs/open_data_sources.json --with-osm --prune-legacy --daemon --interval-seconds 21600
  5. API starten:
    • python3 server.py
  6. Frontend starten (zweites Terminal):
    • cd ../src
    • python3 -m http.server 8080
  7. App oeffnen:
    • http://localhost:8080
  8. PWA-Test:
    • iOS Safari: Seite aufrufen -> Teilen -> "Zum Home-Bildschirm"
    • Danach aus Home-Screen starten (Standalone-Modus)

OpenData Connector Config

Datei: docs/open_data_sources.json

  • enabled: Quelle aktivieren/deaktivieren
  • format: csv oder json
  • url oder file: Quelle
  • field_map: Mapping auf StaySense-Felder
  • event_type_map: optionale Typ-Normalisierung
  • json_path: Pfad auf Array bei JSON-Feeds
  • Validierung aktiv:
    • Koordinaten muessen in DE-Bounds liegen
    • start_datetime < end_datetime
    • Event-Typ muss auf market|waste|event|construction normalisiert werden

Live-Beispiel fuer echte NRW-OpenData-Quellen:

  • Datei: docs/open_data_sources_nrw_live.json
  • Enthalten:
    • Koeln Verkehrsbeeintraechtigungen (ArcGIS JSON)
    • Koeln Baustellen Notfall (WFS GeoJSON)
  • Import:
    • cd StaySense/backend
    • python3 run_import_jobs.py --config ../docs/open_data_sources_nrw_live.json --prune-legacy

Tests

  • Backend Unit-Tests:
    • cd StaySense/backend
    • python3 -m unittest discover -s tests -p \"test_*.py\"

API Beispiele

Score holen:

  • curl "http://127.0.0.1:8787/spot/score?lat=51.25&lon=6.97&at=2026-02-15T20:00:00Z"

Signal senden:

  • curl -X POST "http://127.0.0.1:8787/spot/signal" -H "Content-Type: application/json" -d '{"spot_id":"<ID>","signal_type":"noise","device_token":"<uuid-v4>","timestamp":"2026-02-15T20:15:00Z"}'

Ortssuche:

  • curl "http://127.0.0.1:8787/geocode/search?q=Mettmann%20Bahnhof"

Tile-Proxy:

  • curl -I "http://127.0.0.1:8787/map/tile/12/2149/1387.png"

Admin-Setup (nur beim ersten Start):

  • curl -X POST "http://127.0.0.1:8787/admin/bootstrap" -H "Content-Type: application/json" -d '{"username":"admin","password":"<starkes-passwort>"}'

DSGVO-Hinweise im MVP

  • Kein Login
  • Keine IP-Speicherung in der Anwendung
  • Kein Device Fingerprinting
  • Missbrauchsschutz nur ueber hashed_device = HMAC_SHA256(device_token, server_salt)

Attribution (Rechtliches)

Unter Attribution muessen die verwendeten Datenquellen und Lizenzen klar genannt werden:

  • OpenStreetMap-Mitwirkende + ODbL-Hinweis
  • Geocoding-Dienst (Nominatim) als Quelle
  • Jede OpenData-Quelle mit Lizenzhinweis (z. B. Datenlizenz Deutschland Zero/By)

In der App ist dafuer die Seite quellen.html vorgesehen.

Produktion

  • STAYSENSE_SERVER_SALT zwingend als geheimes Env setzen
  • HTTPS-only bereitstellen
  • OpenStreetMap-/Open-Data-Attribution in App verpflichtend sichtbar halten

Doku Uebersicht

  • Architektur / Umsetzung: docs/IMPLEMENTATION_PLAN.md
  • Server-Deployment (Linux + Nginx + systemd): docs/DEPLOYMENT.md
  • CloudPanel-Setup (Hetzner): docs/CLOUDPANEL_SETUP.md
  • Betrieb / Runbook: docs/OPERATIONS.md
  • GitHub Publish Ablauf: docs/GITHUB_PUBLISH.md
  • Connector-Konfiguration: docs/open_data_sources.json
  • Event-Template: docs/open_data_events_template.csv