Skip to content

feat: Workflow Knowledge Collection 런타임 라우팅 연결 - #400

Merged
HyungminYoon1 merged 15 commits into
devfrom
feature/mba-233
Jul 13, 2026
Merged

feat: Workflow Knowledge Collection 런타임 라우팅 연결#400
HyungminYoon1 merged 15 commits into
devfrom
feature/mba-233

Conversation

@HyungminYoon1

Copy link
Copy Markdown
Contributor

변경 사항

  • LLM 노드 그래프에 기존 knowledgeBases와 함께 사용할 수 있는 knowledgeCollections 참조를 추가하고, UUID 형식·객체 구조·목록별 최대 20개 제한을 Shared 계약으로 검증합니다.
  • Workflow Builder에서 직접 Knowledge Base와 Knowledge Collection을 구분해 함께 선택할 수 있도록 UI와 API 타입을 확장했습니다. 현재 선택 권한이 사라진 참조는 임의 삭제하지 않고 안전한 unavailable 상태로 유지합니다.
  • Gateway에 Collection route 권한만 반영하는 최소 선택 목록 API를 추가했습니다. 모든 편집 가능 그래프 저장 경로에서 직접 KB use와 Collection route 권한을 서버가 다시 검증하며, 관리용 응답이나 저장된 표시값을 권한 근거로 사용하지 않습니다.
  • 배포 사전검사가 직접 KB와 Collection을 함께 검사하도록 확장했습니다. 익명 공개·인증 사용자·상속 audience를 서버에서 결정하고, 비공개·교차 조직·비활성·source-managed 공개 제한을 고정 코드와 제한된 집계만으로 차단하거나 경고합니다.
  • Workflow Engine이 Knowledge가 설정된 LLM 노드 invocation마다 MBA-232 runtime resolver를 정확히 한 번 호출하도록 연결했습니다. 현재 권한과 Collection membership으로 해석된 최대 20개의 정렬된 KB 후보만 기존 retrieval fan-out에 전달하며, 후보 없음 또는 resolver 실패 시 embedding·retrieval·LLM provider 호출 전에 안전하게 종료합니다.
  • 직접 KB와 Collection이 같은 KB를 가리키는 경우 canonical ID 기준으로 한 번만 검색하며, model routing과 관련 graph transformer가 Collection 참조를 보존하도록 보강했습니다.
  • 공개 app/deployment projection에서는 두 Knowledge 참조 목록을 모두 제거하고, 로그·trace·오류에는 Collection/숨겨진 후보의 식별자나 raw payload가 추가되지 않도록 경계를 유지했습니다.
  • ADR-0038과 Knowledge, Workflow, Deployment, 아키텍처 및 데이터 모델 문서를 현재 구현 계약에 맞게 갱신했습니다.
  • Collection 그래프 노출은 새 Workflow Engine worker 배포·기존 worker drain 이후 Gateway, Client 순서로 진행해야 합니다.

관련 이슈

Linear: MBA-233

변경 유형

  • 버그 수정
  • 새로운 기능
  • 리팩토링
  • 문서 수정
  • 기타: 권한·배포 사전검사·런타임 회귀 테스트 보강

테스트

  • 로컬에서 테스트 완료

  • 기존 테스트 통과 확인

  • Workflow Engine 전체: 606 passed

  • Gateway 관련 범위: 158 passed

  • Shared 전체: 714 passed, 31 skipped

  • Root 영향 범위: 169 passed, 1 skipped

  • Client 전체 Vitest: 통과

  • Client lint: 오류 0건, 기존 warning 225건

  • Client production build: 통과

  • git diff --check origin/dev...HEAD: 통과

로컬 PostgreSQL 연결이 필요한 일부 검증과 실제 배포 환경의 Worker-first canary/drain 증거는 배포 전 운영 게이트로 남아 있습니다.

스크린샷 (UI 변경 시)

LLM 노드 Knowledge 선택 패널 UI가 변경되었습니다. 컴포넌트 테스트와 production build로 검증했으며 별도 스크린샷은 첨부하지 않았습니다.

@linear-code

linear-code Bot commented Jul 13, 2026

Copy link
Copy Markdown

MBA-233

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcb4428076

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +156 to +160
WorkflowService.validate_knowledge_references(
db,
request,
user_id=user_id,
organization_id=workflow.organization_id,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 지식 참조가 없을 때는 조직 UUID 검증을 건너뛰세요

이 새 검증 호출은 Knowledge 참조 존재 여부와 무관하게 모든 draft 저장에 실행되는데, workflows.organization_id는 아직 nullable이고 legacy app/workflow 보정 경로도 남아 있습니다. 그런 legacy workflow에서 지식 참조가 전혀 없는 그래프를 저장해도 validate_knowledge_references()uuid.UUID(str(None))를 수행해 422로 막히므로, 먼저 그래프의 Knowledge 참조를 파싱/집계한 뒤 참조가 없으면 반환하거나 기존 fallback으로 organization scope를 보정해야 합니다.

Useful? React with 👍 / 👎.

.filter(
KnowledgeBase.id.in_(direct_ids),
KnowledgeBase.organization_id == self.organization_id,
KnowledgeBase.lifecycle_state == "active",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge source_deleted KB를 저장 단계에서도 제외하세요

source_deleted KB가 과거 ready chunk/version을 보존한 경우 이 loader와 _retrieval_ready_ids()는 lifecycle만 확인하므로 direct KB 참조가 저장/배포 검증을 통과합니다. 하지만 이번 변경의 runtime candidate adapter는 sync_state == "source_deleted"를 후보에서 제외하므로, preflight는 통과했는데 배포된 RAG 노드는 실행 시 후보 없음으로 안전 응답을 반환할 수 있습니다. write/preflight readiness 경계에도 동일한 sync_state != "source_deleted" 조건을 적용해야 합니다.

Useful? React with 👍 / 👎.

else self._resolve_runtime_knowledge_candidates()
)
candidate_summary = self._knowledge_candidate_trace_summary(resolution)
kb_ids = [str(candidate.knowledge_base_id) for candidate in resolution.candidates]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Collection 후보 ID를 trace/result에 노출하지 마세요

Collection을 선택한 LLM 노드에서는 resolver가 동적으로 찾은 child KB들이 여기서 provenance 없이 평탄한 KB id 목록이 되고, 이후 _knowledge_trace_metadata()_record_rag_retrieve_audit()가 이 id와 chunk/document id를 metadata.knowledge_search, trace payload, audit metadata에 그대로 씁니다. Collection membership을 graph에 materialize하지 않고 count bucket만 남기는 계약과 달리 public/실행 결과에서 숨겨야 할 child identity가 드러날 수 있으므로, collection 유래 candidate는 provenance를 유지해 result/trace/audit에서는 id 대신 bucket/route summary로 redaction해야 합니다.

Useful? React with 👍 / 👎.

KnowledgeCollection.created_at.desc(),
KnowledgeCollection.id.asc(),
)
.limit(MAX_LLM_SELECTABLE_COLLECTION_SCAN)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 권한 필터 전에 Collection 목록을 자르지 마세요

여기서 active Collection을 최신순 500개로 먼저 자른 뒤에 bulk_evaluate_collection_action(..., "route")를 적용하므로, 조직에 active Collection이 500개를 넘고 사용자가 route 권한을 가진 Collection이 그 뒤에 있으면 LLM picker가 빈 목록을 반환하거나 기존 선택을 unavailable로 표시합니다. route 권한이 있는 후보 기준으로 제한하거나 pagination/search를 붙여야 권한 있는 Collection을 안정적으로 선택할 수 있습니다.

Useful? React with 👍 / 👎.

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

@codex review

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56cb023719

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

KnowledgeBase.id.in_(direct_ids),
KnowledgeBase.organization_id == self.organization_id,
KnowledgeBase.lifecycle_state == "active",
KnowledgeBase.sync_state != "source_deleted",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 선택 후보와 저장 검증 조건을 맞추세요

이 새 source_deleted 제외 조건은 저장/배포 시 해당 KB 참조를 403으로 막지만, Builder가 쓰는 /knowledge/llm-selectable 후보 조회는 여전히 lifecycle_state == "active"와 completed chunk만 확인해서 source-deleted KB가 목록에 남을 수 있습니다. 외부 source 삭제 후 chunk가 남아 있는 KB를 사용자가 picker에서 선택하면 UI가 허용한 선택을 저장할 때 바로 실패하므로, 같은 sync_state != "source_deleted" 필터를 selectable 후보에도 적용해야 합니다.

Useful? React with 👍 / 👎.

.filter(
KnowledgeCollection.id.in_(collection_ids),
KnowledgeCollection.organization_id == self.organization_id,
KnowledgeCollection.lifecycle_state == "active",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge source-deleted Collection을 저장 시 제외하세요

source-backed Collection이 삭제되어 sync_state='source_deleted'가 되었지만 lifecycle이 아직 active인 경우, 이 조회는 계속 Collection을 로드해서 route 권한만 있으면 workflow 저장/배포 검증을 통과시킵니다. 그러면 stale Collection 참조가 runtime 후보 해석까지 남을 수 있으므로, Collection의 sync eligibility도 검증하도록 KnowledgeCollection.sync_state != 'source_deleted' 조건을 같은 경계에 추가해야 합니다.

Useful? React with 👍 / 👎.

Comment on lines +274 to +277
kbs_by_id = self.repository.get_active_knowledge_bases(
kb_ids,
self.organization_id,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge preflight에서도 KB readiness를 검증하세요

여기서는 direct KB를 active 여부로만 평가해서, public Collection에 연결된 active KB가 아직 retrieval-visible chunk/version이 없는 경우에도 preflight가 통과할 수 있습니다. 하지만 실제 배포 생성은 앞단의 validate_knowledge_references에서 같은 KB를 retrieval-ready가 아니라고 403으로 거부하므로, 사용자는 배포 전 검사는 통과했는데 곧바로 배포가 실패하는 흐름을 보게 됩니다; preflight repository/result에도 save-time과 같은 readiness 경계를 반영해야 합니다.

Useful? React with 👍 / 👎.

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown
Contributor Author

Codex 리뷰를 검토한 결과, 최신 P2 3건이 모두 타당하여 인접 우회 경로까지 함께 보완했습니다.

조치 내용

  • /knowledge/llm-selectable에서 source_deleted 및 retrieval-invisible KB 제외
  • Collection picker·editable graph save·deployment preflight·Workflow Engine runtime에서 source_deleted parent Collection 제외
  • Direct KB preflight와 public membership/Collection aggregate에 save-time과 동일한 retrieval-visible completed chunk readiness 적용
  • lifecycle/sync/readiness 조건을 공통 Knowledge eligibility predicate로 정리
  • Architecture, ADR-0039, Knowledge/Deployment 공식 문서 계약 정렬

근본 원인은 picker, save, preflight, runtime이 적격성 조건을 개별 구현하면서 lifecycle, sync state, retrieval readiness 일부가 경로별로 누락된 policy drift였습니다. 공통 predicate와 교차 경계 테스트를 추가해 재발 가능성을 낮췄습니다.

검증

  • Knowledge/Deployment/Workflow 도메인 회귀: 147 passed, 1 skipped
  • 최종 변경 관련 테스트: 76 passed
  • Ruff 및 git diff --check: 통과
  • Skip 1건은 로컬 disposable PostgreSQL 접속 환경 미설정이며 실제 DB fixture 자체는 source-deleted/archived/cross-org/retrieval-visible 조합으로 보강했습니다.

커밋

  • b4ff694f fix(knowledge): 적격성 경계 정합성 보강
  • 286416d4 docs(knowledge): 적격성 경계 계약 정렬

두 커밋 모두 feature/mba-233에 push 완료했습니다.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

return (
isinstance(safe_metadata, dict)
and safe_metadata.get("visibility") == "public"

P1 Badge anonymous 런타임에서 source-managed Collection을 제외하세요

Preflight는 source-managed Collection을 source_public_exposure_required로 차단하도록 추가됐지만, 실제 런타임 resolver는 여기서 safe_metadata.visibility == "public"만 확인해 allowed_collection_ids에 포함합니다. 그래서 public/chatbot/webhook 같은 anonymous_public 실행에서 기존 public Collection이 source-managed가 되거나 source-managed Collection이 public 상태이면, 배포 전 검사와 달리 그 Collection의 manual child KB가 검색 후보로 사용되어 source public exposure 경계를 우회할 수 있습니다; runtime에서도 source_identity_id/public exposure approval을 fail-closed로 확인해야 합니다.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

리뷰에서 지적된 anonymous source-managed Collection 우회 경로를 커밋 54405aae에서 보완했습니다.

조치 내용:

  • 원인: anonymous runtime이 Collection의 visibility=public만 확인하고 source_identity_id를 조회·검증하지 않아 Gateway preflight와 runtime 정책이 어긋났습니다.
  • Shared eligibility 정책에 anonymous public Collection의 공통 SQL predicate와 loaded-row fail-closed 판정을 추가했습니다.
  • Workflow Engine은 source-managed Collection 또는 source identity projection이 누락된 Collection을 membership scan 전에 제외합니다.
  • 동일 정책을 직접 KB의 public Collection membership 경로와 Gateway deployment preflight에도 적용했습니다.
  • source public exposure approval primitive가 없는 현재 상태에서는 source-managed Collection의 public 전환도 차단합니다.
  • 인증 실행의 Collection route 및 KB use 권한 경로는 그대로 유지했습니다.
  • ADR-0036 및 Knowledge requirements/API/component/test 문서를 현재 계약에 맞게 갱신했습니다.

검증 결과:

  • Shared eligibility: 5 passed
  • Gateway 관련 회귀: 84 passed, 1 skipped
  • Workflow Engine RAG 회귀: 164 passed
  • Ruff 및 git diff --check: 통과

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

PostgreSQL CI 실패를 커밋 4344d98e에서 수정했습니다.

원인:

  • runtime이 anonymous Collection 공개 경계를 검증하기 위해 knowledge_collections.source_identity_id를 projection하도록 변경됐습니다.
  • 실제 모델과 migration에는 컬럼이 있지만, disposable PostgreSQL CI fixture의 수동 CREATE TABLE 정의에는 해당 컬럼이 누락돼 있었습니다.
  • 따라서 실제 PostgreSQL snapshot query가 실패했고, runtime의 안전한 오류 변환에 따라 8건 모두 snapshot_read_failed로 표시됐습니다.

조치:

  • disposable knowledge_collections schema에 nullable source_identity_id 컬럼을 추가했습니다.
  • public source-managed Collection에 manual ready KB가 연결돼 있어도 anonymous snapshot에서 제외되는 실제 PostgreSQL 통합 테스트를 추가했습니다.

검증:

  • PostgreSQL 16 임시 인스턴스에서 CI와 동일한 명령 실행
  • 38 passed
  • Ruff 및 git diff --check 통과

@HyungminYoon1

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 4344d98e36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@HyungminYoon1
HyungminYoon1 marked this pull request as ready for review July 13, 2026 16:45
@HyungminYoon1
HyungminYoon1 merged commit 16cf9c0 into dev Jul 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant