-
hanyul released this
2026-10-11 21:52:47 +09:00 LINKS 1.0.3
이 patch 릴리스는 이전 릴리스 1.0.2(
4c4a5d3715)부터 최종 소스5e262a8dde까지를 묶었습니다. 루트 패키지는 1.0.3이고 ARCA pin은 exact 0.1.18로 그대로입니다. 주요 변경은 세 가지입니다. VX/VX Ace 원본 봉인을 stager 계정 one-shot으로 바꿔LINKS_RUNTIME_STAGER_UID/GID가 10001이 아닌 NAS에서도 package가 동작합니다. package·저장소 권한 실패가 구체 code와 원인 code로 표시됩니다.update.sh는 배포 파일 SHA-256 대조 없이 release tag의 파일을 HTTPS로 받습니다. schema는 바뀌지 않았으므로 DB 초기화와 migration이 필요 없습니다.업그레이드 주의: 1.0.2 → 1.0.3은
update.sh를 한 번만 직접 받습니다(초기화 없음)- 1회 전환: 1.0.2의
update.sh는 release assetdeploy-files.sha256을 요구합니다. 1.0.3부터는 이 asset이 없으므로, 설치된 1.0.2update.sh를 그대로 실행하면 아무것도 바꾸지 않고Release 1.0.3 does not support automatic updates; follow the manual procedure in the operations guide.한 줄로 멈춥니다. 배포 디렉터리에서 아래 명령으로 새update.sh를 한 번 받아 실행합니다. 이후 갱신은sh update.sh한 줄입니다. 1.0.2의 coordinator는 이미 Compose service이므로 host coordinator 종료 같은 추가 작업은 없습니다. - schema 변경 없음, backup 선택: 기준 schema(
infra/migrations/base.sha256)는 1.0.2와 같고 migration은 0개입니다.reset.sh를 실행하지 않습니다. 이번 갱신 전 backup(sh backup.sh)은 선택입니다. - VX/VX Ace 원본 봉인 계정: 원본 봉인(seal)이 package worker(10001)가 아니라 stager 계정(
LINKS_RUNTIME_STAGER_UID:GID)의 one-shot Compose serviceruntime-package-stager에서 실행됩니다. 그래서 stager 계정이 10001이 아닌 NAS(예: 1026:100)에서도 VX/VX Ace 준비가 동작합니다. 운영자 추가 작업은 없습니다. 새 service는 package worker와 같은 image를 쓰고update.sh가 설치하는compose.yaml·coordinator script에 들어 있습니다. 이미 stager 계정 소유인 sealed store와 MV/MZ 입력을 그대로 씁니다. 단 sealed store 전체가 stager 계정 소유여야 합니다(혼재 소유는 지원하지 않습니다). 1.0.2에서 실패로 끝난 VX/VX Ace 준비(RUNTIME_PREPARATION_FAILED, MV/MZ 준비가 먼저 있던 store에서는SEALED_INPUT_INVALID로도 끝납니다)는 화면의다시 시도로 다시 요청합니다. 관리자는빌드 재생성도 쓸 수 있습니다. - 구체 실패 code: package·저장소 권한 실패가 화면과 버그 신고에 구체 code(
RUNTIME_STORE_PERMISSION_DENIED등)와 경로 없는 원인 code(EACCES·EPERM·EROFS등)로 표시됩니다. 이전에는RUNTIME_PREPARATION_FAILED나ARCA_PACKAGE_FAILED로 뭉뚱그려졌습니다. - 배포 파일 SHA-256 대조 제거:
update.sh는 더 이상deploy-files.sha256asset을 받거나 배포 파일 hash를 대조하지 않습니다. 배포 파일의 무결성은 HTTPS 전송(최초 URL과 redirect 모두 HTTPS만)과 Git release tag에 맡깁니다. 서명 인증은 없습니다. 1.0.3 릴리스에는 asset이 없습니다. 1.0.2의 기존 asset은 1.0.2update.sh가 쓰므로 그대로 둡니다. - NAS host Compose 2.20.1: 릴리스 전에 격리
docker:24.0.2-dind의 host Compose를 공식 Docker Compose v2.20.1 binary(release의 게시 checksum으로 확인)로 바꿔 이 전환을 검증했습니다. 1.0.2 설치 → 1.0.2update.sh의 무변경 중단 → 1회curl전환 → VX Ace 준비 → 재-update까지 모두 성공했습니다(아래 검증). Synology build(v2.20.1-6047-g6817716)의 자체 패치와 공식 binary는 다를 수 있으므로 실제 NAS 결과는 확인 전입니다.
NAS 절차(1.0.2에서 한 번):
cd /volume1/docker/links curl -fsSL https://git.2ex.dev/hanyul/LINKS/raw/tag/1.0.3/ops/deploy-registry.sh -o update.sh sh update.sh성공하면 단계 표시 6줄 뒤에
Updated to 1.0.3 (catalog 6420862bb806), runtime.package ready.가 출력됩니다. 실패하면 원인 한 줄을 출력하고 nonzero로 끝납니다. 이후 갱신은cd /volume1/docker/links && sh update.sh입니다.원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.
VX/VX Ace 원본 봉인의 stager 계정 분리
- coordinator의 한 attempt는 이제 seal → stage → Builder → publish 순서입니다. seal은 새 one-shot service
runtime-package-stager가 실행합니다. 계정은LINKS_RUNTIME_STAGER_UID:GID이고group_add10001, network는backend입니다. 원본 library는 read-only로, sealed store는 쓰기로 mount하며 package·artifact·RTP 저장소는 mount하지 않습니다. - stage를 실행하는 package worker(10001)는 sealed store를 read-only로 mount합니다. sealed store를 쓰는 계정은 MV/MZ의
runtime-stager와 같은 stager 계정 하나입니다. - 봉인된 파일은 0444, 디렉터리는 0555이며 Builder 계정(10001)이 읽고 탐색할 수 있습니다.
package 실패 원인 노출
- sealed store 자체의 파일 작업이 단계 계정에 거부되면 준비는
RUNTIME_STORE_PERMISSION_DENIED(재시도 불가)로 끝납니다. 버그 신고 진단에는 경로 없는 cause(EACCES·EPERM·EROFS)가 남습니다. root·.staging·하위 디렉터리, 봉인 metadata·payload 파일 읽기 거부가 모두 이 code로 분류됩니다. - package 실패는 원본·staging·공간 원인을
ARCA_PACKAGE_FAILED로 덮지 않고 원래 code로 기록합니다. 작업 기록의error_detail은 경로 없는 형식을 유지합니다.
SHA-256 없는
update.sh- 1단계는 최신 release tag의
ops/deploy-registry.sh를 먼저 받습니다. 이 파일이 없거나(HTTP 404) 자동 갱신 표식 줄# links-auto-update: 2가 없으면(1.0.2 이하) 나머지를 받지 않고 자동 갱신 미지원으로 멈춥니다. - 7개 파일은 각각 curl이 성공하고 비어 있지 않아야 합니다. 하나라도 받지 못하거나 비어 있으면 받은 파일을 모두 지우고, 기존 파일과 container를 바꾸지 않은 채 멈춥니다. 내용이 같은 파일(
cmp)은 교체하지 않습니다. - 이전 실행이 남긴
.tmp(1.0.2의deploy-files.sha256.tmp포함)는 모든 모드에서 시작할 때 지웁니다. - 자동 갱신 미지원 release(1.0.2 이하)를 설치하거나 그 release로 되돌릴 때의 수동 절차는 SHA-256 대조 없이 7개 파일을 모두 받은 뒤에만 교체합니다.
문서
- 운영 가이드: 1.0.2에서의 전환,
update.sh1단계·실패 메시지, release 절차(asset 없음), 수동 절차, Stager 계정과 저장소 권한,RUNTIME_STORE_PERMISSION_DENIED복구. - AGENTS.md(배포 파일 SHA-256 금지), API 계약, 보안 정책, 아키텍처, 런타임 계약, 완료 기준선, 개발 계획, tests/README, README도 갱신했습니다.
알려진 제한(후속 과제)
/artifacts쓰기 거부는 이번에 바꾸지 않았고 기존 분류를 따릅니다.- load 뒤에 권한이 바뀌면
ARTIFACT_INVALID로 끝납니다. - 소유 계정이 섞인 sealed store는 지원하지 않습니다. sealed store 전체가 stager 계정 소유여야 합니다.
- 실제 NAS에서의 실행은 NOT RUN입니다.
- 1.0.2와 같은 제한:
- Docker 24 graphdriver에서는 Builder config digest를 pin과 직접 대조하지 않습니다(ARCA 후속).
- 3단계 이후 실패하면 coordinator는 정지된 채 남습니다. 원인을 고친 뒤 다음
sh update.sh가 다시 기동합니다. - Player 세이브 관리 listener(3005)는 catalog caller token으로만 보호되며
edgenetwork에서 TCP로 닿을 수 있습니다. - catalog·Player의 일반 egress를 network가 제한하지 않습니다.
update.sh는 opt-in profile container(translation-import등)를 갱신하지 않습니다. 갱신 뒤 직접 다시 기동합니다.
검증과 남은 범위
- PASS: drop-deploy-sha256 브랜치(병합
6888a56)update.sh기록기 93개 PASS(수정 전 script로는 64개 FAIL), 수동 절차 블록의 부분 파일·빈 파일·전체 성공 사례(dash·BusyBox)- 문서 검사,
git diff --check - HTTPS dind e2e(Docker 24.0.2): asset 없는 release의 최초 설치·자기 교체, reset, 배포, 표식 없는 release의 무변경 중단, 1.0.2
update.sh의 무변경 중단 뒤 1회curl전환 - 리뷰 최종 판정: 병합 가능
- PASS: pkg-uid 브랜치(병합
6cf8f1f)- 전체 unit 149 files / 1,167 tests, static, 문서 검사
- 격리 dind e2e(stager 1026:100): 수정 전 3 attempt 실패 재현 → 수정 뒤 seal → stage → Builder → publish → build
ready. RGSS·MV/MZ 봉인 사본 읽기 거부의 RED → GREEN - 리뷰 최종 판정: 병합 가능
- PASS: 릴리스 gate(Compose v2.20.1)
- 환경: 격리
docker:24.0.2-dind(overlay2, BusyBox ash), host Compose는 공식 v2.20.1 linux-x86_64 binary(release의 게시 checksum과 일치)입니다. 합성 CA의 HTTPS release 서버가 Gitea를, 합성 TLS registry가git.2ex.dev를 대신했습니다(dind daemon에만 적용). registry에는 실제 1.0.2 image와 이 릴리스의 1.0.3 image를 넣었습니다. 배포 파일은 1.0.2 tag와 이 릴리스 커밋의 Git blob입니다. - 운영과 같은 계정: scanner·stager 1026:100,
./databind store - 1.0.2 최초 설치 →
reset.sh→update.sh: exit 0(107초). sealed store 1026:100, MV/MZ 준비 성공. VX Ace 준비는 1.0.2 결함으로 3 attempt 모두 실패(SEALED_INPUT_INVALID) - 1.0.3 게시 뒤 설치된 1.0.2
update.sh: 자동 갱신 미지원 줄, exit 1, 배포 파일·container 변화 없음 - 운영 가이드의 1회
curl→sh update.sh: exit 0(47초),Updated to 1.0.3 ..., 7개 파일이 release와 같음,.tmp0 - 1.0.2에서 실패한 VX Ace 준비를 다시 요청:
runtime-package-stagerone-shot(exit 0)이 1026:100으로 봉인 → stage → Builder(exit 0) → publish → buildready. sealed 항목은 모두 1026:100이고 Builder 계정의 읽기·탐색 실패는 0 - 설치 상태에서 재-update: exit 0(13초), 배포 파일 변화 없음
- 매 배포 뒤 12개 service의 network가 선언과 일치(불일치 0)했고 unhealthy는 0, package·runtime readiness는 exit 0, coordinator 재시작 0이었습니다.
- 환경: 격리
- PASS: 최종 1.0.3 소스. 릴리스 커밋 두 개(root version, 완료 기준선의 version 문구) 뒤 문서 검사(759개 파일 / Markdown 32개), static(Prettier·ESLint·typecheck·docs-static),
git diff --check를 다시 통과했습니다. - 게시 이미지: 같은 최종 소스에서 build했습니다. image 안에서 root version 1.0.3, ARCA pin·설치본 0.1.18을 확인했습니다.
- PARTIAL: 전체 UI/제품 acceptance. 화면·fixture·package/build 성공을 실제 browser play PASS로 기록하지 않습니다.
- NOT RUN:
- Synology NAS 실제 환경(Compose v2.20.1 Synology build, Docker 24 btrfs)에서의 1.0.2 → 1.0.3 전환과
sh update.sh - 실제 Gitea release·registry에서의 전체 stack 갱신(gate는 합성 release 서버·registry)
- 실제 library/private game과 실제 scan
- 입력·오디오·save/reload의 실제 게임 acceptance
- live provider
- 개발 rebuild
- Synology NAS 실제 환경(Compose v2.20.1 Synology build, Docker 24 btrfs)에서의 1.0.2 → 1.0.3 전환과
배포 이미지와 파일
- Git annotated tag는 1.0.3이고 최종 소스는
5e262a8dde입니다. - 단일 linux/amd64 이미지:
git.2ex.dev/hanyul/links:1.0.3=git.2ex.dev/hanyul/links:latest - 원격 digest:
sha256:6420862bb806cd543dd5e54c38e8ac0d9fe2eb5c183daf4e8494e17265a5cf46 - release asset은 없습니다.
update.sh가 tag1.0.3의 7개 배포 파일을 HTTPS로 받습니다(update.sh=ops/deploy-registry.sh,reset.sh=ops/reset-registry.sh,backup.sh=ops/backup-registry.sh, 그리고compose.yaml·infra/docker/Caddyfile·ops/backup-verify.compose.yaml·ops/runtime-package-coordinator.sh). - 1.0.2 대비 바뀐 배포 파일:
compose.yaml(runtime-package-stagerservice, package worker의 sealed store read-only),ops/deploy-registry.sh(SHA-256 없는 다운로드·자동 갱신 표식),ops/runtime-package-coordinator.sh(seal 단계). 나머지 4개는 같습니다.
Downloads 2
-
Source code (zip)
0
2026-10-11 21:52:47 +09:00 -
Source code (tar.gz)
0
2026-10-11 21:52:47 +09:00
- 1회 전환: 1.0.2의