docs: audit 1.0.5 playout package

This commit is contained in:
2026-07-12 19:47:03 +09:00
parent df60e09884
commit f5bf7daee4
5 changed files with 134 additions and 10 deletions

View File

@@ -36,11 +36,12 @@ Oracle/MariaDB 조회 계층과 Tornado/K3D 어댑터의 코드·계약·자동
## 최종 검증 기준선 (2026-07-12) ## 최종 검증 기준선 (2026-07-12)
- 현재 마이그레이션 소스에서 Core 1,377개, Infrastructure 173개, Playout 387개가 Debug/Release x64에서 각각 모두 통과했다. 구성별 1,937개, 두 구성 합계 3,874개이며 실패·skip은 0건이다. Web 구문 27개와 테스트 413/413, 원본 scene 기준선 35/35도 통과했다. - 현재 마이그레이션 소스에서 Core 1,383개, Infrastructure 173개, Playout 393개가 Debug/Release x64에서 각각 모두 통과했다. 구성별 1,949개, 두 구성 합계 3,898개이며 실패·skip은 0건이다. Web 구문 27개와 테스트 415/415, 원본 scene 기준선 35/35도 통과했다.
- 원본 `Cuts` 기준 active alias 45개의 `.t2s`는 missing/unsafe 0건이고 종속 asset 23개는 unsafe 0건, missing 14건이다. 누락은 `s5006` 큐브 배경 1개와 `s6001` 국가별 영상 13개다. 실제 Oracle 21c/MariaDB read-only 스모크는 `삼성` 검색과 필수 loader 33/33, 전체 query 58건을 통과했지만 DB→DTO→mutation 검증 범위다. - 원본 `Cuts` 기준 active alias 45개의 `.t2s`는 missing/unsafe 0건이고 종속 asset 23개는 unsafe 0건, missing 14건이다. 누락은 `s5006` 큐브 배경 1개와 `s6001` 국가별 영상 13개다. 실제 Oracle 21c/MariaDB read-only 스모크는 `삼성` 검색과 필수 loader 33/33, 전체 query 58건을 통과했지만 DB→DTO→mutation 검증 범위다.
- Visual Studio 2026 MSBuild `18.7.8.30822` clean source commit `af80c36` Release x64 signed MSIX를 빌드했다. `1.0.4.0` SHA-256은 `E8DB3C0E94963130548FAEF1880A9F9B99829064257F7196F41B7B8F0EE50B6C`이며, `CN=Comtrophy` 서명, 290개 패키지 항목, Web 33개 byte-for-byte 일치, 금지 자산·비밀값 0건을 확인했다. - clean source commit `df60e09`에서 Release x64 signed MSIX를 새로 빌드했다. `1.0.5.0` SHA-256은 `1B0BA713619CC3BD7CB3E03D78FD1EB1CEAF49E7D50F5C00DDFB483917BA5437`이며, `CN=Comtrophy` SignTool 검증, 290개 패키지 항목, Web 33개 byte-for-byte 일치, 금지 자산·비밀값 0건을 확인했다.
- 설치본 `Wickedness.MBNStockWebView_1.0.4.0_x64__qbv3jkvsn3aj0` `C:\Program Files\WindowsApps`의 실제 package context에서 실행다. 단일 인스턴스, 기본 해외 화면, 실제 `삼성` 검색 63건, 모든 10개 업무 탭을 거친 뒤 검색 상태·31개 컷 유지, 비교 8쌍 영속성을 확인했다. 상태는 `DryRunReady`, Oracle/MariaDB `Healthy`였고 playout command·`OutcomeUnknown`은 0건이다. 상세 증거는 [1.0.4 패키지 감사](docs/RELEASE_1_0_4_AUDIT.md)에 있다. - 설치본 `Wickedness.MBNStockWebView_1.0.5.0_x64__qbv3jkvsn3aj0` `C:\Program Files\WindowsApps`의 실제 package context에서 실행다. 실제 `삼성전자` 검색`1열판기본_현재가` 5001 구성, PREPARE → TAKE IN → 자동 refresh 정확히 1회 → `CAPPED · 1/1` → 3.5초 무변화 → TAKE OUT/IDLE을 DryRun에서 확인했다. Oracle/MariaDB는 2/2 정상이고 KTAP 시도·NEXT·DB write·`OutcomeUnknown`은 0건이다. 상세 증거는 [1.0.5 패키지 감사](docs/RELEASE_1_0_5_AUDIT.md)에 있다.
- 실제 Tornado2 검증은 고정 계획 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19``MBNWEB-20260711-H` 한 회차로 제한했다. PGM에서 `5001``5074` page 1/page 2를 확인한 뒤 TAKE OUT의 검은 화면을 확인했다. Network Monitoring의 정확한 합계는 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`, retry `0`이며 최종 `OutcomeUnknown = false`다. - 실제 Tornado2 검증은 고정 계획 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19``MBNWEB-20260711-H` 한 회차로 제한했다. PGM에서 `5001``5074` page 1/page 2를 확인한 뒤 TAKE OUT의 검은 화면을 확인했다. Network Monitoring의 정확한 합계는 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`, retry `0`이며 최종 `OutcomeUnknown = false`다.
- 이후 Round I는 자동 refresh 최대 1회를 넘어 9회가 실행되어 `FAIL` 처리했다. 1.0.5의 native cap은 package-context DryRun을 통과했지만 실제 Tornado 재검증 전이므로 Round I 승인이나 Round H 패키지 증거를 새 패키지에 재사용하지 않는다.
- 실제 Tornado 증거는 승인된 `5001`/`5074`에만 적용한다. 나머지를 포함한 35개 builder, 45개 active alias, 5·6·12행 PageN 경계와 마지막 페이지는 자동 매트릭스 테스트로 검증했다. `s5025`는 Git/MSIX 밖의 승인된 trusted CP949 입력 파일이 있어야 하는 운영 전제조건을 유지한다. - 실제 Tornado 증거는 승인된 `5001`/`5074`에만 적용한다. 나머지를 포함한 35개 builder, 45개 active alias, 5·6·12행 PageN 경계와 마지막 페이지는 자동 매트릭스 테스트로 검증했다. `s5025`는 Git/MSIX 밖의 승인된 trusted CP949 입력 파일이 있어야 하는 운영 전제조건을 유지한다.
## Visual Studio 2026에서 실행 ## Visual Studio 2026에서 실행

View File

@@ -278,11 +278,11 @@
| 항목 | 결과 | | 항목 | 결과 |
|---|---| |---|---|
| 자동 테스트 | Core 1,377개, Infrastructure 173개, Playout 387개가 Debug/Release x64에서 각각 통과했고 Web workflow·bridge 413/413도 통과했다. 412 action의 폐쇄형 매트릭스, 계약·경계·복원 실패와 native fail-closed gate를 검증한다. | | 자동 테스트 | Core 1,383개, Infrastructure 173개, Playout 393개가 Debug/Release x64에서 각각 통과했고 Web workflow·bridge 415/415도 통과했다. 412 action의 폐쇄형 매트릭스, 계약·경계·복원 실패와 native fail-closed gate를 검증한다. |
| 실제 운영 DB write | **미실행.** GraphE, named playlist, ThemeA, EList의 mutation executor는 fake/계약 테스트로 검증했으며 운영 DB에는 쓰지 않았다. FSell/VI는 테스트용 격리 저장소만 사용했다. | | 실제 운영 DB write | **미실행.** GraphE, named playlist, ThemeA, EList의 mutation executor는 fake/계약 테스트로 검증했으며 운영 DB에는 쓰지 않았다. FSell/VI는 테스트용 격리 저장소만 사용했다. |
| 실제 Tornado2 PGM | 제한된 승인 회차에서 `5001`, `5074` page 1·2, TAKE OUT을 확인했다. 이는 전체 412 action, GraphE, FSell, VI, ThemeA, EList, 이름 있는 playlist 각각의 UI 동등성 검증이 아니다. | | 실제 Tornado2 PGM | 제한된 승인 회차에서 `5001`, `5074` page 1·2, TAKE OUT을 확인했다. 이는 전체 412 action, GraphE, FSell, VI, ThemeA, EList, 이름 있는 playlist 각각의 UI 동등성 검증이 아니다. |
| PList legacy 복원 | 실제 `DC_TITLE`/`LIST_TEXT` 2,213행의 한국어·7필드 무손상과 typed persistence 일치를 확인했다. 기본 `selectionMapped=1,581`/차단 632와 별도 GraphE 22/14를 합친 결과는 1,603/610이다. selection 매핑은 scene data·asset·PREPARE·PGM 완료 증거가 아니다. | | PList legacy 복원 | 실제 `DC_TITLE`/`LIST_TEXT` 2,213행의 한국어·7필드 무손상과 typed persistence 일치를 확인했다. 기본 `selectionMapped=1,581`/차단 632와 별도 GraphE 22/14를 합친 결과는 1,603/610이다. selection 매핑은 scene data·asset·PREPARE·PGM 완료 증거가 아니다. |
| manual named save | 현재 legacy PList manual 36행은 모두 GraphE이며 fresh proof로 22행을 복원하고 저장값 무효 9행·identity 중복 5행을 차단했다. FSell/VI PList행은 0건이고 production source read는 FSell 3×5행, VI 9항목·2 page로 전후 불변이다. 실제 Oracle save→reload와 PGM은 미검증이다. | | manual named save | 현재 legacy PList manual 36행은 모두 GraphE이며 fresh proof로 22행을 복원하고 저장값 무효 9행·identity 중복 5행을 차단했다. FSell/VI PList행은 0건이고 production source read는 FSell 3×5행, VI 9항목·2 page로 전후 불변이다. 실제 Oracle save→reload와 PGM은 미검증이다. |
| ThemeA/EList identity | expected identity·상관 응답 계약은 구현했다. 실제 운영 DB의 KRX/NXT·동명이름·코드 경계와 정확한 선택 행 replace/delete는 미검증이다. | | ThemeA/EList identity | expected identity·상관 응답 계약은 구현했다. 실제 운영 DB의 KRX/NXT·동명이름·코드 경계와 정확한 선택 행 replace/delete는 미검증이다. |
| legacy file import | `종목비교.dat`는 signed package에서 8쌍 1회 실행·재시작 marker까지 확인했다. FSell·VI importer는 strict parser, source/hash 재검증, durable intent/marker와 격리 fixture를 통과했으며 현재 운영 profile은 기존 동일 파일 때문에 no-overwrite 차단된다. | | legacy file import | `종목비교.dat`는 signed package에서 8쌍 1회 실행·재시작 marker까지 확인했다. FSell·VI importer는 strict parser, source/hash 재검증, durable intent/marker와 격리 fixture를 통과했으며 현재 운영 profile은 기존 동일 파일 때문에 no-overwrite 차단된다. |
| 남은 실환경 검증 | 다섯 전용 화면의 Web 연결과 signed `1.0.4.0` Release MSIX package-context 실행은 화면/계약 검증 범위에서 확인됐다. package UI에서 실제 종목 검색·10개 업무 탭 상태 유지·비교 8쌍 영속성을 확인했다. 실제 입력→운영 DB write→재조회와 각 전용 scene PGM 검증은 별도 승인·테스트 데이터·rollback 회차에서만 수행한다. | | 남은 실환경 검증 | 다섯 전용 화면의 Web 연결과 signed `1.0.5.0` Release MSIX package-context 실행은 화면/계약 검증 범위에서 확인됐다. 1.0.5 package UI에서 실제 삼성전자 검색·현재가 5001 DryRun과 자동 refresh cap을 확인했으며, 기존 10개 업무 탭 상태·비교 8쌍 영속성 증거는 1.0.4 감사에 보존한다. 실제 입력→운영 DB write→재조회와 각 전용 scene PGM 검증은 별도 승인·테스트 데이터·rollback 회차에서만 수행한다. |

View File

@@ -7,9 +7,9 @@
| 항목 | 상태 | | 항목 | 상태 |
|---|---| |---|---|
| 기본 모드 | `DryRun`; COM 객체와 `KTAPConnect`를 만들지 않음 | | 기본 모드 | `DryRun`; COM 객체와 `KTAPConnect`를 만들지 않음 |
| 자동 테스트 | 최종 전체 재검증에서 Core Debug/Release x64 각각 1,377/1,377, Playout 각각 387/387, Infrastructure 각각 173/173(합계 각 1,937/1,937), Web 413/413 통과; 실패·skip 0건 | | 자동 테스트 | 최종 전체 재검증에서 Core Debug/Release x64 각각 1,383/1,383, Playout 각각 393/393, Infrastructure 각각 173/173(합계 각 1,949/1,949), Web 415/415 통과; 실패·skip 0건 |
| Visual Studio 2026 | MSBuild `18.7.8.30822` Debug x64와 signed Release x64 패키지 빌드 성공 | | Visual Studio 2026 | MSBuild `18.7.8.30822` Debug x64와 signed Release x64 패키지 빌드 성공 |
| trusted Release x64 MSIX | clean commit `af80c36`에서 `1.0.4.0` 생성·`CN=Comtrophy` 서명/SignTool 검증·x64 update 설치·package context 실행 성공. SHA-256 `E8DB3C0E94963130548FAEF1880A9F9B99829064257F7196F41B7B8F0EE50B6C`; 290개 항목, source Web 33개 byte 일치, 금지 자산 0건. 단일 인스턴스, 실제 종목 검색·업무 탭 상태·비교 8쌍, `DryRunReady`, Oracle/MariaDB `Healthy` 확인 | | trusted Release x64 MSIX | clean commit `df60e09`에서 `1.0.5.0` 생성·`CN=Comtrophy` 서명/SignTool 검증·x64 update 설치·package context 실행 성공. SHA-256 `1B0BA713619CC3BD7CB3E03D78FD1EB1CEAF49E7D50F5C00DDFB483917BA5437`; 290개 항목, source Web 33개 byte 일치, 금지 자산 0건. 실제 삼성전자 현재가 5001 DryRun에서 자동 refresh 1회 뒤 `CAPPED 1/1`, 3.5초 무변화, TAKE OUT/IDLE, Oracle/MariaDB `Healthy`, KTAP 미호출을 확인 |
| 실제 DB read→DTO→mutation smoke | 34개 도달 가능 data route 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic과 NXT restore audit를 포함한 Oracle/MariaDB query 58건 통과. 종속 asset·운영 DB-W·PGM 검증은 포함하지 않음 | | 실제 DB read→DTO→mutation smoke | 34개 도달 가능 data route 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic과 NXT restore audit를 포함한 Oracle/MariaDB query 58건 통과. 종속 asset·운영 DB-W·PGM 검증은 포함하지 않음 |
| `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight | | `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight |
| `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 | | `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 |
@@ -24,6 +24,11 @@ in-place update했다. remove/reset 없이 비교 8쌍과 one-time marker가 유
확인했다. 로그는 `DryRunReady`와 DB Healthy만 기록했으며 playout command는 0건이다. 확인했다. 로그는 `DryRunReady`와 DB Healthy만 기록했으며 playout command는 0건이다.
상세 내용은 [`RELEASE_1_0_4_AUDIT.md`](RELEASE_1_0_4_AUDIT.md)에 있다. 상세 내용은 [`RELEASE_1_0_4_AUDIT.md`](RELEASE_1_0_4_AUDIT.md)에 있다.
1.0.4에서 1.0.5로도 정상 종료 뒤 같은 package family에 in-place update했다.
새 signed package에서 trusted 자동 refresh 상한 1을 package-context DryRun으로
검증하고 정상 종료 뒤 임시 local config와 모든 playout 환경 override를 제거했다.
상세 내용은 [`RELEASE_1_0_5_AUDIT.md`](RELEASE_1_0_5_AUDIT.md)에 있다.
과거 고정 `5001 → 5006` runner의 실제 PGM 기록은 연결과 기본 K3D 명령 표면의 증거다. 현재 WebView playlist, fresh TAKE IN, Page NEXT, timer refresh, callback/unload의 동등성 완료 증거는 아니다. 과거 고정 `5001 → 5006` runner의 실제 PGM 기록은 연결과 기본 K3D 명령 표면의 증거다. 현재 WebView playlist, fresh TAKE IN, Page NEXT, timer refresh, callback/unload의 동등성 완료 증거는 아니다.
2026-07-11의 승인 회차 `MBNWEB-20260711-A`에서는 현재 MSIX WebView runtime으로 `CONNECT → PREPARE 5001/page 1`까지 성공했다. Network Monitoring에 `HELLO`, `LOAD_SCENE`, `BEGIN_TRANSACTION`, 데이터 mutation, `QUERY_VARIABLES`, `END_TRANSACTION`, `SCENE_PREPARE`의 request/success가 기록됐고 PREPARE 동안 PGM은 검은 화면이었다. TAKE IN은 두 번째 K3D Prepare/Play 전에 수행하는 fresh Oracle 조회에서 `DATABASE_UNAVAILABLE`로 명확히 실패했다. `PLAY`가 없고 PGM도 검은 상태임을 확인해 TAKE IN을 반복하지 않았으며, 승인 범위의 `TAKE OUT All` 한 번으로 `STOPAL → UNLOAD_SCENE 5001` 성공을 확인하고 `BYE` 뒤 앱을 정상 종료했다. 직후 probe는 Oracle unhealthy/MariaDB healthy와 정상 DNS/TCP 도달을 보였고, 회차 종료 뒤 전체 55-query 스모크는 두 DB 모두 다시 통과했다. 이 회차는 실패·복구 증거이며 동등성 완료 증거가 아니다. 새 package/계획 SHA-256과 새 Gate A/B로 처음부터 다시 시작한다. 2026-07-11의 승인 회차 `MBNWEB-20260711-A`에서는 현재 MSIX WebView runtime으로 `CONNECT → PREPARE 5001/page 1`까지 성공했다. Network Monitoring에 `HELLO`, `LOAD_SCENE`, `BEGIN_TRANSACTION`, 데이터 mutation, `QUERY_VARIABLES`, `END_TRANSACTION`, `SCENE_PREPARE`의 request/success가 기록됐고 PREPARE 동안 PGM은 검은 화면이었다. TAKE IN은 두 번째 K3D Prepare/Play 전에 수행하는 fresh Oracle 조회에서 `DATABASE_UNAVAILABLE`로 명확히 실패했다. `PLAY`가 없고 PGM도 검은 상태임을 확인해 TAKE IN을 반복하지 않았으며, 승인 범위의 `TAKE OUT All` 한 번으로 `STOPAL → UNLOAD_SCENE 5001` 성공을 확인하고 `BYE` 뒤 앱을 정상 종료했다. 직후 probe는 Oracle unhealthy/MariaDB healthy와 정상 DNS/TCP 도달을 보였고, 회차 종료 뒤 전체 55-query 스모크는 두 DB 모두 다시 통과했다. 이 회차는 실패·복구 증거이며 동등성 완료 증거가 아니다. 새 package/계획 SHA-256과 새 Gate A/B로 처음부터 다시 시작한다.
@@ -73,6 +78,16 @@ Round H 전에 Core 790, Infrastructure 65, Playout 374개 테스트를 Debug/Re
Round I `MBNWEB-20260712-I`는 계획 SHA-256 `D221841A15593A987FB944648F0ACE0AC5940936AEE16C74DC9B901A2F45B332`로 CONNECT 1회와 PREPARE 5001/page 1, TAKE IN 1회를 실행했다. 5001 삼성전자 PGM 표시는 확인했지만, 실시간 관찰 자동화가 TAKE OUT까지 하나의 중단 없는 작업으로 묶이지 않아 승인된 자동 refresh 최대 1회를 넘어 9회가 실행됐다. 최종 누적 PLAY/`OnScenePlayed`는 각각 10회(초기 TAKE IN 1 + refresh 9)였다. NEXT와 다른 scene LOAD는 없었고 FAILURE/ERROR는 0이었다. 승인된 TAKE OUT 1회로 STOPALL/UNLOAD 5001 각 1회 성공, PGM black, BYE request 1, 앱 정상 종료를 확인했다. 회차 결과는 `FAIL`, `OutcomeUnknown=false`, vendor command retry 0이며 결과 SHA-256은 `E5FD13E7FCDF87B6ADCFB696EFF2E957B70ECA821A424FC15EE41043CFA0E37E`이다. Round I `MBNWEB-20260712-I`는 계획 SHA-256 `D221841A15593A987FB944648F0ACE0AC5940936AEE16C74DC9B901A2F45B332`로 CONNECT 1회와 PREPARE 5001/page 1, TAKE IN 1회를 실행했다. 5001 삼성전자 PGM 표시는 확인했지만, 실시간 관찰 자동화가 TAKE OUT까지 하나의 중단 없는 작업으로 묶이지 않아 승인된 자동 refresh 최대 1회를 넘어 9회가 실행됐다. 최종 누적 PLAY/`OnScenePlayed`는 각각 10회(초기 TAKE IN 1 + refresh 9)였다. NEXT와 다른 scene LOAD는 없었고 FAILURE/ERROR는 0이었다. 승인된 TAKE OUT 1회로 STOPALL/UNLOAD 5001 각 1회 성공, PGM black, BYE request 1, 앱 정상 종료를 확인했다. 회차 결과는 `FAIL`, `OutcomeUnknown=false`, vendor command retry 0이며 결과 SHA-256은 `E5FD13E7FCDF87B6ADCFB696EFF2E957B70ECA821A424FC15EE41043CFA0E37E`이다.
로컬 결과 파일은 `artifacts\pgm-evidence\MBNWEB-20260712-I\round-result.json`이고,
적용한 Live 설정 SHA-256은
`BE282B9AF0AC5D8C243234D70587497ADACC7A47ED85C1865ED595949FC8759F`다.
운영 증거 원본은 Git 제외 대상이므로 Gitea에서는 결과 hash만으로 파일을 재취득할
수 없다. 또한 Round I 계획은 자동 refresh 1회를 허용하면서 일부 예상 native
range에는 그 추가 PREPARE/PLAY를 반영하지 않은 불일치가 있었다. 새 계획은 Gate A
뒤 누적 PREPARE 1/PLAY 0, Gate B cap 도달 뒤 누적 PREPARE 3/PLAY 2/
`OnScenePlayed` 2를 명시해야 한다. 종료 직전 native snapshot이 별도 파일로
남지 않은 점도 Round I의 증거 제한으로 보존한다.
이 실패 뒤 `maximumAutomaticRefreshesPerTakeIn` trusted JSON-only 상한을 추가했다. 기본 `null`은 원본 연속 갱신을 유지하고, 실제 검증 설정의 `1`은 scheduler와 실제 refresh dispatch 경계에서 두 번째 실행을 이중 차단한다. 상태는 `refreshCompletedCount`, `refreshMaximumCount`, `refreshLimitReached`를 제공하며, 마지막 refresh `OnScenePlayed`가 drain되기 전에는 count가 상한에 도달해도 `refreshLimitReached=false`를 유지한다. 검증은 `completed=1`, `maximum=1`, `limitReached=true`, `refreshActive=false`, `playCompletionPending=false`를 모두 확인해야 한다. 변경된 package는 Round I 승인/계획을 재사용할 수 없으며 새 package hash, 새 회차 계획과 새 CONNECT/PREPARE/TAKE IN 승인이 필요하다. 이 실패 뒤 `maximumAutomaticRefreshesPerTakeIn` trusted JSON-only 상한을 추가했다. 기본 `null`은 원본 연속 갱신을 유지하고, 실제 검증 설정의 `1`은 scheduler와 실제 refresh dispatch 경계에서 두 번째 실행을 이중 차단한다. 상태는 `refreshCompletedCount`, `refreshMaximumCount`, `refreshLimitReached`를 제공하며, 마지막 refresh `OnScenePlayed`가 drain되기 전에는 count가 상한에 도달해도 `refreshLimitReached=false`를 유지한다. 검증은 `completed=1`, `maximum=1`, `limitReached=true`, `refreshActive=false`, `playCompletionPending=false`를 모두 확인해야 한다. 변경된 package는 Round I 승인/계획을 재사용할 수 없으며 새 package hash, 새 회차 계획과 새 CONNECT/PREPARE/TAKE IN 승인이 필요하다.
이 실제 Live PGM 증거는 회차에 허용된 5001과 5074에 한정된다. 35개 scene builder 전체 동등성은 자동 테스트, 55-query 실데이터 smoke와 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md) 매트릭스로 유지하며, 나머지 scene이 실제 PGM에서 각각 송출됐다는 의미로 기록하지 않는다. 이 실제 Live PGM 증거는 회차에 허용된 5001과 5074에 한정된다. 35개 scene builder 전체 동등성은 자동 테스트, 55-query 실데이터 smoke와 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md) 매트릭스로 유지하며, 나머지 scene이 실제 PGM에서 각각 송출됐다는 의미로 기록하지 않는다.

108
docs/RELEASE_1_0_5_AUDIT.md Normal file
View File

@@ -0,0 +1,108 @@
# 1.0.5 Release x64 MSIX 감사
기준일: 2026-07-12
패키지 소스 커밋: `df60e09884acac2e9cb47d50ba902fa13cf7e154`
## 변경 목적
Round I `MBNWEB-20260712-I`에서 승인된 자동 refresh 최대 1회를 넘어 9회가
실행된 회귀를 차단하기 위해 trusted JSON-only
`maximumAutomaticRefreshesPerTakeIn` 상한을 추가했다. 유한 상한에서는 두 번째
refresh를 scheduler와 실제 dispatch 경계에서 모두 차단하고, 마지막
`OnScenePlayed`가 drain된 뒤에만 `refreshLimitReached=true``CAPPED`
보고한다. callback timeout·취소·구세대 상태는 fail-closed이며 자동 재시도하지
않는다.
## 빌드와 자동 검증
- Core 1,383, Infrastructure 173, Playout 393 테스트가 Debug/Release x64에서
각각 모두 통과했다. 구성별 1,949개, 두 구성 합계 3,898개이며 실패·skip은
0건이다.
- Web 구문 27개, Web 테스트 415/415, scene catalog 35, reachable preset 34,
원본 scene 기준선 35/35가 통과했다.
- 실제 Oracle/MariaDB SELECT-only smoke는 query 58건과 필수 scene loader
33/33을 통과했다. `writesAttempted=false`이며 운영 DB write는 수행하지 않았다.
- Release x64 앱과 MSIX 생성은 경고 0, 오류 0으로 끝났다.
## 서명 패키지
| 항목 | 결과 |
|---|---|
| identity | `Wickedness.MBNStockWebView` |
| 버전·아키텍처 | `1.0.5.0`, x64 |
| package family | `Wickedness.MBNStockWebView_qbv3jkvsn3aj0` |
| 설치본 | `Wickedness.MBNStockWebView_1.0.5.0_x64__qbv3jkvsn3aj0` |
| SHA-256 | `1B0BA713619CC3BD7CB3E03D78FD1EB1CEAF49E7D50F5C00DDFB483917BA5437` |
| 크기 | 48,472,530 bytes |
| 서명 | `CN=Comtrophy`, SignTool `/pa` 검증 성공, warning/error 0 |
| 내용 | 290개 항목, source Web 33개 byte-for-byte 일치 |
| 제외 검사 | vendor/K3D/Tornado DLL, 인증서·개인 키, Cuts, `.t2s`, `.vrv`, 운영 local config 0건 |
서명에는 timestamp가 없으므로 이 파일을 인증서 만료 뒤 장기 유효 서명으로
간주하지 않는다. MSIX는 `.gitignore` 대상이며 로컬 경로는
`AppPackages\MBN_STOCK_WEBVIEW_1.0.5.0_x64_Test\MBN_STOCK_WEBVIEW_1.0.5.0_x64.msix`다.
## 설치 package-context DryRun
1.0.4를 정상 종료한 뒤 같은 package family의 1.0.5로 in-place update했으며
app-data reset이나 강제 종료를 사용하지 않았다. 설치된 WindowsApps 실행 파일은
`C:\Program Files\WindowsApps\Wickedness.MBNStockWebView_1.0.5.0_x64__qbv3jkvsn3aj0\MBN_STOCK_WEBVIEW.exe`였다.
임시 trusted 설정을 `DryRun`, `maximumAutomaticRefreshesPerTakeIn=1`로 고정하고
실제 종목 검색에서 `삼성전자`를 선택해 `1열판기본_현재가` 5001 한 건을
구성했다. 다음 상태 전이가 모두 통과했다.
1. 시작: `IDLE`, `completed=0`, `maximum=1`, `limitReached=false`,
`connected=false`, `ktapConnectAttempted=false`
2. PREPARE: 5001/page 1, builder `s5001`, 실제 DB mutation preview 생성
3. TAKE IN 뒤 정확히 한 번 refresh: `PROGRAM`, `completed=1`, `maximum=1`,
`limitReached=true`, `refreshActive=false`, `playCompletionPending=false`,
화면 `CAPPED · 1/1`
4. 3.5초 추가 대기: count와 `refreshLastSuccessAt`가 변하지 않아 두 번째
dispatch가 없음을 확인
5. TAKE OUT: `IDLE`, `completed=0`, `maximum=1`, `limitReached=false`,
`OutcomeUnknown=false`
전 과정에서 Oracle/MariaDB는 2/2 정상이고 COM/KTAPConnect는 호출되지 않았다.
NEXT와 DB write도 실행하지 않았다. preliminary DryRun에서 현재 시점의
`1열판기본_예상체결가`는 DB row-count precondition이 맞지 않아
`SCENE_DATA_INVALID`로 명확히 거부됐다. native 상태는 IDLE이었고 KTAP 호출은
없었다. 이 컷은 이번 1.0.5 성공 범위로 계산하지 않으며 별도 데이터 시점
검증이 필요하다.
로컬 증거 해시는 다음과 같다. 파일은 운영 정보 보존 정책에 따라 Git에 넣지
않는다.
| 증거 | SHA-256 |
|---|---|
| 초기 native/package 상태 | `154A87ACA8D46132CE06538013BC0DA4E08AB27FE6D92B38F42E3B881EE262EE` |
| 삼성전자·현재가 5001 구성 | `73064F13D4ECF89DF6549FEA348AA350CB13011A10BE47C34A7BC9DC4168E60A` |
| PREPARED 5001/page 1 | `1DA53B5E9E33D8CE820BBDA87D6B8E0897ACAED6DE28F73AD0599EDC42F45C5B` |
| TAKE IN 단일 발행 | `B35D9E664983E7D232952EF699A0C9D0D12A8CE3D604DACA6E847E1B4BA9D74C` |
| CAPPED 1/1 및 3.5초 안정성 | `1C34FF5780F8F75E52C02C064D776D7E6E8321116C448E13805C77565D8D6547` |
| CAPPED 화면 | `35F7D7BA67417C4595D5F6F2306CC5EC4BEE0EAEA719D5165CA59BFEC7BAAD70` |
| TAKE OUT 단일 발행 | `BC6186648FB09B1C4A4210D5853AF3FE39E0A2FE2C68E6EE8A0629FCAF500648` |
| 최종 IDLE | `5F5C16853048BD269A29BA9BA045CF6BC47C88623ADFA4548FC99A8947E3DFB5` |
검증 뒤 ContentDialog의 `종료`를 명시적으로 눌러 정상 종료했고 앱 프로세스와
CDP listener가 모두 0임을 확인했다. 임시 playout local config를 삭제했으며
process/user/machine 범위 `MBN_STOCK_PLAYOUT_*`도 모두 0이다. 1.0.5 signed
설치본은 `Status=Ok`로 유지한다.
## Round I 실패 증거와 다음 회차
Round I의 결과는 계속 `FAIL`이다. 로컬 증거는
`artifacts\pgm-evidence\MBNWEB-20260712-I\round-result.json`, SHA-256은
`E5FD13E7FCDF87B6ADCFB696EFF2E957B70ECA821A424FC15EE41043CFA0E37E`다.
적용했던 Live 설정의 SHA-256은
`BE282B9AF0AC5D8C243234D70587497ADACC7A47ED85C1865ED595949FC8759F`다.
Round I 계획에는 자동 refresh 1회가 허용됐지만 일부 예상 native range가 이를
반영하지 못한 불일치도 있었다. 새 회차는 cumulative PREPARE 3회와 PLAY/
`OnScenePlayed` 2회를 명시하고, 새 package hash와 cap=1 설정 hash를 함께
고정해야 한다.
1.0.5 DryRun 통과는 실제 Tornado callback/PGM 검증을 대신하지 않는다. 새
계획 SHA-256에 대한 Gate A 승인 전에는 CONNECT/PREPARE를 보내지 않고, 같은
회차의 Gate B 승인 전에는 TAKE IN을 보내지 않는다. 결과 불명확 상태에서는
어떤 명령도 반복하지 않는다.

View File

@@ -11,12 +11,12 @@
| 원본 inventory와 hash 기준선 | 완료 | 35/35 builder, 원본 기준선 스크립트 35/35 | | 원본 inventory와 hash 기준선 | 완료 | 35/35 builder, 원본 기준선 스크립트 35/35 |
| DTO와 mutation builder | 완료 | registry가 정확히 35개 builder를 발견하고 catalog와 1:1 대조 | | DTO와 mutation builder | 완료 | registry가 정확히 35개 builder를 발견하고 catalog와 1:1 대조 |
| loader와 runtime route | 완료 | MainForm 도달 가능 builder 34개, active alias 45개를 fail-closed route로 등록; `s8086`은 원본과 같이 무alias 진단 전용 | | loader와 runtime route | 완료 | MainForm 도달 가능 builder 34개, active alias 45개를 fail-closed route로 등록; `s8086`은 원본과 같이 무alias 진단 전용 |
| 자동 테스트 | 완료 | Core 1,377/1,377, Playout 387/387, Infrastructure 173/173이 Debug/Release x64에서 각각 통과했다. 구성별 1,937개, 두 구성 합계 3,874개이며 실패·skip은 0건이다. Web 413/413와 원본 baseline 35/35도 통과 | | 자동 테스트 | 완료 | Core 1,383/1,383, Playout 393/393, Infrastructure 173/173이 Debug/Release x64에서 각각 통과했다. 구성별 1,949개, 두 구성 합계 3,898개이며 실패·skip은 0건이다. Web 415/415와 원본 baseline 35/35도 통과 |
| Visual Studio 2026 빌드 | 완료 | MSBuild `18.7.8.30822`로 Debug x64와 signed Release x64 앱 패키지 빌드 성공 | | Visual Studio 2026 빌드 | 완료 | MSBuild `18.7.8.30822`로 Debug x64와 signed Release x64 앱 패키지 빌드 성공 |
| Release x64 MSIX | 완료 | clean commit `af80c36``1.0.4.0` 서명·설치·내용 감사와 package-context 실행 통과. SHA-256 `E8DB3C0E94963130548FAEF1880A9F9B99829064257F7196F41B7B8F0EE50B6C`; 290개 항목, Web 33개 source 일치, 금지 자산 0건, 단일 인스턴스와 정상 update를 확인. 기본 상태는 `DryRunReady`, Oracle/MariaDB `Healthy` | | Release x64 MSIX | 완료 | clean commit `df60e09``1.0.5.0` 서명·설치·내용 감사와 package-context 실행 통과. SHA-256 `1B0BA713619CC3BD7CB3E03D78FD1EB1CEAF49E7D50F5C00DDFB483917BA5437`; 290개 항목, Web 33개 source 일치, 금지 자산 0건. 기본 상태는 `DryRunReady`, Oracle/MariaDB `Healthy`; 삼성전자 현재가 5001 자동 refresh cap 1과 TAKE OUT/IDLE을 확인 |
| 실제 DB read→DTO→mutation smoke | 완료 | 34개 도달 가능 builder의 data route 통과: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일. 무alias `s8086` diagnostic과 NXT restore audit를 포함한 실제 Oracle/MariaDB query 58건이 성공했다. 종속 asset 또는 PGM 준비 상태는 이 행의 범위가 아니다. | | 실제 DB read→DTO→mutation smoke | 완료 | 34개 도달 가능 builder의 data route 통과: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일. 무alias `s8086` diagnostic과 NXT restore audit를 포함한 실제 Oracle/MariaDB query 58건이 성공했다. 종속 asset 또는 PGM 준비 상태는 이 행의 범위가 아니다. |
| 종속 asset preflight | **외부자산 필요 / 검사 보강 적용 중** | 승인 Cuts에서 `s5006``Video\큐브배경.vrv``s6001` 해외지수용 국가별 영상 13개가 없다. 현재 작업 트리에는 45 alias와 builder 소유 자산 23개의 누락·빈 파일·root 탈출·reparse 검사가 반영돼 있지만 최종 전체 회귀·패키지 반영 전에는 완료로 올리지 않는다. | | 종속 asset preflight | **외부자산 필요 / 검사 보강 적용 중** | 승인 Cuts에서 `s5006``Video\큐브배경.vrv``s6001` 해외지수용 국가별 영상 13개가 없다. 현재 작업 트리에는 45 alias와 builder 소유 자산 23개의 누락·빈 파일·root 탈출·reparse 검사가 반영돼 있지만 최종 전체 회귀·패키지 반영 전에는 완료로 올리지 않는다. |
| 이번 마이그레이션의 실제 Tornado2/PGM | **승인 범위 완료** | 계획 SHA-256 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19``MBNWEB-20260711-H`에서 `5001 → 자동 refresh 1회 → 5074 page 1 → page 2 → TAKE OUT`을 PGM과 Network Monitoring으로 함께 확인. 최종 검은 화면, retry 0, `OutcomeUnknown = false` | | 이번 마이그레이션의 실제 Tornado2/PGM | **이전 승인 범위 완료 / 1.0.5 재검증 대기** | 계획 SHA-256 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19`Round H는 5001/5074에 통과했지만 Round I는 refresh 상한 초과로 실패했다. 새 1.0.5 package의 cap은 DryRun만 통과했으며 실제 PGM은 새 계획·Gate A/B 승인 뒤 다시 검증해야 한다. |
Round H의 실제 Network Monitoring 합계는 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`이다. PGM은 5001 데이터, 5074의 page 1과 page 2를 순서대로 렌더링했고 TAKE OUT 뒤 검은 화면이 됐다. 이 증거는 승인된 두 scene에만 유효하다. 과거 실패 회차와 고정 runner는 장애 복구·기본 연결 근거로 보존하되 Round H의 동등성 근거를 대신하거나 확장하지 않는다. Round H의 실제 Network Monitoring 합계는 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`이다. PGM은 5001 데이터, 5074의 page 1과 page 2를 순서대로 렌더링했고 TAKE OUT 뒤 검은 화면이 됐다. 이 증거는 승인된 두 scene에만 유효하다. 과거 실패 회차와 고정 runner는 장애 복구·기본 연결 근거로 보존하되 Round H의 동등성 근거를 대신하거나 확장하지 않는다.