로컬 회귀와 공개 prod-safe 게이트 통과
백엔드 unittest 20개, Python compile, 웹 production build, 전체 Playwright 72개가 통과했다. 공개 API도 `environment:"prod"`, `db:true`, `engine:true`로 응답한다.
이번 세션은 seed persona 결합 제거, 비개발 fail-closed 설정, compose OAuth 주입, admin 모바일 overflow 수정, persona 인증 경계 보강, 전체 Playwright 재통과, 공개 API prod 전환까지 완료했다. 이후 로컬 5175 런타임 재기동, admin 사용자 관리 E2E 안정화, 학습자 홈 0회 기록 UX, active session 실제 SSE 스트림 전환, 텍스트/음성 실패 턴 미저장, 직접 URL persona 우회 차단, Live2D demo fallback 제거, AI 운영 fail-closed 보강까지 전체 Playwright로 확인했다. 2026-06-26 14:53 KST 기준 공개 API 터널을 복구한 뒤 전체 Playwright 72개가 desktop/mobile/single-run 모두 통과했다. Cloudflare Pages production 배포 `b5e22068`도 완료했고, 커스텀 도메인이 새 asset을 서빙하는 것을 확인했다. 공개 Google OAuth 실제 `/turn` 증명만 storageState 캡처 후 남아 있다.
이 HTML만 보고 판단해야 하는 항목
백엔드 unittest 20개, Python compile, 웹 production build, 전체 Playwright 72개가 통과했다. 공개 API도 `environment:"prod"`, `db:true`, `engine:true`로 응답한다.
Cloudflare Pages production `b5e22068`이 `188e899`로 배포됐고, `https://vignette.chanpaca.net`이 `index-BKpoLhfw.js`와 `index-BA9-xxfn.css`를 서빙한다.
실제 Google 로그인 쿠키가 필요한 공개 `/turn` smoke는 아직 storageState가 없어 미완이다. 로그인 가능한 계정으로 한 번 캡처하면 바로 검증 가능하다.
프론트 페이지는 실제 API/DB 경로를 탄다. 남은 `mock` 표기는 테스트 코드의 `unittest.mock` 또는 의도적 fixture이며, seed fallback은 prod/staging에서 fail-closed 된다.
새 세션에서 반복하지 않아도 되는 작업
`session-persistence`, `teacher`, `voice`는 `/api/personas`에서 실제 DB persona를 가져온다.
prod/staging에서 dev login, seed fallback, OAuth 누락, 기본 secret, localhost CORS를 거부한다.
`ENVIRONMENT`, Google OAuth vars, `CORS_ORIGINS`, `OPENAI_BASE_URL`을 API 컨테이너에 명시했다.
긴 readiness detail을 안정화했고, 사용자 변경은 DB 저장소가 durable할 때만 허용한다. AI 운영은 실제 어댑터명과 health 상태를 표시한다.
`db-persistence`는 전역 engine config를 바꾸므로 `@single-run`으로 분리했다.
`docs/HANDOFF.md`, `docs/dev_dashboard.html`, `apps/web/e2e/README.md`를 최신 상태로 맞췄다.
`cloudflared` ingress를 `127.0.0.1:8001` prod API로 돌렸고 public readiness gate가 통과했다.
`scripts/start-public-runtime.ps1`와 `scripts/stop-public-runtime.ps1`로 API 8001과 cloudflared를 재현 가능하게 만들었다.
`/personas`는 이제 비로그인 401이다. 로컬과 공개 API 모두 직접 확인했고 E2E 회귀를 추가했다.
public 웹에서 `/api/auth/config`가 SPA HTML로 떨어지지 않도록 public API origin fallback을 추가했다.
학습자 홈은 이제 fake 기록 없이 실제 서버 세션 0개를 `기존 회기` 빈 상태와 0 카운트로 표시한다.
`127.0.0.1:5175` web, `8000` API, `9099` engine을 재기동하고 dev-login 서버 세션과 `/learn` redirect를 확인했다.
375px급 active session에서 stage 내부가 1px 넘게 잘리던 문제를 avatar/padding 조정으로 제거했다.
`POST /sessions/{id}/stream` token 이벤트로만 내담자 자막을 쌓고, HTTP 거절과 SSE error 모두 실패 턴을 transcript와 저장소에 남기지 않는다.
음성 회기도 엔진 응답 생성 성공 후에만 learner/client turn을 저장한다. 실패한 transcript는 pending 상태에서 제거한다.
admin health와 voice degraded reason은 내부 fallback/seed 표현 대신 비영구 런타임 상태를 사용자용 문구로 표시한다.
`/learn/session/:code`로 직접 들어와도 DB 원본 persona가 아니면 회기 시작을 막는다. degraded/seed fallback 회귀를 추가했다.
Mao/Haru 샘플은 공용 fallback으로 쓰지 않는다. 실제 persona별 `live2dModelUrl`이 있을 때만 Live2D를 렌더링한다.
마지막으로 직접 실행한 결과
| 범위 | 명령 | 결과 |
|---|---|---|
| Web typecheck | npm run typecheck | Passed |
| Backend | python -m unittest app.test_runtime_policy app.test_session_turn_persistence engine_gateway.test_gateway_model | 20 tests OK |
| Compile | python -m compileall app engine_gateway | Passed |
| Web build | npm run build | Passed |
| Pages production deploy | wrangler pages deploy dist --project-name vignette --branch main | `b5e22068`, source `188e899` |
| Custom domain assets | https://vignette.chanpaca.net/ | `index-BKpoLhfw.js`, `index-BA9-xxfn.css` |
| Compose | docker compose --env-file .env.example config --quiet | Passed with dummy required env |
| Focused E2E | admin + db-persistence + voice-success | 10 passed |
| Admin manage-users | admin.spec.ts --grep manage real server-known users | desktop/mobile 2 passed |
| Full E2E | PLAYWRIGHT_HOST=127.0.0.1 npx playwright test | 72 passed |
| Public auth discovery | E2E_PUBLIC_AUTH=1 npx playwright test --list --project=chromium-public-auth | 2 tests listed |
| Public readiness | public-auth-turn.spec.ts --grep production-safe | 1 passed |
| Persona auth boundary | GET /personas | local/public unauth 401 |
| Public login | auth.spec.ts --grep public login | 1 passed |
| Public runtime script | scripts\start-public-runtime.ps1 | API 8001 + cloudflared running |
| Public API health | https://api-vignette.chanpaca.net/health | prod, db true, engine true |
| Local 5175 login | PLAYWRIGHT_BASE_URL=http://127.0.0.1:5175 auth.spec.ts | desktop/mobile passed |
| Learner/readiness E2E | learner.spec.ts + readiness.spec.ts desktop/mobile | 14 passed |
| Learner screenshots | learn-empty-desktop.png / learn-empty-mobile-compact.png | document overflow 0, empty history visible |
| Session layout/turn | session-layout.spec.ts desktop/mobile | 8 passed |
| Voice/session focused | voice + voice-success + session-layout | 15 passed |
| Latest focused E2E | learner + session-layout + settings + admin | 37 passed |
다음 세션 첫 작업
2026-06-26 14:53 KST 기준 Google 로그인 storageState가 없어 공개 API `/turn` 실제 성공 증거가 아직 없다.
터널은 `127.0.0.1:8001` prod API를 본다. 재부팅 후에는 prod API와 cloudflared를 같이 재기동해야 한다.
E2E가 admin engine config를 건드린다. 배포 전 의도한 model/url/mode인지 다시 확인해야 한다.
공개 OAuth smoke
cd D:\workspace\vignette\apps\web npx playwright codegen https://vignette.chanpaca.net/login --save-storage=.\node_modules\.tmp\public-auth.json $env:E2E_PUBLIC_AUTH="1" $env:E2E_PUBLIC_STORAGE_STATE=".\node_modules\.tmp\public-auth.json" .\node_modules\.bin\playwright.cmd test e2e/public-auth-turn.spec.ts --project=chromium-public-auth
cd D:\workspace\vignette powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-public-runtime.ps1
작업 방식