Structum Bootstrap (structum-bootstrap)

Documentation Source Code Python 3.11+ License: Apache-2.0

Structum Bootstrap provides “Fail Fast” mechanisms to validate the execution environment at application startup.

Feature

Status

Version

Status

Alpha

0.1.0

Namespace

structum_lab.plugins.bootstrap

Dependencies

pydantic, psutil (opt)


Index

  1. What is Bootstrap Plugin

  2. Core Concepts

  3. Quick Start (5 Minutes)

  4. Built-in Validators

  5. Custom Validators

  6. Bootstrap Context

  7. Error Handling

  8. Advanced Patterns

  9. Production Deployment

  10. API Reference


1. What is Bootstrap Plugin

structum-bootstrap implements the “Professional Paranoia” philosophy: explicit verification of runtime state before application startup.

1.1 The Problem

Before (Without Plugin):

# ❌ Implicit Assumptions
app.run()

# Runtime errors after deploy:
# - "DATABASE_URL not set"
# - "/var/log/app not writable"  
# - "Python 3.8 required, found 3.7"

After (With Plugin):

# ✅ Explicit Validation
boot = SystemBootstrapper()
boot.add_validator(EnvValidator(required=["DATABASE_URL"]))
boot.add_validator(DirectoryValidator("/var/log/app", writable=True))
boot.add_validator(PythonVersionValidator(min_version="3.9"))

boot.run_or_exit()  # Fails FAST with detailed report

# If we reach here, the environment is GUARANTEED valid
app.run()

1.2 Key Features

Feature

Description

Fail Fast

Errors at startup, not runtime

Detailed Reports

Textual report with all checks

Type Safe

Protocol-based Validators

Extensible

Create custom validators easily

Zero Secrets Leak

Validates ENV existence without logging values

Production Ready

Filesystem, network, database connectivity validation

1.3 Philosophy: Explicit > Implicit

        graph TD
    subgraph "Traditional Approach (Implicit)"
        A["app.run"] --> B{"Check Runtime?"}
        B -->|No| C["Assume DB_URL exists"]
        B -->|No| D["Assume /logs writable"]
        C & D --> E["Runtime Crash 💥"]
        style E fill:#ffcccc,stroke:#cc0000
    end

    subgraph "Structum Approach (Explicit)"
        X["boot.validate"] --> Y["Check Environment"]
        Y --> Y1["Check DB_URL"]
        Y --> Y2["Check /logs"]
        Y --> Y3["Check Python Ver"]
        Y1 & Y2 & Y3 -->|All Pass| Z["app.run GUARANTEED Safe ✅"]
        Y1 & Y2 & Y3 -->|Fail| F["Exit Immediately with Report"]
        style Z fill:#ccffcc,stroke:#006600
        style F fill:#ffffcc,stroke:#aaaa00
    end
    

2. Core Concepts

2.1 SystemBootstrapper

The central orchestrator that runs validators in sequence:

bootstrapper = SystemBootstrapper()
bootstrapper.add_validator(validator1)
bootstrapper.add_validator(validator2)

# Run validation
result = bootstrapper.run()

if not result.success:
    print(result.report)
    sys.exit(1)

2.2 Validator Protocol

Every validator implements this contract:

from typing import Protocol

class Validator(Protocol):
    """Protocol for custom validators."""
    
    def validate(self, context: ValidationContext) -> None:
        """
        Executes validation.
        Records results in context.
        """
        ...

2.3 ValidationContext

Container for validation results:

context = ValidationContext()

# Record check success
context.add_check("Database", success=True, message="Connected OK")

# Record check failure
context.add_check("Redis", success=False, message="Connection timeout")

# Check status
if context.has_failures():
    print(context.get_report())

3. Quick Start (5 Minutes)

Step 1: Installation

pip install -e packages/bootstrap

Step 2: Basic Validation

from structum_lab.plugins.bootstrap import (
    SystemBootstrapper,
    EnvValidator,
    PythonVersionValidator
)

def main():
    # 1. Create bootstrapper
    boot = SystemBootstrapper()
    
    # 2. Add validators
    boot.add_validator(
        EnvValidator(required=["DATABASE_URL", "API_KEY"])
    )
    boot.add_validator(
        PythonVersionValidator(min_version="3.9")
    )
    
    # 3. Run validation
    boot.run_or_exit()  # Exits with code 1 if validation fails
    
    # 4. Start application (guaranteed valid environment)
    print("✅ Environment validated - starting application")
    start_application()

if __name__ == "__main__":
    main()

Step 3: Test Validation

# Missing env var - should fail
python main.py
# Output:
# ❌ Bootstrap Validation Failed
# 
# Environment Variables:
#   ✗ DATABASE_URL: Missing
#   ✗ API_KEY: Missing
# 
# Python Version:
#   ✓ Version 3.11.0 >= 3.9 (required)

# Set env vars
export DATABASE_URL=postgresql://localhost/mydb
export API_KEY=secret-key-123

python main.py
# Output:
# ✅ Environment validated - starting application

4. Built-in Validators

4.1 EnvValidator

Validates that environment variables exist.

from structum_lab.plugins.bootstrap import EnvValidator

# Required vars
validator = EnvValidator(required=["DB_URL", "API_KEY"])

# Optional vars (warns if missing)
validator = EnvValidator(
    required=["DB_URL"],
    optional=["REDIS_URL", "CACHE_TTL"]
)

# Custom names for reporting
validator = EnvValidator(
    required={
        "DATABASE_URL": "Primary Database Connection",
        "REDIS_URL": "Cache Server Connection"
    }
)

Security Note: validator logs only presence, never values.

✓ DATABASE_URL: Present
✗ API_KEY: Missing

4.2 PythonVersionValidator

Validates Python runtime version.

from structum_lab.plugins.bootstrap import PythonVersionValidator

# Minimum version
validator = PythonVersionValidator(min_version="3.9")

# Exact version range
validator = PythonVersionValidator(
    min_version="3.9",
    max_version="3.11"
)

# Specific versions
validator = PythonVersionValidator(
    allowed_versions=["3.10", "3.11"]
)

4.3 DirectoryValidator

Validates that directories exist and are writable.

from structum_lab.plugins.bootstrap import DirectoryValidator

# Check existence
validator = DirectoryValidator("/var/log/myapp")

# Check writable
validator = DirectoryValidator(
    "/var/log/myapp",
    writable=True
)

# Check readable
validator = DirectoryValidator(
    "/etc/myapp",
    readable=True
)

# Auto-create if missing
validator = DirectoryValidator(
    "/var/log/myapp",
    writable=True,
    create_if_missing=True
)

4.4 ConfigValidator

Validates that Structum config loads correctly.

from structum_lab.plugins.bootstrap import ConfigValidator

# Basic validation
validator = ConfigValidator()

# Validate specific keys exist
validator = ConfigValidator(
    required_keys=["database.url", "app.name"]
)

# Validate config provider
validator = ConfigValidator(
    provider_class=DynaconfConfigProvider
)

4.5 DatabaseValidator

Validates database connectivity.

from structum_lab.plugins.bootstrap import DatabaseValidator

# Basic connectivity check
validator = DatabaseValidator(
    url="postgresql://localhost/mydb"
)

# With timeout
validator = DatabaseValidator(
    url="postgresql://localhost/mydb",
    timeout=5.0  # seconds
)

# From config
validator = DatabaseValidator.from_config()

4.6 FileValidator

Validates existence and permissions of files.

from structum_lab.plugins.bootstrap import FileValidator

# Check file exists
validator = FileValidator("/etc/myapp/config.toml")

# Check readable
validator = FileValidator(
    "/etc/myapp/config.toml",
    readable=True
)

# Check specific size constraints
validator = FileValidator(
    "/var/lib/myapp/data.db",
    max_size_mb=1000
)

5. Custom Validators

5.1 Simple Custom Validator

from structum_lab.plugins.bootstrap import Validator, ValidationContext

class PortAvailableValidator(Validator):
    """Check if network port is available."""
    
    def __init__(self, port: int):
        self.port = port
    
    def validate(self, context: ValidationContext) -> None:
        import socket
        
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.bind(('localhost', self.port))
            sock.close()
            
            context.add_check(
                f"Port {self.port}",
                success=True,
                message=f"Available"
            )
        except OSError:
            context.add_check(
                f"Port {self.port}",
                success=False,
                message=f"Already in use"
            )

# Usage
boot.add_validator(PortAvailableValidator(8000))

5.2 Advanced Custom Validator

from datetime import datetime, timedelta

class SSLCertificateValidator(Validator):
    """Validate SSL certificate is not expired."""
    
    def __init__(self, cert_path: str, warn_days: int = 30):
        self.cert_path = cert_path
        self.warn_days = warn_days
    
    def validate(self, context: ValidationContext) -> None:
        from pathlib import Path
        import ssl
        import OpenSSL
        
        cert_file = Path(self.cert_path)
        
        if not cert_file.exists():
            context.add_check(
                "SSL Certificate",
                success=False,
                message=f"File not found: {self.cert_path}"
            )
            return
        
        # Load certificate
        with open(cert_file, 'rb') as f:
            cert_data = f.read()
        
        cert = OpenSSL.crypto.load_certificate(
            OpenSSL.crypto.FILETYPE_PEM,
            cert_data
        )
        
        # Check expiration
        not_after = datetime.strptime(
            cert.get_notAfter().decode('ascii'),
            '%Y%m%d%H%M%SZ'
        )
        
        days_until_expiry = (not_after - datetime.utcnow()).days
        
        if days_until_expiry < 0:
            context.add_check(
                "SSL Certificate",
                success=False,
                message=f"Expired {abs(days_until_expiry)} days ago"
            )
        elif days_until_expiry < self.warn_days:
            context.add_check(
                "SSL Certificate",
                success=True,
                message=f"⚠️  Expires in {days_until_expiry} days (warning threshold: {self.warn_days})"
            )
        else:
            context.add_check(
                "SSL Certificate",
                success=True,
                message=f"Valid for {days_until_expiry} days"
            )

5.3 Async Validator

import asyncio

class AsyncDatabaseValidator(Validator):
    """Async database connectivity check."""
    
    def __init__(self, url: str):
        self.url = url
    
    def validate(self, context: ValidationContext) -> None:
        # Run async code in sync context
        result = asyncio.run(self._async_check())
        
        context.add_check(
            "Database (Async)",
            success=result["success"],
            message=result["message"]
        )
    
    async def _async_check(self) -> dict:
        try:
            import asyncpg
            
            conn = await asyncpg.connect(self.url, timeout=5.0)
            await conn.close()
            
            return {
                "success": True,
                "message": "Connected successfully"
            }
        except Exception as e:
            return {
                "success": False,
                "message": f"Connection failed: {e}"
            }

6. Bootstrap Context

6.1 Accessing Context

from structum_lab.plugins.bootstrap import ValidationContext

context = ValidationContext()

# Add checks
context.add_check("Service A", True, "OK")
context.add_check("Service B", False, "Failed to connect")

# Query status
print(f"Total checks: {context.total_checks}")
print(f"Successful: {context.successful_checks}")
print(f"Failed: {context.failed_checks}")

# Get detailed report
print(context.get_report())

6.2 Report Format

┌─────────────────────────────────────┐
│ Bootstrap Validation Report         │
├─────────────────────────────────────┤
│ Status: ❌ FAILED (5/7 checks passed)│
└─────────────────────────────────────┘

Environment Variables:
  ✓ DATABASE_URL: Present
  ✓ API_KEY: Present
  ✗ REDIS_URL: Missing

Python Version:
  ✓ Version 3.11.0 >= 3.9 (required)

Directories:
  ✓ /var/log/myapp: Exists and writable
  ✗ /etc/ssl/certs/app.pem: Not readable

6.3 Programmatic Access

# Check specific results
for check in context.checks:
    print(f"{check.name}: {check.success}")
    if not check.success:
        print(f"  Error: {check.message}")

# Export to JSON
import json
report_json = {
    "total": context.total_checks,
    "passed": context.successful_checks,
    "failed": context.failed_checks,
    "checks": [
        {
            "name": check.name,
            "success": check.success,
            "message": check.message
        }
        for check in context.checks
    ]
}
print(json.dumps(report_json, indent=2))

7. Error Handling

7.1 Exit on Failure (Production)

# Production mode: exit immediately on failure
boot = SystemBootstrapper()
boot.add_validator(EnvValidator(required=["DB_URL"]))

boot.run_or_exit()  # sys.exit(1) if validation fails

# This line only executes if validation passed
start_application()

7.2 Continue on Failure (Development)

# Development mode: collect all errors
boot = SystemBootstrapper()
boot.add_validator(EnvValidator(required=["DB_URL"]))
boot.add_validator(DirectoryValidator("/var/log"))

result = boot.run()

if not result.success:
    print("⚠️  Found validation issues:")
    print(result.report)
    
    # Developer can decide whether to continue
    if input("Continue anyway? (y/n): ").lower() != 'y':
        sys.exit(1)

start_application()

7.3 Custom Error Handling

class CustomBootstrapper(SystemBootstrapper):
    """Custom bootstrapper with logging."""
    
    def on_validation_start(self):
        """Called before validation starts."""
        logger.info("Starting bootstrap validation")
    
    def on_validation_complete(self, context: ValidationContext):
        """Called after all validators run."""
        logger.info(
            f"Validation complete: {context.successful_checks}/{context.total_checks} passed"
        )
        
        if context.has_failures():
            logger.error(f"Validation failed:\n{context.get_report()}")
            
            # Send to monitoring
            metrics.increment("bootstrap.failures")
    
    def on_validator_error(self, validator: Validator, error: Exception):
        """Called if validator raises exception."""
        logger.exception(f"Validator {validator.__class__.__name__} crashed: {error}")

8. Advanced Patterns

8.1 Conditional Validation

import os

boot = SystemBootstrapper()

# Always validate
boot.add_validator(PythonVersionValidator(min_version="3.9"))

# Production-only validators
if os.getenv("ENV") == "production":
    boot.add_validator(SSLCertificateValidator("/etc/ssl/app.pem"))
    boot.add_validator(DirectoryValidator("/var/log", writable=True))

# Development-only validators
if os.getenv("ENV") == "development":
    boot.add_validator(PortAvailableValidator(8000))

boot.run_or_exit()

8.2 Validator Groups

class InfrastructureValidators:
    """Group of infrastructure validators."""
    
    @staticmethod
    def get_all() -> list[Validator]:
        return [
            EnvValidator(required=["DB_URL", "REDIS_URL"]),
            DatabaseValidator.from_config(),
            PortAvailableValidator(5432),  # PostgreSQL
            PortAvailableValidator(6379),  # Redis
        ]

class SecurityValidators:
    """Group of security validators."""
    
    @staticmethod
    def get_all() -> list[Validator]:
        return [
            SSLCertificateValidator("/etc/ssl/app.pem"),
            FileValidator("/etc/ssl/private/app.key", readable=True),
            EnvValidator(required=["JWT_SECRET", "ENCRYPTION_KEY"]),
        ]

# Usage
boot = SystemBootstrapper()

for validator in InfrastructureValidators.get_all():
    boot.add_validator(validator)

for validator in SecurityValidators.get_all():
    boot.add_validator(validator)

boot.run_or_exit()

8.3 Progressive Validation

def bootstrap_application():
    """Multi-stage bootstrap with fail-fast."""
    
    # Stage 1: Critical checks (fail immediately)
    stage1 = SystemBootstrapper()
    stage1.add_validator(PythonVersionValidator(min_version="3.9"))
    stage1.add_validator(EnvValidator(required=["DATABASE_URL"]))
    stage1.run_or_exit()
    
    print("✓ Stage 1: Critical checks passed")
    
    # Stage 2: Infrastructure (can warn)
    stage2 = SystemBootstrapper()
    stage2.add_validator(DatabaseValidator.from_config())
    stage2.add_validator(DirectoryValidator("/var/log", create_if_missing=True))
    
    result = stage2.run()
    if not result.success:
        print(f"⚠️  Stage 2: Infrastructure warnings:\n{result.report}")
    
    print("✓ Stage 2: Infrastructure checks completed")
    
    # Stage 3: Optional features
    stage3 = SystemBootstrapper()
    stage3.add_validator(EnvValidator(optional=["REDIS_URL", "CACHE_TTL"]))
    stage3.run()  # Never fails
    
    print("✓ Stage 3: Optional features validated")
    print("✅ Bootstrap complete - starting application")

9. Production Deployment

9.1 Container Health Checks

# health_check.py
from structum_lab.plugins.bootstrap import SystemBootstrapper, DatabaseValidator

def health_check() -> bool:
    """Health check for Kubernetes/Docker."""
    boot = SystemBootstrapper()
    boot.add_validator(DatabaseValidator.from_config())
    
    result = boot.run()
    return result.success

if __name__ == "__main__":
    import sys
    sys.exit(0 if health_check() else 1)

Dockerfile:

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD python health_check.py || exit 1

9.2 Systemd Integration

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target postgresql.service

[Service]
Type=simple
ExecStartPre=/usr/bin/python3 /app/bootstrap.py
ExecStart=/usr/bin/python3 /app/server.py
Restart=always

[Install]
WantedBy=multi-user.target

10. API Reference

See the Core Docs for details on protocols and base classes.