preview host 허용 회귀 가드 추가 (check:preview-hosts)
배포 도메인 블랭크(vite preview allowedHosts 누락) 재발을 막는 행동 검증 스크립트를 추가. preview를 띄워 공개 Host(vnet/api-vnet/chanpaca) 3종이 200으로 허용되고 임의 Host는 403으로 차단(DNS 리바인딩 보호 유지)되는지 http.request로 직접 Host 헤더를 보내 확인한다. package.json에 check:preview-hosts로 등록. 검증: npm run check:preview-hosts → 공개 3 allowed + unlisted blocked PASS, exit 0. 대시보드 104차 갱신.
This commit is contained in:
parent
7b2ceafd68
commit
5c4ac04e06
3 changed files with 99 additions and 1 deletions
|
|
@ -536,7 +536,7 @@
|
|||
<p class="dg-note">101차 적용(2026-06-30): 관리자(<code>role=admin</code>)가 학습자·교수자·관리자 워크스페이스를 모두 직접 오갈 수 있도록 권한 경계를 정리했다. 백엔드는 <code>Principal.can_access_role()</code>이 <code>role=admin</code>이면 모든 역할 접근을 허용하고, <code>require_role()</code>은 super_admin뿐 아니라 admin도 허용 역할로 승격한다. 학습자 전용 경로(<code>/consent</code> accept/withdraw, <code>/voice/ws</code>)의 super_admin-only 승격 분기도 <code>can_access_role(Role.LEARNER)</code> 기준으로 바꿔 admin이 동일하게 통과한다. 프론트는 <code>auth.tsx</code>의 <code>canAccessRole()</code>에 admin 전체 접근을 반영하고, 역할 전환 메뉴는 <code>accessibleRolesFor()</code> 단일 헬퍼가 소유하며, <code>Sidebar</code> admin 내비에 <code>운영 홈</code>·<code>교수 콘솔</code>·<code>학습자 홈</code>·<code>학습</code>·<code>기록</code> 진입을 추가했다. 외부 API 계약·DB schema·승인 게이트(<code>account_status</code>)·super_admin 권한 부여/회수 동작은 바꾸지 않았다. 검증: <code>npm run typecheck</code>, <code>npm run check:api-types</code>, <code>py -3.11 -X utf8 -B -m pytest app/ -q</code> 290 passed(RBAC/runtime 30 포함), admin 워크스페이스 내비 E2E 1 passed, layout 시각게이트 9/9, session-layout 4 passed.</p>
|
||||
<p class="dg-note">102차 적용(2026-06-30): 소유자(윤찬) 결정 4건이 확정되어 owner 보드 결정 카드 7→3으로 줄었다. (1) <b>s2s 2차 PoC 유지</b> — 캐스케이드 1차를 운영 기준으로 두면서 <code>voice-s2s-poc.md</code> 비교 PoC를 계속 연다(최종 채택은 비교 리포트 이후). (2) <b>fast-loop 외부 폴백 허용</b> — 로컬 상주 분류기 기본 + 외부 Haiku/Solar 폴백 허용, 전송 시 데이터주권·보존·동의 가드 적용. (3) <b>재귀학습 fine-tuning 포함</b> — few-shot 자동갱신에 더해 fine-tuning까지 범위에 포함하되, 데이터셋은 동의·추가 축어록 수급 게이트가 닫힌 뒤 구성. (4) <b>서비스 음성 = 대체 TTS provider</b> — 상업 라이선스가 명확한 대체 provider 채택, Higgs synthetic·dev sample provider는 개발 플래그로만 유지, 실존 인물/성우 ref 금지 유지. 네 결정 모두 방향 확정이며 구현/실측은 후속 build 항목으로 남는다. 남은 owner 결정은 평가설계(H1 κ/ICC), 운영 보존·에스컬레이션, 추가 축어록 수급 3건이다. SSOT drift 게이트(<code>check-dev-dashboard-ssot.py</code>)의 기대 카운트도 결정 3·decision panel 3행으로 동기화했다.</p>
|
||||
<p class="dg-note">103차 적용(2026-06-30): 남은 소유자 결정 3건이 확정되어 owner 결정 7건이 전건 확정(결정 필요 3→0)됐다. (1) <b>평가설계 H1</b> — 평가자 신뢰도 κ≥0.70 & ICC≥0.75, 환각률 ≤3%, 독립표본 t-검정(α=0.05), 20명 실험/통제군 무작위 배정, 단회기 50분·3척도 pre-post 유지. (2) <b>운영 보존·에스컬레이션</b> — 헬스 raw 90일·rollup 365일, escalation 운영자 수동 승인, SLA 미표기(관측 샘플 이력 유지), 담당 그룹 자동 배정 미도입. (3) <b>추가 축어록</b> — 20건을 1개월 내 수급. 이 결정들은 설계·정책 확정이며, KPI threshold 반영·retention 기본값 적용·실제 수급/파일럿 evidence·통계해석은 후속 build/GATE로 남는다. 즉 owner 보드의 남은 항목은 모두 외부 증거·기관 의존(공개 OAuth 실 <code>/turn</code>, vnet DNS, 한신대 거버넌스, 임상팀 콘텐츠, 20명 파일럿·법무·물리 실측)이며, 운영 원칙상 E2E/외부 증거 없이는 DONE으로 체크하지 않는다. SSOT drift 게이트의 기대 카운트도 결정 0·decision panel 0행으로 동기화했다.</p>
|
||||
<p class="dg-note">104차 적용(2026-06-30): 공개 배포 도메인(<code>vnet.18ka.net</code>)에서 슈퍼관리자가 관리자 페이지 전체를 블랭크로 보던 문제를 고쳤다. 원인은 권한이 아니라 <code>vite preview</code> 서버의 host 검증이었다. 배포는 <code>npm run preview</code>를 cloudflared 터널로 공개 도메인에 연결하는데, <code>vite.config.ts</code>에 <code>preview.allowedHosts</code>가 없어 공개 Host 요청이 <code>Blocked request. This host is not allowed.</code> 403 텍스트만 받아 SPA가 통째로 로드되지 못했다(에러 바운더리 부재로 전체 흰 화면). <code>server.allowedHosts</code>와 동일 목록을 <code>preview</code>에도 적용하고 기본 허용에 <code>vnet.18ka.net</code>/<code>api-vnet.18ka.net</code>/<code>vignette.chanpaca.net</code>를 추가했다. 검증: 재현(<code>curl -H "Host: vnet.18ka.net" 127.0.0.1:5174</code> → 수정 전 Blocked, 수정 후 <code>200</code>+정상 index), 로컬 dev·preview에서 일반/슈퍼 관리자 전 admin·teach·learn 페이지 정상 렌더(pageerror 0), <code>npm run typecheck</code>. 공개 OAuth 실 <code>/turn</code> 증명은 여전히 별도 BLOCK이다.</p>
|
||||
<p class="dg-note">104차 적용(2026-06-30): 공개 배포 도메인(<code>vnet.18ka.net</code>)에서 슈퍼관리자가 관리자 페이지 전체를 블랭크로 보던 문제를 고쳤다. 원인은 권한이 아니라 <code>vite preview</code> 서버의 host 검증이었다. 배포는 <code>npm run preview</code>를 cloudflared 터널로 공개 도메인에 연결하는데, <code>vite.config.ts</code>에 <code>preview.allowedHosts</code>가 없어 공개 Host 요청이 <code>Blocked request. This host is not allowed.</code> 403 텍스트만 받아 SPA가 통째로 로드되지 못했다(에러 바운더리 부재로 전체 흰 화면). <code>server.allowedHosts</code>와 동일 목록을 <code>preview</code>에도 적용하고 기본 허용에 <code>vnet.18ka.net</code>/<code>api-vnet.18ka.net</code>/<code>vignette.chanpaca.net</code>를 추가했다. 검증: 재현(<code>curl -H "Host: vnet.18ka.net" 127.0.0.1:5174</code> → 수정 전 Blocked, 수정 후 <code>200</code>+정상 index), 로컬 dev·preview에서 일반/슈퍼 관리자 전 admin·teach·learn 페이지 정상 렌더(pageerror 0), <code>npm run typecheck</code>. 회귀 방지로 <code>npm run check:preview-hosts</code>(<code>scripts/check-preview-hosts.mjs</code>)를 추가해 preview를 띄워 공개 Host 3종 200 허용·임의 Host 403 차단을 행동 검증한다(공개 3 allowed·unlisted blocked 통과). 공개 OAuth 실 <code>/turn</code> 증명은 여전히 별도 BLOCK이다.</p>
|
||||
<p class="dg-note">20차 적용(2026-06-28): 신규 Google/SAML 사용자는 <code>account_status=pending</code>으로 시작하고 승인 전에는 <code>/pending</code> 안내 화면만 본다. <code>yunchan@twentyoz.kr</code>는 슈퍼 관리자 allowlist로 admin+approved를 받으며, <code>/admin/users</code>는 가입 승인 탭에서 pending 계정을 승인 또는 보류 처리한다.</p>
|
||||
<p class="dg-note">21차 적용(2026-06-28): 관리자 페이지 진입권을 기본 역할과 분리해 <code>app_user.admin_access</code>로 저장한다. <code>AUTH_SUPER_ADMIN_EMAILS</code> 기본값은 <code>yunchan@twentyoz.kr</code>, <code>hoonjungkoo@hs.ac.kr</code>이며, 슈퍼 관리자는 학습자·교수자·관리자 공간 전환과 관리자 권한 부여/회수를 할 수 있다. 학생·교수 계정도 <code>admin_access=true</code>면 우측 상단 관리자 진입이 노출된다. 구성 슈퍼 관리자의 권한 회수와 계정 비활성화는 차단한다.</p>
|
||||
<p class="dg-note">25차 적용(2026-06-28): <code>/admin/users</code>에서 허용 도메인 밖 이메일도 정확한 계정 단위로 강제 등록할 수 있다. Google/SAML/dev-login은 미리 등록된 이메일만 도메인 게이트 예외로 통과시키고, provider 로그인 시 기존 관리 row의 역할·코호트·승인 상태를 이어받는다. 미등록 외부 도메인 로그인은 계속 차단한다.</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue