Skip to content

feat(knowledge): add selective share and promote UI - #2065

Merged
ootakazuhiko merged 12 commits into
mainfrom
feat/2015-knowledge-share-promote-ui
Aug 10, 2026
Merged

feat(knowledge): add selective share and promote UI#2065
ootakazuhiko merged 12 commits into
mainfrom
feat/2015-knowledge-share-promote-ui

Conversation

@ootakazuhiko

@ootakazuhiko ootakazuhiko commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

対象

背景・目的

Knowledge の selective immutable share、Chat の knowledge-share card、選択 reply の Knowledge synthesis promotion を既存 Knowledge Hub / Room Chat UI へ接続します。共有は元 Knowledge ACL の移譲ではなく、room 利用者が閲覧できるのは共有時に固定した選択済み snapshot のみです。

実装概要

  • Knowledge Hub に Chatへ共有 パネルを追加
    • destination room、field/label/annotation/turn/synthesis version の明示選択
    • exact preview、omitted field 表示、external audience の追加確認
    • confirm 後の idempotent commit、pending reconcile、revoke
    • sensitive category は既定未選択、title のみ安全な既定選択
  • Room Chat に immutable knowledge-share card を追加
    • selected content のみ表示、generic fallback body を維持
    • source-open は専用 endpoint 経由で current Knowledge ACL を再評価
    • revoked placeholder、thread/reaction/ACK/unread の既存 UI と統合
  • thread promotion dialog を追加
    • root card と direct active reply のみを候補化
    • reply は既定未選択、選択順・本文・時刻を preview response と照合
    • personal 既定、organization は grant と audience confirmation を必須化
    • preview token / request key は component memory のみに保持し、tab/room/thread 切替で破棄
  • additive API: GET /knowledge/items/{id}/label-assignments
    • canonical actor の item/label ACL を適用し、active assignment を最大100件、allowlist response で返却
  • PostgreSQL 実 E2E で判明した既存 raw SQL alias grant の構文問題を item_grant へ修正
  • manual、test-results、synthetic screenshot 3点を追加・更新

設計上の判断

  • Room card 閲覧と source-open を分離し、room-only viewer へ source/internal ID を返しません。
  • ChatMessage body へ title/excerpt/URL 等を複製せず、旧 client は非機密な generic body を表示します。
  • card/promotion API response は allowlist normalize し、unknown/provider/internal/raw error field を state/DOM へ取り込みません。
  • promotion は、room に明示共有済みの immutable card snapshot と current room で見える選択 reply を source とします。元 item の source-open 権限は付与しません。
  • root ID 収集は direct root のみに限定し、現在開いている thread root を100件上限より優先します。
  • 同件数の別 reply 置換を content/createdAt/order/authorCategory の照合で fail-closed にします。commit の exact identity/version は backend preview token が保証します。

契約変更

  • API: GET /knowledge/items/{id}/label-assignments を additive に追加
  • Prisma schema / migration / env / npm dependency: 変更なし
  • OpenAPI: additive endpoint のみ。breaking diff なし
  • 既存 Chat/Knowledge API: field rename/delete/type change なし

後方互換性・ロールバック

Security / Privacy

  • unselected canary(private label、annotation、AI/system/tool turn、synthesis version、private URL/provider metadata)が card/API/search/notification/UI/evidence に現れないことを real-backend E2E で確認しました。
  • preview token / opaque request key は DOM、localStorage、log、screenshot へ出さず、panel unmount と context switch で破棄します。
  • unauthorized/not-found は同一の安全な表示へ正規化し、ACL 喪失時は cached card/source state を purge します。
  • screenshot は synthetic data のみで、実利用者・実本文・credential・内部 ID を含みません。
  • independent correctness/security review の初回指摘(root/reply境界、100件境界、same-count reply置換、token memory retention、確定中のApp/room/thread遷移、非同期snapshot混入)は修正済みです。最終 exact-head correctness/security review は blocking 0 / non-blocking 0、Copilot actionable finding 0 で完了しました。
  • Copilot 指摘の重複し得る固定 ARIA ID は React useId() に置換しました。promotion context key は exact card/reply変更時の fail-closed invalidationを維持しつつ、useMemoで大きなobjectの毎render serializationを避けました。確定中は内部guardだけでなくRoom作成・投稿・ACK等のcontrolもdisabledに揃え、共有者メモの方向制御文字Setはmodule定数として再利用します。

検証

Exact head: c2f6d14d3fc22636c89c4b6060b983ea7c927d1b

  • backend focused: 65/65 PASS
  • frontend full: 104 files / 793 tests PASS
  • RoomChat root lifecycle race regression: 20/20 runs PASS(2 cases/run、composer表示完了を公開待機条件へ変更)
  • backend full: 2168/2168 PASS
  • frontend focused exact-head remediation: 9 files / 145 tests PASS(App/room/thread/itemの確定所有権、body-target Escape、非同期snapshot混入防止、抽出 lifecycle helper、複数dialog ARIA関連付けを含む)
  • PostgreSQL 15 real-backend focused E2E: 1/1 PASS(promotion previewを固定IDではなくaccessible region名で検証)
  • extended/full E2E: 154 PASS / 34 existing environment-conditional SKIP / 0 FAIL
  • RELEASE_E2E_SCOPE=core make release-readiness: PASS
  • CI remediation: snapshot保存後の非同期描画を findByRole で待機。対象case 20/20、UI core coverage 104 files / 793 tests PASS
  • UI core coverage: statements 73.55%、branches 66.59%、functions 73.22%、lines 76.34%(抽出 helper 2件を追加し、既存 threshold 維持)
  • frontend build budget: PASS(initial gzip 158.1 KiB、largest chunk gzip 87.1 KiB)
  • make lint: PASS
  • make format-check: PASS
  • make typecheck: PASS
  • make build: PASS
  • make test: PASS
  • make audit: PASS(backend/frontend high audit 0)
  • make ops-quality: PASS
  • bounded-context dependency / coverage: PASS
  • Prisma format / validate: PASS
  • OpenAPI export / breaking diff: PASS(additive endpoint のみ)
  • docs index / image links: PASS
  • secret scan: PASS(tracked 2091 files、match 0)
  • git diff --check: PASS
  • exact-head CI: push 31391418331 / PR 31391421907 / CodeQL 31391422005 / Link Check 31391419135, 31391421952 PASS
  • review completeness: status=ok、unresolved thread 0

証跡

未実施範囲

  • external LLM / AI 自動要約
  • Google Drive / Sakura Object Storage の実 credential
  • Sakura VPS / live Quadlet / systemd
  • production migration / provider cutover / DB restore

GitHub の既存 Dependabot alerts は本 PR へ混在させていません。repository lockfile に対する npm audit --audit-level=high は backend/frontend とも 0 vulnerabilities です。

Copilot AI 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.

Pull request overview

Knowledge の selective immutable share と、Chat 上の knowledge-share card 表示・選択 reply の promote(synthesis 化)を既存 UI に接続し、Additive な label-assignment 参照 API も追加する PR です(#2015)。

Changes:

  • Room Chat に immutable knowledge-share card の描画と promote UI(thread 内)を統合
  • Knowledge Hub に「Chatへ共有」タブ+knowledge_item deep link の受け口を追加
  • Additive API GET /knowledge/items/{id}/label-assignments と、関連 adapter / use case / OpenAPI / テストを追加(+ SQL alias grant 修正)

Reviewed changes

Copilot reviewed 47 out of 50 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/frontend/src/sections/RoomChat.tsx knowledge-share 統合 hook / presentation helper の導入と thread 側への promote renderer 注入
packages/frontend/src/sections/RoomChat.test.tsx RoomChat における knowledge-share card 置換の統合テスト追加(hook mock)
packages/frontend/src/sections/room-chat/RoomMessageList.tsx message body の描画に knowledge-share renderer を差し込めるよう拡張
packages/frontend/src/sections/room-chat/ChatThreadPanel.tsx thread root に knowledge-share renderer を差し込み、promote UI を thread 下部に追加可能に
packages/frontend/src/sections/room-chat/RoomKnowledgeShareIntegration.tsx timeline/thread の root 群から share card を読み、card 描画と promote launcher を提供
packages/frontend/src/sections/room-chat/RoomKnowledgeShareIntegration.test.tsx visible root selection(100件上限・opened thread 優先)のユニットテスト追加
packages/frontend/src/sections/room-chat/useRoomKnowledgeShares.ts room 内で見えている root だけを対象に summary → card を安全に解決する hook を追加
packages/frontend/src/sections/room-chat/useRoomKnowledgeShares.test.tsx 取得の並列数制限、purge、fail-closed、100件超入力などのテスト追加
packages/frontend/src/sections/room-chat/KnowledgeShareCard.tsx selected-only 表示・revoked placeholder・source-open(安全化)を持つカード UI を追加
packages/frontend/src/sections/room-chat/KnowledgeShareCard.test.tsx カードの表示・選択カテゴリガード・source-open の安全化/abort のテスト追加
packages/frontend/src/sections/room-chat/KnowledgeThreadPromotionDialog.tsx 選択 reply を preview/confirm して synthesis 化する dialog 実装
packages/frontend/src/sections/room-chat/KnowledgeThreadPromotionDialog.test.tsx promote の選択/順序/confirm/abort/サニタイズ等のテスト追加
packages/frontend/src/sections/room-chat/roomChatPresentation.tsx RoomChat の markdown body 描画・リンクコピー・サマリー構築を helper 化
packages/frontend/src/sections/room-chat/roomChatApi.ts fetchChatRooms が RequestInit(signal 等)を受け取れるよう拡張
packages/frontend/src/sections/KnowledgeHub.tsx erp4_open_entity で knowledge_item を開く deep link 対応、SharePanel へ snapshots を供給
packages/frontend/src/sections/KnowledgeHub.test.tsx knowledge_item deep link を受けて item を開くテスト追加
packages/frontend/src/sections/knowledge-hub/KnowledgeProvenanceWorkspace.tsx provenance workspace に「Chatへ共有」タブを追加
packages/frontend/src/sections/knowledge-hub/KnowledgeProvenanceWorkspace.test.tsx 4タブ化と SharePanel 表示のテスト追加
packages/frontend/src/sections/knowledge-hub/KnowledgeSharePanel.tsx selective share の preview/commit/reconcile/revoke を UI として統合
packages/frontend/src/sections/knowledge-hub/knowledgeSharePanelHelpers.ts share panel 用の候補マージ/表示ラベル/unsafe 文字判定 helper を追加
packages/frontend/src/sections/knowledge-hub/knowledgeProvenanceApi.ts provenance API 群に AbortSignal をフォワード可能に拡張
packages/frontend/src/sections/knowledge-hub/knowledgeProvenanceApi.test.ts AbortSignal フォワードのテスト追加
packages/frontend/src/sections/knowledge-hub/knowledgeHubApi.ts getKnowledgeItem(deep link 用)を追加
packages/frontend/src/sections/knowledge-hub/knowledgeHubApi.test.ts getKnowledgeItem の encode と allowlist 正規化のテスト追加
packages/frontend/src/sections/knowledge-share/knowledgeShareApi.ts share/promotion/label-assignments/read 系の API boundary(safe error + allowlist 正規化)を追加
packages/frontend/src/sections/knowledge-share/knowledgeShareApi.test.ts API boundary の allowlist / safe error / topology binding のテスト追加
packages/frontend/src/sections/knowledge-share/knowledgeShareModel.test.ts request/response 正規化・binding・拒否条件のテスト追加
packages/frontend/src/pages/App.tsx deep link kind knowledge_item を knowledge-hub セクションへルーティング
packages/frontend/src/pages/App.test.tsx knowledge_item deep link の dispatch テスト追加
packages/frontend/e2e/frontend-knowledge-share-promote.spec.ts 実 backend E2E(share card / ACL / omitted field / promote)追加
packages/frontend/coverage-thresholds.json 追加コンポーネント/境界を coverage 対象へ追加
packages/backend/src/routes/knowledgeLabels.ts GET /knowledge/items/:id/label-assignments を additive に追加
packages/backend/src/application/knowledge/knowledgeLabelUseCases.ts label assignment selection の use case(404 正規化・100件上限)追加
packages/backend/src/application/knowledge/knowledgeLabelPorts.ts selection option 型と read repository port を追加
packages/backend/src/adapters/knowledge/prismaKnowledgeLabelAdapter.ts item ACL + label 可視性を組み合わせた selection 読み取りを実装
packages/backend/src/adapters/knowledge/prismaKnowledgeShareAdapter.ts raw SQL の予約語 alias grantitem_grant に修正
packages/backend/test/knowledgeLabelUseCases.test.js selection use case の 404 正規化/上限/actor 伝播テストを追加
packages/backend/test/knowledgeLabelRoutes.test.js label-assignments route の allowlist 返却/404 正規化テストを追加
packages/backend/test/knowledgeLabelPrismaAdapter.test.js selection 読み取りの predicate / bound / null 正規化テストを追加
docs/api/openapi.json label-assignments endpoint を OpenAPI に追加
docs/manual/README.md Knowledge Hub マニュアルのスコープ更新
docs/manual/knowledge-hub.md selective share / promote の操作手順と注意点を追記
docs/manual/chat-guide.md knowledge-share card と promote の利用ガイド追記
docs/test-results/README.md #2015 証跡リンクを追加
docs/test-results/2026-08-10-issue2015-knowledge-share-promote-ui.md #2015 検証記録(UI/E2E/安全性)を追加

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI 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.

Pull request overview

Copilot reviewed 47 out of 50 changed files in this pull request and generated no new comments.

Copilot AI 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.

Pull request overview

Copilot reviewed 47 out of 50 changed files in this pull request and generated no new comments.

Copilot AI 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.

Pull request overview

Copilot reviewed 49 out of 52 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/frontend/src/sections/room-chat/KnowledgeShareCard.tsx:75

  • <dl> の子要素として dt/dddiv でラップしていますが、dl の直接の子要素として許可されるのは dt / dd(他に script / template)のみのため、HTML セマンティクスが崩れて支援技術での読み上げが不安定になる可能性があります。SelectedFieldFragmentdt/dd を直接返す形にしてください。

Copilot AI 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.

Pull request overview

Copilot reviewed 51 out of 54 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/frontend/src/sections/room-chat/KnowledgeThreadPromotionDialog.tsx:219

  • contextKeyroot / knowledgeShare のオブジェクト全体を JSON.stringify しており、本文やカード内容を含む大きなオブジェクトを毎回シリアライズするためレンダリングコストが増えます。プレビュー/確定の整合性確認に必要な最小限の安定キー(roomId/root.id/shareId/version/status/activeReplyKey 等)に絞って組み立てると、意図も明確になりパフォーマンスも改善します。
    packages/frontend/src/sections/room-chat/KnowledgeThreadPromotionDialog.tsx:691
  • aria-labelledby / aria-describedby に固定ID(knowledge-thread-promotion-*)を使っているため、同ダイアログが並行して2つ以上開かれる(あるいはテスト/将来のUI変更で複数マウントされる)と DOM 内で ID が重複し、支援技術での関連付けが壊れます。useId() などでインスタンス固有IDを生成し、見出し/説明/各セクションの idaria-* 参照を同じ値で結び直してください。

Copilot AI 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.

Pull request overview

Copilot reviewed 51 out of 54 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/frontend/src/sections/RoomChat.tsx:140

  • knowledgeCommitBusy 中は createPrivateGroup / createDm / postMessage などが roomNavigationBlockedRef で早期returnする一方、UI 側は rootPostBlocked(root投稿だけ)でdisabled判定している箇所が残っているため、ボタン等が有効に見えるのにクリックしても何も起きない状態になります。rootPostBlockedroomNavigationBlocked と同じ条件にして、disabled状態とガード条件を一致させてください。
  const rootPostBlocked = rootPostLifecycle !== 'idle';

packages/frontend/src/sections/knowledge-hub/knowledgeSharePanelHelpers.ts:54

  • hasUnsafeKnowledgeShareNoteCharacter が呼ばれるたびに new Set([...]) を生成しており(入力バリデーション等で繰り返し呼ばれると)不要な割り当てになります。方向制御コードポイントのSetはモジュール定数にして再利用してください。

@ootakazuhiko
ootakazuhiko requested a lite review from Copilot August 10, 2026 12:48

Copilot AI 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.

Pull request overview

Copilot reviewed 51 out of 54 changed files in this pull request and generated no new comments.

@ootakazuhiko

Copy link
Copy Markdown
Collaborator Author

Exact-head independent review record

Exact head: 2004254823f86c707dd76a43421e23730b2f31a8
Base: ac51f1f6a6241e044c28cb191b6bdcaf5f557036

  • Independent correctness review: blocking 0 / non-blocking 0
    • commit ownership across App / Knowledge item / Chat room / thread
    • stale async state, body-target Escape, reply/card context invalidation
    • instance-scoped ARIA relationships and semantic E2E selector
    • exact E2E-only delta from the previous reviewed head
  • Independent security/privacy review: blocking 0 / non-blocking 0
    • room-card/source-open ACL separation
    • token/request-key in-memory boundary
    • source/internal/provider/raw-error non-disclosure
    • unselected content canaries and promotion destination boundary
    • exact E2E-only delta from the previous reviewed head

Reviewer-side focused evidence included RoomChat 62/62 and the promotion-commit focused path. Parent exact-head evidence additionally includes frontend 104 files / 793 tests, focused UI 71/71, UI-core coverage gate, and real PostgreSQL/browser @knowledge-share E2E 1/1.

Copilot AI 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.

Pull request overview

Copilot reviewed 51 out of 54 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/frontend/src/sections/room-chat/KnowledgeThreadPromotionDialog.tsx:349

  • useEffect(() => resetDialog(), [contextKey, open]) が commit 中も無条件に実行されるため、スレッドの返信追加などで contextKey が変化した場合に commitInFlightRef/busy 状態がリセットされ、非中断コミットの所有権(ダイアログを閉じない/遷移しない)を失う可能性があります。commit 中はコンテキスト変化でリセットしないようガードしてください。

@ootakazuhiko

Copy link
Copy Markdown
Collaborator Author

@copilot review

@ootakazuhiko

Copy link
Copy Markdown
Collaborator Author

CI remediation: UI coverage実行で検出された snapshot 保存後の非同期描画raceを、公開accessible roleを findByRole で待機する形へ修正しました。exact head c2f6d14d3fc22636c89c4b6060b983ea7c927d1b で focused 20/20 と UI core coverage 104 files / 793 tests が成功しています。新headとしてCI・独立review・Copilot・coolingを再実施します。

Copilot AI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@copilot review

The current branch has only test/E2E fix commits (c2f6d14, 2004254). No new issues found:

  • c2f6d14: replaces findByTestId snapshot wait with findByRole accessible-role wait — correct fix for the async paint race.
  • 2004254: replaces fixed element ID selector in E2E with accessible region name — correct fix for the semantic selector.

No blocking or non-blocking concerns on the test-only delta.

@ootakazuhiko

Copy link
Copy Markdown
Collaborator Author

Final exact-head independent review record

Exact head: c2f6d14d3fc22636c89c4b6060b983ea7c927d1b
Base: ac51f1f6a6241e044c28cb191b6bdcaf5f557036

  • Independent correctness review: blocking 0 / non-blocking 0
    • 20042548..c2f6d14dKnowledgeHub.test.tsx の非同期 assertion 1行のみ
    • production code不変
    • reviewer focused: KnowledgeHub 14/14、対象case 3/3
  • Independent security/privacy review: blocking 0 / non-blocking 0
    • test-only deltaでACL、token/request-key、redaction、secret境界への影響なし
  • Parent exact-head evidence:
    • 対象case 20/20
    • UI core coverage 104 files / 793 tests、threshold PASS
  • Copilot exact-head review: actionable finding 0

required CI と release-readiness 完了後に review completeness を再実行し、その時刻から cooling を開始します。

@ootakazuhiko

Copy link
Copy Markdown
Collaborator Author

Exact-head gate and cooling start

  • Exact head: c2f6d14d3fc22636c89c4b6060b983ea7c927d1b
  • Base: ac51f1f6a6241e044c28cb191b6bdcaf5f557036
  • required CI / CodeQL / Link Check / security audit / secret scan: PASS
  • local RELEASE_E2E_SCOPE=core make release-readiness: PASS(9m49s、core E2E 108/108)
  • independent correctness/security review: blocker 0
  • Copilot exact-head review: actionable finding 0
  • review completeness: status=ok、unresolved thread 0
  • mergeable: CLEAN

Cooling start: 2026-08-10T13:22:53Z(JST 2026-08-10T22:22:53+09:00
Earliest merge gate: 2026-08-10T14:22:53Z(JST 2026-08-10T23:22:53+09:00

Cooling中も head/base/check/review/thread を再取得し、変更またはactionable findingがあればgateをリセットします。

@ootakazuhiko
ootakazuhiko marked this pull request as ready for review August 10, 2026 14:25
@ootakazuhiko
ootakazuhiko merged commit d801cda into main Aug 10, 2026
23 checks passed
@ootakazuhiko
ootakazuhiko deleted the feat/2015-knowledge-share-promote-ui branch August 10, 2026 14:59
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.

feat(knowledge): selective Chat share card and promote flow

3 participants