/////

Export Artifact Generation Failure Modes: Deterministic Manifests, Content Hashes, Atomic Writes, Schema Versions, and Partial-Upload Recovery

Export artifact 생성은 “파일 하나를 만들어 다운로드하게 한다”보다 실패 모드가 많다. 재사용 가능한 안전한 설계는 결정적 manifest , 콘텐츠 해시 , 원자적 로컬 쓰기 , schema/version metadata , 업로드 무결성 검증 , 부분 업로드 복구/폐기 정책 을 하나의 계약으로 묶어야 한다. 핵심 불변식은 다음과 같다: 1. manifest가 export artifact의 단일 진실 공급원이어야 한다. 2. manifest와 pa

/////

Summary#

Export artifact 생성은 “파일 하나를 만들어 다운로드하게 한다”보다 실패 모드가 많다. 재사용 가능한 안전한 설계는 결정적 manifest, 콘텐츠 해시, 원자적 로컬 쓰기, schema/version metadata, 업로드 무결성 검증, 부분 업로드 복구/폐기 정책을 하나의 계약으로 묶어야 한다.

핵심 불변식은 다음과 같다:
1. manifest가 export artifact의 단일 진실 공급원이어야 한다.
2. manifest와 payload는 재생성 시 가능한 한 byte-for-byte 안정적이어야 한다.
3. artifact는 완성 전까지 최종 이름/최종 URL로 노출되지 않아야 한다.
4. 저장소나 object storage에 올라간 뒤에도 선언된 digest로 검증 가능해야 한다.
5. 중단된 생성·업로드는 “완성본”으로 오인되지 않도록 명시적으로 resume, abort, garbage-collect 되어야 한다.

Key Points#

  • Deterministic manifest
  • manifest에는 export 대상 파일 목록, 상대 경로, byte size, content digest, media type, 생성기 버전, schema version, export kind, created timestamp 정책, entity counts/check counts를 포함한다.
  • 파일 열거 순서는 filesystem 반환 순서에 의존하지 말고 정렬된 순서를 사용한다.
  • manifest JSON/CBOR 등은 canonical serialization을 사용한다. 예: key order, whitespace, number/string encoding, timestamp format을 고정한다.
  • archive 내부 경로는 OS별 path separator, locale collation, case sensitivity 차이에 흔들리지 않게 정규화한다.
  • manifest 자체도 digest 대상에 포함하되, self-digest가 필요한 경우 manifest.digest를 별도 envelope에 두거나 manifest-without-signature canonical form을 정의한다.

  • Content hashing

  • 각 payload entry는 최소한 {path, size, digest_algorithm, digest}를 가진다.
  • SHA-256 같은 cryptographic digest를 기본으로 두되, object storage의 native checksum과 다를 수 있음을 명확히 기록한다.
  • multipart upload의 ETag를 “전체 파일 MD5”로 가정하지 않는다. AWS S3 문서는 multipart object의 ETag가 전체 객체 MD5가 아니라고 설명한다.
  • object storage checksum은 upload-time 검증에는 유용하지만, restore/download 검증을 위해서는 export manifest의 content digest도 유지하는 편이 안전하다.
  • 압축 archive의 digest와 내부 파일 digest를 모두 기록하면 두 종류의 검증이 가능하다:

    • transport/storage integrity: archive blob digest
    • semantic restore integrity: 내부 파일별 digest와 manifest counts
  • Reproducible archive generation

  • archive 생성 시 nondeterminism 원인을 제거한다:
    • 파일 순서 고정
    • mtime/ctime/atime 정규화
    • owner/group/numeric id 고정
    • permission mode 고정
    • locale 고정
    • gzip 등 compressor metadata 제거
  • Reproducible Builds 문서는 archive가 directory entry를 filesystem 반환 순서대로 읽으면 실행마다 순서가 달라질 수 있다고 지적한다.
  • tar 계열은 --sort=name, 고정 mtime, owner=0, group=0, numeric owner, pax header 정리 같은 옵션이 필요할 수 있다.
  • zip 계열은 extra attributes와 timestamps가 재현성에 영향을 줄 수 있으므로 별도 정규화가 필요하다.

  • Atomic local writes

  • export 생성 중에는 최종 경로에 직접 쓰지 않는다.
  • 같은 filesystem/directory 안에 temporary file 또는 staging directory를 만들고, 모든 write/hash/verify가 끝난 뒤 rename 또는 move로 publish한다.
  • atomic write 구현에서는 temp file을 같은 directory에 두어 cross-filesystem rename 문제를 피한다.
  • POSIX 계열에서는 temp file fsync 후 rename, 이후 parent directory fsync가 durability 관점에서 중요하다.
  • 실패 시 policy:

    • temp artifact는 최종 artifact로 간주하지 않는다.
    • .partial, .tmp, staging directory는 재시도 시 검사 후 재사용 또는 폐기한다.
    • 동일 export id에 대해 중복 writer가 생기지 않도록 lock/idempotency key를 둔다.
  • Schema/version metadata

  • manifest에는 다음 필드를 권장한다:
    • schema_version
    • generator_name
    • generator_version
    • export_kind
    • created_at
    • source_snapshot_id 또는 export 대상 기준점
    • content_encoding / archive_format
    • digest_algorithm
    • entries[]
    • entity_counts
    • compatibility
    • features_required
  • restore reader는 모르는 major schema version을 추측해서 읽지 말고 fail closed 해야 한다.
  • minor/patch 호환성은 명시적으로 정의한다.
  • OCI image manifest 같은 공개 artifact 형식은 schemaVersion, mediaType, descriptor digest/size 같은 필드를 통해 versioned manifest와 content-addressed descriptor 패턴을 제공한다. export artifact도 이 패턴을 차용할 수 있다.

  • Partial-upload recovery

  • object storage 업로드는 다음 상태 machine으로 관리한다:
    • planned
    • building
    • built_local
    • uploading
    • uploaded_unverified
    • verified
    • published
    • failed
    • aborted
  • “uploaded”와 “published”를 분리한다. object가 저장소에 있어도 checksum 검증과 manifest commit 전에는 사용자에게 최종 URL을 주지 않는다.
  • multipart upload는 upload id, part number, part size, part checksum, completed parts를 별도 checkpoint에 기록한다.
  • 재시도 시:
    • 동일 source snapshot과 동일 manifest digest면 resume 가능하다.
    • manifest digest가 다르면 기존 partial upload를 abort하고 새 upload로 간주한다.
    • part size 정책이 바뀌면 composite checksum/part mapping이 달라질 수 있으므로 resume하지 않는다.
  • AWS S3 multipart checksum 사용 시 checksum algorithm 지정, part 번호 연속성, full-object checksum 가능 여부 등 provider별 제약을 반영해야 한다.
  • upload 완료 후에는 remote checksum metadata 또는 다운로드/HEAD 기반 checksum과 local manifest digest를 비교한다.
  • lifecycle rule 또는 cleanup worker로 오래된 multipart upload/staging object를 정리한다.

  • Recommended artifact contract

  • 예시 manifest shape:
{
  "schema_version": "1.0.0",
  "export_kind": "account_export",
  "generator": {
    "name": "example-exporter",
    "version": "2.3.4"
  },
  "created_at": "2026-09-18T00:00:00Z",
  "source_snapshot_id": "snapshot-...",
  "archive": {
    "format": "tar.zst",
    "canonicalization": {
      "path_order": "bytewise-lexicographic",
      "mtime": "SOURCE_DATE_EPOCH",
      "uid": 0,
      "gid": 0,
      "permissions": "normalized"
    }
  },
  "digest": {
    "algorithm": "sha256"
  },
  "entries": [
    {
      "path": "data/users.json",
      "media_type": "application/json",
      "bytes": 12345,
      "sha256": "..."
    }
  ],
  "entity_counts": {
    "users": 10,
    "projects": 25
  },
  "compatibility": {
    "min_reader_version": "1.0.0",
    "features_required": []
  }
}
  • Primary failure modes to test
  • Process crash while writing payload.
  • Process crash after payload write but before manifest write.
  • Process crash after manifest write but before archive digest calculation.
  • Process crash after local artifact complete but before upload starts.
  • Network failure during multipart upload.
  • Multipart upload completed but checksum mismatch.
  • Upload completed but publish DB transaction fails.
  • Publish succeeds but signed/download URL generation fails.
  • Concurrent export requests for same user/snapshot.
  • Restore attempts against unknown schema version.
  • Restore attempts with missing file, wrong size, or wrong digest.
  • Archive regenerated from same logical input but different byte output due to timestamps, file order, permissions, compression metadata, locale, or path normalization.

Cautions#

  • 이 초안은 export artifact 일반 설계 패턴을 정리한 것이며, 특정 제품의 법적·규제 준수 요건을 검증한 것은 아니다.
  • Object storage의 checksum semantics는 provider와 API 방식에 따라 다르다. S3 multipart upload의 checksum/ETag 동작을 다른 storage에 그대로 일반화하면 안 된다.
  • “atomic rename”은 같은 filesystem 안에서의 local filesystem publish에는 유용하지만, object storage에는 동일한 의미의 atomic rename이 없는 경우가 많다. object storage에서는 staging key, final key, manifest commit, conditional write, versioning 등을 별도로 설계해야 한다.
  • 생성 시각을 manifest에 넣으면 byte-for-byte reproducibility와 충돌할 수 있다. 재현성을 우선하면 timestamp를 source snapshot에서 파생하거나 별도 envelope metadata로 분리해야 한다.
  • 압축 알고리즘과 버전, compression level, dictionary, thread count도 artifact bytes를 바꿀 수 있다. 필요한 경우 compressor 설정까지 manifest나 build recipe에 고정해야 한다.
  • 공개 검색 결과 중 일부는 특정 프로젝트 문서나 예시성 문서였으므로, 이 초안은 주로 Reproducible Builds, AWS S3, atomicwrites, OCI spec 계열의 공개 문서를 근거로 작성했다.

Sources#

  • https://reproducible-builds.org/docs/archives/
  • https://python-atomicwrites.readthedocs.io/_/downloads/en/latest/pdf/
  • https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html
  • https://specs.opencontainers.org/image-spec/manifest/

Sagwan Revalidation 2026-09-18T19:03:29Z#

  • verdict: ok
  • note: 원자적 쓰기·해시·manifest·부분 업로드 권장안은 여전히 유효하다.

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1