"""Runtime firewall: every billing/checkout request is inspected before it reaches any handler. A payload carrying score-, rank-, record- or expedite-related fields is refused and the attempt is logged publicly (count on /conflicts).""" import json import logging from datetime import datetime, timezone from deps import db logger = logging.getLogger("firewall") FORBIDDEN = {"score", "target_score", "score_delta", "covenant_score", "grade", "rank", "ranking", "boost", "hide_record", "hide", "suppress", "remove_record", "expedite", "priority_correction", "record_edit", "edit_record", "ledger", "index_value"} BILLING_MARKERS = ("checkout", "/billing", "/sponsor", "/subscribe", "/purchase", "/comp") POLICY = "Billing endpoints accept payment for placement, alerts, pages and reports only. Any billing request that names a score, rank, record, ledger, or expedite field is refused before it reaches a handler, and the attempt is logged." def _keys(o, out: set, depth: int = 0): if depth > 6: return if isinstance(o, dict): for k, v in o.items(): out.add(str(k).lower()) _keys(v, out, depth + 1) elif isinstance(o, list): for v in o[:50]: _keys(v, out, depth + 1) def is_billing_path(path: str) -> bool: p = path.lower() return p.startswith("/api/") and any(m in p for m in BILLING_MARKERS) def offending_fields(body: bytes) -> list[str]: if not body: return [] try: data = json.loads(body) except Exception: return [] found: set = set() _keys(data, found) return sorted(found & FORBIDDEN) class BillingFirewall: """Pure ASGI middleware so the request body is buffered once and replayed to the app unchanged.""" def __init__(self, app): self.app = app async def __call__(self, scope, receive, send): if scope["type"] != "http" or scope.get("method") not in ("POST", "PUT", "PATCH") or not is_billing_path(scope.get("path", "")): return await self.app(scope, receive, send) chunks, more = [], True while more: msg = await receive() chunks.append(msg.get("body", b"")) more = msg.get("more_body", False) body = b"".join(chunks) bad = offending_fields(body) if bad: client = (scope.get("client") or ("", 0))[0] try: await db.firewall_events.insert_one({"at": datetime.now(timezone.utc).isoformat(), "path": scope.get("path"), "fields": bad, "client": client, "action": "REJECTED"}) except Exception: pass logger.warning(f"firewall rejected {scope.get('path')} fields={bad}") payload = json.dumps({"detail": "Refused: billing requests cannot carry score, rank, record, ledger or expedite fields. Nothing about a record is for sale.", "fields": bad, "policy": POLICY}).encode() await send({"type": "http.response.start", "status": 403, "headers": [(b"content-type", b"application/json"), (b"content-length", str(len(payload)).encode())]}) await send({"type": "http.response.body", "body": payload}) return sent = False async def replay(): nonlocal sent if not sent: sent = True return {"type": "http.request", "body": body, "more_body": False} return await receive() return await self.app(scope, replay, send) async def stats() -> dict: total = await db.firewall_events.count_documents({}) last = await db.firewall_events.find_one({}, {"_id": 0, "client": 0}, sort=[("at", -1)]) return {"policy": POLICY, "forbidden_fields": sorted(FORBIDDEN), "guarded_paths": "every /api route whose path contains: " + ", ".join(BILLING_MARKERS), "attempts_blocked": total, "last_blocked": last, "status": "intact"}