feat: 주요 CLI, 인증, 서비스 로직 및 문서 개선

This commit is contained in:
2026-04-15 00:48:22 +09:00
parent 36fbb0879e
commit 0e9d2a16d8
17 changed files with 864 additions and 18 deletions
+59
View File
@@ -345,6 +345,30 @@ class PostgresPortfolioRepository:
ON portfolio_tags (tag_value, portfolio_id)
"""
)
cur.execute(
"""
CREATE TABLE IF NOT EXISTS auth_audit_logs (
id TEXT PRIMARY KEY,
event_type TEXT NOT NULL,
action TEXT NOT NULL,
actor_id TEXT NOT NULL,
bot_id TEXT NOT NULL,
token_id_masked TEXT NOT NULL,
token_ref_masked TEXT NOT NULL,
result TEXT NOT NULL,
detail TEXT,
payload JSONB NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
"""
)
cur.execute(
"""
CREATE INDEX IF NOT EXISTS idx_auth_audit_logs_bot_occurred
ON auth_audit_logs (bot_id, occurred_at DESC)
"""
)
cur.execute("SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'timescaledb')")
if cur.fetchone()[0]:
cur.execute(
@@ -821,6 +845,41 @@ class PostgresPortfolioRepository:
bot_principal_id=row[4],
)
def record_audit_event(self, payload: dict[str, Any]) -> None:
self.ensure_schema()
event_id = str(uuid.uuid4())
occurred_at_raw = payload.get("occurred_at")
occurred_at = datetime.now(timezone.utc)
if isinstance(occurred_at_raw, str):
try:
occurred_at = datetime.fromisoformat(occurred_at_raw)
except ValueError:
occurred_at = datetime.now(timezone.utc)
with self._connect().cursor() as cur:
cur.execute(
"""
INSERT INTO auth_audit_logs (
id, event_type, action, actor_id, bot_id,
token_id_masked, token_ref_masked, result, detail, payload, occurred_at
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s::jsonb, %s)
""",
(
event_id,
str(payload.get("event_type", "auth.bot_token")),
str(payload.get("action", "")),
str(payload.get("actor_id", "unknown")),
str(payload.get("bot_id", "unknown")),
str(payload.get("token_id", "")),
str(payload.get("token_ref", "")),
str(payload.get("result", "unknown")),
payload.get("detail"),
json.dumps(payload, ensure_ascii=True),
occurred_at,
),
)
def get(self, portfolio_id: str) -> Portfolio:
self.ensure_schema()
with self._connect().cursor() as cur: