fix(execution): KIS child cancel identity binding, sanitized logging, PG cancel SQL tests

Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-09-01 12:06:45 +00:00
committed by GitHub
co-authored by genichin
parent f0ac909958
commit 65df10542b
5 changed files with 331 additions and 31 deletions
@@ -1,19 +1,22 @@
"""Regression: execution loop exceptions must be logged, not silently swallowed.
"""Regression: execution loop exceptions must be logged without leaking secrets.
dcy-031 / issue #81: exceptions from execution.run_once() were silently ignored
via bare `continue`, making it impossible to observe repository or adapter errors.
dcy-031 / issue #81 (Fix C):
- Exceptions from execution.run_once() were silently ignored via bare `continue`.
- Sanitized logging requirement: only type(exc).__name__ is emitted; the
exception message, traceback, and exc_info must NOT appear in the log record
so adapter exceptions containing credentials/DSN/raw payload are never exposed.
- Worker must continue after the error (loop survives).
"""
from __future__ import annotations
import logging
import threading
import types
import pytest
_SENTINEL = "SECRET-DSN-CREDENTIAL-RAWPAYLOAD-DO-NOT-LOG"
def test_execution_loop_logs_exception(caplog):
"""When execution.run_once() raises, the error is logged and the loop continues."""
def test_execution_loop_logs_exception_without_leaking_secrets(caplog):
"""Exception type is logged; secret sentinel in exc message is NOT logged."""
import trex_core.runtime.daemon as daemon_mod
call_count = 0
@@ -24,7 +27,8 @@ def test_execution_loop_logs_exception(caplog):
nonlocal call_count
call_count += 1
if call_count == 1:
raise RuntimeError("simulated repo error: IndeterminateDatatype")
raise RuntimeError(f"dsn=postgresql://user:{_SENTINEL}@host/db")
# Stop after second successful tick
stop_event.set()
class _FakePublisher:
@@ -34,8 +38,6 @@ def test_execution_loop_logs_exception(caplog):
class _FakeConfig:
execution_interval_sec = 0.001
# Build a minimal stub Daemon without invoking its real __init__, so we can
# inject only the attributes _execution_loop reads.
daemon = object.__new__(daemon_mod.Daemon)
daemon.stop = stop_event
daemon.config = _FakeConfig()
@@ -48,6 +50,21 @@ def test_execution_loop_logs_exception(caplog):
t.join(timeout=2.0)
assert not t.is_alive(), "execution loop did not exit cleanly"
assert any(
"execution loop error" in r.message for r in caplog.records
), f"expected 'execution loop error' log, got: {[r.message for r in caplog.records]}"
error_records = [r for r in caplog.records if "execution loop error" in r.message]
assert error_records, (
f"expected 'execution loop error' log record, got: {[r.message for r in caplog.records]}"
)
# Secret sentinel must NOT appear in any log record (message or exc_info output)
for rec in caplog.records:
assert _SENTINEL not in rec.getMessage(), (
f"secret sentinel leaked into log: {rec.getMessage()}"
)
# exc_info must not be attached
assert rec.exc_info is None or rec.exc_info == (None, None, None), (
"exc_info must not be set on execution loop error record"
)
# The loop continued: second call_count tick was reached
assert call_count >= 2, "loop did not continue after exception"