feat(knowledge): promote selected Chat thread messages - #2052
Conversation
There was a problem hiding this comment.
Pull request overview
Knowledge Hub の「Chat thread から、利用者が明示選択した direct reply のみを新規 KnowledgeSynthesis v1 へ昇格する」バックエンド境界(schema / domain / routes / adapters / tests / docs)を追加し、既存の Knowledge share / Chat 互換を維持したまま promotion を additive に実装するPRです。
Changes:
KnowledgeThreadPromotionaggregate(selected-only immutable snapshot / request ledger / group grants / provenance FK)と expand-only migration を追加- preview/commit API(
/chat-messages/:rootMessageId/promote-to-knowledge[/preview])と token/idempotency を実装 - synthesis visibility / provenance へ thread promotion source を統合し、Chat ACL 失効後は provenance を redact する挙動を追加
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| scripts/test-knowledge-thread-promotion-schema-postgres.sh | Promotion schema の PostgreSQL 統合検証スクリプト追加 |
| scripts/test-knowledge-thread-promotion-old-app.sh | old-app 互換検証(baseline SHA 固定)スクリプト追加 |
| packages/backend/test/knowledgeThreadPromotionUseCases.test.js | use case(preview/commit/idempotency/validation)単体テスト追加 |
| packages/backend/test/knowledgeThreadPromotionToken.test.js | preview token codec の単体テスト追加 |
| packages/backend/test/knowledgeThreadPromotionSchema.test.js | Prisma schema/migration/integration wrapper の契約テスト追加 |
| packages/backend/test/knowledgeThreadPromotionRoutes.test.js | Fastify routes の入出力 allowlist/validation テスト追加 |
| packages/backend/test/knowledgeThreadPromotionAuditAdapter.test.js | promotion audit writer のメタデータ境界テスト追加 |
| packages/backend/test/knowledgeProvenanceUseCases.test.js | 一般 synthesis API から thread_promotion source を指定不可にする回帰テスト追加 |
| packages/backend/src/routes/knowledgeThreadPromotions.ts | promotion preview/commit の新規 route と schema/mapper 追加 |
| packages/backend/src/routes/knowledgeSyntheses.ts | actor に chat claims を含め、thread promotion provenance の可視性評価を可能に |
| packages/backend/src/routes/knowledgeShares.ts | knowledgeSharePublicCardSchema を export、chat actor 取得を共通化 |
| packages/backend/src/routes/knowledgeRouteContext.ts | chat claims を KnowledgeActor へ optional に注入できるよう拡張 |
| packages/backend/src/routes/index.ts | promotion routes の登録追加 |
| packages/backend/src/application/knowledge/knowledgeThreadPromotionUseCases.ts | promotion use cases(validation/token/idempotency)追加 |
| packages/backend/src/application/knowledge/knowledgeThreadPromotionToken.ts | domain-separated HMAC preview token codec 追加 |
| packages/backend/src/application/knowledge/knowledgeThreadPromotionPorts.ts | promotion port/DTO/limits 定義追加 |
| packages/backend/src/application/knowledge/knowledgeSynthesisUseCases.ts | synthesis source kind の入力許可リストを knowledgeSynthesisInputSourceKinds に更新 |
| packages/backend/src/application/knowledge/knowledgeProvenancePorts.ts | thread_promotion kind を内部用に追加、入力用 kind を分離 |
| packages/backend/src/application/knowledge/knowledgeItemPorts.ts | KnowledgeActor に optional chat claims を追加 |
| packages/backend/src/adapters/knowledge/prismaKnowledgeThreadPromotionAuditAdapter.ts | promotion audit の Prisma writer 追加 |
| packages/backend/src/adapters/knowledge/prismaKnowledgeSynthesisVisibility.ts | synthesis 可視性 where と thread promotion source の Chat ACL 検査を追加 |
| packages/backend/src/adapters/knowledge/prismaKnowledgeProvenanceAdapter.ts | provenance に thread promotion source を統合、visibility where を差し替え |
| packages/backend/scripts/knowledge-thread-promotion-schema-integration.mjs | promotion schema の DB 統合検証追加 |
| packages/backend/scripts/knowledge-thread-promotion-application-integration.mjs | app レベル統合(ACL loss redaction / audit rollback 等)検証追加 |
| packages/backend/scripts/knowledge-thread-promotion-old-app-compat.mjs | old-app read/write 互換検証を追加 |
| packages/backend/prisma/schema.prisma | promotion/grants/provenance FK を Prisma schema に追加 |
| packages/backend/prisma/migrations/20260810130000_add_knowledge_thread_promotion/migration.sql | expand-only migration(constraints/triggers/index/audit check)追加 |
| packages/backend/bounded-context-registry.cjs | Knowledge routes に ThreadPromotions を追加 |
| Makefile | knowledge-thread-promotion-postgres / knowledge-thread-promotion-old-app ターゲット追加 |
| docs/requirements/knowledge-hub.md | thread promote の要件追記 |
| docs/architecture/knowledge-hub-boundary.md | promotion 境界の設計追記 |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (1)
packages/backend/src/routes/knowledgeThreadPromotions.ts:258
- The preview response schema allows
destination.organizationGroupCountup to 100, but the request contract/validation capsorganizationGroupAccountIdsatknowledgeThreadPromotionLimits.organizationGroupAccountIds(20). Keeping the response schema aligned helps prevent contract drift and ensures OpenAPI reflects real bounds.
organizationGroupCount: {
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 33 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
packages/backend/test/knowledgeThreadPromotionUseCases.test.js:294
- The preview-usecase test exercises
includeSharedCard=true, but it doesn't assert the full shared-card shape required by the route mapper (knowledgeShareCardResponseexpectsomittedCategories). Adding a regression assertion here would have caught the missingomittedCategoriesfield that can otherwise surface as a runtime 500 when mapping the preview response.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (1)
packages/backend/src/routes/knowledgeThreadPromotions.ts:21
knowledgeShares.jsis imported twice; consolidating into a single import avoids duplicate-import patterns and keeps the import section easier to maintain.
import { knowledgeSharePublicCardSchema } from './knowledgeShares.js';
import { knowledgeShareCardResponse } from './knowledgeShares.js';
対象
Refs #2015
Parent: #2003 Workstream 07
Depends on merged PR #2050 / #2051
背景と目的
Knowledge share の Chat thread から、利用者が明示選択した direct reply だけを新規 KnowledgeSynthesis version 1 へ昇格する backend 境界を追加します。自動要約、thread 全文コピー、既存 synthesis への append は行いません。
実装概要
KnowledgeThreadPromotion、immutable selected-message snapshot、opaque request ledger、explicit synthesis group grant を expand-only migration で追加KnowledgeSynthesisSourceに typedsourceThreadPromotionIdFKを追加し、既存 exactly-one 制約を維持POST /chat-messages/{rootMessageId}/promote-to-knowledge/previewPOST /chat-messages/{rootMessageId}/promote-to-knowledgethread_promotionsourceを指定不可。promotion use caseだけがtyped sourceを作成設計上の判断
契約変更
Schema / migration
additive only:
KnowledgeThreadPromotionAuthorCategoryKnowledgeThreadPromotionKnowledgeThreadPromotionMessageKnowledgeThreadPromotionRequestKnowledgeSynthesisGroupGrantKnowledgeSynthesisSource.sourceThreadPromotionId既存table/columnのdrop・rename・destructive type changeはありません。
API
上記preview/commit endpointをadditiveに追加。OpenAPI breaking diffは0件です。
Env
新規env keyなし。既存
KNOWLEDGE_CURSOR_SIGNING_SECRETから用途分離keyを導出します。productionでは既存どおり32 UTF-8 bytes以上を必須とします。後方互換性
直前main
b720f575140e533c59070d33723146925faad489の旧backendを新migration適用DBへ接続し、実promotion row存在下でtimeline/thread/search/unread/notification/health/readiness/writeを検証しました。Chat rootはmessageType=textかつgeneric fallbackのため未知enum値はありません。Security / privacy
検証
make audit: backend/frontend 0 vulnerabilitiesmake ops-quality: PASSgit diff --check: PASSRELEASE_E2E_SCOPE=core make release-readiness: PASS(core E2E 107/107)未実施
リスク
Rollback
applicationを直前mainへ戻し、新endpoint/UIを無効化します。expand-only table/column、promotion snapshot、synthesis version、audit historyは保持し、migration down/dropやsource/message削除は行いません。ChatMessageTypeを変更していないため旧clientはgeneric text fallbackを継続表示できます。
Review remediation
exact-head review前の指摘を以下のとおり修正しました。
promotion_conflictへ正規化し、逐次・並行ともpromotion/synthesis/request ledgerが1件へ収束するPostgreSQL回帰testを追加Current exact head:
3f4b3cc5eeeaccfabf34c851201d9700e5a87426