diff --git a/docs/requirements/req-001_dashboard-admin-authentication.md b/docs/requirements/req-001_dashboard-admin-authentication.md new file mode 100644 index 0000000..f81da12 --- /dev/null +++ b/docs/requirements/req-001_dashboard-admin-authentication.md @@ -0,0 +1,246 @@ +--- +{ + "schema": "proofline.requirement/v1", + "id": "REQ-001", + "title": "Dashboard 관리자 인증", + "revision": "0.1", + "status": "draft", + "depends_on": [], + "applies_to": ["streamlit-dashboard"], + "language": "ko" +} +--- + +# REQ-001 — Dashboard 관리자 인증 + +## 1. 목적 + +금융 데이터를 표시·변경하는 Jarca Ledger Streamlit Dashboard를 단일 관리자 인증으로 보호한다. 인증되지 않았거나 상태를 신뢰할 수 없는 사용자는 Dashboard 데이터와 변경 기능에 접근하거나 실행할 수 없어야 한다. + +## 2. 배경 + +현재 Dashboard는 MCP를 경유하지 않고 MCP 서버와 동일한 SQLite 파일을 직접 읽고 쓴다. Dashboard에는 요약·거래·계좌·카테고리·규칙·Import·자산/마감 화면 및 데이터 변경 기능이 있다. + +## 3. 범위 + +### 포함 + +- 모든 Dashboard 화면·조회·navigation의 로그인 전 차단 +- 단일 관리자 로그인·로그아웃 및 session 상태 +- Dashboard write/delete/import/rollback의 관리자 인가와 재확인 +- 배포 Secret에서 주입되는 단일 credential verifier의 검증 +- 인증 실패·세션 누락·구성 누락·권한 불명 시 fail-closed 처리 + +### 제외 + +- MCP 도구 또는 MCP HTTP endpoint의 인증·인가 +- SSO/OIDC, 다중 사용자·역할·테넌트, 세분화 RBAC +- Kubernetes manifest/Secret 생성·교체·배포 자동화 +- 기존 금융 데이터 schema migration + +## 4. 용어와 기준 + +- **Dashboard**: `dashboard/app.py`를 entry point로 실행되는 Streamlit UI. +- **관리자**: 배포 Secret의 단일 credential verifier로 인증된 Dashboard 사용자. +- **보호 기능**: Dashboard 화면 렌더링, SQLite 읽기, write/delete/import/rollback을 포함한 Dashboard 동작. +- **정본 기준**: verifier는 배포 Secret이다. 평문 credential과 verifier는 Git, 이미지, Issue, UI, 로그 또는 SQLite에 저장하지 않는다. + +## 5. 요구사항 + +### REQ-001.01 — 전체 Dashboard 인증 경계 + +시스템은 인증된 관리자 session 전에는 모든 Dashboard 화면, 데이터 조회, navigation 및 보호 기능을 제공하지 않아야 한다. 기본 URL 또는 지원되는 page query parameter를 직접 지정해도 금융 데이터·보호 화면·mutation control이 노출되지 않아야 한다. + +**Impact** + +- Interfaces: Streamlit 로그인·로그아웃 UI 및 session state +- Persistence: 기존 SQLite 금융 데이터 변경 없음 +- Consumers: Dashboard 사용자 +- Migration: 없음 +- Compatibility: 인증 후 기존 Dashboard 화면과 기능은 계속 사용 가능 +- Deployment prerequisites: 관리자 credential verifier 배포 Secret + +### REQ-001.02 — 단일 credential verifier 검증 + +시스템은 배포 Secret에서 주입되는 단일 관리자 credential verifier만으로 로그인 입력을 검증해야 한다. verifier가 누락·빈 값·검증 불가이거나 입력이 불일치하면 로그인 성공을 허용하지 않아야 한다. 비교는 credential 추측에 이용될 수 있는 불필요한 차이를 노출하지 않는 방식이어야 한다. + +**Impact** + +- Interfaces: Secret 기반 Dashboard runtime configuration +- Persistence: credential 또는 인증 session을 SQLite에 기록하지 않음 +- Consumers: Dashboard runtime +- Migration: 없음 +- Compatibility: `JARCA_LEDGER_DB_PATH` 동작 유지 +- Deployment prerequisites: Secret은 image/Git/Issue 외부에서 주입되고 평문이 아님 + +### REQ-001.03 — session 무효화와 로그아웃 + +시스템은 성공한 로그인에 대해서만 현재 Dashboard session에 관리자 인증 상태를 설정해야 하며, 로그아웃 시 인증에 의존하는 상태를 제거해야 한다. 새 session, 누락·손상 session 또는 권한 불명은 미인증으로 처리해야 한다. + +**Impact** + +- Interfaces: Streamlit session state 및 로그인·로그아웃 UI +- Persistence: session을 SQLite에 저장하지 않음 +- Consumers: Dashboard 사용자 +- Migration: 없음 +- Compatibility: 인증 후 query parameter의 기존 화면 선택 의미 유지 +- Deployment prerequisites: 없음 + +### REQ-001.04 — 변경 작업 fail-closed 인가 + +시스템은 Dashboard에서 시작되는 write, delete, import, rollback 및 데이터 상태 변경 동작을 실행 직전에 관리자 인증 상태로 재확인해야 한다. 인증 실패·세션 누락·구성 오류·권한 불명 상태에서는 동작을 실행하지 않고 거래·계좌·카테고리·규칙·예산·import batch 상태를 변경하지 않아야 한다. + +**Impact** + +- Interfaces: Dashboard mutation controls +- Persistence: 기존 SQLite tables; 실패 경로에는 변경 없음 +- Consumers: Dashboard 사용자 및 같은 DB를 쓰는 MCP runtime +- Migration: 없음 +- Compatibility: 인증된 관리자의 기존 변경 기능 유지 +- Deployment prerequisites: 없음 + +## 6. 제약과 불변조건 + +- Dashboard 인증 범위는 MCP에 확장하지 않는다. +- 인증 전에는 금융 데이터, import metadata, 보호 화면 내용 또는 변경 control을 노출하지 않는다. +- 평문 credential과 verifier를 Git, 이미지, Issue, UI, 로그, SQLite에 기록하지 않는다. +- 인증·인가 실패는 deny로 처리하며 SQLite 상태를 변경하지 않는다. +- SQLite DB schema, DB 경로 선택, 단일 Pod/공유 PVC 및 단일 replica 전제는 유지한다. + +## 7. Acceptance Criteria + +### REQ-001.01-AC01 — 미인증 Dashboard 차단 + +**Criterion** + +- 미인증 사용자가 기본 URL 또는 모든 지원 page query parameter로 접근하면 로그인 UI 외의 금융 데이터, 보호 화면, page dispatch 및 mutation control을 볼 수 없다. + +**Verification** + +- Streamlit application test에서 기본 화면과 각 page query parameter를 미인증 상태로 실행한다. + +**Verification Classification** + +- Level: `integration` +- Backend: `Streamlit Dashboard entry point` +- Cases: `negative | boundary | unchanged-state` + +**State Invariants** + +- 검증 중 SQLite와 관리자 인증 session은 생성·변경되지 않는다. + +### REQ-001.02-AC01 — 유효 verifier만 로그인 허용 + +**Criterion** + +- 유효한 Secret-provided verifier와 일치하는 입력만 관리자 session을 만들고, 불일치·누락·빈 값·검증 불가 verifier는 로그인 성공을 만들지 않는다. + +**Verification** + +- 유효 verifier, 불일치 입력, 누락 verifier, 빈 verifier 각각의 application test를 실행한다. + +**Verification Classification** + +- Level: `integration` +- Backend: `Streamlit Dashboard runtime configuration` +- Cases: `positive | negative | boundary | unchanged-state` + +**State Invariants** + +- verifier와 입력 평문은 test output, UI, SQLite에 보존되지 않는다. + +### REQ-001.03-AC01 — 로그아웃과 신뢰할 수 없는 session 차단 + +**Criterion** + +- 로그인 성공 후 로그아웃하면 보호 화면 접근이 즉시 차단되고, 새·누락·손상 session은 미인증으로 처리된다. + +**Verification** + +- 로그인, 로그아웃, 새 session, session key 변조 및 page 재접근을 순서대로 검증한다. + +**Verification Classification** + +- Level: `integration` +- Backend: `Streamlit session state` +- Cases: `positive | negative | boundary | unchanged-state` + +**State Invariants** + +- 로그아웃과 미인증 재접근은 SQLite와 import batch를 변경하지 않는다. + +### REQ-001.04-AC01 — 미인증 변경 무실행 + +**Criterion** + +- 미인증·세션 누락·구성 오류·권한 불명 상태에서 Dashboard mutation을 시도해도 write/delete/import/rollback이 실행되지 않고 SQLite 상태가 변경되지 않는다. + +**Verification** + +- fixture SQLite DB에서 각 mutation 종류의 실패 경로 전후 table과 import batch를 비교한다. + +**Verification Classification** + +- Level: `integration` +- Backend: `Streamlit Dashboard and SQLite fixture` +- Cases: `negative | unchanged-state` + +**State Invariants** + +- 실패 경로에는 거래·계좌·카테고리·규칙·예산·import batch의 추가·수정·삭제가 없다. + +## 8. 오류 및 충돌 계약 + +- verifier의 누락·공백·형식 오류·검증 오류는 일반적인 인증 실패로 처리하며 보호 기능을 허용하지 않는다. +- 인증 상태가 없거나 일관되지 않으면 로그아웃된 상태로 처리한다. +- 인증/인가 실패 중 DB transaction 또는 부분 기록을 남기지 않는다. +- Secret 교체 후 새 runtime이 새 verifier를 사용한다. 재기동은 운영 절차이며 이 REQ 범위 밖이다. + +## 9. 데이터 및 인터페이스 계약 + +- 입력: 로그인 UI credential 및 배포 Secret credential verifier. +- 출력: 성공 시 보호 Dashboard, 실패 시 금융 데이터를 포함하지 않는 로그인/실패 안내. +- 인증 session은 Dashboard runtime session에만 존재하며 SQLite에 저장하지 않는다. +- Secret key 이름, password hashing 알고리즘, cookie/session backend 같은 구현 세부는 고정하지 않는다. 선택 방식은 본 문서의 불변조건과 AC를 충족해야 한다. + +## 10. 하위호환성 + +- SQLite schema와 `JARCA_LEDGER_DB_PATH` 선택 방식은 유지한다. +- 기존 page query parameter는 인증된 관리자에게만 기존 화면 선택 의미를 유지한다. +- MCP 도구·endpoint와 인증 동작은 변경하지 않는다. +- 기존 Dashboard read/write/delete/import 기능은 인증된 관리자에게만 유지한다. + +## 11. 검증 계획 + +- Streamlit entry point로 미인증 기본 URL 및 모든 지원 page query parameter 차단을 검증한다. +- 유효/불일치/누락/빈 verifier, 로그인·로그아웃·session 오류를 검증한다. +- 각 Dashboard mutation의 인증 재확인 및 실패 시 SQLite 무변경을 fixture DB로 검증한다. +- 전체 `pytest`와 `ruff check .`를 실행한다. +- 실제 운영 Secret 또는 credential 값은 테스트·문서·evidence에 사용하지 않는다. + +## 12. 추적성 + +- 근거 이슈: Refs #1 +- 구현 PR: 없음 — 본 문서는 구현 전 canonical draft다. +- 관련 설계 문서: `README.md`, `dashboard/app.py`, `docs/requirements/TEMPLATE.md` +- 관련 requirement: 없음 +- Discovery fingerprint: `210f67c76ce488e61454091f1755a4c67f7e21e75d71982b08771f6294cd226c` + +## 13. 확정된 결정 + +- Dashboard의 모든 화면과 조회는 로그인 후에만 접근한다. +- Dashboard write/delete/import는 인증된 관리자만 실행한다. +- 범위는 Dashboard 인증으로 한정하며 MCP 권한 제어는 후속 이슈다. +- 최초 관리자 credential verifier는 배포 Secret에서 주입하며 값은 이미지·Git·Issue에 저장하지 않는다. +- Secret 교체 후 runtime 재기동으로 credential 교체를 반영한다. +- 인증 실패·세션 누락·권한 불명은 보호 기능을 실행하지 않는다. + +## 14. Open Questions + +- 없음. 구현 세부는 제품 정책을 바꾸지 않고 본 문서의 불변조건과 AC를 충족해야 한다. + +## 15. 승인 기록 + +- 상태: `draft` +- 승인 주체: 미승인 +- 승인 근거: 사용자 검토 및 이 PR의 명시적 병합 대기