From 6ec4a42d90f3bd30dbe6d7f4cde2c22dbd178905 Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sun, 28 Jun 2026 12:20:18 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/dev_dashboard.html | 6 +++--- docs/guides/local-development.md | 2 +- docs/guides/testing.md | 34 ++++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/docs/dev_dashboard.html b/docs/dev_dashboard.html index 0aa501f..54fd317 100644 --- a/docs/dev_dashboard.html +++ b/docs/dev_dashboard.html @@ -633,7 +633,7 @@
-
현재

정규식 폴백에 한국어 고위험 패턴 추가: 구체 날짜(2001.4.18→[DATE])·금액(1200원→[MONEY])·행정구역 주소(서울시 강남구 역삼동→[ADDR]). 상담 생성(generate/stream)·fast/deep 평가의 외부 LLM 호출 직후 audit.llm_call_log에 provider/model/token/cost/inference_geo/latency만 적재한다. prompt/completion 본문은 저장하지 않는다. 로컬 dev-login 실제 /turn smoke에서 audit.llm_call_log가 8→11로 3행 증가했다. 이번 패스에서 app_user에 이름·소속·학과·학년/직위·연락처·주소/수령지·닉네임·자기소개·아바타 URL·약관/개인정보 동의 시각·버전을 추가했다. 로그인 후 onboarding_completed_at이 없으면 전역 OnboardingGate/onboarding 외 URL(/learn, /settings, /admin, /dev/avatar-preview, /login 포함)을 모두 온보딩으로 돌리고, 온보딩 중에는 공용 셸 메뉴 없이 가입 직후 사용자 정보 입력 폼만 보여준다. learner 회기 시작도 온보딩 완료 전에는 막는다. /users/me/avatar는 PNG/JPG/WebP MIME·시그니처·3MB 제한 후 파일을 USER_UPLOAD_DIR/profile-avatars에 저장하고 URL만 보관한다. 약관·개인정보 처리방침 초안은 /users/legal-docs에서 제공한다. 관리자/교수자 권한은 온보딩에서 받지 않고 allowlist/관리자 사용자 관리로만 부여한다. 검증: pytest app/ -q 145 passed, pytest engine_gateway/ -q 9 passed, npm run check:api-types, npm run typecheck, npm run build, auth E2E 7 passed, 최종 PLAYWRIGHT_PORT=5174 npm run e2e 113 passed.

잔여

이름/기관명은 NER 필요(Presidio ko 모델·spaCy ko, 무거움 — TODO 명시). 미성년/guardian 및 법무 검토가 필요한 최종 서명 동의서·개인정보 처리방침·약관 evidence는 외부 게이트다. 공개 Google OAuth 실제 /turn proof는 별도 운영 게이트.

+
현재

정규식 폴백에 한국어 고위험 패턴 추가: 구체 날짜(2001.4.18→[DATE])·금액(1200원→[MONEY])·행정구역 주소(서울시 강남구 역삼동→[ADDR]). 상담 생성(generate/stream)·fast/deep 평가의 외부 LLM 호출 직후 audit.llm_call_log에 provider/model/token/cost/inference_geo/latency만 적재한다. prompt/completion 본문은 저장하지 않는다. 로컬 dev-login 실제 /turn smoke에서 audit.llm_call_log가 8→11로 3행 증가했다. 이번 패스에서 app_user에 이름·소속·학과·학년/직위·연락처·주소/수령지·닉네임·자기소개·아바타 URL·약관/개인정보 동의 시각·버전을 추가했다. 로그인 후 onboarding_completed_at이 없으면 전역 OnboardingGate/onboarding 외 URL(/learn, /settings, /admin, /dev/avatar-preview, /login 포함)을 모두 온보딩으로 돌리고, 온보딩 중에는 공용 셸 메뉴 없이 가입 직후 사용자 정보 입력 폼만 보여준다. learner 회기 시작도 온보딩 완료 전에는 막는다. /users/me/avatar는 PNG/JPG/WebP MIME·시그니처·3MB 제한 후 파일을 USER_UPLOAD_DIR/profile-avatars에 저장하고 URL만 보관한다. 약관·개인정보 처리방침 초안은 /users/legal-docs에서 제공한다. 관리자/교수자 권한은 온보딩에서 받지 않고 allowlist/관리자 사용자 관리로만 부여한다. 검증: pytest app/ -q 178 passed, pytest engine_gateway/ -q 11 passed, npm run check:api-types, npm run typecheck, npm run build, auth E2E 7 passed, 최종 PLAYWRIGHT_PORT=5174 npm run e2e 113 passed.

잔여

이름/기관명은 NER 필요(Presidio ko 모델·spaCy ko, 무거움 — TODO 명시). 미성년/guardian 및 법무 검토가 필요한 최종 서명 동의서·개인정보 처리방침·약관 evidence는 외부 게이트다. 공개 Google OAuth 실제 /turn proof는 별도 운영 게이트.

@@ -677,7 +677,7 @@
-
현재

apps/web/index.html에 canonical, description, Open Graph/Twitter Card, JSON-LD(WebApplication)를 추가했고, public/robots.txt, sitemap.xml, llms.txt로 공개 사이트와 AI 검색용 설명을 정리했다. 인증 내부 경로는 robots에서 차단한다. 학습자 회기 리뷰는 종료 후 POST /sessions/{id}/share로 공개 토큰을 만들고, GET /share/session/{token}이 서버 렌더 HTML/OG/JSON-LD를 반환한다. app.session_share_link에는 토큰 해시와 sanitized preview payload만 저장하며 원문 축어록·학습자 식별자는 저장하지 않는다.

검증

pytest app/test_session_share.py app/test_session_turn_persistence.py -q 21 passed, python -m pytest app/ -q 145 passed, python -m pytest engine_gateway/ -q 9 passed, npm run check:api-types, npm run typecheck, npm run build passed.

판정

공개 제품 페이지는 색인 가능, 회기 공유 페이지는 교수자 전달용 unfurl 카드라 noindex와 API robots Disallow: /share/를 유지한다. 실제 공개 도메인 unfurl 검증은 배포 후 1회 필요하다.

+
현재

apps/web/index.html에 canonical, description, Open Graph/Twitter Card, JSON-LD(WebApplication)를 추가했고, public/robots.txt, sitemap.xml, llms.txt로 공개 사이트와 AI 검색용 설명을 정리했다. 인증 내부 경로는 robots에서 차단한다. 학습자 회기 리뷰는 종료 후 POST /sessions/{id}/share로 공개 토큰을 만들고, GET /share/session/{token}이 서버 렌더 HTML/OG/JSON-LD를 반환한다. app.session_share_link에는 토큰 해시와 sanitized preview payload만 저장하며 원문 축어록·학습자 식별자는 저장하지 않는다.

검증

pytest app/test_session_share.py app/test_session_turn_persistence.py -q 21 passed, python -m pytest app/ -q 178 passed, python -m pytest engine_gateway/ -q 11 passed, npm run check:api-types, npm run typecheck, npm run build passed.

판정

공개 제품 페이지는 색인 가능, 회기 공유 페이지는 교수자 전달용 unfurl 카드라 noindex와 API robots Disallow: /share/를 유지한다. 실제 공개 도메인 unfurl 검증은 배포 후 1회 필요하다.

@@ -828,7 +828,7 @@ API typegen SSOTnpm run check:api-typesPassed; FastAPI OpenAPI → src/lib/api.gen.ts stale check Contract SSOT aggregate DTOnpm run typecheck / npm run build / session persistence / learner + session-review + teacher + layout gatePassed; learner sessions, session review/worksheet, teacher dashboard, session start/detail DTOs now use generated ApiSchema aliases with UI fallback. Stage responses are OpenAPI enum unions. Focused E2E 32 passed. .github/workflows/api-contract.yml now runs npm run check:api-types on API/Web contract changes. SEO/GEO share cardspytest app/test_session_share.py app/test_session_turn_persistence.py -q / npm run generate:api-types / npm run typecheck21 passed; session share creates hashed-token public unfurl payload without raw transcript, revoked token returns 404, OpenAPI generated share DTOs, review screen share button typechecks. Static robots.txt/sitemap.xml/llms.txt added. - Backend pytestpython -m pytest app/ -q145 passed + Backend pytestpython -m pytest app/ -q178 passed X2 evaluator model routingpython -m pytest app/test_evaluator_model_routing.py app/test_runtime_policy.py -q23 passed; fast/deep evaluator model override and blank-default routing covered C1 case worksheetpython -m pytest app/test_session_turn_persistence.py app/test_rbac_idor.py -q / npm run check:api-types / npm run typecheck / npm run build / local API smoke25 passed; session review exposes transcript-grounded caseWorksheet, learner-edited saved_by_learner worksheet persists through app.case_worksheet, and evaluator-only turns stay hidden. Local smoke returned saved_by_learner:local smoke saved worksheet. Stage labels are normalized at response boundaries. M3 auth claim mappingpython -m pytest app/test_auth_providers.py -q22 passed; Google/SAML cohort maps, provider external_id, provider error reason covered diff --git a/docs/guides/local-development.md b/docs/guides/local-development.md index 87adf6a..2084998 100644 --- a/docs/guides/local-development.md +++ b/docs/guides/local-development.md @@ -381,7 +381,7 @@ RAG 임베딩/리랭커 의존성은 기본 이미지에 설치하지 않는다. ```powershell # 백엔드 (apps/api) cd apps\api -python -m pytest app/ -q # 현재 145 pass +python -m pytest app/ -q # 현재 178 pass python -m pytest engine_gateway\ -q # 현재 11 pass # 웹 (apps/web) diff --git a/docs/guides/testing.md b/docs/guides/testing.md index ae8e2e5..f32e6aa 100644 --- a/docs/guides/testing.md +++ b/docs/guides/testing.md @@ -15,7 +15,7 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타 | 검증 | 작업 디렉터리 | 명령 | DB | API(8000) | 웹(5173) | 엔진GW(9099) | 브라우저 | 현재 통과 | |---|---|---|---|---|---|---|---|---| -| 백엔드 단위 테스트 | `apps/api` | `python -m pytest app/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 145 pass | +| 백엔드 단위 테스트 | `apps/api` | `python -m pytest app/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 178 pass | | 엔진 게이트웨이 테스트 | `apps/api` | `python -m pytest engine_gateway/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 11 pass | | API 타입 생성 체크 | `apps/web` | `npm run check:api-types` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass | | 웹 타입체크 | `apps/web` | `npm run typecheck` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass | @@ -42,15 +42,15 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타 ```sh # apps/api -python -m pytest app/ -q # 앱 단위 테스트 (현재 145 pass) +python -m pytest app/ -q # 앱 단위 테스트 (현재 178 pass) python -m pytest engine_gateway/ -q # 게이트웨이 단위 테스트 (현재 11 pass) ``` 수집만 빠르게 확인하려면: ```sh -python -m pytest app/ --collect-only -q # → "145 tests collected" -python -m pytest engine_gateway/ --collect-only -q # → "9 tests collected" +python -m pytest app/ --collect-only -q # → "178 tests collected" +python -m pytest engine_gateway/ --collect-only -q # → "11 tests collected" ``` > 참고: 실행 중 `PendingDeprecationWarning: Please use 'import python_multipart'` @@ -81,6 +81,32 @@ python -m pytest engine_gateway/ --collect-only -q # → "9 tests collected" --- +### 1.5 로컬 DB smoke — 저항엔진 openness 곡선 + +저항엔진은 단위 테스트와 별도로 실제 API 경로와 Postgres 저장 상태를 함께 확인할 수 있다. +이 smoke는 dev-login으로 학습자 세션을 만들고, P1 상담 2개에 공감 발화/조언점프 발화를 각각 +5턴씩 넣은 뒤 `app.session_state`, `app.turns`, `app.turn_client_state`를 직접 조회한다. + +사전 조건: + +- API가 DB 연결 상태로 떠 있어야 한다. +- `apps/api/.env` 또는 환경변수에 `DATABASE_URL`이 있어야 한다. +- API는 dev-login과 onboarding 저장이 가능한 dev 런타임이어야 한다. + +```sh +# repo root +python scripts/smoke-resistance-openness-db.py \ + --api-base-url http://127.0.0.1:8000 \ + --timeout 240 \ + --out docs/ops/resistance-openness-db-smoke-YYYY-MM-DD.json +``` + +통과 기준: + +- 공감 세션은 5턴 안에 `stage=탐색`으로 열리고 `effective_openness`가 0보다 커진다. +- 조언점프 세션은 `stage=라포`, `effective_openness=0.0`을 유지한다. +- DB의 `turn_seq`와 `app.turns` 저장 행 수가 API 턴 수와 일치한다. + ## 2. 웹 타입체크 / 빌드 ### 2.1 대상과 구성