7.0.9 페이로드 대비 버전이 오른 패키지 31종과 코어의 CHANGELOG 최상단 절 날짜를 2026-09-04 로 맞췄다. 이어서 릴리즈 스크립트의 게이트를 브랜치 생성 없이 전수 실행한 결과, 파일 본문 누출 검사가 error 25건으로 릴리즈를 막고 있었다. 전부 이번 사이클에 들어온 것이다. - 확장 문서·코어 주석 20건이 공개 배포본에 없는 를 가리켰다. 공개되는 AGENTS.md 참조로 바꾸고, 참조된 9개 절의 실재를 전수 확인했다. 유일하게 빠져 있던 「독립 레이아웃의 글로벌 호스트 컴포넌트」절은 원래 동기화 대상이었으므로 AGENTS.md 에 반영했다. - 시나리오 매니페스트의 내부 문서 포인터는 소비자가 하나도 없어 제거했다. - 공개 테스트 3건이 내부 검사 스크립트를 열어 도구 간 리터럴을 대조하고 있었다. tests/** 는 배포 페이로드에 포함되고 는 제외되므로 배포본에서 원리상 성립할 수 없는 검사다. 대조를 그 도구 옆으로 옮기고 공개 테스트에는 자기 동작 단언만 남겼다. 존재 가드로 무마하지 않은 것은 그 경우 배포본에서 검사가 조용히 건너뛰어져 "검사하지 않음" 과 "통과" 가 구분되지 않기 때문이다. 옮긴 대조는 돌지 않으면 잠그지 못하므로 대상 파일 편집 시 자동 실행되도록 등록했다. 누출 검사 자체도 릴리즈 시점에만 돌아 위반이 다음 릴리즈까지 드러나지 않았으므로, 룰을 복제하지 않고 실행 시점만 세션 종료로 앞당겼다. 같은 검증 중 드러난 선행 결함 하나(이커머스 문서의 집계 블록 드리프트)도 함께 정리했다.
77 lines
4.0 KiB
YAML
77 lines
4.0 KiB
YAML
# audit:allow test-scenario-coverage reason: 인스톨러(설치 전 표면)는 설치 완료 사이트에 붙는 Playwright 인프라와 양립하지 않는다 (_guard 가 410). 브라우저 계층은 Chrome MCP 정밀 점검 매트릭스로 대체하며, 그 결과는 작업 이력 문서에 기재한다.
|
|
|
|
feature: 인스톨러 프로세스 출력 인코딩 정규화와 JSON 응답 경계
|
|
|
|
description: |
|
|
외부 프로세스 출력(`whoami`, composer stdout, powershell/wmic)은 UTF-8 이 아니라
|
|
그 명령을 실행한 콘솔의 코드페이지로 나온다. 한국어 Windows(OEM 949)에서 계정명에
|
|
한글이 있으면 invalid UTF-8 바이트가 응답 배열에 실리고, `json_encode()` 가 false 를
|
|
반환해 `echo false` = HTTP 200 + 빈 본문이 나간다. 예외도 로그도 남지 않는다.
|
|
|
|
핵심 동작:
|
|
- ProcessOutputEncoding: 한국어 코드페이지 확정 감지 → Windows OEM/ANSI 폴백 → mb_scrub
|
|
(복원 가능한 출력은 한글 그대로 살리고, 불가능한 바이트만 대체)
|
|
- installer_json_encode: 정규화 + substitute + 실패 시 파싱 가능한 오류 JSON
|
|
(false·빈 문자열을 절대 반환하지 않는다)
|
|
- 출처 정규화: getWebServerUser/Group, composer 스트림, addLog, 상태 파일 저장
|
|
- 관측성: 정규화가 실제로 필요했으면 설치 로그에 1회 기록, encode 실패는 키 경로까지 기록
|
|
- 프론트: 빈 본문/비 JSON 응답을 읽을 수 있는 안내 문구로, 폴링은 5회 연속 실패 시 중단
|
|
|
|
axes:
|
|
output_encoding: [utf8, cp949_korean, cp949_extended_hangul, truncated_utf8, single_high_byte, empty]
|
|
sink:
|
|
- requirements_response
|
|
- polling_state_response
|
|
- sse_event
|
|
- state_json_file
|
|
- installation_log
|
|
- js_embedded_view
|
|
- core_system_info
|
|
value_position: [scalar, nested_array_value, array_key]
|
|
locale: [ko, en]
|
|
|
|
exclusions:
|
|
- { output_encoding: empty, value_position: array_key, reason: "빈 문자열 키는 인스톨러 응답 형태에 존재하지 않는다" }
|
|
- { sink: core_system_info, value_position: array_key, reason: "CPU 정보는 스칼라 값 한 개" }
|
|
- { sink: core_system_info, locale: en, reason: "정규화는 로케일에 의존하지 않는다 — ko 표본으로 충분" }
|
|
- { sink: installation_log, value_position: array_key, reason: "로그 메시지는 스칼라 문자열" }
|
|
- { sink: installation_log, value_position: nested_array_value, reason: "동일" }
|
|
|
|
effects:
|
|
# 응답이 절대 비지 않는다 (결함 본체)
|
|
- response_body_never_empty
|
|
- requirements_response_parses_after_cp949_account_name
|
|
- polling_response_parses_after_invalid_utf8_log
|
|
- sse_data_line_never_empty
|
|
# 복원 품질 (mb_scrub 단독 대비 향상)
|
|
- korean_account_name_restored_exactly
|
|
- extended_hangul_restored
|
|
- valid_utf8_passes_through_unchanged
|
|
- non_string_scalars_preserve_type_and_value
|
|
- unrecoverable_bytes_still_yield_encodable_utf8
|
|
# 출처 차단
|
|
- web_server_user_always_valid_utf8
|
|
- composer_stream_line_normalized_before_emit
|
|
- state_json_file_written_with_substitute_flag
|
|
- core_cpu_info_normalized_before_serialization
|
|
# 관측성 (제보 사례에 로그 흔적이 0 이었다)
|
|
- encode_failure_logged_with_key_path
|
|
- non_utf8_process_output_logged_once_per_source
|
|
# 프론트 안내
|
|
- frontend_shows_readable_message_on_empty_body
|
|
- frontend_shows_readable_message_on_unparsable_body
|
|
- polling_stops_after_5_consecutive_parse_failures
|
|
- polling_parse_failure_counter_resets_on_success
|
|
- new_error_message_keys_defined_in_ko_and_en
|
|
# 재발 차단
|
|
- no_raw_json_encode_remains_in_installer_output_paths
|
|
- sse_emitter_routes_through_guarded_encoder
|
|
- get_cpu_info_routes_both_branches_through_normalizer
|
|
|
|
test_files:
|
|
- tests/Unit/Support/ProcessOutputEncodingTest.php
|
|
- tests/Unit/Installer/InstallerJsonOutputTest.php
|
|
- tests/Unit/Installer/RequirementsResponseUtf8Test.php
|
|
- tests/Unit/Installer/AddLogUtf8ScrubTest.php
|
|
- tests/Unit/Services/SettingsServiceCpuInfoTest.php
|