Project 카탈로그 문서 조회 계약
product.project.resolve_document는 서버의 카탈로그 항목을 실제 저장된 Flow 또는 Report의 현재 리비전으로 조회하는 읽기 operation입니다. 카탈로그의 itemRef나 표시 이름에서 SDK key를 추측하지 않습니다. 이 계약은 서비스 통합용이며 새 Python Client 메서드를 추가하지 않습니다. 정식 서버 HTTP와 Home·Flow·Report 웹 호스트에 연결됐습니다. 명시적으로 연결된 PostgreSQL·SQLite Project에서는 저장 시 카탈로그 항목을 자동 등록합니다. 내부 호스트의 빈 Project 연결과 기존 문서 등록은 지원하며, 공개 Project 생성 API와 실제 사이트 배포는 아직 완료되지 않았습니다.
요청
기존 Runtime JSON envelope를 사용합니다. arguments는 아래 두 문자열만 허용하며 빈 문자열을 거절합니다. 참조는 불투명한 값으로 유지하고 Unicode 정규화나 경로 분해를 하지 않습니다. 기존 carrier의 요청 크기·깊이 제한이 적용됩니다.
{
"operation": "product.project.resolve_document",
"arguments": {
"workspaceRef": "workspace:engineering",
"itemRef": "report:review"
}
}서버 HTTP는 기존 POST / operation endpoint를 사용하고, 정식 BFF를 사용하는 웹 통합은 POST /v1/runtime으로 같은 요청을 전달합니다. 브라우저는 BFF 세션·CSRF를 사용하며 bearer credential은 BFF에서 서버로 전달합니다. Organization 선택은 기존 X-PX-Organization-Ref 헤더의 canonical base64url UTF-8 값입니다. 본문의 organizationRef·scope·target으로 Organization이나 문서 소속을 덮어쓸 수 없습니다. 선택을 생략하면 해당 Workspace의 현재 membership이 유일한 Organization으로 해석돼야 합니다.
응답
성공 envelope의 data는 document 하나를 갖습니다. 문서가 있으면 아래 여섯 필드가 반환됩니다.
| 필드 | 의미 |
|---|---|
organizationRef | 인증으로 선택한 Organization |
workspaceRef | 요청한 카탈로그 Workspace의 불투명한 참조 |
projectRef | 해당 카탈로그 Project의 불투명한 참조 |
itemRef | 조회한 카탈로그 항목 참조 |
kind | pxflow 또는 report |
target | 기존 Core FlowTarget 또는 ReportTarget |
target.scope는 kind: "project", workspaceKey, projectKey를 갖습니다. Flow에는 flowKey, Report에는 reportKey가 있고 둘 다 revisionRef를 갖습니다. 이 scope는 명시적 저장 관계에서 읽으며 카탈로그 Workspace·Project 참조와 같은 문자열일 필요가 없습니다. head가 가리키는 리비전의 실제 문서가 같은 scope에 저장되어 있어야 반환합니다. 응답 후 head가 바뀌어도 반환된 revisionRef를 새 head로 바꾸지 않습니다.
인증된 카탈로그 Workspace 안에서 연결되지 않은 항목, 없는 문서/head, 카탈로그 Project를 볼 수 없는 경우, 실제 SDK 문서의 membership·읽기 권한 또는 관련 operation scope가 부족한 경우는 모두 동일하게 data: { "document": null }을 반환합니다. 이 응답으로 부재와 권한 거절을 구분할 수 없습니다.
인가와 거절
credential은 이 operation과 project_search를 허용해야 합니다. Flow 조회는 product.flow.authoring.head와 pxflow_describe, Report 조회는 report_search와 product.report.read_revision도 필요합니다. 등록 OIDC client와 발급 토큰의 허용 operation을 모두 충족해야 하며, 이 목록을 추가했다고 기존 credential이나 client에 권한을 자동 부여하지 않습니다.
카탈로그 Project visibility와 실제 SDK Workspace membership·Project ArtifactRead를 요청마다 다시 검사합니다. 반환 target은 이후 문서 읽기·편집·Run 실행·파일 조회의 인가를 대신하지 않습니다. 인증 실패·만료·요청 Workspace의 유효한 membership을 선택할 수 없는 경우는 기존 PX_PERMISSION_DENIED와 requiredPermission: "authenticatedPrincipal"을 반환합니다. 잘못된 인자 집합·타입·빈 참조는 인증된 요청에서 PX_REQUEST_SHAPE_INVALID로 거절합니다. Workspace 선택 자체가 불가능한 잘못된 인자는 인증 단계에서 먼저 거절될 수 있습니다. 저장소 장애는 서버 HTTP 503이며 문서 부재로 변환하지 않습니다.
카탈로그 resolver가 연결되지 않은 로컬 carrier는 인증된 유효 요청에 PX_CAPABILITY_DENIED, capability: "catalogDocumentResolution"을 반환합니다. 로컬 Client의 기존 scope·문서 key 기반 열기 경로는 이 operation에 의존하지 않습니다.
웹 문서 진입
서비스 Home의 행 열기와 제품 진입은 catalogWorkspace, catalogItem 주소 인자로 명시적 카탈로그 참조를 전달합니다. 예를 들어 Report 주소는 아래 형태입니다.
/px/document/report?catalogWorkspace=workspace%3Aengineering&catalogItem=report%3AreviewOrganization 선택이 있으면 기존 organization 인자도 유지합니다. 이 주소 인자들은 조회 대상을 선택할 뿐 권한을 부여하지 않습니다. 중복·누락·손상된 참조는 거절합니다.
Flow·Report 호스트는 이 참조가 있으면 배포 snapshot 대신 조회 API를 호출합니다. VITE_PX_CATALOG_ENDPOINT가 있으면 그 endpoint를 사용하고, 없으면 해당 제품의 문서 endpoint를 사용합니다. 반환된 Organization과 typed target을 후속 문서 읽기에 고정합니다. Report는 같은 열기 과정에서 head를 다시 조회해 반환된 리비전을 바꾸지 않습니다. 조회 거절·장애·부재 시 기존 문서 열기 실패 상태를 표시하며 snapshot으로 우회하지 않습니다.
Home 목록의 project_search는 요청 workspaceKey로 Workspace membership을 선택하고, 서버의 중앙 Project grant로 표시 권한을 검사합니다. 문서 resolver와 같은 권한 저장소를 사용하므로 grant를 Organization별 문서 저장소에 별도로 복사할 필요가 없습니다. 카탈로그 표시 권한이 있어도 연결된 SDK 문서의 별도 읽기 권한은 계속 필요합니다.
저장 후 목록 반영 범위
PostgreSQL·SQLite에서 SDK Project scope와 카탈로그 Project의 명시적 연결이 있으면, 기존 Flow·Report 저장과 Report 가져오기가 head·receipt를 확정할 때 새 항목도 함께 등록합니다. 같은 문서를 다시 저장하거나 receipt를 재시도해도 itemRef가 중복되지 않습니다. 이후 저장은 카탈로그의 이름과 폴더 위치를 유지합니다. 카탈로그 반영이 실패하면 해당 head· receipt와 새 항목은 함께 롤백됩니다.
내부 호스트의 StoreProjectCatalogProject는 Project root와 SDK scope 연결을 등록하고, 해당 scope의 현재 Flow·Report head를 같은 트랜잭션에서 목록에 반영합니다. 아직 head가 없는 임시 리비전은 등록하지 않습니다. 같은 등록 요청을 반복하면 항목 참조·이름·폴더·활동 시각을 유지하며, 기존 Project의 다른 scope 재연결은 거절합니다. 등록 실패 시 새 root·연결·항목은 함께 롤백하고 이미 저장된 문서는 유지합니다. PostgreSQL에서는 연결과 저장의 순서를 보장하되 서로 다른 문서 저장은 같은 Project라는 이유만으로 직렬 처리하지 않습니다.
이 내부 저장소 operation은 권한을 부여하지 않습니다. 호출 호스트가 카탈로그와 SDK scope 양쪽 소속을 인가해야 합니다. 공개 HTTP/Python Project 생성 진입점은 아직 연결하지 않았습니다. 연결되지 않은 scope를 이름이나 URL로 다른 Project에 자동 배정하지 않습니다. 최신 Python 설치 환경에서 공개 서버까지의 전체 여정도 아직 검증하지 않았습니다.
SDK Project의 catalog 위치 조회
product.project.resolve_project는 기존 SDK Project scope에 저장된 명시적 catalog 연결을 조회하는 호스트용 operation입니다. 문서가 없는 빈 Project도 반환할 수 있습니다.
{
"operation": "product.project.resolve_project",
"arguments": {
"scope": { "kind": "project", "workspaceKey": "engineering", "projectKey": "analysis" }
}
}scope는 기존 Core ProjectScope의 닫힌 형식입니다. Organization은 인증 carrier에서 선택하며 본문의 Organization·target·다른 Workspace 인자는 거절합니다. 인증할 Workspace는 이 scope의 workspaceKey에서 선택합니다. scope 자체가 잘못되면 인증 단계에서 먼저 거절될 수 있습니다.
성공 응답의 data.project는 다음 네 필드만 갖습니다. scope는 요청한 SDK scope이며 workspaceRef·projectRef는 저장소가 확인한 opaque catalog 참조입니다. 표시 이름이나 문서 리비전은 반환하지 않습니다.
{
"project": {
"organizationRef": "organization:example",
"workspaceRef": "catalog:engineering",
"projectRef": "project:analysis",
"scope": { "kind": "project", "workspaceKey": "engineering", "projectKey": "analysis" }
}
}credential은 product.project.resolve_project와 기존 project_search를 모두 허용해야 합니다. SDK Workspace·Project와 연결된 catalog Workspace·Project의 현재 membership·visibility를 각각 확인합니다. Project 이동은 Home과 같은 표시 권한을 적용하며 문서의 ArtifactRead를 추가 조건으로 요구하지 않습니다. 이후 문서 읽기·편집·실행 권한은 각 요청에서 별도로 검사합니다.
인증된 요청에서 연결 없음·Project 표시 권한 부족은 동일한 data: {"project": null}입니다. 인증 실패·operation scope 부족·SDK Workspace membership 선택 불가는 기존 PX_PERMISSION_DENIED, 인증 후 잘못된 인자 집합은 PX_REQUEST_SHAPE_INVALID, 저장소 장애는 HTTP 503입니다. 서버 resolver가 없는 로컬 carrier는 인증된 유효 요청에 PX_CAPABILITY_DENIED와 capability: "catalogProjectResolution"을 반환합니다. 기존 로컬 SDK 문서 열기는 영향을 받지 않습니다.
이 조회도 generated product descriptor와 SDK transport 허용 목록·digest에 등록합니다. 기존 credential·OIDC client에 새 operation 권한을 자동 부여하지 않습니다. 호환되는 Runtime과 SDK를 함께 사용해야 하며, 기존 문서 bytes·revision·SQL schema는 변경하지 않습니다. 로그인 callback은 새 credential로 이 operation을 읽고 검증된 SDK scope와 opaque 위치를 복귀 주소에 보존합니다. Flow·Report는 다음 로그인과 Home 이동에도 이 위치를 유지합니다. Home은 현재 catalog 권한으로 지정 Project를 다시 읽어 선택·펼치며, 부재·거절이면 다른 Project를 선택하지 않고 안내합니다. 원본 문서와 복귀 Project는 독립적입니다. URL 자체가 권한을 부여하지 않으며 이후 문서 읽기도 기존 서버 인가를 거칩니다. 실제 회원·issuer 공급과 정식 배포를 포함한 전체 여정의 운영 검증은 아직 남아 있습니다.
버전과 제공 범위
고정된 21개 Tool 목록은 유지하며 별도의 generated product descriptor에 이 operation을 등록합니다. SDK transport의 허용 목록과 productOperationSchemaDigest pin도 같은 변경에서 갱신합니다. 새 응답을 읽으려면 해당 descriptor와 호환되는 SDK·Runtime을 사용해야 합니다.
이 조회는 catalog 항목을 생성하거나 SDK save/import의 publication을 수행하지 않습니다. 등록된 카탈로그 항목의 Home→Flow·Report 진입과 연결된 PostgreSQL·SQLite Project의 저장 자동 등록은 연결됐습니다. Report→Flow 이동은 아래의 기존 typed target 읽기를 사용합니다. 실제 로그인· 공개 배포는 후속 연결입니다.
Report에서 정확한 Flow·Run 열기
저장된 Report connection은 이미 정확한 FlowTarget을 갖습니다. 서비스 호스트는 이 target을 flowWorkspace, flowProject, flowKey, flowRevision 주소 인자로 전달하고 기존 pxflow_describe로 해당 리비전을 읽습니다. 별도의 inverse catalog API나 배포 snapshot 조회로 Flow의 소속을 다시 결정하지 않습니다. 이 주소는 일시적인 탐색 상태이며 Report 저장 bytes나 SDK 문서 key·scope·revision 문법을 바꾸지 않습니다.
Run을 함께 열면 run, runWorkspace, runProject를 별도로 유지합니다. Report에서 시작한 Run의 scope를 원본 Flow scope로 대신 사용하지 않습니다. Organization 선택은 기존 주소 계약을 유지하고 Flow/Run 읽기의 권한은 각 기존 서버 operation에서 다시 검사합니다. 이 주소 자체는 membership, grant 또는 실행 권한을 부여하지 않습니다.
불완전·중복·잘못된 Flow/Run 참조는 문서를 읽기 전에 거절합니다. catalog 참조도 함께 있으면 인가된 catalog 조회 결과와 명시한 Flow의 scope·key가 일치해야 합니다. 일치해도 명시한 과거 revision을 catalog의 최신 head로 바꾸지 않습니다. Flow scope가 없는 이전 Run 주소는 기존 catalog/snapshot에서 원본 Flow identity를 찾는 경로로 읽으며 Run scope에서 추측하지 않습니다. 새 서비스 링크는 원본 scope를 포함하므로 snapshot이 필요하지 않습니다.
서비스가 없으면 명시한 Flow target을 snapshot 내용으로 대신 표시하지 않습니다. 문서 부재나 권한 거절은 기존 Flow 읽기 상태로 표시하며, Run을 선택하는 이동으로 새 계산을 제출하지 않습니다. Home에서 항목을 찾는 catalog visibility와, 이미 주어진 SDK target의 문서를 읽는 인가는 별도입니다. 이 이동은 catalog의 숨겨진 표시 이름·폴더·itemRef를 새로 조회하거나 공개하지 않습니다.