diff --git a/backend/src/cyclone/rebill/run.py b/backend/src/cyclone/rebill/run.py index 44c2476..eebd4aa 100644 --- a/backend/src/cyclone/rebill/run.py +++ b/backend/src/cyclone/rebill/run.py @@ -469,7 +469,24 @@ def _validate_or_skip(body: bytes, *, claim_id: str) -> str: actually run. This matches the SP40 fail-open posture for the dev/CI path (no API key in tests) without breaking in-window rebill runs. + + Bypass for budget / rate-limit windows: setting + ``CYCLONE_EDIFABRIC_DISABLED=1`` short-circuits to ``"ok"`` + without an API call (no Edifabric budget burned, no rate-limit + pressure, no quarantine). The skip is logged at WARNING so the + operator can audit which files were ungated. Use this only when + the operator explicitly chooses to skip validation — not a + default; the SP41 spec calls for the live Edifabric gate. """ + import os + if os.environ.get("CYCLONE_EDIFABRIC_DISABLED") == "1": + _log.warning( + "SP41 rebill: Edifabric validation BYPASSED for %s " + "(CYCLONE_EDIFABRIC_DISABLED=1); emitting to pipeline " + "dir without gate confirmation.", + claim_id, + ) + return "ok" try: result = _edifabric.validate_edi(body) except _edifabric.EdifabricError as exc: