mirror of
https://github.com/iflytek/skillhub.git
synced 2026-09-05 08:05:56 +00:00
* feat(security): extend scanner config with full analyzer options
Integrate skill-scanner's 8 analysis engines and policy configuration
into SkillHub's config system. Operators can now control behavioral,
LLM, Meta, AI Defense, VirusTotal, and trigger analyzers via
application.yml or environment variables.
Changes:
- Add Analyzers and Policy nested classes to SkillScannerProperties
- Create ScanOptions record to encapsulate analyzer flags
- Update SkillScannerService to pass options in /scan body and /scan-upload query params
- Wire ScanOptions through SkillScannerConfig and SkillScannerAdapter
- Extend application.yml with full scanner config block and env var overrides
- Update all tests to verify new configuration flow
All tests pass.
* feat(security): add domain model and integrate scan into publish flow
Add SCANNING/SCAN_FAILED status to SkillVersionStatus. Introduce
SecurityScanService, SecurityScanner port, ScanTask, SecurityAudit
and related domain types. Wire scan trigger into SkillPublishService
so non-auto-publish versions enter scanning when scanner is enabled,
falling back to review task creation when disabled.
* feat(security): add infra layer for scanner HTTP client and adapters
Add WebClient-based HttpClient abstraction with WebClientHttpClient
implementation. Add SkillScannerApiResponse record, SecurityScanException,
and SecurityAuditJpaRepository. Add webflux and test dependencies to
infra module.
* feat(security): add Redis stream consumers, audit API, and DB migration
Add AbstractStreamConsumer base class, ScanTaskConsumer for processing
scan results from Redis stream, and RedisScanTaskProducer. Add
RedisStreamConfig for stream/group initialization. Add SecurityAudit
REST controller and DTO. Add V35 Flyway migration for security_audits
table.
* feat(security): add scanner config to application profiles
Add scanner enabled flag to application-local.yml and
application-test.yml. Enable behavioral analyzer by default
in application.yml.
* feat(deploy): add skill-scanner to docker-compose and k8s manifests
Add skill-scanner service to docker-compose.yml with health check.
Add scanner k8s deployment, service, and configmap entries. Wire
scanner env vars into Makefile dev-all flow. Add verify-scanner.sh
script for post-deploy validation.
* docs(security): add scanner documentation suite
Add scanner docs: configuration guide, failure impact analysis,
monitoring guide, improvement recommendations, custom rules guide,
and skill-vetter rules conversion example. Update deployment docs
with scanner section. Add security-scanning overview and PRD.
* feat(security): add skill-vetter custom rule examples
Add example Regex and YARA rules derived from skill-vetter RED FLAGS
in scanner/examples/vetter-rules/. Includes 7 Regex rules
(signatures-append.yaml) and 3 YARA rules (skillhub_vetter.yara)
covering agent memory theft, IP-based exfiltration, and browser
data theft detection.
* feat(security): add scanner Docker build context
Add Dockerfile for cisco-ai-skill-scanner container and
.env.example with LLM configuration placeholders.
* fix(security): align Finding mapping with scanner API response schema
SkillScannerApiResponse.Finding used incorrect field names (message,
location.file, location.line, code_snippet) that did not match the
scanner's actual JSON output (description, file_path, line_number,
snippet), causing all four fields to deserialize as null.
Flatten Finding to match scanner API: remove nested Location, rename
fields to description/file_path/line_number/snippet. Add skill_name
and timestamp to SkillScannerApiResponse. Extend SecurityFinding with
remediation, analyzer, and metadata fields to capture LLM analyzer
output. Retain 8-arg compact constructor for backward compatibility.
* chore(security): add debug logging to scanner response mapping
Log raw scanner API response and mapped SecurityFinding fields
side-by-side to help verify data consistency between scanner
output and database records.
* feat(security): add multi-scanner support and soft delete for security audits
- Add ScannerType enum for type-safe scanner identification
- Update V35 migration to support multiple scanners and soft delete
- Remove CASCADE delete, use code-level soft delete (deleted_at)
- Add repository methods for querying latest audit by scanner type
- Update SecurityScanService to handle scanner type parameter
- Integrate soft delete in SkillHardDeleteService
- Update all tests to use ScannerType enum
This enables multiple scanner integrations (skill-scanner, future LLM/compliance scanners)
and preserves complete audit history through soft deletion.
* feat(security): add security audit UI to review detail and skill detail pages
Display security scan results on the review detail page (full audit
section with collapsible findings) and the skill detail sidebar (compact
summary with dialog for details). Handles empty/404 gracefully by
returning null, avoids loading shimmer flicker, and separates lifecycle
action buttons with a visual divider.
* docs(security): add security audit UI PRD
* docs(prd): add related documents section to file browser sidebar PRD
* feat(skill): add file tree builder utility
Implement buildFileTree function to convert flat SkillFile[] into hierarchical tree structure.
- Nodes sorted alphabetically by path
- Support for nested directories
- Each node includes depth, type, and path information
- Includes comprehensive test coverage
* feat(skill): add file type detection utilities
Implement utilities for file type detection and preview capability checks:
- isPreviewable: checks if file can be previewed based on extension and size
- canPreviewFile: provides detailed reason when file cannot be previewed
- getFileTypeLabel: returns human-readable file type labels
- getFileIcon: maps file types to appropriate Lucide icons
- Supports 1MB max file size limit
- Comprehensive test coverage for all functions
* feat(skill): add file tree node component
Implement recursive FileTreeNodeComponent with:
- Expand/collapse functionality for directories
- File and directory icons from Lucide React
- Hover effects showing file sizes
- Proper indentation based on depth
- Support for nested directory structures
* refactor(skill): upgrade file tree to hierarchical structure
Replace flat file list with tree structure:
- Use buildFileTree to convert flat files into hierarchy
- Integrate FileTreeNodeComponent for rendering
- Update onFileClick to accept FileTreeNode instead of SkillFile
- Add file count badge in header
- Root-level directories expanded by default
* feat(skill): add file preview dialog component
Implement FilePreviewDialog with:
- Markdown rendering via existing MarkdownRenderer
- Plain text/code display with monospace font
- Non-previewable file message with download button
- Copy-to-clipboard and download actions in header
- File path display in footer
- Loading and error states
* feat(i18n): add file tree and preview translations
Add Chinese and English translations for:
- File browser title
- Preview error messages (load failure, too large, binary, unsupported)
- Download file button
* feat(skill): integrate file preview into skill detail page
- Add useSkillFile hook for fetching arbitrary file content
- Add file preview state, click handler, and download handler
- Pass onFileClick to FileTree for opening preview dialog
- Add FilePreviewDialog to skill detail page
* feat(review): add file reading API endpoint
Add GET /api/v1/reviews/{id}/file?path=... for reading single files
from the review-bound skill version:
- ReviewController: new endpoint with path traversal validation
- GovernanceWorkflowAppService: route method for review file access
- ReviewSkillDetailAppService: authorization and delegation
- SkillQueryService: getFileContentByVersionId for direct version access
* feat(review): integrate file preview into review detail
- Add useReviewFile hook for fetching review file content
- Add file preview state and handlers to ReviewSkillDetailSection
- Pass reviewId prop for API calls
- Add FilePreviewDialog to review detail expanded section
- Update review-detail.tsx to pass taskId as reviewId
* fix(test): update test mocks for file preview hooks
- Add useSkillFile mock to skill-detail.test.tsx
- Add useQuery mock to @tanstack/react-query mock
- Add useReviewFile mock to review-skill-detail-section.test.tsx
- Fix SkillFile test fixtures to include all required properties
- Remove unused imports in test and component files
* fix(skill): use DomainBadRequestException for version not found
Replace DomainNotFoundException with DomainBadRequestException in
getFileContentByVersionId to match existing patterns and imports.
* feat(skill): add file tree sidebar with file sizes
- Move file tree to right sidebar for persistent visibility
- Display file sizes always visible (not just on hover)
- Keep Files tab showing the same tree structure
- Add scrollable container with max-height for long file lists
* fix(skill): improve file tree sidebar UI and UX
- Remove redundant title from file tree sidebar
- Adjust scrollbar placement with proper flex layout
- Sort folders first, then files (both alphabetically)
- Collapse all folders by default for cleaner initial view
- Increase dialog width to max-w-5xl and height to 90vh
- Remove duplicate close button (X icon)
- Add hover effects to action buttons
- Use flexbox for proper content scrolling
- Allow .pyc files in backend configuration
Fixes:
1. File tree sidebar now has cleaner layout without title
2. Scrollbar properly contained within card
3. Folders appear before files in tree
4. All folders collapsed by default
5. Preview dialog wider and more usable
6. Single close method (ESC or click outside)
7. Action buttons have visual feedback on hover
* fix(skill): refine file tree sidebar and preview dialog
1. Default all folders to collapsed state
2. File tree sidebar now uses Card+bare pattern matching SecurityAuditSummary
- Scrollbar inside the card content area instead of wrapping the tree
- Consistent padding and header layout with other sidebar cards
3. Preview dialog close button fixed:
- Hide DialogContent's built-in close button via [&>button]:hidden
- Add X button in the header row, same level as copy/download
- All action buttons share consistent hover animation (opacity transition)
4. Sort directories before files at every tree level
5. Update tests for new directory-first sort order
* feat(skill): collapsible file browser, wider dialog, button animations
1. File browser sidebar now supports expand/collapse toggle
- Click the header row to toggle visibility
- ChevronUp/Down icon indicates state
- Default expanded on page load
2. File preview dialog widened to 72rem (was 5xl/64rem)
- Uses w-[min(calc(100vw-2rem),72rem)] for responsive max
3. Header action buttons now have micro-interactions:
- Copy/Download: scale up on hover, scale down on click
- Close (X): rotates 90° on hover with destructive tint
- All buttons: opacity 60→100 transition on hover
* feat(skill): chevron animation, button effects, download path hint, review sidebar
1. File browser chevron: single ChevronDown with rotate-180 CSS transition
instead of swapping two icons — smooth 200ms rotation animation
2. Preview dialog action button animations:
- Copy icon: active:scale-125 feedback on click
- Download icon: hover:translate-y-0.5 subtle downward motion
- Close icon: hover:rotate-90 with destructive tint (unchanged)
3. Download tooltip now shows full file path:
"下载 src/prompts/system.md" instead of generic "下载文件"
- New i18n keys: filePreview.downloadHint, filePreview.copy, filePreview.close
4. Review detail page now has a sidebar file browser:
- Two-column layout (main content + lg:w-80 sidebar)
- File tree sourced from reviewSkillDetail.files (active review version)
- Collapsible with same chevron animation as skill detail page
- Shows active version badge below file tree
- File preview uses review file API (/reviews/{id}/file?path=...)
- Test mocks updated for new useReviewFile dependency
* fix(skill): download shows filename, copy rotates with success toast
1. Download button tooltip/text now shows actual filename:
"下载 README.md" instead of generic path
- i18n key changed from {{path}} to {{name}}
2. Copy button animation reworked to rotation:
- idle: hover:rotate-180 on the Copy icon
- click: animate-spin during clipboard write
- done: swap to green Check icon for 1.5s, then reset
3. Copy success toast notification:
- Shows "已复制到剪贴板" / "Copied to clipboard" via toast.success
- New i18n key: filePreview.copySuccess
* fix(skill): set download attribute so browser saves with original filename
The <a> element was missing the download attribute, causing the browser
to derive the filename from the URL path segment (/file?path=...) which
always resolved to "file". Now explicitly sets link.download = node.name
so the saved file uses the original name (e.g. README.md, config.json).
Applied to all three download handlers:
- skill-detail.tsx (skill version file)
- review-detail.tsx (review sidebar file)
- review-skill-detail-section.tsx (review expanded section file)
* feat(skill): add icons to all sidebar card headers
Add Lucide icons to each sidebar section for visual consistency
with the existing SecurityAuditSummary (Shield) and file browser (Folder):
- Terminal: Install command
- Clock: Pending review (amber-colored to match card theme)
- RefreshCw: Lifecycle management
- Tag: Label management (in SkillLabelPanel component)
- ArrowUpCircle: Promotion
- ShieldCheck: Governance
All icons use the same pattern: w-4 h-4 text-muted-foreground
placed inside a flex row with gap-2 before the section title.
* fix(skill): allow owners to preview all version statuses
When a skill has only a REJECTED version, the detail page crashed with
400 "版本未发布" because assertPreviewAccessible() only allowed PUBLISHED
and PENDING_REVIEW(owner). The frontend fallback to versions[0] would
pick the REJECTED version and fail all file/readme queries.
Backend changes:
- assertPreviewAccessible(): now allows owners and namespace admins to
preview ANY version status (DRAFT, REJECTED, YANKED, SCANNING, etc.)
via canManageRestrictedSkill() check. Also passes userNsRoles so
namespace admin role is respected, not just owner.
- resolveOwnerPendingPreview(): expanded from PENDING_REVIEW-only to
include all non-published, non-yanked statuses so headlineVersion
resolves correctly for owners with REJECTED/DRAFT/SCANNING versions.
Frontend changes:
- isOwnerPreviewResolution(): relaxed from checking PENDING_REVIEW
specifically to checking any non-PUBLISHED status, matching the
backend's broader projection.
Fixes: owner viewing skill with only REJECTED version → 400 error
Also fixes: DRAFT-only, SCANNING-only, SCAN_FAILED-only scenarios
* docs(requirements): add comprehensive requirements for file preview syntax highlighting
Generated complete documentation suite including:
- Core PRD (clarity score: 95/100)
- Constraints specification (8 business rules)
- Impact analysis (8 risks identified)
- Acceptance cases (25 test cases: 10 positive, 5 error, 7 boundary, 3 security)
- Test plan (100% coverage)
Mode: Quick (3 clarification rounds)
Complexity: Simple (3.5 days estimated)
* feat(skill): add syntax highlighting for code file preview
Implement syntax highlighting for code files in the file preview dialog:
- Add CodeRenderer component using lowlight (highlight.js wrapper via rehype-highlight)
- Add getLanguageForHighlight() to map file extensions to highlight.js languages
- Support 20+ languages: Python, JS/TS, Java, Go, Rust, C/C++, Ruby, PHP, Shell, JSON, YAML, XML, etc.
- Apply 500KB threshold for syntax highlighting (larger files show plain text)
- Maintain visual consistency with Markdown code blocks
- Auto-adapt to light/dark theme using existing CSS variables
- Add lowlight as direct dependency to enable programmatic syntax highlighting
Implements solution 1 from PRD (reuse rehype-highlight infrastructure).
* fix(security): resolve security audit FK constraint and stale query issues
Backend:
- Add hardDeleteByVersionId to physically remove audit records before
deleting skill versions (fixes FK constraint violation on hard delete)
- Add softDeleteByVersionId calls in SkillGovernanceService and
SkillPublishService version deletion paths
- Add V36 migration to convert security_audit TIMESTAMP columns to
TIMESTAMPTZ matching project convention
- Update tests to verify audit cleanup in all deletion flows
Frontend:
- Prevent stale API calls after skill deletion by gating all query
hooks with a skillDeleted flag that disables them immediately
- Move cache cleanup from useDeleteSkill onSuccess to the handler
to avoid refetching while the component is still mounted
* fix(skill): handle SCANNING and SCAN_FAILED statuses across all pages
Backend:
- Include SCANNING/SCAN_FAILED in version listing filters so owners
can see versions being scanned
- Add explicit lifecycle sort priority for scanner statuses
- Allow deletion of SCAN_FAILED versions alongside DRAFT and REJECTED
Frontend:
- Add i18n labels and CSS classes for SCANNING/SCAN_FAILED in my-skills
- Add localized version status labels in skill-detail version list
- Hide archive button when no published version exists (my-skills and
skill-detail)
- Allow deleting SCAN_FAILED versions from skill-detail
* gitignore
6.2 KiB
6.2 KiB
| name | description | type |
|---|---|---|
| 文件预览语法高亮影响分析 | 代码影响范围、API 变更、数据库变更、风险评估 | impact-analysis |
影响分析:文件预览语法高亮
1. 代码影响矩阵
| 模块 | 文件/类 | 变更类型 | 影响级别 | 备注 |
|---|---|---|---|---|
| 前端 - 组件 | web/src/features/skill/code-renderer.tsx |
新增 | 低 | 新增组件,无依赖冲突 |
| 前端 - 工具 | web/src/features/skill/file-type-utils.ts |
修改 | 低 | 新增函数,不修改现有函数 |
| 前端 - 弹窗 | web/src/features/skill/file-preview-dialog.tsx |
修改 | 中 | 修改渲染逻辑,需回归测试 |
| 前端 - 样式 | web/src/features/skill/markdown-renderer.tsx |
只读 | 无 | 复用样式,不修改 |
| 前端 - 依赖 | web/package.json |
无变更 | 无 | 复用现有 highlight.js |
| 后端 - API | 无 | 无变更 | 无 | 复用现有文件读取 API |
| 后端 - 缓存 | 待定 | 后续新增 | 低 | 后续优化阶段实现 |
| 后端 - 限流 | 待定 | 后续新增 | 低 | 后续优化阶段实现 |
2. API 影响
新增端点
无
修改端点
无(复用现有 API)
现有端点依赖
| 端点 | 变更 | 是否破坏性 | 备注 |
|---|---|---|---|
GET /api/v1/reviews/{id}/file?path={filePath} |
无变更 | 否 | 前端根据响应内容渲染 |
GET /api/v1/skills/{namespace}/{slug}/versions/{version}/file?path={filePath} |
无变更 | 否 | 前端根据响应内容渲染 |
3. 数据库影响
模式变更
无
数据迁移
无
4. 前端影响
受影响页面
| 页面 | 影响描述 | 测试重点 |
|---|---|---|
| 技能详情页 | 文件预览弹窗增强 | 各种文件类型渲染测试 |
| 审核详情页 | 文件预览弹窗增强 | 各种文件类型渲染测试 |
i18n 变更
无新增翻译键(复用现有错误提示)
路由变更
无
5. 风险评估
| 风险 ID | 描述 | 概率 | 影响 | 缓解措施 |
|---|---|---|---|---|
| R-001 | 大文件语法高亮导致浏览器卡顿 | 中 | 高 | 设置 500KB 阈值,超过则不高亮 |
| R-002 | highlight.js 包体积过大 | 低 | 中 | 按需导入语言包,初始只加载核心 |
| R-003 | 语法高亮样式与 Markdown 不一致 | 低 | 中 | 复用相同的 CSS 类名和样式 |
| R-004 | 某些语言无法识别 | 低 | 低 | 降级到纯文本显示,不报错 |
| R-005 | 渲染失败导致页面崩溃 | 低 | 高 | 使用 Error Boundary 捕获错误 |
| R-006 | 主题切换时样式闪烁 | 低 | 低 | 使用 CSS 变量,确保平滑过渡 |
| R-007 | 后端文件读取性能下降 | 中 | 中 | 后续实现缓存和限流(不在本次范围) |
| R-008 | XSS 安全风险 | 低 | 高 | 确保 highlight.js 输出已转义 |
风险详细说明
R-001: 大文件语法高亮导致浏览器卡顿
- 触发条件:用户尝试预览 > 500KB 的代码文件
- 影响范围:前端渲染性能,用户体验
- 缓解措施:
- 设置 500KB 阈值,超过则显示纯文本
- 增加 loading 状态提示用户
- 提供"取消加载"按钮(后续优化)
- 监控指标:前端渲染时间(通过 RUM)
R-005: 渲染失败导致页面崩溃
- 触发条件:highlight.js 渲染异常、内存不足
- 影响范围:文件预览功能不可用
- 缓解措施:
- 使用 React Error Boundary 捕获渲染错误
- 降级到纯文本显示
- 记录错误日志,便于排查
- 监控指标:错误率(通过前端错误监控)
R-007: 后端文件读取性能下降
- 触发条件:大量用户同时预览文件
- 影响范围:后端 API 响应时间增加,云存储 API 配额消耗
- 缓解措施:
- 后续实现 Redis 缓存(缓存命中率 > 60%)
- 后续实现限流(认证用户 60 次/分钟,匿名 20 次/分钟)
- 监控云存储 API 调用次数
- 监控指标:API 响应时间、缓存命中率、限流触发次数
R-008: XSS 安全风险
- 触发条件:恶意用户上传包含 XSS 代码的文件
- 影响范围:安全漏洞,可能导致用户信息泄露
- 缓解措施:
- 确保 highlight.js 输出已转义(highlight.js 默认转义)
- 代码审查确认
dangerouslySetInnerHTML使用安全 - 不允许用户自定义语法高亮规则
- 监控指标:安全审查通过
6. 测试影响
新增测试
| 测试类 | 覆盖用例 | 描述 |
|---|---|---|
CodeRenderer.test.tsx |
AC-P-001 ~ AC-P-005 | CodeRenderer 组件单元测试 |
file-type-utils.test.ts |
AC-P-006 | 语言映射函数测试 |
file-preview-dialog.test.tsx |
AC-P-007 ~ AC-P-010 | 文件预览弹窗集成测试 |
修改测试
| 测试类 | 修改原因 | 描述 |
|---|---|---|
file-preview-dialog.test.tsx |
新增渲染逻辑 | 更新快照,增加语法高亮测试用例 |
7. 部署影响
前端部署
- 构建时间:预计增加 10-20 秒(新增组件编译)
- 包体积:预计增加 50-80KB(gzipped,按需导入语言包)
- 缓存失效:文件预览相关页面缓存失效,需重新加载
后端部署
- 本次无变更
- 后续优化:需要部署缓存和限流逻辑(独立任务)
数据库部署
无
8. 回滚计划
回滚触发条件
- 前端渲染错误率 > 5%
- 用户投诉语法高亮功能异常 > 10 次/天
- 性能指标严重下降(P95 响应时间 > 3s)
回滚步骤
- 前端回滚:
- 回滚到上一个稳定版本(git revert)
- 重新构建和部署前端
- 验证文件预览功能恢复正常(显示纯文本)
- 监控验证:
- 确认错误率恢复正常
- 确认性能指标恢复正常
- 问题排查:
- 分析错误日志,定位问题根因
- 修复问题后重新部署
回滚影响
- 用户将无法使用语法高亮功能,回退到纯文本显示
- 不影响文件下载和其他核心功能
变更日志
| 日期 | 章节 | 变更 | 原因 | 触发者 |
|---|---|---|---|---|
| 2026-03-22 | 初始版本 | 创建影响分析文档 | 需求澄清完成 | requirements-clarity |