镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

[P1][A09] 검증된 staging 복원과 runtime·알림 세대 교체를 원자적 경계로 연결 #602

Open

Description

@jjoonleo

[P1][A09] 검증된 staging 복원과 runtime·알림 세대 교체를 원자적 경계로 연결

문제와 영향

현재 Backup Restore는 활성 DB의 durable rows를 transaction으로 교체하지만, SharedPreferences의 timed preparation·early start 상태, singleton의 시작 기록, timer·구독·준비 map, pending launch를 하나의 복원 수명으로 정리하지 않는다. 같은 일정 ID와 fingerprint를 가진 백업을 복원하면 백업에서 제외돼야 할 옛 Preparation Run이 다시 연결될 수 있다. 메모리 generation이 바뀌는 것만으로는 DB commit 직후 프로세스가 종료되는 상황이나 복원 후 도착한 옛 OS callback을 막을 수 없다.

추가로 ADR 0028은 실제 staging Local Data Store 검증 뒤 Restore Preview를 요구한다. 현재 preview는 decrypt/JSON parse/모델 검증 후 메모리 candidate를 반환하므로 이 요구를 충족한 증거가 아니다. A09는 정상적으로 열리는 DB에서 staging 검증, transaction 교체, crash 이후에도 유지되는 runtime 무효화, 현재 데이터로 안전한 재진입을 끝까지 연결한다. 손상 DB를 여는 복구 경로는 D02, 화면의 workflow·typed 결과는 C01의 계약을 사용한다.

우선순위 P1. 조사 기준 SHA는 **dac9c5a2d2097c22f8998743db86b99e28e23e8b**이다. 병행 중인 A14 구현 파일은 수정하지 않았다. 아래 내용은 조사와 합의된 계획이며 구현·테스트 통과 보고가 아니다.

코드와 문서 근거

근거 확인한 사실
BackupService:54–59, preview:126–172 candidate는 _BackupData와 preview만 보유한다. 실제 staging DB/확인 시점 generation/revision 증거가 없다.
BackupService:174–224 DB delete/insert는 transaction 안에 있다. runtime/OS 취소와 crash-safe cleanup 상태는 이 transaction에 포함되지 않는다.
MyDataScreen:159–169 UI가 applyRestore 다음 reconcile을 직접 호출한다. DB commit 뒤 reconcile 실패도 공통 오류로 전달된다.
Timed preparation source, Early start source 일정 ID별 prefs namespace를 사용하며 복원 세대를 구별하지 않는다. timed snapshot의 schema 2 최소 정보/개인정보 제한은 유지해야 한다. early marker의 쓰기/삭제 bool 확인도 복원 정리의 성공 증거로 검토해야 한다.
Session use case:66–88, 118–166 ID Set이 싱글턴에 남고, 유효 fingerprint snapshot은 startedAt/actionEvents/elapsed 복원에 쓰인다. 개별 ID clear만으로 모든 orphan runtime을 지우지 못한다. A07이 시작 멱등성/세대별 flight를 소유한다.
Preparation repository:129–136 BehaviorSubject map에 기존 항목을 펼쳐 추가한다. DB watch 재구독만으로 준비 map에 남은 이전 값을 제거했다고 볼 수 없다.
Operation gate:15–29 replacement 진입 시 action 전에 메모리 generation을 올린다. C01의 exclusive claim 이전/이후 세대를 구별해야 하며 crash 이후 영속 무효화 근거도 별도로 필요하다.
Minimal route payload, Tap router payload는 schedule ID 중심이고 A12는 수신 시 메모리 generation을 붙인다. 복원 뒤 늦게 들어온 옛 표시 알림을 새 데이터의 같은 ID와 구별할 영속 delivery identity가 없다.
Native DB open, Installation key store 정상 활성 DB는 설치 키를 사용한다. 정상 복원에 파일/설치 키 swap을 새로 도입할 필요가 없다. staging 임시 키가 설치 키를 덮어써서는 안 된다.
Database schema/transaction, Backup tests schema 2, format 2 반복 preparation/exclusions와 format 1 호환 테스트가 있다. 현재 테스트는 전체 runtime/OS/crash 수명을 증명하지 않는다.

기존 CONTEXT의 Backup Restore, Restore Preview, Durable OnTime Data, Reconstructible App State, Preparation Run, Installation Data Key를 그대로 따른다. restore/runtime epoch와 operation receipt는 구현 용어이며 새 제품 glossary를 만들지 않는다.

  • ADR 0013: 검증한 durable data 전체 교체, active session/early state/등록·권한 제외, 미래 일정 알림 재계산.
  • ADR 0022: 암호화 DB가 durable data의 유일한 권위다. prefs는 reconstructible state에 제한된다.
  • ADR 0023: 오류 때 DB/설치 키 보존, 제한된 복구 경로. 정상 복원 실패를 자동 초기화로 처리하지 않는다.
  • ADR 0028: 실제 staging 검증→preview→별도 최종 확인. 취소 때 활성 데이터 보존.
  • ADR 0029: run/action 의미를 보존한다. 복원하면서 임의의 시작·완료 action을 생성하지 않는다.

확정한 동작과 구현 경계

1. 실제 staging 검증과 후보 수명

  1. 기존 암호 suite로 전체 백업을 인증·복호화하고 지원 format을 현재 표현으로 해석한다. format 1/2와 반복 일정 호환을 보존한다.
  2. 별도 임시 키로 암호화한 실제 staging Local Data Store에 현재 schema로 적재한다. 필요한 forward migration, 제약/참조/준비 순서·소유 관계 검사와 read-back을 완료한 후에만 preview를 만든다. 메모리 parse나 mocked port 성공만으로 대체하지 않는다.
  3. staging은 앱 소유 보호된 임시 경로에 두고 Android/iOS OS 백업 및 외부 OnTime Backup에서 제외한다. sidecar/WAL/SHM까지 같은 보호·정리 대상으로 관리한다. 임시 키를 Installation Data Key 저장 위치에 넣거나 덮어쓰지 않는다. plaintext 임시 DB/원문 로그/암호 로그를 만들지 않는다.
  4. immutable 검증 candidate에 C01의 현재 generation+durable revision 확인 token을 연결한다. preview 이후 파일을 다시 읽어 다른 내용을 적용하지 않는다.
  5. 취소·검증 실패·stale preview·성공·후보 종료 때 staging/키/참조를 정리한다. 프로세스 종료로 남은 staging은 다음 startup에서 앱 소유 경로만 정리한다. 유효 후보가 현재 진행 중인 작업에 소유돼 있으면 UI dispose만으로 파일을 지워 실행 중 apply를 망가뜨리지 않는다.
  6. cleanup 실패는 C01 typed 결과/제한 상태로 전달한다. 정상 원본 DB를 삭제하거나 설치 키를 새로 발급하여 임시 파일 정리 오류를 숨기지 않는다. 메모리 참조 해제를 안전한 zeroization이나 저장장치 완전 소거라고 과장하지 않는다.

구체 staging factory/path/key scope는 선행 구현과 실제 플랫폼 보장을 보고 정한다. 구현 전 미정인 API 이름이나 fsync 내구성을 이미 확보한 것처럼 쓰지 않는다. D05의 전체 입력 상한·timezone/graph 검증은 공유 validator로 연결하되 A09에서 실제 staging 검증을 생략하는 핑계가 되지 않는다.

2. 최종 확인, quiesce, 활성 DB transaction

  • C01의 배타적 claim 안에서 preview generation/revision을 확인한다. 외부 check-then-act 또는 자신의 generation 증가 때문에 모든 후보가 stale이 되는 구현은 금지한다. stale이면 DB/키/runtime을 파괴하지 않고 재확인을 받는다.
  • A15 단일 writer와 기존 data gate를 재사용하여 기존 DB/runtime writer, timer, stream, 진행 중 OS side effect가 안전한 경계에 이르도록 한다. 별도 coordinator, 중첩 gate, Future 무시를 실제 취소로 취급하는 구현을 만들지 않는다.
  • 정상 활성 DB와 Installation Data Key는 유지한다. 검증된 staging 내용을 한 실제 DB transaction으로 전체 교체한다. DB 파일 rename/key swap은 D02 손상 DB 복원 범위다.
  • 교체 transaction에는 외부 백업에 포함되지 않는 설치 로컬 restore/runtime generation 또는 pending-cleanup 사실을 원자적으로 기록한다. commit 이후 prefs cleanup 전 종료돼도 새 DB와 옛 runtime을 구별할 수 있어야 한다. 필요한 내부 DB 메타데이터/schema migration은 가능하지만 portable Backup Format Version/암호 suite 변경을 뜻하지 않는다.
  • DB commit 전 기존 persisted runtime을 삭제하지 않는다. commit 전 실패/rollback이면 원본 durable rows와 설치 키를 보존하고 기존 run을 현재성 검사 후 재개할 수 있어야 한다. 안전을 위해 옛 OS 등록을 이미 취소했다면 원본 DB를 기준으로 같은 coordinator가 다시 조정하고, 미완료 delivery는 별도 사실로 표시한다.
  • OS call이 명시적 실패/unknown으로 반환한 상태와 아직 반환하지 않은 상태를 구별한다. 후자는 UI timeout만으로 quiesce를 통과하지 못한다. 늦은 반환의 ownership은 A15가 계속 소유한다.
  • commit 후에는 candidate 재사용과 DB 교체 반복을 막는다. runtime/delivery 실패는 데이터 rollback이 아니다. C01은 데이터 복원 완료 + 후속 정리 미완료를 표시하고 필요한 후속 단계만 retry한다.

3. 전 세대 runtime 제거와 새 상태 재진입

복원된 일정 목록에 있는 ID만 순회하지 않는다. 삭제된 일정의 orphan을 포함한 앱 소유 runtime namespace 전체를 세대별로 처리한다.

대상 필요한 경계
timed snapshot/action events/elapsed/early marker/옛 confirmation marker commit된 복원 세대와 불일치하면 같은 ID·같은 fingerprint여도 읽거나 재사용하지 않는다. bool false/IO 실패를 성공 삭제로 표시하지 않는다.
시작 flight/ID Set, active run, timer/tick, notified-step set A07/A12 owner/run/generation 경계로 멈추고 새 데이터에 영향 못 미치게 한다.
repository BehaviorSubject, preparation map, nearest schedule 구독 새 DB로 재생성 또는 명시적 clear/reload. old load의 늦은 완료가 새 map을 채우지 못한다.
prompt/view owner, deferred tap, native pending launch, cold getter A12 무효화와 다음 절의 영속 delivery identity를 함께 사용한다.
D03 journal, Installation Data Key, 새 generation의 유효 runtime 일반 prefs.clear로 지우지 않는다. old cleanup이 나중에 완료됐다는 이유로 새 run 상태를 제거하지 않는다.

DB commit 직후 프로세스를 재시작해도 startup은 정상 UI/timer/native 재진입 전에 설치 로컬 복원 세대/cleanup marker를 읽는다. 정리가 끝나지 않으면 옛 runtime을 차단하고 멱등적으로 필요한 정리만 재개한다. 실패하면 D01/C01의 제한된 복구 상태에서 현재 사실과 retry를 제공한다. pre-runApp throw만 추가하여 흰 화면에 남기는 것은 수용하지 않는다.

복원된 durable startedAt/preparationFrozen/outcome/점수는 그대로 보존한다. DB startedAt이나 과거 Preparation Start Moment만으로 active timer·elapsed·action event·완료 결과를 생성하지 않는다. 완료되지 않은 복원 일정의 재진입은 A07/A11 명시적 확인·새 run 경계를 지킨다. 최초 durable 시작 시각을 새 run 시각으로 덮어쓰거나 완료 기록을 재집계하지 않는다. 안정된 새 DB 화면으로 돌아오는 UI는 C01에서 연결한다.

4. 구세대 알림과 동일 ID 안전성

  • 복원은 기존 OnTime의 일정·준비 단계·표시 중 알림·native pending 등 옛 delivery를 정리한다. 다른 앱/OS 전역은 대상이 아니며 일반 일정 OFF의 범위와도 구별한다.
  • D03 최소 ownership journal과 취소 엔진을 재사용한다. journal은 새 DB 내용으로 교체하거나 prefs 정리로 잃지 않는다. provider별 성공/실패/unknown은 A14의 실제 관측 기준을 따른다.
  • 원문 없는 installation-local delivery generation 또는 검증 가능한 불투명 receipt identity를 예약→표시→tap 경계에 연결한다. 늦은 구세대 callback을 현재 수신 시각의 메모리 generation으로 다시 표시해서 새 DB 동일 scheduleId로 해석하지 않는다.
  • payload에는 제목/장소/준비명/시각/fingerprint/시작 명령을 추가하지 않는다. 최소 세대/불투명 ID는 라우팅 안전 metadata이며 외부 백업에 포함하지 않는다. 필요한 native/Dart allowlist 버전 변경은 A11의 개인정보 경계와 함께 검증한다.
  • generation 없는 legacy launch는 최초 복원 경계 전 호환을 유지할 수 있지만, 복원 경계 후에는 안전한 매핑 증거 없이 확인 화면도 열지 않는다. 악성/잘못된 ID 역시 DB 검증을 우회하지 못한다.
  • 취소가 명시적 실패/unknown으로 반환한 경우 journal을 보존하면서 DB commit은 허용할 수 있으나 후속 정리 미완료다. 동일 provider ID 새 등록은 옛 취소 확인 전 금지한다. 아직 반환하지 않은 OS Future는 quiesce 완료가 아니다.
  • 새 예약은 복원된 미래 일정, 현재 기기 권한/시간대, 기존 60개 용량과 A13 timing mode로 다시 계산한다. 백업 원본 기기의 registry/권한/설치 키를 가져오지 않는다. 안전한 runtime 재진입과 delivery 미확정에 대한 구체 제한 상태는 C01/D01에서 사실대로 표시하며 전체 완료를 거짓 보고하지 않는다.

의존성과 제외 범위

이슈 역할
A02/A03 실제 mobile export/import·파일 receipt를 유지한다. 이미 통과한 파일 저장 검사로 staging/runtime 해결을 주장하지 않는다.
A04/A08 profile 부분 수정·원자적 durable 저장/revision 경계를 보존한다. apply 중 old write가 새 DB를 변경하지 않는 통합 검증 필요.
A06/A07 action/start 멱등성·run identity·후속 부분 오류 계약을 사용한다. 복원으로 active run을 가져오지 않는다.
A11/A12 최소 payload/privacy, 확인 경계, prompt/view/route owner와 tap 무효화 유지. 영속 세대가 필요한 gap을 A09에서 끝낸다.
A13/A14/A15 현재 권한/timing mode, provider별 관측·미확정, 단일 OS writer/quiesce/late receipt 재사용.
D03 prefs/DB와 독립적인 ownership journal·공통 cleanup engine 제공. restore commit/rollback 책임은 A09다.
C01 #600 입력/preview/확인/token/typed 단계별 결과와 UI 연결. 실제 staging이 통합되기 전 C01도 완료 처리하지 않는다.
D01/D02 startup 제한 복구 및 손상 DB 복원. A09의 commit 뒤 cleanup 재개에 필요한 최소 startup 연결은 이 작업의 필수 통합이며 D01/D02 전체 완료 주장과 구별한다.
D05/D07 백업 검증 범위/한도와 template timestamp 보존 등 연관 회귀. staging의 실제 data round-trip 차이를 숨기지 않는다.

구현은 선행 A14/A15/D03/A07/C01/A08의 최신 계약을 재확인한 뒤 진행한다. 의존성을 이유로 동일 writer/journal/gate를 중복 작성하지 않는다. 제외: 서버·로그인·클라우드 동기화, 새 portable 백업 format/crypto suite, active run 백업, 설치 키 교체, 손상 DB 복원을 정상 DB 인스턴스로 가장하기, 전역 generic workflow/retry 프레임워크, timer 의미·점수 정책·반복 일정 재설계. 생성 Dart는 필요하면 로컬 재생성하되 커밋하지 않는다.

수용 기준과 검증 계획

아래는 아직 실행하지 않은 계획이다. 실제 durable 내용과 실행 수명 결과를 확인하며 spy 호출 순서만으로 통과 처리하지 않는다.

시나리오 필요한 결과/증거
유효 format 1/2 후보 실제 암호화 staging 생성·현재 schema 적재·관계 검증·read-back 후 preview. 단계별 count와 source/cutoff 일치.
잘못된 암호/손상/미지원/참조 오류/부분 write 실패 preview 또는 apply 파괴 작업 없음. 원본 DB/설치 키/runtime 보존. staging/키 정리 결과가 명시됨.
preview 취소/route exit/실행 중 route exit 미확정 후보 정리, 이미 진행 중 operation owner는 최종 receipt/정리까지 유지. dispose context 접근이나 stale navigation 없음.
preview 후 durable edit/reset/다른 restore exclusive currentness 재검사로 파괴 이전 중단. 같은 revision 숫자여도 다른 generation은 거절. 정상 candidate가 자기 generation 증가로 거절되지 않음.
중복 apply/export/reset/old writer 경쟁 단일 commit 또는 typed busy/동일 pending 결과. 중첩 gate 교착 없음, old DB write가 새 데이터를 바꾸지 않음.
transaction 중 각 insert/revision/marker failure 실제 Drift rollback으로 모든 원본 durable rows/설치 키 보존, 기존 run 재검증 후 재개. OS 후속 상태는 별도로 truthful 표시.
같은 ID+fingerprint 백업 복원 옛 elapsed/action/early/confirmation/flight/Set이 새 run으로 살아나지 않음.
삭제된 schedule의 orphan runtime prefs 새 DB 목록에 없는 키도 정리. journal/키/새 run의 유효 키는 유지.
DB commit 직후 prefs 삭제 전 프로세스 재구성 persisted 세대/cleanup marker가 정상 startup 이전 차단. old run 자동 부활 없이 남은 단계만 재개.
cleanup bool false/읽기 실패/부분 삭제/완료 marker write 실패 미완료 상태와 안전 retry, 성공 위조 없음. marker 제거 후 재시작해 이전 복원을 다시 commit하지 않음.
늦은 DB load/snapshot/tick/finish/시작 결과 새 generation cache/run/durable data/navigation을 변경하지 않음.
옛 표시 알림/late native callback/재시작 cold launch 새 DB 동일 scheduleId를 열거나 시작하지 않음. opaque identity 검증, legacy 경계, A12 last-valid/dedupe 유지.
취소 failure/unknown과 영구 pending Future 앞의 두 결과는 ownership 유지·부분 성공, 뒤는 quiesce 이전 commit 금지. timeout을 native 취소 완료로 보지 않음.
새 DB 같은 provider ID 재등록 옛 취소 확인 전 덮기 없음. 뒤늦은 구세대 취소가 새 등록을 삭제하지 않음.
복원 후 future scheduling 현재 권한/timing/시간대/60-cap/반복 exclusions 반영. 과거 완료 일정 재알림이나 registry import 없음.
durable startedAt/frozen/outcome/score 보존되고 timer 자동 생성·중복 score 없음. 명시적 새 run과 최초 durable 시작 시각 구별.
반복 일정 round-trip series/occurrence/owned preparation/exclusions/frozen 회차, v1/v2 호환 보존. template createdAt/updatedAt 차이는 D07과 추적하고 숨기지 않음.
staging 파일/sidecar/키 수명 임시 원문 없음, OS/외부 백업 제외, 취소/성공/시작 잔여물 정리, 원본 DB/키 불변.
한국어/영어 UI 및 logging commit 전 실패와 commit 후 미완료 구별, raw error/경로/암호/사용자 원문 없음, 실제 남은 단계만 retry.
  • 실제 Drift 및 workflow/Bloc/widget에서 위 장애·경쟁·재시작 시나리오를 재현하고 구현 SHA에 연결했다.
  • 기존 A02/A04/A07/A11/A12/A13 및 반복 일정 테스트, analyzer, 적절한 전체 테스트/CI가 통과했다.
  • Android→iOS, iOS→Android의 실제 저장 파일 선택·복원 내용 동등성과 runtime 제외를 기기/OS/artifact별로 확인했다.
  • 실제 앱 강제 종료와 provider pending/표시 알림/늦은 tap 관찰을 별도로 기록했다. 새 인스턴스 fault injection은 crash protocol 모델 검증이지 실기기 프로세스 종료 증거가 아니다.
  • 임시 암호화 DB 플랫폼 보호/backup 제외와 실제 cleanup 결과를 확인했다. unit test만으로 OS 저장장치 내구성 또는 OS 전달을 보장하지 않았다.
  • 미충족 D01/C01 통합·D05/D07 관련 data round-trip·실기기 조건은 해결하거나 의존 미완료로 남겼다. 구현/CI만으로 이슈를 닫지 않았다.

grill-with-docs 실제 전체 문답

전담 서브에이전트 /root/grill_a09가 /Users/ejunpark/.agents/skills/grill-with-docs/SKILL.md를 직접 읽고 적용했다. 코드로 확인 가능한 사실은 먼저 조사하고 root에게 한 번에 하나씩 질문한 뒤 답을 기다렸다. 사용자 지시에 따라 root가 대리 답했다. 아래 실제 문답 원문을 보존한다.

Q1 — 실제 staging과 정상 DB 교체 방식

전담 질문

A09 Q1 — 현재 preview는 메모리 parse만 하고 apply는 활성 DB 안에서 delete/insert transaction을 실행하며, runtime prefs/세션 정리는 없습니다. ADR 0028을 충족할 추천은 임시 암호화 staging Local Data Store에 현재 schema로 실제 적재·제약/관계 검증·read-back을 끝낸 뒤 preview를 만들고, 최종 확정 시 C01 token의 generation/revision을 exclusive 경계 안에서 재검사하는 것입니다. 정상 DB 복원은 기존 설치 키와 활성 DB를 유지한 채 검증된 staging 내용을 한 transaction으로 교체하는 방식을 우선하여 DB 파일/키 swap의 추가 crash 위험을 피하고, 손상 DB 파일 교체는 D02가 담당합니다. staging은 앱 소유 보호된 임시 경로·외부/OS 백업 제외, 별도 임시 키 수명, 취소/실패/성공 및 다음 startup 잔여물 정리까지 필요합니다. 이렇게 '실제 staging 검증 + 정상 활성 DB transaction 교체'로 확정할까요? 새 backup format/암호 suite나 active run 포함은 하지 않습니다.

Root 답변

A09 Q1 추천확정. 현재schema암호화staging실제적재/제약/관계검증/readback완료후preview, C01token generation/revisionexclusive재검사. 정상DB는설치키/활성DB유지+검증staging내용한transaction교체, filesystem/keyswap불필요. 손상DBreplacementD02소유. staging별도임시키/보호temp/OS·외부backup제외, 취소/실패/성공/startup찌꺼기cleanup범위포함. 키/원문로그금지, preview취소시liveDB/key/runtime무변경. tempcleanup실패가있다고정상DB원본삭제나새key발급으로해결금지, typed제한상태C01연결. format/crypto/activerunbackup변경없음.

Q2 — DB commit과 runtime 무효화의 crash 경계

전담 질문

A09 Q2 — 가장 중요한 crash 경계입니다. DB 교체 후 prefs를 지우기 전에 프로세스가 죽으면 동일 ID/fingerprint의 옛 runtime을 새 DB에 붙일 수 있어 메모리 generation만으로는 부족합니다. 추천: C01/A15 배타 경계에서 기존 writers·timer·stream을 quiesce하고, 설치 로컬의 restore/runtime 세대 또는 pending-cleanup 사실을 DB 교체 transaction과 원자적으로 묶어 영속화합니다(외부 백업 제외; 구체 DB 메타데이터 구조는 구현 시 최소로 결정). commit 전에는 기존 prefs/runtime을 파괴하지 않고 실패하면 원본 durable data·키 보존, 유효한 기존 run은 재검증해 재개합니다. commit 후에는 전 세대 timed snapshots/early markers/confirmation markers, 메모리 run·시작 flight/Set·timer·캐시·구독·pending launch를 새 DB에 절대 재사용하지 않습니다. prefs 삭제가 실패해도 committed 세대/cleanup marker가 재실행에서 먼저 판독되어 옛 상태를 차단하고 정리 재시도하며, 완전 정리 전 정상 타이머/알림 경로 재진입을 막습니다. DB commit 뒤 오류는 복원 실패/rollback이 아니라 '데이터 복원 완료, 후속 정리 미완료'로 표시하고 후속 단계만 retry합니다. 이 crash-safe runtime 무효화·commit 전 원본 보존·부분 성공 경계로 확정할까요?

Root 답변

Q2 확정. 메모리generation만아닌DB교체와원자적인installation-local restore/runtime generation또는cleanupmarker필수,외부backup제외. exclusiveclaim/quiesce후commit전기존runtime삭제금지, rollback시원본DB/key와유효run재검증복귀. commit후모든oldruntime/early/confirmation/flight/Set/cache/stream/launch재사용금지, 같은ID/fingerprint여도차단. startup은UI/timer/native재진입전에committedmarker확인/정리, 실패면typed복구상태(white screen금지 D01연결). committed데이터복원을실패롤백으로표시/재apply하지말고후속정리만retry. A11confirmation정책은새DB의정상진입에서유지하고새generation유효marker까지oldcleanup으로지우지않도록owner/generation분리. OS부작용은A15/D03미완료증거보존, 커밋전quiesce를Dartfutureignore로대체금지.

Q3 — 늦은 구세대 delivery와 같은 schedule ID

전담 질문

A09 Q3 — 현재 A11 최소 launch payload에는 scheduleId만 있어, 복원 뒤 같은 ID의 옛 표시 알림을 누르면 A12는 그때의 현재 메모리 generation으로 받아 새 일정 확인 화면을 열 수 있습니다. pending launch를 한 번 비우는 것만으로 이미 전달된 늦은 callback/재시작을 구별할 수 없습니다. 추천: 정상 복원도 전체 옛 OnTime delivery(일정·준비 단계·표시 중·native pending)를 D03 ownership 엔진으로 정리하고, 예약/탭에는 원문 없는 installation-local delivery generation 또는 registry에 검증 가능한 불투명 receipt identity를 연결해 구세대 탭을 새 DB 동일 ID로 해석하지 않게 합니다. 최소 payload 개인정보 제한은 유지하고 원문/지문/시작 명령은 추가하지 않습니다. legacy generation 없는 launch는 교체 전 기존 호환을 유지할 수 있으나 한 번 restore 경계를 지난 설치에서는 안전한 매핑 증거 없으면 거절합니다. OS 취소가 실패/unknown으로 반환하면 ownership을 남긴 채 검증된 DB commit은 허용하되 후속 정리 미완료로 보고, 동일 provider ID 재등록은 확인 전 금지합니다. 아직 반환 안 한 OS call은 A15 quiesce 전 commit하지 않습니다. 새 등록은 복원된 미래 일정/현재 기기 권한·시간대·60개 용량에서 재계산하며 옛 registry나 권한은 가져오지 않습니다. 이 stale delivery 판별과 부분 실패 정책으로 확정할까요?

전담 추가 조사

A09 추가 조사 근거: PreparationRepositoryImpl은 BehaviorSubject<Map<scheduleId, PreparationEntity>>에 기존 map을 spread하며 개별 load 결과를 계속 추가합니다. DB watch만 새로 열어도 옛 preparation map이 남을 수 있어 실제 repository cache 재생성/clear와 늦은 load generation 검사가 필요합니다. runtime cleanup은 복원된 schedule ID 목록만 순회하면 이미 삭제된 일정의 orphan prefs를 놓치므로 전체 앱 소유 runtime namespace를 처리하되 D03 ownership journal/설치키/새 generation 유효 상태는 건드리지 않는 AC로 넣겠습니다.

Root 답변

Q3 확정. restoreoldappdelivery전체정리+opaqueinstallation-localdeliverygeneration/receipt검증으로늦은구세대callback같은ID재매핑차단. payload원문/시간/지문/시작명령추가금지; generation/opaqueID는routing안전용최소metadata이며백업제외. legacy없음은restore경계전기존호환유지가능,경계후증거없으면확인화면도열지않음(새동일ID로묵시해석금지). 명시OS취소실패/unknown은소유권보존하면서DBcommit가능하나후속정리미완료와동일providerID등록block, 아직pendingOSFuture는실제quiesce전commit금지. 새예약복원DB현재권한/timezone/60cap재계산. 이미표시된다른목적OS알림정리도app소유만,일반OFF범위와구분. C01typedpartial/ D03engine/A15직렬화를재사용하고추가새coordinator금지.

Root 추가 조사 답변

추가근거/AC맞습니다. 실제repositorycache.clear/recreate+oldasyncloadgeneration검사 필요. 전체app-ownedruntime namespace inventory와prefix정확히식별하여orphan정리, 기존D03journal/설치키/새generation유효상태/무관prefs를blanketclear금지. startupcleanup/commit후재구독실제동작으로검증하고가짜map만clear하는테스트에그치지말것. 충분하면모든3문답+추가원문포함상세본문작성해주세요.

Q4 — durable 기록과 재진입·검증 범위

전담 질문

A09 Q4 — 복원된 일정의 durable startedAt/preparationFrozen/완료 outcome은 보존해야 하지만 active run은 백업 대상이 아닙니다. 추천: 복원 직후 진행하던 화면으로 자동 복귀하거나 DB startedAt/과거 준비 시작 시각만으로 timer·elapsed·action event·완료 결과를 만들어 내지 않습니다. 아직 완료되지 않은 복원 일정의 재진입은 A07/A11의 명시적 확인/새 run 경계를 거치며 최초 durable startedAt과 frozen preparation·기존 outcome/점수는 유지합니다. 복원은 orphan runtime 전체를 제거하고 새 repository/cache/구독이 현재 DB만 읽는 안정된 화면으로 돌아오며, 후속 정리 실패 시에는 D01/C01 제한 화면에서 사실·재시도만 표시합니다. 테스트는 동일 ID+동일 fingerprint+동일 revision 숫자, 삭제된 일정의 orphan prefs, 늦은 old DB load/snapshot/OS callback, commit 직전/직후 새 인스턴스 재시작, staging 취소·손상·쓰기 실패, format1/2·반복 exclusions/frozen/소유 preparation round-trip을 실제 Drift/Bloc 경로로 검증하고, Android↔iOS 파일 복원 및 실제 알림은 별도 기기 증거로 남깁니다. 이 재진입·durable 기록 보존 및 완료 검증 범위를 확정할까요?

Root 답변

Q4 확정. durable최초startedAt/frozen/outcome/score보존하되복원DB의과거시각만으로timer/run/actions/outcome합성/자동진입금지. 미완료일정재진입명시확인/A07새run경계, 안정화실패제한화면(D01/C01)과후속retry. 제시한동일ID/동일지문/동일revision+orphan+lateasync+commit경계재시작+실제stagingDrift+format1/2/recurringroundtrip모두AC, 실제Android↔iOS/provider파일/알림증거와simulation구분. 네문답+보충모두본문보존하여동결해주세요.

이번 작업의 실제 범위

읽기 조사, root와의 실제 4문답 및 추가 근거/답변, 이 이슈 본문 작성만 수행했다. 제품 소스·테스트·CONTEXT/ADR·공유 tracking·GitHub·commit은 변경하거나 실행하지 않았다. 새 제품 용어/ADR를 도입하지 않고 기존 문서의 staging/원자적 복원/active run 제외 약속을 구체화했다. 구현·검증 및 GitHub 생성/read-back은 후속 작업이다.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions