feat: make LegacyParityApp playout live-only

This commit is contained in:
2026-07-28 14:52:59 +09:00
parent 11d3849933
commit ea96a08ad5
23 changed files with 456 additions and 270 deletions

View File

@@ -9,11 +9,11 @@
## 안전 기준
기본 모드는 `DryRun`입니다. `DryRun`은 COM 객체를 만들거나 Tornado 출력에 명령을 보내지 않고 WebView 메시지, 큐, 상태 및 오류 표시 흐름만 검증합니다. 현재 방송 PROGRAM(PGM)에 연결된 Tornado 프로세스는 항상 **안전하지 않은 대상**으로 취급합니다. 프로세스 이름이나 실행 여부만으로 테스트 대상이라고 판단하지 않습니다.
지정 개발 PC의 기본 모드는 보호된 `Live`입니다. 승인 파일·K3D 해시·scene/path allowlist 같은 불변식 검증에 실패하면 Live 엔진 기동을 차단하며 비송출 모드로 폴백하지 않습니다. K3D/PGM/DB가 일시적으로 준비되지 않은 경우에는 Live 엔진을 `Disconnected` 또는 `Faulted`로 유지합니다. 현재 방송 PROGRAM(PGM)에 연결된 Tornado 프로세스는 항상 **안전하지 않은 대상**으로 취급합니다. 프로세스 이름이나 실행 여부만으로 테스트 대상이라고 판단하지 않습니다.
운영/방송 대상의 작업과 자동 검증은 실제 PGM 출력 또는 라이브 `TAKE IN`을 자동 허가하지 않습니다. `Test` 검증은 PGM과 분리된 전용 테스트 인스턴스, 테스트 출력 채널 및 허용 목록에 든 테스트 씬을 모두 확인한 뒤에만 수행합니다. 단, 위에 링크한 현재 개발 PC의 상시 권한 범위에서는 별도의 회차별 허가를 다시 요청하지 않습니다.
이 문서의 adapter·builder·DryRun 완료 표현은 화면/계약 구현 범위다. 운영 DB-W, 외부 asset readiness, 기존 데이터 복원과 장면별 실제 PGM은 별도 증거가 있어야 한다. 현재 미적용·적용 중·외부자산 필요 항목은 [`LEGACY_FEATURE_AUDIT.md`](LEGACY_FEATURE_AUDIT.md)를 따른다.
이 문서의 과거 adapter·builder·DryRun 완료 표현은 당시 화면/계약 구현 기록이다. 운영 DB-W, 외부 asset readiness, 기존 데이터 복원과 장면별 실제 PGM은 별도 증거가 있어야 한다. 현재 미적용·적용 중·외부자산 필요 항목은 [`LEGACY_FEATURE_AUDIT.md`](LEGACY_FEATURE_AUDIT.md)를 따른다.
## 확인된 x64 COM 등록
@@ -93,9 +93,9 @@ SDK가 기본 위치에 없다면 x64 SDK의 `TlbImp.exe` 절대 경로를 `-Tlb
%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\Config\runtime-folders.local.json
```
[playout.example.json](../Config/playout.example.json)을 `playout.local.json`의 구조 참고용으로 사용합니다. 예시는 `DryRun`, 출력 채널 미지정, 빈 씬 허용 목록, 라이브 신뢰 플래그 해제 상태이므로 실제 출력에 사용할 수 없습니다. `runtime-folders.local.json`은 좌측 `설정` 메뉴에서 네이티브 폴더 선택 창으로 지정한 디자인(`Cuts`), 설정(`Res`), 운영 배경 폴더와 왼쪽 메뉴 시작 상태를 앱이 자동 저장하는 파일이므로 직접 편집하지 않습니다. 폴더 변경은 앱을 다시 시작한 뒤 자산·카탈로그에 적용되며, 메뉴 펼침 상태는 즉시 적용됩니다.
[playout.example.json](../Config/playout.example.json)을 `playout.local.json`의 구조 참고용으로 사용합니다. 예시는 `Live` 형식이지만 출력 채널 미지정, 빈 씬 허용 목록, 라이브 신뢰 플래그 해제 상태이므로 실제 출력에 사용할 수 없습니다. 실제 개발 PC 설정은 보호된 초기화 스크립트로만 생성합니다. `runtime-folders.local.json`은 좌측 `설정` 메뉴에서 네이티브 폴더 선택 창으로 지정한 디자인(`Cuts`), 설정(`Res`), 운영 배경 폴더와 왼쪽 메뉴 시작 상태를 앱이 자동 저장하는 파일이므로 직접 편집하지 않습니다. 폴더 변경은 앱을 다시 시작한 뒤 자산·카탈로그에 적용되며, 메뉴 펼침 상태는 즉시 적용됩니다.
송출 장면 루트는 환경 변수, 사용자 설정 메뉴, `playout.local.json`, 실행 파일 옆 기본 `Cuts` 순으로 우선합니다. 운영 배경 루트도 환경 변수, 사용자 설정 메뉴, `playout.local.json` 순으로 우선하며 모두 비어 있으면 최종 장면 루트의 sibling `배경` 폴더를 사용합니다. 사용자 설정 메뉴가 덮어쓰는 송출 값은 이 두 자산 루트뿐입니다. Release/default `DryRun`, KTAP 호스트·포트·채널, Test/Live 게이트, allowlist와 벤더 해시는 이 화면에서 편집할 수 없고 기존 검사를 그대로 통과해야 합니다. 별도 씬 루트나 보호 설정을 명시할 때는 테스트 장비의 호스트, 채널, 창 제목 패턴과 허용할 씬 이름을 로컬 파일에만 기록하고 Git, 로그 또는 지원 첨부파일에 넣지 않습니다.
송출 장면 루트는 환경 변수, 사용자 설정 메뉴, `playout.local.json`, 실행 파일 옆 기본 `Cuts` 순으로 우선합니다. 운영 배경 루트도 환경 변수, 사용자 설정 메뉴, `playout.local.json` 순으로 우선하며 모두 비어 있으면 최종 장면 루트의 sibling `배경` 폴더를 사용합니다. 사용자 설정 메뉴가 덮어쓰는 송출 값은 이 두 자산 루트뿐입니다. 보호된 `Live` 모드, KTAP 호스트·포트·채널, Test/Live 게이트, allowlist와 벤더 해시는 이 화면에서 편집할 수 없고 기존 검사를 그대로 통과해야 합니다. 별도 씬 루트나 보호 설정을 명시할 때는 테스트 장비의 호스트, 채널, 창 제목 패턴과 허용할 씬 이름을 로컬 파일에만 기록하고 Git, 로그 또는 지원 첨부파일에 넣지 않습니다.
| 속성 | 의미 |
|---|---|
@@ -151,9 +151,9 @@ MBN_STOCK_PLAYOUT_RECONNECT_ENABLED
### KTAP 포트와 Network Monitoring 판정
K3DAsyncEngine 매뉴얼의 `KTAPConnect(bTCP, HostAddress, nHostPort, nClientPort, handler)`에서 Test/Live는 `tcpMode: 1`(TCP)만 허용하므로 로컬 JSON의 `port`는 격리 Test Tornado의 `Tools > Option > Control > Network Server > TCP Port`와 정확히 같아야 합니다. `clientPort`는 UDP일 때만 의미가 있고 `TAP TCP Port`/`TAP UDP Port`는 이 연결의 host port가 아닙니다. 매뉴얼 18쪽의 설명과 26쪽 및 192쪽 예시에 표시된 포트 숫자가 서로 다르므로 `30001`/`30002`를 추정하거나 원본·예제 값을 복사하지 않습니다. 해당 회차 Test 인스턴스 화면의 설정값이 유일한 기준입니다. `playout.example.json``30001` DryRun 구조 예시일 뿐 새 Test endpoint의 검증값이 아닙니다.
K3DAsyncEngine 매뉴얼의 `KTAPConnect(bTCP, HostAddress, nHostPort, nClientPort, handler)`에서 Test/Live는 `tcpMode: 1`(TCP)만 허용하므로 로컬 JSON의 `port`는 격리 Test Tornado의 `Tools > Option > Control > Network Server > TCP Port`와 정확히 같아야 합니다. `clientPort`는 UDP일 때만 의미가 있고 `TAP TCP Port`/`TAP UDP Port`는 이 연결의 host port가 아닙니다. 매뉴얼 18쪽의 설명과 26쪽 및 192쪽 예시에 표시된 포트 숫자가 서로 다르므로 `30001`/`30002`를 추정하거나 원본·예제 값을 복사하지 않습니다. 해당 회차 Test 인스턴스 화면의 설정값이 유일한 기준입니다. `playout.example.json``30001`도 구조 예시일 뿐 새 Test endpoint의 검증값이 아닙니다.
Tornado2의 `View > Network Monitoring Window`에서 `[R]`은 서버가 클라이언트 요청을 받은 기록, `[S]`는 서버가 응답을 보낸 기록이며 `TCPSession`은 TCP 세션 수입니다(매뉴얼 26~27쪽). 프로세스 감지, COM 등록 probe 또는 COM 객체 생성만으로는 이 기록이 생기지 않습니다. 기본 앱과 `--dry-run`, `--probe`, `--test-plan`은 KTAP를 호출하지 않으므로 빈 모니터가 정상입니다.
Tornado2의 `View > Network Monitoring Window`에서 `[R]`은 서버가 클라이언트 요청을 받은 기록, `[S]`는 서버가 응답을 보낸 기록이며 `TCPSession`은 TCP 세션 수입니다(매뉴얼 26~27쪽). 프로세스 감지, COM 등록 probe 또는 COM 객체 생성만으로는 이 기록이 생기지 않습니다. `--probe` `--test-plan`은 KTAP를 호출하지 않으므로 빈 모니터가 정상입니다. 정상 앱 실행은 보호된 `Live`이므로 CONNECT 시 네트워크 기록을 기대합니다.
상태의 `accepted-unconfirmed``KTAPConnect`가 SDK 성공값 `1`을 반환했다는 뜻일 뿐입니다. 매뉴얼 41쪽의 `OnHello` 콜백이나 실제 `[R]`/`[S]`를 자동 확인했다는 뜻이 아닙니다. connect-only `--pgm-connect-diagnostic`은 렌더 API 표면을 제거한 별도 binding이라 callback을 관찰하지 않고 `ktapHelloObserved``null`로 보고합니다. 일반 `IPlayoutEngine` 경로는 검증된 282-method `DynamicK3dEventHandler``OnHello`와 lifecycle callback을 수신하지만, callback 미수신 상태를 성공으로 추정하지 않으며 Network Monitoring은 계속 사람이 대조합니다. `lastKtapConnectState`는 현재 연결 상태가 아니라 가장 최근 KTAP dispatch 시도의 증거이며, 화면은 `Connected`/`Faulted` 같은 현재 상태와 분리해 표시합니다. 따라서 격리 `--test-connect`가 성공했는데도 같은 시각의 `[R]`/`[S]`가 전혀 없다면 `--test-sequence`로 진행하지 말고 mode/config 파일, 실제 Network Server TCP Port와 안전 게이트 거부 여부를 먼저 확인합니다.
@@ -257,7 +257,7 @@ Test에서 로컬 프로세스/창 제목 검사를 원격 KTAP endpoint의 신
## 안전한 스모크 절차
먼저 `mode``DryRun`이고 라이브 환경 변수가 없는지 확인합니다.
먼저 보호된 Live 설정·승인 파일과 K3D 등록을 읽기 전용으로 확인합니다.
```powershell
Remove-Item Env:MBN_STOCK_PLAYOUT_AUTHORIZE_LIVE_OUTPUT -ErrorAction SilentlyContinue
@@ -265,10 +265,8 @@ powershell -NoProfile -ExecutionPolicy Bypass `
-File .\scripts\Inspect-K3DRegistration.ps1
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.PlayoutSmoke `
-c Debug -p:Platform=x64 -- --probe
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.PlayoutSmoke `
-c Debug -p:Platform=x64 -- --dry-run
dotnet test .\MBN_STOCK_WEBVIEW.sln -c Debug -p:Platform=x64
dotnet test .\MBN_STOCK_WEBVIEW.sln -c Release -p:Platform=x64
dotnet build .\MBN_STOCK_WEBVIEW.sln -c Debug -p:Platform=x64
dotnet build .\MBN_STOCK_WEBVIEW.sln -c Release -p:Platform=x64
powershell -NoProfile -ExecutionPolicy Bypass `
-File .\scripts\Test-WebPlayout.ps1
```
@@ -392,7 +390,7 @@ Network Monitoring 최종 증분은 HELLO 1/1, 5001/5074 LOAD 각각 1/1, 5001 P
Round H cleanup은 승인된 TAKE OUT 1회와 두 scene unload, disconnect, 앱·진단 listener 종료, 회차 전용 Live 설정과 승인 환경 제거, PGM/Network Monitoring 창 상태 복원으로 끝났습니다. 정상 회차라 추정 rollback은 실행하지 않았습니다. 장애 rollback은 기본 `DryRun`/`Disabled`로 복귀하거나 조직 절차로 직전 승인 패키지를 복원하는 범위이며, vendor DLL·COM 등록·라이선스·실제 자산은 수정하거나 저장소에 넣지 않습니다. 실제 Live PGM 검증 범위는 허용된 5001/5074뿐이고, 35개 scene 전체 완료 근거는 자동 테스트·55-query 실데이터 smoke·매트릭스입니다.
패키지 스모크에서는 벤더 x64 COM이 장비에 정식 등록되어 있어야 합니다. MSIX에 벤더 DLL을 복사해 활성화 오류를 우회하지 않습니다. 패키지 컨텍스트에서 COM 활성화가 막히면 `DryRun` 또는 `Disabled` 유지하고 HRESULT와 등록 검사 결과만 보고합니다.
패키지 스모크에서는 벤더 x64 COM이 장비에 정식 등록되어 있어야 합니다. MSIX에 벤더 DLL을 복사해 활성화 오류를 우회하지 않습니다. 패키지 컨텍스트에서 COM 활성화가 막히면 Live 엔진을 `Faulted`/`Disconnected` 유지하고 HRESULT와 등록 검사 결과만 보고합니다.
## 장애 및 롤백