feat: backend ingest API, Docker Compose, Ubuntu install guide

- FastAPI: POST /api/v1/events, GET /health, JSON Schema validation

- PostgreSQL models, Alembic migration, bootstrap API key

- deploy/docker-compose.yml, .env.example

- docs/install-ubuntu-24.04.md, updated work-plan (agents first)
This commit is contained in:
PTah
2026-05-26 20:21:31 +10:00
parent bf1c1c9fe9
commit 69a232d08a
34 changed files with 1139 additions and 134 deletions
View File
+43
View File
@@ -0,0 +1,43 @@
from typing import Any
from fastapi import APIRouter, Body, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session
from app.auth.api_key import get_api_key_auth
from app.config import get_settings
from app.database import get_db
from app.services.ingest import ingest_event
from app.services.schema_validate import validate_event_payload
router = APIRouter(prefix="/events", tags=["events"])
class IngestResponse(BaseModel):
status: str
event_id: str
created: bool
sac_event_url: str
@router.post("", status_code=202, response_model=IngestResponse)
def post_event(
payload: dict[str, Any] = Body(...),
db: Session = Depends(get_db),
_api_key: str = Depends(get_api_key_auth),
) -> IngestResponse:
errors = validate_event_payload(payload)
if errors:
raise HTTPException(status_code=422, detail={"schema_errors": errors[:20]})
event, created = ingest_event(db, payload)
db.commit()
settings = get_settings()
base = settings.sac_public_url.rstrip("/")
return IngestResponse(
status="accepted",
event_id=event.event_id,
created=created,
sac_event_url=f"{base}/api/v1/events/{event.id}",
)
+21
View File
@@ -0,0 +1,21 @@
from fastapi import APIRouter, Depends
from sqlalchemy import text
from sqlalchemy.orm import Session
from app.database import get_db
router = APIRouter(tags=["health"])
@router.get("/health")
def health(db: Session = Depends(get_db)) -> dict:
db_status = "ok"
try:
db.execute(text("SELECT 1"))
except Exception:
db_status = "error"
return {
"status": "ok" if db_status == "ok" else "degraded",
"database": db_status,
"service": "security-alert-center",
}
+7
View File
@@ -0,0 +1,7 @@
from fastapi import APIRouter
from app.api.v1 import events, health
api_router = APIRouter()
api_router.include_router(health.router)
api_router.include_router(events.router)