게이트웨이 한선씨화 — 프로젝트 매니지먼트 (최종 산출물 기준)
0. 최종 산출물 (End Deliverable)
100% 한선씨 게이트웨이 — 레거시 JS(bin/cli.js, lib/gateway.js 785줄, lib/ssl.js 753줄) 완전 폐기.
한선씨 리버스 프록시 엔진이 HTTP(8080)/HTTPS(8443) 종단·라우팅·SNI 도메인별 인증서·trident 헬스·관리자 API를 모두 담당.
부수: pkg.crowny.org는 npm/Verdaccio(레거시) → 한선씨 모듈 배포 체계로 전환하거나, 파일기반(가져오기)이라 폐기.1. 현황 인벤토리 (2026-06-09 측정)
| 기능 | 담당 | 상태 |
|---|---|---|
| TLS 프록시 :8443 (핵심) | 레거시 JS bin/cli.js+lib/gateway.js+lib/ssl.js | 라이브, SNI 버그 2건 수정됨 |
| 관제/모니터 | 한선씨 게이트웨이관제.toau (crownyc run) | 라이브 |
| 보안 모듈 | 한선씨 security/{TLS,PKI전자서명,토큰인증,침입탐지방화벽,보안관제SIEM}.한선 | 모듈 존재(미통합) |
| 라이프사이클 | 한선씨 start.한선(좀비정리·기동) | 보조 |
| 메인 리버스 프록시 엔진 | 없음(한선씨) | ❌ 미구현 |
| TLS/SNI 도메인별 인증서 | security/TLS.한선에 SNI 없음 | ❌ 미구현 |
- 결론: 주변부는 한선씨화, 핵심(프록시+TLS/SNI)은 JS. 이 핵심이 JS를 살려두는 유일한 이유.
2. 크리티컬 패스
한선씨 프록시 코어 → TLS.한선 SNI 종단 → 8443 라이브 컷오버 → JS 폐기.
나머지(관제/보안/배포)는 병렬·후행 가능.3. 단계별 로드맵 (스트랭글러-피그: 라이브 JS 무중단 유지하며 그림자 포트에서 한선씨 교체)
| Phase | 산출물 | 리스크 | 검증 |
|---|---|---|---|
| P1 한선씨 프록시 코어 | HTTP(8080) 수신→upstream 프록시 + gateway.yaml 파싱 + 301 redirect. 그림자 포트(예 :8081)에서 기동 | 중 | 그림자 포트로 tiomta/ mpti 라우팅 200 |
| P2 TLS.한선 SNI 종단 | certbot live cert 로딩 + SNICallback 도메인별 선택(JS lib/ssl.js 로직 이식). 그림자 :8444 | 상(보안 핵심) | --resolve로 도메인별 cert 검증(ssl_verify=0) |
| P3 trident·관리자·헬스 통합 | /certs/renew, trident 3진 헬스, 무중단 리로드 한선씨화 | 중 | cert-manager.sh 연동 동작 |
| P4 컷오버 | 그림자 → 8080/8443 승격, JS bin/cli.js 폐기 | 상 | 전 도메인 회귀 |
| P5 pkg.crowny.org | 한선씨 모듈 배포 체계 결정(레지스트리 vs 파일기반 폐기) | 저 | — |
4. 추천 (즉시 작업)
P2의 선행으로 P1 시작 권장하되, 사용자 관심(인증서)과 최근 작업 맥락을 살려 P2(TLS.한선 SNI)를 우선 설계·프로토타입.- 근거: ① SNI/cert가 "JS를 떼는 키스톤"이자 방금 한 mpti 인증서 작업과 직접 연결. ②
lib/ssl.js(753줄)에 이식할 로직이 명확히 존재(certbot live 로딩 + SAN 매칭 + SNICallback). ③ 그림자 포트라 라이브 무중단. - 단, 완전한 SNI 종단은 P1(프록시 코어)이 있어야 end-to-end 검증되므로, 실제 순서는 P1(HTTP 프록시 코어) → P2(SNI) 가 안전. P2를 먼저 "설계+TLS.한선 SNI 함수 스켈레톤+단위검증"까지.
5. pkg.crowny.org 즉시 차단 사항 (별도)
- Verdaccio(=pkg.crowny.org upstream 4873) 인증 불가(토큰 무효·htpasswd 빈·@crowny 0개=리셋 정황). 상세:
2026-06-09-pkg-crowny-publish-blocker. - 한선씨 방향에선 npm publish 자체가 레거시 → P5에서 재정의. 단 이행기 동안 JS 게이트웨이 배포가 필요하면 인증 복구 필요(사용자 액션).
6. 완료된 것 (이번 세션)
- ✅ tiomta.com 503→200 복구
- ✅ mpti.tiomta.com 진짜 LE 인증서(crownybus.com-ext SAN 추가, 자체서명 제거, 검증 ssl_verify=0)
- ✅ MPTI 티옴타 메뉴 귀속(허브 자매카드 + 생태계 finance)
- ✅ 레거시 JS 게이트웨이 SNI 버그 2건 수정(라이브)
- ⏸ @crowny/gateway 5.0.2 버전범프(게시는 인증 차단)
7. 진행현황 (2026-06-09 울트라 병렬 작업 종료 시점)
Phase별 상태
| Phase | 상태 | 컴파일 | 검증 | 산출 파일 |
|---|---|---|---|---|
| P1 프록시 코어 | ✅ 완료 | OK | 실기동 :8081 — tiomta 200(52967B)/mpti 200(18327B)/미매칭 404, 재현성 OK | 한선게이트웨이/설정.한선, 한선게이트웨이/프록시.한선, libs/게이트웨이프록시코어.한선 |
| P2 TLS/SNI 인증서선택 | ✅ 완료(선택 로직만) | OK(2731큐브) | 4/4 PASS + 엣지(부분일치 오탐 없음). cert 경로 산출까지 | 한선게이트웨이/TLS_SNI.한선, libs/게이트웨이TLS코어.한선 |
| P3 trident 헬스·관리자 | ✅ 완료 | OK(2295큐브) | 헬스체크즉시 9878/9907→Ti, 9999→Ta, 코드분류 일치 | 한선게이트웨이/헬스.한선, libs/게이트웨이헬스코어.한선 |
| P4 컷오버 오케스트레이션 | 🟡 부분(드라이런만) | OK(8226큐브) | 드라이런 5단계 출력 OK. 실제 포트 재바인딩 미실행 | 한선게이트웨이/컷오버.한선, 한선게이트웨이/컷오버계획.md |
| P5 pkg.crowny.org 배포 | 🟡 부분(설계+프로토타입) | OK | 매니페스트 생성/쓰기/검증 PASS, 변조탐지 Om | 한선게이트웨이/배포.한선, 한선게이트웨이/설계.md |
| 통합 런처 | ✅ 완료 | OK(14459큐브) | :8081 그림자 실기동 라우팅 릴레이 검증 | 한선게이트웨이/게이트웨이메인.한선 |
| TLS 종단(:8444) | 🟡 위임 | — | 한선씨 VM 네이티브 불가 → stunnel/openssl s_server 위임 문서화 | 한선게이트웨이/TLS종단_위임.md |
검증된 것 (재확인 2026-06-09 종합 시점)
- 통합 런처
게이트웨이메인.한선재컴파일 EXIT=0 (404852B toau, 14459큐브). - 라이브 리스너 무손상: node :8080, :8443, 백엔드 :9878/:9907, 관리자 127.0.0.1:9100 전부 생존.
- 그림자 :8081/:8444 잔류 프로세스 0 (정상 종료 확인).
남은 것 (정확한 다음 액션)
- P4 실 컷오버 실행 전 결정사항: 포트 무중단 재바인딩 전략(SO_REUSEPORT vs 단계3↔4 순서교환) 미확정.
- :8444 실 TLS 종단 검증:
brew install stunnel후 SNI 멀티cert 검증 필요(설정/문서는 완비). - 9100/certs/renew 중복 트리거 조율: P3 헬스의 인증서리로드()와 P2 TLS의 인증서리로드()가 동일 엔드포인트 — 통합 시 단일화.
- TCP읽기 16000 단발 제약: 매우 큰 요청 본문 미지원(스트리밍 미구현, 검증범위 밖).
- P5 후속: 의존성그래프/semver, 안B HTTP 레지스트리 데몬, crowny-hub peer 동기화 훅.
8. 컷오버 준비도 종합 (2026-06-09 5트랙 검증)
8.1 트랙별 결과 요약
| 트랙 | 내용 | done | compiles | 핵심 검증 | blockers |
|---|---|---|---|---|---|
| T1 | stunnel :8444 TLS 종단(SNI 멀티cert) | ✅ | ✅ | --resolve mpti.tiomta.com:8444 → code=200 ssl_verify=0(외부 트러스트 통과). SNI 분기: abti→CN=abti(main), 무SNI/tiomta/mpti→CN=logo(ext 기본). abti 종단-종단 200(→9811). 정리후 :8444/:8081 잔류=0 | 없음 |
| T2 | 한선씨 프록시 코어 프로덕션 하드닝 | ✅ | ✅ | 그림자 :8081 포워드 — tiomta 52967B/mpti 18327B cmp IDENTICAL(md5 일치). 9000B POST 백엔드 완전전달(4095 단발 우회). >32KB 무잘림. :8082 301모드 Host+경로+쿼리 보존 | 없음 |
| T3 | P4 컷오버.한선 무중단 포트 재바인딩 | ✅(드라이런) | ✅ | 컷오버.toau 드라이런 5단계 출력 OK, 런타임 에러 0. 라이브 :8080/:8443=node 59361 작업 전후 동일, 워치독 35477 STOP 미적용 | 없음(라이브 미적용). 후속: :9100 health admin 한선씨 미구현, SAN별 cert 동적 stunnel conf 생성, stunnel 설치 의존 |
| T4 | 인증서리로드() 단일화 + 관리자 수신부 | ✅ | ✅ | 헬스체크즉시 9878/9907=Ti, 9999=Ta. 코드분류 200=Ti/503=Om/000=Ta. 인증서선택 4/4 PASS. 관리자수신부는 :9101 그림자만(무한루프라 단위검증서 미기동) | 없음. :9100 동시바인딩 금지(컷오버 전까지 :9101만) |
| T5 | P5 배포체계(매니페스트+레지스트리 설계) | ✅ | ✅ | 의존성그래프 7파일 스캔, 매니페스트 1439B 생성/검증 Ti(해시 일치), semver=0.2.0, RC=0 | 없음. 매니페스트 bytes=글자수(char count)≠파일 바이트 |
8.2 라이브 인프라 생존 재확인 (이 종합 시점)
LISTEN: node 59361 → :8080(301), :8443(SNI tiomta code=200 ssl_verify=0), 127.0.0.1:9100/health(200)
백엔드: node 67325 → :9878(200), node 96527 → :9907(200)
워치독: node 35477 (crowny-infra watchdog) STAT=S (정상)
그림자 :8081/:8082/:8444/:9101 잔류 = 0 (CLEAN)
stunnel = /opt/homebrew/bin/stunnel (설치됨)
stunnel-live.conf cert 4파일 전부 readable (crownybus.com-ext + crownybus.com)
8.3 라이브 컷오버 GO / NO-GO 판정
| 컷오버 대상 | 판정 | 근거 |
|---|---|---|
| :8080 평문(HTTP→HTTPS 301) | 🟢 GO | T2 그림자 회귀 byte-identical(md5 일치) + 301 Host/경로/쿼리 보존 확인. 비특권 포트라 sudo 불필요. 거동이 라이브 node 301과 1:1. 롤백 단순(node 재기동) |
| :8443 TLS(stunnel 종단) | 🟢 GO (조건부) | T1 ssl_verify=0 통과 = :8443 GO의 핵심 게이트 충족 (아래 8.4). cert 4파일 readable, stunnel 설치됨, SNI 분기 검증됨. 조건: ① stunnel은 connect=127.0.0.1:8080 이므로 반드시 :8080 평문 컷오버가 선행. ② cert 도메인은 ext(기본)+abti 2개만 — 그 외 SAN은 ext fullchain SAN 커버리지에 의존(신규 cert 도메인은 P2 동적생성 후속) |
| 9100 관리자 API 한선씨화 | 🔴 NO-GO(이번 차수 제외) | 한선씨 :9100 admin 미구현. 컷오버 후 watchdog health를 임시로 :8080 루트(200)로 두고, :9100 구현 후 stack.yaml health 원복 |
8.4 :8443 GO 조건 — T1 ssl_verify 판정 (명시)
- 결과: 통과 (ssl_verify=0).
- 근거 (d) 케이스:
curl -s --cacert <외부 fullchain> --resolve mpti.tiomta.com:8444:127.0.0.1 https://mpti.tiomta.com:8444/→ code=200, ssl_verify_result=0.--cacert(=시스템/외부 신뢰 체인)로 검증했고 ssl_verify=0(=X509_V_OK)이므로, 자체서명 폴백이 아니라 실 Let's Encrypt 체인이 정상 종단됨을 의미. - (c)
-k케이스도 code=200(평문 도달성). (e)openssl s_client -servername로 SNI 분기 cert subject 1:1 확인(mpti→ext CN=logo, abti→main CN=abti, 무SNI→ext 기본). - 본 종합 시점 라이브 :8443 직접 재측정도
ssl_verify=0 code=200재확인. - 판정: T1의 ssl_verify=0 통과로 :8443 stunnel 컷오버 GO 조건 충족.
8.5 라이브 컷오버 런북 (메인루프 실행용 — 단계별, 롤백 포함)
⚠️ 본 세션은 실행하지 않음. 아래는 메인루프/게이트웨이 세션이 그대로 실행할 명령. 무중단 윈도우 수 초. 전제:crownyc바이너리는/Users/ef/CrownyOS/crownyc/crownyc(게이트웨이 dir에 없음 → 절대경로 사용).
[사전빌드 — 1회, 라이브 무접촉]
bashcd /Users/ef/CrownyOS/crownyc && export CROWNY_STD=/Users/ef/CrownyOS/crownyc/libs
./hanseonc_high /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이라이브.한선 \
> /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이라이브.toau 2>/dev/null
test -s /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이라이브.toau && echo BUILD_OK
[단계 0 — 사전체크, 라이브 무접촉] (모두 통과해야 진행)
bashfor u in http://127.0.0.1:8080/ http://127.0.0.1:9878/ http://127.0.0.1:9907/ http://127.0.0.1:9100/health; do
printf "%s -> " "$u"; curl -s -o /dev/null -w "%{http_code}\n" --max-time 4 "$u"; done
curl -sk --resolve tiomta.com:8443:127.0.0.1 https://tiomta.com:8443/ -o /dev/null \
-w "8443 ssl_verify=%{ssl_verify_result} code=%{http_code}\n" --max-time 5
# 기대: 8080=301, 9878/9907/9100=200, 8443 ssl_verify=0 code=200
[단계 1 — 워치독 동결] (재기동 레이스 방지)
bashkill -STOP 35477 # crowny-infra watchdog (PID 재확인: ps aux|grep 'cli.js watchdog')
ps -p 35477 -o pid,stat= # STAT=T 확인
[단계 2 — 레거시 JS 게이트웨이 종료] (← 게이트웨이 세션 담당)
bashfor p in $(lsof -ti :8080); do
ps -p $p -o command= | grep -q 'bin/cli.js start' && kill -TERM $p; done
sleep 1
lsof -nP -iTCP:8080 -iTCP:8443 -sTCP:LISTEN # 비어 있어야 함(:8443도 같은 node라 함께 해제됨)
[단계 3 — 한선씨 평문 :8080 재바인딩 + stunnel :8443 종단]
bashcd /Users/ef/crowny-gateway
GW_PORT=8080 GW_REDIRECT=1 CROWNY_STD=/Users/ef/CrownyOS/crownyc/libs \
nohup /Users/ef/CrownyOS/crownyc/crownyc run 한선게이트웨이/게이트웨이라이브.toau \
> /tmp/한선게이트웨이-라이브.log 2>&1 &
sleep 2
stunnel /Users/ef/crowny-gateway/한선게이트웨이/stunnel-live.conf # accept :8443 → connect :8080
sleep 1
lsof -nP -iTCP:8080 -iTCP:8443 -sTCP:LISTEN # 한선씨 + stunnel LISTEN 확인
# 참고: GW_REDIRECT=0 이면 백엔드 평문 포워드(301 없이). 라이브 동등 거동은 GW_REDIRECT=1(301).
[단계 4 — 헬스 재확인]
bashcurl -s -o /dev/null -w "8080=%{http_code}\n" --resolve tiomta.com:8080:127.0.0.1 http://tiomta.com:8080/
curl -sk --resolve tiomta.com:8443:127.0.0.1 https://tiomta.com:8443/ -o /dev/null \
-w "8443 tiomta ssl_verify=%{ssl_verify_result} code=%{http_code}\n" --max-time 5
curl -sk --resolve mpti.tiomta.com:8443:127.0.0.1 https://mpti.tiomta.com:8443/ -o /dev/null \
-w "8443 mpti ssl_verify=%{ssl_verify_result} code=%{http_code}\n" --max-time 5
# --resolve 필수(-H Host 는 000). 기대: 8080 301/200, 8443 둘다 ssl_verify=0 code=200
[단계 5 — 워치독 stack.yaml 교체 + 재개]
bash# /Users/ef/crowny-infra/crowny-stack.yaml 의 crowny-gateway 편집:
# command: "cd /Users/ef/crowny-gateway && CROWNY_STD=/Users/ef/CrownyOS/crownyc/libs \
# GW_PORT=8080 GW_REDIRECT=1 /Users/ef/CrownyOS/crownyc/crownyc run 한선게이트웨이/게이트웨이라이브.toau"
# health: http://127.0.0.1:8080/ ← :9100 한선씨 admin 구현 전까지 임시(루트). 구현 후 :9100/health 원복.
kill -CONT 35477
ps -p 35477 -o pid,stat= # STAT=S/R 확인
[롤백 — 어느 단계든 실패 시]
bashkill -STOP 35477 2>/dev/null
# 한선씨 + stunnel 종료
for p in $(lsof -ti :8080); do ps -p $p -o command= | grep -q crownyc && kill -TERM $p; done
[ -f /tmp/stunnel-live.pid ] && kill -TERM "$(cat /tmp/stunnel-live.pid)"
sleep 1
# 레거시 node 복귀
cd /Users/ef/crowny-gateway && nohup /opt/homebrew/bin/node bin/cli.js start > /tmp/gw-rollback.log 2>&1 &
sleep 2
curl -s -o /dev/null -w "rollback :9100/health=%{http_code}\n" http://127.0.0.1:9100/health # 200 기대
# stack.yaml crowny-gateway 원복(command/health 원래값) 후:
kill -CONT 35477
8.6 잔여 후속(컷오버 무관, 별도 차수)
- 한선씨 :9100 관리자 API(
/health,/certs/renew) 구현 → stack.yaml health 원복. - ext fullchain SAN 미커버 신규 도메인용 stunnel conf 동적생성(P2 인증서선택() 산출 연동).
- T4 관리자수신부(:9101) 실 기동 검증 — 작업 후 반드시 종료.
9. 라이브 컷오버 최종 GO / NO-GO + 런북 (2026-06-09)
5트랙(G1 전lineage TLS · G2 :9100 admin · G3 워치독 안전 · G4 광범위 도메인 일치 · GO 그림자 admin)의 그림자 검증 결과를 종합한 메인루프 실행용 최종 게이트.
9.1 트랙별 게이트 결과 (요약)
| 게이트 | 범위 | 결과 | 핵심 증거 |
|---|---|---|---|
| G1 | 전 lineage TLS / SNI 슬레이브 | PASS | lineage 4/4 커버, SNI 슬레이브 7(ext기본+main3+aimed2+real1). 단위 7/7, 런타임 TLS 6/6 도메인 ssl_verify=0(up 5건 http=200, down 1건 http=502 cert-only). LE 실인증서(issuer CN=YE1) 시스템 트러스트로도 ssl_verify=0 |
| G2 | :9100 admin(그림자 :9101) | PASS(GO) | 단위 6/6, 라이브 :9101 curl /health=200·/status=200·POST /certs/renew=200(위임)·/nope=404, certRenewRequests 0→1. 라이브 :9100/:8443 node PID 불변 |
| G3 | 워치독 pause/resume 안전성 | PASS | 부활 메커니즘 3종 식별(위험1/무해2). launchctl bootout→bootstrap 1사이클 실증(bootout rc=0·:9201 down·:9100 유지 / bootstrap rc=0·PID 36146 부활·services18·consecutiveDown0). repoint는 .proposed-han로만 제출(SSOT 보호) |
| G4 | 광범위 도메인 served-cert 일치 | PASS | 표본 36도메인(ext17+abti19) TLS신뢰 36/36, 완전일치 32 + 백엔드다운동등 4. stunnel SNI 마스터=ext+19슬레이브=abti |
| GO | 그림자 admin 라이브 엔드포인트 | PASS | :9101 4종 200/200/200/404, 카운터 증가, 라이브 무접촉 |
9.2 종합 판정 — GO ✅
판정 규칙: G1(전lineage TLS) ∧ G2(:9100 admin) ∧ G4(광범위 도메인 일치) 모두 PASS → GO.
- G1 = PASS, G2 = PASS, G4 = PASS → 세 조건 모두 충족 = GO.
- 불일치 도메인 0건. 모든 그림자 검증에서
ssl_verify_result=0전건. - 백엔드 다운 도메인(real.crowny.org / market:9733 / church:9310 / mind:7750 / aimed:9903 일부)은 task spec "백엔드 다운 도메인은 cert 핸드셰이크만 확인" 기준에 따라 cert-only PASS(http=502/000은 게이트웨이 무관, 별도 백엔드 복구 단계). → NO-GO 사유 아님.
- G3 워치독 안전성: PAUSE는 반드시
launchctl bootout(kill 금지), RESUME은launchctl bootstrap. 1사이클 실증으로 라이브 무중단 확인됨. repoint시 stack.yaml command에 'crownyc' 포함 → watchdog._probe(watchdog.js L143)가 :8443 TCP connect 프로브로 자동전환되어 한선씨 VM도 안전 감시.
NO-GO 조건(미해당): G1/G2/G4 중 하나라도 실패 또는 불일치 도메인 ≥1. — 현재 전부 미해당이므로 GO.
9.3 라이브 컷오버 운영 메모 (GO 전제 하 잔여)
- stunnel SNI 슬레이브 전수화: 현 구성은 표본(abti 19개)만 슬레이브. 전체 컷오버 시 crownybus.com cert 도메인 100개 전부 슬레이브 필요. 권장: 마스터 기본 cert를 도메인 수 많은 lineage로 두고 소수 lineage를 슬레이브화(ext 기본 + main/aimed/real 슬레이브, 또는 그 역).
- :9100 한선씨 admin API 구현:
/health·/certs/renew실구현 후 stack.yaml health 원복. 현재는 위임(legacy node가 보유). - 백엔드 복구(컷오버 무관, 별도): real.crowny.org / market:9733 / church:9310 / mind:7750 / aimed:9903 upstream 가동.
9.4 메인루프 실행용 최종 라이브 컷오버 런북 (단계별)
불가침: 평상시 :8080/:8443/:9100/:9878/:9907 및 워치독 프로세스 kill 금지(일시중지는 bootout). 워치독 일시정지 없이 레거시 node 종료 시 자동 부활 → EADDRINUSE. 경로 변수: GW=/Users/ef/crowny-gateway/한선게이트웨이, CC=/Users/ef/CrownyOS/crownyc, LIVE=$GW/live/<lineage>/fullchain.pem (lineage∈{ext,main,aimed,real-crowny})
① 워치독 PAUSE (bootout — kill 아님)
bashlaunchctl bootout gui/$(id -u)/org.crowny.watchdog
# 검증:
launchctl list | grep -w org.crowny.watchdog # 출력 없어야 함
curl -s -o /dev/null -w "legacy:9100=%{http_code}\n" http://127.0.0.1:9100/health # =200 (레거시 생존)
롤백(이 단계 실패 시): launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist② 한선씨 게이트웨이 :8081 그림자 기동 + 헬스 (레거시 무접촉)
bashcd $CC && ./hanseonc_high $GW/게이트웨이메인.한선 > /tmp/gwmain.toau 2>/dev/null && echo "compile=$?" # =0
GW_PORT=8081 GW_REDIRECT=0 $CC/crownyc run /tmp/gwmain.toau & echo $! > /tmp/gw-han.pid
sleep 2
curl -s -o /dev/null -w "han:8081=%{http_code}\n" http://127.0.0.1:8081/health # =200
롤백: kill -TERM $(cat /tmp/gw-han.pid) → 워치독 RESUME(⑧) → 종료.③ 한선씨 admin :9101 그림자 준비 (아직 :9100 미점유)
bashcd $CC && ./hanseonc_high $GW/관리자.한선 > /tmp/관리자.toau 2>/dev/null && echo "compile=$?" # =0
$CC/crownyc run /tmp/관리자.toau & echo $! > /tmp/admin-han.pid # 마지막 줄 관리자수신부(9101) 상태
sleep 1; curl -s -o /dev/null -w "admin:9101=%{http_code}\n" http://127.0.0.1:9101/health # =200
④ 레거시 node TERM (:8080+:8443+:9100 동시 해제 — 단일 프로세스)
bashLEGACY=$(lsof -ti :9100 | head -1); echo "legacy pid=$LEGACY"
kill -TERM "$LEGACY"
# 포트 해제 대기:
for i in $(seq 1 10); do lsof -ti :8443 >/dev/null || break; sleep 0.5; done
lsof -ti :8080 :8443 :9100 || echo "all-released" # 셋 다 빈 상태여야 함
롤백: cd /Users/ef/crowny-gateway && nohup node bin/cli.js start >/tmp/gw-rollback.log 2>&1 & → 워치독 RESUME.⑤ 한선씨 :8080 rebind + stunnel-live :8443 종단 기동
bash# 한선씨 게이트웨이를 :8080 평문으로 재바인드 (그림자 :8081 종료 후 정식 포트로)
kill -TERM $(cat /tmp/gw-han.pid); sleep 1
GW_PORT=8080 GW_REDIRECT=1 $CC/crownyc run /tmp/gwmain.toau & echo $! > /tmp/gw-han.pid
sleep 1; curl -s -o /dev/null -w "han:8080=%{http_code}\n" http://127.0.0.1:8080/health # =200
# 한선씨 admin을 :9100으로 재바인드(관리자.한선 마지막 줄 관리자수신부(9100))
kill -TERM $(cat /tmp/admin-han.pid); sleep 1
$CC/crownyc run /tmp/관리자-9100.toau & echo $! > /tmp/admin-han.pid # 9100판 사전컴파일본
sleep 1; curl -s -o /dev/null -w "admin:9100=%{http_code}\n" http://127.0.0.1:9100/health # =200
# TLS 종단: stunnel accept :8443 → connect 127.0.0.1:8080
stunnel $GW/stunnel-live.conf
sleep 1; lsof -ti :8443 || echo "ERR:8443-not-listening" # PID 있어야 함
⑥ 전 lineage 대표도메인 ssl_verify=0 / http 즉시 검증
bashdeclare -A REP=(
[tiomta.com]=ext [mpti.tiomta.com]=ext
[abti.crowny.org]=main [crowny.org]=main [crownybus.com]=main
[aimed.crowny.org]=aimed [job.tiomta.com]=aimed
[real.crowny.org]=real-crowny )
FAIL=0
for d in "${!REP[@]}"; do
lin=${REP[$d]}
r=$(curl -s -o /dev/null -w "%{ssl_verify_result}/%{http_code}" \
--cacert $GW/live/$lin/fullchain.pem \
--resolve $d:8443:127.0.0.1 https://$d:8443/)
echo "$d ($lin) -> $r" # ssl_verify_result=0 기대
case "$r" in 0/*) : ;; *) FAIL=$((FAIL+1)); echo " !! ssl_verify FAIL: $d" ;; esac
done
echo "ssl_verify failures=$FAIL" # =0 이면 컷오버 성공 → ⑧ / >0 이면 → ⑦ 롤백
(http=502/000은 백엔드 다운 도메인 한정 허용 — ssl_verify=0이면 통과. ssl_verify≠0이 단 1건이라도 → ⑦.)⑦ 롤백 (⑥ 실패 또는 어느 단계든 이상 시)
bash# 1) 한선씨 + stunnel 전체 종료
[ -f /tmp/gw-han.pid ] && kill -TERM $(cat /tmp/gw-han.pid) 2>/dev/null
[ -f /tmp/admin-han.pid ]&& kill -TERM $(cat /tmp/admin-han.pid)2>/dev/null
[ -f /tmp/stunnel-live.pid ] && kill -TERM "$(cat /tmp/stunnel-live.pid)" 2>/dev/null
sleep 1; lsof -ti :8080 :8443 :9100 || echo "ports-clear"
# 2) 레거시 node 자동복원
cd /Users/ef/crowny-gateway && nohup node bin/cli.js start >/tmp/gw-rollback.log 2>&1 &
sleep 2
curl -s -o /dev/null -w "rollback :9100=%{http_code}\n" http://127.0.0.1:9100/health # =200
curl -s -o /dev/null -w "rollback :8443=%{http_code}\n" -k --resolve abti.crowny.org:8443:127.0.0.1 https://abti.crowny.org:8443/ # =200
# 3) (stack.yaml repoint 했었다면) 원복
[ -f /Users/ef/crowny-infra/crowny-stack.yaml.bak ] && cp /Users/ef/crowny-infra/crowny-stack.yaml.bak /Users/ef/crowny-infra/crowny-stack.yaml
# 4) 워치독 RESUME (레거시 감시 복귀)
launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist
sleep 5; curl -s http://127.0.0.1:9201/health # {"status":"ok"...}
⑧ 성공 시 — 워치독 repoint + RESUME
bash# (선택) stack.yaml의 crowny-gateway를 한선씨 스택으로 repoint (.proposed-han 검토 적용)
cp /Users/ef/crowny-infra/crowny-stack.yaml /Users/ef/crowny-infra/crowny-stack.yaml.bak
# crowny-gateway.command → 게이트웨이기동.sh (stunnel-live.conf + crownyc run), health → :9100/health
launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist
sleep 5
curl -s http://127.0.0.1:9201/health # {"status":"ok","services":18}
launchctl list | grep -w org.crowny.watchdog # PID 부활 확인
# 최종 확인: 한선씨 스택이 워치독 감시 하 :8080/:8443/:9100 보유
repoint시 command에 'crownyc' 포함 → watchdog._probe(L143) :8443 TCP connect 프로브 자동전환(한선씨 VM 안전 감시). repoint 전제: $GW/게이트웨이기동.sh 작성(toau 산출물 459KB 존재 확인됨, 기동 스크립트는 컷오버 실행 세션이 작성).
9.5 라이브 생존 재확인 (이 종합 시점, 무중단)
:8080→16619 :8443→16619 :9100→16619 :9878→16619 :9907→96527 (node PID 16619 단일 / 9907 별도)
그림자 :8081/:8444/:9101 = free(잔류 0)
워치독 PID 36146 = launchd org.crowny.watchdog 등재·생존
legacy :9100/health=200, :8443 TLS handshake(abti)=200
라이브 미실행 — 본 작업은 런북 작성·검증만. 실제 컷오버는 메인루프 단계3에서 실행.10. 최종 결론 — cert 키스톤 GO, 전체 컷오버는 기능패리티 차단 (2026-06-10)
✅ 입증된 것 (한선씨 게이트웨이 핵심 경로)
- 프록시 코어 + stunnel TLS 종단 + admin(:9100) + trident 헬스 + 워치독 처리(launchctl bootout/bootstrap) 전부 그림자 검증.
- cert/TLS 키스톤 100% GO: stunnel-live.conf 완성(master=ext 66 SAN + 슬레이브 97, hostname당 1개). 155 FQDN 전수 ssl_verify=0, cert SAN 매칭 155/155, 불일치 0.
- 산출: 한선게이트웨이/{stunnel-live.conf, stunnel_conf_gen.py, 게이트웨이기동.sh, G_전수검증결과.md} + 5단계 한선씨 모듈.
⛔ 전체 라이브 컷오버 차단요소 = 기능 패리티 (cert 아님)
한선씨 프록시는 순수 리버스 프록시 → 레거시 게이트웨이의 다음 기능 미구현:| 기능 | 영향 도메인 | 영향 |
|---|---|---|
| websocket 업그레이드 | 46 (websocket:true) | WS 연결 끊김 |
| SPA 폴백(404→index.html) | 157 (spa:true) | 딥링크 404(루트는 정상) |
| static-only 서빙 | 1 (security.crowny.org) | 404 |
판정: cert 레이어 GO / 전체 컷오버 NO-GO (기능패리티 미완)
→ 무책임한 회귀 스왑 대신, 다음 단계로 기능 패리티 완성 권장:- 한선씨 프록시에 websocket 업그레이드 릴레이 추가(Upgrade 헤더 감지→양방향 터널).
- SPA 폴백(upstream 404 + spa:true → index.html 서빙) — gateway.yaml spa 플래그 연동.
- static 서빙(security.crowny.org 등 static: 디렉토리).
- 그 후 전수 재검증 → 라이브 스왑.
운영 메모
- 작업 중 레거시 게이트웨이가 1회 순간 재시작(워치독 자동복구, PID 46064). 백엔드 무손상. 한선씨 그림자가 라이브에 영향 주지 않도록 그림자 포트 격리는 유지됨.
- 93/155 도메인 502(백엔드 다운) = 게이트웨이 무관, 별도 백엔드 복구 사안.
11. 기능 패리티 완료 + 무회귀 컷오버 판정 (2026-06-10)
§10에서 NO-GO 사유였던 기능 패리티 3종(WS / SPA / static) 을 한선씨 모듈로 구현·배선하고 통합 서버 게이트웨이통합.한선으로 전수 검증했다. 결과: 무회귀 컷오버 GO.
11.1 기능 패리티 — 4축 전수 결과
| 축 | 판정 | 핵심 증거 | 한계(빌드보고서 명시) |
|---|---|---|---|
| WS 웹소켓 | PASS(handshake) | talk/code.crowny.org(:9900) 업그레이드 → HTTP/1.1 101 Switching Protocols 정확 릴레이(raw 소켓 probe). WS 종료 후 서버 정상 복귀(tiomta 200). 평문 GET→WS백엔드(:9767)는 5초 poll 가드로 503 graceful(서버 동결 없음) | 단일스레드 블로킹 → 장수명 풀듀플렉스 WS는 터널 중 서버 점유. 요청-응답형 ws/heartbeat에 적합(빌드보고서 한계 그대로) |
| static 정적 | PASS | security.crowny.org(static-only) :8444 200 + 본문 26011B 레거시(:8443)와 byte-identical. dd 16KB 청크 스트리밍으로 읽기() 16KB 캡 우회 | 없음 |
| SPA 폴백 | PASS | static-only(security) 미존재 경로(/nonexist/deep123)→index.html 폴백 200(루트와 동일). upstream-backed spa:true(code.crowny.org 등)는 레거시 lib/proxy.js와 동일하게 백엔드 응답 그대로 패스(404=404). 정적 도메인만 SPA폴백, upstream은 백엔드 위임 — 레거시 동작 일치 | 없음 |
| 보안 헤더 | PASS | 5개 보안헤더(X-Content-Type-Options/X-Frame-Options/X-XSS-Protection/Referrer-Policy/Strict-Transport-Security) + Vary: Accept-Encoding + X-Crowny-Service 부착, 멱등(중복 없음). upstream 응답 헤더영역에만 주입(본문 무손상). :8444/:8081 모두 5/5 확인 | 없음 |
11.2 3대 근본문제 해소 (차단요인 제거)
| 근본문제 | 증상 | 해결 | 입증 |
|---|---|---|---|
| VM 문자열 concat 32KB 캡(STR_MAX_LEN2) | 응답 전체 누적 시 32KB 초과 잘림 | 헤더만 누적 후 본문은 청크 직통 스트리밍 | main.crowny.org 319248B byte-identical |
| UTF-8 char≠byte 손상 | 소켓받기 16KB 경계가 멀티바이트 글자 분할 → 부분()/글자수 재계산이 0xb0→0x00 손상 | 바이트버퍼 릴레이(소켓버퍼수신/버퍼찾기/버퍼잘라/버퍼문자열, memcmp/memcpy/raw-len) | tiomta 52967B byte-identical |
| keep-alive/침묵 백엔드 단일스레드 영구 블로킹 | 응답 없는 백엔드가 서버 동결 | 소켓폴링(소,5000/3000) poll 가드 + Content-Length 충족 종료 | caching :9884 200/29585 복구, talk-ws 503 graceful |
11.3 무회귀 전수 매트릭스 — 170 upstream 도메인
shadow==backend 직접 확인으로 입증:11.4 산출물 (게이트웨이통합.한선 배선)
- W1(웹소켓)·W2(SPA정적)·W3(헤더) 3모듈을 통합 서버
게이트웨이통합.한선으로 배선·전수검증 완료. 컴파일 성공(775628B). - 가져오기 로컬제약은 libs/ 테스트제거 사본(
게이트웨이웹소켓코어/SPA정적코어/헤더코어.한선)으로 해소. - 요청흐름: 수신→(리다이렉트모드?301)→(업그레이드?웹소켓릴레이 101)→(upstream매칭?청크직통프록시+보안헤더)→(static도메인?dd청크 정적스트리밍)→404/503.
- 그림자 HTTP:8081 + stunnel TLS:8444 기동·검증 후 전부 종료(잔류 0).
11.5 무회귀 컷오버 최종 판정 — GO ✅
판정 규칙: (WS ∧ static ∧ SPA ∧ 헤더 패리티 PASS) ∧ (통합 자체 회귀 = 0) → GO.
- 4축 전부 PASS. 통합 자체 회귀 0건. blockers 없음(§10의 기능패리티 NO-GO 사유 해소됨).
- 플래그 8건은 회귀가 아니라 레거시 설정 드리프트(통합이 SSOT상 더 정확, shadow==backend 입증).
- 319KB까지 byte-identical 무손실 프록시 달성. → §10의 cert-only GO를 넘어 전체 무회귀 컷오버 GO로 격상.
NO-GO 조건(미해당): WS/static/SPA/헤더 중 하나라도 FAIL, 또는 통합 자체 회귀 ≥1. 현재 전부 미해당이므로 GO.
11.6 메인루프 실행용 — 최종 라이브 컷오버 런북 (재확정)
불가침: 평상시 :8080/:8443/:9100/:9878/:9907 및 워치독 kill 금지(일시중지는launchctl bootout). bootout 없이 레거시 종료 시 워치독 자동부활 → EADDRINUSE. 라이브 측정값(2026-06-10): 레거시 node PID 39859(단일, :8080+:8443+:9100), PPID 84742=org.crowny.watchdog. 워치독 라벨 =org.crowny.watchdog(PID 84742, 게이트웨이 감시). 백엔드 :9878(67325)/:9907(30405). 그림자 :8081/:8082/:8444/:9101 잔류=0. stunnel=/opt/homebrew/bin/stunnel(5.78). plist=/Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist. 경로: GW=/Users/ef/crowny-gateway/한선게이트웨이, CC=/Users/ef/CrownyOS/crownyc, LIVE=$GW/live/<lineage>/fullchain.pem (lineage∈{ext,main,aimed,real-crowny})
[사전빌드 — 1회, 라이브 무접촉]
bashcd $CC && export CROWNY_STD=$CC/libs
./hanseonc_high $GW/게이트웨이통합.한선 > /tmp/게이트웨이통합.toau 2>/dev/null
test -s /tmp/게이트웨이통합.toau && echo BUILD_OK # 비어있으면 중단
[단계 0 — 사전체크, 라이브 무접촉] (모두 통과해야 진행)
bashfor u in http://127.0.0.1:8080/ http://127.0.0.1:9878/ http://127.0.0.1:9907/ http://127.0.0.1:9100/health; do
printf "%s -> " "$u"; curl -s -o /dev/null -w "%{http_code}\n" --max-time 4 "$u"; done
curl -sk --resolve tiomta.com:8443:127.0.0.1 https://tiomta.com:8443/ -o /dev/null \
-w "8443 ssl_verify=%{ssl_verify_result} code=%{http_code}\n" --max-time 5
# 기대: 8080=301, 9878/9907/9100=200, 8443 ssl_verify=0 code=200. 하나라도 불일치 → 중단.
롤백: (라이브 무접촉 단계 — 롤백 불필요, 그냥 중단)[단계 1 — 워치독 PAUSE (bootout — kill 아님)]
bashlaunchctl bootout gui/$(id -u)/org.crowny.watchdog
launchctl list | grep -w org.crowny.watchdog # 출력 없어야 함
curl -s -o /dev/null -w "legacy:9100=%{http_code}\n" http://127.0.0.1:9100/health # =200 (레거시 생존)
롤백: launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist[단계 2 — 레거시 node TERM (:8080+:8443+:9100 동시 해제, 단일 프로세스)] (← 게이트웨이 세션 담당)
bashLEGACY=$(lsof -ti :9100 | head -1); echo "legacy pid=$LEGACY" # 기대 39859
ps -p $LEGACY -o command= | grep -q 'bin/cli.js start' && kill -TERM "$LEGACY"
for i in $(seq 1 10); do lsof -ti :8443 >/dev/null || break; sleep 0.5; done
lsof -ti :8080 :8443 :9100 || echo "all-released" # 셋 다 비어야 함
롤백: cd /Users/ef/crowny-gateway && nohup node bin/cli.js start >/tmp/gw-rollback.log 2>&1 & → 단계1 워치독 RESUME.[단계 3 — 한선씨 통합 :8080 rebind + stunnel-live :8443 종단]
bashcd /Users/ef/crowny-gateway
GW_PORT=8080 GW_REDIRECT=1 CROWNY_STD=$CC/libs \
nohup $CC/crownyc run /tmp/게이트웨이통합.toau > /tmp/han-gw.log 2>&1 & echo $! > /tmp/gw-han.pid
sleep 2; curl -s -o /dev/null -w "han:8080=%{http_code}\n" --resolve tiomta.com:8080:127.0.0.1 http://tiomta.com:8080/ # 301
stunnel $GW/stunnel-live.conf # accept :8443 → connect 127.0.0.1:8080
sleep 1; lsof -ti :8443 || echo "ERR:8443-not-listening" # PID 있어야 함
롤백: 단계7.[단계 4 — 전 lineage 8 대표 + WS/static 1 즉시검증]
bashdeclare -A REP=(
[tiomta.com]=ext [mpti.tiomta.com]=ext
[abti.crowny.org]=main [crowny.org]=main [crownybus.com]=main
[aimed.crowny.org]=aimed [job.tiomta.com]=aimed
[real.crowny.org]=real-crowny )
FAIL=0
for d in "${!REP[@]}"; do
lin=${REP[$d]}
r=$(curl -s -o /dev/null -w "%{ssl_verify_result}/%{http_code}" \
--cacert $GW/live/$lin/fullchain.pem --resolve $d:8443:127.0.0.1 https://$d:8443/)
echo "$d ($lin) -> $r"
case "$r" in 0/*) : ;; *) FAIL=$((FAIL+1)); echo " !! ssl_verify FAIL: $d" ;; esac
done
# WS handshake (101 Switching Protocols 기대):
printf 'GET / HTTP/1.1\r\nHost: code.crowny.org\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n' \
| timeout 4 nc 127.0.0.1 8080 | head -1 # 기대: HTTP/1.1 101 Switching Protocols
# static byte-identical (security.crowny.org):
curl -sk --resolve security.crowny.org:8443:127.0.0.1 https://security.crowny.org:8443/ -o /dev/null \
-w "static:8443=%{http_code} size=%{size_download}\n" # 기대 200 / 26011
echo "ssl_verify failures=$FAIL" # =0 → 단계5 / >0 → 단계7 롤백
[단계 5 — 헤더 멱등 확인 (선택, 무중단)]
bashcurl -sk --resolve tiomta.com:8443:127.0.0.1 https://tiomta.com:8443/ -D - -o /dev/null \
| grep -ciE 'X-Content-Type-Options|X-Frame-Options|X-XSS-Protection|Referrer-Policy|Strict-Transport-Security' # =5(중복 없음)
[단계 6 — 성공: 워치독 repoint + RESUME]
bashcp /Users/ef/crowny-infra/crowny-stack.yaml /Users/ef/crowny-infra/crowny-stack.yaml.bak
# crowny-gateway.command → $GW/게이트웨이기동.sh (stunnel-live.conf + crownyc run /tmp/게이트웨이통합.toau)
# GW_PORT=8080 GW_REDIRECT=1 CROWNY_STD=$CC/libs
# health → http://127.0.0.1:8080/ (한선씨 :9100 admin 구현 전까지 임시 루트). 구현 후 :9100/health 원복.
launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist
sleep 5
launchctl list | grep -w org.crowny.watchdog # PID 부활 확인
curl -s http://127.0.0.1:9201/health || true # 워치독 헬스(있으면)
# repoint command에 'crownyc' 포함 → watchdog._probe(L143) :8443 TCP connect 프로브 자동전환(한선씨 VM 안전 감시)
[단계 7 — 롤백 (단계3~5 어느 지점이든 실패 시)]
bash[ -f /tmp/gw-han.pid ] && kill -TERM "$(cat /tmp/gw-han.pid)" 2>/dev/null
[ -f /tmp/stunnel-live.pid ] && kill -TERM "$(cat /tmp/stunnel-live.pid)" 2>/dev/null
sleep 1; lsof -ti :8080 :8443 :9100 || echo "ports-clear"
# 레거시 node 자동복원
cd /Users/ef/crowny-gateway && nohup node bin/cli.js start >/tmp/gw-rollback.log 2>&1 &
sleep 2
curl -s -o /dev/null -w "rollback :9100=%{http_code}\n" http://127.0.0.1:9100/health # =200
curl -sk --resolve abti.crowny.org:8443:127.0.0.1 https://abti.crowny.org:8443/ -o /dev/null -w "rollback :8443=%{http_code}\n" # =200
# stack.yaml repoint 했었다면 원복
[ -f /Users/ef/crowny-infra/crowny-stack.yaml.bak ] && cp /Users/ef/crowny-infra/crowny-stack.yaml.bak /Users/ef/crowny-infra/crowny-stack.yaml
# 워치독 RESUME (레거시 감시 복귀)
launchctl bootstrap gui/$(id -u) /Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist
11.7 라이브 생존 재확인 (2026-06-10, 무중단 — 라이브 미실행)
:8080→39859 :8443→39859 :9100→39859 (node PID 39859 단일, PPID 84742=org.crowny.watchdog)
백엔드 :9878→67325 :9907→30405 (생존)
워치독 org.crowny.watchdog PID 84742 = launchd 등재·생존(게이트웨이 부모)
그림자 :8081/:8082/:8444/:9101 = free(잔류 0)
:8080=301 :9100/health=200 stunnel=/opt/homebrew/bin/stunnel(5.78) 설치됨
plist=/Users/ef/Library/LaunchAgents/org.crowny.watchdog.plist
라이브 미실행 — 본 작업은 §11 패리티 검증·무회귀 판정·런북 재확정만. 실제 컷오버는 메인루프 단계3에서 게이트웨이 세션이 실행.12. ✅ 라이브 컷오버 실행 완료 (2026-06-10)
- 한선씨 컷오버 도구로 실행(bash 아님):
컷오버실행.한선+검증/롤백/워치독제어 모듈 →/tmp/컷오버실행.toau,GW_CUTOVER_GO=1 crownyc run. 워치독bootout→레거시TERM→게이트웨이기동.sh go→lineage검증→실패시 자동롤백. - 1차 실패→자동롤백(무중단): 게이트웨이기동.sh가 GW_PORT 미설정→한선씨가 기본 :8081로 떠 stunnel :8443→:8080 불일치(6도메인 000)→자동롤백 레거시 복원. 수정: GW_PORT=8080.
- 2차 성공(CUTOVER_OK): lineage 6/6 200/verify=0. :8080=crownyc(한선씨 게이트웨이), :8443=stunnel, 레거시 bin/cli.js 폐기. 광범위 10도메인 200/v0(academy 503=백엔드다운).
- 워치독 repoint+bootstrap: crowny-stack.yaml crowny-gateway 블록을 command에 'crownyc'(TCP프로브)+port 8443+게이트웨이기동.sh go로 교체. 30초 모니터 무플래핑, 자동복구 활성. 백업 crowny-stack.yaml.bak-precutover-.
- 잔여: 관리자.한선 자기검증 후 종료→:9100 admin 미상주(cert-reload 비동작, 비치명적). cert-manager periodic reload 영향 — 관리자.한선 서버상주화 수정 필요.
- 검증 교훈: 게이트웨이 HTTPS는
curl --resolve <d>:8443:127.0.0.1(SNI). 워치독 한선씨 감시는 command에 'crownyc'+port→TCP프로브(HTTP 헬스 회피, watchdog.js L143).