현재 작업 상태 저장

This commit is contained in:
Yun Chan 2026-06-27 11:20:24 +09:00
parent 07cc67761e
commit 6bd91b0d5e
674 changed files with 8726 additions and 298 deletions

View file

@ -40,6 +40,10 @@ def _is_allowed_local_dev_cors_origin(value: str) -> bool:
)
def _is_local_or_forbidden_non_dev_origin(value: str) -> bool:
return _is_local_url(value) and not _is_allowed_local_dev_cors_origin(value)
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
@ -84,6 +88,14 @@ class Settings(BaseSettings):
default="https://api.openai.com/v1",
validation_alias="OPENAI_BASE_URL",
)
voice_poc_sample_tts_enabled: bool = Field(
default=False,
validation_alias="VIGNETTE_VOICE_POC_SAMPLE_TTS",
)
voice_poc_sample_tts_dir: str = Field(
default="",
validation_alias="VIGNETTE_VOICE_POC_SAMPLE_TTS_DIR",
)
# ── 세션/인증 (BFF OAuth 2.1, 토큰 서버 보관) ────────
session_secret: str = Field(
@ -143,15 +155,27 @@ class Settings(BaseSettings):
default="http://localhost:5173",
validation_alias="FRONTEND_BASE_URL",
)
frontend_origin_map: dict[str, str] = Field(
default_factory=lambda: {
"api-vignette.chanpaca.net": "https://vignette.chanpaca.net",
"api-vnet.18ka.net": "https://vnet.18ka.net",
},
validation_alias="FRONTEND_ORIGIN_MAP",
)
# ── CORS (정적 프론트 + SSE 분리경로) ────────────────
cors_origins: list[str] = Field(
default=[
"https://vignette.chanpaca.net",
"https://vnet.18ka.net",
"https://vignette-b1q.pages.dev",
],
validation_alias="CORS_ORIGINS",
)
auth_dev_login_extra_origins: list[str] = Field(
default=[],
validation_alias="AUTH_DEV_LOGIN_EXTRA_ORIGINS",
)
# Built-in personas are developer/bootstrap fixtures, not runtime truth.
# Production should use approved rows from app.persona_card only.
@ -181,6 +205,8 @@ class Settings(BaseSettings):
forbidden.append("AUTO_SEED_PERSONAS")
if self.allow_seed_persona_fallback:
forbidden.append("ALLOW_SEED_PERSONA_FALLBACK")
if self.voice_poc_sample_tts_enabled:
forbidden.append("VIGNETTE_VOICE_POC_SAMPLE_TTS")
if not self.oauth_google_client_id.strip():
forbidden.append("OAUTH_GOOGLE_CLIENT_ID")
if not self.oauth_google_client_secret.strip():
@ -189,11 +215,13 @@ class Settings(BaseSettings):
forbidden.append("SESSION_SECRET")
if _is_local_url(self.frontend_base_url):
forbidden.append("FRONTEND_BASE_URL")
if any(
_is_local_url(origin) and not _is_allowed_local_dev_cors_origin(origin)
for origin in self.cors_origins
):
if any(_is_local_or_forbidden_non_dev_origin(origin) for origin in self.cors_origins):
forbidden.append("CORS_ORIGINS")
if any(
_is_local_or_forbidden_non_dev_origin(origin)
for origin in self.frontend_origin_map.values()
):
forbidden.append("FRONTEND_ORIGIN_MAP")
if forbidden:
joined = ", ".join(forbidden)
raise ValueError(f"{joined} must be production-safe when ENVIRONMENT={self.environment}")