dashboard 에서 페이지를 옮길 때 마다 로그인을 해야하는 문제 #6

Closed
opened 2026-10-01 01:11:27 +00:00 by genichin · 1 comment
Owner

요약

Dashboard 관리자 로그인을 현재 Streamlit st.session_state 범위에서 브라우저가 다시 연결되어도 복원 가능한 지속 로그인으로 확장한다. Dashboard server-side adapter가 HttpOnly cookie를 발급·검증하며, 로그인 성공 시각부터 기본 24시간 또는 로그인 form의 로그인 유지 선택 시 30일 후 절대 만료한다. 활동이나 인증 복원으로 만료를 연장하지 않는다. 전용 signing secret rotation과 관리자 password 변경은 기존 지속 로그인을 무효화한다. Sidebar의 페이지 링크로 이동할 때도 유효한 인증이 있으면 로그인 화면으로 돌아가지 않아야 한다.

문제

  • Issue #6은 Dashboard에서 페이지를 옮길 때마다 다시 로그인해야 하며, 브라우저를 닫았다 열어도 일정 기간 인증을 유지해야 한다고 요구한다.
  • dashboard/authentication.py는 인증 성공 여부를 _jarca_dashboard_authenticated라는 st.session_state boolean으로만 저장한다. 새 Streamlit browser session에는 복원할 인증 증거가 없다.
  • dashboard/common.py의 sidebar navigation은 ?page=...로 이동하는 target="_self" 링크를 렌더링하므로, 페이지 이동 과정에서 새 Streamlit 연결이 형성되면 session-only 인증 상태를 복원할 수 없다.
  • 승인된 REQ-001과 현재 docs/interface-contract.md, docs/runtime-flow.md, README는 persistent cookie를 제외하고 새 session 재인증을 명시한다. 따라서 이번 변경은 기존 인증 경계의 보안·인터페이스·런타임 계약을 명시적으로 확장해야 한다.

포함 범위

  • 기존 관리자 ID·password 검증 성공 후 Dashboard server-side adapter가 HttpOnly cookie로 지속 인증 증거를 발급·검증하고 브라우저 재연결에서 복원하는 동작
  • 로그인 form에 기본 미선택 상태의 로그인 유지 checkbox 추가
  • checkbox 미선택 로그인은 로그인 성공 시각부터 24시간, 선택 로그인은 30일 후 절대 만료하며 활동·페이지 이동·인증 복원으로 연장하지 않음
  • 같은 브라우저 profile에서 sidebar 페이지 이동, 새 탭 또는 브라우저 종료 후 재접속하더라도 만료되지 않은 인증을 복원
  • 지속 인증 복원, 절대 만료 및 현재 설정 binding 판정을 모든 DB 경로 취득·gateway 호출·page dispatch보다 먼저 수행하고, 기존 session boolean만으로 만료·무효화를 우회하지 않음
  • 위조·변조·만료·설정 오류가 있는 지속 인증 증거를 fail-closed하고 로그인 화면으로 전환
  • 명시적 로그아웃 시 현재 Streamlit 인증 상태와 브라우저의 지속 인증 증거를 함께 폐기
  • 전용 signing secret rotation 또는 관리자 password 변경 후 이전 설정으로 발급된 지속 인증을 거부하고, 그 증거에서 복원된 session 상태만으로 접근을 유지하지 않음
  • 관리자 credential 원문을 브라우저 저장소, URL, log, traceback 또는 st.session_state에 남기지 않는 기존 비노출 계약 유지
  • 단위·통합 test에서 24시간/30일 선택과 절대 만료 경계, 활동 시 미연장, 페이지 이동, 새 session 복원, 변조, 로그아웃, signing secret rotation, 관리자 password 변경 및 설정 오류를 검증하고 실제 browser test에서 server-set HttpOnly cookie의 발급·복원·삭제를 확인
  • .env.example, Compose, k3s Secret 계약과 README에 필요한 비밀값·HTTPS·만료 운영 조건 반영

제외 범위

  • 다중 사용자, 회원가입, 역할 기반 권한, 사용자별 데이터 분리
  • OIDC, SSO, 외부 IdP 도입
  • reverse proxy/auth gateway 또는 외부 session middleware로 지속 인증의 발급·검증 책임을 이전하는 방식
  • 활동에 따른 sliding 만료 또는 복원 시 만료 기간 재설정
  • MCP endpoint 인증 또는 MCP transport 변경
  • SQLite 가계부 schema, 금융 데이터 모델 또는 DB-backed session table 추가
  • 다른 브라우저·기기 사이의 로그인 공유
  • 활성 기기 목록, 개별 session 원격 폐기 또는 관리 UI
  • 기존 실패 로그인 최소 1초 지연과 배포 경계 rate limiting 정책 변경
  • Dashboard 이외 서비스의 cookie·session 정책 변경

제약 조건

  • Pinned source revision은 7bea8b368e02e98afd4b2dc463fb270b0e6eb297이며 구현 근거는 이 revision의 tree로 한정한다.
  • 기존 JARCA_DASHBOARD_ADMIN_ID와 JARCA_DASHBOARD_ADMIN_PASSWORD는 계속 environment에서만 읽고 브라우저에 저장하지 않는다.
  • 지속 인증 증거는 관리자 ID·password 또는 재사용 가능한 credential 원문을 포함해서는 안 되며, 변조 여부와 만료 시각을 server-side 신뢰 경계에서 검증해야 한다.
  • 만료 판정은 브라우저가 전달한 현재 시각만 신뢰해서는 안 된다. Server-side에서 로그인 성공 시각에 고정한 24시간 또는 30일의 만료 시각을 검증하며 활동·복원으로 연장하지 않는다. 만료되거나 검증할 수 없는 증거는 session boolean이 참이어도 인증되지 않은 것으로 처리하고 금융 DB·gateway를 호출하지 않는다.
  • 브라우저에 저장되는 인증 material은 배포 환경에서 HTTPS를 전제로 Secure, HttpOnly, 적절한 SameSite와 최소 path/domain 범위를 적용할 수 있는 방식이어야 한다. JavaScript에서 읽을 수 있는 저장소만으로 인증 credential을 보존하는 방식은 허용하지 않는다.
  • 지속 인증 검증용 전용 signing secret은 repository나 image에 넣지 않고 Compose/Kubernetes의 별도 secret으로 주입하며, 누락·빈 값·읽기 오류 시 지속 인증을 fail-closed한다. Signing secret rotation은 모든 기존 지속 로그인을 무효화하며, 관리자 password 변경도 검증 binding을 바꿔 기존 지속 로그인을 무효화한다. Binding과 검증 과정은 credential 원문·재사용 가능한 verifier를 브라우저나 log에 노출하지 않아야 한다.
  • 선택한 Dashboard server-side adapter는 실제 Streamlit runtime의 HTTP response에서 HttpOnly cookie를 발급·삭제할 수 있어야 한다. 현재 저장소 근거만으로 이 구현 가능성이 검증됐다고 간주하지 않으며, 불가능한 경우 JavaScript-readable 저장소나 미선택 proxy/middleware 방식으로 임의 대체하지 않는다.
  • 인증 복원·로그아웃은 SQLite 가계부 데이터와 금융 transaction을 변경하지 않는다.
  • 기존 Dashboard page 목록, query parameter, gateway와 MCP 동작은 인증 성공 이후 동일하게 유지한다.

확정된 결정

  • Dashboard 페이지 이동만으로 재로그인을 요구하지 않는다.
  • 로그인 유지를 선택하지 않은 정상 로그인도 브라우저 종료 후 24시간 유지한다.
  • 로그인 유지를 선택한 로그인은 30일 동안 유지한다.
  • Dashboard server-side adapter가 HttpOnly cookie를 발급·검증·삭제하며 실제 Streamlit runtime에서 HTTP response 제어가 가능한 구현을 사용한다.
  • 만료 기준은 로그인 성공 시각이며 24시간 또는 30일 후 절대 만료한다. 활동·페이지 이동·새 session 복원으로 만료를 연장하지 않는다.
  • 전용 signing secret rotation은 모든 기존 지속 로그인을 무효화하고, 관리자 password 변경도 검증 binding을 바꿔 기존 지속 로그인을 무효화한다.
  • 로그인 유지 checkbox의 기본값은 선택하지 않은 상태다.
  • 지속 인증은 동일한 브라우저 profile에서만 복원하며 다른 기기로 복제하거나 동기화하지 않는다.
  • 명시적 로그아웃은 session-only 인증과 해당 브라우저의 지속 인증을 모두 종료한다.
  • 현재 단일 관리자 credential, 공통 인증 gate, 인증 전 DB 차단과 credential 비노출 계약은 유지한다.
  • 가계부 SQLite schema와 MCP 인증 범위는 변경하지 않는다.

저장소 근거

  • dashboard/authentication.py:21-25,92-139 — 인증 상태가 st.session_state boolean과 session-local 값으로만 관리되고, 성공 시 persistent 인증 material을 발급하지 않는다.
  • dashboard/app.py:28-59 — 인증 gate가 DB 경로 취득과 page dispatch보다 먼저 실행되므로 지속 인증 복원도 이 경계 안에서 완료되어야 한다.
  • dashboard/common.py:358-364 — sidebar navigation이 ?page=...의 target="_self" anchor를 사용한다.
  • tests/test_dashboard_authentication_app.py:108-135 — 현재 test는 같은 AppTest session의 rerun 유지와 새 session 재인증을 승인된 동작으로 검증한다.
  • docs/requirements/req-001_dashboard-administrator-authentication.md:31-40,105-116,328-346 — REQ-001은 browser session 범위만 포함하고 persistent cookie를 제외하며 새 session 재인증을 요구한다.
  • docs/interface-contract.md:42-83,104-111 — login·logout interface가 st.session_state boolean만 정의하고 persistent 인증 입력·출력·오류를 정의하지 않는다.
  • docs/runtime-flow.md:15-29,69-74 — runtime flow는 새 browser session과 rerun에서 session state만 판정하며 persistent 인증 복원 단계가 없다.
  • .env.example:4-6, docker-compose.yml:30-35, deploy/k8s/base/deployment.yaml:123-139 — 현재 배포 secret 계약에는 관리자 ID·password만 있고 지속 인증 검증용 별도 secret은 없다.
  • deploy/k8s/base/deployment.yaml:8-10, deploy/k8s/README.md:63-67 — 운영 배포는 단일 replica와 Recreate 전략이므로 별도 DB-backed distributed session store는 현재 배포 구조의 전제가 아니다.
  • pyproject.toml:19-25 — Dashboard optional dependency는 pandas·plotly·Streamlit이며 server-set persistent cookie/session 전용 dependency는 명시돼 있지 않다. dashboard/authentication.py:92-139에도 해당 adapter 구현이 없다. 이는 현재 지속 인증 구현의 부재에 대한 근거이며, 선택한 server-side adapter의 구현 가능성이나 불가능성을 증명하지 않는다.
  • docs/requirements/req-001_dashboard-administrator-authentication.md는 Dashboard 관리자 인증의 canonical 요구사항이며 session 범위, persistent cookie 제외, 새 session 재인증을 직접 규정한다. Issue #6은 같은 인증 기능의 해당 계약을 변경하므로 새 ID를 만들지 않고 이 문서의 revision과 추적성을 갱신해야 한다.

문서 영향 및 산출물

요구사항명세서

  • 조치: 갱신
  • 경로: docs/requirements/req-001_dashboard-administrator-authentication.md
  • 문서 ID: REQ-001
  • 제목: Dashboard 관리자 인증
  • 변경 내용: 기존 canonical REQ-001의 revision을 상향하고, 현재 session-only·persistent-cookie 제외·새 session 재인증 계약을 Issue #6의 지속 로그인 계약으로 교체한다. 24시간 기본 유지, 로그인 유지 선택 시 30일, checkbox 기본 미선택, 페이지 이동·브라우저 재시작 복원, 로그인 성공 시각 기준 절대 만료와 활동·복원 시 미연장, 변조·만료·설정 오류 fail-closed, logout 폐기, credential 비노출, Dashboard server-side adapter의 실제 response 제어와 cookie 보안 속성, 전용 signing secret 주입·rotation 및 관리자 password 변경 시 기존 로그인 무효화, 인증 전 DB 차단과 기존 페이지 호환성을 기존 요구사항과 acceptance criteria에 반영한다. 기존 인증 경계·credential 검증·실패 지연·보호 범위 요구사항은 유지하고 session·로그아웃, 배포 설정, 관찰 가능성, 오류·인터페이스·하위 호환성 및 관련 acceptance criteria를 함께 갱신한다. 단위 test에는 token 발급·검증·절대 만료·활동 시 미연장·변조·시간 경계·설정 binding과 비민감 log를, Streamlit/browser 통합 test에는 form 선택, query-link 페이지 이동, 새 session 복원, server-set HttpOnly cookie의 발급·삭제와 logout, signing secret rotation과 관리자 password 변경 후 기존 cookie 및 복원된 session의 접근 거부를 포함한다. 추적성에는 근거 Issue #1, #6, 기존 구현 PR #3과 이번 구현 PR 미정을 구분해 기록한다.
  • 포함할 내용: Dashboard server-side adapter의 지속 인증 발급·복원·검증·폐기 계약, 로그인 성공 시각 기준 24시간/30일 절대 만료와 미연장, signing secret rotation·관리자 password 변경 시 기존 로그인 무효화, 브라우저·서버 신뢰 경계, 비밀값 주입, 오류 및 관찰 가능성, REQ-001 기존 계약과의 변경 관계, 테스트 가능한 acceptance criteria와 Issue #6 추적성
  • 제외할 내용: 다중 사용자·RBAC·SSO·MCP 인증, DB-backed session, 다른 기기 공유, 금융 SQLite migration, 원격 session 관리 UI, sliding 만료, proxy/auth gateway·외부 session middleware로 인증 책임 이전
  • 근거: Issue #6은 REQ-001이 이미 소유한 Dashboard 관리자 인증의 session·logout·배포 계약을 변경하며, 별도 기능 경계나 독립 lifecycle을 만들지 않는다.

데이터 모델

  • 조치: 영향 없음
  • 경로: docs/data-model.md
  • 변경 내용: 지속 인증은 금융 SQLite entity·field·relation·migration을 추가하지 않으며 DB-backed session store를 범위에서 제외한다. 브라우저 인증 material의 claims와 만료 값은 데이터 모델이 아니라 인터페이스 계약에서 정의한다.
  • 근거: dashboard/authentication.py가 가계부 DB와 독립적이고, 단일-replica 배포와 이번 제외 범위가 server-side session table을 요구하지 않는다. Pinned tree에도 docs/data-model.md가 없다.

인터페이스 계약

  • 조치: 갱신
  • 경로: docs/interface-contract.md
  • 변경 내용: 로그인 입력에 기본 미선택 로그인 유지 boolean을 추가하고, Dashboard server-side adapter의 지속 인증 증거 발급·브라우저 전달·복원·검증·만료·삭제 interface와 실제 HTTP response 제어 경계를 정의한다. 로그인 성공 시각 기준 24시간/30일 절대 만료와 활동·복원 시 미연장, cookie 이름·scope·Secure·HttpOnly·SameSite, token payload의 비민감 필드, signing secret source, 변조·만료·secret 누락 오류, logout, 전용 signing secret rotation에 의한 모든 기존 지속 로그인 무효화와 관리자 password 변경 시 검증 binding 변경·기존 로그인 무효화, 기존 st.session_state boolean이 만료·binding 검증을 우회하지 못하는 관계를 명시한다. 실제 secret·credential·token 예시는 포함하지 않는다.
  • 근거: 현재 문서는 login 결과를 st.session_state boolean으로만 정의하고 새 session 복원 interface가 없다.

프로젝트 구조

  • 조치: 갱신
  • 경로: docs/project-structure.md
  • 변경 내용: 지속 인증의 발급·검증·cookie adapter 책임을 dashboard/authentication.py의 공통 인증 경계에 두고 dashboard/app.py, page view, 금융 gateway로 역방향 의존하지 않게 한다. 필요한 dependency와 배포 설정은 pyproject.toml, .env.example, docker-compose.yml, deploy/k8s/base/deployment.yaml 및 관련 test 경로에 배치하며, 별도 모듈이 필요할 경우 Dashboard server-side adapter의 HTTP response 제어 경계와 test 대응을 문서화한다. 선택하지 않은 proxy/auth gateway·외부 session middleware로 인증 책임을 옮기거나 page별 인증 분기를 추가하지 않는다.
  • 근거: 현재 프로젝트 구조는 공통 인증을 dashboard/authentication.py에 집중하고 page view의 인증 의존을 금지한다.

런타임 흐름

  • 조치: 갱신
  • 경로: docs/runtime-flow.md
  • 변경 내용: Dashboard 진입과 보호 기능 실행 전 설정, 지속 인증의 무결성·절대 만료·현재 설정 binding을 판정하고 유효한 경우에만 session을 복원·유지하는 순서를 추가한다. 기존 session boolean만으로 만료·무효화를 우회하지 않는다. 로그인 성공 시 Dashboard server-side adapter가 로그인 시각부터 24시간 또는 30일 후 만료하는 HttpOnly cookie를 발급하고, 페이지 이동·새 연결·활동에서는 그 만료를 연장하지 않는다. 만료·변조·secret 누락 시 cookie 삭제와 미인증 전이, logout 시 session과 browser material의 멱등 폐기, signing secret rotation과 관리자 password 변경 시 이전 증거 및 그 증거로 복원된 session의 무효화, 동시 요청의 실패 복구와 비민감 event 관찰 가능성을 정의한다. 모든 실패 경로에서 DB·gateway 호출 전 중단하도록 유지한다.
  • 근거: 현재 flow에는 session state 판정만 있고 browser 재연결 복원·만료·cookie 폐기 단계가 없다.

미해결 질문

없음

<!-- gitea-agent:discovery-draft/v2 --> ## 요약 Dashboard 관리자 로그인을 현재 Streamlit `st.session_state` 범위에서 브라우저가 다시 연결되어도 복원 가능한 지속 로그인으로 확장한다. Dashboard server-side adapter가 `HttpOnly` cookie를 발급·검증하며, 로그인 성공 시각부터 기본 24시간 또는 로그인 form의 `로그인 유지` 선택 시 30일 후 절대 만료한다. 활동이나 인증 복원으로 만료를 연장하지 않는다. 전용 signing secret rotation과 관리자 password 변경은 기존 지속 로그인을 무효화한다. Sidebar의 페이지 링크로 이동할 때도 유효한 인증이 있으면 로그인 화면으로 돌아가지 않아야 한다. ## 문제 - Issue #6은 Dashboard에서 페이지를 옮길 때마다 다시 로그인해야 하며, 브라우저를 닫았다 열어도 일정 기간 인증을 유지해야 한다고 요구한다. - `dashboard/authentication.py`는 인증 성공 여부를 `_jarca_dashboard_authenticated`라는 `st.session_state` boolean으로만 저장한다. 새 Streamlit browser session에는 복원할 인증 증거가 없다. - `dashboard/common.py`의 sidebar navigation은 `?page=...`로 이동하는 `target="_self"` 링크를 렌더링하므로, 페이지 이동 과정에서 새 Streamlit 연결이 형성되면 session-only 인증 상태를 복원할 수 없다. - 승인된 REQ-001과 현재 `docs/interface-contract.md`, `docs/runtime-flow.md`, README는 persistent cookie를 제외하고 새 session 재인증을 명시한다. 따라서 이번 변경은 기존 인증 경계의 보안·인터페이스·런타임 계약을 명시적으로 확장해야 한다. ## 포함 범위 - 기존 관리자 ID·password 검증 성공 후 Dashboard server-side adapter가 `HttpOnly` cookie로 지속 인증 증거를 발급·검증하고 브라우저 재연결에서 복원하는 동작 - 로그인 form에 기본 미선택 상태의 `로그인 유지` checkbox 추가 - checkbox 미선택 로그인은 로그인 성공 시각부터 24시간, 선택 로그인은 30일 후 절대 만료하며 활동·페이지 이동·인증 복원으로 연장하지 않음 - 같은 브라우저 profile에서 sidebar 페이지 이동, 새 탭 또는 브라우저 종료 후 재접속하더라도 만료되지 않은 인증을 복원 - 지속 인증 복원, 절대 만료 및 현재 설정 binding 판정을 모든 DB 경로 취득·gateway 호출·page dispatch보다 먼저 수행하고, 기존 session boolean만으로 만료·무효화를 우회하지 않음 - 위조·변조·만료·설정 오류가 있는 지속 인증 증거를 fail-closed하고 로그인 화면으로 전환 - 명시적 로그아웃 시 현재 Streamlit 인증 상태와 브라우저의 지속 인증 증거를 함께 폐기 - 전용 signing secret rotation 또는 관리자 password 변경 후 이전 설정으로 발급된 지속 인증을 거부하고, 그 증거에서 복원된 session 상태만으로 접근을 유지하지 않음 - 관리자 credential 원문을 브라우저 저장소, URL, log, traceback 또는 `st.session_state`에 남기지 않는 기존 비노출 계약 유지 - 단위·통합 test에서 24시간/30일 선택과 절대 만료 경계, 활동 시 미연장, 페이지 이동, 새 session 복원, 변조, 로그아웃, signing secret rotation, 관리자 password 변경 및 설정 오류를 검증하고 실제 browser test에서 server-set `HttpOnly` cookie의 발급·복원·삭제를 확인 - `.env.example`, Compose, k3s Secret 계약과 README에 필요한 비밀값·HTTPS·만료 운영 조건 반영 ## 제외 범위 - 다중 사용자, 회원가입, 역할 기반 권한, 사용자별 데이터 분리 - OIDC, SSO, 외부 IdP 도입 - reverse proxy/auth gateway 또는 외부 session middleware로 지속 인증의 발급·검증 책임을 이전하는 방식 - 활동에 따른 sliding 만료 또는 복원 시 만료 기간 재설정 - MCP endpoint 인증 또는 MCP transport 변경 - SQLite 가계부 schema, 금융 데이터 모델 또는 DB-backed session table 추가 - 다른 브라우저·기기 사이의 로그인 공유 - 활성 기기 목록, 개별 session 원격 폐기 또는 관리 UI - 기존 실패 로그인 최소 1초 지연과 배포 경계 rate limiting 정책 변경 - Dashboard 이외 서비스의 cookie·session 정책 변경 ## 제약 조건 - Pinned source revision은 `7bea8b368e02e98afd4b2dc463fb270b0e6eb297`이며 구현 근거는 이 revision의 tree로 한정한다. - 기존 `JARCA_DASHBOARD_ADMIN_ID`와 `JARCA_DASHBOARD_ADMIN_PASSWORD`는 계속 environment에서만 읽고 브라우저에 저장하지 않는다. - 지속 인증 증거는 관리자 ID·password 또는 재사용 가능한 credential 원문을 포함해서는 안 되며, 변조 여부와 만료 시각을 server-side 신뢰 경계에서 검증해야 한다. - 만료 판정은 브라우저가 전달한 현재 시각만 신뢰해서는 안 된다. Server-side에서 로그인 성공 시각에 고정한 24시간 또는 30일의 만료 시각을 검증하며 활동·복원으로 연장하지 않는다. 만료되거나 검증할 수 없는 증거는 session boolean이 참이어도 인증되지 않은 것으로 처리하고 금융 DB·gateway를 호출하지 않는다. - 브라우저에 저장되는 인증 material은 배포 환경에서 HTTPS를 전제로 `Secure`, `HttpOnly`, 적절한 `SameSite`와 최소 path/domain 범위를 적용할 수 있는 방식이어야 한다. JavaScript에서 읽을 수 있는 저장소만으로 인증 credential을 보존하는 방식은 허용하지 않는다. - 지속 인증 검증용 전용 signing secret은 repository나 image에 넣지 않고 Compose/Kubernetes의 별도 secret으로 주입하며, 누락·빈 값·읽기 오류 시 지속 인증을 fail-closed한다. Signing secret rotation은 모든 기존 지속 로그인을 무효화하며, 관리자 password 변경도 검증 binding을 바꿔 기존 지속 로그인을 무효화한다. Binding과 검증 과정은 credential 원문·재사용 가능한 verifier를 브라우저나 log에 노출하지 않아야 한다. - 선택한 Dashboard server-side adapter는 실제 Streamlit runtime의 HTTP response에서 `HttpOnly` cookie를 발급·삭제할 수 있어야 한다. 현재 저장소 근거만으로 이 구현 가능성이 검증됐다고 간주하지 않으며, 불가능한 경우 JavaScript-readable 저장소나 미선택 proxy/middleware 방식으로 임의 대체하지 않는다. - 인증 복원·로그아웃은 SQLite 가계부 데이터와 금융 transaction을 변경하지 않는다. - 기존 Dashboard page 목록, query parameter, gateway와 MCP 동작은 인증 성공 이후 동일하게 유지한다. ## 확정된 결정 - Dashboard 페이지 이동만으로 재로그인을 요구하지 않는다. - `로그인 유지`를 선택하지 않은 정상 로그인도 브라우저 종료 후 24시간 유지한다. - `로그인 유지`를 선택한 로그인은 30일 동안 유지한다. - Dashboard server-side adapter가 `HttpOnly` cookie를 발급·검증·삭제하며 실제 Streamlit runtime에서 HTTP response 제어가 가능한 구현을 사용한다. - 만료 기준은 로그인 성공 시각이며 24시간 또는 30일 후 절대 만료한다. 활동·페이지 이동·새 session 복원으로 만료를 연장하지 않는다. - 전용 signing secret rotation은 모든 기존 지속 로그인을 무효화하고, 관리자 password 변경도 검증 binding을 바꿔 기존 지속 로그인을 무효화한다. - `로그인 유지` checkbox의 기본값은 선택하지 않은 상태다. - 지속 인증은 동일한 브라우저 profile에서만 복원하며 다른 기기로 복제하거나 동기화하지 않는다. - 명시적 로그아웃은 session-only 인증과 해당 브라우저의 지속 인증을 모두 종료한다. - 현재 단일 관리자 credential, 공통 인증 gate, 인증 전 DB 차단과 credential 비노출 계약은 유지한다. - 가계부 SQLite schema와 MCP 인증 범위는 변경하지 않는다. ## 저장소 근거 - `dashboard/authentication.py:21-25,92-139` — 인증 상태가 `st.session_state` boolean과 session-local 값으로만 관리되고, 성공 시 persistent 인증 material을 발급하지 않는다. - `dashboard/app.py:28-59` — 인증 gate가 DB 경로 취득과 page dispatch보다 먼저 실행되므로 지속 인증 복원도 이 경계 안에서 완료되어야 한다. - `dashboard/common.py:358-364` — sidebar navigation이 `?page=...`의 `target="_self"` anchor를 사용한다. - `tests/test_dashboard_authentication_app.py:108-135` — 현재 test는 같은 AppTest session의 rerun 유지와 새 session 재인증을 승인된 동작으로 검증한다. - `docs/requirements/req-001_dashboard-administrator-authentication.md:31-40,105-116,328-346` — REQ-001은 browser session 범위만 포함하고 persistent cookie를 제외하며 새 session 재인증을 요구한다. - `docs/interface-contract.md:42-83,104-111` — login·logout interface가 `st.session_state` boolean만 정의하고 persistent 인증 입력·출력·오류를 정의하지 않는다. - `docs/runtime-flow.md:15-29,69-74` — runtime flow는 새 browser session과 rerun에서 session state만 판정하며 persistent 인증 복원 단계가 없다. - `.env.example:4-6`, `docker-compose.yml:30-35`, `deploy/k8s/base/deployment.yaml:123-139` — 현재 배포 secret 계약에는 관리자 ID·password만 있고 지속 인증 검증용 별도 secret은 없다. - `deploy/k8s/base/deployment.yaml:8-10`, `deploy/k8s/README.md:63-67` — 운영 배포는 단일 replica와 `Recreate` 전략이므로 별도 DB-backed distributed session store는 현재 배포 구조의 전제가 아니다. - `pyproject.toml:19-25` — Dashboard optional dependency는 pandas·plotly·Streamlit이며 server-set persistent cookie/session 전용 dependency는 명시돼 있지 않다. `dashboard/authentication.py:92-139`에도 해당 adapter 구현이 없다. 이는 현재 지속 인증 구현의 부재에 대한 근거이며, 선택한 server-side adapter의 구현 가능성이나 불가능성을 증명하지 않는다. - `docs/requirements/req-001_dashboard-administrator-authentication.md`는 Dashboard 관리자 인증의 canonical 요구사항이며 session 범위, persistent cookie 제외, 새 session 재인증을 직접 규정한다. Issue #6은 같은 인증 기능의 해당 계약을 변경하므로 새 ID를 만들지 않고 이 문서의 revision과 추적성을 갱신해야 한다. ## 문서 영향 및 산출물 ### 요구사항명세서 - 조치: 갱신 - 경로: `docs/requirements/req-001_dashboard-administrator-authentication.md` - 문서 ID: `REQ-001` - 제목: Dashboard 관리자 인증 - 변경 내용: 기존 canonical REQ-001의 revision을 상향하고, 현재 session-only·persistent-cookie 제외·새 session 재인증 계약을 Issue #6의 지속 로그인 계약으로 교체한다. 24시간 기본 유지, `로그인 유지` 선택 시 30일, checkbox 기본 미선택, 페이지 이동·브라우저 재시작 복원, 로그인 성공 시각 기준 절대 만료와 활동·복원 시 미연장, 변조·만료·설정 오류 fail-closed, logout 폐기, credential 비노출, Dashboard server-side adapter의 실제 response 제어와 cookie 보안 속성, 전용 signing secret 주입·rotation 및 관리자 password 변경 시 기존 로그인 무효화, 인증 전 DB 차단과 기존 페이지 호환성을 기존 요구사항과 acceptance criteria에 반영한다. 기존 인증 경계·credential 검증·실패 지연·보호 범위 요구사항은 유지하고 session·로그아웃, 배포 설정, 관찰 가능성, 오류·인터페이스·하위 호환성 및 관련 acceptance criteria를 함께 갱신한다. 단위 test에는 token 발급·검증·절대 만료·활동 시 미연장·변조·시간 경계·설정 binding과 비민감 log를, Streamlit/browser 통합 test에는 form 선택, query-link 페이지 이동, 새 session 복원, server-set `HttpOnly` cookie의 발급·삭제와 logout, signing secret rotation과 관리자 password 변경 후 기존 cookie 및 복원된 session의 접근 거부를 포함한다. 추적성에는 근거 Issue `#1`, `#6`, 기존 구현 PR `#3`과 이번 구현 PR `미정`을 구분해 기록한다. - 포함할 내용: Dashboard server-side adapter의 지속 인증 발급·복원·검증·폐기 계약, 로그인 성공 시각 기준 24시간/30일 절대 만료와 미연장, signing secret rotation·관리자 password 변경 시 기존 로그인 무효화, 브라우저·서버 신뢰 경계, 비밀값 주입, 오류 및 관찰 가능성, REQ-001 기존 계약과의 변경 관계, 테스트 가능한 acceptance criteria와 Issue #6 추적성 - 제외할 내용: 다중 사용자·RBAC·SSO·MCP 인증, DB-backed session, 다른 기기 공유, 금융 SQLite migration, 원격 session 관리 UI, sliding 만료, proxy/auth gateway·외부 session middleware로 인증 책임 이전 - 근거: Issue #6은 REQ-001이 이미 소유한 Dashboard 관리자 인증의 session·logout·배포 계약을 변경하며, 별도 기능 경계나 독립 lifecycle을 만들지 않는다. ### 데이터 모델 - 조치: 영향 없음 - 경로: `docs/data-model.md` - 변경 내용: 지속 인증은 금융 SQLite entity·field·relation·migration을 추가하지 않으며 DB-backed session store를 범위에서 제외한다. 브라우저 인증 material의 claims와 만료 값은 데이터 모델이 아니라 인터페이스 계약에서 정의한다. - 근거: `dashboard/authentication.py`가 가계부 DB와 독립적이고, 단일-replica 배포와 이번 제외 범위가 server-side session table을 요구하지 않는다. Pinned tree에도 `docs/data-model.md`가 없다. ### 인터페이스 계약 - 조치: 갱신 - 경로: `docs/interface-contract.md` - 변경 내용: 로그인 입력에 기본 미선택 `로그인 유지` boolean을 추가하고, Dashboard server-side adapter의 지속 인증 증거 발급·브라우저 전달·복원·검증·만료·삭제 interface와 실제 HTTP response 제어 경계를 정의한다. 로그인 성공 시각 기준 24시간/30일 절대 만료와 활동·복원 시 미연장, cookie 이름·scope·`Secure`·`HttpOnly`·`SameSite`, token payload의 비민감 필드, signing secret source, 변조·만료·secret 누락 오류, logout, 전용 signing secret rotation에 의한 모든 기존 지속 로그인 무효화와 관리자 password 변경 시 검증 binding 변경·기존 로그인 무효화, 기존 `st.session_state` boolean이 만료·binding 검증을 우회하지 못하는 관계를 명시한다. 실제 secret·credential·token 예시는 포함하지 않는다. - 근거: 현재 문서는 login 결과를 `st.session_state` boolean으로만 정의하고 새 session 복원 interface가 없다. ### 프로젝트 구조 - 조치: 갱신 - 경로: `docs/project-structure.md` - 변경 내용: 지속 인증의 발급·검증·cookie adapter 책임을 `dashboard/authentication.py`의 공통 인증 경계에 두고 `dashboard/app.py`, page view, 금융 gateway로 역방향 의존하지 않게 한다. 필요한 dependency와 배포 설정은 `pyproject.toml`, `.env.example`, `docker-compose.yml`, `deploy/k8s/base/deployment.yaml` 및 관련 test 경로에 배치하며, 별도 모듈이 필요할 경우 Dashboard server-side adapter의 HTTP response 제어 경계와 test 대응을 문서화한다. 선택하지 않은 proxy/auth gateway·외부 session middleware로 인증 책임을 옮기거나 page별 인증 분기를 추가하지 않는다. - 근거: 현재 프로젝트 구조는 공통 인증을 `dashboard/authentication.py`에 집중하고 page view의 인증 의존을 금지한다. ### 런타임 흐름 - 조치: 갱신 - 경로: `docs/runtime-flow.md` - 변경 내용: Dashboard 진입과 보호 기능 실행 전 설정, 지속 인증의 무결성·절대 만료·현재 설정 binding을 판정하고 유효한 경우에만 session을 복원·유지하는 순서를 추가한다. 기존 session boolean만으로 만료·무효화를 우회하지 않는다. 로그인 성공 시 Dashboard server-side adapter가 로그인 시각부터 24시간 또는 30일 후 만료하는 `HttpOnly` cookie를 발급하고, 페이지 이동·새 연결·활동에서는 그 만료를 연장하지 않는다. 만료·변조·secret 누락 시 cookie 삭제와 미인증 전이, logout 시 session과 browser material의 멱등 폐기, signing secret rotation과 관리자 password 변경 시 이전 증거 및 그 증거로 복원된 session의 무효화, 동시 요청의 실패 복구와 비민감 event 관찰 가능성을 정의한다. 모든 실패 경로에서 DB·gateway 호출 전 중단하도록 유지한다. - 근거: 현재 flow에는 session state 판정만 있고 browser 재연결 복원·만료·cookie 폐기 단계가 없다. ## 미해결 질문 없음
Owner

Discovery 작성 전 이슈 원본

  • dashboard 에서 페이지를 옮길 때 마다 로그인을 해야하는 문제가 있음.
  • 한 번 로그인하면 브라우저가 닫히더라도 24시간은 유지되게 하라.
  • '로그인 유지' 체크박스를 체크하면 30일동안 유지하게 하라.
<!-- gitea-agent:discovery-origin/v1 owner=jsfamily repository=jarca-ledger-mcp issue=6 body-sha256=ff8e7f7252cdfdd8d267642cd40e550c3d1bc1f9e7976c728c5168737fe92cc4 --> ## Discovery 작성 전 이슈 원본 - dashboard 에서 페이지를 옮길 때 마다 로그인을 해야하는 문제가 있음. - 한 번 로그인하면 브라우저가 닫히더라도 24시간은 유지되게 하라. - '로그인 유지' 체크박스를 체크하면 30일동안 유지하게 하라.
Sign in to join this conversation.