QTZPOC-20

QTZPOC-20: Enhance system robustness and test coverage across bundle processing, activity error handling, and worker operations.

*   Strengthen bundle reader validation with new tests for archive integrity, security vulnerabilities (e.g., path traversal, duplicate entries, special file types), and I/O error resilience.
*   Improve error handling and status propagation in PI Web API, MLflow, and OPC activities, including partial write scenarios and OPC session management.
*   Add comprehensive tests for worker startup, configuration, graceful shutdown, and Prometheus metrics server initialization.
*   Introduce a new utility for intelligent DataFrame debugging, summarizing large dataframes for concise logging, and refine exception chain summarization.
*   Update code coverage configuration to exclude @overload decorator lines.
This commit is contained in:
2026-09-08 09:42:23 -03:00
parent 61db575cdc
commit e4fc12e529
15 changed files with 891 additions and 1 deletions

View File

@@ -1,7 +1,11 @@
"""The seven gates: what each one rejects, in what order, and what it leaves on disk."""
import io
import json
import os
import random
import stat
import zipfile
from pathlib import Path
import nacl.bindings as sodium
@@ -173,6 +177,16 @@ def test_gate_2_rejects_a_truncated_transfer(work_dir, reader):
assert error.value.gate == 2
def test_gate_2_wraps_an_os_error_reading_the_file(work_dir, reader):
"""A download that never landed on disk is an OS error, not a format one."""
missing = work_dir / 'never-downloaded.sientia'
with pytest.raises(BundleGateError, match='could not be read') as error:
reader.open(missing, factory.DEFAULT_PASSWORD, work_dir / 'extract', work_dir)
assert error.value.gate == 2
def _never_called(message: str):
def _raise(*_args, **_kwargs):
raise AssertionError(message)
@@ -220,6 +234,22 @@ def test_gate_3_stream_without_a_final_tag_is_rejected(work_dir, reader):
assert AMBIGUOUS_REASON in str(error.value)
def test_gate_3_wraps_an_os_error_while_writing_the_decrypted_zip(work_dir, reader, monkeypatch):
"""A write failure while streaming the plaintext to disk is reported as disk trouble, not as
a bad password — the AEAD never even got to disagree."""
payload = factory.make_bundle()
def _raise_os_error(*_args, **_kwargs):
raise OSError('disk full')
monkeypatch.setattr(reader, '_pull_stream', _raise_os_error)
with pytest.raises(BundleGateError, match='could not be written') as error:
_open(reader, work_dir, payload)
assert error.value.gate == 3
def test_gate_3_leaves_no_decrypted_zip_behind(work_dir, reader):
payload = factory.make_bundle()
@@ -316,6 +346,27 @@ def test_gate_4_rejects_content_that_is_not_an_archive(work_dir, reader):
assert error.value.gate == 4
def test_gate_4_rejects_an_empty_archive(work_dir, reader):
payload = factory.make_bundle(factory.ZipSpec(files={}, include_metadata=False))
with pytest.raises(BundleGateError, match='archive is empty') as error:
_open(reader, work_dir, payload)
assert error.value.gate == 4
def test_gate_4_rejects_an_entry_that_is_neither_a_file_nor_a_directory(work_dir, reader):
"""A FIFO's mode bits are neither a symlink's, a regular file's, nor a directory's."""
payload = factory.make_bundle(
factory.ZipSpec(special_mode_entries={'artifacts/pipe': stat.S_IFIFO | 0o644})
)
with pytest.raises(BundleGateError, match='not a regular file') as error:
_open(reader, work_dir, payload)
assert error.value.gate == 4
# ------------------------------------------------------------------- gate 5
@@ -338,6 +389,61 @@ def test_gate_5_extraction_writes_plain_files(work_dir, reader):
assert path.stat().st_mode & 0o111 == 0, path
def test_gate_5_extraction_creates_declared_directory_entries(work_dir, reader):
"""The producer never writes directory entries, but a bundle from anywhere else might."""
payload = factory.make_bundle(factory.ZipSpec(directory_entries=['artifacts/empty_dir']))
opened = _open(reader, work_dir, payload)
assert (opened.extracted_dir / 'artifacts' / 'empty_dir').is_dir()
def test_gate_5_rejects_a_duplicate_entry_name(work_dir, reader):
"""Two archive entries claiming the same path: gate 4 checks each name on its own and cannot
see the collision, so extraction is where an overwrite is caught — and rejected."""
payload = factory.make_bundle(factory.ZipSpec(repeat_file='artifacts/prediction_model/MLmodel'))
with pytest.raises(BundleGateError, match='overwrite') as error:
_open(reader, work_dir, payload)
assert error.value.gate == 5
assert not (work_dir / 'extract').exists()
def test_gate_5_wraps_an_os_error_during_unpacking(work_dir, reader, monkeypatch):
"""A write failure partway through extraction (e.g. disk full) is reported as unpacking
trouble, not surfaced as the raw OSError."""
payload = factory.make_bundle()
def _raise_os_error(*_args, **_kwargs):
raise OSError('disk full')
monkeypatch.setattr('laborious.utils.bundle.reader.shutil.copyfileobj', _raise_os_error)
with pytest.raises(BundleGateError, match='could not be unpacked') as error:
_open(reader, work_dir, payload)
assert error.value.gate == 5
assert not (work_dir / 'extract').exists()
def test_extract_member_rechecks_containment_on_the_resolved_path(work_dir, reader):
"""Gate 4 already rejects a traversal by name; extraction re-checks on the *resolved* path as
a second, independent line of defense."""
root = work_dir / 'root'
root.mkdir()
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, 'w') as archive:
archive.writestr('safe.txt', b'hello')
with zipfile.ZipFile(io.BytesIO(buffer.getvalue())) as archive:
entry = archive.infolist()[0]
with pytest.raises(BundleGateError, match='resolves outside') as error:
reader._extract_member(archive, entry, root, work_dir / 'somewhere-else')
assert error.value.gate == 5
# ------------------------------------------------------------------- gate 6
@@ -375,6 +481,10 @@ def test_gate_5_extraction_writes_plain_files(work_dir, reader):
),
'experiment name',
),
(
factory.ZipSpec(document={'metadata': 'not-a-dict', 'parameters': {}}),
'not objects',
),
],
)
def test_gate_6_rejects_a_malformed_metadata_document(work_dir, reader, spec, match):
@@ -457,6 +567,19 @@ def test_gate_7_rejects_content_a_model_export_should_not_carry(work_dir, reader
assert not (work_dir / 'extract').exists()
def test_gate_7_rejects_a_non_regular_file_left_in_the_tree(work_dir, reader):
"""Extraction itself only ever writes plain files and directories; this is the check that
would catch anything else showing up in the tree by some other means."""
root = work_dir / 'weird_root'
root.mkdir()
os.mkfifo(root / 'pipe')
with pytest.raises(BundleGateError, match='not a file') as error:
reader._gate_7_content_policy(root)
assert error.value.gate == 7
# ------------------------------------------------------------------ ordering