Files
mo 02b1d155d4 Add home-security-agent with PostgreSQL persistence for dashboard.
The autonomous agent writes all observations to agent.* tables consumed by Homelab Command on port 8765.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 21:57:16 +02:00

76 lines
2.3 KiB
Python

"""SQLite — geheugen van de agent (dedupe, incidenten)."""
import json
import sqlite3
from datetime import datetime, timedelta
from pathlib import Path
DB_PATH = Path(__file__).resolve().parent.parent / "data" / "agent.db"
def connect():
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
conn.executescript(
"""
CREATE TABLE IF NOT EXISTS incidents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fingerprint TEXT NOT NULL,
severity TEXT NOT NULL,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at TEXT NOT NULL,
notified INTEGER DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_fp ON incidents(fingerprint);
CREATE TABLE IF NOT EXISTS runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
started_at TEXT NOT NULL,
summary TEXT,
raw_observations TEXT
);
"""
)
return conn
def was_notified_recently(fingerprint: str, minutes: int) -> bool:
since = (datetime.utcnow() - timedelta(minutes=minutes)).isoformat()
conn = connect()
row = conn.execute(
"SELECT 1 FROM incidents WHERE fingerprint=? AND notified=1 AND created_at>?",
(fingerprint, since),
).fetchone()
conn.close()
return row is not None
def record_incident(fingerprint: str, severity: str, title: str, body: str, notified: bool):
conn = connect()
conn.execute(
"INSERT INTO incidents (fingerprint, severity, title, body, created_at, notified) VALUES (?,?,?,?,?,?)",
(fingerprint, severity, title, body, datetime.utcnow().isoformat(), 1 if notified else 0),
)
conn.commit()
conn.close()
def recent_incidents(limit: int = 10) -> list[dict]:
conn = connect()
rows = conn.execute(
"SELECT severity, title, body, created_at FROM incidents ORDER BY id DESC LIMIT ?",
(limit,),
).fetchall()
conn.close()
return [dict(r) for r in rows]
def log_run(summary: str, observations: dict):
conn = connect()
conn.execute(
"INSERT INTO runs (started_at, summary, raw_observations) VALUES (?,?,?)",
(datetime.utcnow().isoformat(), summary, json.dumps(observations, default=str)),
)
conn.commit()
conn.close()