Document Management Service
호스트 애플리케이션이 제공하는 문서 정보 저장소와 문서 본문 저장소를 통해 문서 등록·조회·삭제·복구를 수행하는 Python SDK입니다.
dms는 독립 실행형 API 서버가 아니라 다른 프로젝트에서 import 해서 사용하는 라이브러리입니다.
Installation
uv add dms-core
Quick start
호스트 애플리케이션이 생성한 SQLAlchemy Engine과 MinIO client를 DocumentManagementSDKFactory에 전달하는 방식으로 조립합니다. SDK는 저장소 연결이나 인프라 client를 생성하지 않습니다.
SQL dialect에 맞는 adapter와 업로드 작업 저장소는 자동으로 조립됩니다.
from dms import DocumentManagementSDKFactory, DocumentPartition, UploadDocumentRequest
sdk = DocumentManagementSDKFactory(
engine=engine,
minio_client=minio_client,
bucket_name="documents",
).create()
partition = DocumentPartition.personal("user-123")
result = sdk.upload_document(
UploadDocumentRequest(
content=b"hello world",
filename="hello.txt",
content_type="text/plain",
),
partition=partition,
)
document_id를 생략하면 문서 정보 저장소의 데이터베이스 자동 증가 식별자가 등록 시 발급되어 결과에 반환됩니다. 호출자가 document_id를 지정한 경우에는 해당 식별자를 그대로 사용합니다.
업로드 요청의 metadata는 호출자가 문서와 함께 보존하는 애플리케이션 소유의 부가 정보입니다. DMS는 그 형식, 업무 스키마, 보안, 정규화 및 직렬화 규칙을 정의하거나 검증하지 않으며, 제공된 값을 문서 정보에 연결해 저장하고 반환합니다. 해당 값의 보안 및 외부 직렬화 가능성은 호출자가 책임집니다.
주입된 저장소와 연결의 생성·readiness 확인·종료는 호스트 애플리케이션 또는 별도 인프라 통합 계층이 담당합니다. SDK는 호출자가 제공한 저장소를 종료하지 않습니다.
비동기 호스트는 AsyncEngine과 minio의 동기 MinIO client를 전달해야 하며, blocking 호출은 event loop 밖의 thread에서 실행합니다.
from dms import (
AsyncDocumentManagementSDKFactory,
DocumentPartition,
UploadDocumentRequest,
)
sdk = AsyncDocumentManagementSDKFactory(
engine=async_engine,
minio_client=async_minio_client,
bucket_name="documents",
).create()
partition = DocumentPartition.group("group-456")
result = await sdk.upload_document(
UploadDocumentRequest(
content=b"hello world",
filename="hello.txt",
content_type="text/plain",
),
partition=partition,
)
metadata = await sdk.get_document_metadata(
result.document_id,
partition=partition,
)
비동기 SDK도 전역 client lifecycle을 소유하지 않습니다. get_document_content_async_stream(...)처럼 SDK가 직접 연 본문 스트림은 사용이 끝나면 aclose()로 정리해야 하며, 호출자가 제공한 입력 스트림은 SDK가 닫지 않습니다. 네이티브 비동기 처리는 AsyncDocumentManagementSDKFactory를 사용합니다.
문서 파티션과 접근 제어 책임
- 모든 문서는
personal또는group중 정확히 하나의 파티션에 속합니다. - 일반 문서 등록·조회·목록·본문·삭제·복구 작업에는
partition=을 필수로 전달합니다. 업로드 요청 안에 파티션을 중복해서 넣지 않습니다. - 개인 파티션에는 호스트의 사용자 식별값을, 그룹 파티션에는 호스트의 그룹 식별값을 사용합니다. 식별값은 비어 있지 않은 불투명 문자열입니다.
- DMS는 전달받은 파티션을 문서 정보, 본문 경로, 커서, 멱등성 작업, 삭제 및 복구의 관리 범위로 사용합니다. 같은 식별값이어도
personal과group은 서로 다른 파티션입니다. - 인증과 그룹 구성원 확인은 호스트 애플리케이션이 수행합니다. DMS는 사용자·그룹 디렉터리나 구성원 정보를 저장·관리하지 않습니다.
- 호스트는
DocumentAccessPolicy와 호출별AccessContext를 제공하여 문서 작업의 접근 제어를 DMS에 위임할 수 있습니다. 정책이 제공되면 DMS는 등록·조회·목록·본문·삭제·복구·초기화 작업 전에 정책을 실행합니다. AccessContext의 사용자·그룹·역할 값은 호스트가 인증하고 구성원 관계를 해석한 뒤 전달하는 불투명한 값입니다. DMS는 해당 값의 진위를 재검증하지 않습니다.access_policy가 없는 기존 조립은 현재와 같은 신뢰 파티션 동작을 유지합니다. 외부 요청자가 SDK를 직접 호출할 수 있는 경우에는 호스트가 정책을 반드시 주입해야 합니다.- 다른 파티션에만 존재하는 문서를 단건 조회·삭제하거나 문서 정보가 필요한 단건 복구를 실행하면
DocumentNotFoundError가 발생합니다. 접근 정책이 제공된 경우 정책의 거부 결과는AccessDeniedError로 구분됩니다. - 문서 목록과 복구 대상 목록은 다른 파티션의 항목을 페이지 제한 전에 제외합니다. 문서 점검은 실제 부재와 다른 파티션을 구분하지 않고 문서 정보 없음 결과를 반환하며, 다른 파티션에서 커서를 재사용하면
ValidationError가 발생합니다. - 이 변경은 이전 사용자 범위 스키마, 본문 경로, 커서 및 멱등성 기록과 호환되지 않습니다. 기존 데이터 이전은 제공하지 않으므로 새 빈 스키마와 저장 범위로 시작해야 합니다.
호스트 제공 접근 정책
DocumentAccessPolicy.allows(operation=..., context=..., metadata=...)는 호스트의 인증·구성원 확인 결과를 바탕으로 작업 허용 여부를 반환합니다.metadata는 항상 공개 문서 정보이며storage_key를 포함하지 않습니다. 업로드, 목록, 데이터 초기화처럼 특정 문서가 없는 작업에서는None입니다.- 정책이
False를 반환하거나 판정 중 오류가 발생하면AccessDeniedError가 발생합니다. 정책 오류의 상세 내용은 외부 오류 메시지에 노출되지 않습니다. - 논리 삭제와 완전 삭제는 각각
document.delete와document.hard_delete작업으로 정책에 전달되어 서로 다른 권한을 부여할 수 있습니다. - native async 조립에서는
AsyncDocumentAccessPolicy를 사용할 수 있으며, 동기 정책은 event loop 밖에서 실행됩니다. - 정책 규칙의 저장·변경, 사용자 인증, 그룹 구성원 추가·삭제는 호스트 애플리케이션의 책임입니다. DMS는 정책을 실행하고 결과를 문서 작업에 적용하는 역할만 담당합니다.
Public API overview
공개 API는 package root의 export와 공개 계약 테스트를 기준으로 관리합니다.
기본 import 경계는 from dms import ...이며, 내부 adapter와 저장소 구현은 공개 API로 간주하지 않습니다. API 문서 끝의 추적성 매트릭스는 각 공개 영역을 구현 파일, 검증 테스트, 실행 예제에 연결합니다.
Integration boundary
- 저장소 연결 생성, 환경변수 해석, database 준비, readiness 및 운영용 health endpoint는 호스트 애플리케이션 또는 별도 인프라 패키지가 담당합니다.
- SDK 공개 조립 API는
DocumentManagementSDKFactory.create()와AsyncDocumentManagementSDKFactory.create()입니다. - SDK 조립 시 지정한 MinIO bucket이 없으면 SDK가 생성하며, 생성한 bucket을 자동으로 삭제하지 않습니다.
- SDK는 주입된 저장소 연결의 lifecycle을 취득하지 않으며 전역
close()·aclose()를 제공하지 않습니다. - SDK가 문서 처리 중 직접 연 파일·본문 스트림은 SDK가 닫고, 호출자가 제공한 스트림과 출력 대상은 닫지 않습니다.
공개 문서 정보와 삭제 조회
- 업로드, 일반 문서 정보 조회, 목록 및 커서 페이지는 파티션 정보는 포함하고 내부 저장 위치는 제외한
PublicDocumentMetadata를 반환합니다. - 저장 위치가 필요한 복구·관리 작업만
get_internal_document_metadata()를 명시적으로 사용해야 합니다. - 일반 단건·목록·커서 조회는 논리 삭제 및 삭제 진행 상태의 문서를 숨깁니다. 삭제 상태 확인은
get_internal_document_metadata()와 복구 API처럼 명시적인 관리 경로를 사용해야 합니다. - 삭제된 문서의 본문 및 본문 스트림 조회는
DocumentDeletedError를 발생시킵니다. PublicDocumentMetadata.to_dict()는 v0.6 호환 필드명을 유지하고, 외부 응답용to_public_dict()는 부가 정보를metadata필드로 노출합니다. 부가 정보의 외부 직렬화 가능성은 호출자가 책임집니다.- 공개 결과 모델은
json_schema()와model_json_schema()를 제공하며 시스템 관리 필드의 구조를 설명합니다. 호출자 부가 정보의 내부 구조는 제한하지 않고, 공개 dump와 schema에는storage_key가 존재하지 않습니다. - 모든
DmsError하위 오류는 안정적인code, 상위category,retryable값을 제공합니다. 문서 관련 오류는 가능한 경우document_id도 제공합니다. DocumentContentStream은 컨텍스트 관리자로 사용할 수 있습니다. 호스트가 본문 반복자만 전달하는 경우에는iter_chunks_closing()또는aiter_chunks_closing()을 사용하면 정상 소진, 읽기 오류, 취소 및 반복자 명시 종료에서 SDK 소유 스트림을 정리합니다.
목록 페이지네이션
list_documents(partition=..., cursor=None, limit=100, status=None)는 기본 목록 API이며DocumentPage를 반환합니다.- 다음 페이지는 반환된
next_cursor를 같은 파티션, 상태 필터 및 페이지 크기로 전달하여 조회합니다. 마지막 페이지에서는next_cursor가None입니다. - 커서는 파티션 종류·식별값, 상태 필터 및 페이지 크기에 결합됩니다. 변조된 커서나 다른 조건에 재사용한 커서는
ValidationError로 거부됩니다. - 목록 조회는 커서 방식만 지원합니다. 기존 오프셋 기반 목록 API는 제거되었습니다.
전체 데이터 삭제와 신규 적재 초기화
clear_all_data()는 DMS가 관리하는 문서 본문(documents/prefix), 문서 정보 및 업로드 작업 기록을 완전 삭제하고DataResetResult로 저장소별 삭제 건수를 반환합니다. 문서 정보가 없는 orphan 본문도 함께 정리합니다.initialize_for_data_load()는 같은 범위를 비운 뒤 새 데이터 적재를 시작할 수 있는 빈 상태를 반환합니다. 이미 빈 상태에서 호출해도 성공하는 멱등 작업입니다.clear_partition_data(partition=...)와initialize_partition_for_data_load(partition=...)는 지정된 파티션의 문서 정보, 본문 및 업로드 작업 기록만 정리합니다.- 전체 범위와 파티션 범위는 별도 관리 작업입니다. 일반 문서 작업에서
partition=None을 전체 범위로 해석하지 않습니다. 접근 정책이 제공되면 해당 관리 작업에도 정책이 적용되며, 정책이 없으면 호출자가 실행 권한을 보장해야 합니다. - 문서 정보 저장소, 문서 본문 저장소 및 업로드 작업 저장소는 분산 트랜잭션으로 묶이지 않습니다. 한 저장소가 실패해도 나머지 저장소 정리를 시도하며, 전체 완료가 되지 않으면 부분 삭제 건수와
failed_stores를 가진DataResetError를 발생시킵니다. 이때error.result.ready_for_data_load는False입니다. AsyncDocumentManagementSDK에서도 전체 및 파티션별 작업을 awaitable 방식으로 제공합니다.
업로드와 비동기 본문 스트리밍
AsyncDocumentManagementSDK는 등록, 문서 정보 및 목록 조회, 본문 조회, 삭제, 복구 및 초기화를 awaitable 방식으로 제공합니다.AsyncDocumentManagementSDKFactory는 비동기 SQLAlchemy와 동기 MinIO client를 받으며, blocking MinIO 호출은 event loop 밖의 thread에서 실행합니다. 동기Engine호환 facade를 사용하는 경우에도 동기 저장소 작업은 event loop 밖에서 실행됩니다.- 업로드 입력은 메모리 바이트, 파일 경로, 정확한 크기가 선언된 동기 바이너리 스트림의 세 범주를 지원합니다. 파일 경로는 SDK가 열고 닫으며, 호출자가 제공한 스트림은 SDK가 닫지 않습니다.
- 스트림 등록은 정확한 양수 크기를 필수로 받고, 실제 읽은 크기가 선언값과 다르면 업로드 객체를 정리한 뒤 유효성 오류를 반환합니다. 최대 파일 크기는 조립 시 설정한 공통 정책으로 적용합니다.
- 크기를 알 수 없는 입력, 비동기 입력 스트림, 요청별 최대 크기, 업로드 chunk 조절 및 스트림 멱등성은 지원하지 않습니다. 네이티브 비동기 SDK의
upload_document_stream(...)도 입력 계약은 정확한 크기를 가진 동기 바이너리 스트림이며, MinIO 업로드와 메타데이터 처리는 비동기로 수행합니다. get_document_content_async_stream(...)은 전체 본문을 메모리에 적재하지 않는 비동기 반복 스트림을 반환합니다.- 다운로드 스트림은 성공, 실패, 취소 및 컨텍스트 종료 시 정리됩니다.
- 비동기 본문 스트림은
async with와 반복 호출에 안전한aclose()를 지원합니다. 비동기 SDK 자체는 전역 lifecycle을 관리하지 않습니다.
업로드 API 축소 이전 안내
- 크기를 알 수 없는 입력은 호출자가 임시 파일 등으로 먼저 크기를 확정한 뒤 파일 또는 동기 스트림 등록 경로를 사용해야 합니다.
- 제거된 bounded·unknown-size·비동기 입력 스트림 요청 타입과 메서드는
UploadDocumentStreamRequest및upload_document_stream(...)으로 자동 호환되지 않습니다. 호출자가 정확한size를 제공해야 합니다.
v0.4 공개 반환값 이전 안내
- 기존
result.storage_key사용 코드는 관리 작업에 한해sdk.get_internal_document_metadata(result.document_id, partition=partition).storage_key로 이전해야 합니다. - 기존 일반 조회와 목록에서
storage_key를 읽던 코드는 공개 반환값에서 해당 필드를 제거해야 합니다. - 내부 저장 위치를 외부 응답이나 업무 메타데이터로 전달하지 말고, 명시적 관리·복구 경로 안에서만 사용해야 합니다.
Document guide
- 제품 요구사항:
docs/prd.md - 소프트웨어 요구사항:
docs/srs.md
Integration tests
저장소 adapter와 실제 외부 서비스 readiness 검증은 호스트 애플리케이션 또는 별도 인프라 패키지의 책임입니다. 이 저장소의 핵심 테스트는 포트 구현 대역을 주입하여 문서 서비스 계약을 검증합니다. 테스트가 Docker Compose를 생성하거나 실행하지 않습니다.
Factory가 실제 PostgreSQL·MinIO client를 통해 문서를 등록하고 조회하는 통합 테스트를 제공합니다. MinIO bucket은 SDK 조립 과정에서 없으면 생성되며, 테스트는 전용 bucket과 고유 문서 ID를 사용하고 종료 시 생성한 자원을 정리합니다.
# 기본 테스트(통합 테스트 제외)
uv run pytest test_dms -m "not integration" -q
# 사전에 실행 중인 PostgreSQL·MinIO를 사용하는 Factory 통합 테스트
uv run pytest test_dms/test_sdk_factory_integration.py -m integration -v
# 전체 테스트
uv run pytest test_dms -q
Out of scope
현재 범위 밖 항목:
- 인증 helper
- presigned URL 발급
- 문서 검색/필터링
- 독립 실행형 비동기 작업 처리 서비스
- 메시지 브로커 연계 API
- 사용자 인증 및 인증 토큰 검증
- 사용자·그룹·구성원 정보와 접근 정책 규칙의 저장·관리
- PostgreSQL·SQLite·MinIO client 생성 및 client lifecycle 관리
- 인프라 readiness 또는 운영용 health endpoint
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dms_core-0.11.0.tar.gz.
File metadata
- Download URL: dms_core-0.11.0.tar.gz
- Upload date:
- Size: 54.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98c266203e45964a8224532f5b5d30490f1d78840c552a7e9ff14ab4d933f965
|
|
| MD5 |
caec312d0ed3e06779268036aa2d7273
|
|
| BLAKE2b-256 |
4c5787067f81b17edc1e925b52dd1e198bf6f846f6218288e87b7be53a23e463
|
Provenance
The following attestation bundles were made for dms_core-0.11.0.tar.gz:
Publisher:
python-publish.yml on kyundae-kim/dms-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dms_core-0.11.0.tar.gz -
Subject digest:
98c266203e45964a8224532f5b5d30490f1d78840c552a7e9ff14ab4d933f965 - Sigstore transparency entry: 2700376902
- Sigstore integration time:
-
Permalink:
kyundae-kim/dms-core@08eceec193e65956832ec10b827edd47c31b2310 -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/kyundae-kim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@08eceec193e65956832ec10b827edd47c31b2310 -
Trigger Event:
release
-
Statement type:
File details
Details for the file dms_core-0.11.0-py3-none-any.whl.
File metadata
- Download URL: dms_core-0.11.0-py3-none-any.whl
- Upload date:
- Size: 61.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7a6b4a4c6407be1750221ffe53aa8e38a0718ea8fe43a0c42dc9ed83a0f1d97
|
|
| MD5 |
84ba8147c73032acb24795d841d71939
|
|
| BLAKE2b-256 |
26d709592e8ebdbf7770714252b2cf2a08b13755f041cd69e94b02b5ea347fb5
|
Provenance
The following attestation bundles were made for dms_core-0.11.0-py3-none-any.whl:
Publisher:
python-publish.yml on kyundae-kim/dms-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dms_core-0.11.0-py3-none-any.whl -
Subject digest:
b7a6b4a4c6407be1750221ffe53aa8e38a0718ea8fe43a0c42dc9ed83a0f1d97 - Sigstore transparency entry: 2700376943
- Sigstore integration time:
-
Permalink:
kyundae-kim/dms-core@08eceec193e65956832ec10b827edd47c31b2310 -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/kyundae-kim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@08eceec193e65956832ec10b827edd47c31b2310 -
Trigger Event:
release
-
Statement type: