Phase 9: production hardening
Config via env, abuse/resource limits, and production serving so the app is safe to expose publicly: - Fail-fast on missing SECRET_KEY when MULTI_USER=true - quickjs per-execution time/memory limits (while(true) can't hang server) - Per-user/per-IP rate limiting on turn/script/auth endpoints - Request body size limit + per-user row caps - Security headers (CSP, X-Frame-Options, nosniff, referrer-policy) incl. SSE - Debug router 403 and /docs disabled in multi-user mode - DATABASE_URL support (defaults to Neon Postgres) alongside SQLite - Documented all env vars in backend/.env.example Verified locally via uvicorn (MULTI_USER=1, SQLite); see plan/09-phase-hardening.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017e6tQuojBLYPetUfmhit4X
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
de4db373f2
commit
4772171b6c
@@ -1,7 +1,7 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .. import auth, models, schemas
|
||||
from .. import auth, limits, models, schemas
|
||||
from ..database import get_db
|
||||
|
||||
router = APIRouter(prefix="/api/story-cards", tags=["story-cards"])
|
||||
@@ -50,6 +50,10 @@ def create_story_card(
|
||||
owner = db.get(owner_model, owner_id)
|
||||
if owner is None or owner.user_id != user.id:
|
||||
raise HTTPException(404, "Owner not found")
|
||||
limits.check_row_cap(
|
||||
"story_cards", db, user,
|
||||
scenario_id=payload.scenario_id, adventure_id=payload.adventure_id,
|
||||
)
|
||||
card = models.StoryCard(**payload.model_dump())
|
||||
db.add(card)
|
||||
db.commit()
|
||||
|
||||
Reference in New Issue
Block a user