-
-
diff --git a/apps/web/src/pages/login/login.css b/apps/web/src/pages/login/login.css
index 8924182..501cae3 100644
--- a/apps/web/src/pages/login/login.css
+++ b/apps/web/src/pages/login/login.css
@@ -221,14 +221,6 @@
border-color: var(--accent);
}
-.lg-obtn.secondary {
- color: var(--text-strong);
-}
-
-.lg-obtn.secondary:hover {
- border-color: color-mix(in srgb, var(--accent) 42%, var(--glass-inset-border));
-}
-
.lg-obtn:disabled {
cursor: not-allowed;
opacity: 1;
@@ -261,10 +253,6 @@
color: var(--accent-deep);
}
-.lg-obtn.secondary .ic {
- background: var(--bg-surface-2);
-}
-
.lg-obtn .txt {
min-width: 0;
display: flex;
diff --git a/docs/TODO.md b/docs/TODO.md
index d10c890..03b8007 100644
--- a/docs/TODO.md
+++ b/docs/TODO.md
@@ -21,7 +21,7 @@
| C-001 | **OPEN · 외부 GATE** | v2 P1 합성 사례 6건·상태별 canonical 판정기와 109·수단 상세 차단·런타임/carry-over/output `ideation_stage <= 3`·4개 공식 source 기술 사전검증은 완료. 사례별 5필드 30개, 청소년 답변 6개, 검토자·소속·자격·검토일·결정 근거·서면 증거/해시·검토 버전/사례 해시를 포함한 승인 10필드가 있어야 닫는다. 현재 `review_complete=false`; F절/B4에서 추적한다. |
| C-002 | **DONE · 내부 기술** | 첫 회기 라포 반영·한 초점 열린 질문 체크리스트, 근거 turn 연결, 이후 회기 not-applicable |
| C-003 | **DONE · 내부 기술** | 종료 회기 4건 미만 insufficient, 이후 최다 페르소나 비중 0.75 이상 훈련 집중 주의; 임상·공정성 판정 아님 |
-| REQ-001 | **DONE · 내부 기술** | provider가 이메일을 검증한 모든 Google 계정은 도메인·사전등록 없이 learner·approved로 즉시 로그인. 관리자 exact-email 연구참여자 사전등록 create는 pending 고정, 승인은 별도 PATCH |
+| REQ-001 | **DONE · 내부 기술 · 공개 UI 미승격** | provider가 이메일을 검증한 모든 Google 계정은 도메인·사전등록 없이 learner·approved로 즉시 로그인. 로그인은 단일 `Google 계정으로 로그인` CTA이며 Google 계정 선택기(`prompt=select_account`)를 유지하고 `hd`를 보내지 않는다. 관리자 exact-email 연구참여자 사전등록 create는 pending 고정, 승인은 별도 PATCH. 로컬 desktop/mobile 직접 영향 32/32, 인증 시각·경계폭 2/2, 전체 7폭 15/15, 세션 8/8, API auth 41/41을 통과했으며 단일 CTA 번들은 아직 공개 미배포다. |
| REQ-002 | **DONE · 내부 기술** | admin protocol draft→active→retired, 라이선스 C/D 외부 LLM 금지, evaluator-only RAG·rollback; migration 17 owner-run/readiness-only |
| REQ-003 | **DONE · 내부 기술** | 페르소나 주호소가 JSON 키 순서나 surface 상태보다 우선 |
| REQ-004 | **DONE · 내부 기술** | learner 현재 설정 AND 세션 snapshot. OFF는 AI 파생 API 403/UI 무요청·혼합 결과 redaction, 사용자 입력·privacy 보존; teacher/admin 유지 |
diff --git a/docs/dev_dashboard.html b/docs/dev_dashboard.html
index b61a4f0..8be6acf 100644
--- a/docs/dev_dashboard.html
+++ b/docs/dev_dashboard.html
@@ -695,6 +695,7 @@
212차 핫픽스(2026-08-18 오후): 공개 POST /sessions/{id}/end 503(소유자 실사용 보고)의 원인은 회기 종료의 pinned_fact upsert가 learner 역할 연결로 실행된 것이었다. app.pinned_fact RLS는 learner에 INSERT(소유 케이스)만 허용하고 SELECT/UPDATE는 AI 컨텍스트·admin/instructor 전용이라 SELECT … FOR UPDATE + INSERT … ON CONFLICT DO UPDATE 조합이 충돌 후보 가시성에서 InsufficientPrivilegeError로 실패하고 fallback 차단이 503으로 노출됐다. 공개 DB 롤백 재현으로 단순 INSERT는 통과·ON CONFLICT 조합은 거부·ai_view=evaluator 컨텍스트는 전체 upsert 통과를 실증했고(bf5f7352), pinned_fact 저장만 같은 learner uid의 AI evaluator 뷰 연결로 분리했다. 검증: 관련 62 passed·app 924 passed, 공개 8001 승격 후 health ok. 엔진이 건강해 deep 평가가 처음 팩트를 반환한 순간 발화한 잠복 결함으로, 아침 degraded 구간엔 팩트가 비어 이 경로가 실행되지 않았다.
213차 복구·전환(2026-08-18 심야): 대청소 사건(node_modules·구 런타임 워크트리·Temp 소실)과 Docker Desktop 사망·whisper 9882 WinNAT 포트 예약·DHCP LAN IP 회수(223→224)가 연쇄 발생했다. 릴레이를 현행 루트 bf5f7352에 같은 4종 핀으로 재기동(r3 영수증)하고 192.168.0.224:9100으로 바인딩(방화벽 규칙 재발행), NAS는 실행 컨테이너 env 전량을 .env(0600)로 재구성해 ENGINE_URL 224 적용 후 api만 재생성했다. 클로드 예산 한도(Reached maximum budget $0.5)가 재발해 NAS ENGINE_MODE를 agy_cli(gemini)로 전환 — 공개는 소유자가 이미 관리자 UI로 agy 전환 완료. 결과: NAS origin health 3/3 status=ok·db·engine true, auth 401, OpenAPI 126, actual-origin 실회기 turn→review smoke 통과(agy 턴 2개→종료 200→리뷰 200) — 2026-08-12 이후 처음으로 201차 current GREEN 조건을 모두 충족했다. 회기 종료 503 핫픽스(bf5f7352)도 소유자 실세션 종료 성공으로 운영 검증. 권고: 공유기 DHCP 예약(호스트 MAC), Docker VM 클럭 동기화(호스트 대비 ~4일 선행 — DB 타임스탬프 오염), NAS 로컬 agy 이전. 증거는 docs/ops/evidence/nas-relay-recovery-2026-08-18.json이다.
214차 개선관리 워크북 동기화(2026-08-27): C-002·C-003과 REQ-001~008은 내부 기술 구현 DONE이다. 첫 회기 체크리스트와 종료 회기 기반 훈련 노출 지표를 추가했고, 외부 연구참여자 사전등록은 create에서 pending 고정 뒤 별도 PATCH 승인으로 분리했다. 프로토콜 레지스트리는 draft→active→retired, 라이선스 C/D의 외부 LLM 금지, evaluator-only RAG 색인·rollback을 강제하며 migration 17은 owner-run이고 startup은 readiness-only라 runtime DDL을 하지 않는다. 주호소는 surface보다 우선하고, 새 회기는 persona_id/version을 고정한다. 학습자 AI 피드백은 현재 계정 설정 AND 세션 snapshot일 때만 노출하며 OFF에서는 순수 파생 API 403·기존 share 404·혼합 응답 AI 필드 redaction·UI 파생 endpoint별 요청 0회를 적용한다. 축어록·저장 워크시트·outcome/calibration 입력·multimodal 동의/철회/삭제/raw audio/privacy 원장은 보존하고 alliance는 self-scores-only로 보여주며, privacy 삭제 조작면은 44px 이상·가로 overflow 0을 유지한다. teacher/admin 감독 뷰는 유지한다. 옛 회기 평가 실패는 degraded 리뷰로 남아도 새 회기를 막지 않는다. 헬스는 기본 엔진과 live-client를 함께 확인하고 구조화 done 없는 EOF는 client_stream_incomplete다. 상담자/내담자 이름은 prompt와 구조화 결과에서 [COUNSELOR]/[CLIENT]로 역할 마스킹한다. C-001은 내부 안전 사전검증만 완료했으며 임상 검토자 이름·소속 기관·검토일·서면 결정이 없어 외부 GATE로 계속 연다.
+
216차 REQ-001 로그인 단순화(2026-08-29): 실제로 같은 startOAuth를 호출하던 학교용·다른 계정용 중복 버튼을 단일 Google 계정으로 로그인 CTA로 통합했다. 보조문구는 모든 Google 계정이며 Google authorize의 prompt=select_account는 남겨 공유 기기에서도 계정을 고를 수 있게 하고 특정 Workspace 도메인을 강제하는 hd는 보내지 않는다. Google이 검증한 이메일은 도메인·사전등록 제약 없이 즉시 승인되는 기존 서버 계약을 유지한다. 검증: auth API 41 passed, 직접 영향 desktop/mobile 32 passed, 인증 시각·경계폭 2 passed, 7폭 전체 레이아웃 15 passed, 세션 무회귀 8 passed, typecheck·lint·build 통과. 이 단일 CTA 번들은 아직 공개 미배포라 현재 공개 Pages의 기존 2버튼 DOM을 새 증거로 대체하지 않는다.
래스터만 사용이미지 생성 도구 산출물은 PNG 기반 시안이다. SVG·벡터·와이어프레임·로고 시트로 해석하지 않는다.
기능 우선메인 라우트의 실제 액션과 정보 구조를 먼저 반영한다. 장식은 기능을 가리지 않는 수준에서만 쓴다.
diff --git a/docs/ops/e2e-full-sweep-2026-07-27.md b/docs/ops/e2e-full-sweep-2026-07-27.md
index 8b20eca..acceb0c 100644
--- a/docs/ops/e2e-full-sweep-2026-07-27.md
+++ b/docs/ops/e2e-full-sweep-2026-07-27.md
@@ -57,8 +57,8 @@
## 1. 인증·온보딩 (auth)
- [x] `auth-login-config-load` 로그인 설정 조회 (OAuth 구성/허용 도메인) — `GET /auth/config`로 OAuth 구성·dev 로그인 가능 여부·허용 도메인을 받아 버튼 활성/라벨/배지를 결정한다 · 검증: 기존(부분) e2e/auth.spec.ts + 탐색 순회 · 탐색 GREEN(2026-07-27 실순회)
-- [x] `auth-login-school-google-button` 학교 Google 계정으로 계속 버튼 (primary) — 클릭 시 `/auth/login?provider=google&next=`로 이동해 Google OAuth를 시작하고 oauthReady가 아니면 비활성화된다 · 검증: 기존(부분) e2e/auth.spec.ts + 탐색 순회 · 탐색 GREEN(2026-07-27 실브라우저 순회)
-- [x] `auth-login-generic-google-button` Google 계정으로 계속 버튼 (secondary) — primary와 동일한 startOAuth를 호출하며 서브라벨에 두 번째 허용 도메인을 표시한다 · 검증: 신규 spec 필요
+- [x] `auth-login-google-button` 단일 Google 계정으로 로그인 버튼 — 클릭 시 `/auth/login?provider=google&next=`로 이동하고, 보조문구는 `모든 Google 계정`이다. Google authorize는 `prompt=select_account`를 유지하고 `hd`를 보내지 않으며 oauthReady가 아니면 비활성화된다 · 검증: 2026-08-29 desktop/mobile 직접 영향 32/32 + auth API 41/41
+- [x] `auth-login-generic-google-button` 중복 secondary 제거 — primary와 같은 `startOAuth`를 호출하던 `다른 Google 계정 선택` 버튼을 제거하고 계정 전환은 Google 계정 선택기가 담당한다 · 검증: 2026-08-29 단일 CTA count·옛 버튼 0건 desktop/mobile GREEN
- [x] `auth-login-oauth-status-notice` OAuth 비활성 사유 status 안내 — oauthReady가 아닐 때 role=status로 설정 확인 중/미연결/로컬 테스트 계정 사유를 아이콘과 함께 표시한다 · 검증: 기존 e2e/auth.spec.ts
- [x] `auth-login-oauth-error-notice` OAuth 콜백 오류 메시지 (?oauth= 쿼리) — 쿼리 사유별(not_configured·domain_not_allowed·access_denied 등) 한국어 안내문과 원본 코드를 표시한다 · 검증: 기존 e2e/auth.spec.ts
- [x] `auth-login-dev-role-radiogroup` 로컬 테스트 역할 선택 라디오그룹 (학습자/교수자/관리자) — DEV이고 dev_login_enabled일 때만 노출되며 세 역할 버튼으로 dev 로그인 역할을 고른다 · 검증: 기존(부분) e2e/auth.spec.ts + 탐색 순회 · 탐색 GREEN(2026-07-27 실순회)
@@ -94,8 +94,7 @@
**의심 결함(에이전트 리포트)**:
- `auth-login-config-load`: config 로드 실패 시 별도 오류 배너 없이 버튼이 영구 비활성 상태로만 남고, statusMessage는 '연결되지 않았습니다' 문구라서 네트워크 오류와 미설정을 구분해 주지 않는다.
-- `auth-login-school-google-button`: '학교 Google 계정' 버튼과 일반 'Google 계정' 버튼이 완전히 동일한 provider=google 흐름을 호출한다(학교 SSO/SAML 별도 흐름 없음). 또한 startOAuth 내부의 !oauthReady 오류 세팅 분기는 버튼이 이미 disabled라 실제로 도달 불가한 사문(死文) 코드다.
-- `auth-login-generic-google-button`: 두 버튼이 기능적으로 중복이라 사용자가 다른 인증 경로로 오해할 수 있다.
+- `auth-login-school-google-button`·`auth-login-generic-google-button`: 2026-08-29 두 버튼이 같은 provider=google 흐름을 호출하던 중복을 단일 CTA로 해소했다. 계정 선택은 `prompt=select_account`로 유지한다. 공개 Pages 번들은 아직 승격 전이라 로컬 증거와 공개 상태를 구분한다.
- `auth-login-oauth-error-notice`: 오류 문단에 role=alert/aria-live가 없어 스크린리더에 즉시 공지되지 않는다.
- `auth-login-dev-role-radiogroup`: role=radio 버튼 그룹이지만 방향키 이동 등 라디오그룹 키보드 시맨틱은 구현되어 있지 않다(Tab으로만 이동).
- `auth-login-dev-enter-button`: 실패 시 err.message를 그대로 노출하는데 ApiError 메시지가 'API 500: ...' 같은 원문이라 사용자 친화적이지 않을 수 있다.
diff --git a/docs/ops/evidence/c-001-clinical-technical-preflight-2026-08-28.json b/docs/ops/evidence/c-001-clinical-technical-preflight-2026-08-28.json
index 25242d1..435d138 100644
--- a/docs/ops/evidence/c-001-clinical-technical-preflight-2026-08-28.json
+++ b/docs/ops/evidence/c-001-clinical-technical-preflight-2026-08-28.json
@@ -91,7 +91,7 @@
},
{
"path": "outputs/01a04217-f73b-7303-b597-401fa7f5d290/Vignette_개선관리_완료.xlsx",
- "sha256": "478fd8612843d6a9c60288934f7992c5cad115d2a3b064a3da4e2a4e9f07b7e2"
+ "sha256": "b334e313c64b530b3525bb9253fef17282df361224d408f3e67a526af0ef55aa"
}
],
"verification": [
@@ -113,7 +113,7 @@
},
{
"command": "artifact-tool workbook rebuild, inspect, formula error scan, six-sheet render",
- "result": "formula errors 0; summary complete=10, review=1, total=11; ten independent external approval inputs G13:G22; canonical gate pending-valid; PACKAGE_MATCH and WORKTREE_DRIFT 0/8; C-001 review_complete=false; six rendered sheets plus focused C-001 sections visually inspected; workbook sha256=478fd8612843d6a9c60288934f7992c5cad115d2a3b064a3da4e2a4e9f07b7e2"
+ "result": "formula errors 0; summary complete=10, review=1, total=11; ten independent external approval inputs G13:G22; canonical gate pending-valid; PACKAGE_MATCH and WORKTREE_DRIFT 0/8; C-001 review_complete=false; six rendered sheets plus focused C-001 sections visually inspected; workbook sha256=b334e313c64b530b3525bb9253fef17282df361224d408f3e67a526af0ef55aa"
}
]
}
diff --git a/docs/ops/pilot-usage-guide-draft.md b/docs/ops/pilot-usage-guide-draft.md
index f5c071f..7fdf56f 100644
--- a/docs/ops/pilot-usage-guide-draft.md
+++ b/docs/ops/pilot-usage-guide-draft.md
@@ -11,11 +11,8 @@
## 1. 접속과 로그인
1. 안내받은 주소로 접속합니다(파일럿 도메인 — 연구팀 공지).
-2. **Google 계정으로 로그인**합니다. 참가자 명단에 등록된 이메일(학교/승인 도메인)로 로그인하세요.
-3. 처음 로그인하면 **"승인 대기"** 화면이 나올 수 있습니다.
- - 운영자가 수업·연구 참여 범위를 확인하는 동안 화면이 열리지 않습니다.
- - 승인되면 화면의 **"승인 상태 새로고침"** 버튼을 누르거나 다시 접속하면 온보딩으로 넘어갑니다.
- - 반나절 이상 승인이 안 되면 아래 §6 연락 채널로 이메일을 알려주세요.
+2. **Google 계정으로 로그인** 버튼을 누르고 사용할 Google 계정을 선택합니다. Google이 이메일을 확인한 계정이면 학교·회사·개인 Gmail 등 도메인과 사전등록 여부에 관계없이 로그인할 수 있습니다.
+3. 처음 로그인하면 온보딩으로 이동합니다. 연구참여자 사전등록과 별도 운영 승인은 Google 로그인 가능 여부를 제한하지 않습니다.
## 2. 온보딩과 동의