@@ -124,6 +124,46 @@ def observe(**kwargs):
124124 assert phases == ["catalog initialization" , "import preflight failure" ]
125125
126126
127+ def test_failed_import_preflight_rejects_catalog_drift_before_audit (
128+ tmp_path , monkeypatch ,
129+ ):
130+ path = tmp_path / "failed-preflight-drift.sqlite"
131+ database_url = f"sqlite:///{ path } "
132+ real_bound_transaction = wide ._bound_catalog_transaction
133+
134+ @contextmanager
135+ def inject_drift (** kwargs ):
136+ if kwargs ["phase" ] == "import preflight failure" :
137+ connection = sqlite3 .connect (path )
138+ connection .execute ("create view foreign_view as select 1 as value" )
139+ connection .commit ()
140+ connection .close ()
141+ with real_bound_transaction (** kwargs ) as connection :
142+ yield connection
143+
144+ monkeypatch .setattr (wide , "_bound_catalog_transaction" , inject_drift )
145+ variables = _variables ()
146+ variables [0 ].update ({
147+ "storage_kind" : "numeric" , "string_width" : None ,
148+ "format" : "F8.2" , "alignment" : "right" ,
149+ })
150+
151+ with pytest .raises (UnsupportedOperationError , match = "foreign" ):
152+ wide .create_wide_dataset (
153+ database_url = database_url ,
154+ dataset_id = "invalid" ,
155+ source_name = "invalid.sav" ,
156+ source_format = "SAV" ,
157+ rows = [{"name" : "not-a-number" }],
158+ variables = variables ,
159+ )
160+
161+ connection = sqlite3 .connect (path )
162+ assert connection .execute ("select count(*) from operation" ).fetchone () == (0 ,)
163+ assert connection .execute ("select count(*) from fidelity_event" ).fetchone () == (0 ,)
164+ connection .close ()
165+
166+
127167def test_export_audit_mutations_route_through_binding_guard (tmp_path , monkeypatch ):
128168 database_url = f"sqlite:///{ tmp_path / 'bound-export.sqlite' } "
129169 _create (database_url )
0 commit comments