본문으로 건너뛰기

Component 작성과 container 계약

`@px.component`는 닫힌 primary task category와 Python type annotation으로 만든 typed port companion metadata를 등록합니다. placement 값은 `.pxflow` `componentNode.settings`가 소유합니다. 하나의 Python Component package/distribution은 하나 이상의 Component symbol을 export할 수 있습니다. 저장소에는 generation-2 container의 install·catalog·presentation read lane이 구현돼 있고, 공개 third-party publisher의 admission workflow는 아직 열려 있지 않습니다.

두 가지 상태를 구분하세요

  • 구현된 lane: generation-2 multi-declaration container의 deterministic packing, drop-folder install, container reader·installer·publisher/packageKey로 한정한 multi-Component resolver, exact ProjectScope { kind: "project", workspaceKey, projectKey }로 격리된 contribution 저장·catalog·detail read, presentation resolution port와 Python worker execution이 저장소에 구현돼 있고 in-repo conformance test가 덮습니다. admitted generation-2 Component는 host-owned component.declarative@2 body로 투영됩니다.
  • 공개 third-party admission — contract_only이고 fail closed: RFC-014 record는 lifecycle: accepted, implementationState: partial-foundation, 비어 있지 않은 implementationEvidencePaths, productAvailability: contract_only를 유지합니다. installer는 executor bytes를 즉시 reachable하게 만들고 안전한 inactive quarantine을 제공하지 않으며, 요청 scope를 authenticated principal의 권한에 결속하지도 않고, publisher trust store와 signed revocation을 소비하는 execution-trust closure도 아직 없습니다. 그래서 공개 marketplace의 외부 publisher install admission과 package executable UI는 계속 막혀 있고, 아래 command와 UI를 사용자에게 제공되는 설치·실행 경로로 해석하지 않습니다. 정리하면 production third-party Component install admission과 activation은 exact ProjectScope authorization, execution-trust closure와 inactive quarantine install state가 함께 닫힐 때까지 차단됩니다.

Generation-2 / V2 경계: Component Node 표현과 서드파티 UInode-presentation-profile.v2.json은 portable container 하나에 여러 Component 선언을 담는 requiredContractVersion: 2 successor를 설명합니다. 이 계약은 bounded local·관리자 lane에서 구현돼 있지만 공개 admission은 contract_only입니다. V2 Node projection은 기존 component.signed@1 재사용이 아니라 component.declarative@2이며, value schema는 component-declarative-node-value.v1.schema.jsonschemaVersion: 1입니다. 이 renderer version은 Component container contract V2·descriptor schema V2·componentContractVersion과 독립입니다. host renderer와 presentation-resolution bridge는 구현돼 있지만 현재 V1 component.signed@1 contract가 아니며, 공개 third-party admission을 열지 않습니다.

먼저 완성된 사용 형태를 확인하세요

아래 네 줄은 이미 materialize된 document/conformance fixture가 보존하는 authoring 모양입니다. 공개 third-party 설치·실행 절차가 아닙니다.

python
from midas_civil.components import model_viewer

view = flow.node("model_view", model_viewer, settings={"display_mode": "solid"})
flow.connect(model, view.inputs.model)

post-closure Component 상세에는 admission 이름, import 이름, Component symbol과 최소 배치 예제를 함께 제공합니다.

여러 Component를 검색하고 각 Node 표현을 비교하는 Components 화면

post-closure catalog에서는 한 package가 제공하는 각 Component를 독립된 항목으로 검색합니다. 구현된 local·관리자 lane의 admitted generation-2 target은 host-owned declarative body로 표시하고, V1 target이나 resolve 실패만 read-only unsupported diagnostic으로 표시합니다.

예시소유하는 것
Python distributionpipelinexlab-midas-civilpublic import와 companion descriptor 배포
public import modulemidas_civil.componentsimport 경로
Component symbolmodel_viewertyped authoring definition과 열린 discovery metadata
Node placement keymodel_view현재 Flow의 위치·연결·instance settings

1. 최소 Component 작성

python
from pipelinexlab import px


class ModelViewerResults(px.Results):
    selection: ModelSelection


@px.component(
    key="model_viewer",
    label="Model viewer",
    description="Displays a connected structural model.",
    category="review",
    subcategory="model",
)
def model_viewer(
    model: ModelRef,
) -> ModelViewerResults:
    ...
선언생성되는 계약
decorator의 key="model_viewer"process registry에서 stable componentKey
일반 Python typed parameterNode input port
px.Results의 annotated fieldNode result port
flow.node(..., settings={...})schema 없는 Node-local settings object
category닫힌 primary task registry(input, transform, calculate, review, deliver, control 여섯 개 중 하나)에서 고른 주작업
subcategory그 category 아래에서 publisher가 정하는 선택적 열린 key
portable V1 container declaration독립 componentContractVersion과 container-carried, integrity-measured declarative icon·summaryResultKeys

decorator는 Component definition metadata를 등록합니다. flow.node("node_key", component)가 만드는 placement shape는 wire와 conformance fixture에서 보존되지만, 외부 Component의 explicit placement와 공개 third-party activation은 위 closure 전까지 열지 않습니다.

현재 public SDK는 px.input, px.result, px.setting symbol이나 Component settings schema를 제공하지 않습니다. input/result는 일반 Python annotation에서 파생되고, settings={...}는 별도 label·default·choices 검증 없이 Node-local object로 저장됩니다. 구현된 lane의 Python worker는 이를 packaged executor의 execute(inputs, settings)에 전달하며, 공개 third-party activation은 계속 차단합니다. decorator가 감싼 Python body를 portable executor로 build하는 bridge도 아직 없으므로, V1 container의 executorEntry는 별도로 작성해 포함해야 합니다.

세 계약의 member를 섞지 않습니다.

권위현재 V1에서 소유하는 것
portable content/component.json declarationclassification: "flow-node" 하나, typed ports, executor와 container-carried, integrity-measured declarative presentation. category와 instance settings는 소유하지 않음
authoring ComponentDescriptor열린 semantic category/subcategory와 typed Component discovery. portable classification을 다시 정의하지 않음
.pxflow componentNode placementNode-local settings object와 binding. portable declaration이나 authoring category에 setting 값을 넣지 않음

2. package 구조와 public import

Component package는 기능별 symbol을 public components module에서 export합니다.

text
src/
└─ midas_civil/
   ├─ __init__.py
   ├─ components/
   │  ├─ __init__.py
   │  ├─ model_viewer.py
   │  └─ result_table.py
python
# midas_civil/components/__init__.py
from .model_viewer import model_viewer
from .result_table import result_table

__all__ = ["model_viewer", "result_table"]

Python Component package는 여러 Component를 export할 수 있습니다. 각 authoring Component는 독립적인 key, input/result, 닫힌 primary task category, publisher가 정하는 subcategory와 도움말을 갖습니다. 이를 Components에서 별도 항목으로 색인·검색하는 catalog query와 그 authenticated read relay는 구현돼 있고, 공개 third-party admission은 아직 열리지 않았습니다. instance setting 값은 배치한 componentNode에 남습니다.

현재 Python registry는 package namespace가 아니라 process 전체의 (kind, key)로 descriptor를 등록하므로, 같은 process에서 import하는 distribution 사이에도 componentKey가 고유해야 합니다. product resolver는 두 가지 argument shape를 받습니다. generation-1 호환 경로는 componentKey 하나로 조회하고 같은 key의 measured release가 둘 이상이면 모호성을 거부합니다. generation-2 경로는 publisherpackageKey로 한정한 package-scoped lookup을 사용하며, 이 경로는 구현돼 있습니다.

이 Python 배포 단위와 portable container 형식을 합치지 않습니다. 현재 portable Component container V1 reader는 container 하나에서 다음 content closure 하나만 받습니다.

text
content/
├─ component.json
└─ executor.py

각 V1 container의 componentContractVersion은 Python package/distribution version과 독립적으로 변경됩니다.

3. package metadata와 현재 build 경계

다음 [tool.pipelinexlab] 문법은 Python distribution에서 portable Component container를 생성할 향후 build contract의 예이며, 현재 packager가 읽는 실행 가능한 설정이 아닙니다.

toml
[project]
name = "pipelinexlab-midas-civil"
version = "2.3.4"

[tool.pipelinexlab]
contract-version = 1
package-key = "midas_civil"
entry-module = "midas_civil.components"
public-module = "midas_civil.components"
이름사용자에게 보여 주는 위치
distribution namePython environment와 public import source
package-key + version계획된 Project dependency와 lock
public moduleComponent 상세의 Use in Python
Component symbolimport와 flow.node(...) 예제

현재 @px.component registry와 portable container packager 사이에는 descriptor/body를 component.json·executor.py로 생성하는 bridge가 없습니다. 별도의 portable V1 container reader는 정확히 하나의 content/component.json 선언을 검사하며, 선언에는 componentKey, 독립 componentContractVersion, typed input/result, executorEntry와 container-carried, integrity-measured declarative presentation.icon·presentation.summaryResultKeys가 함께 들어갑니다. 내부 V1 구현에서 installer는 측정한 release와 closed grammar로 판정한 declaration을 저장합니다. 이는 production admission이 아닙니다. 그 내부 install 후 product.component.resolve의 product resolver가 두 record를 결합하고 closed target grammar로 다시 판정해 exact 7필드 ComponentRef를 만듭니다. 실행 materialization은 이 단계와 별개로 worker가 pinned release identity와 executor source digest를 다시 검증합니다.

현재 installer는 trust authority가 없을 때 signed Component를 기록 전에 거부하고, 명시적으로 수용한 unsigned Component만 absent·not-checked로 기록합니다. verified marketplace channel이 signature를 실제로 검증하고 그 결과를 기록한 release/declaration만 verified 또는 signed로 부릅니다. component.signed@1은 registry identifier일 뿐 signature 검증 증거가 아닙니다.

현재 production Flow reader는 V1 icon·summaryResultKeyscomponent.signed@1에 연결하지 않습니다. 이 V1 target은 exact identity를 보존한 read-only unsupported diagnostic으로 투영됩니다. V1 declaration→component.signed@1 bridge는 구현되지 않았지만 generation-2 component.declarative@2 bridge는 구현돼 있습니다. 어느 bridge의 존재도 공개 admission의 증거로 사용하지 않습니다.

4. V1 wire/internal fixture에서 배치·연결 검증

python
from pipelinexlab import px
from midas_civil.components import model_viewer


flow = px.Flow(
    "bridge_model_review",
    label="Bridge model review",
    description="Reviews selected members in one structural model.",
)
model = flow.input(
    "model",
    ModelRef,
    description="Structural model to review.",
)
view = flow.node(
    "model_view",
    model_viewer,
    settings={"display_mode": "solid"},
)
flow.connect(model, view.inputs.model)
flow.result(
    "selection",
    view.results.selection,
    description="Members selected in the model view.",
)

검증할 항목은 다음과 같습니다.

  • resolve 실패나 V1 target의 read-only unsupported diagnostic이 exact 7-field ComponentRef와 dependency identity를 보존하는지
  • input/result 이름, type과 unit이 source와 일치하는지
  • raw settings가 source/document V1 wire에 그대로 보존되는지
  • admitted generation-2 target은 host-owned declarative body로, resolve 실패나 V1 target은 read-only unsupported로 표시하며 settings editor를 잘못 열지 않는지
  • light/dark theme, keyboard와 200% zoom에서 사용할 수 있는지

5. 현재 install 구현을 production 경계와 구분하기

다음 Python module command는 구현된 local·관리자 install lane을 실행합니다. 공개 third-party Component admission으로 사용할 수 있는 public workflow가 아닙니다.

bash
python -m pipelinexlab install . --workspace <workspace_key> --project <project_key>

이 command는 Project scope를 exact contribution storage key와 catalog/detail/execution read에 보존합니다. 다만 executor bytes와 scoped contribution row를 곧바로 reachable하게 만들고 별도 inactive quarantine을 제공하지 않으며, 요청 Project를 authenticated principal의 권한에 결속하지도 않습니다. 따라서 이를 공개 third-party admission이 승인한 Component dependency 설치로 설명하면 안 됩니다. 다음 dependency command와 Studio workflow는 구현된 ProjectScope data-path isolation에 authorization·execution-trust closure를 더한 뒤에만 열 수 있는 successor contract이며, 현재 실행 가능한 CLI/UI가 아닙니다.

bash
# Planned contract only; not a current executable command.
pxlab dependency add midas_civil@^2.3.0

closure 이후의 Studio workflow에서는 Project → Dependencies → Add package에서 publisher, version, license와 capability를 검토합니다. admission이 통과한 뒤 Components → Installed에서 각 Component를 찾아 sample Flow에 배치합니다. 사용자 승인은 Project authorization이나 execution trust 검증을 우회하지 않습니다.

6. 선언형 presentation, Component Settings와 현재 reader

portable V1 content/component.json은 integrity-measured declarative presentationiconsummaryResultKeys를 container에 담습니다. 현재 production Flow reader는 이 V1 metadata를 component.signed@1 body로 resolve하지 않아 read-only unsupported diagnostic을 표시합니다. generation-2 target은 별도 component.declarative@2 value와 presentation-resolution bridge로 host-owned compact body를 그립니다.

향후 live resolver가 연결되더라도 선언형 presentation은 port나 실행 의미를 다시 정의하지 않습니다. flow.node(..., settings={...})는 선언된 Component면 그 선언에 대조해 값을 판정하고, 선언이 없는 기존 object는 Node instance에 그대로 저장합니다. public px.setting(...) authoring 문법과 settings schema는 component-declared-settings@1이 소유합니다.

현재 production Flow reader의 unsupported 경로는 settings 편집 surface를 활성화하지 않으며, 저장된 raw settings와 exact Component identity를 읽기 전용으로 보존합니다. V2 Node는 settings를 component-declared-settings@1로 선언당 최대 8개까지 받고 host control registry가 그립니다. category/subcategory도 기존의 열린 discovery metadata 의미를 유지합니다.

adapter와 standalone app surface는 V2 Component declaration field가 아닙니다. 격리 editor는 RFC-016의 별도 versioned contribution과 bridge를 사용하며, 외부 publisher package에서는 RFC-014 공개 admission을 통과해야 합니다. 외부 제품·서비스 연결도 별도 Integration contribution으로 다룹니다.

7. dependency 복구

현재 Flow document가 직접 보존하는 범위는 saved Node의 exact 7-field ComponentRef, raw settings, 그리고 input binding·public result usage에서 추론할 수 있는 partial ports입니다. original package bytes는 package artifact owner가 실제로 보존한 경우에만 exact bytes로 복구합니다. package release contribution custody는 canonical declaration과 executor digest를 저장하지만, 공개 recovery UI가 그 full snapshot을 읽어 표시하는 activation은 아직 닫혀 있습니다.

아래 상태와 동작은 authenticated-principal authorization과 execution-trust closure 이후의 successor recovery UI입니다. 현재 production에서 Add/Install을 실행하는 action이 아닙니다.

계획된 상태계획된 Node 정보계획된 동작
Extension requiredpackage, Component와 exact versionAdd required Extension
Version mismatchrequired/installed version과 contract diffReview update
Registry unavailableexact ref와 package artifact owner가 실제로 보존한 경우의 original package bytesRetry 또는 Locate package
Access requiredlicense·permission·capability reasonReview access

post-closure workflow는 복구 후 exact Component를 다시 resolve하고 Validate로 port, setting과 기존 연결을 확인합니다. 이름이 비슷한 Component나 다른 version으로 자동 교체하지 않습니다.

필요한 Component dependency와 계획된 복구 동작을 보여 주는 prototype Node

이 prototype은 successor exact-package recovery action을 보여 줍니다. Flow document는 exact 7-field target, raw settings와 usage-derived partial ports를 보존하고, package release custody의 retained declaration을 공개 recovery UI로 읽어 표시하는 activation은 아직 닫혀 있습니다.

8. post-closure release 문서 체크리스트

production admission closure 이후의 Component 상세 페이지는 같은 순서를 사용합니다.

  1. 한 문장 목적
  2. Function package의 현재 설치 명령 또는 Component의 post-closure admission 상태
  3. public import
  4. flow.node(...)flow.connect(...) 최소 예제
  5. V1 raw settings 호환 또는 별도 versioned settings contract 상태
  6. inputs
  7. results
  8. Studio 위치와 이미지
  9. compatibility와 capability
  10. 문제 해결과 source 링크

다음 문서