Files
arch_agent f015092b1f feat: scan-only server mode + local build on client
Server:
- config: server.scan_only flag (default: false)
- /api/build returns scan_only=true without building when enabled
- /api/status reports scan_only mode

Client (safe-yay):
- Detects server scan_only from API response
- Scan-only server: builds locally with yay/paru after clean scan
- Full server: installs from pacman repo as before
- --noinstall flag for scan-only without build (was --scan-only)
- Suspicious: prompts for local build or repo install depending on server mode
2026-08-04 10:34:34 +02:00

92 lines
2.4 KiB
Python

"""Configuration loader for AUR-Shield."""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
import yaml
@dataclass
class OllamaConfig:
url: str = "http://localhost:11434"
model: str = "qwen2.5:latest"
timeout: int = 120
@dataclass
class ServerConfig:
host: str = "0.0.0.0"
port: int = 8443
repo_dir: str = "/var/cache/aur-shield/repo"
work_dir: str = "/var/cache/aur-shield/build"
build_user: str = "nobody"
scan_only: bool = False
@dataclass
class SecurityConfig:
block_patterns: list[str] = field(default_factory=lambda: [
r"curl.*\|.*bash",
r"wget.*/tmp/.*\|.*sh",
r"eval.*base64",
r"nc\s+-.*\d+",
r"/dev/tcp/",
r"systemctl.*enable.*--now",
])
max_pkg_size_mb: int = 500
allowed_source_schemes: list[str] = field(default_factory=lambda: [
"https", "http", "git", "ftp", "file",
])
@dataclass
class CacheConfig:
ttl_hours: int = 168
max_cache_gb: int = 10
@dataclass
class BuildConfig:
use_devtools: bool = True
timeout: int = 600
@dataclass
class Config:
ollama: OllamaConfig = field(default_factory=OllamaConfig)
server: ServerConfig = field(default_factory=ServerConfig)
security: SecurityConfig = field(default_factory=SecurityConfig)
cache: CacheConfig = field(default_factory=CacheConfig)
build: BuildConfig = field(default_factory=BuildConfig)
@classmethod
def load(cls, path: str | Path | None = None) -> "Config":
"""Load config from YAML file, falling back to defaults."""
if path is None:
path = Path(os.environ.get(
"AUR_SHIELD_CONFIG",
"config.yaml",
))
path = Path(path)
if not path.exists():
return cls()
with open(path) as f:
raw: dict[str, Any] = yaml.safe_load(f) or {}
cfg = cls()
if "ollama" in raw:
cfg.ollama = OllamaConfig(**raw["ollama"])
if "server" in raw:
cfg.server = ServerConfig(**raw["server"])
if "security" in raw:
cfg.security = SecurityConfig(**raw["security"])
if "cache" in raw:
cfg.cache = CacheConfig(**raw["cache"])
if "build" in raw:
cfg.build = BuildConfig(**raw["build"])
return cfg