fix: establish read-only audit transaction before identity check
This commit is contained in:
@@ -99,15 +99,29 @@ def _load(
|
||||
) -> dict[str, Any]:
|
||||
with engine.connect() as conn:
|
||||
conn = conn.execution_options(isolation_level="AUTOCOMMIT")
|
||||
identity = conn.execute(text(
|
||||
"SELECT current_database(), current_user, current_setting('transaction_read_only')"
|
||||
)).one()
|
||||
if identity[0] != expected_database or (expected_user and identity[1] != expected_user):
|
||||
raise RuntimeError(f"refusing unexpected database identity: {identity!r}")
|
||||
if require_read_only and identity[2] != "on":
|
||||
raise RuntimeError(f"read-only simulation requires transaction_read_only=on: {identity!r}")
|
||||
conn.execute(text("BEGIN READ ONLY"))
|
||||
transaction_started = False
|
||||
try:
|
||||
# A fresh connection commonly reports transaction_read_only=off.
|
||||
# Establish the protected transaction on the same connection used
|
||||
# for every factual read before validating a strict audit.
|
||||
if require_read_only:
|
||||
conn.execute(text("BEGIN READ ONLY"))
|
||||
transaction_started = True
|
||||
|
||||
identity = conn.execute(text(
|
||||
"SELECT current_database(), current_user, current_setting('transaction_read_only')"
|
||||
)).one()
|
||||
if identity[0] != expected_database or (expected_user and identity[1] != expected_user):
|
||||
raise RuntimeError(f"refusing unexpected database identity: {identity!r}")
|
||||
if require_read_only and identity[2] != "on":
|
||||
raise RuntimeError(f"read-only simulation requires transaction_read_only=on: {identity!r}")
|
||||
|
||||
# Preserve the development/test path's established ordering: check
|
||||
# its identity first, then protect the factual reads themselves.
|
||||
if not require_read_only:
|
||||
conn.execute(text("BEGIN READ ONLY"))
|
||||
transaction_started = True
|
||||
|
||||
opportunities = [dict(row) for row in conn.execute(text("""
|
||||
SELECT o.*, o.id::text AS id, o.local_customer_id::text,
|
||||
c.name AS linked_customer_name, c.tax_id, c.email AS fiscal_email,
|
||||
@@ -157,7 +171,8 @@ def _load(
|
||||
WHERE status IN ('open','needs_review','conflict') ORDER BY created_at
|
||||
""")).mappings()]
|
||||
finally:
|
||||
conn.execute(text("ROLLBACK"))
|
||||
if transaction_started:
|
||||
conn.execute(text("ROLLBACK"))
|
||||
return {
|
||||
"identity": {"database": identity[0], "user": identity[1], "transaction_read_only": identity[2]},
|
||||
"opportunities": opportunities, "tasks": _group(tasks), "messages": _group(messages),
|
||||
|
||||
Reference in New Issue
Block a user