Files

8.2 KiB
Raw Permalink Blame History

Find-Word v0.2.5 정적 배포 인계

이 문서는 Neo가 검토 후 수행할 절차다. Codex는 서버, DNS, 인증정보에 접근하지 않았고 배포·서비스 생성·Git commit/push도 하지 않았다.

산출물

Node.js 최소 22.22.2 (>=22.22.2)의 지원 LTS 환경에서 npm ci, npm run lint, npm test, npm run build를 실행한다. dist/ 전체를 하나의 릴리스로 전달한다. dist/audio/의 24kHz neural WAV 101개와 version 0.2.5 manifest가 반드시 포함되어야 한다. dist/ambience/의 고유 현장 WAV 8개·manifest와 dist/ambience/AMBIENCE_NOTICES.md도 필수다. 런타임은 Nginx 정적 파일만 필요하며 Node 서버·TTS 엔진·DB·환경변수·API 키는 필요 없다. 잠긴 jsdom 계열 의존성 때문에 24.x는 24.15.0 이상, 26.x는 26.0.0 이상이어야 한다. 브라우저 검증의 Chromium sandbox는 기본 활성화다. sandbox를 지원하지 않는 격리된 개발 환경에서만 PLAYWRIGHT_NO_SANDBOX=1로 명시적으로 끈다.

Canonical repository는 OZ-Group/Find-Word다. 프로젝트 자체는 private / all-rights-reserved이며 LICENSE를 따른다. 생성 음성은 프로젝트의 독점 권리 주장 대상이 아니며 provider 조건은 AUDIO_PROVENANCE에 기록한다. React, ReactDOM, scheduler의 MIT 전문을 담은 dist/THIRD_PARTY_NOTICES.md도 반드시 배포한다. build 검증기는 고지 파일이 없거나 축약·변조되면 실패한다.

현재 앱은 도메인 루트(/) 배포 기준이다. 하위 경로 배포 시 Vite base뿐 아니라 음성 URL도 함께 변경하고 테스트해야 한다. 예정 도메인은 findword.heart-m.com이다.

Nginx 예시

아래 root는 예시다. 실제 경로·기존 서버 블록·인증서는 Neo가 확인한다. 기존 서비스 설정을 덮어쓰지 않고 검토 후 적용한다.

# 정적 릴리스 디렉터리를 가리킨다. 인증서와 HTTPS 설정은 운영자가 별도 추가한다.
server {
    listen 80;
    server_name findword.heart-m.com;
    root /var/www/findword/current;
    index index.html;

    # 기본 MIME 정의로 JS/CSS/WAV가 올바른 타입으로 제공되게 한다.
    include /etc/nginx/mime.types;
    add_header X-Content-Type-Options nosniff always;
    add_header Referrer-Policy no-referrer always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; media-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;

    # 파일명이 해시로 바뀌는 번들만 장기 캐시한다.
    location /assets/ {
        try_files $uri =404;
        expires 1y;
    }

    # 앱은 intro·목표 모두 같은 자산 버전 query를 붙여 이전 캐시와 구분한다.
    # $uri는 query를 제외한 실제 WAV 경로다. 누락 시 index.html 대신 404로 응답한다.
    location /audio/ {
        try_files $uri =404;
        expires 7d;
    }

    # 현장음도 누락 시 SPA HTML로 대체하지 않는다.
    location /ambience/ {
        try_files $uri =404;
        expires 7d;
    }

    # SPA의 직접 진입·새로고침을 index.html로 받되 HTML은 재검증한다.
    location / {
        try_files $uri $uri/ /index.html;
        expires -1;
    }
}

인수 확인

  1. 서버에 적용하기 전 nginx -t, 기존 서비스 충돌, 파일 읽기 권한을 확인한다.
  2. TLS/HTTPS와 DNS를 운영자가 확인한다. 실제 도메인에서 시작 후 음성이 들리는지 확인한다.
  3. audio/intro.wav?v=0.2.5와 목표 WAV의 같은 버전 query가 정상 응답하고 존재하지 않는 오디오는 query가 있어도 404인지 확인한다.
  4. 모바일 Safari/Chrome, 데스크톱에서 음량·중단·다시 듣기·3문항 완주·다음 난이도·시작 단계·SNR 변경·중도 종료를 직접 확인한다.
  5. 원자적으로 릴리스 디렉터리를 전환하고 이전 디렉터리를 보관해 되돌릴 수 있게 한다.

오프라인 캐시를 제공하는 PWA는 아니다. 정적 자산의 최초 로드에는 해당 서버 연결이 필요하다. HTML은 재검증하고, 오디오는 URL의 자산 버전으로 구분한다. 같은 파일명으로 WAV를 교체할 때 src/audio/assets.ts의 AUDIO_ASSET_VERSION도 갱신한다. 제품 버전을 유지하는 음성 수정에서도 새 자산 버전이 필요하다. 이 query는 로컬 정적 파일 요청에만 사용하며 런타임 외부 요청을 추가하지 않는다.

0.2.5 독립 인수와 릴리스 (Neo 수행, 이 작업에서는 미실행)

  1. .agent/RESULT-v0.2.5.md와 RED/GREEN 원문, 원본/배포 해시, 라이선스 고지를 검토한다.
  2. sandboxed system Chrome desktop/mobile suite와 npm audit를 다시 실행한다.
  3. 검토 완료 후 feature branch push, main fast-forward, annotated v0.2.5 tag, fresh-clone readback으로 commit과 자산 해시를 확인한다.
  4. commit-addressed release 디렉터리로 dist를 복사하고 current 심볼릭 링크를 원자 전환한다. 이전 release는 rollback 대상으로 보존한다.
  5. 공개 HTTPS에서 title/UI 0.2.5, WAV MIME·SHA-256·cache-busting query, 누락 자산 404, 시작 단계·3문항 완료→다음 단계·SNR·중도 종료를 실제 Chrome으로 재검증한다.

이 문서의 Nginx 설정은 인계 예시이며 실행 증거가 아니다. 이번 작업은 localhost의 production preview만 사용하며 Git commit/push/merge/tag, 외부 배포, secrets 사용은 하지 않는다.

v0.2.3 리뷰 검증은 .agent/evidence-v0.2.3/review-fixes/에 별도로 보존한다. check-build는 앱 콘텐츠로 구성한 정확히 101개의 음성 파일명과 dist 파일 집합을 독립 대조하므로, manifest와 디렉터리를 함께 축약하거나 추가 WAV를 넣어도 실패한다. 현장음은 승인 계획의 출처 수치와 각 notice 항목의 저작자·primary URL·direct URL·라이선스 링크·outputLicense·변경 고지까지 검사한다. 현장음 notice의 배포 URL은 /ambience/AMBIENCE_NOTICES.md다. 고지는 음원/manifest와 함께 원자 교체하는 같은 디렉터리 안에 있으며, 기존 루트의 notice 사본은 제거했다.

v0.2.5 음원 인수 추가 항목

현재 exact 자산은 Oz의 새 소유자 청취 승인으로 릴리스 gate를 통과한다. 새 market WAV의 동일 faster-whisper/VAD 검사는 1개 segment, requiredEmptyPassed=false인 상태 그대로다. python3 scripts/release_approval.py는 자동 empty-ASR OR 유효한 exact-byte 소유자 승인을 검사하며, 현재 통과 경로는 승인 기록뿐이다. manifest/WAV/notice 또는 검수 ZIP 바이트가 달라지면 이 승인은 유효하지 않다. 법적/privacy clearance는 false다. RESULT와 실패 원문을 확인한다.

  • 수용 계기는 전용 ebur128=peak=true이며 loudnorm input_i의 이전 0.01 LU 주장은 거부한 역사 기록이다.
  • 원본/구간/라이선스와 101 voice bytes는 불변이다. 새 8 WAV의 목표는 −32.5 LUFS ±0.2, spread≤0.4 LU, true peak≤−6 dBTP다. 12초/24kHz/mono/PCM16/50ms fade를 유지한다. 생성기 내부 ceiling은 −6.2 dBTP다.
  • loudness 수치는 ebur128 0.0 LU spread, 독립 pyloudnorm 0.2.0 0.0772 LU spread로 통과했다. 버전·입력 통계·정확한 gain/filter·iterations·최종 ebur128 통계와 독립 측정 hash를 보존한다.
  • 향후 별도로 배포할 때 공개 HTTPS의 109 WAV hash/bytes/MIME와 ?v=0.2.5를 검사하고, 다운로드한 최종 WAV를 새 ebur128 프로세스로 재측정해야 한다.
  • 실제 Chrome의 master=1, SNR −12/0/+12, 8환경 배경 GainNode는 고정 0.41988845여야 한다. voice만 SNR에 반응하며 3문항·다음 단계·재청취·중도 종료를 유지한다.
  • 새 WAV의 Oz 청취 인수 시각은 2026-10-14T11:29:51Z다. 이 인수는 법적/privacy clearance를 제공하지 않는다.
  • 이번 작업에서 commit/push/merge/tag/deploy는 실행하지 않았다. production 검증도 미실행이다.