feat: harden storyforge production baseline

This commit is contained in:
kris
2026-03-26 19:33:36 +08:00
parent 38b02a9799
commit a30ed8decd
9 changed files with 1883 additions and 20 deletions

View File

@@ -1,11 +1,16 @@
from __future__ import annotations
import os
import sqlite3
from contextlib import contextmanager
from pathlib import Path
from typing import Any, Iterator
SQLITE_BUSY_TIMEOUT_MS = int(os.getenv("SQLITE_BUSY_TIMEOUT_MS", "5000"))
SQLITE_CONNECT_TIMEOUT_SEC = float(os.getenv("SQLITE_CONNECT_TIMEOUT_SEC", "30"))
def utc_now() -> str:
from datetime import datetime, timezone
@@ -22,9 +27,14 @@ class Database:
self.path.parent.mkdir(parents=True, exist_ok=True)
def connect(self) -> sqlite3.Connection:
conn = sqlite3.connect(self.path)
conn = sqlite3.connect(self.path, timeout=SQLITE_CONNECT_TIMEOUT_SEC)
conn.row_factory = dict_factory
conn.execute("PRAGMA journal_mode = WAL")
conn.execute("PRAGMA synchronous = NORMAL")
conn.execute(f"PRAGMA busy_timeout = {SQLITE_BUSY_TIMEOUT_MS}")
conn.execute("PRAGMA foreign_keys = ON")
conn.execute("PRAGMA temp_store = MEMORY")
conn.execute("PRAGMA wal_autocheckpoint = 1000")
return conn
@contextmanager
@@ -265,6 +275,41 @@ class Database:
FOREIGN KEY(source_id) REFERENCES live_recorder_sources(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS tenant_quota_profiles (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
project_id TEXT NOT NULL DEFAULT '',
monthly_budget_cents INTEGER NOT NULL DEFAULT 0,
storage_limit_bytes INTEGER NOT NULL DEFAULT 0,
analysis_quota INTEGER NOT NULL DEFAULT 0,
copy_quota INTEGER NOT NULL DEFAULT 0,
ai_video_quota INTEGER NOT NULL DEFAULT 0,
real_cut_quota INTEGER NOT NULL DEFAULT 0,
recorder_quota INTEGER NOT NULL DEFAULT 0,
enabled INTEGER NOT NULL DEFAULT 1,
config_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE(user_id, project_id),
FOREIGN KEY(user_id) REFERENCES accounts(id) ON DELETE CASCADE,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS tenant_usage_ledger (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
project_id TEXT NOT NULL DEFAULT '',
category TEXT NOT NULL,
quantity INTEGER NOT NULL DEFAULT 1,
cost_cents INTEGER NOT NULL DEFAULT 0,
reference_type TEXT NOT NULL DEFAULT '',
reference_id TEXT NOT NULL DEFAULT '',
details_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL,
FOREIGN KEY(user_id) REFERENCES accounts(id) ON DELETE CASCADE,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS job_events (
id TEXT PRIMARY KEY,
job_id TEXT NOT NULL,