# Runtime Flow — Dashboard Persistent Authentication ## 목적과 범위 Dashboard startup, login token 발급, 새 browser session의 인증 복원, 실패 차단과 logout cookie 삭제 순서를 정의한다. - 포함: ASGI startup, config, login/logout POST, signed cookie, Streamlit gate, DB 이전 차단 - 제외: MCP 요청, token registry, OAuth/OIDC, external auth middleware ## 정상 흐름 ### START — ASGI server 시작 | 단계 | 주체 | 처리 | 다음 | |---|---|---|---| | `START-01` | Uvicorn | `dashboard.server:app` 로드 | `START-02` | | `START-02` | Streamlit `App` | custom auth routes와 `dashboard/app.py` runtime 조립 | `UNAUTHENTICATED` | 운영 command는 `uvicorn dashboard.server:app --host 0.0.0.0 --port 8501`이다. ### LOGIN — Credential 제출과 token 발급 | 단계 | 주체 | 입력/처리 | 상태·외부 효과 | 다음 | |---|---|---|---|---| | `LOGIN-01` | Browser | Streamlit이 렌더링한 HTML form을 same-origin HTTPS POST | credential은 request body에만 존재 | `LOGIN-02` | | `LOGIN-02` | `auth_server` | Origin, content type, body size와 field cardinality 검증 | 금융 상태 없음 | `LOGIN-03` 또는 `LOGIN-REJECT` | | `LOGIN-03` | `authentication` | 세 environment setting을 fail-closed로 읽음 | process memory | `LOGIN-04` 또는 `CONFIG-FAIL` | | `LOGIN-04` | `authentication` | ID와 password 모두 constant-time 비교 | 실패 시 남은 최소 1초 sleep | `LOGIN-05` 또는 `LOGIN-FAIL` | | `LOGIN-05` | `authentication` | `v/sub/iat/exp/jti` payload와 derived key로 token 서명 | DB 상태 없음 | `LOGIN-06` | | `LOGIN-06` | `auth_server` | 303 response에 hardened cookie 설정 | browser cookie 생성 | `RESTORE-01` | 기본 `exp-iat`는 86400초, remember-me는 2592000초다. 이 값은 발급 시 고정된다. ### RESTORE — 새 session·재접속 인증 복원 | 단계 | 주체 | 입력/처리 | 상태 | 다음 | |---|---|---|---|---| | `RESTORE-01` | Browser | Streamlit initial request/WebSocket handshake에 host cookie 전송 | HttpOnly token | `GATE-01` | | `GATE-01` | `dashboard.app` | page config 직후 authentication gate 호출 | DB 미접근 | `GATE-02` | | `GATE-02` | `authentication` | 현재 ID/password/signing secret 로드 | secret은 session에 저장하지 않음 | `GATE-03` 또는 `CONFIG-FAIL` | | `GATE-03` | `authentication` | signature 검증 후 exact claim schema, subject, TTL, time 검증 | token 재발급 없음 | `DASHBOARD-01` 또는 `TOKEN-FAIL` | | `DASHBOARD-01` | `dashboard.app` | DB path 해석과 기존 page dispatch | 기존 금융 계약 | `AUTHENTICATED` | 각 rerun은 cookie를 현재 설정으로 다시 검증한다. 일반 요청은 `iat`, `exp`, cookie `Max-Age`를 연장하지 않는다. ### LOGOUT — Browser cookie 삭제 | 단계 | 주체 | 처리 | 다음 | |---|---|---|---| | `LOGOUT-01` | Browser | same-origin HTTPS POST `/api/auth/logout` | `LOGOUT-02` | | `LOGOUT-02` | `auth_server` | matching name/path/security 속성과 `Max-Age=0` response | `LOGOUT-03` | | `LOGOUT-03` | Browser | cookie 삭제 후 `/` 재접속 | `UNAUTHENTICATED` | Logout은 DB를 변경하지 않는다. 복사된 stateless token의 개별 server-side revocation은 없으며 password/signing-secret rotation이 전체 기존 token을 무효화한다. ## 실패와 복구 | 실패 상태 | 원인 | 차단 범위 | 복구 | |---|---|---|---| | `CONFIG-FAIL` | ID/password/signing secret 누락·invalid·read error | DB/gateway/page 전체 | 올바른 secret 주입 후 rerun | | `LOGIN-REJECT` | cross-site, malformed, oversized POST | cookie 발급 | same-origin 정상 form 재시도 | | `LOGIN-FAIL` | ID 또는 password 불일치 | cookie 발급·DB 접근 | 최소 1초 후 일반 오류, 재시도 | | `TOKEN-FAIL` | absent/malformed/tampered/expired/wrong claims/rotation | DB/gateway/page 전체 | 재로그인 | | `DASHBOARD-FAIL` | 인증 이후 기존 page/DB 오류 | 기존 page 계약 | 기존 운영 복구 | Invalid token의 세부 원인을 UI에서 구분하지 않는다. Credential, secret, token, cookie header 또는 exception 원문을 log에 넣지 않는다. ## 동시성·순서 - 서로 다른 browser session은 같은 signed token을 보낼 수 있다. - Token verification은 stateless이고 shared mutable authentication state를 만들지 않는다. - 설정 및 cookie 검증은 항상 DB path/gateway/page보다 먼저다. - Password/signing-secret rotation 직후 다음 rerun부터 기존 token이 실패한다. - 실패당 1초 delay는 병렬 요청을 직렬화하지 않으므로 TLS ingress/reverse-proxy 경계에서 rate limiting이 필요하다. ## 관찰 가능성 허용 event: `configuration_error`, `authentication_required`, `token_accepted`, `login_succeeded`, `login_failed`, `login_origin_rejected`, `login_request_rejected`, `logout`, `logout_origin_rejected`. 각 log는 event와 비민감 correlation ID만 포함한다. Token, credential, origin 세부값, request body와 cookie header는 기록하지 않는다. ## 검증 - Normal/remember TTL 및 non-sliding: token unit tests - Tamper/expiry/rotation/schema rejection: token unit tests - HTTP response cookie와 logout deletion: auth-server tests - Fail-closed DB-before-gate ordering: AppTest - 실제 loopback HTTPS login/reconnect/logout와 cookie 속성: HTTP evidence script - MCP behavior와 DB schema가 변경되지 않았음을 full regression과 diff로 확인