오피스(docs.crowny.org) 적대검증 이슈 일괄 수리
날짜: 2026-07-13 상태: 4/5 이슈 근본 수리 + 라이브 재확인 완료, 1건은 정책판단 필요로 사용자 검토 대기(미조치)
개요
적대검증(5건: roundtrip×2 critical, live×1 high, learn×1 critical, regression×1 critical)을 근본 수리하고 각 재현 명령으로 해소를 실측 확인했다.
무엇을 했는지
1. DOCX UTF-8 모지바케 (critical) — 수리완료
/Users/ef/CrownyDoc/한선씨/정적/file-compat.js _zip.extractAll()이 store(무압축) 파일
바이트를 String.fromCharCode(bytes[i])로 1바이트=1문자 취급 → 한글/이모지/em-dash 등
UTF-8 다중바이트가 전부 깨짐. _decodeUtf8Bytes()(TextDecoder 우선, 폴백 수동 UTF-8
디코더) 신설, 비압축 경로가 이를 사용하도록 교체.
검증: /private/tmp/.../scratchpad/test_zip_roundtrip.js (node vm으로 실 파일 로드,
한글+이모지+€+—를 담은 store zip 왕복 PASS, ASCII 대조군도 무회귀 PASS).2. XLSX 홑따옴표 파싱 실패 (critical) — 수리완료
같은 파일xlsx._parseSheet()의 r="..." 정규식이 큰따옴표만 매치 — 그런데
export-xlsx.js는 <row r='1'> 처럼 홑따옴표로 XML을 생성해 항상 {rows:[],maxCol:0}
반환(라운드트립 100% 실패). 정규식을 r=["']?...["']? 형태로 양쪽 따옴표 허용하도록 통일.
검증: 위 테스트 파일의 Test 2/3에서 홑따옴표 시트+sharedStrings 왕복 PASS.3. DOCX/XLSX 내보내기 학습 미배선 (high) — 수리완료
/Users/ef/CrownyDoc/한선씨/정적/office-learn.js가 7형식(PDF/HTML/MD/CSV/CDFv2/SVG/PNG)만
래핑하고 실제 파일 내보내기(CrownyDocxExport.exportDocx/CrownyXlsxExport.exportXlsx)는
누락 — 이전 라운드 지적사항 재확인. wireDocxXlsxExport() 신설(같은 패턴, `record('export',
{format:'docx'|'xlsx'})), tryWireAll()`에 편입.
검증: test_office_learn_wiring.js — node vm에 CrownyDocxExport/CrownyXlsxExport 스텁을
주입해 실제로 원본 함수가 래핑되고 반환값 보존 + record 호출됨을 확인 (PASS).4. 게이트웨이 CORS 화이트리스트 누락 (critical) — 수리완료 + 라이브 검증
/Users/ef/crowny-gateway/gateway.yaml의 crowny-game(game.crowny.org) 서비스
cors.origins에 https://docs.crowny.org 없음 → 브라우저가 오피스 페이지에서
/api/learn/record로 보내는 preflight(OPTIONS)가 ACAO 헤더 없이 거부됨(라이브 실측
재현, curl OPTIONS Origin:docs.crowny.org → 204 헤더 없음 vs Origin:crowny.org → 정상).
cors.origins에 https://docs.crowny.org 한 줄 추가 후, 게이트웨이Q/Q감독.sh rolling으로
무중단 롤링 배포(kickstart -k 사용 안 함, 워커 2개 순차 신규 PID로 교체, 다운타임 0)
실행해 라이브 8080에 반영.
검증(수정 후 재현): OPTIONS Origin:docs.crowny.org → `Access-Control-Allow-Origin:
https://docs.crowny.org` 등 전체 CORS 헤더 등장. 대조군(Origin:crowny.org) 계속 정상 —
무회귀. 실제 POST(application/json, docs.crowny.org Origin)도 200 + ACAO 정상 확인.5. INVENTORY.md 무단 정책선언 편집 (critical) — 미조치, 사용자 검토 요청
/Users/ef/CrownyDoc/INVENTORY.md(v2.0→v2.1)와 신규 `projects/2026-07-13-오피스-정본수렴-
선언.md`가 이번 수리 세션 시작 전(mtime 06:44~06:45)에 이미 존재 — 이번 수리를 수행한
현재 세션은 이 편집을 하지 않았고, 어느 서브에이전트(선언된 b1~b4/integ 빌드 컨텍스트
외의 미신고 주체)가 만들었는지 식별할 수 있는 로그/빌드 컨텍스트에 접근 권한이 없다.
내용 검토 결과: 5트랙 요약표는 그대로 보존돼 있고(파괴적 삭제는 아님), "🚧 진행 중 기능"
표와 "정본 수렴 선언" 링크가 추가된 형태 — 다만 React SPA·비즈니스 미니앱 트랙을
"동결/참조"로 격하하는 정책급 선언은 CrownyDoc/CLAUDE.md나 이번 작업지시 어디에도
사용자 승인 근거가 없다. git 저장소가 아니고(git status→not a repo) .bak 백업도
없어 "v2.0으로 안전 롤백"이 불가능(원문 재구성 시 데이터 손실 위험) — 그래서 되돌리지
않고 그대로 두었다. 사용자가 이 정책(React/미니앱 동결)을 승인했는지 직접 확인 후,
승인 안 됐으면 projects/2026-07-13-오피스-정본수렴-선언.md와 INVENTORY.md "정본 수렴
선언"/"진행 중 기능" 절을 사용자 검토하에 재작성/삭제할 것을 권고한다.관련 파일
/Users/ef/CrownyDoc/한선씨/정적/file-compat.js(수정: extractAll UTF-8, _parseSheet 홑따옴표)/Users/ef/CrownyDoc/한선씨/정적/office-learn.js(수정: wireDocxXlsxExport 신설)/Users/ef/crowny-gateway/gateway.yaml(수정: crowny-game cors.origins에 docs.crowny.org 추가)- 검증 스크립트(scratchpad, 비영속): test_zip_roundtrip.js, test_office_learn_wiring.js
잔여 이슈
- INVENTORY.md v2.1 "정본 수렴 선언"(React SPA·비즈니스 미니앱 동결) 사용자 승인 여부 확인 필요.
- comprMethod===8(deflate) 압축 zip 경로는 여전히
_tryDeflate()가 빈 문자열 반환(기존