""" app/__init__.py Application factory and startup hooks for SneakyScope. Responsibilities: - Create the Flask app. - Load settings (YAML -> dataclasses) with safe defaults. - Initialize and load the Suspicious Rules Engine from YAML. - Register blueprints (routes). - Configure core paths (e.g., SANDBOX_STORAGE). """ import os import logging from pathlib import Path from flask import Flask # Local imports from .utils.settings import get_settings from .utils import io_helpers # if you need logging/setup later from .utils import cache_db # available for future injections from .utils.rules_engine import RuleEngine, load_rules_from_yaml # rules engine from . import routes # blueprint def create_app() -> Flask: """ Create and configure the Flask application instance. Returns: Flask: The configured Flask app. """ # Basic app object app = Flask(__name__, template_folder="templates", static_folder="static") # Load settings (safe fallback to defaults if file missing) settings = get_settings() # Secret key loaded from env app.secret_key = os.getenv("SECRET_KEY") # Configure storage directory (bind-mount is still handled by sandbox.sh) sandbox_storage_default = Path("/data") app.config["SANDBOX_STORAGE"] = str(sandbox_storage_default) # Initialize Suspicious Rules Engine at startup # Determine rules file path relative to this package base_dir = Path(__file__).resolve().parent rules_path = base_dir / "config" / "suspicious_rules.yaml" # Create an engine instance (even if file missing, we still want an engine) engine = RuleEngine() # Try to load from YAML if present; log clearly if not if rules_path.exists(): try: loaded_rules = load_rules_from_yaml(rules_path) # Add rules one-by-one (explicit) for rule in loaded_rules: engine.add_rule(rule) app.logger.info(f"[+] Loaded {len(loaded_rules)} suspicious rules from {rules_path}") except Exception as e: app.logger.warning(f"[!] Failed loading rules from {rules_path}: {e}") else: app.logger.warning(f"[!] Rules file not found at {rules_path}. Engine will start with zero rules.") # Store engine on app config so it is accessible via current_app app.config["RULE_ENGINE"] = engine # Make app name/version available for templates here if you want it globally app.config["APP_NAME"] = settings.app.name app.config["APP_VERSION"] = f"v{settings.app.version_major}.{settings.app.version_minor}" # Register blueprints app.register_blueprint(routes.bp) # Example log line so we know we booted cleanly app.logger.info(f"SneakyScope started: {app.config['APP_NAME']} {app.config['APP_VERSION']}") app.logger.info(f"SANDBOX_STORAGE: {app.config['SANDBOX_STORAGE']}") return app