---
document_id: PLAI_SERVICE_SURVIVABILITY_PC_NODE_HANDOFF
schema_version: 2
canonical: true
snapshot_date: 2026-08-09
coordination_root: D:\aisfor-chain
current_phase: PHASE_3_MAIN_HOST_LOSS_CODE_READY_STABLE_INGRESS_AND_DATA_REPLICA_REQUIRED
latest_stage_document: docs/resilience/43-PROMOTION-LEASE-AND-SIGNED-REPLICA-READINESS-KO.md
production_change_allowed: false
primary_server_preservation_required: true
external_transfers_locked: true
operator_signing_locked: true
public_rpc_unlock_allowed: false
---

# PLAI 서비스 생존성·PC 노드 전환 작업 인계 문서

## 0. 2026-08-09 진행 현황

Phase 0 읽기 전용 inventory/failure-domain map에서 시작해 production 잠금을 유지한 채 다음 기반까지 진행했다.

- 암호화 chunk 3복제, 한 노드 상실, 네 번째 노드 보충, 메인 cache를 쓰지 않은 PC restore live canary 완료
- 3개 PC Ed25519 node key의 동일 block `620000` 3-of-3 RPC attestation live 증명
- NAT peer push 한계 확인: 한 relay만 도달, private LAN URL을 광고한 노드는 cross-NAT push 실패
- finite 1800초 UPnP relay를 default-OFF로 구현하고 parser/lease/CGNAT 거부 self-test 완료; 내부 TCP 5277에 대해 admitted node key별 외부 포트 52001~52003을 선택할 수 있으며 실제 mapping은 미실행
- secret-free/no-fs/no-db/no-network read capsule과 요청별 32 MiB/3초 child-process fence 구현
- signed event·rebuildable projection protocol 구현 및 self-test
- admitted PC node의 3-of-3 signed manifest vote와 RPC certificate에 묶인 service-directory mailbox, target resource challenge, witness/admission/eligibility mailbox를 PC Sync candidate `1.4.81-node-bound-distinct-upnp-port-default-off-locked`에 구현
- admission-backed storage candidate를 deterministic 선출하고 3-peer vote/2-domain/fencing token으로 제한하는 replica-repair mailbox를 default-OFF로 구현
- 운영 중 관측된 Windows `EPERM` atomic rename 재시작 원인을 위해 unique temp file과 bounded retry 소스를 추가하고 self-test 완료; 실행 중 production 프로세스는 재시작하지 않음
- bootstrap 이후 고정 node allowlist 없이 이전 epoch의 유효 lease 보유자 3명이 새 PC를 admission하고 다음 epoch witness set으로 회전시키는 capability admission protocol self-test 완료
- Android에 Ed25519 vote·commitment·lease·rollback을 검증하는 native directory cache와 default-OFF main-frame failover hook을 추가하고 debug build 완료
- Android에 3개 독립 HTTPS source/failure-domain/root-key pin과 2-of-3 동일 bundle quorum을 요구하는 default-OFF bootstrap client를 추가하고 debug build 완료
- recovery-capable PC signer와 3-peer/2-domain vote로 finalized 되는 ciphertext-hash-only `service-recovery` event mailbox 및 rebuildable projection을 default-OFF로 구현
- 3-witness/2-domain/RPC-finality 서명 checkpoint가 확정된 뒤에만 recovery history를 줄이고 tombstone version floor와 다음 event 연속성을 보존하는 bounded compaction을 PC Sync `1.4.81`에 구현
- Web/TWA에 WebCrypto Ed25519 3표, 3-source/2-source-domain bootstrap, rollback floor, service-worker 재검증을 추가하고 PC에는 manifest-bound read-only stateless service shell을 default-OFF로 구현; 첫 검증 노드가 응답하지 않으면 signed health identity를 확인하며 다음 노드를 선택
- 메인 서버/DB/DNS/network를 사용하지 않는 4-node synthetic integration에서 RPC quorum, directory, Web bootstrap, capsule, 3복제 repair, projection rebuild를 연결해 통과
- 최신 읽기 전용 live topology preflight에서 최근 PC 5대·fresh PC 5대·runtime-ready PC 4대와 2개 WAN failure domain을 확인; 3-node/2-domain 메인 호스트 단절 canary topology는 준비됐고 최종 WAN-loss 등급에는 제3 WAN이 필요
- 승인형 canary를 3개 독립 WAN이 아니면 실행 거부하도록 강화하고, 3 relay RPC certificate·manifest vote fan-out·3-source directory·3 capsule·3 service shell 검증 후 feature와 UPnP mapping을 회수하는 통합 실행 경로를 합성 상태 머신으로 통과
- PC Sync `1.4.81`에 admitted Ed25519 node key별 HTTPS relay URL을 HMAC runtime policy로 짧게 결합하는 default-OFF 경로를 추가하고 HTTPS-only·origin 고유성·자기 key URL 선택·만료를 self-test; tunnel이나 외부 전송은 시작하지 않음
- 2-domain profile은 명시적 HTTP finite canary에서만 허용하고 production HTTPS verifier의 3-domain 기본값은 유지; 같은 NAT의 여러 PC가 TCP 5277 충돌 없이 서로 다른 node-bound 외부 포트를 쓰도록 구현
- Android에 실제 relay URL과 root node key를 build property로 주입하는 debug-only HTTP canary 경로를 추가하고 configured compile 및 최종 default-OFF debug rebuild를 통과; release HTTP canary와 실제 APK 설치는 미실행
- 승인된 3-PC/2-domain/외부 TCP 52001·52002·52003/최대 1800초 live canary에서 후보 설치 3대와 동시 유효 attestation 3개를 확인했지만 public relay는 최대 2개만 확보되어 메인 호스트 단절 생존은 미증명
- PC Sync 후보를 `1.4.83-peer-sponsored-upnp-diagnostic-default-off-locked`로 보완해 같은 LAN peer sponsor와 제한된 UPnP 진단을 추가했으나, 서로 다른 private LAN과 `UPNP_IGD_NOT_DISCOVERED`를 확인해 UPnP만으로 불특정 NAT PC를 service node로 만들 수 없음을 실증
- 모든 live 시도는 false policy, attestation lease 만료, TCP 52001~52003 삭제, rollout policy 삭제까지 완료했고 기존 public TCP 5277은 보존; 메인 서비스와 chain health는 HTTP 200 유지
- PC Sync 후보 `1.4.84-outbound-peer-overlay-default-off-locked`에 NAT 뒤 target의 inbound 포트 없이 동작하는 Ed25519 session·signed poll/response·180초 lease·replay 차단·read-only virtual gateway를 구현하고 기존 후보 회귀시험 9개와 continuity 합성시험 통과
- 2-domain main-host-loss 전용으로 하나의 public ingress가 세 node-bound virtual URL을 전달하는 합성 profile을 추가했으며 production 3-domain 검증 기준은 낮추지 않음; 후보 배포와 live session은 미실행
- 후속 34~39차 finite canary에서 PC Sync `1.4.105-signed-overlay-bootstrap-priority-default-off-locked`까지 배포했고, 3개 PC 후보·동시 유효 attestation·2-domain topology·승인 포트의 공개 ingress를 live로 확인
- runtime policy의 선택적 exact endpoint map, 동일 버전 feature 변경 hot-restart, 승인 포트 직접 경로와 node-bound virtual overlay 경로 분리, signed overlay bootstrap 우선순위를 구현하고 자체시험 통과
- 공개 ingress에는 NAT 뒤 PC 1대의 Ed25519 outbound session이 live로 연결됐지만 나머지 1대는 고포트 ingress에 연결하지 못해 3개 relay route·directory·capsule·service shell의 최종 live 교환은 미통과
- Web/TWA의 3개 HTTPS source, 2-source quorum, 3개 pinned root key, service-worker proof 재검증 기반은 이미 default-OFF로 구현돼 재검증을 통과했으나 실제 독립 HTTPS 443 PC relay·인증서·bootstrap origin은 아직 없음
- 39차 종료 뒤 false policy, attestation lease 만료, TCP 52001~52003 매핑과 rollout policy 삭제를 확인했으며 DB·DNS·공개 API·운영자 서명·validator·transaction submission은 변경하지 않음
- PC Sync `1.4.106-https-relay-default-off-locked`에 공인 인증서를 직접 종료하는 HTTPS 443 reverse relay를 추가했다. signed node origin과 인증서 hostname/key 일치, 요청마다 runtime policy 재검증, 읽기 전용 경로 allowlist, nested control/write 차단, credential 제거, 크기·rate 제한, TLS 1.2~1.3을 자체시험했다.
- HTTPS relay staging plan은 서로 다른 node key·hostname·failure domain·인증서 fingerprint 3개 이상과 최대 30분 lease를 강제하고 private key/token 필드를 거부한다. 생성되는 PC/Web/Android 설정은 모두 activation OFF다.
- `scripts/prepare-https-relay-staging.js`는 실제 plan이 들어오면 기본 offline 검증만 수행하며, 명시적 `--probe`에서만 시스템 CA·TLS fingerprint·HSTS·node identity를 읽기 전용 확인한다. 출력 artifact를 써도 활성화 값은 false다.
- 당시 live topology는 candidate `1.4.106` 설치 0대, runtime-ready 3대/2 failure domain으로 확인됐다. 이 과거 제3 WAN blocker는 아래 3-domain live canary에서 해소됐으며 stable HTTPS origin 조건은 남아 있다.
- Cloudflare 공식 Windows binary `2026.7.3`을 staging에만 내려받아 Authenticode `Valid`/Cloudflare 서명자와 SHA-256을 확인했다. production-data-free 합성 Quick Tunnel은 외부 HTTPS health 200과 비허용 경로 403을 9초 안에 증명하고 프로세스를 자동 종료했다.
- PC Sync `1.4.107-quick-tunnel-discovery-default-off-locked`에 최대 30분·admitted node 전용 Quick Tunnel discovery, pinned binary hash, 제한된 loopback proxy, URL commitment heartbeat, policy-off process cleanup을 구현했다.
- 사용자의 명시적 informed approval 아래 3-PC/2-domain Quick Tunnel live canary를 실행했다. 첫 시도는 capsule policy 전파 대기 누락, 두 번째는 HTTPS bundle의 더 엄격한 `allowHttpForCanary:false`를 거부하는 검증 오류를 각각 발견했고, 모든 시도에서 false policy·tunnel 종료·lease 만료·rollout 삭제를 완료했다.
- 두 결함을 수정한 세 번째 live canary에서 서로 다른 임시 HTTPS origin 3개, node identity 3개, 동일 RPC certificate 3표, manifest vote 3표, directory source 3개, stateless capsule 실행 3개, read-only service shell 3개를 실제 외부 경로로 검증했다. 결과는 `TWO_DOMAIN_THREE_NODE_HTTPS_QUICK_TUNNEL_CONTINUITY_PROVEN_AND_REVOKED`이며 production traffic·DNS·DB·validator·transaction은 변경하지 않았다.
- 이 증명은 `MAIN_HOST_LOSS_ONLY_NOT_WAN_DOMAIN_LOSS` 등급의 유한 read-only canary다. Quick Tunnel은 종료·삭제됐고 production endpoint로 상시 활성화되지 않았으므로 현재 메인 서버를 끌 수 있다는 뜻은 아니다.
- 이후 USB 테더링으로 분리한 세 번째 public failure domain을 확보하고 `--require-three-domains` gate를 통과했다. PC Sync `1.4.109-runtime-heartbeat-null-stale-fallback-default-off-locked`은 Sync 재기동 뒤 오래된 validator runtime heartbeat를 실행 중 PID와 loopback RPC 읽기만으로 복구하며 validator start/stop은 허용하지 않는다. Windows 설치·supervisor·restart·rollback·RPC·tunnel 통합시험과 후보 attestation을 통과했다.
- 승인된 3-PC/3-domain Quick Tunnel live canary에서 서로 다른 외부 HTTPS origin과 node identity 3개, RPC 3표, manifest 3표, directory 3곳, capsule 3회, service shell 3개를 검증했다. 최종 결과는 `THREE_DOMAIN_THREE_NODE_HTTPS_QUICK_TUNNEL_CONTINUITY_PROVEN_AND_REVOKED`이고 모든 tunnel process·URL·lease·policy를 회수했다. production traffic·DB·DNS·validator·operator signing·transaction은 변경하지 않았다.
- 이 성공으로 유한 `THREE_INDEPENDENT_WAN_DOMAIN_READ_ONLY_CONTINUITY`는 live-proven 상태다. 다만 Quick Tunnel은 임시 origin이고 회수됐으므로 상시 production continuity인 `currentContinuity`는 여전히 false다.
- 상시 origin용 별도 default-OFF plan gate를 추가했다. 이 gate는 3개 독립 node/network/control-plane domain, 공개 HTTPS 443, 인증서·SPKI pin, 30일 이상 인증서, 자동 갱신·재시작 복구 증거를 요구하고 Quick Tunnel·secret 필드·activation true를 거부한다. 실제 stable origin은 아직 생성하지 않았다.
- production data replica용 default-OFF plan gate를 추가했다. 독립 node/network/control-plane domain 3개, private transport, mTLS, 디스크 암호화, 격리 restore, MongoDB 8.2.x, majority read/write를 요구하고 production 인증자료·평문 backup·validator 역할 결합·activation을 거부한다. 실제 production DB 연결·backup read·외부 전송은 수행하지 않았다.
- production data replica 읽기 전용 live inventory에서 fresh 5대 중 저장공간·지속 supervisor 적격 PC 4대와 3개 독립 failure domain을 확인했다. topology는 준비됐지만 mTLS·디스크 암호화·격리 restore workspace의 authenticated evidence는 0대라 live replica plan은 아직 false다.
- 2026-08-09 재점검에서는 fresh 5대와 적격 4대는 유지됐지만 독립 network failure domain이 2개만 관측돼 topology readiness도 다시 false가 됐다. 과거 3-domain 증거를 현재 상태로 오인하지 않도록 readiness evidence를 갱신했다.
- AISFOR·AISTALK·AISFOR Group·AISMALL·PLAI Sharing에 default-OFF `PASSIVE_STANDBY` fence를 추가했다. session/DB middleware 앞에서 동적 route와 쓰기를 막고 Socket 연결을 거부하며, AISFOR·AISMALL·PLAI Sharing의 예약 worker 시작을 차단한다. 다섯 서비스 fleet 합성검사는 모두 통과했고 production process는 재시작하지 않았다.
- 다섯 서비스를 별도 loopback port에서 실제 `PASSIVE_STANDBY`로 기동해 DB/session 없이 health 200, dynamic GET 503, POST 503, 종료 후 port 폐쇄를 모두 확인했다.
- 설치된 MongoDB 8.2 binary로 Temp 하위 3노드 replica set을 구성해 majority write, primary process 종료, 다른 primary 선출, 장애 후 majority write와 장애 전 record 보존을 격리 환경에서 증명했다. 세 mongod·port·합성 데이터는 모두 제거했고 production Mongo는 읽거나 변경하지 않았다.
- Socket.IO를 사용하는 네 서비스에 공식 Mongo adapter 0.4.0을 exact dependency로 추가하고 default-OFF replica-set gate를 연결했다. 합성 3노드 Mongo primary 장애 전·후 두 Socket.IO instance의 server-side broadcast가 모두 전달됐으며 production adapter와 index는 활성화하지 않았다.
- `PROMOTED_ACTIVE` 준비 전 Socket.IO 연결이 들어올 수 있던 AISFOR·AISTALK 경로를 포함해 네 Socket 서비스에 promotion Socket gate를 설치했다. AISTALK·AISFOR Group은 별도 connect-mongo client 연결 완료도 기다린다. 다섯 서비스 회귀시험과 관련 JavaScript 구문 검사를 통과했고 production process는 재시작하지 않았다.
- AISFOR network worker가 매분 최대 250개 chunk와 80개 원본을 `readFileSync` Buffer로 해시해 private memory가 약 2 GiB까지 치솟고 event-loop p95가 약 8.7초로 관측된 경로를 찾았다. 반복 hash를 256 KiB streaming으로 변경하고 64 MiB 합성 hash/event-loop self-test를 통과했으나 production process는 재시작하지 않아 아직 미활성이다.

정본 상세 증거는 `docs/resilience/09`부터 `38` 및 각 `evidence/*.json`에 있다. 3-WAN read-only continuity, stable-origin·data-replica 입력 gate, passive fleet process, 합성 Mongo failover와 Socket shared bus는 성공했지만 실제 stable ingress와 production data replica가 없으므로 상시 production continuity를 뜻하는 `currentContinuity`는 false다.

남은 live gate:

1. Quick Tunnel 개발용 임시 주소가 아닌 stable HTTPS 443 PC relay/bootstrap origin 최소 3개와 공개 인증서 준비
2. physical Android에서 live signed bundle 수신·Ed25519 native 검증
3. 최소 3개의 독립 authenticated bootstrap/peer discovery 경로
4. Web/TWA용 다중 HTTPS app-shell/origin 경로
5. Mongo/Redis/session/upload와 background worker fencing을 포함한 production data/write HA rehearsal
6. 별도의 명시적 outage window에서 메인 서버 격리 E2E

UPnP canary는 실행 후 안전 회수됐고 생존 증명에는 실패했다. 메인 outage rehearsal은 여전히 별도 승인 대상이며 outbound overlay가 준비되기 전에는 실행하지 않는다.

## 1. 사용자의 최종 목표

현재 메인 서버가 셧다운되거나 물리적으로 사라지고, 최초 개발자가 장기간 운영에 참여하지 못하더라도 다음 앱과 시스템이 가능한 범위에서 계속 운영되거나 다른 노드에서 복구되어야 한다.

- AISFOR
- AISTALK
- AISGROUP
- AISMALL
- PLAI Sharing 및 연결 서비스
- PLAIS Chain, RPC, Explorer 및 서비스 증명 연동

사용자가 원하는 핵심은 코인 발행주체를 형식적으로 없애는 것이 아니라 **현재 연결된 PC들이 서비스·저장·RPC·복구 역할을 나누어 맡아 단일 메인 서버 장애를 견디는 구조**다.

이 작업은 기존 시스템을 교체하거나 한 번에 재구축하지 않는다. 현재 서버를 `Primary A`로 유지하고 보조 PC를 추가하는 additive migration으로 진행한다.

초기 목표:

- RPO: 최대 데이터 손실 5분 이내
- RTO: 메인 서버 장애 후 30분 이내 복구
- 1차 운영 모드: `ACTIVE_PASSIVE`
- 검증 후 목표 운영 모드: 역할별 `ACTIVE_ACTIVE`

## 2. 중요한 개념 경계

- 분산 시스템: 여러 노드가 데이터와 처리를 나누는 구조
- 서비스 생존성: 특정 서버 또는 운영자가 없어도 복구·운영 가능한 구조
- 탈중앙화: 한 사람이 네트워크를 단독 통제하지 못하는 구조
- 무허가형: 누구나 승인 없이 consensus에 참여 가능한 구조

이번 작업의 1차 목표는 서비스 생존성이다. 모든 PC를 자동으로 validator로 만들거나 Bitcoin형 무허가 consensus로 바꾸는 작업이 아니다.

Storage/sync node, service replica, RPC node와 QBFT validator는 서로 다른 역할이다. PC가 storage node라고 해서 validator 권한을 자동으로 얻어서는 안 된다.

## 3. 절대 유지할 안전 경계

- 기존 Primary 서비스와 DB를 준비 없이 중단하지 않는다.
- 기존 공개 도메인의 목적지를 준비 없이 변경하지 않는다.
- 기존 chain ID `20260718`, canonical genesis, 블록 이력을 변경하지 않는다.
- 동일 validator private key를 두 PC에서 동시에 실행하지 않는다.
- validator set 변경, 키 전달, validator 시작은 기존 명시적 승인 gate를 우회하지 않는다.
- 공개 RPC/API, 외부 전송, 운영자 서명 잠금을 해제하지 않는다.
- 사용자 명시적 승인 없이 실제 코인 전송, 토큰 선판매 또는 production transaction을 만들지 않는다.
- `.env`, Firebase service account, validator key, seed, 복구문구, API secret를 문서·소스·로그에 출력하지 않는다.
- 기존의 광범위한 dirty worktree를 정리하거나 덮어쓰지 않는다. 관련 없는 사용자 변경을 그대로 보존한다.
- 공개 IPFS나 public chain에 채팅 원문, 개인정보, 비공개 업로드를 저장하지 않는다.
- Active-Active 준비 전 두 서버에서 background reward, 정산, push, deletion job을 동시에 실행하지 않는다.

상장 준비의 기존 정본 문서도 함께 준수한다.

```text
D:\aisfor-chain\docs\listing\00-LISTING_RESUME_HANDOFF_KO.md
```

## 4. 2026-08-04 읽기 전용 조사에서 확인한 현재 기반

### PC Sync/Gateway에 이미 존재하는 기능

활성 소스 `E:\aisfor\pc-sync\sync.js`에는 다음 기반이 이미 있다.

- PC gateway 기본 활성화 설정
- `/gateway/health`
- 파일·청크 목록과 제공
- decentralized manifest 캐시와 제공
- gateway 등록
- node 등록과 heartbeat
- storage chunk 저장·검증·복구 task
- 서명된 client update manifest 검증

따라서 PC 노드 계층은 새로 작성하지 말고 기존 gateway·chunk·heartbeat 패턴을 확장한다.

### QBFT 독립 PC 이전 기반

`D:\aisfor-chain\docs\CANONICAL_VALIDATOR_MIGRATION.md`와 관련 script에 다음이 준비돼 있다.

- canonical genesis와 chain ID를 유지하는 validator host migration
- 네 개 validator identity의 독립 LAN/VPN PC 배치
- 최소 3/4 quorum 유지
- 동일 validator key 중복 실행 금지
- pre-sync와 activation 승인 분리
- validator에서는 P2P만 노출하고 RPC는 별도 노드에 유지

이 절차를 서비스 replica 작업과 혼동하지 않는다. 일반 PC service/storage node를 validator로 자동 승격하지 않는다.

### 웹서비스의 현재 공통 장애점

읽기 전용 `pm2 list` 기준 핵심 Node.js 웹서비스가 현재 Windows 서버 한 대에서 주로 `fork` 단일 프로세스로 실행된다. 이 서버가 공통 failure domain이다.

코드 조사 결과:

- AISFOR, AISTALK, AISGROUP는 MongoDB 기반 세션을 사용한다.
- AISMALL은 Redis session을 사용하지만 Redis 실패 시 MemoryStore로 fallback한다.
- AISTALK, AISFOR, AISMALL은 Socket.IO를 사용하지만 서버 간 Redis adapter는 확인되지 않았다.
- AISFOR, AISTALK, AISGROUP, AISMALL, PLAI Sharing은 로컬 upload/media 경로를 사용한다.
- PLAI Sharing은 Mongo persistence와 별도로 실행 중 in-memory post cache를 가진다.
- 일부 서비스와 SSO 경로는 단일 public base URL에 의존한다.
- AISTALK와 PLAIS Chain에는 health endpoint가 있다. 다른 서비스는 통일된 readiness/liveness 규약이 필요하다.

실제 운영 DB URI나 secret 확인을 위해 `.env` 내용을 출력하지 않는다. 연결 구조는 secret을 마스킹한 별도 진단으로 확인한다.

## 5. 목표 역할 모델

연결된 PC마다 하드웨어, 가동률, 네트워크와 신뢰수준에 따라 하나 이상의 역할을 부여한다.

| 역할 | 기능 | 쓰기 권한 | 초기 자동 승격 |
|---|---|---:|---:|
| Gateway node | health, endpoint discovery, reverse proxy | 제한 | 가능 |
| Service standby | Node.js 서비스 복제본 | Passive | 가능 |
| Storage node | 암호화된 파일·청크 복제와 복구 | 해당 chunk만 | 가능 |
| Mongo secondary | DB replica 및 선출 후보 | Replica set 정책 | 제한 |
| Redis replica | session·Socket.IO 상태 복제 | Redis 정책 | 제한 |
| RPC/full node | canonical chain read 및 제한된 submission | 투표 없음 | 가능 |
| Validator | QBFT consensus voting | consensus | 자동 금지 |
| Backup/archive node | 암호화 snapshot과 release 보존 | 복구 전용 | 가능 |

한 PC에 모든 역할과 모든 키를 몰아넣지 않는다. 최소 세 개의 서로 다른 failure domain을 목표로 한다.

## 6. 목표 구조

```text
Android/Web Apps
       |
       | signed endpoint manifest + built-in fallback list
       v
Gateway A  ---- Gateway B ---- Gateway C
   |               |              |
Primary A      Standby B      Standby C
   |               |              |
   +------ Mongo replica set ------+
   +------ Redis/SIO shared bus ----+
   +------ encrypted object data ---+
                   |
             RPC/full nodes
                   |
        independent QBFT validators
```

초기에는 Gateway가 Primary A에만 쓰기 트래픽을 보낸다. Standby B/C는 health와 복제만 수행한다. 수동 failover가 통과한 뒤 자동 failover를 허용한다.

## 7. 구현 단계

### Phase 0 — 무변경 인벤토리와 failure-domain map

- 모든 서비스, 프로세스, 포트, domain, DB, upload, cron/background job, 외부 provider 목록화
- secret 값은 수집하지 않고 secret의 존재·소유자·복구절차만 기록
- PC node별 CPU, RAM, disk, OS, uptime, LAN/VPN address, NAT, 운영자 독립성 기록
- 서비스별 RPO/RTO와 개인정보 등급 결정
- 현재 백업의 복원 가능성 확인

산출물:

```text
docs/resilience/01-FAILURE_DOMAIN_INVENTORY_KO.md
docs/resilience/evidence/inventory-redacted.json
```

### Phase 1 — 백업과 독립 복원시험

- Mongo logical backup과 가능하면 filesystem snapshot 병행
- upload/media/download package 암호화 백업
- source와 release artifact의 signed manifest 생성
- 격리된 PC에 복원해 서비스가 기동되는지 확인
- 복원시험 전 production traffic을 연결하지 않음

### Phase 2 — Passive PC service node

- 기존 배포물을 재현 가능한 node package로 작성
- 기존 PC Sync의 서명 update·gateway 패턴 재사용
- Standby에서 health/readiness만 노출
- write job, reward, settlement, push worker는 fence 상태 유지
- Primary와 같은 DB에 무제한 연결하지 않음

### Phase 3 — 데이터 계층 복제

- MongoDB 3-node replica set 설계와 rehearsal
- AISMALL Redis MemoryStore production fallback 제거 계획
- Redis Sentinel/Cluster 또는 동급 HA 구성
- 초기 local upload 단방향 복제
- 검증 후 encrypted object storage abstraction 적용
- data checksum과 restore proof 기록

Standalone Mongo를 replica set으로 바꾸는 실제 작업은 짧은 계획정지와 rollback plan이 준비된 후에만 한다.

### Phase 4 — 수동 Active-Passive failover

- Gateway health check가 실패해도 처음에는 자동 승격하지 않음
- operator가 Primary write fence를 확인한 후 Standby 승격
- split-brain 방지 lease/fencing 구현
- 중복 reward, push, settlement, deletion 여부 검사
- 앱 reconnect, session 유지, media 접근, chain proof 제출 확인

### Phase 5 — 앱 endpoint 생존성

- 기존 production domain을 1순위로 유지
- Android/Web에 최소 2개 fallback endpoint 추가
- offline public key로 검증하는 signed endpoint manifest 도입
- DNS와 manifest가 모두 실패할 때 built-in endpoint list 사용
- 악성 PC가 endpoint를 위조하지 못하도록 node identity와 manifest signature 검증

### Phase 6 — 역할별 Active-Active

- Socket.IO Redis adapter
- shared session store
- object storage
- idempotency key와 distributed leader lease
- background worker 단일 리더 또는 partitioned ownership
- load balancer와 WebSocket 정책

### Phase 7 — 운영자 소멸 대응

- 복수 관리자와 법적 승계 절차
- 2-of-3 또는 3-of-5 운영승인
- domain, app store, Firebase, cloud, backup 복구계정 분산
- 비상 예산과 자동결제
- 신규 운영자가 문서만 보고 복구하는 분기별 훈련

## 8. 첫 작업에서 반드시 확인할 단일 장애점

1. 모든 public domain이 같은 Nginx/서버/IP에 종속되는가
2. MongoDB가 같은 물리 서버의 standalone인가
3. Redis가 같은 물리 서버에 있고 AISMALL이 MemoryStore로 fallback하는가
4. upload, download, APK, source release가 로컬 디스크에만 존재하는가
5. Socket.IO room/event가 process memory에만 존재하는가
6. AISFOR identity/SSO가 단일 service endpoint인가
7. cron, reward, push, cleanup worker가 여러 노드에서 중복 실행될 수 있는가
8. Firebase, Play Console, DNS, SSL, PM2, Windows 관리자 계정을 한 사람만 보유하는가
9. PC gateway가 중앙 AISFOR server 없이 서로를 발견하고 signed manifest를 검증할 수 있는가
10. 현재 네 개 validator가 메인 웹서버 소멸 뒤에도 3/4 quorum을 유지하는가

## 9. 성공 기준

- Primary 웹서버 접근을 차단해도 30분 이내 Standby에서 핵심 로그인과 조회가 가능하다.
- Mongo primary 장애 후 승인된 secondary가 승격되고 acknowledged data 손실이 목표 RPO 이내다.
- 기존 세션 또는 안전한 재로그인으로 사용자가 복구된다.
- 사진·영상·첨부파일이 Standby에서 같은 hash로 제공된다.
- Socket.IO 사용자는 재연결되고 메시지·이벤트가 중복 또는 누락되지 않는다.
- reward, push, settlement, deletion worker가 중복 실행되지 않는다.
- PLAIS canonical chain이 동일 chain ID와 genesis로 유지된다.
- validator key 중복 실행이 없고 최소 3/4 quorum이 유지된다.
- 외부 전송, 운영자 서명, public unlock 잠금이 계속 유지된다.
- 새 운영자가 기존 개발자 도움 없이 문서만으로 격리 복원시험을 통과한다.

## 10. 새 Codex 창에서 사용할 재개 문장

> `D:\aisfor-chain\docs\resilience\00-PLAI_SERVICE_SURVIVABILITY_HANDOFF_KO.md`와 `D:\aisfor-chain\docs\listing\00-LISTING_RESUME_HANDOFF_KO.md`를 먼저 UTF-8로 끝까지 읽고, 현재 메인 서버를 유지한 채 연결된 PC들을 서비스·저장·RPC·복구 노드로 전환하는 작업을 Phase 0부터 이어서 진행해줘. 첫 단계에서는 production 서비스, DB, DNS, 공개 API, 외부 전송, 운영자 서명, validator를 변경하거나 시작하지 말고 읽기 전용 인벤토리와 failure-domain map부터 만들어줘. 기존 PC Sync gateway·chunk·heartbeat와 canonical validator migration 기반을 재사용하고, 관련 없는 dirty worktree는 건드리지 마.
