Skip to content

Development Guide

Ryan edited this page Jul 18, 2026 · 1 revision

Development Guide

Standards, workflow, and tooling for contributing to Apotropaios.

Quality Gates (Non-Negotiable)

Every commit must pass:

make typecheck      # mypy --strict: 0 errors / 35 files
make test           # pytest: 322/322 passing
make security-scan  # 6 static pattern checks passing

Setup

git clone https://github.com/Sandler73/Apotropaios-Firewall-Manager-Python-Variant.git
cd Apotropaios-Firewall-Manager-Python
make dev-setup && source .venv/bin/activate
make check     # Full CI verification

Coding Standards

Mandatory Requirements

  1. Type annotations: Full annotations on every function (params + return type)
  2. from __future__ import annotations: At top of every module
  3. Docstrings: Google-style on all public functions/classes with Args/Returns/Raises
  4. Module headers: File, Project, Synopsis, Description, Notes, Version
  5. No shell=True: All subprocess calls use list-form arguments
  6. Capture stderr: capture_output=True on all subprocess calls
  7. Validate input: Through core/validation.py before any use
  8. Atomic writes: temp → os.replace()os.chmod(0o600) for persistent data
  9. Thread safety: threading.Lock on shared mutable state
  10. Layer ordering: No upward imports (core → detection → backends → engine → UI)
  11. No stubs: Every function fully implemented when committed (Lesson PY-003)

Correct vs Incorrect Examples

# CORRECT -- full annotations, list-form subprocess
def validate_port(value: str) -> int:
    """Validate a TCP/UDP port number.
    
    Args:
        value: String representation of port number.
    
    Returns:
        Validated port as integer.
    
    Raises:
        ValidationError: If port is invalid.
    """
    port = int(value)
    if not (1 <= port <= 65535):
        raise ValidationError(f"Port out of range: {port}")
    return port

# WRONG -- missing types, shell=True
def validate_port(value):
    return int(value)

Naming

Type Convention Example
Modules snake_case.py os_detect.py
Classes PascalCase IptablesBackend
Functions snake_case validate_port
Constants UPPER_SNAKE TERMINAL_ACTIONS
Private _leading _build_match_args
Singletons lower_snake rule_index

Testing

make test              # Full: lint + unit + integration + security
make test-quick        # Unit only (fast loop)
make test-validation   # Individual module
make test-report       # Per-file breakdown
make test-coverage     # HTML coverage report

Requirements for PRs:

  • New feature → unit tests (normal + error paths)
  • Bug fix → regression test
  • New validator → valid + invalid input tests
  • New CLI command → subprocess integration test

Adding a New Backend

  1. Create firewall/newbackend.py, subclass FirewallBackend
  2. Implement all 12 abstract methods
  3. Register: register_backend(_instance) at module level
  4. Add to SUPPORTED_FIREWALLS in constants.py
  5. Add detection in fw_detect.py
  6. Import in cli.py _initialize()
  7. Add tests, update docs
  8. make check must pass

Commit Messages

feat(scope): description
fix(scope): description
docs(scope): description
test(scope): description

Apotropaios -- Python Variant

Getting Started

Architecture

Operations

Project


35 files · 14,545 lines · 322 tests

Clone this wiki locally