Harden production workflows and agent admission

This commit is contained in:
Stanislav Rossovskii
2026-05-28 14:19:27 +04:00
parent a2e88b4e76
commit 37b1a1d6d6
109 changed files with 4927 additions and 894 deletions

View File

@@ -13,9 +13,9 @@ class Settings(BaseSettings):
body_limit_bytes: int = 1_048_576
output_max_bytes: int = 8192
max_batch_events: int = 200
stale_after_sec: int = 90
dead_after_sec: int = 300
detector_tick_sec: int = 15
stale_after_sec: int = 20
dead_after_sec: int = 30
detector_tick_sec: int = 5
host: str = "0.0.0.0"
port: int = 8000
enable_detector: bool = True
@@ -24,8 +24,18 @@ class Settings(BaseSettings):
events_future_partitions: int = 3
event_dedup_retention_days: int = 30
event_dedup_prune_batch_size: int = 5000
max_pending_agents: int = 10_000
pending_agent_ttl_days: int = 7
pending_agent_prune_batch_size: int = 1000
partition_maintenance_interval_sec: int = 3600
outbox_retention_max_rows: int = 50_000
# PH-012: bounded prune per maintenance tick to avoid one huge DELETE.
outbox_prune_batch_size: int = 5000
# PH-016: explicit DB pool sizing for production tuning.
db_pool_size: int = 10
db_max_overflow: int = 10
db_pool_timeout_sec: float = 30.0
db_pool_recycle_sec: int = 1800
notifier_tick_sec: int = 5
notifier_batch_size: int = 20
notifier_max_attempts: int = 8
@@ -33,6 +43,11 @@ class Settings(BaseSettings):
notifier_http_timeout_sec: float = 10.0
notification_time_zone: str = "UTC"
# PH-020: notifier output policy. include controls whether output text is
# sent at all; max_bytes truncates it before delivery (after redaction).
notifier_include_output: bool = True
notifier_max_output_bytes: int = 1024
notifier_debug_enabled: bool = True
notifier_telegram_enabled: bool = False
notifier_telegram_token: str = ""
@@ -43,12 +58,26 @@ class Settings(BaseSettings):
notifier_alertmanager_enabled: bool = False
notifier_alertmanager_url: str = ""
@staticmethod
def _validate_token_list(value: str, env_name: str) -> str:
if not value or value == "changeme":
raise ValueError(f"{env_name} must be set to a non-default value")
tokens = [t for t in value.replace(",", " ").split() if t]
if not tokens:
raise ValueError(f"{env_name} must contain at least one token")
if any(t == "changeme" for t in tokens):
raise ValueError(f"{env_name} must be set to a non-default value")
return value
@field_validator("auth_token")
@classmethod
def _validate_auth_token(cls, value: str) -> str:
if not value or value == "changeme":
raise ValueError("MONLET_AUTH_TOKEN must be set to a non-default value")
return value
return cls._validate_token_list(value, "MONLET_AUTH_TOKEN")
@property
def auth_tokens(self) -> list[str]:
"""Active Bearer tokens (>=1). Multiple tokens enable overlap rotation."""
return [t for t in self.auth_token.replace(",", " ").split() if t]
@field_validator("notification_time_zone")
@classmethod