• LINKS 0.22.1 — 배포 wrapper 기본 흐름·pids_limit 제거·스캔 상태 popover

    LINKS 0.22.1

    이전 릴리스 0.22(a96fbde7d0)부터 최종 소스 5cf5e1f2c3까지의 patch 릴리스입니다. 루트 패키지는 0.22.1, ARCA는 exact 0.1.17(변경 없음)입니다. 기준 schema는 0.22와 같고, 운영 compose.yaml과 배포 wrapper(ops/deploy-registry.sh → NAS update.sh)가 바뀌었습니다.

    업그레이드 주의 — DB 초기화는 필요 없지만, 배포 wrapper·Compose·coordinator·image를 같은 0.22.1 태그로 함께 교체합니다

    기준 schema는 바뀌지 않았습니다(743448f6d2891794e5ba98834d9f5055c3f5c58e22276ed701de36650f4b2b07 유지). 0.22 DB·사용자·패스키·세이브·backup·실행 build를 그대로 사용하며 reset.sh를 실행하지 않습니다. ARCA pin과 coordinator script가 0.22와 같으므로 실행 build 재준비도 필요 없습니다.

    1. pids_limit 제거: 공통 compose.yaml의 byedpi·log-reader·backup에서 pids_limit을 지웠습니다. NAS 커널이 PIDs cgroup을 지원하지 않아 나던 경고가 사라지며, 이제 어떤 service에도 PID 수 제한이 없습니다.

    2. 배포 wrapper는 option을 받지 않습니다: 0.22의 sh update.sh --defer-package-readiness는 Unknown option으로 Docker 호출 전에 거부됩니다. VX/VX Ace(ARCA package) 실행이 기본 구성이므로 wrapper는 1단계에서 Compose가 렌더링한 catalog의 LINKS_RUNTIME_PACKAGE_ENABLED로 LINKS_RUNTIME_PACKAGER_DATABASE_PASSWORD가 비어 있지 않은지 확인하고, 비어 있으면 멈춥니다(shell 변수가 빈 값으로 설정돼 있어도 그 값이 우선합니다). 갱신 뒤에는 항상 미완료 안내와 함께 coordinator 시작과 아래 --package readiness 명령을 안내하며, 그 명령이 종료 코드 0이어야 갱신 완료입니다. 그래서 운영 배포는 coordinator 정지 → 같은 0.22.1 태그의 update.sh·compose.yaml·ops/runtime-package-coordinator.sh 등을 아래 해시로 대조해 함께 교체 → sh update.sh → coordinator 시작 → 출력된 명령 실행의 단일 절차입니다(운영 가이드 운영 배포).

      cd /volume1/docker/links
      docker compose --env-file '.env.production' exec -T catalog node apps/worker/dist/runtime-readiness-command.js --package
      
    3. 스캔 상태 상세 위치 변경(관리자 UI): 우측 하단 고정창·header 아래 흐름 배치였던 스캔 상태 상세가 상단바 스캔 표시기의 hover·키보드 초점·탭 popover로 바뀌었습니다. 데이터·API 변경은 없습니다.

    원본 game library는 읽기 전용으로 유지하며 변경하지 않습니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.

    운영 배포

    • compose.yaml에서 pids_limit: 64 세 곳을 삭제했습니다. 보안 격리 정책과 운영 가이드 요구 사항에 "공통 Compose의 어떤 service에도 pids_limit을 선언하지 않는다"를 적었습니다. develop·test·backup-verify Compose에는 원래 없었습니다.
    • 배포 wrapper 기본 흐름:
      • 인자는 환경 파일 하나뿐이며 -로 시작하는 인자는 모두 거부합니다(--defer-package-readiness 포함). 두 번째 환경 파일도 거부합니다.
      • [1/5]에서 compose config 렌더링 결과를 출력하지 않고 변수로만 받아, packager 비밀번호로 파생되는 LINKS_RUNTIME_PACKAGE_ENABLED가 "true"인지로 판정합니다. 따옴표·주석·export·interpolation·CRLF·마지막 중복 값은 Compose 해석을 그대로 따르며, 이 단계에서 실패하면 Docker 호출은 config 하나뿐입니다. 형식이 잘못된 env 줄은 Compose 자체 오류(stderr)에 그 내용이 포함될 수 있습니다.
      • up --wait 뒤 catalog의 package 기능이 켜졌는지 다시 확인하고, 아니면 같은 release의 compose.yaml을 쓰라는 오류와 rollback digest를 출력합니다.
      • [5/5]는 coordinator가 정지한 상태를 전제로 stage·build readiness만 확인합니다. 성공하면 "NOT complete" 안내, 배포 디렉터리에서 실행할 정확한 --package 명령(환경 파일 경로 인용), 실패 시 이전 coordinator script·compose.yaml·image digest를 함께 되돌리는 안내를 출력합니다.
      • LINKS_REGISTRY_TAG가 CRLF 환경 파일에 있을 때 rollback 안내가 깨지던 결함을 고쳤습니다.
    • 배포 wrapper 기록기(tests/scripts/check-deploy-registry.mjs)를 27개 사례로 다시 썼습니다. 성공 경로·실패 경로·Docker 호출 0 거부, 비밀번호 판정(shell 빈 값·따옴표 빈 값과 주석·export·CRLF·중복 마지막 값·interpolation 등), 출력된 --package 명령을 그대로 실행해 coordinator 전 exit 1·heartbeat 뒤 exit 0, 모든 출력에 합성 비밀 표식이 없음을 단언합니다. mock의 dotenv 해석은 같은 13개 입력을 실제 Docker Compose 렌더링과 대조했습니다.
    • RED 보존: 0.22 script는 같은 기록기에서 27개 중 19개, 수정 중간판은 16개 실패했고, 렌더링 결과를 출력하는 변형도 16개 실패해 비출력 단언이 동작함을 확인했습니다.
    • 운영 가이드의 운영 배포를 coordinator를 포함한 하나의 5단계 절차로 다시 썼고, NAS ARCA package coordinator에서 option 언급을 지우고 비밀번호가 운영 필수임을 적었습니다. .env.example의 비밀번호 주석도 같은 규칙으로 맞췄습니다.

    관리자 UI — 스캔 상태 표시기

    • 상단바의 스캔 표시기 하나만 상시 보입니다(관리자 전용, 이전 상태창과 같은 노출 조건). 진행 중 스캔 중 · <단계>, 중단 요청 뒤 스캔 중단 요청됨, 끝난 뒤 닫기 전까지 스캔 완료·스캔 실패·스캔 중단됨을 표시하고 tone은 기존 token만 씁니다.
    • 상세는 표시기의 popover(role=dialog)로 엽니다.
      • 마우스: hover로 열고, 표시기와 popover를 벗어난 뒤 150ms가 지나면 닫힙니다(그 사이 재진입하면 유지).
      • 키보드: :focus-visible 초점일 때만 열고 초점이 밖으로 나가면 닫습니다. Escape는 닫고 초점을 표시기로 돌리며, Enter/Space로 다시 엽니다. 페이지 입력란에 초점이 있으면 초점을 빼앗지 않고 닫기만 합니다.
      • 터치: 탭으로 toggle하고 바깥을 탭하면 닫습니다.
    • 끝난 scan은 닫기 전까지 완료 상태를 유지합니다. 닫기는 열림 이유와 대기 중인 hover timer를 모두 버리고 표시기를 지운 뒤 초점을 본문으로 옮깁니다. 다음 scan 요청 때 popover가 저절로 열리지 않습니다.
    • popover의 경과 시간은 열려 있는 동안만 1초마다 갱신합니다. 닫힌 동안 interval이 없고, 다시 열면 현재 시각에서 바로 계산합니다.
    • 접근 이름은 보이는 문구를 따릅니다. 표시기 버튼과 관리자에서 보기에는 aria-label이 없고, 닫기는 dialog 제목 문맥의 보이는 닫기입니다. live region은 표시기 버튼만 감싸므로 경과 시간과 열림·닫힘은 낭독되지 않습니다.
    • popover는 sticky header 안에 배치되어 header 바로 아래에서 viewport 안에 들고, 관리자 탭·스캔 옵션 메뉴 위에 그려지며, 320–1440px·글자 200%에서 가로 넘침이 없습니다.
    • 우측 하단 고정창, header 아래 흐름 slot·spacer, 접기 toggle과 관련 CSS·layout 변수를 삭제했습니다.
    • browser check 행렬을 교체했습니다. catalog-browser-check는 표시기·hover·이탈·키보드·Escape·scroll·좁은 폭·터치·닫기, 다음 요청에서 닫힌 상태 유지와 1초 interval 수를 확인하고, library-browser-check는 홈·라이브러리·상세 화면의 popover 노출을 확인합니다. 통합 runner도 표시기 hover와 popover로 바꿨습니다.

    문서·검증 갱신

    • 운영 가이드: 운영 배포 단일 절차, wrapper 1단계 판정, 최종 readiness 명령 블록(배포 디렉터리에서 실행), 관리자 scan 절차의 상단바 표시기 안내.
    • 완료 기준선·tests README: 기록기 27건과 RED 수치, mock 한계, 표시기 검증 범위(unit은 reducer/helper·static markup, 실제 mount는 browser check).
    • 보안 격리 정책: PIDs 제한 없음.

    검증과 남은 범위

    • PASS — pids 브랜치(병합 3990d18): compose config --profile '*' 4조합(compose / +develop / +test / +develop+test) 종료 코드 0과 렌더링 pids_limit 0건, 배포 wrapper 기록기 27개 사례, run-foundation(격리 Compose, PIDs 경고 0건), static, 문서 검사, git diff --check.
    • PASS — scanfloat 브랜치(병합 e0520c1과 같은 tree, main 3990d18 반영 뒤): apps/web unit 38개 파일 / 167개 테스트, static, catalog-browser-check Chromium·Firefox × 글자 100%·200%, library-browser-check Chromium·Firefox, run-catalog-browser, 문서 검사, git diff --check. 수정 전 표시기로 같은 check를 돌려 기대대로 실패하는 RED도 보존했습니다. personal-library·admin-operations·background-jobs browser check는 대상 표면이 바뀌지 않아 1차 수정(b635239)의 PASS를 유지합니다.
    • PASS — 최종 0.22.1 소스: 릴리스 커밋 두 개(root version, 완료 기준선 version 문구) 뒤 문서 검사(747개 파일 / Markdown 30개, mount 6개 / 29개 문서 파일), static과 git diff --check를 다시 통과했습니다. 게시 이미지는 같은 최종 소스에서 build했고 image 안의 root version 0.22.1·ARCA 0.1.17을 확인했습니다.
    • PARTIAL — 전체 UI/제품 acceptance: 화면·fixture·package/build 성공을 실제 browser play PASS로 기록하지 않습니다.
    • NOT RUN: 실제 library/private game과 실제 library scan, 입력·오디오·save/reload의 실제 게임 acceptance, NAS 설치 Compose의 렌더링·dotenv 해석과 BusyBox sh에서의 wrapper 실행, 실제 registry pull·container 교체·coordinator 교체 중 --package readiness, 실제 모바일 기기·보조 기술 낭독, live provider, fresh schema 테스트(schema 변경 없음), 개발 rebuild와 NAS/production 배포.

    배포 이미지와 파일

    • Git annotated tag: 0.22.1, 최종 소스 5cf5e1f2c3.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:0.22.1 = git.2ex.dev/hanyul/links:latest.
    • 원격 digest: sha256:f78426e91a2c221f33fa02eed518d824ad8e5ac499f1470c0df10f2e0f2a0902.
    • 아래 SHA-256은 checkout의 CRLF 변환본이 아닌 0.22.1 태그의 Git blob 원본 byte 기준입니다. NAS 배포 목록은 앞의 6개이며, reset-registry.sh는 전체 초기화 때만, .ps1은 Windows 개발 coordinator입니다. 0.22 대비 바뀐 파일은 **compose.yaml**과 ops/deploy-registry.sh(NAS update.sh) 두 개이고 나머지는 0.22와 byte 동일합니다.
    SHA-256 파일 0.22 대비
    cce561572e41f26fe368814c190423a8b48364ed231a35b20119964062411480 compose.yaml 변경 (pids_limit 제거)
    6e1fd3f2f73faee52abca28c8552cde417f496d86fc3d78c7001dec480e171a3 infra/docker/Caddyfile 동일
    39a4c55050e76043c8ca70f11f59dbdf08fff7ef38c1f1ec878f96194988d9d8 ops/backup-verify.compose.yaml 동일
    9872d5e5ae4046915625e76dbbe8cb750ff42fb7396563826f56c4f305bfc128 ops/deploy-registry.sh 변경 (option 없음, packager 비밀번호 필수)
    89375a986b3cb64cf74145541701b32c6a0e983a72ca46be21a8bcfad7beaa3d ops/backup-registry.sh 동일
    79c5fbd082ada3117e0915af76c714ed498ea018f151a998cd23f53d92fc3530 ops/runtime-package-coordinator.sh 동일
    84bcc60de28de692fba4d7bea16bf008a8ac55abe394e26f87e541abf5db52dc ops/reset-registry.sh 동일
    0593ef6347103a9ceffb65969c63794ce6ab6f5321e094a7681b61f54ca19104 ops/runtime-package-coordinator.ps1 동일
    cce561572e41f26fe368814c190423a8b48364ed231a35b20119964062411480  compose.yaml
    6e1fd3f2f73faee52abca28c8552cde417f496d86fc3d78c7001dec480e171a3  infra/docker/Caddyfile
    39a4c55050e76043c8ca70f11f59dbdf08fff7ef38c1f1ec878f96194988d9d8  ops/backup-verify.compose.yaml
    9872d5e5ae4046915625e76dbbe8cb750ff42fb7396563826f56c4f305bfc128  ops/deploy-registry.sh
    89375a986b3cb64cf74145541701b32c6a0e983a72ca46be21a8bcfad7beaa3d  ops/backup-registry.sh
    79c5fbd082ada3117e0915af76c714ed498ea018f151a998cd23f53d92fc3530  ops/runtime-package-coordinator.sh
    84bcc60de28de692fba4d7bea16bf008a8ac55abe394e26f87e541abf5db52dc  ops/reset-registry.sh
    0593ef6347103a9ceffb65969c63794ce6ab6f5321e094a7681b61f54ca19104  ops/runtime-package-coordinator.ps1
    
    Downloads 2