vignette/apps/web/e2e
Yun Chan 93dd8f82d7 G8 실제 rollback 증명 종료와 비-secure origin 회기 리뷰 크래시 수정
G8 마지막 게이트인 receipt-bound 실제 image rollback을 격리 NAS
vignette-preview-20260807 에서 실행해 종료했다.

Gate6 계약 정정:
감사 대상 current API 이미지가 com.docker.compose.project/service/version
image label 을 갖고 있어 "helper 의 compose label 0개" 계약은 감사되지 않은
다른 이미지를 쓰지 않는 한 성립하지 않는다. 계약을 key 부재가 아니라
소속(membership) 으로 바꿔 launch-nas-preview-g8-helpers.py 에 구현했다.
image 상속 label 을 baseline 으로 읽고 container 의 모든 compose label 이
baseline 과 같거나 선언된 격리 override 인지 검사하며, 최종 project 는
target 이 아니고 service 는 api/web/db/proxy 가 아니어야 한다. docker run
argv 에 target label 을 주입하면 fake-runner 테스트가 먼저 깨진다 (37/37).

실행 결과:
- rollback-old  receipt nas-g8-723eeef22eab05e63e3fafb0 -> 79ec../c530..
- restore-current receipt nas-g8-2738846cf2cf4fbe8ce0fc26 -> 52e0../6fdb..
- release gate/approval 각 2회 멱등, audit.ci_lifecycle_event rollback/executed 2,
  audit.ci_human_approval_event authorize_rollback 2, silent auto-promotion 0
- HMAC journal 6-record 체인 검증, health 3/3, OpenAPI 126, auth 401, Web 200
- helper 0, listener 0, 비밀 env 파기. down/volume rm/prune 미실행, 공개 런타임 미접촉
- 계획했던 Windows SSH 터널은 NAS sshd 가 direct-tcpip 를 거부해 사용할 수 없어
  sshd 설정 변경 대신 같은 격리 계약의 NAS-side probe 컨테이너로 실행했다

비-secure origin 크래시 수정:
배포된 NAS 프리뷰(평문 HTTP, 비-localhost)에 회기 스펙을 돌려 24건 실패를 확인했고
원인은 하나였다. crypto.randomUUID 는 secure context 전용인데 제품 코드 18곳이
fallback 없이 호출했고 RuptureRepairCard 는 렌더 시점 호출이라 회기 리뷰 라우트
전체가 error boundary 로 떨어졌다. 릴리스 게이트 108/108 은 localhost 후보 스택에서만
돌아 이 경로를 밟은 적이 없다. src/lib/uuid.ts 의 randomUuid() 로 통일하고 fallback 도
crypto.getRandomValues 를 우선 사용해 idempotency key 의 예측 불가능성을 유지했다.
회귀는 insecure-context-uuid.spec.ts 6/6 으로 고정했다(직접 호출 0건 검사 포함).
이 수정은 아직 NAS 에 배포하지 않았다.

검증:
API 898, gateway 58, executor 28, probe 11, helper launcher 37, release agent 21,
ruff clean, web api-types/typecheck/build, SSOT FAIL 0, SSOT unit 5/5,
dashboard E2E 10/10, 학생 폐루프 실 DB 브라우저 4/4(일회용 클론),
crypto 수정 후 기존 스펙 회귀 70/70, 복원된 NAS 실제 브라우저 SSE->DB 리뷰 PASS.

부수 발견(열린 항목):
공개 API 가 engine=false 로 degraded 인데 워치독이 이를 감지하지 못한다. engine 판정이
게이트웨이 /health 의 ok 만 보고 claude readiness probe 를 돌리지 않기 때문이다.
같은 .env 와 같은 CLI 로 새 게이트웨이를 다른 포트에 띄우면 즉시 ready 이므로 상주
프로세스의 세션만 죽은 형태다. TODO A절과 대시보드에 기록했다.

이 커밋은 파일 단위로 담겼다. 위 파일들에는 이전 세션의 미커밋 G0~G8 작업이 함께
들어 있으며, hunk 를 쪼개면 대시보드/체커/TODO 정합성이 깨져 SSOT 체커가 실패한다.
2026-08-07 22:17:20 +09:00
..
admin.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
auth-visual.spec.ts 전 저장소 리팩터링과 SSOT 정비 2026-07-15 21:31:30 +09:00
auth.spec.ts 음성 재생과 운영 배포 정리 2026-06-28 12:18:20 +09:00
avatar-expression-lab.spec.ts 음성 재생과 운영 배포 정리 2026-06-28 12:18:20 +09:00
avatar-expression.spec.ts 전 저장소 리팩터링과 SSOT 정비 2026-07-15 21:31:30 +09:00
breakpoint-sweep.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
chunk-recovery-preview.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
db-persistence.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
dev-dashboard.spec.ts G8 실제 rollback 증명 종료와 비-secure origin 회기 리뷰 크래시 수정 2026-08-07 22:17:20 +09:00
full-sweep-admin-ai.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
full-sweep-admin.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
full-sweep-auth.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-learner-home.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-persona-studio.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-professor.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-session-review.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-session.spec.ts 세션 화면 디자인 개편 2026-07-31 09:19:42 +09:00
full-sweep-settings.spec.ts 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영 2026-07-27 14:25:24 +09:00
full-sweep-shell.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
insecure-context-uuid.spec.ts G8 실제 rollback 증명 종료와 비-secure origin 회기 리뷰 크래시 수정 2026-08-07 22:17:20 +09:00
kb-source-packs.spec.ts 세션 평가·라이브코치·교수자 분석 라운드 마감 + 문서 정리 + 코드품질 리팩터 2026-07-02 02:50:36 +09:00
layout-visual-gate.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
learner.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
live2d-assets.spec.ts 대시보드 폴드아웃/드릴다운 정리 + 페르소나 역린·misconduct 반응 + 게이트웨이 격리·RAG 비차단 수정 2026-06-27 02:30:46 +09:00
public-admin-visual.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
public-auth-turn.spec.ts Stabilize runtime auth and E2E coverage 2026-06-26 14:47:00 +09:00
readiness.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
README.md feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
session-layout.spec.ts 음성 재생과 운영 배포 정리 2026-06-28 12:18:20 +09:00
session-mvp.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
session-persistence.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
session-review-fixture.ts 운영 화면과 회기 리뷰 UI 갱신 2026-06-28 20:13:21 +09:00
session-review.spec.ts 전 저장소 리팩터링과 SSOT 정비 2026-07-15 21:31:30 +09:00
settings.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
support.ts 한신대 피드백 개선팩 반영 2026-07-03 19:53:14 +09:00
teacher.spec.ts feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
voice-success.spec.ts 텍스트 응답 음성 재생 연결 2026-07-13 16:09:34 +09:00
voice.spec.ts 세션 평가·라이브코치·교수자 분석 라운드 마감 + 문서 정리 + 코드품질 리팩터 2026-07-02 02:50:36 +09:00

Playwright E2E

This directory contains both full-stack E2E tests that exercise the app through the Vite /api proxy and a running local FastAPI server, and focused UI regression tests that pin states with Playwright route fixtures. Treat a test as DB-backed/real-API evidence only when the spec does not fulfill the endpoint being verified and asserts the actual API response or persisted read model.

Required local services:

# apps/api
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000

# apps/web, started automatically by Playwright unless already running
npm run dev -- --host 127.0.0.1 --port 5173

Useful overrides:

PLAYWRIGHT_PORT=5174 npm run e2e
PLAYWRIGHT_BASE_URL=http://localhost:5173 npm run e2e
VITE_API_BASE=http://127.0.0.1:8000 npm run e2e

Feature evidence map:

  • session-persistence.spec.ts is the primary DB-backed evidence for session runtime flows. It covers browser openSessionStream() persistence, Korean PII masking through the browser stream into DB-backed detail/review payloads, crisis learner-only safety persistence without a client AI reply, AI tutor live coach history, source-pack metadata round-trip, voice metadata persistence, learner worksheet/review persistence, session-end evaluation storage, explicit teacher session/turn reevaluation, and fail-closed admin engine configuration that rejects an unreachable gateway without mutating the durable setting. The AI tutor history test must see status=ready and latency_ms>0; degraded fallback must not pass as normal engine-backed coaching.
  • kb-source-packs.spec.ts is DB-backed source-pack sync evidence. It checks admin-only sync and source-scoped evaluator RAG lookup for the licensed source packs; evaluator retrieval 503 is a failure, not a skipped proof.
  • session-review.spec.ts is route-fixture UI regression evidence for review states, including delayed 평가 대기 to 평가 완료 polling, 평가 실패, AI 평가 재시도, and pre/post input validation states. It does not prove that the evaluator wrote a DB row unless paired with session-persistence.spec.ts.
  • teacher.spec.ts mixes DB-backed teacher console paths with route-fixture queue/readability checks. Use the individual test body before citing it as persisted evidence.
  • session-mvp.spec.ts is mostly route-fixture UI regression evidence. The AI tutor tests mock normal coaching, stale quota refresh, quota exhaustion over an old card, degraded fallback, history load failure, and runtime persistence source to prove the UI does not show replacement coaching, missing history, stale credits, or temporary storage as a silent success; the voice tests mock the browser microphone/WebSocket to prove both a final transcript followed by turn_persistence_unavailable and a voice conversation_stopped crisis reply remain visible as failure/safety states instead of successful client turns. These are not DB-backed engine success evidence.

Public Google OAuth /turn smoke:

# 1) Verify the public API is not accidentally serving the dev runtime.
$env:E2E_PUBLIC_AUTH="1"
npx playwright test e2e/public-auth-turn.spec.ts --project=chromium-public-auth --grep "production-safe"

# 2) Open a browser, sign in with an allowed Google account, then close codegen.
npx playwright codegen https://vignette.chanpaca.net/login --save-storage=./node_modules/.tmp/public-auth.json

# 3) Reuse that authenticated storage state for the public API turn smoke.
$env:E2E_PUBLIC_AUTH="1"
$env:E2E_PUBLIC_STORAGE_STATE="./node_modules/.tmp/public-auth.json"
npx playwright test e2e/public-auth-turn.spec.ts --project=chromium-public-auth

Public admin visual smoke:

# Capture storage state after signing in with an admin-entitled Google account.
npx playwright codegen https://vignette.chanpaca.net/login --save-storage=./node_modules/.tmp/public-admin-auth.json

# Verify that https://vignette.chanpaca.net/admin visibly renders the admin console.
$env:E2E_PUBLIC_AUTH="1"
$env:E2E_PUBLIC_STORAGE_STATE="./node_modules/.tmp/public-admin-auth.json"
npx playwright test e2e/public-admin-visual.spec.ts --project=chromium-public-auth

이 스모크에는 공식 EasyList의 과거 충돌 규칙(.ad-root, .ad-section)을 첫 paint부터 주입한 상태로 운영 홈·AI 운영·사용자·권한·티켓 5경로의 실제 가시성을 확인하는 게이트가 포함된다. API 200, DOM 존재, selector count만으로는 통과하지 않는다.

Production lazy-chunk recovery smoke (no sign-in state required):

$env:E2E_PREVIEW_BUILD="1"
$env:PLAYWRIGHT_SKIP_WEB_SERVER="1"
$env:PLAYWRIGHT_BASE_URL="https://vignette.chanpaca.net"
npx playwright test e2e/chunk-recovery-preview.spec.ts --project=chromium-single-run --workers=1

Notes:

  • E2E_PUBLIC_AUTH=1 targets the public site and does not start the local Vite web server.
  • public-auth.json contains the HttpOnly API session cookie exported by Playwright. Treat it as sensitive and keep it under node_modules/.tmp.
  • The API session TTL is currently 8 hours, so recapture storage state when the smoke begins returning 401.

Install browser binaries once with:

npx playwright install chromium