Releases

  • LINKS 1.0.18 — Player 자동 시작·선명한 표시(ARCA 0.1.23 focus·fresh 재시작)·표지 선택 제거

    LINKS 1.0.18

    이 릴리스는 이전 릴리스 1.0.17(6909122178) 위에 ARCA pin 0.1.23, Player 자동 시작·선명한 표시(T81), 자동 시작 초점 옵션과 fresh 재시작 연결(T82-A·B), 관리자 표지 선택 제거(T82-C)를 더했습니다. 최종 소스는 b38525b677, 루트 패키지는 1.0.18, ARCA pin은 exact 0.1.23(0.1.22에서 변경)입니다. schema 변경이 있습니다: migration 0006_remove_cover_override.

    업그레이드: 1.0.17 → 1.0.18은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema: update.sh가 [4/6]에서 Pending migrations: 1을 출력하고 up 때 migration service가 0006_remove_cover_override를 한 transaction으로 적용합니다(관리자 표지 선택 table·view·index 삭제, 공급자 표지 asset과 audit 기록은 유지). migration이 적용된 뒤에는 1.0.17 image가 이 DB를 열 수 없으므로 1.0.17로 되돌릴 수 없습니다. 관리자가 수동으로 골랐던 표지는 공급자 표지로 돌아갑니다.
    3. 배포 파일 변경: 없습니다. compose.yaml, infra/docker/Caddyfile, ops/deploy-registry.sh(update.sh), ops/runtime-package-coordinator.sh, ops/reset-registry.sh, .env.example은 1.0.17과 byte 단위로 같고 .env.production에 할 일은 없습니다.
    4. ARCA pin 변경에 따른 자동 재준비: 0.1.23은 SDK에 시작 focus 옵션과 restart({ presentation: "fresh" })를 더한 release로 native runtime·Builder·contracts 동작은 0.1.22와 같지만 release manifest hash와 산출물 digest가 바뀌었습니다. catalog 기동 sweep이 0.1.22로 만든 모든 rgss-wasm ready build의 재준비를 priority -20으로 마지막 요청자 이름으로 요청합니다. 기존 build는 대체 build가 준비될 때까지 그대로 실행되고, MV/MZ build는 대상이 아닙니다.
    cd /volume1/docker/links
    sh update.sh
    

    운영자 작업은 없습니다. 기존 실행 버전, 세이브, RTP, 설정은 그대로입니다. 원본 game library는 읽기 전용으로 유지합니다. 갱신 뒤 VX/VX Ace 설치본 수만큼 background 재준비 job이 순서대로 돕니다.

    변경 내용

    ARCA 0.1.23 pin(package.json, apps/worker, apps/player, packages/runtime-builder, lockfile)

    • @rgss23/arca exact pin 0.1.22 → 0.1.23. npm registry는 0.1.23만 보관하므로 이전 pin은 더 이상 설치되지 않습니다.
    • 런타임 계약 문서의 ARCA 링크가 0.1.23 tag를 가리킵니다. LINKS의 ARCA 변경 요청 2건(자동 시작 focus 옵션, fresh 재시작)이 이 버전에 채택·부분 채택되어 연결됐습니다.

    T81. Player 자동 시작과 선명한 표시(apps/web, apps/player)

    • 준비가 끝나면 시작 버튼 없이 바로 게임을 시작합니다. 설명성 안내 문구(자동 시작 예고, 실행 파일 안내, 저장된 파일 사용 안내)는 지웠습니다. 자동 재생이 막힌 브라우저에서는 frame 안 첫 키 입력 때 오디오가 재개됩니다.
    • Player iframe을 표시 크기(정수 CSS px, transform 없음)로 배치해 시작 때 canvas drawing buffer가 표시 크기 × devicePixelRatio(synced)입니다. VX/VX Ace 글자가 흐리게 확대되던 문제가 해결됐습니다(꽉 채우기만 예외).
    • 게임 canvas에 초점이 가도 focus ring(테두리 선)이 그려지지 않습니다.

    T82-A. 자동 시작 초점(apps/web, apps/player)

    • 시작 시점에 modal dialog·설정 패널·링크가 초점을 가지면 부모가 focus: false를 보내고 frame이 SDK의 prepareRgss23Player({ focus })·prepared.start({ focus })에 그대로 넘깁니다. 자동 시작이 바깥 초점과 다음 키 입력을 빼앗지 않으며, canvas나 터치 패드(방향·동작·토글)의 첫 누름에 게임이 초점을 받습니다.

    T82-B. 크기 변경 뒤 fresh 재시작(apps/web, apps/player)

    • 시작 뒤 화면 크기를 바꿔 scaled가 되면 설정의 재시작이 ARCA 0.1.23 fresh 재시작(restart({ presentation: "fresh" }))으로 새 canvas element와 현재 표시 크기 × DPR의 backing으로 다시 시작합니다(synced). 크기를 바꾸지 않았으면 기존 빠른 재시작입니다. 안내 문구는 "시작 뒤 바꾼 크기는 재시작하면 선명해집니다."입니다.

    T82-C. 관리자 표지 선택 제거(apps/api, apps/web, packages/db, infra/schema, migration 0006)

    • 상세 화면의 표지 선택 버튼·dialog와 override API·DB table을 지웠습니다. 설치본 표지는 항상 DLsite 표지 head(첫 공급자 이미지)입니다. 공급자 이미지 수집·공개 범위와 audit 기록은 그대로입니다.

    검증과 남은 범위

    • PASS(릴리스 소스 b38525b, 코디네이터 실행): static(Prettier·ESLint·typecheck·docs-static), 전체 unit 187 files·1,676 tests, schema(빈 DB fresh 적용과 baseline+0001~0006 사슬 적용의 구조 등가 포함), 문서 검사, git diff --check, run-catalog-browser(Chromium, 21개 단언, 오류 0), no-cache frozen install image build(0.1.23 설치, 이미지 안 root 1.0.18·migration 6개·자동 갱신 표식), foundation, run-browser matrix(MZ·MV × Chromium·Firefox browser-acceptance 4개와 guest-play-acceptance 4개), run-runtime-workers.
    • PASS(ARCA pin gate, 0.1.23 release dir): run-rgss23-release-set(exact pin), run-rgss23-runtime-binding, run-rgss23-builder(합성 VX Ace), arca-npm-check, node 24 container frozen lockfile 재해석.
    • PASS(병합된 main b38525b, 코디네이터 실행): run-player-lazy(Chromium·chromium-gesture·Firefox), run-player-dpr Chromium 전체 matrix, run-player-touch-pad(Chromium·Firefox), run-player-layout, run-player-loading PASS. run-player-dpr Firefox는 PARTIAL: RGSS 셀 전체(fresh·빠른 재시작 45행 포함) PASS, MV 셀에서 코디네이터 harness의 page.goto 30초 timeout으로 2회 중단(독립 리뷰어의 격리 project 전체 Firefox matrix 165 records PASS, 같은 test 파일).
    • PASS(브랜치별 작업자·독립 리뷰어 실행): run-player-lazy(Chromium·chromium-gesture·Firefox, 바깥 초점·다음 키 유지 단언), run-player-dpr(Chromium·Firefox, DPR 1~3 × 3 viewport, fresh·빠른 재시작 cell), run-player-touch-pad(Chromium·Firefox), run-player-layout, metadata-display(관리자 상세에 표지 선택 없음)와 독립 Sol 리뷰(A 2회·B 3회·C 1회) 병합 가능.
    • 알려진 제한·NOT RUN: 실제 VX/VX Ace 게임의 브라우저 타이틀·save/load·재시작 확인, 실제 모바일 기기·실제 망, 실제 오디오 출력, 격리 dind의 1.0.17→1.0.18 update.sh·migration 0006 리허설, 0.1.23 Builder의 실제 NAS load(운영 배포 때 재준비 sweep으로 확인). heap·web-static 실행 경로는 시작 때 SDK 기본값대로 canvas가 초점을 가져갑니다(개발 계획 항목).

    배포 이미지와 파일

    • Git annotated tag는 1.0.18이고 최종 소스는 b38525b677(branch main)입니다.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.18 = git.2ex.dev/hanyul/links:latest(index digest sha256:b26f7c9c43305ae762a9b7bdd6344dbafb7f43e7f53c70ebca23a84ff5d50bed, 로컬 image ID와 동일).
    • release asset은 없습니다. 배포 파일은 update.sh가 tag에서 HTTPS로 받습니다.
    Downloads 2
  • LINKS 1.0.17 — ARCA 0.1.22 pin·UI/UX 개편(서가 디자인 시스템, T80)

    LINKS 1.0.17

    이 릴리스는 이전 릴리스 1.0.16(79c115dc9c) 위에 ARCA pin 0.1.22와 web UI/UX 개편(T80 A·B·C·D, "서가" 디자인 시스템)을 더했습니다. 최종 소스는 34c57015ce, 루트 패키지는 1.0.17, ARCA pin은 exact 0.1.22(0.1.21에서 변경)입니다. schema 변경은 없습니다(infra/schema·infra/migrations는 1.0.16과 동일).

    업그레이드: 1.0.16 → 1.0.17은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema: migration이 없으므로 update.sh는 [4/6]에서 pending migration을 출력하지 않습니다. 1.0.16 image를 rollback pin으로 지정하면 같은 DB로 되돌아갑니다.
    3. 배포 파일 변경: 없습니다. compose.yaml, infra/docker/Caddyfile, ops/deploy-registry.sh(update.sh), ops/runtime-package-coordinator.sh, ops/reset-registry.sh, .env.example은 1.0.16과 byte 단위로 같고 .env.production에 할 일은 없습니다.
    4. ARCA pin 변경에 따른 자동 재준비: 0.1.22는 ARCA의 docs-only release라 runtime·SDK·Builder 동작은 0.1.21과 같지만 release manifest hash와 산출물 digest가 바뀌었습니다. 그래서 1.0.16에서 넣은 catalog 기동 sweep이 0.1.21로 만든 모든 rgss-wasm ready build의 재준비를 priority -20으로 마지막 요청자 이름으로 요청합니다. 기존 build는 대체 build가 준비될 때까지 그대로 실행되고, MV/MZ build는 대상이 아닙니다.
    cd /volume1/docker/links
    sh update.sh
    

    운영자 작업은 없습니다. 기존 실행 버전, 세이브, RTP, 설정은 그대로입니다. 원본 game library는 읽기 전용으로 유지합니다. 갱신 뒤 VX/VX Ace 설치본 수만큼 background 재준비 job이 순서대로 돕니다.

    변경 내용

    ARCA 0.1.22 pin(package.json, apps/worker, apps/player, packages/runtime-builder, lockfile)

    • @rgss23/arca exact pin 0.1.21 → 0.1.22. npm registry는 0.1.22만 보관하므로 이전 pin은 더 이상 설치되지 않습니다.
    • 런타임 계약 문서의 ARCA 링크가 0.1.22 tag를 가리킵니다.

    A. 디자인 시스템 기반(apps/web/src/styles)

    • Pretendard Variable을 동적 subset으로 자체 제공(OFL, npm 의존성 아님)하고 색·간격·활자·motion token, 8가지 상태의 버튼 행렬(화면 상태당 채워진 primary 최대 1개), dialog motion, .section-block·.definition-list, 축소된 헤더 chrome을 정의했습니다. 규칙은 apps/web/src/styles/README.md가 소유합니다.

    B. 홈(apps/web)

    • toolbar를 평면화하고 표지 주도 카드(첫 카드 제목 8 computed-root rem, 잘림 없음)와 조용한 페이지네이션으로 바꿨습니다.

    C. 게임 상세·라이브러리(apps/web)

    • 상세 hero, 출처 정의 목록, section-block 하단 섹션, 라이브러리 sidebar를 재구성하고 guest 차단 결정에 맞춰 guest 단계를 정리했습니다.

    D. 실행 준비·Player·인증·관리자(apps/web)

    • 준비 화면(MV/MZ 4단계·VX/VX Ace 5단계)과 Player 화면, 로그인·계정 dialog, 관리자 workspace를 디자인 시스템에 맞췄습니다. 로딩 overlay는 입력 계약대로 pointer-events: none을 유지하고 하단 고정 불러오기 취소 footer로 빠져나옵니다. spinner는 전체 크기를 모를 때만 표시합니다.

    검증과 남은 범위

    • PASS(릴리스 소스 34c5701, 코디네이터 실행): static(Prettier·ESLint·typecheck·docs-static), 전체 unit 186 files·1,672 tests, schema(빈 DB fresh 적용과 baseline+0001~0005 사슬 적용의 구조 등가 포함), 문서 검사, git diff --check, run-catalog-browser(Chromium 153, 21개 단언, 오류 0), no-cache frozen install image build(0.1.22 설치, 이미지 안 root 1.0.17·migration 5개·자동 갱신 표식), foundation, run-browser matrix(MZ·MV × Chromium·Firefox browser-acceptance 4개와 guest-play-acceptance 4개), run-runtime-workers.
    • PASS(ARCA pin gate, 0.1.22 release dir): run-rgss23-release-set(exact pin), run-rgss23-runtime-binding(67 files), run-rgss23-builder(합성 VX Ace, digest-pinned Builder, CAS publish-and-reuse, compatibility exact-match), arca-npm-check(floating version 거부 포함), node 24 container frozen lockfile 재해석.
    • PASS(브랜치별 작업자·독립 리뷰어 실행): 각 작업의 합성 browser check(홈·상세·준비·Player·관리자·sandbox-rgss)와 독립 Sol 리뷰(A 1회·B 3회·C 2회·D 2회) 병합 가능.
    • 알려진 제한·NOT RUN: 실제 VX/VX Ace 게임의 브라우저 타이틀·save/load 확인, 실제 모바일 기기·실제 망, 실제 오디오 출력, 격리 dind의 1.0.16→1.0.17 update.sh 리허설, 0.1.22 Builder의 실제 NAS load(운영 배포 때 재준비 sweep으로 확인).

    배포 이미지와 파일

    • Git annotated tag는 1.0.17이고 최종 소스는 34c57015ce(branch main)입니다.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.17 = git.2ex.dev/hanyul/links:latest(index digest sha256:d3932590a5952f403c1f65b8366e859d29e172422bf1f825ef7996379c97f4c6, 로컬 image ID와 동일).
    • release asset은 없습니다. 배포 파일은 update.sh가 tag에서 HTTPS로 받습니다.
    Downloads 2
  • LINKS 1.0.16 — VX/VX Ace 실행 준비 시간 단축(T79)·북마크 저장과 ARCA pin 변경 자동 재준비

    LINKS 1.0.16

    이 릴리스는 이전 릴리스 1.0.15(37f9ca3af3) 위에 VX/VX Ace 실행 준비 소요 시간 단축(T79 A·B·C·D)과 북마크 저장·ARCA pin 변경 자동 재준비를 더했습니다. 최종 소스는 79c115dc9c, 루트 패키지는 1.0.16, ARCA pin은 exact 0.1.21(변경 없음)입니다. schema 변경은 없습니다(infra/schema·infra/migrations는 1.0.15와 동일).

    업그레이드: 1.0.15 → 1.0.16은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema: migration이 없으므로 update.sh는 [4/6]에서 pending migration을 출력하지 않습니다. 1.0.15 image를 rollback pin으로 지정하면 같은 DB로 되돌아갑니다.
    3. 배포 파일 변경: update.sh가 받는 5개 파일 중 compose.yaml(catalog 환경 변수 LINKS_RUNTIME_REPREPARE_ON_PIN_CHANGE 한 줄, 기본 true)과 ops/runtime-package-coordinator.sh(상주 claim worker 프로토콜)가 바뀌었고 update.sh가 둘을 설치합니다. 두 파일은 1.0.16 worker image와 짝이므로 1.0.15 image와 섞어 쓰지 않습니다. ops/deploy-registry.sh(update.sh), reset.sh, infra/docker/Caddyfile은 1.0.15와 byte 단위로 같습니다. .env.example에 위 키가 추가됐지만 선택 항목이라 .env.production에 할 일은 없습니다.
    cd /volume1/docker/links
    sh update.sh
    

    운영자 작업은 없습니다. 기존 MV/MZ·VX/VX Ace 실행 버전, 세이브, RTP, 설정은 그대로입니다. 원본 game library는 읽기 전용으로 유지합니다. 갱신 뒤 설치본의 첫 재준비는 원본을 한 번 더 복사한 뒤 기존 sealed input과 대조하고(copy-then-dedupe), 기존 CAS object의 첫 재사용은 전체 검증 1회로 검증 기록을 남깁니다. ARCA pin이 같으므로 catalog 기동 때의 pin 변경 재준비 sweep은 대상이 없습니다.

    변경 내용

    A. package job 검증·container 축소(apps/worker, ops/)

    • VX/VX Ace package job은 ARCA release set(contracts 결속 포함)을 job당 한 번(claim) 전체 검증하고, stage·publish는 그 identity 기록을 확인만 합니다(다르면 전체 검증).
    • coordinator는 job마다 상주 claim worker 하나를 두어 3초마다 lease를 갱신하고 Builder 진행을 중계하며, lease를 잃으면 Builder를 멈춥니다(stdin stage/end 프레이밍, end가 순서 장벽). Builder 밖 container 시작은 job당 6→4, cleanupAttempts·capability 확인은 job당 1회입니다.

    B. CAS object 검증 기록(packages/runtime-builder)

    • game·RTP CAS object의 전체 검증 결과를 object 옆 봉인된 <hash>.verified.json에 남깁니다. 이후 준비의 import와 build job의 load는 stat identity가 같으면 archive 재hash를 생략하고, 기록이 없거나 identity가 다르면 전체 검증으로 돌아가며 손상 object는 거부합니다.
    • GC는 마지막 참조가 사라진 RGSS portable object를 기록과 함께 수거합니다.

    C. 원본 본문 1회 읽기(packages/scanner, packages/contracts, apps/web)

    • 최초 검사 pass는 경로·size·mtime·ctime만 열거하고(VX는 Game.ini만 읽음) 복사 pass가 hash와 봉인을 한 번에 수행합니다. verify-source는 파일을 읽지 않고 목록 metadata digest를 대조합니다. 준비당 원본 읽기 횟수는 MV/MZ 2→1회, VX/VX Ace 3→1회입니다.
    • 나이 판정으로 대기를 생략하지 않는 경로는 두 번째 관찰을 유지하고, 복사 전후 identity·size·mtime·ctime·파일 집합 비교와 복사 중 변경의 RUNTIME_SOURCE_CHANGED는 그대로입니다. partial 사본의 identity는 쓰기 descriptor에 결속합니다.
    • 준비 화면은 MV/MZ 4단계·VX/VX Ace 5단계를 번호로 표시합니다. 준비 상태 API의 inspectionPass·operation 값이 이에 맞춰 바뀌었습니다.

    D. 자동 준비 요청(apps/api, packages/db)

    • 북마크 저장(PUT /bookmarks/{installationId})이 저장한 사용자의 실행 준비를 요청합니다. 같은 설치본의 준비 중 요청은 설치본 잠금 아래에서 replay하고, 요청 실패는 북마크 응답에 영향을 주지 않습니다.
    • ARCA pin을 바꾼 image의 catalog는 기동 때 한 번 다른 release로 만든 rgss-wasm ready active build의 재준비를 마지막 준비 요청자 이름으로 priority -20에 요청합니다(LINKS_RUNTIME_REPREPARE_ON_PIN_CHANGE, 기본 켬). 발급 여부는 서버가 쓴 audit(after.trigger: arca-pin·after.release)로 설치본·release마다 한 번만 판정하고, worker가 없거나 준비 중이면 30분간 1분·그 뒤 10분 간격으로 다시 돕니다. /runtime-preparations/mine은 자동 요청을 숨기고 관리자 감사 기록 API는 trigger를 반환합니다.

    검증과 남은 범위

    • PASS(릴리스 소스 79c115d, 코디네이터 실행): static(Prettier·ESLint·typecheck·docs-static), 전체 unit 186 files·1,669 tests, schema 40 files·288 tests(빈 DB fresh 적용과 baseline+0001~0005 사슬 적용의 구조 등가 포함), 문서 검사, git diff --check, run-catalog-browser(Chromium 153, 21개 단언, 오류 0), no-cache frozen install image build(이미지 안 root 1.0.16·migration 5개·자동 갱신 표식), foundation, run-browser matrix(MZ·MV × Chromium·Firefox browser-acceptance 4개와 guest-play-acceptance 4개), run-runtime-workers.
    • PASS(브랜치별 작업자·독립 리뷰어 실행): 합성 fixture의 읽기 횟수 unit(VX 3→1, MV/MZ 2→1, release 3→1, CAS 재hash 0), lease 상실 → Builder 중단·cancel → attempt 실패, 검증 기록 누락·identity 불일치의 전체 검증 fallback과 손상 object 거부, 복사 중 변경 → RUNTIME_SOURCE_CHANGED, 북마크·pin sweep schema test(동시 저장 action 1개, release당 자동 요청 1회, 요청자 변경·동시 catalog·재시작에 추가 job 0), 독립 Sol 리뷰(A 3회·B 2회·C 2회·D 3회) 병합 가능.
    • 변경 전 실측(운영 NAS, 2026-10-19, 재준비 1건, 1,716 파일·436 MB): enqueue→package 완료 231 s, 그중 container·Compose 비용 약 145 s. 변경 뒤 같은 NAS·설치본 재측정은 배포 뒤 실행 예정(NOT RUN).
    • 알려진 제한·NOT RUN: 실제 VX/VX Ace 게임의 브라우저 타이틀·save/load 확인, 실제 모바일 기기·실제 망, 실제 오디오 출력, 격리 dind의 1.0.15→1.0.16 update.sh 리허설.

    배포 이미지와 파일

    • Git annotated tag는 1.0.16이고 최종 소스는 79c115dc9c(branch main)입니다.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.16 = git.2ex.dev/hanyul/links:latest(index digest sha256:4994796a90bb7c54b866be8c4104b12adbb70f6cc0c8f0ce2e6a605a5f12c09c, 로컬 image ID와 동일).
    • release asset은 없습니다. 배포 파일은 update.sh가 tag에서 HTTPS로 받습니다.
    Downloads 2
  • LINKS 1.0.15 — 문서 정리·사용자 결정 15건 적용·migration 0005

    LINKS 1.0.15

    이 릴리스는 이전 릴리스 1.0.14(ee9e5a6877) 위에 문서 정리(T77), 미뤄 두었던 사용자 결정 15건 적용(T78), schema migration 0005를 더했습니다. 최종 소스는 37f9ca3af3, 루트 패키지는 1.0.15, ARCA pin은 exact 0.1.21(변경 없음)입니다. schema가 바뀌어 migration 1개가 적용되며, 적용 뒤에는 이전 image(1.0.14)로 되돌릴 수 없습니다.

    업그레이드: 1.0.14 → 1.0.15는 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. migration 0005 적용: update.sh가 [4/6] Checking the database schema version 뒤에 Pending migrations: 1 한 줄을 출력하고, [5/6]의 up 때 migration service가 0005_edition_notes_sidecar_method를 적용합니다(schema aa95c192… → d37d2c2e…). 이 migration은 view installation_localized_text_values 하나를 CREATE OR REPLACE로 바꿉니다. table·column·권한·행은 바뀌지 않습니다. 성공하면 Updated to 1.0.15 (catalog <image id>), runtime.package ready.로 끝납니다.
    3. 이전 image로 복귀 불가: migration이 적용된 DB는 1.0.14 image의 사슬 밖(mismatch)입니다. 1.0.14를 rollback pin으로 지정하면 update.sh가 [4/6]에서 Run: sh reset.sh로 멈추고 아무것도 바꾸지 않습니다. 이 안내를 따르지 마십시오(데이터를 지우는 초기화입니다). pin을 비우고 sh update.sh를 다시 실행하면 1.0.15로 돌아옵니다. LINKS는 backup을 제공하지 않습니다.
    4. 배포 파일 변경: update.sh가 받는 5개 파일 중 ops/deploy-registry.sh(update.sh 자신), compose.yaml, **infra/docker/Caddyfile**이 바뀌었고 update.sh가 셋을 설치합니다. 실행 중인 1.0.14 update.sh는 새 update.sh를 받아 한 번 이어 실행합니다. 새 update.sh는 0.x schema 상태 legacy-migrations를 더 이상 구분하지 않습니다(그런 DB는 unversioned로 같은 초기화 안내). compose.yaml은 runtime-package-coordinator image docker:24.0.9-cli를 digest로 고정합니다(다른 구성은 동일). Caddyfile은 Permissions-Policy를 site 공통 header에서 catalog handle로 옮겨 /player/* 응답에 Player 자신의 값(clipboard 차단 포함)이 그대로 나가게 합니다. reset.sh, ops/runtime-package-coordinator.sh는 1.0.14와 byte 단위로 같고 .env.example도 바뀌지 않아 .env.production에 할 일은 없습니다.
    cd /volume1/docker/links
    sh update.sh
    

    운영자 작업은 없습니다. 기존 MV/MZ·VX/VX Ace 실행 버전, 세이브, RTP, 설정은 그대로입니다. 원본 game library는 읽기 전용으로 유지합니다. 관리자가 1.0.14에서 열어 둔 match 후보 검토 페이지의 cursor는 갱신 뒤 거부되므로 화면을 새로 고칩니다.

    변경 내용

    문서 정리(T77)

    • docs/, .agents/, README.md, AGENTS.md를 현재 코드·설정·실행 방식에 맞게 다시 썼습니다. 날짜별 일지, ARCA 버전별 적용 변경 절, 제거된 표면의 중복 목록, 참고 조사 문서를 지웠고 개발 계획은 주제별로, 완료 기준선은 현재 제공 범위와 최신 검증만 남기도록 재구성했습니다. 깨진 anchor는 저장소 전체 대조로 0건입니다.

    API·web(사용자 결정 2026-10-19)

    • match 후보 cursor는 모든 filter와 정렬을 query key에 넣습니다. 이전 key 배치로 발급된 cursor는 다른 조건의 cursor와 같은 400 CURSOR_INVALID로 거부됩니다.
    • Player session 응답의 expiresInSeconds는 필수이고 부모 화면의 expiresAt·browser 시계 fallback을 지웠습니다.
    • 버그 신고의 같은 key·다른 내용 응답을 다른 route와 같은 409 IDEMPOTENCY_CONFLICT로 통일했습니다(REPORT_CONFLICT 제거).
    • 상세 행동 영역의 도달 불가 guest 분기(로그인하고 저장)를 지웠습니다. /installations의 missing·stability filter와 cursor 페이지는 관리자 진단용으로 유지합니다.

    Schema migration 0005·DB 상태

    • 0005_edition_notes_sidecar_method: 판본 메모의 local sidecar 값이 제목과 같이 method folder-derived가 되어, 한국어 후보가 없을 때 manual 판본 메모가 sidecar 값보다 앞섭니다. 기준 schema도 같은 변경을 담습니다.
    • 0.x DB 감지 상태 legacy-migrations를 코드·update.sh·기록기·문서에서 지웠습니다.

    Infra·scanner

    • gateway는 Permissions-Policy를 catalog 응답에만 붙이고 /player/* 응답에는 Player 값이 한 줄로 나갑니다.
    • runtime-package-coordinator image를 digest로 고정했습니다.
    • local sidecar 경계 표시가 reader와 같은 정확한 이름 .links.json 비교를 씁니다. 대소문자만 다른 이름은 경계도 sidecar도 아닙니다(합성 fixture 결과 변화 없음).

    검증과 남은 범위

    • PASS(릴리스 소스 37f9ca3, 코디네이터 실행): static(Prettier·ESLint·typecheck·docs-static), 전체 unit 183 files·1,588 tests, schema 39 files·277 tests(빈 DB fresh 적용과 baseline+0001~0005 사슬 적용의 구조 등가 포함), 문서 검사, git diff --check, run-catalog-browser(Chromium), no-cache frozen install image build(Lockfile is up to date, 이미지 안 root 1.0.15·migration 5개·자동 갱신 표식), foundation, run-browser matrix(MZ·MV × Chromium·Firefox browser-acceptance 4개와 guest-play-acceptance 4개 모두 PASS).
    • PASS(브랜치별 작업자·독립 리뷰어 실행): 배포 기록기 check-deploy-registry 91 case, 격리 scanner gate, develop stack의 catalog·/player/* header 관찰(전후 비교), image index digest 대조, 이전 cursor 거부 변이 검증, 로그인 사용자 상세 markup 동일성, 독립 리뷰 R1~R4 병합 가능.
    • 알려진 제한·NOT RUN: 실제 모바일 기기·실제 망, 실제 VX/VX Ace 게임과 RTP, 실제 오디오 출력. 격리 dind의 1.0.14→1.0.15 update.sh 리허설은 실행하지 않았습니다(update.sh 변경은 분기 문자열 한 줄이며 기록기 91 case와 독립 리뷰로 확인).

    배포 이미지와 파일

    • Git annotated tag는 1.0.15이고 최종 소스는 37f9ca3af3(branch main)입니다.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.15 = git.2ex.dev/hanyul/links:latest(index digest sha256:9aaba46591f0995703e7d8c244d53961e0c292a0b6bd7eb9a133c227da4c5182, 로컬 image ID와 동일).
    • release asset은 없습니다. 배포 파일은 update.sh가 tag에서 HTTPS로 받습니다.
    Downloads 2
  • LINKS 1.0.14 — 코드 정리·하위호환 제거·migration 0004·결함 수정

    LINKS 1.0.14

    이 릴리스는 이전 릴리스 1.0.13(e43a2034b2) 위에 코드 정리 wave(T75), 하위호환 제거, 미사용 schema 정리(migration 0004), 결함 수정(T76)을 더했습니다. 최종 소스는 ee9e5a6877, 루트 패키지는 1.0.14, ARCA pin은 exact 0.1.21(변경 없음)입니다. schema가 바뀌어 migration 1개가 적용되며, 적용 뒤에는 이전 image(1.0.13)로 되돌릴 수 없습니다.

    업그레이드: 1.0.13 → 1.0.14는 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. migration 0004 적용: update.sh가 [4/6] Checking the database schema version 뒤에 Pending migrations: 1 한 줄을 출력하고, [5/6]의 up 때 migration service가 0004_remove_unused_schema를 적용합니다(schema d28acb3f… → aa95c192…). 이 migration은 index 8개 DROP, audit_events.actor_type CHECK 교체(operator·service 제거), runtime_build_pins.kind column DROP만 하며 행을 다시 쓰지 않습니다(운영 DB에 지우는 값을 가진 행은 0건). 성공하면 Updated to 1.0.14 (catalog <image id>), runtime.package ready.로 끝납니다.
    3. 이전 image로 복귀 불가: migration이 적용된 DB는 1.0.13 image의 사슬 밖(mismatch)입니다. 1.0.13을 rollback pin으로 지정하면 update.sh가 [4/6]에서 Run: sh reset.sh로 멈추고 아무것도 바꾸지 않습니다. 이 안내를 따르지 마십시오(데이터를 지우는 초기화입니다). pin을 비우고 sh update.sh를 다시 실행하면 1.0.14로 돌아옵니다. LINKS는 backup을 제공하지 않습니다.
    4. 배포 파일 변경: update.sh가 받는 5개 파일 중 ops/deploy-registry.sh(update.sh 자신)와 **compose.yaml**이 바뀌었고 update.sh가 이 둘을 설치합니다. 실행 중인 1.0.13 update.sh는 새 update.sh를 받아 한 번 이어 실행합니다. 새 update.sh에는 1.0.8 backup stub 목록, 구 파일 삭제, 1.0.2 deploy-files.sha256.tmp 정리, 1.0.1 host coordinator lock 확인이 없습니다. compose.yaml은 반복되는 service 설정을 YAML anchor로만 묶었고 렌더링된 구성은 1.0.13과 같습니다. reset.sh, infra/docker/Caddyfile, ops/runtime-package-coordinator.sh는 1.0.13과 byte 단위로 같고 .env.example도 바뀌지 않아 .env.production에 할 일은 없습니다.
    cd /volume1/docker/links
    sh update.sh
    

    운영자 작업은 없습니다. 기존 MV/MZ·VX/VX Ace 실행 버전, 세이브, RTP, 설정은 그대로입니다. 원본 game library는 읽기 전용으로 유지합니다.

    변경 내용

    코드 정리 wave(T75)

    • web, API·launch broker·contracts, worker, scanner·runtime-builder·runtime, db, providers·domain, Player, tests·ops 8개 영역에서 중복 로직 통합, 과대 파일 분할, 죽은 분기·export와 공허한 test 제거. 공개 API(OpenAPI byte 동일)와 schema는 바뀌지 않았습니다.

    하위호환 제거(사용자 결정 2026-10-18)

    • 1.0.8 update.sh용 호환 stub(ops/backup-registry.sh·ops/backup-verify.compose.yaml), retired_files 처리, 1.0.2 deploy-files.sha256.tmp 정리, 1.0.1 이하 host coordinator lock 확인, 운영 가이드의 구 버전 전환 안내를 지웠습니다. 자동 갱신 표식이 없는 release는 Release <tag> does not support automatic updates; nothing was changed.로 멈춥니다.

    Schema migration 0004

    • 0004_remove_unused_schema: 선두 column으로 거르거나 정렬하는 query가 없는 index 8개 삭제(운영 DB 통계 idx_scan 0, FK를 받치는 edition_resolution_decisions_history_idx는 유지), audit_events.actor_type에서 operator·service 제거(DB type·공유 contract·API 문서 동기화), runtime_build_pins.kind column과 CHECK 삭제(pin index 재생성). 기준 schema도 같은 변경을 담습니다.

    Player

    • artifact 응답의 adapter별 CSP와 launch·HTML의 CORP 예외를 지웠습니다. game frame 응답의 CSP는 그대로이고, 그 밖 Player 응답(artifact·launch·비인증)은 공통 strict CSP와 CORP same-origin을 씁니다. frame-ancestors·nosniff·no-transform은 유지됩니다.
    • runtime-cache-client의 requestPersistence option과 항상 켜져 있던 reserve 인자를 지웠습니다.

    API·web

    • GET /play-links/{token}이 cover를 항상 돌려주고 include=cover query를 받지 않습니다(모르는 query는 400 유지). 게스트 page는 기본 조회를 씁니다.
    • INSTALLATION_NOT_FOUND·IDEMPOTENCY_CONFLICT 문제 응답을 factory 하나로 통일했습니다(code·status 동일, title·detail 문구 통일). launch broker의 발급 거부 409는 code별 문구표 대신 고정 detail을 씁니다(catalog는 code만 읽음).
    • 참조 없는 og-default.svg를 지웠고, @rgss23/arca를 실제로 import하는 packages/runtime-builder·apps/worker(dependencies)·apps/player(devDependencies)에 root와 같은 exact version으로 선언했습니다.

    결함 수정

    • 재분류 job과 상품 후보 discovery가 scan 완료 경로와 같이 parse 실패 sidecar의 root도 경계로 씁니다.
    • 재연결 검토 화면이 서버가 확인한 stale·결정됨·없음 후보의 초안을 비우고 다시 불러오며, 그 뒤 같은 후보에 새로 쓴 초안은 보존합니다.
    • tests/run-player-lazy.ps1의 Firefox 셀이 Windows PowerShell 5.1에서 실행됩니다. container-log·editions·player-layout browser check의 기대값을 현재 세션·게스트 동작에 맞췄습니다.

    검증과 남은 범위

    • PASS(통합 main, 코디네이터 실행): static(Prettier·ESLint·typecheck·docs-static 944 files), 전체 unit 183 files·1,589 tests, schema 39 files·276 tests(빈 DB fresh 적용과 baseline+0001~0004 사슬 적용의 구조 등가 포함), 문서 검사, git diff --check, run-catalog-browser(Chromium, 21개 단언, 오류 0), 1.0.13 대비 Compose 렌더링 동일(3 profile 조합).
    • PASS(브랜치별 작업자·독립 리뷰어 실행): MV/MZ × Chromium·Firefox browser matrix와 게스트 acceptance(Player header 변경·게스트 page 변경), VX Ace RGSS Chromium gate(운영 header hook 적용), 배포 기록기 check-deploy-registry 92 case, scanner 통합, review-candidates·container-log·editions·player-layout check(Chromium·Firefox), run-player-lazy Firefox(PowerShell 5.1), OpenAPI diff(play-links 변경만), lockfile frozen install.
    • PASS(릴리스 소스 ee9e5a6, 코디네이터 실행): no-cache frozen install image build(Lockfile is up to date, 이미지 안 root 1.0.14·ARCA 0.1.21·migration 4개·자동 갱신 표식), foundation(7 service, catalogHttps·schemaReadiness·opaquePlayerOrigin·rejectedLaunchGrant·scannerReadOnly·roleIsolation PASS), run-browser matrix(MZ·MV × Chromium·Firefox browser-acceptance 4개와 guest-play-acceptance 4개 모두 PASS).
    • 알려진 제한·NOT RUN: 개발 계획 9.1 잔여 3건과 R65c P3 후속, 실제 모바일 기기·실제 망, 실제 VX/VX Ace 게임과 RTP, 실제 오디오 출력. 격리 dind의 1.0.13→1.0.14 update.sh 리허설은 이번에 실행하지 않았습니다(update.sh 변경은 기록기 92 case와 독립 리뷰로 확인).

    배포 이미지와 파일

    • Git annotated tag는 1.0.14이고 최종 소스는 ee9e5a6877(branch main)입니다.
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.14 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:499e87953c61b2eac5967a5fef4175247b359ada5b6283282bf1667118056b22
    • release asset은 없습니다. update.sh가 tag 1.0.14의 5개 배포 파일을 HTTPS로 받습니다. 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2
  • LINKS 1.0.13 — 결함 수정 wave 1·ARCA 0.1.21·migration 0003·RGSS 지연 콘텐츠

    LINKS 1.0.13

    이 릴리스는 이전 릴리스 1.0.12(8843007119) 위에 결함 수정 wave 1, ARCA 0.1.21 pin, schema migration 0003, RGSS 지연 콘텐츠·선부팅을 더했습니다. 최종 소스는 e43a2034b2, 루트 패키지는 1.0.13, ARCA pin은 exact 0.1.21입니다. schema가 바뀌어 migration 1개가 적용되며, 적용 뒤에는 이전 image(1.0.12)로 되돌릴 수 없습니다.

    업그레이드: 1.0.12 → 1.0.13은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. migration 0003 적용: update.sh가 [4/6] Checking the database schema version 뒤에 Pending migrations: 1 한 줄을 출력하고, [5/6]의 up 때 migration service가 0003_job_failure_handling을 적용합니다(schema f7fe92f3… → d28acb3f…). catalog의 /readyz는 적용이 끝난 뒤 준비됩니다. 성공하면 Updated to 1.0.13 (catalog a718b2dc9b42), runtime.package ready.로 끝납니다.
    3. 이전 image로 복귀 불가: migration이 적용된 DB는 1.0.12 image의 사슬 밖(mismatch)입니다. 1.0.12를 rollback pin(LINKS_REGISTRY_TAG=1.0.12@sha256:…)으로 지정하면 update.sh가 [4/6]에서 Run: sh reset.sh로 멈추고 아무것도 바꾸지 않습니다. 이 안내를 따르지 마십시오(데이터를 지우는 초기화입니다). pin을 비우고 sh update.sh를 다시 실행하면 1.0.13으로 돌아옵니다. 문제가 생기면 이전 image로 되돌리지 말고 원인을 고쳐 다시 갱신하거나 수정 release를 기다립니다. LINKS는 backup을 제공하지 않습니다.
    4. 배포 파일 변경: update.sh가 받는 5개 파일 중 compose.yaml(worker service의 stop_grace_period: 30s와 LINKS_WORKER_SHUTDOWN_GRACE_SECONDS, package one-shot의 DB pool 2)과 ops/runtime-package-coordinator.sh(Builder image를 검증된 두 digest로만 선택)가 바뀌었고 update.sh가 이 둘을 설치합니다. update.sh(ops/deploy-registry.sh), reset.sh(ops/reset-registry.sh), infra/docker/Caddyfile은 1.0.12와 byte 단위로 같습니다. .env.example에는 LINKS_WORKER_SHUTDOWN_GRACE_SECONDS=20이 추가됐지만 Compose 기본값이 같은 20이라 .env.production에 할 일은 없습니다.
    cd /volume1/docker/links
    sh update.sh
    

    기존 VX/VX Ace 게임은 "준비 필요"로 바뀝니다. ARCA release manifest와 Builder digest가 달라졌기 때문입니다. 로그인 사용자가 다시 준비하면 새 실행 버전(generation)이 만들어지고(서버에 보관된 게임 object는 재사용), 이 generation은 지연 모드(필요한 부분만 Range로 받기·선부팅·시작 버튼)로 실행됩니다. 브라우저는 처음 한 번 게임을 다시 받으며, chunk cache는 artifact 기준이라 그 뒤에는 다시 받지 않습니다. 기존 세이브는 그대로 열립니다. MV/MZ 게임은 영향이 없습니다. RTP 재준비·설정 변경·DB 작업·artifact 삭제 같은 운영자 작업은 없습니다. 격리 gate에서 postgres container는 다시 만들어지지 않았습니다. 원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 운영 NAS 배포나 DB 초기화는 실행하지 않았습니다.

    변경 내용

    결함 수정 wave 1(개발 계획 9.1)

    • 스캐너: 거부 이름 cursor, frame 깊이 상한 256, entry realpath 실패 격리, PE 서명 상한을 companion directory별로 적용, 하위 sidecar 경계 귀속과 유효 sidecar만의 경계 선택, 완료 후보 loop의 후보별 발행(정규화 충돌 보존, 경로 충돌 warning 1회), 후보별 발행의 VNDB lookup을 scan 성공 transaction에서 100개 batch로 접수.
    • API·launch broker: 발급 거부를 trigger별 code(PLAY_SESSION_NOT_READY·PLAY_SESSION_PREPARATION_REQUIRED 등)와 DB 장애 503으로 구분, SSE 종료, 429·validation·413 응답, 세션 조회를 SELECT + 5분 touch로, body 64 KiB 상한.
    • web: 세션 부팅·로그인 세대별 401 처리, 화면 오류 경계와 root 오류 요약 log, Player 세션 종료(DELETE)에서 저장 보존, 게스트 자체 종료, timer NaN·peer 알림·스크롤·Back·초점·title 결함.
    • 메타데이터·번역: 이미지 루프 heartbeat, 요약 머지 우선순위·태그 상한, 페이지 cool-down 전파, 결정적 거부만 즉시 종료, 공급자·DB 일시 장애는 deferJobAttempt로 미룸, VNDB lookup이 새 circuit 기간만큼 미룸.
    • 런타임: build 시작 시 source 재검사, heartbeat 재시도, CAS object·generation과 store root까지 fsync, DB 시계 사용, Player /session의 expiresInSeconds.
    • job: 최종 실패 cascade, 재시도 지수 backoff, deferJobAttempt, role별 DB pool 기본값, worker crash handler, 종료 유예(LINKS_WORKER_SHUTDOWN_GRACE_SECONDS)와 Compose stop_grace_period, 의존 연결 요소 잠금과 잠금 경합 재시도.

    Schema migration 0003

    • 0003_job_failure_handling: job 최종 실패 cascade trigger(기다리던 queued 자손 job을 같은 transaction에서 DEPENDENCY_FAILED로 닫음), jobs.deferral_count, 의존 연결 요소 행을 id 순서로 잠그는 함수 links_lock_job_dependency_component. 기준 schema(infra/schema/030_jobs.sql)도 같은 변경을 담습니다.

    ARCA 0.1.21 pin

    • Builder manifest digest와 config digest를 release pin에 결속하고, coordinator가 Builder image ID를 이 두 digest로만 선택합니다(tag fallback 제거).
    • RGSS frame launch에 presentation(nearest/fit)을 전달하고 보고합니다. letterbox oracle은 기대 geometry와 대조합니다.

    RGSS 지연 콘텐츠·선부팅

    • game·RTP에 chunk digest가 있는 generation은 1 MiB chunk를 HTTP Range로 읽어 부모의 OPFS content-addressed chunk cache에 두고, 타이틀까지 선부팅한 뒤 부모의 시작 버튼을 기다립니다. chunk digest가 없으면 기존 heap 경로로 실행합니다.
    • Player artifact 요청의 세션 조회를 5초 재사용하고, 보관 object의 archive에서 chunk digest를 계산해 host launch에 싣습니다(derived chunks).
    • 자동 재생이 허용되지 않은 브라우저에서는 preboot:false로 시작 클릭 때 부팅합니다. ARCA 0.1.21이 suspended AudioContext 정체를 고쳐 강제 선부팅 READY가 3.6~3.7초입니다.

    세션 남은 시간·VNDB

    • 세션 남은 시간을 DB가 계산한 값(sessionExpiresInSeconds)으로 broker → Player → 부모에 전달하고, 만료 안내·게스트 만료 종료를 받은 시각 + expiresInSeconds로 정합니다.
    • VNDB lookup circuit 지연, 완료 경로의 lookup batching, 직접 begin transaction의 잠금 경합 재시도 경계.

    검증과 남은 범위

    • PASS: 브랜치 gate(고유 Compose project, BuildKit cache 없는 frozen install)
      • 설치본 identity: ARCA 0.1.21 release manifest 219cfa29…, Builder manifest digest sha256:83adbc29…, config digest sha256:43bc702e…, arca-release verify, npm integrity sha512-MA28Kw…(lockfile·registry metadata·registry tarball·ARCA 배포 tarball 일치).
      • static(Prettier·ESLint·typecheck·docs-static), 전체 unit 175 files·1,468 tests, schema 36 files·273 tests(빈 DB fresh 적용과 migration 적용 결과의 구조 등가 포함), 문서 검사, git diff --check, deploy 기록기 96·reset 기록기 30 case, Compose config 3조합과 Watchtower label, foundation.
      • arca-npm-check(+ 3 files·42 tests), RGSS release-set·runtime-binding(67 files)·Builder 입력 5 case·Builder와 import 통합(합성 VX Ace: digest로 고정한 Builder, chunks game 3, 보관 object reused-derived-equals-builder).
      • run-player-lazy(Chromium, 자동 재생 정책을 강제한 Chromium, Firefox), Player DPR·터치 패드(Chromium·Firefox), sandbox-rgss, Player 재시작(Chromium·Firefox), browser acceptance mz-chromium(12개 단언, 공유 링크 게스트 실행).
    • PASS: 릴리스 gate(Compose v2.20.1, NAS 조건)
      • 환경: 격리 docker:24.0.2-dind, 공식 Docker Compose v2.20.1 binary(게시 checksum 일치), stager 1026:100, ./data bind store, library 최상위 0:0 000 + 1026 ACL, 합성 HTTPS release 서버와 합성 TLS registry.
      • 1.0.12 설치에서 합성 MZ ready build, ARCA 0.1.20 Builder로 만든 합성 VX Ace ready build(chunks 포함), 로그인 사용자 세이브(MZ·VX Ace).
      • 설치된 1.0.12 sh update.sh → 1.0.13: exit 0(53초), Pending migrations: 1, migration 0003 적용(links_schema_version d28acb3f…, 이력에 0003, jobs.deferral_count·잠금 함수 존재), /readyz 200, compose.yaml과 coordinator script 2개만 설치, 12개 service network 불일치 0·unhealthy 0·모두 Watchtower 제외, readiness PASS, catalog·Player 1.0.13·ARCA 0.1.21, worker stop_grace_period 30초·종료 유예 20초, postgres 재생성 없음.
      • Builder image rgss23-builder:0.1.21 = config digest sha256:43bc702e…(Docker 24), 준비 중 Builder container가 그 digest로 생성됨(tag 사용 없음).
      • VX Ace가 "준비 필요"로 바뀌고, 준비 요청 → 0.1.21 새 generation. 1.0.12의 game object를 재사용하고 chunks를 유지, Player가 chunk Range 요청에 206(Content-Range, chunk digest 일치)으로 답함. 1.0.12에서 만든 세이브가 새 generation에서 200(같은 ETag·bytes, 이전 build 출처).
      • 실제 web app·Player를 Chromium으로 실행: frame data-content-mode=lazy, 선부팅 뒤 시작, 게임 읽기는 206 Range 1회뿐(전체 GET 0), OPFS chunk cache에 저장. 다시 열면 게임 byte를 하나도 받지 않음(cache hit).
      • 1.0.13에서 처음 준비한 두 번째 합성 VX Ace도 chunks 유지·Range 206. MZ build·세이브 불변. 재-update exit 0(13초), 변경 없음.
      • 1.0.12 rollback pin은 schema mismatch로 [4/6]에서 거부되고 container·schema·postgres가 바뀌지 않음. pin을 비운 update.sh로 복구(coordinator 재기동).
    • 알려진 제한·NOT RUN: 개발 계획 9.1 잔여 3건(MV/MZ 저장 단일 slot 1 MiB, web-static 검사의 주석 host 수집, 운영 memory·pid·shm 한도), R65c P3 후속(Player 세션 cache 시계, host-launch 실패 memo, 지연 경로 letterbox 측정 등, 개발 계획 9.2), 실제 망(느린 모바일)·느린 OPFS·실제 다중 탭 부하, 실제 모바일 기기, 실제 VX/VX Ace 게임과 실제 RTP, 실제 오디오 출력, 실제 NAS 갱신.

    배포 이미지와 파일

    • Git annotated tag는 1.0.13이고 최종 소스는 e43a2034b2입니다(branch release-1.0.13).
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.13 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:a718b2dc9b42742bc418739a44c7231097da669873e9cdbc1c7605cfee931068
    • release asset은 없습니다. update.sh가 tag 1.0.13의 5개 배포 파일을 HTTPS로 받습니다. 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2
  • LINKS 1.0.12 — ARCA 0.1.20 pin과 이전 Builder object 재사용

    LINKS 1.0.12

    이 릴리스는 이전 릴리스 1.0.11(8484a44e3d) 위에 ARCA를 0.1.20으로 올리고, 0.1.19 이하 Builder로 만든 VX/VX Ace 게임을 다시 준비할 때 실패하던 결함을 고쳤습니다. 최종 소스는 8843007119, 루트 패키지는 1.0.12, ARCA pin은 exact 0.1.20입니다. schema 변경이 없어 migration이 없습니다.

    업그레이드: 1.0.11 → 1.0.12는 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema 변경 없음: DB schema는 1.0.11과 같습니다(f7fe92f3…). update.sh는 Pending migrations: 줄을 출력하지 않습니다(대기 migration 0개).
    3. 배포 파일 변경 없음: update.sh가 받는 5개 파일(compose.yaml, infra/docker/Caddyfile, update.sh, reset.sh, ops/runtime-package-coordinator.sh)은 1.0.11과 byte 단위로 같습니다. 아무 파일도 설치하지 않고 image만 바뀝니다. .env.example도 바뀌지 않아 .env.production에 할 일이 없습니다. coordinator가 image에 든 ARCA 0.1.20 Builder OCI archive(61.9 MB)를 load합니다.
    cd /volume1/docker/links
    sh update.sh
    

    성공하면 단계 표시 6줄 뒤에 Updated to 1.0.12 (catalog 5440e5292d11), runtime.package ready.가 출력됩니다. 격리 gate에서 postgres container는 다시 만들어지지 않았습니다(DB 중단 0초). 원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.

    기존 VX/VX Ace 게임은 "새 준비 필요"로 바뀝니다. ARCA release manifest와 Builder digest가 달라졌기 때문입니다. 로그인 사용자가 게임을 다시 준비하면 새 실행 버전(generation)이 만들어지고, 이때 서버에 보관된 게임 archive는 그대로 재사용됩니다(다시 만들지 않음, 세이브 호환 유지). 다만 브라우저 캐시는 새 build 기준이라 첫 실행 때 게임을 다시 다운로드합니다. MV/MZ 게임은 영향이 없습니다. RTP 재준비·설정 변경·DB 작업·artifact 삭제 같은 운영자 작업은 없습니다.

    변경 내용

    ARCA 0.1.20 pin

    • @rgss23/arca를 exact 0.1.20으로 올렸습니다(SA-06 빠른 시작·heap 축소 release). LINKS에는 가산 변경이며 기존 heap 경로를 유지합니다. 0.1.20의 지연 콘텐츠·선부팅·폴더 실행은 아직 적용하지 않았습니다(후속 후보).
    • 키보드·터치 패드 입력의 keyboard.minimumPressMs는 SDK 기본값 50 ms를 그대로 씁니다.
    • 새 Builder manifest의 payload.archive.chunks를 보존해 host-launch의 game·RTP descriptor로 SDK에 넘깁니다. LINKS CAS의 artifact.json과 DB 형식은 바뀌지 않습니다.

    이전 Builder object 재사용(결함 수정)

    • 0.1.20 Builder는 같은 입력에 0.1.19와 byte가 같은 archive를 만들고 manifest에 chunks만 더합니다. 1.0.11까지는 0.1.19로 준비한 게임을 다시 준비하면 CAS import가 ARTIFACT_INVALID로 실패했습니다(기존 RGSS 게임 전부 재준비 불가).
    • 이제 새 manifest가 보관 manifest와 chunks 추가만 다를 때 보관 object와 descriptor를 그대로 재사용합니다(reused=true, chunks: null). 그 밖의 차이는 계속 거부합니다. descriptor가 유지되므로 이전 build에서 만든 세이브를 새 build에서 그대로 읽습니다.

    검증과 남은 범위

    • PASS: 브랜치 gate(고유 Compose project, BuildKit cache 없는 frozen install)
      • 설치본 identity: ARCA 0.1.20 release manifest a6dac661…, Builder digest sha256:6b0f47fa…, npm integrity sha512-b4QlYh…(lockfile·registry metadata·registry tarball 일치).
      • static(Prettier·ESLint·typecheck·docs-static), 전체 unit 153 files·1,263 tests, schema 34 files·235 tests, 문서 검사, git diff --check, deploy 기록기 96·reset 기록기 30 case, Compose config 3조합과 Watchtower label, foundation.
      • arca-npm-check(+ 3 files·40 tests), RGSS release-set·runtime-binding(67 files)·Builder(합성 VX Ace: chunks game 1, 이전 Builder object reused-without-chunks)·Builder 입력 5 case, Player DPR·터치 패드(Chromium·Firefox), browser acceptance mz-chromium(12개 단언, 공유 링크 게스트 실행).
    • PASS: 릴리스 gate(Compose v2.20.1, NAS 조건)
      • 환경: 격리 docker:24.0.2-dind, 공식 Docker Compose v2.20.1 binary(게시 checksum 일치), stager 1026:100, ./data bind store, library 최상위 0:0 000 + 1026 ACL, 합성 HTTPS release 서버와 합성 TLS registry.
      • 1.0.11 설치에서 합성 MZ ready build, ARCA 0.1.19 Builder로 만든 합성 VX Ace ready build, 로그인 사용자 세이브(MZ·VX Ace).
      • 설치된 1.0.11 sh update.sh → 1.0.12: exit 0(53초), Pending migrations: 줄 없음(schema current, 이력 변화 없음), 설치 0·배포 파일 크기·mtime 불변, 12개 service network 불일치 0·unhealthy 0·모두 Watchtower 제외, readiness PASS, catalog·Player 1.0.12·ARCA 0.1.20, Builder image rgss23-builder:0.1.20 = sha256:a2c4940d…(Docker 24 config digest). postgres 재생성 없음.
      • VX Ace 설치본이 "새 준비 필요"(needs-preparation, 요청 가능)로 바뀌고, 준비 요청 → package job 성공 → 0.1.20 새 generation 게시. 두 build가 같은 game artifact 행을 쓰고 CAS 파일의 bytes·mtime·inode가 1.0.11 때와 같음(보관 object 재사용, manifest에 chunks 없음). Player로 실행(rgss-wasm, host-launch·game archive 200, bytes 일치), 1.0.11에서 만든 세이브가 새 build에서 200(같은 ETag·bytes, 이전 build 출처).
      • 1.0.12에서 처음 준비한 두 번째 합성 VX Ace는 CAS manifest와 host-launch game descriptor에 같은 chunks(sha256, 1 MiB, digest 1개)가 있음. MZ build·세이브 불변. 재-update exit 0(12초), 변경 없음, 확인 반복 PASS.
      • gate에서 게시된 두 package(재사용 object·chunks 포함)를 실제 ARCA runtime(heap 경로)에서 실행: 키보드·터치 패드 입력, Player 음량·음소거 조절, DPR 표시 PASS(Chromium).
    • 리뷰: R64 '병합 가능'. R64 P2(기존 결함: generic artifact GC가 3파일 RGSS portable CAS object를 거부해 참조가 모두 사라진 object가 수거되지 않음, 삭제 위험은 없고 저장 공간 누수 가능)는 이 릴리스에서 고치지 않고 개발 계획의 후속 항목으로 기록했습니다.
    • 알려진 제한·NOT RUN: 실제 VX/VX Ace 게임과 실제 RTP, 실제 오디오 출력(합성 게임에 소리 없음), 실제 모바일 기기, 실제 NAS 갱신, 지연 콘텐츠·선부팅, browser matrix의 mv-chromium·mz-firefox·mv-firefox.

    배포 이미지와 파일

    • Git annotated tag는 1.0.12이고 최종 소스는 8843007119입니다(branch release-1.0.12).
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.12 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:5440e5292d11d2a6a0e518d50ffc3218b6893e970c274f3acb500aea61e0b6bb
    • release asset은 없습니다. update.sh가 tag 1.0.12의 5개 배포 파일을 HTTPS로 받습니다(1.0.11과 같은 내용). 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2
  • LINKS 1.0.11 — 게임 링크 Open Graph 임베드와 공개 표지 route

    LINKS 1.0.11

    이 릴리스는 이전 릴리스 1.0.10(6a9d016126) 위에 게임 링크의 Open Graph 미리보기(Discord 등 임베드)와 세션 없는 공개 표지 route를 얹었습니다. 최종 소스는 8484a44e3d, 루트 패키지는 1.0.11, ARCA pin은 exact 0.1.19(1.0.10과 같음)입니다. schema 변경이 없어 migration이 없습니다.

    업그레이드: 1.0.10 → 1.0.11은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema 변경 없음: DB schema는 1.0.10과 같습니다(f7fe92f3…). update.sh는 Pending migrations: 줄을 출력하지 않습니다(대기 migration 0개).
    3. 배포 파일 변경 없음: update.sh가 받는 5개 파일(compose.yaml, infra/docker/Caddyfile, update.sh, reset.sh, ops/runtime-package-coordinator.sh)은 1.0.10과 byte 단위로 같습니다. 그래서 아무 파일도 설치하지 않고 image만 바뀝니다. .env.example도 바뀌지 않아 .env.production에 할 일이 없습니다.
    4. 되돌리기: schema가 같으므로 문제가 생기면 1.0.10 image로 고정해 되돌릴 수 있습니다(update.sh가 실패할 때 출력하는 Rollback: LINKS_REGISTRY_TAG=…@sha256:…).
    cd /volume1/docker/links
    sh update.sh
    

    성공하면 단계 표시 6줄 뒤에 Updated to 1.0.11 (catalog 47795342a79b), runtime.package ready.가 출력됩니다. postgres 정의가 1.0.10과 같아 격리 gate에서 postgres container는 다시 만들어지지 않았습니다(DB 중단 0초). 원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.

    Discord 등은 이미 올린 링크의 미리보기를 캐시합니다. 배포 전에 올린 게임 링크는 예전(미리보기 없음) 모습으로 남을 수 있으니, 배포 뒤 링크를 다시 올려야 새 임베드가 나옵니다.

    변경 내용

    게임 링크 미리보기(Open Graph·twitter:card)

    • /games/<id>, /library?game=<id>, /play/<id>, /play/<공유 링크 token> 문서가 서버에서 Open Graph·twitter:card=summary tag를 담습니다. 제목은 catalog와 같은 표시 제목, 설명은 확인된 엔진(RPG Maker MZ 등)·제작사·LINKS에서 브라우저로 실행, 이미지는 그 게임의 공개 표지 URL(표지가 없으면 사이트 기본 이미지)입니다.
    • 로그인 여부와 무관하게 같은 미리보기를 보냅니다(사용자 결정 2026-10-15). 미리보기용으로 공개하는 것은 제목·표지·엔진(과 제작사)뿐이며, 목록·검색·상세 API와 실행은 여전히 로그인 또는 공유 링크 token이 필요합니다.
    • 없는 게임, 꺼진·없는 공유 링크, 형식이 잘못된 값, /와 그 밖의 문서는 사이트 기본 임베드(og:title LINKS, og:image /og-default.png, 512×512 자체 제작 PNG)로 200입니다. /play/ 뒤의 형식 오류·없는·꺼진 링크는 서로 구별되지 않는 같은 응답입니다.
    • 공유 링크 문서의 tag에는 token·hash가 없고 og:url도 넣지 않습니다(경로가 credential). og:image는 설치본 UUID 경로입니다. 미리보기 DB 조회는 한 번의 경량 조회이며 client 주소별 분당 설치본 120회·공유 링크 30회 예산을 쓰고, 넘으면 DB 조회 없이 사이트 기본 tag로 200을 보냅니다(문서 자체에 429 없음).
    • 구 VNDB cache만 있는 승인 VNDB 작품도 catalog 요약과 같은 제작사를 미리보기에 씁니다(R62b-01 수정).

    공개 표지 route

    • 새 API GET /api/v1/public/installations/<id>/cover(선택 ?variant=w320|w640)는 세션 없이 그 설치본의 현재 표지를 돌려줍니다. Cache-Control: public, max-age=3600, ETag(If-None-Match → 304), Cross-Origin-Resource-Policy: cross-origin, nosniff, client 주소별 분당 60회입니다. 없는 설치본·표지 없음은 404, 모르는 variant·query는 400입니다.
    • 공급자 표지를 미리보기로 재배포하는 조건과 아직 정하지 않은 age/content gating은 보안 문서에 기록했습니다.

    호환

    • API의 기존 응답은 바뀌지 않았습니다. 공유 링크 조회 API는 1.0.10과 같이 기본 네 key, ?include=cover에서만 cover를 더합니다.
    • 1.0.10에서 만든 공유 링크는 1.0.11에서 그대로 쓰이며 미리보기도 나옵니다(격리 gate에서 확인).

    검증과 남은 범위

    • PASS: 브랜치 gate(최종 1.0.11 소스, 고유 Compose project)
      • static(Prettier·ESLint·typecheck·docs-static), 전체 unit 153 files·1,257 tests, 문서 검사, git diff --check.
      • schema gate 34 files·235 tests(빈 DB fresh 적용과 1.0 기준 schema + 0001+0002 적용 결과의 구조 등가, 사슬, 링크 미리보기 4개 포함 — 새 회귀: 구 VNDB cache만 있는 승인 작품의 요약·미리보기 첫 제작사 일치).
      • deploy 기록기 96·reset 기록기 30 synthetic case, Compose config 3조합(19·19·30 services)과 Watchtower label, foundation.
      • browser acceptance mz-chromium: 12개 단언과 공유 링크 게스트 29개 단언(guestLinkPreviewMeta: 링크 문서 og:title=조회 제목, og:image=공개 표지 경로·cookie 없이 200 image, og:url·token 없음) PASS.
    • PASS: 릴리스 gate(Compose v2.20.1, NAS 조건)
      • 환경: 격리 docker:24.0.2-dind, 공식 Docker Compose v2.20.1 binary(게시 checksum 일치), stager 1026:100, ./data bind store, library 최상위 0:0 000 + 1026 ACL. 합성 HTTPS release 서버와 합성 TLS registry에 게시된 1.0.10 image와 이 릴리스의 1.0.11 image를 넣었습니다.
      • 1.0.10 설치 → reset.sh → update.sh, 합성 MZ ready build, 로그인 사용자 세이브, 표지 asset, 관리자 공유 링크 1개.
      • 설치된 1.0.10 sh update.sh → 1.0.11: exit 0(48초), Pending migrations: 줄 없음(대기 0, schema current f7fe92f3…, migration 이력 변화 없음), 5개 배포 파일이 1.0.10과 같아 설치 0·크기·mtime 불변, .tmp 0. 12개 service network 불일치 0·unhealthy 0·모두 Watchtower 제외, readiness PASS, catalog·Player 1.0.11. postgres container 재생성 없음(DB 중단 0초). 세이브·MZ ready·row count 불변.
      • 세션 없는 curl: /games/<id>·/library?game=<id>·/play/<id>·/play/<token>이 합성 제목 og:title·공개 표지 og:image·twitter:card=summary(token 문서는 og:url 없음, 본문에 token·hash 없음). 없는 UUID·꺼진 token·/는 og:image /og-default.png 기본 임베드이고 본문은 주소별 og:url tag만 다르며, 꺼진·없는·형식 오류 token 문서는 byte 단위로 같습니다. /og-default.png 200 image/png(8,678 bytes). 공개 표지 200(seed bytes, public, max-age=3600, ETag → 304), 없는 id 404, variant=w480 400. 서비스 로그(catalog·gateway·Player·broker) 전체에 token·hash 0건. 기존 공유 링크 확인(네 key, include=cover, token 표지, 게스트 실행, Player /save 403)도 PASS.
      • 재-update: exit 0(18초), 배포 파일 변경 없음, 위 확인 모두 반복 PASS.
    • 리뷰: R62(P2 무제한 공개 문서 DB 조회 → T62b 해소)·R62b 최종 '병합 가능'. R62b의 P3 2건(구 VNDB cache 제작사 누락, API 계약 fallback 문장)은 이 릴리스에서 고쳤습니다.
    • 알려진 제한·NOT RUN: 실제 Discord·Slack 미리보기 표시(NOT RUN, 합성 curl·browser 확인만), age/content gating 미결(제목·표지·엔진은 미리보기용으로 누구에게나 공개), 실제 NAS 갱신, 실제 Cloudflare 경유, live provider, browser matrix의 mv-chromium·mz-firefox·mv-firefox.

    배포 이미지와 파일

    • Git annotated tag는 1.0.11이고 최종 소스는 8484a44e3d입니다(branch release-1.0.11).
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.11 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:47795342a79bda7254342e80c9c4e6077252ea3eeaee29fea6f1281472836a69
    • release asset은 없습니다. update.sh가 tag 1.0.11의 5개 배포 파일을 HTTPS로 받습니다(1.0.10과 같은 내용). 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2
  • LINKS 1.0.10 — 터치 가상 패드·공유 링크 게스트 표지·지원 브라우저 안내

    LINKS 1.0.10

    이 릴리스는 이전 릴리스 1.0.9(53f517cd1e) 위에 터치 가상 패드, 공유 링크 게스트 표지, 지원 브라우저 안내를 얹었습니다. 최종 소스는 6a9d016126, 루트 패키지는 1.0.10, ARCA pin은 exact 0.1.19(1.0.9와 같음)입니다. schema 변경이 없어 migration이 없습니다.

    업그레이드: 1.0.9 → 1.0.10은 sh update.sh만 실행합니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다.
    2. schema 변경 없음: DB schema는 1.0.9와 같습니다(f7fe92f3…). update.sh는 Pending migrations: 줄을 출력하지 않습니다(대기 migration 0개).
    3. 배포 파일 변경 없음: update.sh가 받는 5개 파일(compose.yaml, infra/docker/Caddyfile, update.sh, reset.sh, ops/runtime-package-coordinator.sh)은 1.0.9와 byte 단위로 같습니다. 그래서 아무 파일도 설치하지 않고 image만 바뀝니다. .env.example도 바뀌지 않아 .env.production에 할 일이 없습니다.
    4. 되돌리기: schema가 같으므로 문제가 생기면 1.0.9 image로 고정해 되돌릴 수 있습니다(update.sh가 실패할 때 출력하는 Rollback: LINKS_REGISTRY_TAG=…@sha256:…).
    cd /volume1/docker/links
    sh update.sh
    

    성공하면 단계 표시 6줄 뒤에 Updated to 1.0.10 (catalog 6e511b7ea214), runtime.package ready.가 출력됩니다. postgres 정의가 1.0.9와 같아 격리 gate에서 postgres container는 다시 만들어지지 않았습니다(DB 중단 0초). 원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.

    변경 내용

    터치 가상 패드(VX/VX Ace)

    • 터치가 주 입력인 기기(휴대폰·태블릿)에서 RGSS(VX/VX Ace, ARCA) 게임 화면 위에 반투명 on-screen 패드가 나옵니다. 방향 D-pad(손가락을 떼지 않고 방향 전환, 모서리는 대각선), 확인, 취소(메뉴), 대시, 오른쪽 위 숨기기/패드 토글이 있습니다.
    • ARCA 0.1.19의 공개 player.input(setButton·releaseAll)에 연결합니다. 여러 손가락이 같은 버튼을 누르면 마지막 손가락을 뗄 때만 뗍니다. 재시작이 진행되는 동안에는 패드를 멈추고(흐리게 표시) 끝나면 로컬과 SDK의 누름 상태를 함께 비운 뒤 다시 받습니다. 탭 숨김·종료·실패에서도 누름을 해제합니다.
    • 주 pointer가 fine인 기기(데스크톱, 터치 노트북)에는 나오지 않습니다. 물리 키보드·게임패드는 함께 쓸 수 있습니다.
    • MV/MZ에는 패드를 그리지 않습니다. 엔진이 터치를 직접 처리합니다(한 손가락 tap = 결정, 두 손가락 = 취소).
    • 로그인 실행과 공유 링크 게스트 실행 모두에 적용됩니다.

    공유 링크 게스트 표지

    • 공유 링크 게스트 화면의 링크 확인 중·게임 불러오는 중·실행·실패·종료 화면에 그 게임의 표지가 나옵니다. 표지가 없거나 받지 못하면 로그인 실행 화면과 같은 placeholder(▶)를 보입니다.
    • 새 API GET /api/v1/play-links/:token/cover(선택 ?variant=w320|w640)는 링크 token 권한으로 그 링크의 설치본 현재 표지만 돌려줍니다. 경로에 asset ID가 없어 다른 설치본이나 다른 asset을 고를 수 없습니다. Cache-Control: private, no-store, 끈 링크는 410입니다.

    지원 브라우저 안내

    • 실행 실패가 브라우저 능력 결함일 때만(RUNTIME_WORKER_FAILED, SDK ENVIRONMENT_UNSUPPORTED, cross-origin isolation이 필요한 session에서 crossOriginIsolated·SharedArrayBuffer 없음) 실패 화면에 "지원 브라우저: Chrome·Edge·Firefox(데스크톱·Android). iOS Safari와 Arc 등 일부 모바일 브라우저는 지원하지 않습니다." 한 줄을 덧붙입니다. user agent로 추정하지 않으며 저장·세션 실패에는 붙이지 않습니다.
    • 문서에 iOS Safari 등 WebKit(opaque-origin sandbox frame의 blob: Worker를 COEP require-corp 아래에서 거부해 VX/VX Ace가 RUNTIME_WORKER_FAILED로 멈춤; Worker 생성은 ARCA 소유라 LINKS는 우회하지 않고 ARCA 요청 후보로 둠)와 Arc(모바일)(큰 artifact를 받기 전에 멈춤, 원인 미확인)를 NOT SUPPORTED로 기록했습니다.

    호환

    • 공유 링크 조회 API의 기본 응답은 1.0.9와 같습니다. GET /api/v1/play-links/:token은 여전히 정확히 네 key(installationId·title·engine·ready)를 돌려주고, 새 web만 ?include=cover를 보내 cover({width, height, variants} 또는 null)를 함께 받습니다. 그래서 갱신 중 열려 있던 1.0.9 게스트 페이지도 그대로 동작합니다. 반대로 새 web이 1.0.9 API를 만나면 cover 없는 응답을 표지 없음으로 받습니다.
    • 바뀐 점: 조회 API는 이제 모르는 query와 include의 다른 값을 400으로 거부합니다(1.0.9는 무시). 1.0.9 web은 query를 보내지 않으므로 영향이 없습니다.
    • 1.0.9에서 만든 공유 링크는 1.0.10에서 그대로 쓰입니다(격리 gate에서 확인).

    검증과 남은 범위

    • PASS: 브랜치 gate(최종 1.0.10 소스, 고유 Compose project)
      • static(Prettier·ESLint·typecheck·docs-static), 전체 unit 152 files·1,241 tests, 문서 검사, git diff --check.
      • schema gate 33 files·231 tests(빈 DB fresh 적용과 1.0 기준 schema + 0001+0002 적용 결과의 구조 등가, 사슬, 공유 링크 표지·기본 응답 네 key 포함).
      • deploy 기록기 96·reset 기록기 30 synthetic case, Compose config 3조합(19·19·30 services)과 Watchtower label, foundation.
      • 터치 패드 gate run-player-touch-pad: Chromium(모바일 emulation, CDP touch 탭만으로 합성 VX Ace 진행·재시작 중 누름 거부)·Firefox PASS. 고 DPR gate run-player-dpr: Chromium·Firefox PASS.
      • browser acceptance mz-chromium: 12개 단언(MZ frame에 패드 없음, 지원 브라우저 안내 없음 포함)과 공유 링크 게스트 28개 단언(표지 확인 중·로드 뒤·게임 불러오는 중·실패 fallback·좁은 화면·종료 화면, 기본 조회 호환 포함) PASS.
    • PASS: 릴리스 gate(Compose v2.20.1, NAS 조건)
      • 환경: 격리 docker:24.0.2-dind, 공식 Docker Compose v2.20.1 binary(게시 checksum 일치), stager 1026:100, ./data bind store, library 최상위 0:0 000 + 1026 ACL. 합성 HTTPS release 서버와 합성 TLS registry에 게시된 1.0.9 image와 이 릴리스의 1.0.10 image를 넣었습니다.
      • 1.0.9 설치 → reset.sh → update.sh, 합성 MZ ready build, 로그인 사용자 세이브, 표지 asset, 관리자 공유 링크 1개.
      • 설치된 1.0.9 sh update.sh → 1.0.10: exit 0(52초), Pending migrations: 줄 없음(대기 0, schema current f7fe92f3…, migration 이력 변화 없음), 5개 배포 파일이 1.0.9와 같아 설치 0·크기·mtime 불변, .tmp 0. 12개 service network 불일치 0·unhealthy 0·모두 Watchtower 제외, readiness PASS, catalog·Player 1.0.10. postgres container 재생성 없음(DB 중단 0초). 세이브 ETag·bytes·Player save 파일 목록 불변, MZ ready 유지, row count 불변.
      • 1.0.9에서 만든 공유 링크를 세션 없이: 조회 200·정확히 네 key, ?include=cover 200·cover 포함, ?include=other 400, /cover 200 image/png(seed한 표지와 bytes 동일, private, no-store), /play/<token> 200, 목록 API 401, 게스트 PlaySession·Player launch 200, Player /save GET·POST 403. 끈 뒤 조회·표지 410.
      • 재-update: exit 0(13초), 배포 파일 변경 없음, 위 확인 모두 반복 PASS.
    • 리뷰: R59·R59b(터치 패드, R59 P2 재시작 경합 → R59b 해소), R60·R60b(게스트 표지, R60 P1 1.0.9 web 호환 → R60b 해소) 최종 '병합 가능'.
    • 알려진 제한·NOT RUN: 실제 iOS·Android 기기에서의 패드 조작과 실제 VX Ace 게임의 패드 조작, Firefox의 touch 탭 흐름(CDP touch 없음; 표시 판정과 mouse 입력만 확인), Arc 모바일 실패 원인(미상), 실제 NAS 갱신, 실제 Cloudflare 경유, live provider, browser matrix의 mv-chromium·mz-firefox·mv-firefox.

    배포 이미지와 파일

    • Git annotated tag는 1.0.10이고 최종 소스는 6a9d016126입니다(branch release-1.0.10).
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.10 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:6e511b7ea21427edb58644eba41ded437ade45bf5a49eac8c673c277d2d448e7
    • release asset은 없습니다. update.sh가 tag 1.0.10의 5개 배포 파일을 HTTPS로 받습니다(1.0.9와 같은 내용). 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2
  • LINKS 1.0.9 — 게스트 공유 링크·ARCA 0.1.19 모바일 배율·backup 기능 제거

    LINKS 1.0.9

    이 릴리스는 이전 릴리스 1.0.8(9f4ada7c6c) 위에 게스트 공유 링크, ARCA 0.1.19 모바일 배율 수정, backup 기능 제거를 얹었습니다. 최종 소스는 53f517cd1e, 루트 패키지는 1.0.9, ARCA pin은 exact 0.1.19(1.0.8은 0.1.18)입니다. schema migration 2개(0001_guest_play_links, 0002_remove_backup)가 적용됩니다.

    업그레이드 주의: 1.0.8 → 1.0.9는 sh update.sh만 실행합니다. migration이 적용된 뒤에는 1.0.8 image로 되돌릴 수 없습니다

    1. 갱신 방법: 배포 디렉터리에서 sh update.sh만 실행합니다. reset.sh는 실행하지 않습니다. update.sh가 Pending migrations: 2를 출력하고 up 때 migration이 두 migration과 schema 버전 갱신을 한 transaction으로 적용합니다(schema 14481d17… → b5dd04a0… → f7fe92f3…).
    2. 되돌릴 수 없음: migration이 적용된 DB는 1.0.8 image의 사슬 밖이라 1.0.8로 기동하지 않습니다. backup 기능이 제거되어 rollback snapshot이 없습니다. migration이 반영된 뒤 실패하면 이전 image로 되돌리지 말고 원인을 고쳐 다시 갱신합니다.
    3. 갱신 뒤 정리: 새 update.sh가 설치 단계에서 NAS의 backup.sh와 ops/backup-verify.compose.yaml(남은 .tmp 포함)을 자동으로 지웁니다. .env.production의 LINKS_BACKUP_* 키와 data/backups 디렉터리는 LINKS가 더 이상 쓰지 않으므로 운영자가 지웁니다.
    4. 호환 stub: 설치된 1.0.8 update.sh는 자기 7개 파일 목록을 새 tag에서 모두 받은 뒤 새 update.sh로 넘어가므로, 저장소의 ops/backup-registry.sh·ops/backup-verify.compose.yaml 경로에 다운로드 호환 stub 2개를 남겼습니다(실행하지 않음, 1.0.9 update.sh는 받지도 설치하지도 않음). 모든 설치가 1.0.9 이상이 되면 제거할 예정입니다.
    cd /volume1/docker/links
    sh update.sh
    

    성공하면 단계 표시 6줄과 Pending migrations: 2 뒤에 Updated to 1.0.9 (catalog 9148653250cf), runtime.package ready.가 출력됩니다. compose.yaml의 postgres 정의는 1.0.8과 같아 격리 gate에서 postgres container는 다시 만들어지지 않았습니다(DB 중단 0초). 원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.

    변경 내용

    게스트 공유 링크

    • 관리자는 ready build가 있는 설치본에 대해 관리 화면에서 <catalog origin>/play/<token> 공유 링크를 만들고 끌 수 있습니다. 링크 주소(token)는 만들 때 한 번만 보이며 DB에는 token의 SHA-256 hash(play_share_links)만 저장됩니다.
    • 세션이 없는 게스트는 그 링크로만 게임을 실행합니다. 홈은 로그인 안내를 보여 주고 목록 API는 401입니다. 게스트 PlaySession은 사용자 대신 공유 링크를 principal로 가집니다(migration 0001_guest_play_links).
    • 게스트 세이브는 그 브라우저의 IndexedDB에만 남습니다. Player의 서버 세이브(/save)는 게스트에게 403입니다.
    • 링크를 끄면 실행 중인 게스트 게임은 약 60초 안에 멈추고, 꺼진 링크는 사용이 중지된 공유 링크입니다로 거부됩니다.

    ARCA 0.1.19 모바일 배율

    • @rgss23/arca exact pin을 0.1.19로 올렸습니다. 고 DPR(모바일) 화면에서 RGSS 게임 배율이 어긋나던 문제를 고친 release입니다(backing store의 DPR 동기화, logicalWidth·logicalHeight 통지, RetroArch presentation geometry).
    • Player frame은 canvas backing 대신 ARCA가 통지한 논리 해상도를 화면 크기로 보고합니다. 고 DPR gate tests/run-player-dpr.*가 Chromium·Firefox에서 DPR 1·2·3과 회전·주소창·resize_screen·100% 배율을 확인합니다.
    • release identity가 바뀌므로 기존 VX/VX Ace active build는 다음 실행 준비에서 새 generation을 만듭니다. 이미지 갱신 외의 운영자 작업은 없습니다.

    backup 기능 제거

    backup 기능 제거: backup.sh·복구 drill·LINKS_BACKUP_* 설정·backup evidence 테이블 삭제(migration 0002). runtime GC는 더 이상 backup 검증을 기다리지 않고 유예·세션·hold만으로 퇴역 build를 삭제한다. 1.0.9부터 migration 릴리즈는 rollback snapshot 없이 진행된다. 기존 data/backups 디렉터리는 LINKS가 쓰지 않으므로 운영자가 삭제한다. 1.0.8에서의 sh update.sh는 그대로 동작하며(release에 남긴 호환 stub), 갱신 뒤 NAS의 backup.sh·ops/backup-verify.compose.yaml은 자동으로 지워진다.

    • backup Compose service와 .env.example의 LINKS_BACKUP_SOURCE도 지웠습니다. update.sh가 받는 배포 파일은 7개에서 5개(compose.yaml, infra/docker/Caddyfile, update.sh, reset.sh, ops/runtime-package-coordinator.sh)로 줄었습니다.
    • 그대로인 것: 1.0.8의 postgres TCP+select 1 healthcheck와 모든 service의 Watchtower 제외 label.

    운영자 주의

    • 공유 링크는 관리 화면의 설치본 대화상자에서 만들고 끕니다. 쓰지 않는 링크는 끕니다.
    • 게스트의 세이브는 게스트 브라우저에만 남으며 서버에서 복구·이전할 수 없습니다.

    검증과 남은 범위

    • PASS: 브랜치 gate(최종 1.0.9 소스, 고유 Compose project)
      • static(Prettier·ESLint·typecheck·docs-static), 전체 unit 149 files·1,222 tests, 문서 검사, git diff --check.
      • schema gate 33 files·230 tests: 빈 DB fresh 적용과 1.0.8 기준 schema + 0001+0002 migration 적용 결과의 구조 등가, 사슬 base → 기준 schema, GC 5 tests.
      • deploy 기록기 96·reset 기록기 30 synthetic case, Compose config 3조합(19·19·30 services)과 Watchtower label, foundation, postgres-init-race 1회, runtime-workers(evidence 없이 grace가 지난 첫 build GC 완료).
      • browser acceptance mz-chromium: 입력·CSP·Bearer·sandbox 격리·서버 세이브 복원·retained build와 공유 링크 게스트 단계 21개 단언(게스트 홈·목록 401, 브라우저 세이브·reload 복원, Player save 요청 0, 링크 끄기 뒤 실행 중·실패 화면 게임 종료 약 60초, 모르는·준비 안 된 링크 거부).
      • 고 DPR gate: Chromium·Firefox 각 42 측정 PASS.
    • PASS: 릴리스 gate(Compose v2.20.1, NAS 조건)
      • 환경: 격리 docker:24.0.2-dind, 공식 Docker Compose v2.20.1 binary(게시 checksum 일치), stager 1026:100, ./data bind store, library 최상위 0:0 000 + 1026 ACL. 합성 HTTPS release 서버와 합성 TLS registry에 게시된 1.0.8 image와 이 릴리스의 1.0.9 image를 넣었습니다.
      • 1.0.8 설치 → reset.sh → update.sh, 합성 MZ ready build, 로그인 사용자 세이브(ETag 기록), sh backup.sh 1회(backup run·released pin·evidence 행 생성).
      • 설치된 1.0.8 sh update.sh → 1.0.9: exit 0(47초), Pending migrations: 2, 5개 파일 설치·release와 동일, 구 backup.sh·ops/backup-verify.compose.yaml 삭제, .tmp 0. schema current(이력 0001 → 0002), backup table 없음·pin 종류 play-session만. 12개 service network 불일치 0·unhealthy 0·모두 Watchtower 제외, readiness PASS, catalog·Player 1.0.9. postgres container 재생성 없음. 세이브 ETag·bytes·Player save 파일 목록 불변, MZ ready 유지, row count 불변.
      • 공유 링크: 관리자 API로 생성 201 → 세션 없이 /play/<token> 200(no-store), 링크 조회 ready, 목록 API 401, 게스트 PlaySession·Player launch 200, Player /save GET·POST 403 → 끈 뒤 조회 410.
      • 재-update: exit 0(13초), 배포 파일 변경 없음.
    • 리뷰: R46c(게스트 공유 링크 보안 3라운드), R50b(ARCA 0.1.19 pin 2라운드), R57(backup 제거) 모두 '병합 가능'.
    • 알려진 제한·NOT RUN: 실제 NAS 갱신, 실제 모바일 기기와 실제 VX/VX Ace 게임의 고 DPR 표시, 실제 Cloudflare 경유 확인, live provider. PostgreSQL·Player 컨테이너 재시작 뒤 데이터 지속성 전용 gate가 없습니다(backup-restore runner 삭제로 생긴 공백, R57-01, 개발 계획 후속). ARCA 0.1.19의 resize_screen letterbox 바깥 잔상은 ARCA 후속 항목입니다.

    배포 이미지와 파일

    • Git annotated tag는 1.0.9이고 최종 소스는 53f517cd1e입니다(branch release-1.0.9).
    • 단일 linux/amd64 이미지: git.2ex.dev/hanyul/links:1.0.9 = git.2ex.dev/hanyul/links:latest
    • 원격 digest: sha256:9148653250cf303f046ead45d826cc55d8d069fb581443fc624d49c7e3da2131
    • release asset은 없습니다. update.sh가 tag 1.0.9의 5개 배포 파일을 HTTPS로 받습니다. 대응은 update.sh=ops/deploy-registry.sh, reset.sh=ops/reset-registry.sh이고, 나머지는 compose.yaml·infra/docker/Caddyfile·ops/runtime-package-coordinator.sh입니다.
    Downloads 2