Files
tech-log-frontend/docs/architecture/browser-data-capability-completion-ledger.md
T

386 lines
27 KiB
Markdown

# Browser data capability completion ledger
## 1. 목적
이 문서는 다음 browser data capability의 **현재 구현 상태, 목표 상태, 남은
공통 구현, 제품 조합 책임, backend/provider 계약과 promotion 조건**을 한곳에서
관리하는 기준 문서다.
- File, Blob, 파일 선택기, preview와 다운로드
- Local/Session Storage, IndexedDB, OPFS와 Cache Storage
- TanStack Query memory cache와 탭 간 무효화
- Presigned URL, multipart/resumable upload와 streaming download
- Range resumable download와 background upload/download
- Image CDN descriptor, 검증, delivery와 presentation
각 상세 문서는 메커니즘과 불변조건을 설명한다. 이 ledger는 상세 문서를
대체하지 않으며, 서로 다른 문서의 "구현됨", "사용 가능", "설계됨" 표현이
production readiness로 잘못 합쳐지는 것을 막는 상태 단일 기준이다.
이 문서가 정한 상태만으로 실제 제품의 `PRODUCTION_READY`를 주장할 수 없다.
제품 owner, backend/provider conformance와 세 browser promotion evidence가 모두
별도 gate를 통과해야 한다.
## 2. 상태 체계
### 2.1 Primary current status
각 capability는 다음 다섯 상태 중 정확히 하나를 갖는다.
| 상태 | 의미 | 허용되는 주장 |
| --- | --- | --- |
| `COMPOSED` | production bootstrap 또는 설치된 feature 호출 경로에 concrete runtime이 연결돼 있다. | 저장소의 현재 제품 경로에서 실행된다. |
| `AVAILABLE_NOT_COMPOSED` | port, policy와 reference runtime이 있으나 기본 production graph에서는 제거돼 있다. | opt-in 조합 후보가 존재한다. |
| `DESIGNED_NOT_IMPLEMENTED` | 불변조건과 계약은 승인됐지만 해당 runtime 또는 필수 orchestration이 없다. | 설계/계약 backlog가 닫혔고 구현 backlog는 열려 있다. |
| `NOT_SELECTED` | 가치, 비용, 보안과 운영 owner가 승인되지 않아 의도적으로 선택하지 않았다. | 누락이 아니라 미선택이다. |
| `PLATFORM_LIMITED` | 브라우저 공통 보장이 불가능하거나 지원 범위가 제한된다. | capability probe와 fallback 안에서만 제공할 수 있다. |
`AVAILABLE_NOT_COMPOSED``COMPOSED`로 표시하거나,
`DESIGNED_NOT_IMPLEMENTED`를 테스트 fixture만으로 구현 완료 처리하지 않는다.
`NOT_SELECTED` capability를 인접 runtime의 "미완성"으로 계산하지 않는다.
### 2.2 독립적인 canonical readiness 축
Primary status와 다음 네 canonical 축을 섞지 않는다. VD-15와 이 ledger를
참조하는 운영 runbook도 축 이름과 literal을 정확히 이 표에 맞춘다.
| canonical 축 | 값 | 의미 |
| --- | --- | --- |
| `Selection` | `NOT_SELECTED`, `SELECTED`, `REMOVING` | 특정 제품이 capability를 채택했는지 여부 |
| `TrafficAdmission` | `DISABLED`, `SHADOW`, `CANARY`, `ENABLED` | 조합된 runtime의 신규 작업 admission |
| `RuntimeHealth` | `UNKNOWN`, `AVAILABLE`, `DEGRADED`, `UNAVAILABLE`, `INCOMPATIBLE` | 현재 runtime/provider 관측 상태 |
| `PromotionEvidence` | `MISSING`, `PARTIAL`, `COMPLETE`, `EXPIRED` | 필요한 contract/provider/browser/operations 증거의 합성 결과 |
`PromotionEvidence`의 입력은 다음 component gate다. 이 값들은 새로운 readiness
축이 아니라 합성 근거이며 evidence record와 함께 보존한다.
| component gate | 값 | 의미 |
| --- | --- | --- |
| contract | `MISSING`, `DRAFT`, `ACCEPTED` | frontend와 provider가 맞출 wire/behavior 계약 상태 |
| provider | `NOT_REQUIRED`, `PENDING`, `CONFORMANT` | 실제 BFF, object storage, CDN 또는 hosting 증거 |
| browser | `MISSING`, `PARTIAL`, `PROMOTABLE` | 승인 browser/device matrix의 native 증거 |
| operations | `MISSING`, `DOCUMENTED`, `DRILLED` | 관측, kill switch, recovery와 rollback 실행 증거 |
projection은 다음처럼 고정한다.
- 필수 component artifact가 없으면 `MISSING`이다.
- 유효한 일부 증거만 있거나 component가 terminal gate 전이면 `PARTIAL`이다.
- contract가 `ACCEPTED`, provider가 `NOT_REQUIRED` 또는 `CONFORMANT`, browser가
`PROMOTABLE`, operations가 `DRILLED`이고 모든 required artifact가 유효할 때만
`COMPLETE`다.
- 한 번 유효했던 required artifact가 정책의 freshness/expiry를 넘으면 다른
component 값과 무관하게 `EXPIRED`다.
예를 들어 Image CDN reference runtime은
`AVAILABLE_NOT_COMPOSED / Selection=NOT_SELECTED /
TrafficAdmission=DISABLED / RuntimeHealth=UNKNOWN /
PromotionEvidence=PARTIAL`이고 그 근거가
`contract=ACCEPTED / provider=PENDING / browser=PARTIAL /
operations=DOCUMENTED`일 수 있다. 이 행을 `COMPOSED`
`PRODUCTION_READY`로 줄여 쓰지 않는다.
### 2.3 가능한 구현 경로
다음은 제품이 아직 선택하지 않았고 reference source도 없는 capability가 거칠 수
있는 **일반적인 경로 예시**다. 다섯 primary status를 선형 maturity로 정의하지
않으며 모든 capability가 이 경로를 밟는 것도 아니다. 이미 reference runtime이
있는 capability는 `AVAILABLE_NOT_COMPOSED`에서 시작할 수 있고, cross-browser
의미가 불가능한 capability는 구현량과 무관하게 `PLATFORM_LIMITED`다.
```text
NOT_SELECTED
-> decision + owner + data classification
-> DESIGNED_NOT_IMPLEMENTED
-> implementation + deterministic evidence + removal evidence
-> AVAILABLE_NOT_COMPOSED
-> product policy + provider contract + bootstrap composition
-> COMPOSED
-> provider/browser/operations promotion gates
-> product-local production approval
```
`PLATFORM_LIMITED`는 위 흐름과 별도 제약이다. 지원 가능한 browser에서는
지원 browser용 runtime 행을 별도 상태로 기록할 수 있지만, cross-browser 보장
행의 primary status는 계속 `PLATFORM_LIMITED`다. 제품 계약은 지원 불가능한
browser의 fallback을 동시에 선언해야 한다.
rollback은 상태를 거꾸로 가장하지 않는다. 신규 진입을 kill switch로 닫고,
active operation을 drain 또는 abort하고, durable state를 정책대로 정리한 뒤
composition과 production module을 제거한다.
## 3. 구현 책임 분류
남은 항목은 다음 네 분류 중 하나 이상을 갖는다.
| 분류 | owner | 설명 |
| --- | --- | --- |
| `COMMON_REQUIRED` | frontend platform | 제품 API 주소 없이도 구현할 수 있고 선택 capability의 안전성에 필수인 port, state machine, policy와 lifecycle |
| `PRODUCT_COMPOSITION` | product/feature owner | dataset, account partition, UX, retention, quota priority, query/preset profile과 use-case facade |
| `PROVIDER_CONTRACT` | backend/storage/CDN/infra owner | authorization, signing, server ledger, storage constraint, CDN preset와 conformance |
| `OPTIONAL_CAPABILITY` | architecture + product approval | 필요성이 확인될 때 별도 threat model과 비용 승인을 거쳐 설치할 기능 |
`COMMON_REQUIRED`는 범용 mega-service를 뜻하지 않는다. 메커니즘은 공통이지만
정책 값은 immutable composition snapshot으로 주입한다.
## 4. 현재 capability snapshot
### 4.1 File, Blob, picker와 download
| capability | 현재 상태 | 현재 보장 | 목표 또는 잔여 | 남은 책임 |
| --- | --- | --- | --- | --- |
| File/Blob intake | `AVAILABLE_NOT_COMPOSED` | opaque file ref, transient vault, metadata normalization, byte/type/signature policy, bounded range read, closed-result stream | native chunk가 hard maximum을 넘지 않도록 재분할하는 ceiling과 제품 profile | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| native input picker | `AVAILABLE_NOT_COMPOSED` | keyboard/focus 가능한 input baseline, multiple, same-file reselection, dismissal outcome | 제품별 copy와 workflow | `PRODUCT_COMPOSITION` |
| enhanced open picker | `AVAILABLE_NOT_COMPOSED` | user activation과 conditional enhancement | browser matrix와 native input fallback 유지 | `PRODUCT_COMPOSITION` |
| directory selection | `NOT_SELECTED` | 없음 | bounded traversal, relative-path policy, symlink/entry ceiling | `OPTIONAL_CAPABILITY` |
| persistent file handle | `NOT_SELECTED` | native handle은 transient vault 밖으로 나가지 않음 | permission recovery, handle registry, retention/logout | `OPTIONAL_CAPABILITY` |
| drag/drop·paste·capture | `NOT_SELECTED` | 공통 file capture primitive 일부만 재사용 가능 | 별도 adapter와 접근 가능한 UX | `OPTIONAL_CAPABILITY` |
| object URL preview lease | `AVAILABLE_NOT_COMPOSED` | receipt binding, active-content denylist, byte cap, lease/revoke | 제품이 preview를 선택할 때 safety probe와 함께 조합 | `PRODUCT_COMPOSITION` |
| local preview decode-safety probe | `DESIGNED_NOT_IMPLEMENTED` | 현재 dimension/pixel/decoded-memory/animation preflight 없음 | object URL 발급 전 static header/decode budget 검증 | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| browser-managed download | `AVAILABLE_NOT_COMPOSED` | synchronous resolver/vault seam과 `BROWSER_HANDOFF` outcome을 saved와 구분 | concrete BFF issuer/strict response와 제품 open/share/save UX | `PRODUCT_COMPOSITION` + `PROVIDER_CONTRACT` |
| picker streaming save | `AVAILABLE_NOT_COMPOSED` | bounded stream, backpressure, integrity, close/abort truth | capability/size 기반 strategy selector | `COMMON_REQUIRED` |
| bounded Blob download | `AVAILABLE_NOT_COMPOSED` | small generated artifact hard cap | browser별 상한과 server-generation fallback | `PRODUCT_COMPOSITION` |
| Range resumable download | `DESIGNED_NOT_IMPLEMENTED` | 현재 one-shot download와 명시적으로 분리 | Range/If-Range/206, validator, checkpoint, seek/truncate, final integrity | `COMMON_REQUIRED` + `PROVIDER_CONTRACT` |
| app-managed background download | `NOT_SELECTED` | browser-managed handoff만 존재 | 지원 browser의 progressive enhancement로만 평가 | `OPTIONAL_CAPABILITY` |
| cross-browser app-managed background download guarantee | `PLATFORM_LIMITED` | 장시간 worker/picker/file permission 유지가 공통 보장되지 않음 | browser-managed handoff 또는 explicit unsupported fallback | 플랫폼 제약 |
### 4.2 Query, Web Storage와 cross-context
| capability | 현재 상태 | 현재 보장 | 목표 또는 잔여 | 남은 책임 |
| --- | --- | --- | --- | --- |
| TanStack Query memory cache | `COMPOSED` | concrete QueryClient, cancellation, stale UI, optimistic rollback, invalidate | session/account scope lifecycle, late-result fence, strict query policy/key codec | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| Local Storage registry | `COMPOSED` | 등록 key, closed codec/envelope, TTL, global hard cap, memory fallback | key별 cap, partition/logout, migration, explicit outcome, bounded sweep | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| Session Storage registry | `COMPOSED` | tab-scoped 등록 control record와 동일 codec | key별 cap과 explicit durability/outcome | `COMMON_REQUIRED` |
| cross-tab invalidation | `COMPOSED` | invalidate-only, versioned envelope, duplicate/stale/gap 처리, BroadcastChannel→localStorage→local-only | account epoch, exact storage source, production coordinator browser E2E | `COMMON_REQUIRED` |
| IndexedDB query persistence reference runtime | `DESIGNED_NOT_IMPLEMENTED` | persistence key는 disabled로 강제되고 persister source는 없음 | 승인 query만 dehydrate/hydrate하는 facade | 선택 시 `COMMON_REQUIRED` |
| product query persistence | `NOT_SELECTED` | persist 대상 query, owner와 retention 승인이 없음 | reference runtime 구현 뒤 별도 opt-in | `OPTIONAL_CAPABILITY` |
| durable cache namespace epoch | `DESIGNED_NOT_IMPLEMENTED` | release epoch만 존재 | persisted resurrection 방지 transaction ledger | persistence 선택 시 `COMMON_REQUIRED` |
| offline mutation command queue | `NOT_SELECTED` | foreground optimistic mutation만 존재 | idempotent durable command/sync protocol | `OPTIONAL_CAPABILITY` + `PROVIDER_CONTRACT` |
| SSR hydration | `NOT_SELECTED` | 현재 client SPA | request-scoped QueryClient와 precedence | SSR 선택 시 `PRODUCT_COMPOSITION` |
### 4.3 IndexedDB, OPFS와 Cache Storage
| capability | 현재 상태 | 현재 보장 | 목표 또는 잔여 | 남은 책임 |
| --- | --- | --- | --- | --- |
| generic IndexedDB runtime | `AVAILABLE_NOT_COMPOSED` | transaction-complete, CAS, idempotency, logical budget, TTL, lifecycle authority, additive DDL, resumable codec migration, blocked/versionchange | feature dataset repository/schema/codec/query와 production composition | `PRODUCT_COMPOSITION` |
| OPFS byte runtime | `AVAILABLE_NOT_COMPOSED` | DedicatedWorker SyncAccessHandle, async fallback, Web Locks, hash tree, IDB journal saga, budget/GC/reconcile | 제품 namespace/dataset policy와 production composition | `PRODUCT_COMPOSITION` |
| OPFS real readiness preflight | `DESIGNED_NOT_IMPLEMENTED` | 없음; API property probe와 별도 native conformance test만 존재 | worker/lock/journal/small write-read-delete-cleanup을 한 readiness operation으로 검증 | `COMMON_REQUIRED` |
| OPFS physical/journal forward migration | `DESIGNED_NOT_IMPLEMENTED` | 없음; 현재 v1 layout/journal과 reconciliation만 존재 | copy-on-write generation, checkpoint, publish authority와 N-1 rollback | `COMMON_REQUIRED` |
| public static Cache release runtime | `AVAILABLE_NOT_COMPOSED` | same-origin public GET, exact Vary/URL/type/size/digest, stage/activate/previous rollback | 제품 release/hosting policy와 production composition | `PRODUCT_COMPOSITION` |
| bounded Cache inspect/cleanup | `DESIGNED_NOT_IMPLEMENTED` | 없음; 현재 ownership 검사는 지키지만 cache-count scan은 unbounded | policy/epoch-bound cursor, count/deadline과 partial-success resume | `COMMON_REQUIRED` |
| Cache control/prefix forward migration | `DESIGNED_NOT_IMPLEMENTED` | 없음; 현재 v1 control/prefix parser와 release primitive만 존재 | 새 schema candidate, verify/activate, N-1 retain과 bounded cleanup | `COMMON_REQUIRED` |
| cross-store quota lifecycle | `DESIGNED_NOT_IMPLEMENTED` | store별 logical budget과 StorageManager signal은 존재 | write admission, pressure hysteresis, GC priority, one retry, scheduled maintenance | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| Service Worker offline fetch | `NOT_SELECTED` | Cache Storage runtime은 window에서도 독립 사용 가능 | registration, install/waiting/activation, client drain, navigation strategy | `OPTIONAL_CAPABILITY` |
| private response cache | `NOT_SELECTED` | 현재 public cache가 명시적으로 거절 | 별도 partition/encryption 오해 방지/retention threat model | `OPTIONAL_CAPABILITY` + `PROVIDER_CONTRACT` |
| sparse Range cache | `NOT_SELECTED` | `Range` request와 206 response를 거절 | validator-bound sparse segment merge | `OPTIONAL_CAPABILITY` + `PROVIDER_CONTRACT` |
### 4.4 Presigned transfer, upload와 Image CDN
| capability | 현재 상태 | 현재 보장 | 목표 또는 잔여 | 남은 책임 |
| --- | --- | --- | --- | --- |
| presigned capability | `AVAILABLE_NOT_COMPOSED` | fixed endpoint provider, strict binding, in-memory single-use vault, safe data-plane fetch | explicit download wire version, browser-handoff provider, actual signer conformance | `COMMON_REQUIRED` + `PROVIDER_CONTRACT` |
| multipart/resumable upload | `AVAILABLE_NOT_COMPOSED` | part hash/retry, IDB checkpoint, server reconcile, cross-tab cancel, complete/abort | pause, checkpoint inventory/retention sweep, unsupported lock decision와 실제 server/session provider | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` + `PROVIDER_CONTRACT` |
| one-shot streaming download | `AVAILABLE_NOT_COMPOSED` | bounded whole-object stream, length/media/integrity, picker/Blob/handoff delivery | strategy selector와 Range capability 분리 | `COMMON_REQUIRED` |
| top-level transfer composition | `DESIGNED_NOT_IMPLEMENTED` | 개별 factory와 dispose는 존재 | strict config, readiness, atomic account teardown, drain, kill switch | `COMMON_REQUIRED` |
| Image CDN verification engine | `AVAILABLE_NOT_COMPOSED` | opaque asset/preset, signed descriptor verification, responsive candidate, static metadata/decode budget | 제품 preset/presentation policy 조합과 실제 provider/private delivery E2E | `PRODUCT_COMPOSITION` + `PROVIDER_CONTRACT` |
| image descriptor HTTP provider | `DESIGNED_NOT_IMPLEMENTED` | caller가 decoded descriptor를 직접 제공 | fixed BFF endpoint, bounded schema, refresh single-flight, expiry/logout fence | `COMMON_REQUIRED` + `PROVIDER_CONTRACT` |
| safe image presentation primitive | `DESIGNED_NOT_IMPLEMENTED` | descriptor 결과만 제공 | URL 재조립 없는 picture/source/img projection | `COMMON_REQUIRED` + `PRODUCT_COMPOSITION` |
| app-managed background upload | `NOT_SELECTED` | checkpoint 기반 foreground resume만 존재 | worker lifetime/staging/permission 모델 별도 설계 | `OPTIONAL_CAPABILITY` |
| cross-browser app-managed background upload guarantee | `PLATFORM_LIMITED` | page/worker lifetime과 local source permission이 공통 보장되지 않음 | foreground resume 또는 explicit unsupported fallback | 플랫폼 제약 |
## 5. 중요한 경계
### 5.1 같은 이름처럼 보이지만 다른 capability
- streaming download는 메모리 상한을 지키며 **이번 응답을 끝까지** 저장한다.
Range resumable download는 새로운 요청에서 validator와 destination offset을
검증해 **이전 partial state를 이어 간다**.
- multipart resume는 upload session protocol이다. Background upload는 page
lifecycle이 끝난 뒤에도 실행 주체가 살아 있다는 별도 보장이다.
- Cache Storage release runtime은 public response를 검증·활성화한다. Service
Worker는 navigation/fetch interception과 controlled-client lifecycle을 소유한다.
- generic IndexedDB runtime은 query persistence가 아니다. Query persistence는
query classification, dehydration, scope epoch와 restore precedence를 추가로
요구한다.
- browser-managed handoff는 브라우저에 전달했다는 결과다. application이
저장 완료, 진행률 또는 background retry를 증명한 결과가 아니다.
- Image CDN engine은 descriptor를 검증한다. BFF descriptor 발급, 실제 CDN,
`<picture>` UX를 자동으로 제공하지 않는다.
### 5.2 정책과 도메인
byte ceiling, retry 상한, schema version, state transition과 fail-closed fallback은
공통 메커니즘이다. 다음 값은 도메인 코드가 아니라 **제품 composition policy**다.
- 어떤 file purpose와 MIME/signature profile을 허용하는가
- 어떤 query/dataset을 어느 account partition에 얼마나 오래 저장하는가
- quota pressure에서 무엇을 먼저 제거하는가
- 어떤 upload purpose와 CDN preset을 설치하는가
- save/open/share와 conflict/recovery UX를 어떻게 보여 주는가
업무 entity와 권한 결과는 backend/domain이 소유한다. frontend policy는 이를
추측하거나 대체하지 않는다.
## 6. External authority·backend·provider 계약
server/session/CDN 경계를 넘는 capability는 해당되는 external 계약 없이 실제
제품에 조합하지 않는다. local-only/reconstructable dataset에 backend를
일괄 요구하지 않는다.
| 경계 | 맞춰야 하는 owner/authority/provider 계약 |
| --- | --- |
| File upload | Web/BFF authorization, upload session API, file server 또는 object-storage data plane, quarantine/scanner/promotion |
| Presigned URL | BFF signer, cloud object storage, CORS/CSP, method/header/length/checksum/expiry 강제 |
| Multipart resume | server session ledger, idempotency, authoritative part status, completion receipt와 orphan janitor |
| Range download | immutable object generation 또는 strong validator, exact Range/If-Range semantics, full-object digest |
| account cache scope | frontend common runtime은 scope snapshot 검증, local generation/fence/teardown을 소유한다. product composition은 account/tenant 의미를 opaque partition policy에 mapping하고, auth/session owner는 sign-in/revoke/switch 사실을 제공한다. backend-issued epoch를 선택한 경우에만 그것이 wire 계약이다. |
| offline mutation | idempotency key, entity revision/ETag, cursor/delta, conflict/merge protocol |
| Image CDN | BFF descriptor endpoint, asset revision/preset registry, signing key rotation, CDN cache/CORS/CSP/no-store |
| eviction recovery | server-authoritative projection의 재구성 또는 all-marker-loss 구분이 필요한 제품에만 re-sync cursor/opaque installation epoch 계약 |
브라우저 native `File`, `FileSystemHandle`, IndexedDB physical store, OPFS path,
Cache name과 local checkpoint revision은 backend wire 계약이 아니다.
## 7. 설계 우선 work package
### WP-01. Scope-safe client cache
- session/account/release scope snapshot과 generation
- old QueryClient cancel, fence, clear, dispose와 remount
- late-result rejection
- strict query registry/key codec와 per-query ceiling
- Web Storage per-key policy, partition/logout/migration/outcome
- production coordinator까지 연결한 multi-page browser evidence
Exit: account A의 cache, storage event와 늦은 async result가 account B runtime에
관측되거나 기록될 수 없음을 deterministic fault와 native browser test로 증명한다.
### WP-02. Range resumable download
- 별도 `ResumableDownloadPort`
- validator-bound checkpoint와 non-authorizing persistence
- 200/206/412/416 state machine
- seek/truncate 또는 OPFS staging destination
- capability renewal와 final whole-object integrity
- browser strategy selector와 fail-closed fallback
Exit: crash, capability expiry, object replacement, malformed Content-Range,
destination mismatch와 integrity failure에서 corrupt saved outcome이 0건이다.
### WP-03. Origin storage lifecycle
- StorageManager signal + actual quota failure 기반 pressure controller
- policy-owned eviction priority와 hysteresis
- bounded maintenance cursor/deadline
- IDB/OPFS/Cache forward migration과 N-1 rollback
- OPFS native preflight와 clear/eviction recovery
- local preview bounded header parser/decode probe, pixel/decoded-byte/animation ceiling과
object URL 발급 전 fail-closed rejection
Exit: quota/migration/crash fault에서 unbounded scan, destructive auto-reset 또는
cross-scope read 없이 read-only/online-only/recovery outcome으로 닫힌다. hostile,
oversize 또는 animated preview fixture는 object URL 발급 전에 거절되고 decode
resource와 lease가 남지 않는다.
### WP-04. Transfer operational composition
- strict config schema와 protocol/version registry
- file/presigned/upload/download/image runtime atomic assembly
- readiness, kill switch, active-operation drain과 idempotent close
- logout/account switch fence
- checkpoint inventory/retention owner와 safe observations
- frontend provider contract harness
Exit: partially configured runtime이 시작되지 않고, teardown 뒤 capability나
late refresh가 새 scope에서 재사용되지 않는다.
### WP-05. Image descriptor delivery
- fixed BFF provider와 bounded closed decoder
- descriptor refresh single-flight와 expiry budget
- logout/account/runtime-generation fence
- static safe picture projection
- actual private/public CDN conformance and browser evidence
Exit: caller-provided URL/transform이 DOM에 도달하지 않고, 만료·회전·logout·decode
failure가 placeholder 또는 closed failure로 복구된다.
### WP-06. Optional capability decisions
directory/persistent handle, Query persistence, offline mutation, Service Worker,
private/range cache와 app-managed background upload/download는 각각 독립 ADR,
threat model, owner, budget과 removal plan을 승인한 뒤에만 시작한다.
## 8. 문서 우선 gate
runtime 구현을 시작하기 전에 해당 work package 문서에 다음이 모두 있어야 한다.
- current/target status와 out-of-scope
- application port와 adapter/provider owner
- immutable policy/config schema와 implementation ceiling
- state machine, concurrency와 cancellation owner
- durable record 분류, scope, TTL, purge와 migration
- backend/provider wire version과 compatibility
- browser capability matrix와 fallback
- observability allowlist와 금지 값
- rollout, kill switch, rollback과 removal
- deterministic, contract, native browser, fault와 operational drill
- 완료 조건과 promotion evidence 위치
문서가 없는 편의 API, fallback, persistence field 또는 retry owner를 구현 중에
추가하지 않는다. 새 요구는 ledger와 해당 ADR을 먼저 변경한다.
## 9. 구현 및 promotion 순서
```text
ledger/ADR accepted
-> port + closed policy/schema
-> deterministic fake/contract harness
-> reference runtime + negative boundary gate
-> fault/migration/removal evidence
-> AVAILABLE_NOT_COMPOSED
-> product owner + 필요한 external provider/config 선택
-> bootstrap composition behind kill switch
-> COMPOSED + TrafficAdmission=DISABLED
-> native Chromium/Firefox/WebKit + device drill
-> provider/browser/operations promotion gates
-> TrafficAdmission=CANARY/ENABLED
-> project-local production promotion
```
추천 구현 순서는 WP-01 → WP-02 → WP-03 → WP-04 → WP-05다. WP-02와 WP-03의
seekable/staging 정책, WP-04와 WP-05의 lifecycle/config 계약은 설계 단계에서
서로 검토하되 한 변경에서 모든 runtime을 동시에 조합하지 않는다.
## 10. 공통 완료 기준
- [ ] 모든 capability가 이 문서의 primary status 하나를 가진다.
- [ ] `AVAILABLE_NOT_COMPOSED` source가 기본 production module inventory에 없다.
- [ ] `COMPOSED` capability는 bootstrap부터 실제 consumer까지 호출 증거가 있다.
- [ ] account/session 전환이 broadcast delivery나 브라우저 종료에 의존하지 않는다.
- [ ] byte, record, queue, candidate, retry, deadline과 scan에 hard ceiling이 있다.
- [ ] durable state는 schema/codec/scope/epoch/retention/migration을 함께 선언한다.
- [ ] raw URL, query, signed header, file name/path, account ID, storage value,
digest/ETag/receipt가 diagnostics나 telemetry에 노출되지 않는다.
- [ ] backend/provider contract는 fake, emulator와 실제 provider에 재사용 가능한
conformance suite를 가진다.
- [ ] Chromium/Firefox/WebKit과 승인 device fallback 증거가 보존된다.
- [ ] kill switch, N-1 rollback, recovery와 optional runtime removal drill이
통과한다.
- [ ] 외부 증거가 없는 항목을 `PRODUCTION_READY`로 표시하지 않는다.
## 11. 상세 문서
- [Browser file and origin storage](./browser-file-and-origin-storage.md)
- [Client cache and storage](./client-cache-and-storage.md)
- [Presigned transfer and Image CDN](./presigned-transfer-and-image-cdn.md)
- [Server file capability infrastructure](./server-file-capability-infrastructure.md)
- [VD-11 Browser file and origin-storage](./decisions/VD-11-browser-file-and-origin-storage.md)
- [VD-12 Presigned transfer and Image CDN](./decisions/VD-12-presigned-transfer-and-image-cdn.md)
- [VD-13 Client cache scope and persistence](./decisions/VD-13-client-cache-scope-and-persistence.md)
- [VD-14 Resumable download and background download](./decisions/VD-14-resumable-download-and-background-transfer.md)
- [VD-15 Origin storage lifecycle and migration](./decisions/VD-15-origin-storage-lifecycle-and-migration.md)
- [VD-16 Browser transfer composition and image delivery](./decisions/VD-16-browser-transfer-composition-and-image-delivery.md)
- [Browser file/storage recovery](../operations/browser-file-storage-recovery.md)
- [Client cache/storage recovery](../operations/client-cache-and-storage-recovery.md)
- [Browser transfer recovery](../operations/browser-transfer-recovery.md)