본문으로 건너뛰기

문서 처리 결과의 원본과 보존 참조

현재 Core·로컬 Runtime·공개 SDK 내보내기·가져오기에 구현된 계약입니다. export_documents는 선택한 Report의 직접 첨부와 보존된 파생 결과의 전이 참조를 포함합니다. 보존 참조가 있는 묶음은 manifest V2, 없는 묶음은 V1입니다. 구버전 SDK의 V2 거절로 파생 참조의 조용한 누락을 방지합니다.

V1은 전체 객체의 정확한 바이트를 SHA-256으로 식별하고 관계형 참조로 읽기 가능 여부를 판정하며, 자동 GC를 제공하지 않습니다. Report에서 첨부 배치를 삭제하면 그 배치의 입력 등록도 제거하지만, 명시적으로 보존한 원본·파생 결과와 부모 관계는 삭제하지 않습니다. 원본 로컬 파일을 지우고 Runtime을 재시작해도 보존 객체는 기존 CAS에서 읽습니다. 향후 물리적 삭제를 도입할 때는 보존 객체의 전이 참조와 진행 중인 작업·반영·Plan의 참조를 삭제 판정에 포함해야 합니다. 현재 GC 기록 상태 전이만으로 이를 수행한다고 해석해서는 안 됩니다.

document-content-closure V1은 선택한 정확한 Report revision이 가리키는 보존 객체를 시작점으로 삼습니다. 분석은 원본 PDF를, 인용·번역은 정확한 분석과 그 원본 PDF를 참조합니다. 다른 객체를 추가로 포함하거나 부모를 생략할 수 없으며, 분석과 번역이 서로 다른 PDF를 가리키는 관계도 거절합니다. 일반 JSON 첨부파일의 문자열에서 참조를 추측하지 않습니다. 형식은 JSON Schema, 관계와 실제 콘텐츠의 검증은 Core가 소유합니다.

객체의 digest는 원본 바이트의 식별자입니다. 크기와 digest뿐 아니라 분석·인용·번역의 canonical bytes 및 원문 연결도 검증합니다. 하나의 분석을 사용하는 여러 결과는 그 분석을 한 번 읽어 순서대로 검증하므로 원문 전체를 결과마다 복제할 필요가 없습니다.

Runtime의 번역 접수는 원본 Report의 정확한 분석 첨부 또는 같은 Project에 명시적으로 보존된 분석을 입력으로 사용합니다. client.retain_document(analysis)로 보존한 분석을 Report 본문에 다시 첨부할 필요는 없습니다. 보존 경로도 분석 종류·크기·정확한 원본 PDF· 선택 페이지와 현재 권한을 확인합니다. 저장소에 바이트가 있거나 다른 Project에서 보존했다는 사실만으로 번역 입력을 읽을 수 없습니다. 공개 계산 접수 API의 제공 여부와는 별개입니다.

원본의 sourceReport는 출처 정보입니다. 다른 Project에서 해당 Report를 읽을 권한을 부여하지 않습니다. 가져오기에서는 호출자가 제공한 파일을 검증하고, 대상 Project의 현재 읽기·생성 권한을 확인합니다. 저장소에 이미 같은 digest가 있다는 사실만으로 파일 제공을 대신할 수 없습니다. 원본 출처는 보존하고 대상 Report와 import 명령의 영수증은 별도로 기록합니다. 가져온 Report에 원본 attachment를 임의로 추가하지 않습니다.

로컬 저장소는 Report·head·설정·객체 도달성·보존 참조·import 출처·명령 영수증을 같은 트랜잭션으로 저장합니다. 실패하면 권위 있는 참조를 남기지 않으며, 같은 명령과 같은 내용의 재시도는 기존 결과를 반환합니다. 같은 명령으로 다른 참조 집합을 보내면 충돌입니다. 트랜잭션 전 검증된 파일이 물리적 CAS에 남을 수 있지만, 이것이 읽기 권한이나 정상 저장을 의미하지는 않습니다.

저장된 출처 정보만으로 원본 Project의 진위나 분석 엔진의 실행을 인증하지 않습니다. 원본 바이트·연결 관계의 무결성, 현재 읽기 권한, 엔진 실행 증거는 구분합니다. 공개 전송 경로는 업로드 소유권을 확인한 파일 핸들을 이 저장 경계에 전달해야 합니다.

SDK 단독 실행의 로컬 저장소는 관리형 Project의 AccessGrant와 다른 권한 경로를 사용합니다. Host의 보호된 시작 채널이 단독 모드를 명시한 경우에만 저장소를 로컬 principal에 연결합니다. 이 연결은 원본·파생 문서의 로컬 보존 권한이며 Organization 가입이나 관리형 Project 권한을 만들지 않습니다. 다른 principal이나 다른 저장소의 증명은 거절하고, 관리형 catalog 또는 grant가 있는 저장소도 이 경로로 열 수 없습니다. 관리형 데이터가 나중에 추가되면 기존 로컬 증명으로 읽는 것도 거절합니다. 재시작은 같은 저장소 소유자를 확인한 뒤에 작업 복구를 시작합니다. principal 설정을 저장할 수 없어 임시 식별자로 실행하는 SDK는 기존 작성 기능을 계속 사용하지만, 영속 문서 소유권을 연결하지 않습니다. 이 경로에는 저장된 principal 또는 Host에 명시적으로 설정한 안정적인 principal이 필요합니다.

이 Host·저장소 기반은 단독 로컬 세션 계약에 정의돼 있습니다. 공개 SDK의 보존 호출은 단독 로컬 경로에서 사용할 수 있습니다. Report 내보내기와 V2 가져오기도 현재 이 권한 경로를 요구합니다. 관리형·임시 principal로 문서 권한을 해석할 수 없으면 내보내기를 거절합니다. V1 가져오기는 기존 경로를 유지합니다. 공개 전송 V1의 파일당 상한은 32MiB이며 파생 값은 16MiB입니다. 이 상한을 넘는 로컬 저장소 파일 처리 능력과 현재 공개 전송 프로필의 제공 범위는 구분합니다.

문서 처리 작업의 권한 기록

Runtime의 내부 문서 처리 작업은 관리형 Project와 단독 로컬 저장소의 출처를 구분합니다. 관리형 작업은 기존 V1 document-compute-binding의 principal·정확한 grant 참조와 바이트를 유지합니다. 단독 로컬 작업은 V2에 principal과 standaloneAuthorityRef를 기록합니다. 로컬 작업을 위해 가상의 조직 grant를 만들거나 권한 허용 결과를 작업에 저장하지 않습니다.

이 출처 기록은 권한이 아닙니다. 복구한 worker는 현재 Host가 해석한 증명의 종류·principal· grant 또는 저장소 ID를 비교하고 현재 저장소 권한을 다시 확인합니다. 단독 모드로 열지 않은 Host, 다른 principal·저장소, 비활성 세션 또는 관리형 데이터가 추가된 저장소의 로컬 증명은 거절합니다. 원본의 각 청크 읽기·실행 대기·결과 보존 전후에도 확인하며, 권한만 확인할 때는 문서 전체나 전이 참조 집합을 다시 읽지 않습니다.

계산 성공은 검토 대기 상태이며 Report를 자동으로 바꾸지 않습니다. 현재 이 경계는 내부 Runtime 실행 드라이버와 저장소에 연결돼 있습니다. 단독 로컬 세션에서는 공개 SDK로 작업 조회·취소·정확한 결과 검토를 요청할 수 있습니다. 검토한 결과 반영과 명령 ID로 반영 상태 조회·재개도 가능합니다. 공개 새 계산 접수는 client.submit_document_job(request, command_id=...)를 사용합니다. 자동 스케줄링은 아래 Host 활성화 경로를 따릅니다. 원본·파생 결과의 공개 보존 및 내보내기·가져오기 제공 범위와 구분합니다.

내부 Runtime의 복구 단계는 Project별로 최대 256개 작업을 조회하고 실행 가능한 작업을 한 번에 하나 처리합니다. 유효한 lease를 가진 작업을 건너뛰고 다음 조회 커서를 반환하므로 앞 페이지의 실행 중인 작업이나 개별 실패가 뒤 작업을 가리지 않습니다. 실제 claim은 기존 트랜잭션으로 다시 판정합니다. 만료된 취소 작업과 결과를 알 수 없는 외부 실행은 엔진을 재실행하지 않고 기존 상태 규칙으로 정리합니다. Host는 작업 간 대기·scope 선택·현재 권한 해석을 맡습니다. 이 단일 단계와 별도로, 현재 supervisor에는 Host가 명시적으로 활성화하는 자동 복구 루프가 연결돼 있습니다.

검토한 결과의 Report 반영 저장 경계

분석·번역 결과를 검토하는 것과 특정 Report 변경을 승인하는 것은 별도입니다. 같은 결과를 여러 Report에 반영할 수 있도록 내부 반영 요청은 workspace·Project·명령 ID로 식별합니다. 각 요청은 정확한 계산 작업·요청·결과 참조, 검토자 출처 기록과 기존 Report ApplyRequest를 묶습니다. 새로운 문서 편집 언어나 자동 원문 재작성 규칙을 만들지 않습니다.

로컬 저장소는 반영 요청의 pending·applied·refused 상태를 Report와 같은 권위 DB에 저장합니다. 반영 시점의 권한과 revision·generation을 확인한 뒤 Report head, 기존 명령 영수증, applied 결과를 한 트랜잭션으로 확정합니다. 실패하면 세 기록이 함께 롤백됩니다. 이미 거절된 요청은 늦게 도착해도 head를 바꿀 수 없으며, 해당 명령 ID를 일반 head 갱신으로 우회할 수도 없습니다. 거절 사유는 구조화된 diagnostic으로 남습니다.

완료된 요청의 내부 복구는 이후 Report가 바뀌어도 원래 영수증을 반환합니다. 이 조회는 완료 사실의 확인이며 새로운 변경 권한을 부여하지 않습니다. 공개 조회에는 별도의 현재 권한 검사가 필요합니다. 대기 요청 조회는 Project 범위와 배타적 명령 커서를 사용하고 페이지당 최대 256개를 반환합니다.

Runtime 내부 서비스는 현재 권한을 가진 human principal의 검토, 정확한 성공 결과, 승인된 Report Plan을 확인한 뒤 반영 요청을 저장합니다. 원본·엔진·언어·분석 참조 검증은 계산 worker와 같은 함수를 사용합니다. 결과 검토만으로는 반영 요청이나 Report 변경이 생기지 않으며, 특정 변경에 대한 승인이 별도로 필요합니다.

승인은 기존 Report Plan의 유효기간 안에 받아야 합니다. 승인 후 대기 중인 요청을 복구할 때는 저장된 승인 시각으로 그 Plan의 유효기간을 확인하고, 현재 권한과 Report head를 다시 확인합니다. Plan 만료 뒤에도 이미 승인된 정확한 요청의 복구는 가능하지만, 승인 전에 만료된 Plan이나 다른 Plan digest는 거절합니다. 향후 Plan 정리 작업은 대기 중인 반영 요청이 참조하는 Plan을 보존해야 합니다.

현재 Report와 충돌한 요청은 구조화된 진단과 함께 refused로 남습니다. 다른 principal의 요청은 기존 승인을 취소할 수 없습니다. 승인자의 현재 권한이 철회됐다면 대기 중인 반영을 거절합니다. 일시적인 저장소 오류와 내부 불일치는 pending을 유지해 복구나 운영자 점검이 가능하도록 합니다.

현재 연결 범위는 Runtime 검토·승인·단일 요청 복구 서비스, Desktop 저장소와 단독 로컬 SDK의 계산 접수·영수증 조회·작업 조회·취소·검토·Report 반영·재개입니다. 관리형 Host의 현재 grant 해석, 설치자가 승인한 모델의 배포는 아직 완료해야 합니다. 단독 로컬 supervisor의 자동 복구는 아래 Host 활성화 경로에 연결돼 있습니다. 저장소 포트를 직접 호출한 것만으로 사용자의 승인을 증명하지 않으며, Host가 현재 principal과 권한을 해석해야 합니다. 기존 Report revision과 내보내기 manifest 형식은 바뀌지 않습니다.

공개 반영 snapshot은 pending·applied·refused, 원래 Report target, 계산·결과 참조와 명령 ID를 반환합니다. applied에는 기존 Apply 영수증, refused에는 구조화된 진단이 있습니다. 조회 자체는 재개하지 않습니다. 반영 오류의 px.Error.command_id로 조회한 뒤 대기 요청을 재개할 수 있습니다. 승인 후 오류가 난 Report 핸들은 일반 save나 다른 명령으로 우회할 수 없습니다. 같은 요청으로 재시도하거나, 별도 재개 뒤 Report를 다시 엽니다. 거절된 초안은 Report를 다시 열어 새 명령 ID로 작성합니다.

Host가 활성화하는 문서 작업 복구

단독 로컬 Host는 보호된 lifecycle 시작 채널의 documentCompute 설정으로 실행을 활성화합니다. Runtime은 설정의 버전·허용 멤버와 정확한 엔진·파일 참조를 검사하고, ready 응답의 detail.documentCompute에 버전과 설정의 configurationRef를 돌려줍니다. Host는 자신이 보낸 설정의 canonical digest와 이 응답이 일치하는지 확인해야 합니다. 이 확인이 없으면 새 시작 멤버를 무시하는 구버전 Runtime을 실행 가능으로 판단할 수 없습니다. 공개 계산 요청으로 실행 파일·모델 경로나 권한을 전달하는 경로는 아닙니다.

Host의 설치 승인과 파일 무결성은 별개입니다. 설치자는 서명·라이선스·품질 검증을 마친 엔진만 승인해야 합니다. Runtime은 승인된 executable·asset의 정확한 파일 해시를 시작 시점과 엔진 선택 시점에 확인합니다. 요청의 모든 modelRefs도 검증한 asset 목록에 포함돼야 합니다. 일반 패키지 설치 기록이나 단순 해시 일치를 게시자 신뢰로 해석하지 않습니다. 파일은 canonical 절대 경로의 일반 파일이어야 합니다. 신뢰된 설치자는 승인된 설치 파일을 실행 중 교체하지 않아야 하며, Runtime의 해시 확인 자체가 원자적 파일 실행이나 설치 디렉터리의 불변성을 보장하는 것은 아닙니다. 실행에는 기존 sandbox와 비운 환경을 사용하고 외부 provider로 자동 우회하지 않습니다.

설정이 없으면 이 실행 루프는 활성화되지 않습니다. 명시적으로 활성화한 엔진 목록이 비어 있거나 작업의 엔진 파일이 없어졌다면 대기 작업은 구조화된 engineUnavailable 실패로 정리됩니다. 만료된 취소·외부 실행 불명 상태는 기존 lease·재실행 금지 규칙으로 정리하며, 이미 성공한 계산이나 Report는 다시 실행하거나 변경하지 않습니다.

루프는 Project가 포함된 작업 키의 배타적 커서로 최대 256개 행을 조회하고 한 번에 하나의 실행만 시작합니다. 활성 lease를 건너뛰며, 현재 단독 권한과 원본·결과 검증은 기존 worker가 수행합니다. 현재 구현은 키 순서 스캔이며 Project별 동일 처리량을 보장하는 우선순위 스케줄러는 아닙니다. 종료 요청은 새 claim을 막고 실행 중 프로세스를 정리합니다. 종료 때문에 계산 실패나 사용자 취소를 기록하지 않으며, 미완료 claim은 lease 만료 후 복구됩니다. 프로세스 전체의 종료를 확인하지 못하면 이 Host의 문서 실행 루프는 추가 작업을 시작하지 않고 공유 중단 신호를 접수 경로에도 전달합니다. 이 상태의 새 명령은 engineUnavailable로 거절하며 접수 영수증을 만들지 않습니다. 이미 접수된 명령의 조회·동일 요청 재전송은 계속 가능하고, 기존 작업을 취소나 실패로 바꾸지는 않습니다. 중단 신호 전에 검증을 시작한 접수는 완료될 수 있으며, 해당 작업은 기존 lease·재시작 복구 규칙을 따릅니다. 이 신호는 새 작업 접수를 막는 조치이며 미확인 프로세스의 종료를 증명하지는 않습니다.

현재 실제 supervisor 연결은 단독 로컬 Host 경로입니다. 관리형 Host의 현재 grant 해석, 설치자가 승인한 모델의 배포·품질 검증은 아직 별도로 완료해야 합니다. 통제된 테스트 엔진이나 설치 엔진이 없는 환경의 실패·복구 검증은 실제 OCR 모델의 실행 성공 증거가 아닙니다.

접수 응답 유실과 명령 ID

client.submit_document_job(request, command_id=...)는 기존 Core document-compute V1 요청을 접수합니다. source에는 정확한 Report target·PDF 참조·크기, processor에는 엔진· 모델·설정 참조, operation에는 페이지와 언어 선택을 담습니다. 실행 명령과 capability는 보호된 Host 설정이 소유하며 공개 요청에서 받지 않습니다. Host가 승인한 환경을 supervisor의 접수 경로와 복구 루프가 함께 사용합니다.

접수 결과는 {schemaVersion: 1, commandId, job}입니다. job은 기존 작업 snapshot이며, 접수 영수증 자체와 달리 상태가 변할 수 있습니다. 응답이 끊기면 보관한 ID로 client.document_submission(command_id)를 호출해 같은 Project의 작업을 찾습니다. SDK의 px.Error에도 command_id가 보존됩니다. 이 조회는 실행이나 재접수를 하지 않습니다.

같은 명령의 같은 정규화 요청은 현재 읽기 권한을 확인한 뒤 저장된 영수증을 먼저 반환합니다. 엔진·원본을 다시 검사하지 않으므로 엔진 비활성화나 원본 읽기 실패가 접수 응답 복구를 막지 않습니다. 같은 명령의 다른 요청·접수 출처는 충돌로 거절합니다. 다른 명령으로 같은 요청을 새로 접수하면 기존 계산에 연결되지만, 새 접수의 Host·원본 검증은 필요합니다. 새 명령 ID는 강제 재실행 옵션이 아닙니다.

명령 ID는 Project별 문서 계산 접수 안에서 해석합니다. SQL의 기존 복합 기본키와 request digest 유일성 제약을 그대로 사용하며 DB나 Report revision 형식은 바뀌지 않습니다. 파생 결과의 보존·검토·Report 반영 규칙도 유지됩니다. 형태 검증은 계산 요청 V1접수 snapshot V1, 언어 정규화·페이지 순서·권한·상태 의미는 Core/Runtime이 소유합니다.

성공한 분석·번역 값 읽기

client.document_job_result(job_ref)는 성공한 작업의 정확한 DocumentAnalysis 또는 DocumentTranslation을 반환합니다. SDK가 같은 Project의 작업 상태와 보존된 콘텐츠를 읽고, Runtime은 각 청크의 현재 읽기 권한을 확인합니다. 콘텐츠 참조·크기·오프셋·바이트 범위, 최대 16MiB, 전체 해시·정규화된 값의 식별자·원본 참조가 일치해야 값을 반환합니다. Core/native가 기존 분석·번역 형식과 언어·좌표 의미를 검증합니다.

성공 전에는 PX_RUN_STATE_CONFLICT로 거절하며 부분 결과를 반환하지 않습니다. 읽기 도중 권한이나 콘텐츠 확인이 실패해도 부분 값을 반환하지 않습니다. 결과 읽기는 검토 승인이나 Report 반영을 뜻하지 않으며, 거절된 검토 결과도 계산이 성공했고 현재 읽기 권한이 있으면 확인할 수 있습니다. 검토와 Report 적용에는 기존 명시적 API를 사용합니다. 원래 업로드한 로컬 PDF 경로는 결과 읽기에 필요하지 않습니다.

생성 PDF와 출처 기록

client.retain_translated_pdf(value, pdf=path)는 이미 보존된 원본·분석·번역을 부모로 삼아 출력 PDF와 별도의 DocumentTranslatedPdf 출처 기록을 보존합니다. 출처 기록을 Report에 attachment로 명시적으로 추가하면 기존 export_documents/import_documents가 선택된 기록과 그 전체 부모 관계를 함께 이동합니다. 보존 자체는 Report나 검토 상태를 변경하지 않습니다.

기존 보존 관계는 document closure V1을 유지합니다. 생성 PDF 또는 번역 PDF 출처가 포함된 관계는 closure V2를 사용합니다. V2는 translated-pdf 출처 kind와 Report 출처가 없는 생성 PDF를 추가합니다. 원본과 출력이 같은 바이트이면 같은 pdf 행을 사용하고, 출처 기록의 식별자는 별도로 유지합니다. Portable manifest V2와 내부 closure의 버전은 서로 다른 버전입니다. 새 reader는 closure V1/V2를 읽으며 지원하지 않는 버전은 거절합니다.

로컬 DB의 보존 kind 변경은 authority migration 20에서 기존 행·참조·import 출처를 유지하며 한 migration transaction으로 적용합니다. 손상된 참조 때문에 마이그레이션이 실패하면 이전 버전과 보존 테이블을 유지합니다. 새 DB 버전을 지원하지 않는 이전 Runtime은 열기를 거절합니다. 원본 출처·레이아웃·렌더·엔진 digest를 아는 것만으로 다른 Project의 파일을 읽을 수는 없습니다.