# SecInterp - Detailed Project Architecture
> **Comprehensive Technical Documentation for the SecInterp QGIS Plugin**
> Version 3.11.0 | Last Updated: 2026-10-24
---
## ๐ Table of Contents
1. [Overview](#overview)
2. [Directory Structure](#directory-structure)
3. [System Architecture](#system-architecture)
4. [GUI Layer - User Interface](#gui-layer---user-interface)
5. [Core Layer - Business Logic](#core-layer---business-logic)
6. [Exporters Layer - Data Export](#exporters-layer---data-export)
7. [Design Principles](#design-principles)
8. [Extensibility](#extensibility)
9. [Project Metrics](#project-metrics)
10. [Quality Assurance & Security Scanning](#quality-assurance--security-scanning)
---
## ๐ฏ Overview
**SecInterp** (Section Interpreter) is a QGIS plugin designed for extracting and visualizing geological data in cross-sections. The plugin allows geologists to generate topographic profiles, project geological outcrops, and analyze structural data in a unified 2D view.
### Key Features
- โ
**Interactive Preview System** with real-time rendering and adaptive LOD (Level of Detail) based on zoom.
- โ
**Parallel Processing** for complex geological intersections.
- โ
**DEM & Profile Insights**: DEM band statistics and profile-vs-DEM min/max/mean, plus gradient/single-color profile styling.
- โ
**CRS Safety**: mixed-CRS warnings and a blocking check for mislabelled layer CRS.
- โ
**Adaptive Vertical Exaggeration** (auto, clamped `0.5รโ20ร`) with manual override.
- โ
**Optional Smoothed Topography** profile (distance-window moving average) with matching smoothed geology.
- โ
**Measurement Tools** with automatic snapping.
- โ
**Drillhole Support** with 3Dโ2D trajectory projection.
- โ
**Multi-format Export** (SHP, GPKG, DXF, CSV, PDF, SVG, PNG).
---
## ๐ Directory Structure
The project organization follows a highly modular architecture based on the **Separation of Concerns** (SoC) principle, decoupling the interface, business logic, and export formats. Each layer has a distinct responsibility and communicates through well-defined interfaces.
- `sec_interp/` โ plugin root โ [`layer_plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_plugin.md) ยท [`plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/plugin.md)
- `__init__.py` โ Plugin entry point (registers with QGIS) โ [`root`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/root.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_plugin.md)
- `sec_interp_plugin.py` โ Root class `SecInterp` (facade) โ [`sec_interp_plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/sec_interp_plugin.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/sec_interp_plugin.md)
- `plugin/` โ Plugin mixins composed by `SecInterp` โ [`plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/plugin.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_plugin.md)
- `plugin/lifecycle.py` โ `PluginLifecycleMixin` (`add_action`, `initGui`, `run`, `unload`) โ [`plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/plugin.md)
- `plugin/input_validator.py` โ `InputValidationMixin` (`_get_and_validate_inputs`) โ [`plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/plugin.md)
- `plugin/render_pipeline.py` โ `RenderPipelineMixin` (`draw_preview`) โ [`plugin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/plugin.md)
- `metadata.txt` โ QGIS plugin metadata
- `Makefile` โ Automation (deploy, tests, docs)
- `logger_config.py` โ [`logger_config`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/logger_config.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/logger_config.md)
- `core/` โ๏ธ โ Business Logic (QGIS-agnostic, thread-safe) โ [`layer_core`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core.md)
- `controller.py` โ Orchestrator `ProfileController` โ [`controller`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/controller.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/controller.md)
- `config.py` โ [`config`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/config.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/config.md)
- `data_cache.py` โ [`data_cache`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/data_cache.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/data_cache.md)
- `exceptions.py` โ [`exceptions`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/exceptions.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/exceptions.md)
- `performance_metrics.py` โ [`performance_metrics`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/performance_metrics.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/performance_metrics.md)
- `algorithms.py` โ Reserved placeholder for pure business-logic algorithms โ [`layer_core`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core.md)
- `domain/` โ DTOs `ProfileData`, `GeologySegment`; modules `dtos.py`, `entities.py`, `enums.py`, `spatial_meta.py`, `task_inputs.py` โ [`domain`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/domain.md) ยท [`layer_core_domain`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_domain.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/domain.md)
- `interfaces/` โ ABCs for DI (`IGeologyService`, `IDrillholeService`, `IPreviewService`, โฆ) โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md)
- `models/settings_model.py` โ Typed settings โ [`layer_core_models`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_models.md)
- `validation/` โ Modular pipeline โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) ยท [`layer_core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_validation.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_validation.md)
- `validation/pipeline.py`, `layer_validator.py`, `field_validator.py`, `path_validator.py`, `project_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md)
- `validation/crs_plausibility.py` โ Best-effort mislabelled-CRS detection from extent plausibility โ [`crs_plausibility`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/crs_plausibility.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_validation.md)
- `validation/layer_metadata.py` โ QGIS-agnostic layer metadata for validation โ [`layer_metadata`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_metadata.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_validation.md)
- `utils/` โ Helpers (pure Python) โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md)
- `utils/safe_loader.py` โ [`safe_loader`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/safe_loader.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/safe_loader.md)
- `utils/i18n.py` โ [`core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_utils.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md)
- `utils/geometry_utils/` (`measurement.py`, `optimization.py`, `processing.py`) โ [`layer_core_utils_geometry_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils_geometry_utils.md)
- `services/` โ Concrete implementations โ [`layer_core_services`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services.md)
- `services/geology_service.py` โ [`geology_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/geology_service.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/geology_service.md)
- `services/structure_service.py` โ [`structure_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/structure_service.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/structure_service.md)
- `services/drillhole_service.py` โ [`drillhole_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_service.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_service.md)
- `services/export_service.py` โ 13-line compatibility shim โ [`core_services`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services.md)
- `services/export/` โ Export package (orchestrator + handlers) โ [`core_services_export`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services_export.md) ยท [`layer_core_services_export`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_export.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_export.md)
- `services/export/orchestrator.py`, `path_resolver.py`, `compat.py`; map settings factory lives in `exporters/map_settings.py`
- `services/export/handlers/` (topography, geology, structures, drillholes, drillholes_3d, interpretations, axes) โ [`layer_core_services_export_handlers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_export_handlers.md)
- `services/preview_service.py` โ [`preview_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_service.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_service.md)
- `services/vertical_exaggeration_service.py` โ [`vertical_exaggeration_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vertical_exaggeration_service.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vertical_exaggeration_service.md)
- `services/access_control_service.py` โ [`core_services`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services.md)
- `services/drillhole/` โ Drillhole pipeline โ [`layer_core_services_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_drillhole.md)
- `services/drillhole/collar_processor.py` โ [`collar_processor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/collar_processor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/collar_processor.md)
- `services/drillhole/survey_processor.py` โ [`core_services_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services_drillhole.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_drillhole.md)
- `services/drillhole/interval_processor.py` โ [`interval_processor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interval_processor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interval_processor.md)
- `services/drillhole/projection_engine.py` โ [`core_services_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services_drillhole.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_services_drillhole.md)
- `services/drillhole/trajectory_engine.py` โ [`trajectory_engine`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/trajectory_engine.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/trajectory_engine.md)
- `gui/` ๐ฅ๏ธ โ UI Layer (QGIS-dependent) โ [`layer_gui`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `gui/main_dialog.py` โ `SecInterpDialog` orchestrator โ [`main_dialog`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/main_dialog.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/main_dialog.md)
- `gui/dialog_dependencies.py` โ Narrow dependency containers injected into managers (composition root) โ [`layer_gui`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `gui/dialog_message_mixin.py`, `dialog_lifecycle_mixin.py`, `dialog_facade_mixin.py` โ Message / lifecycle / facade mixins โ [`main_dialog`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/main_dialog.md)
- `gui/interpretation_inheritance_mixin.py`, `interpretation_persistence_mixin.py` โ Attribute inheritance (nearest geology/drillhole) + project persistence โ [`dialog_interpretation_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_interpretation_manager.md)
- `gui/main_dialog_config.py`, `main_dialog_utils.py` โ Dialog configuration, defaults and UI helpers โ [`main_dialog`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/main_dialog.md)
- `gui/utils.py` โ General-purpose UI helpers and user messaging โ [`layer_gui`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `gui/adapters/` โ Extract phase (QGIS โ DTOs) โ [`gui_adapters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_adapters.md) ยท [`layer_gui_adapters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_adapters.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_adapters.md)
- `adapters/drillhole_extractor.py` โ [`drillhole_extractor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_extractor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_extractor.md)
- `adapters/geology_extractor.py` โ [`geology_extractor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/geology_extractor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/geology_extractor.md)
- `adapters/structure_extractor.py` โ [`structure_extractor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/structure_extractor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/structure_extractor.md)
- `adapters/validation_extractor.py` โ [`validation_extractor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/validation_extractor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/validation_extractor.md)
- `adapters/profile_extractor.py` โ [`profile_extractor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/profile_extractor.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_adapters.md)
- `adapters/feature_fetcher.py`, `layer_resolver.py`, `geometry.py` โ [`gui_adapters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_adapters.md)
- Managers (orchestration)
- `dialog_signal_manager.py` โ [`dialog_signal_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_signal_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `dialog_input_manager.py` โ [`dialog_input_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_input_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `dialog_preview_manager.py` โ [`dialog_preview_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_preview_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_preview_manager.md)
- `dialog_export_manager.py` โ [`dialog_export_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_export_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_export_manager.md)
- `dialog_interpretation_manager.py` โ [`dialog_interpretation_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_interpretation_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `dialog_state_manager.py` โ [`dialog_state_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_state_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `dialog_settings_persistence.py` โ [`dialog_state_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_state_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `dialog_tool_manager.py` โ [`dialog_tool_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_tool_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `layer_notification_manager.py` โ [`layer_notification_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_notification_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_notification_manager.md)
- `ui_status_manager.py` โ [`ui_status_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/ui_status_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/ui_status_manager.md)
- `dialogs/` โ Modal dialogs โ [`layer_gui_dialogs`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_dialogs.md)
- `dialogs/interpretation_properties_dialog.py` โ [`layer_gui_dialogs`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_dialogs.md)
- Rendering Engine
- `preview_renderer.py` โ [`preview_renderer`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_renderer.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_renderer.md)
- `preview_layer_factory.py` โ [`preview_layer_factory`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_layer_factory.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_layer_factory.md)
- `preview_axes_manager.py` โ [`preview_axes_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_axes_manager.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_axes_manager.md)
- `preview_param_hasher.py` โ Render-parameter hashing for LOD cache invalidation โ [`preview_param_hasher`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_param_hasher.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `preview_render_mixin.py`, `preview_callbacks_mixin.py` โ Rendering and async-task callback mixins โ [`preview_render_mixin`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_render_mixin.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `preview_task_orchestrator.py` โ Queues, prioritizes and monitors background preview tasks โ [`preview_task_orchestrator`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_task_orchestrator.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `preview_legend_renderer.py` โ Draws the legend (topography, structures, units) on a `QPainter` โ [`preview_legend_renderer`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_legend_renderer.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui.md)
- `preview_reporter.py` โ [`preview_state`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md)
- `preview_state.py` โ [`preview_state`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md)
- `preview_side_panel.py` โ collapsible legend side panel (per-unit hide/color/alias, interpretations list)
- `renderers/` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) ยท [`layer_gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_renderers.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_renderers.md)
- `renderers/base_renderer.py`, `topo/geology/drillhole/structure/interpretation_renderer.py`, `color_manager.py`
- `tasks/` (`geology_task.py`, `drillhole_task.py`) โ [`gui_tasks`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_tasks.md) ยท [`layer_gui_tasks`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_tasks.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_tasks.md)
- `tools/` โ Interactive map tools โ [`layer_gui_tools`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_tools.md)
- `tools/measure_tool.py` โ [`measure_tool`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/measure_tool.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/measure_tool.md)
- `tools/interpretation_tool.py` โ [`interpretation_tool`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_tool.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_tool.md)
- `tools/snapper.py`
- `ui/` โ Programmatic window + sidebar โ [`layer_gui_ui`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui.md)
- `ui/main_window.py`, `ui/sidebar.py` โ [`gui_ui_pages`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_ui_pages.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages.md)
- `ui/pages/` โ Tab-based pages โ [`layer_gui_ui_pages`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages.md)
- `ui/pages/base_page.py`, `dem_page.py`, `section_page.py`, `geology_page.py`, `structure_page.py`, `preview_page.py` โ [`gui_ui_pages`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_ui_pages.md)
- `ui/pages/section_feature_selector.py` โ 2-vertex section selector (`fid โ label`, label field) โ [`gui_ui_pages`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_ui_pages.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/section_feature_selector.md)
- `ui/pages/interpretation_page.py` โ compatibility shim for `InterpretationTab` ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_tab.md)
- `ui/pages/drillhole_page.py` โ [`drillhole_page`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_page.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_page.md)
- `ui/pages/drillhole/` (collar / survey / interval tabs) โ [`gui_ui_pages_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_ui_pages_drillhole.md) ยท [`layer_gui_ui_pages_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages_drillhole.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages_drillhole.md)
- `ui/pages/settings_page.py` โ [`settings_page`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/settings_page.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/settings_page.md)
- `ui/pages/settings/` (default / advanced / symbology / interpretation tabs + persistence) โ [`gui_ui_pages_settings`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_ui_pages_settings.md) ยท [`layer_gui_ui_pages_settings`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages_settings.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_gui_ui_pages_settings.md)
- `exporters/` ๐ค โ Factory `BaseExporter` โ [`layer_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_exporters.md)
- `base_exporter.py` โ [`base_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/base_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/base_exporter.md)
- `vector_exporter.py` โ [`vector_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vector_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vector_exporter.md)
- `dxf_exporter.py` โ [`dxf_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dxf_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dxf_exporter.md)
- `profile_exporters.py` / `csv_exporter.py` โ [`profile_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/profile_exporters.md) ยท [`csv_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/csv_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/csv_exporter.md)
- `interpretation_3d_exporter.py` โ [`interpretation_3d_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_3d_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_3d_exporter.md)
- `interpretation_exporters.py` โ [`interpretation_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_exporters.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_exporters.md)
- `drillhole_3d_exporter.py` โ [`drillhole_3d_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_3d_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_3d_exporter.md)
- `drillhole_exporters.py` โ [`drillhole_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_exporters.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_exporters.md)
- `pdf_exporter.py` โ [`pdf_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/pdf_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/pdf_exporter.md)
- `svg_exporter.py` โ [`svg_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/svg_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/svg_exporter.md)
- `image_exporter.py` โ [`image_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/image_exporter.md) ยท [doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/image_exporter.md)
- `docs/` ๐ โ `ARCHITECTURE_EN.md` (this file) ยท `ARCHITECTURE.mmd` ยท `code_walkthrough_v2/` vault
- `tests/` ๐งช โ `base_test.py`, `core/`, `gui/`, `exporters/`, `integration/`, `agentic/`, `mcp/`, `mocks/`, `benchmarks/` (Mock-First, `unittest`)
- `scripts/` ๐ง โ `security_scan.py` ยท `build_docs.sh` ยท `i18n/` ยท `sync_vault_mirrors.sh`
- `resources/` ๐จ โ `icons/`, `styles/`, `resources.qrc` โ `resources.py`
> [!tip] En Obsidian este รกrbol es navegable: cada `[`slug`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/slug.md)` abre la nota de la bรณveda y alimenta el Graph View. En GitHub/Sphinx usa el link `[doc](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/slug.md)` relativo. Los espejos en `docs/code_walkthrough*/ARCHITECTURE_EN.md` se re-sincronizan con `bash scripts/sync_vault_mirrors.sh`.
---
## ๐๏ธ System Architecture
### Complete Architecture Diagram
```mermaid
graph TD
classDef module fill:#f9f,stroke:#333,stroke-width:2px;
classDef manager fill:#e1f5fe,stroke:#0277bd,stroke-width:2px;
classDef service fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
classDef interface fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,stroke-dasharray: 5 5;
classDef exporter fill:#fce4ec,stroke:#c2185b,stroke-width:2px;
classDef task fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px;
classDef renderer fill:#e0f2f1,stroke:#00695c,stroke-width:2px;
%% ========== ENTRY POINT ==========
QGIS[QGIS Application]
PLUGIN[sec_interp_plugin.py
SecInterp Class
Plugin Root]
%% ========== GUI LAYER ==========
subgraph GUI["๐ฅ๏ธ GUI Layer - User Interface"]
direction TB
MAIN[main_dialog.py
SecInterpDialog]
subgraph MANAGERS["Managers (Orchestration)"]
direction TB
SIGNALS_MGR[dialog_signal_manager.py
DialogSignalManager]:::manager
INPUT_MGR[dialog_input_manager.py
DialogInputManager]:::manager
PREVIEW_MGR[dialog_preview_manager.py
PreviewManager]:::manager
EXPORT_MGR[dialog_export_manager.py
ExportManager]:::manager
INTERP_MGR[dialog_interpretation_manager.py
InterpretationManager]:::manager
STATE_MGR[dialog_state_manager.py
DialogStateManager]:::manager
SETTINGS_MGR[dialog_settings_persistence.py
SettingsPersistence]:::manager
TOOL_MGR[dialog_tool_manager.py
ToolManager]:::manager
LAYER_NOTIF[layer_notification_manager.py
LayerNotificationManager]:::manager
UI_STATUS[ui_status_manager.py
UIStatusManager]:::manager
end
subgraph RENDERING["Rendering Engine"]
direction TB
LAYER_FACTORY[preview_layer_factory.py
PreviewLayerFactory]
AXES_MGR[preview_axes_manager.py
PreviewAxesManager]
RENDERER[preview_renderer.py
PreviewRenderer]
REPORTER[preview_reporter.py
PreviewReporter]
PARAM_HASH[preview_param_hasher.py
PreviewParamHasher]
PREVIEW_STATE[preview_state.py
PreviewState]
end
subgraph RENDERERS["Specialized Renderers"]
direction TB
BASE_RENDERER[renderers/base_renderer.py
BaseRenderer]:::renderer
TOPO_RENDERER[renderers/topo_renderer.py
TopoRenderer]:::renderer
GEOLOGY_RENDERER[renderers/geology_renderer.py
GeologyRenderer]:::renderer
DRILLHOLE_RENDERER[renderers/drillhole_renderer.py
DrillholeRenderer]:::renderer
STRUCT_RENDERER[renderers/structure_renderer.py
StructureRenderer]:::renderer
INTERP_RENDERER[renderers/interpretation_renderer.py
InterpretationRenderer]:::renderer
COLOR_MGR[renderers/color_manager.py
ColorManager]:::renderer
end
subgraph WORKERS["Async Tasks (QgsTask)"]
direction TB
TASK_ORCH[preview_task_orchestrator.py
PreviewTaskOrchestrator]:::task
GEOLOGY_TASK[tasks/geology_task.py
GeologyTask]:::task
DRILL_TASK[tasks/drillhole_task.py
DrillholeTask]:::task
end
subgraph TOOLS["Map Tools"]
direction TB
MAP_TOOLS[tools/
QgsMapTool Implementations]
end
subgraph UI_PAGES["UI Components"]
direction TB
PAGES[ui/pages/
Tab-based Pages]
ADAPTERS[adapters/
UI Adapters]
SIDE_PANEL[preview_side_panel.py
Preview Side Panel]
SYMBOLOGY[symbology_tab.py
Live Symbology]
end
MAIN --> MANAGERS
MAIN --> RENDERING
MAIN --> RENDERERS
MAIN --> WORKERS
MAIN --> TOOLS
MAIN --> UI_PAGES
MAIN --> SIDE_PANEL
MAIN --> SYMBOLOGY
MANAGERS --> RENDERING
MANAGERS --> WORKERS
MANAGERS --> UI_PAGES
WORKERS --> TASK_ORCH
RENDERING --> RENDERERS
end
%% ========== CORE LAYER ==========
subgraph CORE["โ๏ธ Core Layer - Business Logic"]
direction TB
CONTROLLER[controller.py
ProfileController]
subgraph INTERFACES["Abstractions (DI) - interfaces/"]
direction TB
I_GEOL[interfaces/geology_interface.py
IGeologyService]:::interface
I_DRILL[interfaces/drillhole_interface.py
IDrillholeService]:::interface
I_STRUCT[interfaces/structure_interface.py
IStructureService]:::interface
I_PREVIEW[interfaces/preview_interface.py
IPreviewService]:::interface
I_CACHE[interfaces/cache_interface.py
ICacheService]:::interface
I_RENDER3D[interfaces/i_renderer_3d.py
IRenderer3D]:::interface
end
subgraph SERVICES["Concrete Services - services/"]
direction TB
GEOL_SVC[services/geology_service.py
GeologyService]:::service
STRUCT_SVC[services/structure_service.py
StructureService]:::service
DRILL_SVC[services/drillhole_service.py
DrillholeService]:::service
EXPORT_SVC[services/export_service.py
ExportService]:::service
PREVIEW_SVC[services/preview_service.py
PreviewService]:::service
VE_SVC[services/vertical_exaggeration_service.py
VerticalExaggerationService]:::service
ACCESS_SVC[services/access_control_service.py
AccessControlService]:::service
subgraph DRILLHOLE_PKG["Drillhole Sub-system"]
direction TB
COLLAR_PROC[drillhole/collar_processor.py
CollarProcessor]
SURVEY_PROC[drillhole/survey_processor.py
SurveyProcessor]
INTERVAL_PROC[drillhole/interval_processor.py
IntervalProcessor]
PROJ_ENGINE[drillhole/projection_engine.py
ProjectionEngine]
TRAJ_ENGINE[drillhole/trajectory_engine.py
TrajectoryEngine]
DRILL_SVC --> COLLAR_PROC
DRILL_SVC --> SURVEY_PROC
DRILL_SVC --> INTERVAL_PROC
DRILL_SVC --> TRAJ_ENGINE
COLLAR_PROC --> PROJ_ENGINE
SURVEY_PROC --> TRAJ_ENGINE
TRAJ_ENGINE --> PROJ_ENGINE
end
end
subgraph MODELS["Domain Models - models/"]
direction TB
SETTINGS_MODEL[models/settings_model.py
SettingsModel]
end
subgraph DOMAIN["Domain Layer - domain/"]
direction TB
ENTITIES[Entities & DTOs
ProfileData, GeologySegment,
DrillholeData, etc.]
end
subgraph VALIDATION["Validation Pipeline - validation/"]
direction TB
BASE_VAL[base_validator.py
BaseValidator]
PIPELINE[pipeline.py
ValidationPipeline]
LAYER_VAL[layer_validator.py
LayerValidator]
FIELD_VAL[field_validator.py
FieldValidator]
PATH_VAL[path_validator.py
PathValidator]
PROJECT_VAL[project_validator.py
ProjectValidator]
PROJECT_VALS[project_validators.py
ProjectValidators]
HELPERS[validation_helpers.py
ValidationHelpers]
VALIDATORS[validators.py
Validators]
end
subgraph UTILS["Utilities - utils/"]
direction TB
DRILL_UTIL[drillhole.py
Drillhole Utils]
GEOL_UTIL[geology.py
Geology Utils]
GEOM_UTIL[geometry_utils/
Geometry Utilities]
I18N_UTIL[i18n.py
i18n Utils]
IO_UTIL[io.py
IO Utils]
META_UTIL[metadata_reader.py
Metadata Reader]
PARSE_UTIL[parsing.py
Parsing Utils]
RENDER_UTIL[rendering.py
Rendering Utils]
SAFE_LOADER[safe_loader.py
Safe Loader]
SAMPLE_UTIL[sampling.py
Sampling Utils]
SPATIAL_UTIL[spatial.py
Spatial Utils]
end
CONTROLLER --> INTERFACES
INTERFACES -.-> SERVICES
SERVICES --> MODELS
SERVICES --> DOMAIN
SERVICES --> VALIDATION
SERVICES --> UTILS
CONTROLLER --> VALIDATION
end
%% ========== EXPORTERS LAYER ==========
subgraph EXPORTERS["๐ค Exporters Layer"]
direction TB
BASE_EXPORT[exporters/base_exporter.py
BaseExporter]:::exporter
subgraph VECTOR["Vector Exporters"]
direction TB
VEC_EXPORT[exporters/vector_exporter.py
VectorExporter
GPKG/SHP/DXF]:::exporter
DXF_EXPORT[exporters/dxf_exporter.py
DxfExporter]:::exporter
end
subgraph PROFILE["Profile Exporters"]
direction TB
PROF_EXPORT[exporters/profile_exporters.py
ProfileExporters]:::exporter
CSV_EXPORT[exporters/csv_exporter.py
CsvExporter]:::exporter
end
subgraph INTERP_3D["3D Geologic Export"]
direction TB
INTERP_3D[exporters/interpretation_3d_exporter.py
Interpretation3DExporter]:::exporter
INTERP_EXP[exporters/interpretation_exporters.py
InterpretationExporters]:::exporter
end
subgraph DRILL_3D["3D Drillhole Export"]
direction TB
DRILL_3D[exporters/drillhole_3d_exporter.py
Drillhole3DExporter]:::exporter
DRILL_EXP[exporters/drillhole_exporters.py
DrillholeExporters]:::exporter
end
subgraph DOCUMENT["Document Exporters"]
direction TB
PDF_EXPORT[exporters/pdf_exporter.py
PdfExporter]:::exporter
SVG_EXPORT[exporters/svg_exporter.py
SvgExporter]:::exporter
IMG_EXPORT[exporters/image_exporter.py
ImageExporter]:::exporter
end
BASE_EXPORT --> VEC_EXPORT
BASE_EXPORT --> PROF_EXPORT
BASE_EXPORT --> INTERP_3D
BASE_EXPORT --> DRILL_3D
BASE_EXPORT --> PDF_EXPORT
BASE_EXPORT --> SVG_EXPORT
BASE_EXPORT --> IMG_EXPORT
VEC_EXPORT --> DXF_EXPORT
PROF_EXPORT --> CSV_EXPORT
INTERP_3D --> INTERP_EXP
DRILL_3D --> DRILL_EXP
end
%% ========== CONNECTIONS ==========
QGIS --> PLUGIN
PLUGIN --> MAIN
%% GUI -> Core
PREVIEW_MGR --> PREVIEW_SVC
EXPORT_MGR --> EXPORT_SVC
INTERP_MGR --> DRILL_SVC
INTERP_MGR --> GEOL_SVC
TOOL_MGR --> CONTROLLER
%% Workers -> Controller
TASK_ORCH --> CONTROLLER
GEOLOGY_TASK --> CONTROLLER
DRILL_TASK --> CONTROLLER
%% Core -> Exporters
EXPORT_SVC --> EXPORTERS
%% Styles
classDef plugin fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px,color:#fff
class PLUGIN plugin
```
---
## ๐ฅ๏ธ GUI Layer - User Interface
### 1. Manager-Based Orchestration (main_dialog.py)
**Main Class**: `SecInterpDialog`
**Responsibility**: The main dialog no longer contains business logic. It coordinates specialized **Managers** that handle specific lifecycle events and UI state.
#### Key Managers (10 Specialized Managers)
| Manager | File | Responsibility |
|---------|------|----------------|
| `DialogSignalManager` | `dialog_signal_manager.py` โ [`dialog_signal_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_signal_manager.md) | Centralizes all signal/slot connections to avoid spaghetti code. |
| `DialogInputManager` | `dialog_input_manager.py` โ [`dialog_input_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_input_manager.md) | Manages input layer selection, schema validation, and layer compatibility. |
| `PreviewManager` | `dialog_preview_manager.py` โ [`dialog_preview_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_preview_manager.md) | Coordinates the preview canvas, axes, LOD calculation, and render triggering. |
| `ExportManager` | `dialog_export_manager.py` โ [`dialog_export_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_export_manager.md) | Maps UI selections to the `ExportService` in the Core layer. |
| `InterpretationManager` | `dialog_interpretation_manager.py` โ [`dialog_interpretation_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_interpretation_manager.md) | Handles 2D/3D geological interpretation state and user interactions. |
| `DialogStateManager` | `dialog_state_manager.py` โ [`dialog_state_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_state_manager.md) | Manages session persistence and UI defaults restoration. |
| `SettingsPersistence` | `dialog_settings_persistence.py` โ [`dialog_state_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_state_manager.md) | Handles QSettings-based persistence for plugin configuration. |
| `ToolManager` | `dialog_tool_manager.py` โ [`dialog_tool_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_tool_manager.md) | Manages `QgsMapTool` lifecycle (pan, measure, interpret tools). |
| `LayerNotificationManager` | `layer_notification_manager.py` โ [`layer_notification_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_notification_manager.md) | Listens to QGIS layer tree changes and updates UI accordingly. |
| `UIStatusManager` | `ui_status_manager.py` โ [`ui_status_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/ui_status_manager.md) | Manages status bar messages, progress indicators, and user notifications. |
### 2. Rendering Engine
**Responsibility**: Handles all preview canvas rendering with adaptive LOD and specialized renderers.
#### Core Rendering Components
| Component | File | Responsibility |
|---------|------|----------------|
| `PreviewRenderer` | `preview_renderer.py` โ [`preview_renderer`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_renderer.md) | Main canvas renderer orchestrating specialized renderers. |
| `PreviewLayerFactory` | `preview_layer_factory.py` โ [`preview_layer_factory`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_layer_factory.md) | Creates temporary memory layers for preview visualization. |
| `PreviewAxesManager` | `preview_axes_manager.py` โ [`preview_axes_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_axes_manager.md) | Manages coordinate axes, grids, and scale annotations. |
| `PreviewReporter` | `preview_reporter.py` โ [`preview_state`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md) | Generates textual/tabular reports from preview data. |
| `PreviewParamHasher` | `preview_param_hasher.py` โ [`dialog_preview_manager`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dialog_preview_manager.md) | Hashes render parameters for LOD cache invalidation. |
| `PreviewState` | `preview_state.py` โ [`preview_state`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_state.md) | Encapsulates preview viewport, scale, and visibility state. |
#### Specialized Renderers (Renderer Pattern)
| Renderer | File | Responsibility |
|----------|------|----------------|
| `BaseRenderer` | `renderers/base_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Abstract base with common rendering utilities. |
| `TopoRenderer` | `renderers/topo_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Renders topography profiles with elevation data. |
| `GeologyRenderer` | `renderers/geology_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Renders geological units, contacts, and structures. |
| `DrillholeRenderer` | `renderers/drillhole_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Renders drillhole traces, intervals, and projections. |
| `StructureRenderer` | `renderers/structure_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Renders structural measurements (strike/dip, foliations). |
| `InterpretationRenderer` | `renderers/interpretation_renderer.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Renders user-drawn geological interpretations. |
| `ColorManager` | `renderers/color_manager.py` โ [`gui_renderers`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_renderers.md) | Centralized color palette and legend management. |
**LOD Optimization Methods** (in `PreviewRenderer`):
| Method | Purpose | Algorithm |
|--------|---------|-----------|
| `_decimate_line_data()` | Line simplification | Douglas-Peucker |
| `_calculate_curvature()` | Local curvature calculation | Angle between segments |
| `_adaptive_sample()` | Adaptive sampling | Curvature-based density |
### 3. Async Task System (QgsTask)
**Responsibility**: Offloads heavy computation to background threads keeping UI responsive.
| Task | File | Responsibility |
|------|------|----------------|
| `PreviewTaskOrchestrator` | `preview_task_orchestrator.py` โ [`gui_tasks`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_tasks.md) | Queues, prioritizes, and monitors background tasks. |
| `GeologyTask` | `tasks/geology_task.py` โ [`gui_tasks`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_tasks.md) | Background geological intersection calculations. |
| `DrillholeTask` | `tasks/drillhole_task.py` โ [`gui_tasks`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/gui_tasks.md) | Background drillhole trajectory processing. |
### 4. Map Tools & UI Components
- **Map Tools** (`tools/`): `QgsMapTool` implementations for interactive editing (pan, measure, interpretation drawing).
- **UI Pages** (`ui/pages/`): Page components for each plugin module; Interpretation Settings is hosted as a tab in `SettingsPage`, not a sidebar page.
- **Section feature selector** (`ui/pages/section_feature_selector.py`): only single-part lines with exactly two vertices; shows `fid โ label`, supports `Auto` or an attribute label field, and forwards `section_feature_id` to preview/export/LOD.
- **Interpretation settings tab** (`ui/pages/settings/interpretation_tab.py`): storage source (project JSON vs vector layer), custom fields and attribute inheritance; `MainWindow.page_interpretation` aliases the tab for compatibility.
- **UI Adapters** (`adapters/`): Adapters bridging QGIS widgets to internal models.
- **PreviewSidePanel** (`preview_side_panel.py`): Collapsible legend beside the preview, synchronized with the renderers; per-unit hide/color/alias, drillhole lithologies and the interpretations list.
- **Symbology tab** (`ui/pages/settings/symbology_tab.py`, `symbology_units.py`): Live per-layer styles (topography, structures, drillholes, interpretations), the shared per-unit editor and the legend layout (position, font size, max items).
## โ๏ธ Core Layer - Business Logic
### 1. Interface-Driven Design (interfaces/)
**Pattern**: Dependency Injection (DI) via Abstract Base Classes (ABCs)
**Responsibility**: All services are defined as interfaces. The `ProfileController` consumes interfaces, allowing for easy mocking during testing and replacement of logic without affecting the GUI.
```python
class IGeologyService(ABC):
@abstractmethod
def build_segments(self, context: GeologyContext, feedback: Any | None = None) -> Any:
"""Build geological segments from a detached context."""
```
#### Core Interfaces (6 Interfaces)
| Interface | File | Purpose |
|-----------|------|---------|
| `IGeologyService` | `interfaces/geology_interface.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `build_segments()` โ geological segments from a detached context. |
| `IDrillholeService` | `interfaces/drillhole_interface.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `process_context()` โ drillhole data processing, 3Dโ2D projection. |
| `IStructureService` | `interfaces/structure_interface.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `project_structures()` โ structural data validation and projection. |
| `IPreviewService` | `interfaces/preview_interface.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `generate_all()` โ preview orchestration and render data prep. |
| `ICacheService` | `interfaces/cache_interface.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `get/set/invalidate/clear` โ caching strategy (typing `Protocol`). |
| `IRenderer3D` | `interfaces/i_renderer_3d.py` โ [`layer_core_interfaces`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_interfaces.md) | `render_3d()`/`clear()` โ 3D visualization abstraction. |
### 2. ProfileController (controller.py)
**Responsibility**: Central orchestrator coordinating all services through their interfaces.
#### Concrete Services (7 Services)
| Service | File | Responsibility |
|---------|------|----------------|
| `GeologyService` | `services/geology_service.py` โ [`geology_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/geology_service.md) | Core intersection algorithms (outcrops, polygons, units). |
| `StructureService` | `services/structure_service.py` โ [`structure_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/structure_service.md) | Structural data processing, validation, stereonets. |
| `DrillholeService` | `services/drillhole_service.py` โ [`drillhole_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_service.md) | 3D trajectory calculation, 2D section projection, interval management. |
| `ExportService` | `services/export_service.py` โ [`core_services`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services.md) | Central orchestrator for Exporters layer, format registry. |
| `PreviewService` | `services/preview_service.py` โ [`preview_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/preview_service.md) | Preview data preparation, LOD computation, render DTOs. |
| `VerticalExaggerationService` | `services/vertical_exaggeration_service.py` โ [`vertical_exaggeration_service`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vertical_exaggeration_service.md) | Adaptive vertical exaggeration from profile aspect ratio and structural density. |
| `AccessControlService` | `services/access_control_service.py` โ [`core_services`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services.md) | License validation, feature gating, user permissions. |
#### Drillhole Sub-system (5 Components)
| Component | File | Responsibility |
|-----------|------|----------------|
| `CollarProcessor` | `drillhole/collar_processor.py` โ [`collar_processor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/collar_processor.md) | Collar data validation, coordinate transformation. |
| `SurveyProcessor` | `drillhole/survey_processor.py` โ [`core_services_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services_drillhole.md) | Survey data (azimuth/dip) processing, interpolation. |
| `IntervalProcessor` | `drillhole/interval_processor.py` โ [`interval_processor`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interval_processor.md) | Lithology/assay interval management, merging. |
| `TrajectoryEngine` | `drillhole/trajectory_engine.py` โ [`trajectory_engine`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/trajectory_engine.md) | 3D trajectory calculation (minimum curvature, etc.). |
| `ProjectionEngine` | `drillhole/projection_engine.py` โ [`core_services_drillhole`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_services_drillhole.md) | 3Dโ2D projection onto section plane. |
#### Geology Sub-system
- Geology processing is consolidated in `services/geology_service.py` (the former `services/geology/` package was removed).
### 3. Domain Layer
- **Domain Models** (`models/settings_model.py`): `SettingsModel` for typed configuration.
- **Entities & DTOs** (`domain/`): Immutable data transfer objects (`ProfileData`, `GeologySegment`, `DrillholeData`, etc.) for layer communication.
### 4. Validation Pipeline (validation/)
Modular validation framework with 11 validators coordinated by `ValidationPipeline`:
| Validator | File | Scope |
|-----------|------|-------|
| `BaseValidator` | `base_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Abstract base with common validation utilities. |
| `ValidationPipeline` | `pipeline.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Orchestrates validators, aggregates results. |
| `LayerValidator` | `layer_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | QGIS layer structure, CRS, geometry type validation. |
| `FieldValidator` | `field_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Attribute field names, types, required fields. |
| `PathValidator` | `path_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | File/directory paths, permissions, existence. |
| `ProjectValidator` | `project_validator.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Project-level consistency (layers, settings). |
| `ProjectValidators` | `project_validators.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Composite project validation rules. |
| `ValidationHelpers` | `validation_helpers.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Shared validation utilities, error formatting. |
| `Validators` | `validators.py` โ [`core_validation`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_validation.md) | Convenience functions for common validations. |
| `LayerMetadata` | `layer_metadata.py` โ [`layer_metadata`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_metadata.md) | QGIS-agnostic layer metadata DTO consumed by the pipeline. |
| `implausible_crs_reason()` | `crs_plausibility.py` โ [`crs_plausibility`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/crs_plausibility.md) | Best-effort mislabelled-CRS detection from extent plausibility. |
### 5. Utilities (utils/)
11 specialized utility modules:
| Utility | File | Purpose |
|---------|------|---------|
| Drillhole Utils | `drillhole.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Drillhole-specific calculations, transformations. |
| Geology Utils | `geology.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Geological computations, unit conversions. |
| Geometry Utils | `geometry_utils/` โ [`layer_core_utils_geometry_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils_geometry_utils.md) | Advanced geometry operations (intersections, buffers). |
| i18n Utils | `i18n.py` โ [`core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/core_utils.md) | Translation helpers, locale management. |
| QGIS I/O | `exporters/qgis_io.py` โ [`layer_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_exporters.md) | Vector writer adapter (Shapefile/GPKG/DXF). |
| Metadata Reader | `metadata_reader.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | QGIS layer metadata extraction. |
| Parsing Utils | `parsing.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Text/CSV/XML parsing with error recovery. |
| Rendering Utils | `rendering.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Render-ready data preparation. |
| Safe Loader | `safe_loader.py` โ [`safe_loader`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/safe_loader.md) | Safe YAML/JSON loading with schema validation. |
| Sampling Utils | `sampling.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Statistical sampling, profile point generation. |
| Spatial Utils | `spatial.py` โ [`layer_core_utils`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/layer_core_utils.md) | Spatial queries, indexing, CRS operations. |
## ๐ค Exporters Layer
The Exporters layer implements the **Factory Pattern** via `BaseExporter` abstract class. All exporters consume QGIS-agnostic DTOs from `core/domain`.
### Export Hierarchy
```
BaseExporter (ABC)
โโโ VectorExporter โ DxfExporter
โ โโโ GPKG, SHP, DXF output
โ โโโ Layer-based feature export
โโโ ProfileExporters โ CsvExporter
โ โโโ Profile data (CSV, Excel)
โ โโโ Sampling results export
โโโ Interpretation3DExporter โ InterpretationExporters
โ โโโ 3D geological interpretations (Z-aware)
โ โโโ GeoPackage 3D, CityJSON
โโโ Drillhole3DExporter โ DrillholeExporters
โ โโโ 3D drillhole traces (Z-aware)
โ โโโ Interval data as 3D cylinders
โโโ PdfExporter
โ โโโ Professional layouts with legends
โ โโโ Multi-page section reports
โโโ SvgExporter
โ โโโ Vector graphics for publications
โ โโโ Scalable section diagrams
โโโ ImageExporter
โโโ PNG/JPG raster output
โโโ High-DPI for presentations
```
### Key Exporters
| Exporter | File | Formats | Purpose |
|----------|------|---------|---------|
| `VectorExporter` | `vector_exporter.py` โ [`vector_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/vector_exporter.md) | GPKG, SHP, DXF | Unified vector export for sections. |
| `DxfExporter` | `dxf_exporter.py` โ [`dxf_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/dxf_exporter.md) | DXF | CAD-compatible export. |
| `ProfileExporters` | `profile_exporters.py` โ [`profile_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/profile_exporters.md) | CSV, XLSX | Profile data tables, sampling results. |
| `CsvExporter` | `csv_exporter.py` โ [`csv_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/csv_exporter.md) | CSV | Raw data export. |
| `Interpretation3DExporter` | `interpretation_3d_exporter.py` โ [`interpretation_3d_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_3d_exporter.md) | GPKG 3D, CityJSON | 3D geological interpretations. |
| `InterpretationExporters` | `interpretation_exporters.py` โ [`interpretation_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/interpretation_exporters.md) | Multiple | Interpretation-specific formats. |
| `Drillhole3DExporter` | `drillhole_3d_exporter.py` โ [`drillhole_3d_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_3d_exporter.md) | GPKG 3D, WellKnown Text | 3D drillhole traces & intervals. |
| `DrillholeExporters` | `drillhole_exporters.py` โ [`drillhole_exporters`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/drillhole_exporters.md) | Multiple | Drillhole-specific formats. |
| `PdfExporter` | `pdf_exporter.py` โ [`pdf_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/pdf_exporter.md) | PDF | Professional section layouts. |
| `SvgExporter` | `svg_exporter.py` โ [`svg_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/svg_exporter.md) | SVG | Vector graphics for reports. |
| `ImageExporter` | `image_exporter.py` โ [`image_exporter`](https://github.com/geociencio/sec_interp/blob/main/docs/code_walkthrough_v2/image_exporter.md) | PNG, JPG | Raster images for presentations. |
### Format Decoupling
All exporters implement:
- `export(dto: ExportDTO, output_path: Path) -> ExportResult`
- Consume only `core/domain` DTOs (no QGIS dependencies)
- Return structured `ExportResult` with metadata (files created, features exported, warnings)
## ๐จ Design Principles
SecInterp v3.9.1 follows industry-standard architectural patterns to ensure high quality and testability.
### Core Architectural Patterns
- **Manager Pattern (GUI)**: Decouples the main window from individual feature logic (Export, Preview, etc.).
- **Dependency Injection (Core)**: Uses `core/interfaces` to decouple the `ProfileController` from concrete service implementations.
- **Factory Pattern (Exporters)**: The `ExportService` dynamically selects the appropriate `BaseExporter` subclass.
- **Observer Pattern (Signals)**: Extensive use of `qgis.PyQt.QtCore.pyqtSignal` for asynchronous communication between Core and GUI.
- **DTO Pattern (Data Transfer Objects)**: All data passing between layers is encapsulated in immutable DTOs from `core/domain`.
### SOLID & Clean Code
- **Interface Segregation**: Clients only depend on the specific service interfaces they need.
- **Single Responsibility**: Each Manager and Service handles a unique, atomic part of the plugin workflow.
- **Thread Safety**: Long-running operations only use `QgsTask` to avoid blocking the QGIS main thread.
---
## ๐ Extensibility
### Adding a New Service
1. Define the interface in `core/interfaces/` (inheriting from `abc.ABC`).
2. Implement the concrete service in `core/services/`.
3. Register the service in `controller.py` and inject it into the `ProfileController`.
### Adding a New Export Format
1. Inherit from `BaseExporter` in `exporters/`.
2. Implement the `export()` method using QGIS-agnostic logic.
3. Update the `ExportService` to include the new format in its registry.
---
## ๐ Project Metrics
| Metric | Value |
|--------|-------|
| **Python Modules** | 200 |
| **Source Lines of Code (SLOC)** | ~24,400 |
| **Core Layer** | ~34% |
| **GUI Layer** | ~54% |
| **Exporters Layer** | ~9% |
| **Plugin Layer** | ~2% |
---
## ๐ Quality Assurance & Security Scanning
SecInterp implements a multi-layered quality assurance strategy that replicates and extends the QGIS Plugin Portal's automated scanning pipeline.
### 1. Local Security Scanning (Portal-Compatible)
The project includes a custom security scanner (`scripts/security_scan.py`) that runs the **exact same tools** used by QGIS Plugin Portal:
| Tool | Severity | Purpose | Configuration |
|------|----------|---------|---------------|
| **Bandit** | CRITICAL (Blocking) | Static analysis for Python security vulnerabilities (shell injection, pickle, eval, hardcoded secrets, weak crypto, SQL injection) | `.bandit` (excludes tests/scripts, 72 tests enabled) |
| **detect-secrets** | CRITICAL (Blocking) | Scans for hardcoded credentials, API keys, private keys, high-entropy strings | `.secrets.baseline` (27 detectors, heuristic filters, excludes tests/venv) |
| **Flake8** | INFO (Non-blocking) | Code quality, PEP 8 style, syntax errors, undefined names | `.flake8` (max-line-length=100, max-complexity=15, JSON output) |
**Run locally:**
```bash
make security-scan # Full portal-compatible scan
make pylint # Additional static analysis
make pep8 # Ruff-based style check (faster)
```
### 2. QGIS Plugin Analyzer (Deep Auditing)
For architectural and deep code quality audits beyond Portal scanning:
```bash
# Security (Bandit + detect-secrets)
uv run qgis-analyzer security .
# Internationalization coverage
uv run qgis-analyzer analyze i18n .
# Performance (UI blocks, expensive loops, signal leaks)
uv run qgis-analyzer analyze performance .
# Architecture (Core/GUI separation, QGIS API usage, circular deps)
uv run qgis-analyzer analyze architecture .
# Full HTML report
uv run qgis-analyzer analyze . --report
```
**Workflow**: `/audit-plugin` (agent `@auditor` with skills: project-context, coding-standards, i18n-standards)
### 3. Qt6 / QGIS 4 Migration Readiness
Automated compatibility checking using the **same tool** QGIS Portal runs on upload:
```bash
make qt6-check # Dry-run check (pyqgis4-checker via Docker)
make qt6-fix # Auto-migrate enums to scoped Qt6 form (edits files)
```
### 4. Pre-Release Validation Pipeline
Complete validation before any release candidate:
```bash
make pre-release # Runs: qt6-check + security-scan + docker-test
```
**`docker-test`** executes the full suite (763 tests, including 76 integration tests) in a clean QGIS Docker environment.
### 5. CI/CD Integration
All tools are configured to run in CI pipelines with:
- **Zero critical Bandit findings** required for merge
- **Zero detect-secrets findings** (above baseline) required for merge
- **Flake8 warnings** reported but non-blocking
- **Full test suite** (unit + integration) must pass
### 6. Configuration Files (Committed to Repo)
| File | Purpose | Portal Compatible |
|------|---------|-------------------|
| `.bandit` | Bandit test selection, exclude dirs | โ
|
| `.secrets.baseline` | detect-secrets baseline, filters, excludes | โ
|
| `.flake8` | Flake8 rules, complexity, output format | โ
|
| `pyproject.toml` | Ruff, pytest, mypy config | โ ๏ธ (dev only) |
---
## ๐ Final Notes
This document provides a detailed overview of the SecInterp plugin architecture. For development information, please refer to [README_DEV.md](file:///home/jmbernales/qgispluginsdev/sec_interp/README_DEV.md).
**Last Updated**: 2026-10-24
**Plugin Version**: 3.11.0
**Author**: Juan M. Bernales