R02 실제 버전 호환 검증 — 입력 없는 추가 저장을 막고 구서버 복구 제한을 안내 (2026-09-11)
- 기간: 2026-09-10 선행대기~2026-09-11 구현·검증, R02 1세션. 오너: “나한테 물어보지 말고 끝까지 완주하고”, 선행의 release/v0.18.0 병합 확인 뒤 진행.
- 랜딩: 앱 PR#1577, release/v0.18.0 merge
4fe99af0aa1df7882cb6007129933bba65ef4875, 2026-09-11 16:13:55 KST. 문서 PR#73. R04 공유 통계 수리 migration2개 포함, Edge 변경·Production 배포 없음. - 설계서: #1541 내부5Phase 계획.
- 정본: 실제 호환 판정과 R05 재현 명령, 실제 구배포93파일 SHA, 저장수리 후보140파일 SHA.
- 도구: 기존 numbered CASE/fixture, Chromium IDB, 실제 Postgres 경합 fixture·codec, 명시적배포 artifact 검증/수집. 임시데이터·trace·키는 repo밖 작업폴더에만 보관.
- 게이트: 각 변경 Phase check, 실제CASE039/040, 네 조합 CASE023, 실패7CASE 선택 재검증, 실제구서버undo·복원outbox 연결. 최종precheck/DB는10분30초에모두통과, Merge Check 성공·실제release조상확인. 선택검사·precheck를 Full CI로 보고하지 않는다.
- 버그리포트: BUG-122 무변경 추가 저장, BUG-123 구서버 되돌리기 미지원 안내. 실제 앱 병합 직후 같은 턴에 작성했다.
- 계약: 이 보고서가 새로운 승격 정책을 만들지 않는다. 기존 no-op/원문/receipt/owner 계약을 실행 증거와 연결하고 신규undo capability 부재를 정확히 표시한다.
Phase 현황
| Phase | 내용 | 상태 |
|---|---|---|
| Phase 1 | 선행 merge·구artifact·네조합 | 실제artifact 확보, 허용/실패조합 고정 |
| Phase 2 | IDB/mirror·업그레이드·재시작 | 기존브라우저23/23·추가4/4·실제구신공존2/2 |
| Phase 3 | 실제DB 경합·응답유실·restore | 기존21/21, 새브라우저연결 포함codec4/4·대표결함대조 |
| Phase 4 | owner/provider/SW·관측회귀 수리 | 경계47/47, 최초12CASE5pass7fail→실패7개수리후7/7 |
| Phase 5 | 미지원안내·최종게이트·R05 | 실제구서버안내1/1, 최종precheck·Merge Check통과·release반영·재현근거인계 |
1. 배경
R01 PR#1569가release/v0.18.0에 실제 병합된 849191b5를 기준으로 시작했다. 기존 테스트·저장 엔진의 복제본 대신 같은 사용자 여정과 oracle를 여러 실제 버전/저장 경계에 연결했다. 구앱은 태그 소스 재빌드가 아니라 원 Deploy run의 불변 URL에서 읽은 실제 배포 바이트다.
2. 문제 제기
완료 화면의 시각 선택기가 같은 시각을 초기화해 전달해도, 흐름이 이를 새 편집으로 판단해 operationId를 바꿨다. 변경 없이 “메인으로”를 눌러도 추가 논리 UPDATE가 생기고, 저장소 abort 후 재시도에서 불필요한 draft archive 경고가 발생했다. 서버의 새 논리저장별 revision 증가는 정상이며 문제는 클라이언트의 잘못된 의도 생성이었다.
구서버에 없는 undo RPC는 안전하게 거부했지만 안내가 일반 오류라 사용자가 기능 미지원인지 알 수 없었다. 일부 기존 CASE는 현행 device_persisted/held 표시 대신 구형 hook을 찾고, 공용 fixture는 이미 폐기된 R facade를 참조해 수집 단계에서 멈췄다.
3. 해결 방안
| 안 | 판단 |
|---|---|
| 실제 저장시각/메모 비교, raw snapshot·원 요청 보존 | 채택. UI 초기화와 실제 편집을 구분하면서 다음 사용자 의도를 보존 |
| 기대 revision 증가·오류 경고 무시 | 기각. 추가 mutation/불필요한 archive를 숨김 |
| 구서버 폐기API fallback·가짜 undo 성공 | 기각. 미지원 capability와 원문 보존 계약 위반 |
| 복구 RPC의 실제PGRST202만 미지원 표시 | 채택. 인증/네트워크/다른404와 구분, 확인/전송은 기존대로 차단 |
| IDB clear·강제 reload·시간/retry 증가 | 기각. 원문·순서·멱등성 증거를 훼손 |
4. 적용한 내용
Phase1~3에서 deployed artifact의 provenance/93파일hash 검증과 기존CASE 재사용 옵션, 실제 Chromium복원→PG→receipt 연결을 추가했다. 공용fixture와 활성28소비자는 현재 domain repository를 직접 사용한다. 폐기 facade는 복원하지 않았다.
Phase4는 mobileWorkoutFlow.ts에서 비교 대상만 실제 저장값으로 정규화했다. snapshot의UI메타/입력토큰과 이미 승인된payload는 그대로 보존하고, 이전 비교형식도 읽는다. 실제시간변경과 후속입력의 새 mutation/owner fence는 유지한다.041/043/044/048의 현행 표시 단언을 맞췄다.
Phase5는 복구 조회의PGRST202만 unsupported로 분류하고 모바일·데스크톱의 실제컴포넌트 안내를 확인했다. U06이 작성한 controller3fixture·#1478제외정책을 담당경계대로 소비했다. 이후 DB precheck준비에서 남아 있던 D09와드업 전용2SQL을 발견해 pgTAP시작 전 중단, 내용변경 없이 optional경로로 옮긴 새커밋에서 다시검증했다. 전용검사를 실행하거나 복귀시키지 않았다.
작업중 생성된 Playwright viewer가UTF8검사에 잡혀 결과폴더를 repo밖으로 옮겼다. Windows드라이브간 이동이sandbox junction을 따라 own추적파일까지 이동했지만 즉시HEAD로복구해 intended diff만 남겼다. 원격·사용자데이터 변경은 없었다. 복원검사 teardown의stats cron FK경합은 테스트정리의잠금순서로 해결했고, 별도통계DB결함 수리는HQ/R04경계를 유지했다.
필수 precheck를 막은 통계 교착은 HQ가 검증해 전달한 R04 제품 수리 646f71d6을 소비했다(ef0f378a). 정규화 관측을 private compute에 두고 원자적으로 게시하며 같은 transaction/lease/불변payload 검증만 재사용한다. 동일 public 행의 INSERT를 피하고 결과 저장 취소도 실패/backoff 경계에 넣는다. migration 20260914223000·20260914233000이 포함돼 서버 변경으로 검증한다. R03 9b3696cc의 fixture worker/cutover 잠금 수리도 83a93fef로 소비하며 양쪽 단언을 유지했다. 사용자 원본 데이터 수리와 장기 성능 전수 합격으로 확대하지 않는다.
5. 적용 결과
| 항목 | 전 → 후 / 제한 |
|---|---|
| 실제구배포 확보 | 없음 → Deploy34122817046/v0.17.1/93파일SHA |
| 구앱/구서버·구앱/신서버 | 미실측 → CASE023각2/2 |
| 신앱/신서버 | 미실측 → 수정빌드CASE0232/2 |
| 신앱/구서버 | 미실측 → 오류없는전체여정2/2실패. 초기canonical생성은통과, 신규API404 이후수정/재진입 미실행 |
| 동일시각picker | 새2회귀2실패 → 수정후기존포함13통과+이전형식재시작1통과 |
| 저장장애7CASE | 최초7실패 → 원래DB/receipt/오류게이트 유지7/7통과 |
| 구서버undo | 일반오류 → 명시적미지원/업데이트안내, 실제2context·apply/fallback0·storage변화0 |
| 실제복원응답유실 | 미연결 → commit후유실·재시작·독립context 동일receipt,apply1회·최신70kg보존 |
| Phase3/4/5 check | 3618/3621/3621통과, 각각0실패·92skip. skip은실행완료로세지않음 |
| 공유 통계 수리 소비 검증 | 기존660세션40P01 → 관련4파일42/42·동일660세션수렴ok=true. CRUD77/57/28ms·후속publish4871ms,6초예산유지·취소복구/원본보존 |
| 공유 fixture 후속 검증 | 다음precheck의D04/D11 두단언실패 → ba1914d4소비09c3802b의새DB두파일21/21·0skip(20433ms), 원래기대값·예산유지 |
| native/provider | 앱경계검증과실제설치·제공자전체인증을분리. 실제기기/외부provider 미검증 |
| 최종precheck·병합 | 최초40P01과다음D04/D11 두실패의원인수리후09c3802b/base607647ef에서전체통과(10분30초). static·unit3622/100skip·pgTAP121/2435·저장복원·순차·worker·660통과, PR1577 Merge Check성공·release4fe99af0반영 |
6. 이번 개선으로 향상된 것
완료 화면을 열었다 닫는 것과 실제 사용자의 편집을 구분해 불필요한 저장·보관 경고를 없앴다. 입력 토큰, 기존 요청, 후속 의도와 영수증은 기존 소유 경계에서 보존한다. 실제배포 바이트와 구서버를 재사용할 수 있어 후속담당자가 지원되지 않는조합을 임의통과로 표시할 이유가 줄었다.
남은 것
신앱을 구서버에 제공하는 전체여정은 허용불가다. 신규undo는 정확히거부/안내하며 서버기능을 복원하지 않았다. native실설치·실제외부provider인증과 최종staging/Production승격·배포는 이 작업에서 검증/승인하지 않는다. 네조합의 초기후보와 공유SQL수리 소비후 검증후보도 구분한다. R05에는 정확한판정·입력·재현명령을 전달한다.