남은 것과 다시 볼 조건
9. 구현 순서
| 순서 | 무엇 | 완료 판정 |
|---|---|---|
| 1 | 골격 — recipe 섹션, 폴더 발견, 규칙 파일 컴파일·실행, 심각도 3종 수집, ①·③ 게이트 배선 | 실패하는 검증이 커밋을 막고 데이터베이스가 그대로인 것을 테스트가 확인. Warn·Info가 막지 않는 것도 함께 |
| 2 | 타입 액세서 — C# 생성기 재사용, 바이너리 메모리 왕복, 기본 인덱스로 셀 위치 역참조 | 픽스처 워크북 + 검증 스크립트 게이트. 오타 스크립트가 컴파일 오류로 보고되는 것과, 보고에 셀 위치가 나오는 것까지 |
| 3 | 전역 — Schema 열거 뷰, 전역 스크립트 실행, 스키마 대상 보고 오버로드 | 규약 위반 픽스처가 컬럼 헤더 셀 위치와 함께 보고되는 것 |
| 4 | 편의 — 공용 코드 결합, 테이블별 병렬, 보고 정렬, --validate-only, 머리말과 --new-validator | 병렬로 돌린 결과의 보고 순서가 실행마다 같은 것. 스캐폴딩이 낸 파일이 그대로 컴파일되고 도는 것 |
| 5 | 런타임 게이트웨이 — MySQL·Redis부터, --skip-runtime-validation | 기존 데이터베이스 테스트 컨테이너에 붙는 게이트 |
| 6 | 이 항목은 없어졌습니다. 이식 대상이던 Lua 검사기 141개는 이전 대규모 코퍼스에 딸린 것이었고, 그 코퍼스가 저장소에서 빠지면서 함께 빠졌습니다 | 이식 과정 자체가 컨텍스트 API의 검증입니다. 부족한 헬퍼가 여기서 드러납니다. LootKindValidator처럼 흩어져 있던 규칙이 전역 파일 하나로 모이는 것도 여기서 확인합니다 |
골든에는 영향이 없습니다 — 검증은 산출물을 바꾸지 않고 통과/실패만 정합니다.
10. 취약점과 개선 여지
설계가 맞아도 구조에서 나오는 위험은 남습니다. 구현 전에 알고 시작하는 것들이고, 완화를 적을 수 없는 것은 완화가 없다고 적습니다.
신뢰 경계 — 임의 코드 실행
규칙 파일은 변환기 프로세스의 권한으로 도는 C#입니다. 파일을 쓸 수 있고, 프로세스를 띄울 수
있고, 네트워크에 나갈 수 있습니다. 샌드박스는 없습니다 — .NET에는 코드 접근 보안이 없고,
어셈블리 참조를 좁히는 것으로는 기본 라이브러리에 이미 있는 것을 막지 못합니다. 「Db()가
읽기 전용」도 편의이지 보증이 아닙니다: 스크립트가 자기 연결을 직접 열면 그 게이트를
지나지 않습니다.
그래서 차단할 수 있다고 주장하지 않고 경계를 명시합니다.
| 사실 | 따라오는 것 |
|---|---|
| 검증 폴더는 코드입니다 | 시트와 같은 취급이 아니라 소스와 같은 취급 — 같은 저장소, 같은 리뷰, 같은 승인 절차 |
| CI가 PR의 스크립트를 도는 것은 PR 작성자가 빌드 머신에서 코드를 도는 것입니다 | 외부 기여를 받는 저장소라면 검증을 신뢰된 리비전으로 고정하거나 격리된 실행자에서 돌립니다 |
Connections의 자격증명은 스크립트가 읽을 수 있습니다 | 읽기 전용 계정 · 운영 계정 금지 · 자격증명은 그 단계에만 노출 |
개선 여지는 별도 프로세스 실행입니다. 검증을 자식 프로세스로 분리하면 변환기의 스테이징·데이터베이스 연결과 떨어지고, 컨테이너로 감싸는 선택지가 생깁니다. 지금 설계는 같은 프로세스이므로, 필요해질 때의 경로로 적어둡니다.
메모리 — 같은 데이터의 세 벌
메모리 왕복(§3)의 대가가 여기 있습니다. 검증이 도는 순간 프로세스에 세 벌이 있습니다.
| 무엇 | 왜 필요한가 |
|---|---|
Model (RawCell 격자 포함) | 셀 위치 역참조가 이것을 봅니다 |
.tcb 바이트 | 리더에 넘기는 것 |
| 리더가 만든 객체 그래프 | 스크립트가 보는 것 |
워크북 읽기의 실측이 62 MiB 워크북 하나에서 live 4.2 GB ·
peak 7.4 GB였습니다(리더를 스트리밍으로 교체하기 전의 값입니다). 그 위에 두 벌이 더 얹히므로
가장 먼저 한계에 닿을 곳은 여기입니다. 완화의 순서는
바이트를 테이블 단위로 넘기고 즉시 놓는 것(전체를 동시에 유지할 이유가 없습니다), 그다음이
위치 역참조에 필요한 최소 인덱스만 남기고 RawCell 격자를 놓는 것입니다. 후자는 「셀 위치를
가리킨다」를 지키면서 격자를 놓는 것이라 설계가 필요합니다.
셀 위치 역참조가 정확하지 않은 자리
Error(row, nameof(row.Field))가 셀을 찾는 것은 필드 이름을 컬럼으로 되돌릴 수 있을 때
입니다. 되돌아가지 않는 경우가 실재합니다.
| 경우 | 무엇이 문제인가 |
|---|---|
접힌 배열 (Text1·Text2 → Text_array) | 이름 하나가 컬럼 여러 개입니다 |
레코드 그룹 (Reward) | 멤버 × 원소로 컬럼 수십 개입니다. nameof(row.Reward)는 그중 어느 것도 특정하지 않습니다 |
| 매트릭스 표 | 값이 배열 하나이고 컬럼 id는 파생 테이블입니다 |
TargetSide로 좁힌 액세서 | 없는 필드는 이름도 없습니다 — 검증용 액세서는 both로 생성해야 합니다 |
앞의 셋은 그룹의 첫 컬럼을 가리키는 것을 기본으로 두고, 원소를 아는 오버로드
(Error(row, nameof(row.Reward), at: k))를 함께 냅니다. 원소를 아는 검사가 그룹의 첫 컬럼을 가리키는
보고를 내면 사람을 잘못된 셀로 보냅니다.
단일 파일 발행에서 돌지 않는 것
규칙을 컴파일하려면 프레임워크 어셈블리의 경로가 필요합니다. 참조를 손으로 조립하지 않고 실행 중인 프로세스의 목록에서 가져오기 때문이고, 그것이 규칙 파일이 프레임워크의 아무 부분이나 쓸 수 있는 이유입니다 — 유지해야 하는 샌드박스를 만들지 않은 대가로 얻은 것입니다.
그런데 PublishSingleFile은 그 어셈블리들을 실행 파일 안에 넣고, 안에 있는 것에는 열 경로가
없습니다. 이 저장소는 자립 배포본을 릴리스로 내므로 그 배포본에서 검증은 돌지 않습니다.
| 무엇 |
|---|