콘텐츠로 이동

2.5.0 릴리스 실행 기록

{
  "schema": "release-metadata/v3",
  "version": "v2.5.0",
  "status": "released",
  "releaseScopes": [
    "db-migration",
    "contracts-package",
    "coupler-api",
    "coupler-admin-web",
    "mobile-nextpush",
    "docs"
  ],
  "extraRepoRefs": [],
  "versionMapping": {
    "docs": {
      "tag": "v2.5.0",
      "commit": null
    },
    "coupler-api": {
      "tag": "v2.5.0",
      "commit": "c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3"
    },
    "coupler-admin-web": {
      "tag": "v2.5.0",
      "commit": "fcde62ef660e9e06c8721898d38e81bda4af6ecf"
    },
    "coupler-mobile-app": {
      "store": {
        "android": {
          "versionBuild": "2.4.2 (103)",
          "releaseTag": "v2.4.2",
          "commit": "37c0da07d22704c3a28723ec6d08758bff0f1aae",
          "sourceStatus": "verified",
          "limitation": null
        },
        "ios": {
          "versionBuild": "2.4.2 (103)",
          "releaseTag": "v2.4.2",
          "commit": "37c0da07d22704c3a28723ec6d08758bff0f1aae",
          "sourceStatus": "verified",
          "limitation": null
        }
      },
      "nextPush": "Android bluedotstudio.official-gmail.com/coupler/Production v28 target 2.4.2; iOS bluedotstudio.official-gmail.com/coupler-ios/Production v25 target 2.4.2",
      "commit": "6050c86d01e61d45d866c00ef332eda040909909"
    }
  },
  "scopeResults": {
    "db-migration": {
      "status": "released",
      "summary": "개발계 apply·status에서 미적용 migration 0건을 확인한 source c0e70bbe를 그대로 운영계에 적용하고 운영 ledger 88건·미적용 migration 0건을 확인했다.",
      "evidence": {}
    },
    "contracts-package": {
      "status": "released",
      "summary": "contracts 0.1.32 stable 발행과 Admin·Mobile exact pin, API release source tree 일치를 확인했다.",
      "evidence": {
        "publishedPackage": "@coupler-developer/coupler-api-contracts@0.1.32",
        "workflow": "https://github.com/coupler-developer/coupler-api/actions/runs/31771588474",
        "sourceRef": "c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3",
        "sourceTree": {
          "path": "packages/contracts",
          "publishedSourceTree": "e76c3329a2f39087d09f587e6379ef32c2ed885f",
          "releaseSourceTree": "e76c3329a2f39087d09f587e6379ef32c2ed885f"
        }
      }
    },
    "coupler-api": {
      "status": "released",
      "summary": "운영 DB 반영 뒤 API source c0e70bbe를 production PM2에 배포하고 v2.5.0 annotated tag로 고정했다.",
      "evidence": {
        "deployment": "2026-08-14 KST /home/projects/coupler-api를 e4e344f3에서 c0e70bbe로 fast-forward하고 frozen install 뒤 production PM2 startOrReload·save를 완료했으며 remote HEAD와 v2.5.0 peeled target이 c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3으로 일치한다.",
        "smoke": "reload 직후 5ms 시점 최초 내부 curl은 readiness race로 connection refused였고 재배포 없이 PM2 online·production, startup log server started on port 3002, 내부 root HTTP 200과 https://api.ritzy.fourhundred.co.kr/ HTTP 200을 확인했다.",
        "publicContract": {
          "apiRefs": {
            "previous": "e4e344f3287c3c81a260ed98d00d1e8ce5a69960",
            "current": "c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3"
          },
          "contractRefs": {
            "previous": "@coupler-developer/coupler-api-contracts@0.1.31",
            "current": "@coupler-developer/coupler-api-contracts@0.1.32"
          },
          "consumers": [
            {
              "state": "present",
              "id": "previous-store",
              "surface": "mobile-store",
              "generation": "previous",
              "artifact": {
                "kind": "store-builds",
                "mappingRef": "Android 2.4.2 (103); iOS 2.4.2 (103)",
                "iosVersionBuild": "2.4.2 (103)",
                "androidVersionBuild": "2.4.2 (103)"
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.30",
              "interfaces": ["rest", "websocket", "bootstrap", "version"],
              "interfaceInventoryEvidence": "Mobile Store v2.4.2 source 37c0da07 exact pins contracts 0.1.30 and contains REST, group-chat WebSocket, bootstrap and version consumers."
            },
            {
              "state": "present",
              "id": "current-store",
              "surface": "mobile-store",
              "generation": "current",
              "artifact": {
                "kind": "store-builds",
                "mappingRef": "Android 2.4.2 (103); iOS 2.4.2 (103)",
                "iosVersionBuild": "2.4.2 (103)",
                "androidVersionBuild": "2.4.2 (103)"
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.30",
              "interfaces": ["rest", "websocket", "bootstrap", "version"],
              "interfaceInventoryEvidence": "릴리스 뒤에도 fallback인 Mobile Store v2.4.2 source 37c0da07은 contracts 0.1.30과 REST, group-chat WebSocket, bootstrap, version 소비 경로를 그대로 유지한다."
            },
            {
              "state": "present",
              "id": "previous-nextpush",
              "surface": "mobile-nextpush",
              "generation": "previous",
              "artifact": {
                "kind": "nextpush-deployment",
                "mappingRef": "Android bluedotstudio.official-gmail.com/coupler/Production v27 target 2.4.2; iOS bluedotstudio.official-gmail.com/coupler-ios/Production v24 target 2.4.2",
                "ios": {
                  "app": "bluedotstudio.official-gmail.com/coupler-ios",
                  "deployment": "Production",
                  "label": "v24",
                  "cohort": "100%",
                  "targetBinary": "2.4.2 (103)"
                },
                "android": {
                  "app": "bluedotstudio.official-gmail.com/coupler",
                  "deployment": "Production",
                  "label": "v27",
                  "cohort": "100%",
                  "targetBinary": "2.4.2 (103)"
                }
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.30",
              "interfaces": ["rest", "websocket", "bootstrap", "version"],
              "interfaceInventoryEvidence": "배포 전 Production history의 Android v27·iOS v24는 Store 2.4.2 대상 기존 Mobile 경로로 REST, group-chat WebSocket, bootstrap, version을 소비한다."
            },
            {
              "state": "present",
              "id": "current-nextpush",
              "surface": "mobile-nextpush",
              "generation": "current",
              "artifact": {
                "kind": "nextpush-deployment",
                "mappingRef": "Android bluedotstudio.official-gmail.com/coupler/Production v28 target 2.4.2; iOS bluedotstudio.official-gmail.com/coupler-ios/Production v25 target 2.4.2",
                "ios": {
                  "app": "bluedotstudio.official-gmail.com/coupler-ios",
                  "deployment": "Production",
                  "label": "v25",
                  "cohort": "100%",
                  "targetBinary": "2.4.2 (103)"
                },
                "android": {
                  "app": "bluedotstudio.official-gmail.com/coupler",
                  "deployment": "Production",
                  "label": "v28",
                  "cohort": "100%",
                  "targetBinary": "2.4.2 (103)"
                }
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.32",
              "interfaces": ["rest", "websocket", "bootstrap", "version"],
              "interfaceInventoryEvidence": "Mobile source 6050c86d와 contracts 0.1.32로 생성한 Android v28·iOS v25 bundle은 REST, group-chat WebSocket, bootstrap, version 소비 경로를 포함한다."
            },
            {
              "state": "present",
              "id": "previous-admin",
              "surface": "admin",
              "generation": "previous",
              "artifact": {
                "kind": "admin-build",
                "artifactRef": "bf64bce4a22a62ed6e314c25bef623aa06caebf1"
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.31",
              "interfaces": ["rest", "websocket"],
              "interfaceInventoryEvidence": "배포 전 Admin source map hash로 고정한 bf64bce4는 contracts 0.1.31의 REST 소비와 concierge WebSocket lifecycle을 포함한다."
            },
            {
              "state": "present",
              "id": "current-admin",
              "surface": "admin",
              "generation": "current",
              "artifact": {
                "kind": "admin-build",
                "artifactRef": "fcde62ef660e9e06c8721898d38e81bda4af6ecf"
              },
              "contractRef": "@coupler-developer/coupler-api-contracts@0.1.32",
              "interfaces": ["rest", "websocket"],
              "interfaceInventoryEvidence": "Admin source fcde62ef와 production artifact는 contracts 0.1.32 exact pin의 REST 소비 및 기존 concierge WebSocket lifecycle을 포함한다."
            }
          ],
          "cases": [
            {"id":"previous-store-rest-current-api","consumerId":"previous-store","interface":"rest","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe verify의 generated REST contract와 additive group-meeting route 검증이 Store 2.4.2 기존 REST 요청을 유지했다."},
            {"id":"previous-store-websocket-current-api","consumerId":"previous-store","interface":"websocket","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe chat 회귀 검증에서 방 알림 OFF도 전체 member WebSocket publish를 유지했다."},
            {"id":"previous-store-bootstrap-current-api","consumerId":"previous-store","interface":"bootstrap","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe verify가 기존 Mobile bootstrap 응답 계약을 변경 없이 통과했다."},
            {"id":"previous-store-version-current-api","consumerId":"previous-store","interface":"version","apiGeneration":"current","exposure":"rollback","expected":"success","evidence":"API c0e70bbe verify가 Store 2.4.2 version 확인 경로의 기존 응답 계약을 유지했다."},
            {"id":"current-store-rest-current-api","consumerId":"current-store","interface":"rest","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Store v2.4.2 source 37c0da07의 contracts 0.1.30 REST 요청은 API c0e70bbe의 additive route 변경 뒤에도 유지됐다."},
            {"id":"current-store-websocket-current-api","consumerId":"current-store","interface":"websocket","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"API c0e70bbe chat 회귀 검증이 Store v2.4.2 fallback의 group-chat WebSocket envelope를 유지했다."},
            {"id":"current-store-bootstrap-current-api","consumerId":"current-store","interface":"bootstrap","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"API c0e70bbe verify가 Store v2.4.2 contracts 0.1.30 bootstrap 응답 계약을 유지했다."},
            {"id":"current-store-version-current-api","consumerId":"current-store","interface":"version","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"API c0e70bbe verify가 Store v2.4.2 contracts 0.1.30 version 응답 계약을 유지했다."},
            {"id":"previous-nextpush-rest-current-api","consumerId":"previous-nextpush","interface":"rest","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"Android v27·iOS v24가 사용하던 REST 경로는 c0e70bbe의 additive 필드·command 추가 뒤에도 제거 또는 변경되지 않았다."},
            {"id":"previous-nextpush-websocket-current-api","consumerId":"previous-nextpush","interface":"websocket","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe chat 회귀 검증이 이전 NextPush 소비자의 WebSocket message envelope를 유지했다."},
            {"id":"previous-nextpush-bootstrap-current-api","consumerId":"previous-nextpush","interface":"bootstrap","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe verify가 Android v27·iOS v24의 기존 bootstrap 계약을 유지했다."},
            {"id":"previous-nextpush-version-current-api","consumerId":"previous-nextpush","interface":"version","apiGeneration":"current","exposure":"rollback","expected":"success","evidence":"API c0e70bbe verify가 이전 NextPush rollback 뒤 사용할 version 경로를 유지했다."},
            {"id":"current-nextpush-rest-current-api","consumerId":"current-nextpush","interface":"rest","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Mobile 6050c86d request body와 API c0e70bbe command response가 contracts 0.1.32 DTO로 결박돼 전체 verify를 통과했다."},
            {"id":"current-nextpush-websocket-current-api","consumerId":"current-nextpush","interface":"websocket","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Mobile 6050c86d race 회귀와 API c0e70bbe chat 회귀가 알림 토글 뒤에도 WebSocket 수신을 유지했다."},
            {"id":"current-nextpush-bootstrap-current-api","consumerId":"current-nextpush","interface":"bootstrap","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Android v28·iOS v25 bundle 전 contracts 0.1.32 exact pin 검사가 bootstrap 소비 source와 일치했다."},
            {"id":"current-nextpush-version-current-api","consumerId":"current-nextpush","interface":"version","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Android v28·iOS v25 bundle 전 contracts 0.1.32 exact pin 검사가 version 소비 source와 일치했다."},
            {"id":"previous-admin-rest-current-api","consumerId":"previous-admin","interface":"rest","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe는 기존 Admin list 기본 query를 보존하고 sort pair만 선택적으로 추가했으며 전체 API verify를 통과했다."},
            {"id":"previous-admin-websocket-current-api","consumerId":"previous-admin","interface":"websocket","apiGeneration":"current","exposure":"activation","expected":"success","evidence":"API c0e70bbe는 기존 Admin concierge WebSocket 경로를 변경하지 않았고 전체 회귀 검증을 통과했다."},
            {"id":"current-admin-rest-current-api","consumerId":"current-admin","interface":"rest","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Admin fcde62ef와 API c0e70bbe의 sort enum·pair parser·generated query 계약이 contracts 0.1.32 기준으로 전체 verify를 통과했다."},
            {"id":"current-admin-websocket-current-api","consumerId":"current-admin","interface":"websocket","apiGeneration":"current","exposure":"post-activation","expected":"success","evidence":"Admin fcde62ef 전체 verify가 기존 concierge WebSocket lifecycle 회귀를 포함해 통과했다."}
          ]
        },
        "runtimeRecovery": {
          "strategy": "forward-fix",
          "stateSafety": {
            "source": "application-evidence",
            "persistedState": "신규 chat_message_notification_enabled는 NOT NULL DEFAULT 1의 additive column이며 운영 migration ledger 88건·미적용 migration 0건 뒤 기존 row와 새 runtime이 같은 상태를 읽는다.",
            "queuedState": "메시지 저장·전체 member WebSocket publish·unread invalidation ownership은 유지되고 방 설정은 type 82 push 수신자 선필터에만 적용된다.",
            "externalEffects": "방별 설정은 이후 type 82 FCM과 t_alarm 발송만 제어하며 durable outbox나 다른 77~81·83~85 알림 효과를 변경하지 않아 문제 시 c0e70bbe 기반 forward fix를 사용한다."
          },
          "previousReleaseCaseIds": []
        }
      }
    },
    "coupler-admin-web": {
      "status": "released",
      "summary": "Admin source fcde62ef의 production build를 원자 교체하고 HTTP·Arc 그룹미팅 정렬 smoke 뒤 v2.5.0 annotated tag로 고정했다.",
      "evidence": {
        "deployment": "source fcde62ef의 production build main.708d3827.js를 포함한 coupler-admin-web-fcde62ef660e9e06c8721898d38e81bda4af6ecf.tar.gz SHA-256 08e3741cbfbc13f9297514a9ec562ec368f9d206a17b4ba4fbdf1c239b1969b8과 index.html SHA-256 43f7a6c056a85760ec68abe0c6d4b3f9d519dce1d5ed8c19d58c9afa4371f87c를 검증하고 /var/www/coupler-admin-web index를 원자 교체했으며 v2.5.0 peeled target을 fcde62ef660e9e06c8721898d38e81bda4af6ecf로 고정했다.",
        "smoke": "내부 http://127.0.0.1:8000/과 외부 https://cms.ritzy.fourhundred.co.kr/가 HTTP 200을 반환했고, 출시 책임자가 2026-08-14 KST Arc 로그인 후 그룹미팅 목록 일시 헤더의 오름차순·내림차순 전환이 정상임을 확인했다.",
        "rollback": "배포 직전 source bf64bce4a22a62ed6e314c25bef623aa06caebf1·index SHA-256 acd7f9cfba099686aaf20d672811b9b16c50c3e325cd2010a36644ba40cf4c87을 /var/www/coupler-admin-web-backup-20260814T073253Z에 metadata와 함께 봉인했다."
      }
    },
    "mobile-nextpush": {
      "status": "released",
      "summary": "Store 2.4.2 (103)을 대상으로 Mobile source 6050c86d의 Android v28·iOS v25 Production NextPush를 배포하고 운영 history를 확인했다.",
      "evidence": {
        "app": "Android bluedotstudio.official-gmail.com/coupler/Production; iOS bluedotstudio.official-gmail.com/coupler-ios/Production",
        "productionLabel": "Android v28; iOS v25",
        "androidPackageHash": "9311edd1ad702431653537594378041590f8317987179ed48f00e08a1d896789",
        "iosPackageHash": "da3e2803f2abd845bb4375cc4312b3bcff3cbef58ac93a20fc6aa1b54bde2713",
        "targetBinary": "Android/iOS 2.4.2 (103)",
        "uploadedAt": "Android 2026-08-14 17:01:24 KST; iOS 2026-08-14 17:02:39 KST",
        "history": "배포 뒤 Production history에서 Android v28·iOS v25, target 2.4.2, mandatory true, disabled false, rollout 100%와 각 package SHA-256을 확인했다.",
        "rollbackTarget": "Android v27 package 99535d8182ad4c799255b0261c85f616df70892f8f1b2d40478e8394ac76fb66; iOS v24 package 10678b5de30746675aaccc4ecad3bbd0c00345666728ebd0a8f6abf9da1a4725",
        "rollout": "Android 100%; iOS 100%",
        "mandatory": "Android true; iOS true",
        "disabled": "Android false; iOS false"
      }
    },
    "docs": {
      "status": "released",
      "summary": "운영 결과와 NextPush label·bundle hash·rollback target을 최종 기록으로 고정하고 병합 뒤 docs v2.5.0을 발행한다.",
      "evidence": {}
    }
  },
  "apiContractCutover": null
}

문서 역할

  • 역할: 시나리오
  • 문서 종류: flow
  • 충돌 시 우선 문서: policy/release-process.md, 태그 기준은 policy/release-tag-policy.md
  • 기준 성격: as-is

목적

  • 그룹미팅 단체채팅 방별 메시지 알림 설정과 CMS 그룹미팅 다열 정렬을 운영계에 반영한다.
  • additive DB/API 계약을 기존 Store 2.4.2 (103)과 호환되게 유지하고, Mobile 변경은 Store 제출 없이 Android·iOS Production NextPush로 배포한다.

범위

  • 대상: docs, coupler-api, coupler-admin-web, coupler-mobile-app
  • 포함 범위: 운영 DB migration, contracts 0.1.32, API·Admin 운영 배포와 v2.5.0 서비스 태그, Android·iOS Production NextPush, docs 최종 기록·태그
  • 제외 범위: Mobile Store 제출·승인·출시, native version/build 변경, Mobile 서비스 태그, reviewer 변경

상위 규범 문서

릴리스 상태

  • 목표 버전: v2.5.0
  • 전체 상태: released
  • 완료 범위: 운영 DB migration, contracts 0.1.32, API·Admin 배포·smoke·태그, Android·iOS Production NextPush 배포·history 검증, docs 최종 기록

버전 매핑

  • docs: 기록 버전 v2.5.0, 태그 v2.5.0, 커밋 N/A
  • coupler-api: 태그 v2.5.0, 커밋 c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3
  • coupler-admin-web: 태그 v2.5.0, 커밋 fcde62ef660e9e06c8721898d38e81bda4af6ecf
  • coupler-mobile-app: Android Store 2.4.2 (103), Android 릴리스 태그 v2.4.2, Android 커밋 37c0da07d22704c3a28723ec6d08758bff0f1aae, Android source verified, iOS Store 2.4.2 (103), iOS 릴리스 태그 v2.4.2, iOS 커밋 37c0da07d22704c3a28723ec6d08758bff0f1aae, iOS source verified, NextPush Android bluedotstudio.official-gmail.com/coupler/Production v28 target 2.4.2; iOS bluedotstudio.official-gmail.com/coupler-ios/Production v25 target 2.4.2, NextPush 커밋 6050c86d01e61d45d866c00ef332eda040909909

릴리스 결과

Scope 상태 결과·증빙
DB migration released 개발계 검증과 동일한 source c0e70bbe 운영 적용, ledger 88건·미적용 0건
contracts package released 0.1.32, workflow run 31771588474, source/tree 일치
API released c0e70bbe production PM2 online, 내부·외부 HTTP 200, v2.5.0
Admin released fcde62ef artifact 원자 교체, HTTP·Arc 정렬 smoke, v2.5.0
Mobile NextPush released Store 2.4.2 (103) 대상 Android v28·iOS v25, bundle hash·mandatory 100%·history 검증
docs released 최종 기록 확정, 병합 뒤 v2.5.0·Release·Pages postcheck
  • 현재 결과: DB·API·Admin 운영 반영과 기능 smoke, Android/iOS NextPush 배포·history 검증이 정상 완료됐다.

메인 흐름

  1. 네 레포의 clean main, exact commit, contracts 0.1.32, 기존 운영 기준과 rollback 지점을 고정했다.
  2. migration source c0e70bbe를 운영계에 적용하고 ledger 88건·미적용 0건을 확인했다.
  3. API c0e70bbe, Admin fcde62ef를 운영계에 반영하고 HTTP·기능 smoke를 완료했다.
  4. Mobile 6050c86d를 Store 2.4.2 (103) 대상 Android v28·iOS v25 Production NextPush로 배포하고 label·bundle hash·history를 확인했다.
  5. API·Admin v2.5.0 annotated tag를 고정하고 최종 기록 병합 뒤 docs tag와 Release/Pages를 확인한다.

검증 근거

  • 원격 기준점: API c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3, Admin fcde62ef660e9e06c8721898d38e81bda4af6ecf, Mobile 6050c86d01e61d45d866c00ef332eda040909909
  • contracts: @coupler-developer/coupler-api-contracts@0.1.32, stable workflow run 31771588474, packages/contracts tree e76c3329a2f39087d09f587e6379ef32c2ed885f, Admin·Mobile manifest/lock exact pin
  • DB migration source: 개발계 apply dev·최종 status dev에서 미적용 0건을 확인한 c0e70bbe3b8767e3cebdc82072a389ce8b4cf2c3 exact checkout을 운영계에도 그대로 사용했다. 운영계 status prod에서 대상 migration 한 건만 미적용임을 확인한 뒤 20260814025412451_add_group_meeting_chat_message_notification_setting.sql을 적용했고, 최종 ledger 88건·미적용 0건을 확인했다.
  • 운영 사전 상태: API e4e344f3287c3c81a260ed98d00d1e8ce5a69960, PM2 online | production, Admin live index SHA-256 acd7f9cfba099686aaf20d672811b9b16c50c3e325cd2010a36644ba40cf4c87
  • Admin live source: source map의 변경 파일 hash가 bf64bce4a22a62ed6e314c25bef623aa06caebf1과 일치하고 이번 그룹미팅 정렬 source는 포함하지 않음을 확인했다.
  • 운영 결과: API PM2 online | production과 내부·외부 HTTP 200, Admin 내부·외부 HTTP 200 및 Arc의 그룹미팅 일시 오름차순·내림차순 전환 정상, NextPush Android v28·iOS v25의 target·bundle hash· mandatory 100%·history 검증
  • API contract cutover: No - 새 room self field·자기 설정 command와 Admin sort query는 additive이며 기존 Store/NextPush가 사용하던 요청·응답·bootstrap/version 경로를 제거하거나 변경하지 않는다.
  • 운영 실행 전 공통 preflight와 각 레포 표준 품질 Gate를 완료했다.

롤백 기준

  • DB: default 1의 additive column은 내리지 않는다. 적용 실패 시 자동 재실행하지 않고 ledger·live schema를 확인하며, 적용 뒤 문제는 새 runtime forward fix로 복구한다.
  • API: 이전 source e4e344f3287c3c81a260ed98d00d1e8ce5a69960은 저장된 방별 mute를 읽지 않아 type 82를 다시 발송할 수 있으므로 rollback을 승인하지 않는다. NextPush rollback 여부와 무관하게 API 장애는 c0e70bbe 기반 forward fix로 복구한다.
  • Admin: live source bf64bce4a22a62ed6e314c25bef623aa06caebf1와 index SHA-256 acd7f9cfba099686aaf20d672811b9b16c50c3e325cd2010a36644ba40cf4c87을 배포 시 backup metadata로 봉인하고, 실패하면 그 exact backup의 asset·index를 복원한다.
  • Mobile NextPush: 문제 시 Android Production v27 package 99535d8182ad4c799255b0261c85f616df70892f8f1b2d40478e8394ac76fb66, iOS Production v24 package 10678b5de30746675aaccc4ecad3bbd0c00345666728ebd0a8f6abf9da1a4725로 rollback한 뒤 history와 기본 채팅 진입을 다시 확인한다.
  • docs: 최종 병합 전에는 같은 PR에서 기록을 보정한다. 병합·태그 뒤에는 기존 기록이나 tag를 이동하지 않는다.

후속 작업

  • Store 제출은 이번 범위가 아니다. NextPush 대상 Store binary 2.4.2 (103)을 유지한다.
  • 병합 뒤 docs v2.5.0 GitHub Release artifact와 Pages 상태를 postcheck한다.

관련 문서