Skip to content

Commit 76e548e

Browse files
Pigbibicodex
andauthored
fix: expose safe reconciliation rejection reason (#478)
Co-authored-by: Codex <noreply@openai.com>
1 parent 4f98faf commit 76e548e

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

main.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,12 @@ def _handle_reconciliation():
19071907
report = None
19081908
scheduler_job_sha256 = _scheduler_job_identity_sha256()
19091909
if scheduler_job_sha256 is None:
1910+
reason = (
1911+
"missing_scheduler_identity"
1912+
if request.headers.get("X-CloudScheduler-JobName") is None
1913+
else "invalid_scheduler_identity"
1914+
)
1915+
print(json.dumps({"event": "broker_reconciliation_rejected", "reason": reason}), flush=True)
19101916
return "Error", 400
19111917
reconciliation_request_id = normalize_reconciliation_request_id(
19121918
request.headers.get("X-QSL-Reconciliation-Request-Id")

tests/test_request_handling.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,3 +1565,33 @@ def test_handle_reconciliation_rejects_missing_scheduler_identity_before_broker_
15651565

15661566
assert (body, response_code) == ("Error", 400)
15671567
assert broker_connection_attempts == []
1568+
1569+
1570+
@pytest.mark.parametrize(
1571+
("scheduler_identity", "reason"),
1572+
[
1573+
(None, "missing_scheduler_identity"),
1574+
("", "invalid_scheduler_identity"),
1575+
("private-invalid-header-value", "invalid_scheduler_identity"),
1576+
],
1577+
)
1578+
def test_reconciliation_rejection_reports_only_safe_reason(
1579+
strategy_module, monkeypatch, capsys, scheduler_identity, reason,
1580+
):
1581+
def forbidden(*_args, **_kwargs):
1582+
raise AssertionError("rejected request must not read broker or persist report")
1583+
1584+
for name in ("connect_ib", "build_execution_report", "persist_reconciliation_report"):
1585+
monkeypatch.setattr(strategy_module, name, forbidden)
1586+
headers = {} if scheduler_identity is None else {"X-CloudScheduler-JobName": scheduler_identity}
1587+
capsys.readouterr()
1588+
response = strategy_module.app.test_client().post("/reconcile", headers=headers)
1589+
1590+
assert response.status_code == 400
1591+
assert response.get_data(as_text=True) == "Error"
1592+
output = capsys.readouterr()
1593+
assert json.loads(output.out) == {
1594+
"event": "broker_reconciliation_rejected",
1595+
"reason": reason,
1596+
}
1597+
assert output.err == ""

0 commit comments

Comments
 (0)