"""Internal service-to-service endpoints. Authenticated via INTERNAL_API_KEY header; never called by browsers.""" from fastapi import APIRouter, Depends, HTTPException import db import enrichment import notifications from berlin_districts import district_for_address from common import _auto_apply_allowed, _kick_apply, require_internal from matching import flat_matches_filter, row_to_dict router = APIRouter() @router.post("/internal/flats") async def internal_submit_flat( payload: dict, _guard: None = Depends(require_internal), ): if not payload.get("id") or not payload.get("link"): raise HTTPException(400, "id and link required") is_new = db.upsert_flat(payload) if not is_new: return {"status": "duplicate"} # Kick LLM enrichment + image download for this fresh flat. enrichment.kick(str(payload["id"])) # Derive the Bezirk once so the districts filter can apply. Without # this, flat_matches_filter sees district=None for every incoming # flat and excludes it whenever a user has an active districts filter. match_payload = dict(payload) match_payload["district"] = district_for_address(payload.get("address")) for u in db.list_users(): if u["disabled"]: continue filters = row_to_dict(db.get_filters(u["id"])) if not flat_matches_filter(match_payload, filters): continue db.log_audit("alert", "flat_matched", f"user={u['username']} flat={payload['id']}", user_id=u["id"]) notifications.on_match(u["id"], payload) prefs = db.get_preferences(u["id"]) if _auto_apply_allowed(prefs): _kick_apply(u["id"], str(payload["id"]), payload["link"], "auto") db.log_audit("system", "auto_apply_kick", f"user={u['username']} flat={payload['id']}", user_id=u["id"]) return {"status": "ok"} @router.post("/internal/heartbeat") async def internal_heartbeat(payload: dict, _g: None = Depends(require_internal)): service = payload.get("service", "unknown") db.set_state(f"last_{service}_heartbeat", db.now_iso()) return {"status": "ok"} @router.post("/internal/error") async def internal_report_error( payload: dict, _g: None = Depends(require_internal), ): db.log_error( source=payload.get("source", "unknown"), kind=payload.get("kind", "error"), summary=payload.get("summary", ""), context=payload.get("context"), ) return {"status": "ok"} @router.get("/internal/secrets") async def internal_secrets(_g: None = Depends(require_internal)): """Give sibling services (alert) the current runtime creds that the admin may have edited via the UI, so no redeploy is needed when rotating.""" return db.all_secrets()