MDN 근거 3건 수집 후 결정 7개를 근거 기반으로 확정하고 §구현 가이드 4개 sub-section 을 채웠다. 조사에서 기존 계약 2건의 사실 오류가 나왔다. - EVICTION_SCOPE_DRIFT: 브라우저 eviction 은 origin 전량 삭제이므로 FE-REG-STORAGE.evictionOrder 는 애플리케이션 주도 정리에만 유효 - CACHE_STORAGE_CONSTRAINT_DRIFT: Cache Storage 는 SW 전용이 아니다 (Window.caches 접근 가능). FE-D027 의 제한은 정책이지 플랫폼 제약이 아님 - NO_GROUND_TRUTH: ca-tmpl 은 backend 전용이라 이 branch 에 미적용 - CAPABILITY_NAME_COLLISION: ca-tmpl capabilities.yaml 과 다른 개념 신규 raw: mdn-storage-quotas-eviction-persistence, mdn-file-system-access-opfs, mdn-object-url-cache-storage 6개 신규 branch-note 전부에 governing_docs 추가.
14 KiB
title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, imports, delegates, accepts_delegations, contract_packet, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label
| title | source_type | status | id | kind | project | work_item | inherits | refines | overrides | depends_on | imports | delegates | accepts_delegations | contract_packet | branch | parent_branch | related_projects | governing_docs | tags | created | target_merge | status_label | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-frontend-large-object-transfer-contract | branch-note | raw | BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-030 | project-work-item | ca-skeleton-frontend-operational-contract | WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-030 |
|
|
|
|
1 | feature-frontend-large-object-transfer-contract |
|
|
|
2026-07-28 | in-progress |
branch: feature-frontend-large-object-transfer-contract
부모 (필수)
형제 branch (같은 부모, 이번 확장에서 함께 생성):
- raw/branch-notes/feature-frontend-binary-file-io-store-contract
- raw/branch-notes/feature-frontend-cache-tier-cross-tab-invalidation-contract
- raw/branch-notes/feature-frontend-multi-protocol-api-transport-contract
- raw/branch-notes/feature-frontend-realtime-subscription-lifecycle-contract
- raw/branch-notes/feature-frontend-background-execution-worker-contract
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
2 - 패킷 스키마:
contract_packet: 1 - 완료 조건: presign 만료·part 재시도·무결성·credential 경계 fixture가 통과한다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001@1 |
신규 runtime capability 6종은 FE-REG-CAPABILITY flag로 default OFF이며 활성화는 owner·gate·runbook을 동반한다 | CAP_FE_LARGE_TRANSFER 를 이 branch 가 소유하고 default OFF 로 유지한다 |
raw/project-notes/ca-skeleton-frontend-operational-contract |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TRANSFER-CREDENTIAL-001@1 |
presigned URL 획득은 shared client를 경유하고 실제 byte 전송은 session credential을 첨부하지 않는 transfer adapter가 수행한다 | UploadTransferPort adapter 가 credential-less transport 를 사용하도록 강제한다 |
raw/project-notes/ca-skeleton-frontend-operational-contract |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RESUMABLE-TRANSFER-001@1 |
재개 가능 전송은 part size·병렬도·part 재시도 상한을 registry로 고정하고 part 상태를 BlobStorePort에 보존한다 | TRANSFER_PART_SIZE_BYTES·TRANSFER_MAX_PARALLEL_PARTS 를 소비하고 UPLOAD_PART_STATE 에 상태를 쓴다 |
raw/project-notes/ca-skeleton-frontend-operational-contract |
브랜치 지역 결정
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|---|---|---|---|
| D1 | transfer adapter 는 shared client 의 auth interceptor 체인을 재사용하지 않고 별도 transport 를 갖는다 | refines DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TRANSFER-CREDENTIAL-001@1 |
근거 raw 미수집 (FE-Q-011) |
proposed |
| D2 | presigned URL 은 telemetry·로그·Referrer 어디에도 남기지 않는다 |
local |
근거 raw 미수집 (FE-Q-011) |
proposed |
| D3 | MediaUrlPolicy 는 port 가 아니라 application/policies/ 의 순수 함수다 |
local |
근거 raw 미수집 (FE-Q-011) |
proposed |
선언한 예외
해당 없음.
가져온 artifact 계약
| Artifact Ref | Owner | Producer | Schema Ref |
|---|
가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
FE-GATE-029@1 |
raw/project-notes/ca-skeleton-frontend-operational-contract | presign 만료·part 재시도·무결성·credential 경계 fixture 가 실패하면 merge·release 를 MUST 차단 | 이 branch 가 owner 로서 fixture 와 report 를 산출 |
FE-OC-006@1 |
raw/branch-notes/feature-api-client-response-envelope-contract | 모든 HTTP는 shared client를 MUST 통과하고 timeout·abort·response parsing을 page에서 구현하면 안 됨 | presign 획득은 shared client 경유, byte 전송은 예외로 선언 |
FE-OC-019@1 |
raw/branch-notes/feature-frontend-browser-security-boundary-contract | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | presigned URL 유출 금지 규칙의 상위 계약 |
FE-OC-027@1 |
raw/branch-notes/feature-frontend-binary-file-io-store-contract | 파일 선택·다운로드·로컬 바이너리 저장은 등록된 port를 MUST 경유하고, 원시 File/Blob handle과 object URL 수명은 adapter 경계를 MUST NOT 벗어남 |
DELEG-FE-008 로 handle 수명을 위임 |
수신한 위임
없음. 이 branch 는 DELEG-FE-008 의 delegator 다.
가져온 흐름 단계
| Stage Ref | Order | Owner | Input | Action | Output |
|---|
목표
UploadTransferPort 와 StreamingDownloadPort 를 정의하고, presigned URL 획득과 byte 전송 사이의 credential 경계를 고정한다. 이 계약이 없으면 presigned URL 로 나가는 요청에 session 헤더가 그대로 붙어 제3자 스토리지 도메인에 인증 정보가 전달된다. 재개 가능 전송의 part 상태 소유자도 함께 고정한다.
- 이슈:
- PR:
범위
포함 범위
UploadTransferPort— presign 결과 소비, part 분할·병렬·재시도, 진행 스트림, 취소StreamingDownloadPort—ReadableStream소비, range/resume, 진행 스트림- credential-less transfer transport 와 그 경계의 negative fixture
- 무결성 검증(체크섬·크기)과
TRANSFER_INTEGRITY_MISMATCH MediaUrlPolicy— CDN base·허용 transform 기반 URL 파생 (순수 함수)- §9.6 전송 진행 surface state
CAP_FE_LARGE_TRANSFERcapability 행 소유
제외 범위
- use case, domain model, business rule — port 와 adapter 계약까지만 정의한다
- backend 의 presign 발급 endpoint 설계와 서명 알고리즘
- object storage vendor 선택과 그 제약(part 최소 크기·만료) —
FE-Q-012 - Image CDN vendor 선택
File/Blobhandle 과 object URL 수명 —DELEG-FE-008로 raw/branch-notes/feature-frontend-binary-file-io-store-contract 에 위임- 업로드 대상의 도메인 검증 규칙
근거 (필수, 최소 1개+)
| Source | 정당화하는 결정 |
|---|---|
[[docs/superpowers/specs/2026-07-28-ca-skeleton-frontend-runtime-adapter-features-design]] §5.1·§5.2·§9.3 |
port 분해, MediaUrlPolicy 가 port 가 아닌 이유, 전송 surface state |
| raw/official-docs/owasp-content-security-policy-cheat-sheet | browser 경계에서 credential·URL 노출을 줄이는 상위 관점 |
| raw/project-notes/ca-skeleton-frontend-operational-contract §5.3·§7.8 | API operation registry 와 auth integration 경계 |
근거 등급 경계: FE-D029(credential 경계)의 rationale 은 credential 유출 방지 invariant, project decision 이고 FE-D030(part 정책)은 project-local default, 외부 source claim 아님 이다. presigned URL·multipart 의 vendor 별 제약을 다룬 raw 자료는 없으며 FE-Q-012 가 수집을 소유한다. part size 8 MiB·병렬도 3 은 측정값이 아니라 초기 default 다.
TODO
UploadTransferPort·StreamingDownloadPort인터페이스 확정 — 등급:planned- credential-less transport 분리와 negative fixture — 등급:
planned - presign 만료 감지와 재획득 1회 경로 — 등급:
planned - part 재시도 상한(≤2)과 상태 보존 — 등급:
planned - 무결성 검증과 불일치 시 재전송 1회 — 등급:
planned - range 기반 다운로드 재개 — 등급:
planned MediaUrlPolicy순수 함수와 허용 transform 강제 — 등급:plannedFE-GATE-029transfer report 산출 — 등급:planned
진행 중 메모
PRESIGN_SAMPLE_UPLOAD 는 FE-REG-API 에 등록되지만 실제 byte 전송 대상 URL 은 registry 에 등록하지 않는다. registry 는 우리 backend 의 operation 장부이고, presigned URL 은 제3자 도메인의 일회용 주소이기 때문이다. 이 비대칭이 FE-OC-006("모든 HTTP 는 shared client 경유")의 유일한 선언적 예외이며, 예외라는 사실 자체를 §범위에 남긴다.
결정 사항
- 2026-07-28: transfer adapter 가 shared client interceptor 를 재사용하지 않음 / 이유: interceptor 체인에 auth 첨부가 있으면 제3자 URL 로 새어나감 / 검토한 대안: interceptor 에 skip 플래그 추가 / 근거:
FE-D029 - 2026-07-28:
MediaUrlPolicy를 port 로 만들지 않음 / 이유: URL 파생에 I-O 가 없어 port 로 만들면 test double 만 늘어남 / 검토한 대안:MediaUrlPort/ 근거: 설계문서 §5.2
결정-근거 매핑
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | 별도 transport 로 credential 분리 | 항상. 스토리지가 same-origin proxy 만 제공하면 FE-D029 재검토 |
없음 — FE-Q-011, FE-Q-012 |
project decision |
두 transport 의 timeout·retry 정책이 갈라질 수 있음 |
| D2 | presigned URL 을 어디에도 남기지 않음 | 항상 | 없음 — FE-Q-011 |
project-local default |
디버깅이 어려워짐. 실패 시 operation ID 만으로 추적 가능해야 함 |
| D3 | MediaUrlPolicy 는 순수 함수 |
항상. CDN 이 서명된 URL 을 요구하면 port 로 승격 재검토 | 없음 — FE-Q-011 |
project-local default |
서명 필요 CDN 을 만나면 설계가 바뀜 |
구현 가이드
근거 raw 자료(
FE-Q-011,FE-Q-012) 수집 전까지 비워 둔다. 특히 part size·병렬도·만료 처리는 storage vendor 제약에 직접 의존하므로, vendor 확정 전에 쓰면 전부UNSUPPORTED_IMPL_DECISION이 된다.
엣지·실패·의존
- 실패·엣지 경로
- presigned URL 만료 →
PRESIGN_EXPIRED, 재획득 1회 후 같은 위치에서 재개. 재획득도 실패하면 사용자 주도 retry - part 재시도 상한 소진 →
UPLOAD_PART_FAILED, part 상태 보존 후transfer-paused - 체크섬/크기 불일치 →
TRANSFER_INTEGRITY_MISMATCH, 해당 part 폐기 후 재전송 1회, 재실패면 terminal - 다운로드 스트림 중단 →
STREAM_INTERRUPTED,resumeStrategy: range면 받은 범위부터 재개 - 사용자 취소 →
REQUEST_ABORTED재사용, part 상태 폐기 여부를 명시 UPLOAD_PART_STATE저장 실패 →BLOB_STORE_UNAVAILABLE. 이 행은 fallback 이 없으므로 전송을 재개 불가로 표시하고 조용히 memory 로 넘어가지 않음
- presigned URL 만료 →
- 다른 계약 의존
- raw/branch-notes/feature-frontend-binary-file-io-store-contract 의
BlobStorePort·handle 수명에 의존 (DELEG-FE-008) - raw/branch-notes/feature-api-client-response-envelope-contract 의 shared client 에 의존 — presign 획득 경로
- raw/branch-notes/feature-frontend-browser-security-boundary-contract 의 header·CSP 정책에 의존 —
Referrer-Policy로 URL 유출 차단
- raw/branch-notes/feature-frontend-binary-file-io-store-contract 의
검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| transfer 요청에 session credential 이 붙지 않는다 | interceptor 가 전역이면 조용히 새어나감 | negative fixture — 전송 요청을 가로채 Authorization·쿠키 헤더 부재 확인 |
planned |
| presigned URL 이 telemetry·로그에 남지 않는다 | 에러 객체에 URL 이 딸려오기 쉬움 | grep + fixture — 전송 실패 시 emit 된 event payload 에 URL 문자열 0건 | planned |
| part 재시도가 2회를 넘지 않는다 | 상위 재시도와 part 재시도가 곱해질 수 있음 | 결정론 fake clock test — 총 시도 횟수 카운트 | planned |
| 만료 후 재획득으로 같은 위치에서 재개된다 | 재개 위치 계산이 vendor 별로 다름 | integration test — 만료 강제 후 이어받기 지점 확인 | needs-confirmation |
| part size 8 MiB 가 실제 환경에서 합리적이다 | 측정 없이 정한 초기 default | 벤치마크 — 네트워크 프로파일별 처리량 비교, FE-D030 revisit trigger 에 연결 |
needs-confirmation |
UPLOAD_PART_STATE 가 quota 초과 시 memory 로 넘어가지 않는다 |
fallback 이 기본 동작으로 새기 쉬움 | negative fixture — quota 초과 강제 후 재개 불가로 표시되는지 | planned |
관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
미생성.
마주친 문제
없음.
묶음 (이 branch에서 파생된 자료)
Sub-branches (세부 작업)
아직 없음.
오류 기록 (이 branch 작업 중 발생)
아직 없음.
면접 준비 (이 작업에서 나올 수 있는 면접 질문)
아직 없음.
강의 (이 작업을 위해 학습한 강의)
아직 없음.
job-posting tie-ins (이 작업에서 파생된 글감)
아직 없음.
관련 일일 노트
- 아직 없음
완료 후 정리
- PR 링크:
- 리뷰 메모:
- 머지 결과 / 배포 환경:
- wiki 추출 대상 (verified만,
wiki/projects/로만 추출):actually-implemented항목: 없음locally-verified항목: 없음prod-verified항목: 없음
- 추출하지 않을 항목: 현재 전 항목
planned