Module boundary enforcement. Use when creating modules, reviewing imports, or validating the modular monolith architecture. Prevents cross-module imports, enforces package structure, and defines file ownership per phase.
Enforce strict module isolation in the modular monolith. Prevents cross-module imports, ensures correct package structure, and validates file ownership during parallel development.
Every module follows this pattern:
app/modules/{module_name}/
├── __init__.py # Public API — exports ONLY the entry function
├── {module_name}.py # Core implementation
└── (internal helpers) # Private, never imported externally
# ✅ ALLOWED — contracts are shared
from contracts.entity import EntityResult
from contracts.processed import ProcessedData
# ✅ ALLOWED — stdlib
import logging, subprocess, hashlib, os, json
# ❌ FORBIDDEN — cross-module import
from app.modules.stage_a.internal import process_data
# ❌ FORBIDDEN — database access in modules
import sqlite3
from database.adapter import DatabaseAdapter
Each module exposes exactly ONE entry function:
# app/modules/processing/__init__.py
from .processing import process
def process(input_dto: InputDTO, config: dict) -> OutputDTO:
...
contracts/contracts/app/modules/__init__.py exports| Package | Who Can Import | Contains |
|---|---|---|
contracts/ | All modules | Frozen dataclass DTOs only |
config/ | Orchestrator only | YAML config files |
database/ | Orchestrator only | DB adapter + engine implementations |
app/orchestrator/ | app/main.py only | Pipeline sequencing |
Modules may NOT import from:
app/modules/* packagesapp/orchestrator/database/| Phase | Owned Directories | DO NOT TOUCH |
|---|---|---|
| Phase 0 | database/, config/, app/main.py | app/modules/ |
| Phase N | app/modules/{stage_name}/ | Other modules |
# ❌ Module reads another module's output file directly
with open(f"output/{entity_id}/data.json") as f:
data = json.load(f)
# ✅ Module receives data via DTO from orchestrator
def process(input_dto: InputDTO, config: dict) -> OutputDTO:
...
# ❌ Module calls another module
from app.modules.stage_a import process as stage_a_process
result = stage_a_process(data, config)
app.modules.* in any module (only contracts.*)__init__.py exports only the public entry function