Skip to content

QA2 검증 범위 보강 2차 — 미배정 공개 경계 172개 배정 (2026-09-15)

  • 기간: 2026-09-15 (세션 1개, 1차에 이어서). 오너 지시 원문 "미배정 경계 172개도 같은 방식으로 2차 보강 진행해줘". 선행 원칙 "QA1의 레거시를 절대 QA2까지 끌고와서는 안됨"(같은 날).
  • 랜딩: QA2 main 096eb5a (PR #5, 커밋 8개 = Phase 1~8) · 앱 qa2.lock.json 갱신은 앱 PR #1626 → 큐 병합 eee3aac1 (release/v0.19.3; staging·Production 미반영). 마이그레이션·Edge 변경 없음.
  • 설계서: QA2#4 본문과 Phase 완료 댓글 8건.
  • 정본: QA2 승격 게이트(09-15 보강 2차 절), QA2 저장소 docs/verification.md(QA2#4 결과 절)·docs/database.md(시나리오 요약)·catalog.mjs(의무-경계 대응 정본).
  • 도구: QA2 scenarios/database/의 신규 시나리오 22개, scenarios/database/catalog.mjs·catalog.mjs의 의무·outOfScope 갱신. 새 도구는 없음(1차의 커버리지·판정·보고 위에서 진행).
  • 게이트: QA2 npm run check 101/101 · 앱 main 157bf12b 전체 실행 71개 중 70 통과(1 실패 = 제품 결함 [Barbelic#1624], releaseEligible false) · 앱 precheck(static·unit-1 2107·unit-2 1778 통과) · 큐 Merge Check 통과. 원격 Full CI는 미실행(지시 범위 밖; 다음 승격 PR에서 처음 실행).
  • 버그리포트: 새로 작성 없음. 유일한 실패는 이미 접수된 앱 이슈 Barbelic#1624(차단당한 계정 삭제 불가). 수리 PR이 병합되면 그때 bug-report/를 작성한다.
  • 계약: QA2 카탈로그의 surfaces·outOfScope(사유 포함)·retired, 판정의 coverage.

Phase 현황

Phase내용상태
Phase 1표 격리(앱 권한 표 전수 열거), 소셜 참조가 있는 계정 삭제06918f6
Phase 2계획 수명주기·가시성8fe45d9
Phase 3그룹 멤버십·보드·라운지·멤버 세션9aae76e
Phase 4팔로우 게이트·세션 상호작용·알림3bb60e2
Phase 5조회 정합성(홈·달력·로그 표·볼륨·기록·리포트·세션 상세·검색)7541330
Phase 6프로필·카탈로그·기록·신체·초안·사진 문80597a5
Phase 7통계 갱신 권한·무결성 검증기·예약 유지보수8f47ba8
Phase 8전체 실행·QA2 게시·앱 락 반영·문서✅ QA2 096eb5a · 앱 PR #1626 → eee3aac1

1. 배경

1차(QA2#2)에서 공개 경계 커버리지라는 분모가 생겼다. 검증 대상 DB에서 로그인 사용자가 부를 수 있는 RPC 문, 앱 계정에 권한이 있는 표, 설치된 예약 작업을 실행 시점에 열거하고, 의무가 선언한 경계(surfaces)와 대조해 의무 있음 / 범위 밖(이유) / 미배정을 보여 준다. 1차 종료 시점 앱 main 기준 공개 경계 208개 중 의무 있음 11·범위 밖 25로, 172개가 미배정으로 남아 있었다. 미배정은 통과가 아니라 아직 약속이 없는 경계다.

2. 문제 제기

미배정 172개(RPC 118·표 47·예약 작업 7)는 QA2가 아직 아무 약속도 검증하지 않는 제품 표면이다. 오너 지시는 이 172개를 "같은 방식으로" — QA1의 케이스·헬퍼·러너·장부를 옮기지 않고, 기록된 제품 실패와 접근 계약의 의미만 QA2의 단위(약속·의무·requiredInputs·대상 지문·교정)로 — 배정하는 것이다.

3. 해결 방안

  • 원칙(오너 결정): QA1 레거시 무이관. 시나리오는 계약(friend-access·app-role-privileges·user-fact-immutability)과 기록된 버그의 의미에서만 기대값을 authoring하고, 조회는 조회끼리 비교하지 않고 저장한 사실의 독립 산술과 대조한다.
  • 접근: 표면 종류별로 의무를 나눠 8개 Phase로 진행하고, 각 Phase는 개발 DB에서 통과·npm run check·커밋·보고를 마친 뒤 다음으로 넘어간다. 마지막에 앱 main 전체 실행 1회로 커버리지 0 미배정과 판정을 확인한다.

4. 적용한 내용

  • Phase 1~4 — 삭제·격리, 계획, 그룹, 소셜: 표 격리는 앱 권한 표를 실행 시점에 전수 열거해 본인 행만 보이는지, 전역 참조 표는 읽기 전용인지 검사한다. 계정 삭제는 팔로우·차단·초대·댓글·좋아요·그룹 관계가 있어도 되고 상대 원본은 그대로여야 한다 — 이 중 "남이 나를 차단한 경우"가 제품에서 실패했고 [Barbelic#1624]로 접수했다. 계획·그룹·소셜은 각 문의 권한(작성자·주인·멤버·팔로워)과 차단·비회원 거부를 검사한다.
  • Phase 5 — 조회 정합성: 한 가상 사용자의 2024년 7월 3회 운동을 저장하고, 손으로 계산한 일별·월별·종목별 수치(일 1220/210/625, 월 8세트·44회·2055, 종목 A 최고 무게 70·5회 기록 60→62.5)와 홈·달력·로그 표·볼륨·기록·리포트·세션 상세·검색을 대조한다.
  • Phase 6 — 프로필·카탈로그·기록·초안·사진: 종목 카탈로그와 커스텀 켜고 끄기, 즐겨찾기 교체, 직접 입력 기록(1RM·최대 반복·버티기·거리), 신체 측정·인바디 가져오기, 온보딩·동의·핸들·성별·설정, 클라이언트 오류 진단, 운동 초안(순서 펜스·복구 영수증), 세션 사진(폴더·객체·피드 게이트), 원본 변경 이력 조회.
  • Phase 7 — 통계·유지보수: 통계 갱신 문은 본인만, 무결성 검증기는 저장 사실 재계산, 예약 유지보수 5종은 특권 전용·유저 원본 불변. 통계 투영 claim 작업은 db-wide-statistics에 편입, pg_cron 실행 로그 정리는 인프라 하우스키핑으로 범위 밖.
  • Phase 8 — 앱 main 157bf12b 전체 실행, QA2 [PR #5] 병합, 앱 락 [PR #1626] → 큐 병합, 문서.

5. 적용 결과

항목전 (1차 종료)후 (2차)
공개 경계 미배정1720
배정(claimed) / 범위 밖11 / 25163 / 45
의무 수3855
시나리오 수5471
앱 main 전체 실행43/43 통과 · releaseEligible true70/71 통과 · releaseEligible false
  • releaseEligible이 false로 내려간 이유는 QA2가 제품 결함 [Barbelic#1624]를 잡았기 때문이다. 제품을 초록으로 만들려 의무를 완화하지 않았다(원본 불변 원칙과 "제품 실패는 실패로 남긴다"). #1624이 고쳐지기 전까지 release/v0.19.3 → staging 승격은 이 판정에 막힌다.
  • 사람 눈으로만 판단할 품질(화면 감각 등)은 이 자동 검증의 대상이 아니다. 통계 워커 문·검증기 일부의 session_user 기반 회원 거부는 하네스 한계로 재현하지 못했다(아래 남은 것).

6. 이번 개선으로 향상된 것

  • QA2가 검증하는 공개 경계가 11개에서 163개로 늘고 미배정이 0이 됐다. 이제 앱의 회원용 문·표·예약 작업 대부분에 "무엇을 약속하는가"가 QA2 단위로 적혀 있고, 판정이 그 약속 위반을 잡는다.
  • 조회 화면이 저장한 사실과 어긋나는 회귀(과거 여러 버그의 유형)를 독립 산술로 잡는다.
  • 커버리지가 0 미배정이므로, 앞으로 새 문·표·예약 작업이 추가되면 인벤토리에 나타나 즉시 미배정으로 보이고 약속을 요구한다.

후속 (2026-09-15, 같은 날)

  • 제품 결함 [Barbelic#1624] — 앱 트랙이 release/v0.19.3 4c4a847e(PR #1632)로 수리, 버그 리포트 bug-report/bug-148-20260915.md. QA2 096eb5a 전체 실행으로 확인: 71개 중 70 통과·실패 0·미검증 1(db-wide-1000 60초 한도 초과 — 로컬 부하, 부하 없이 54.4초 통과). 차단당한 계정 삭제 의무 통과.
  • 하네스 후속 — QA2 PR #6(05332518): 배우 작업을 이미지의 비특권 로그인 authenticator의 두 번째 연결에서 실행하고, 로그인이 특권이면 미검증으로 거부. 회원 거부 검사 5개 복원(워커 일괄 문 2·검증기 3, 모두 42501). 앱 4c4a847e 전체 실행 71/71 통과(releaseEligible true, 미배정 0/208, 시나리오 실행 2분 46초, 2026-09-15 05:58Z). 앱 락 갱신 PR #1635 → 큐 병합 79026980(release/v0.19.3). 상세는 승격 게이트의 후속 절.

남은 것

  • 없음(승격 ① release→staging의 GitHub Full CI에서 QA2 판정 게이트가 처음 실행된다).