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

@@ -23,6 +23,7 @@ import hashlib
import io
import json
import os
import stat
import struct
import unicodedata
import zipfile
@@ -118,6 +119,15 @@ class ZipSpec:
traversal_entry: str | None = None
bomb_bytes: int = 0
extra_files: dict[str, bytes] = field(default_factory=dict)
# name -> a raw `stat.S_IF*` mode, for an entry that is neither a symlink, a regular file nor a
# directory (e.g. `stat.S_IFIFO`) — gate 4 must reject these on their file-type bits alone.
special_mode_entries: dict[str, int] = field(default_factory=dict)
# Directory entries the producer never writes (`build_zip` stores none), but a gate 5 defense
# this repository still carries has to be exercised by something.
directory_entries: list[str] = field(default_factory=list)
# A file name already in `files`/`extra_files`, written a second time under the same name — two
# archive entries claiming the same path, which only gate 5's extraction can catch.
repeat_file: str | None = None
def build_zip(spec: ZipSpec | None = None) -> bytes:
@@ -145,6 +155,19 @@ def build_zip(spec: ZipSpec | None = None) -> bytes:
archive.writestr(_regular_file_info(spec.traversal_entry), b'traversal\n')
if spec.bomb_bytes:
archive.writestr(_regular_file_info('artifacts/bomb.csv'), b'\0' * spec.bomb_bytes)
for name, mode in spec.special_mode_entries.items():
info = zipfile.ZipInfo(name)
info.create_system = 3
info.external_attr = mode << 16
archive.writestr(info, b'')
for name in spec.directory_entries:
info = zipfile.ZipInfo(name if name.endswith('/') else f'{name}/')
info.create_system = 3
info.external_attr = (stat.S_IFDIR | 0o755) << 16
archive.writestr(info, b'')
if spec.repeat_file:
content = {**spec.files, **spec.extra_files}[spec.repeat_file]
archive.writestr(_regular_file_info(spec.repeat_file), content)
return buffer.getvalue()