fix(operation-trace): correct capture scope, broaden coverage, polish panel

- Capture scope: treat the ``audit`` bucket (viewing the log / tracing
  settings) as a read-level observation instead of recording it from the
  mutation level. At "mutations only" the log no longer fills with GET page
  views; views are recorded only at the read level.
- Coverage: classify plugin lifecycle (install / upgrade / config / page),
  skills, knowledge bases and MCP servers, with dedicated actions and
  resource types, so those operations are traced instead of falling into the
  generic resource bucket. Route rules now support multi-fragment AND
  matching and per-verb read/write actions.
- Panel: move "Download logs" next to "Refresh" in the toolbar.
- Verification: count hash mismatches and broken links separately instead of
  collapsing both into one "tampered" signal.
- i18n: add the new action labels plus the split verification labels in all
  eight locales.
This commit is contained in:
TyperBody
2026-09-26 02:26:48 +08:00
parent 78baabde96
commit 48d92ad612
11 changed files with 261 additions and 51 deletions
@@ -323,6 +323,19 @@ export default function OperationTracePanel({
)}
{t('operationTrace.refresh')}
</Button>
<Button
size="sm"
variant="outline"
onClick={() => void downloadLogs()}
disabled={exporting}
>
{exporting ? (
<Loader2 className="size-3.5 animate-spin" />
) : (
<Download className="size-3.5" />
)}
{t('operationTrace.export')}
</Button>
</PanelToolbar>
<PanelBody className="space-y-6">
@@ -429,13 +442,22 @@ export default function OperationTracePanel({
{t('operationTrace.records')}
</h3>
<Badge variant="secondary">{total}</Badge>
{(page?.tampered_count ?? 0) > 0 && (
<Badge variant="destructive">
{t('operationTrace.tamperedCount', {
count: page?.tampered_count ?? 0,
})}
</Badge>
)}
{(page?.tampered_count ?? 0) > 0 &&
(page?.integrity_failed_count ?? 0) > 0 && (
<Badge variant="destructive">
{t('operationTrace.integrityFailedCount', {
count: page?.integrity_failed_count ?? 0,
})}
</Badge>
)}
{(page?.tampered_count ?? 0) > 0 &&
(page?.chain_failed_count ?? 0) > 0 && (
<Badge variant="destructive">
{t('operationTrace.chainFailedCount', {
count: page?.chain_failed_count ?? 0,
})}
</Badge>
)}
</div>
<div className="ml-auto flex flex-wrap items-center gap-2">
<Select
@@ -490,19 +512,6 @@ export default function OperationTracePanel({
))}
</SelectContent>
</Select>
<Button
size="sm"
variant="outline"
onClick={() => void downloadLogs()}
disabled={exporting}
>
{exporting ? (
<Loader2 className="size-3.5 animate-spin" />
) : (
<Download className="size-3.5" />
)}
{t('operationTrace.export')}
</Button>
<Select
value={query.actor ?? ALL_VALUE}
onValueChange={(value) =>
@@ -76,6 +76,10 @@ export interface OperationLogPage {
offset: number;
/** How many records on this page failed hash or chain verification. */
tampered_count: number;
/** Records whose stored hash no longer matches their content. */
integrity_failed_count: number;
/** Records whose predecessor link is broken. */
chain_failed_count: number;
}
export interface OperationLogFilters {
+13
View File
@@ -2753,6 +2753,8 @@ const enUS = {
tamperedBadge: 'Possibly tampered',
verifiedBadge: 'Verified',
tamperedCount: '{{count}} records failed verification',
integrityFailedCount: '{{count}} hash mismatches',
chainFailedCount: '{{count}} broken links',
levels: {
off: {
label: 'Tracing off',
@@ -2783,6 +2785,17 @@ const enUS = {
member_role_update: 'Update member role',
member_remove: 'Remove member',
member_view: 'View members',
plugin_view: 'View extension pages',
plugin_config: 'Change extension config',
plugin_install: 'Install extension',
plugin_upgrade: 'Upgrade extension',
page_view: 'View extension page',
skill_view: 'View skill',
skill_install: 'Install skill',
knowledge_base_view: 'View knowledge base',
knowledge_base_update: 'Change knowledge base',
mcp_view: 'View MCP server',
mcp_config: 'Change MCP server',
export: 'Export data',
execute: 'Execute task',
debug: 'Debug task',
+13
View File
@@ -2808,6 +2808,8 @@ const esES = {
tamperedBadge: 'Posible manipulación',
verifiedBadge: 'Verificado',
tamperedCount: '{{count}} registros fallaron la verificación',
integrityFailedCount: '{{count}} hashes no coinciden',
chainFailedCount: '{{count}} enlaces rotos',
levels: {
off: {
label: 'Sin trazabilidad',
@@ -2838,6 +2840,17 @@ const esES = {
member_role_update: 'Actualizar rol del miembro',
member_remove: 'Eliminar miembro',
member_view: 'Ver miembros',
plugin_view: 'Ver páginas de extensión',
plugin_config: 'Cambiar configuración de extensión',
plugin_install: 'Instalar extensión',
plugin_upgrade: 'Actualizar extensión',
page_view: 'Ver página de extensión',
skill_view: 'Ver habilidad',
skill_install: 'Instalar habilidad',
knowledge_base_view: 'Ver base de conocimiento',
knowledge_base_update: 'Cambiar base de conocimiento',
mcp_view: 'Ver servidor MCP',
mcp_config: 'Cambiar servidor MCP',
export: 'Exportar datos',
execute: 'Ejecutar tarea',
debug: 'Depurar tarea',
+13
View File
@@ -2771,6 +2771,8 @@ const jaJP = {
tamperedBadge: '改ざんの可能性',
verifiedBadge: '検証済み',
tamperedCount: '{{count}} 件が検証に失敗',
integrityFailedCount: '{{count}} 件のハッシュ不一致',
chainFailedCount: '{{count}} 件のリンク断絶',
levels: {
off: {
label: 'トレース無効',
@@ -2801,6 +2803,17 @@ const jaJP = {
member_role_update: 'メンバーのロールを変更',
member_remove: 'メンバーを削除',
member_view: 'メンバーを閲覧',
plugin_view: '拡張ページを閲覧',
plugin_config: '拡張設定を変更',
plugin_install: '拡張をインストール',
plugin_upgrade: '拡張をアップグレード',
page_view: '拡張ページを閲覧',
skill_view: 'スキルを閲覧',
skill_install: 'スキルをインストール',
knowledge_base_view: 'ナレッジベースを閲覧',
knowledge_base_update: 'ナレッジベースを変更',
mcp_view: 'MCP サーバーを閲覧',
mcp_config: 'MCP サーバーを変更',
export: 'データをエクスポート',
execute: 'タスクを実行',
debug: 'タスクをデバッグ',
+13
View File
@@ -2778,6 +2778,8 @@ const ruRU = {
tamperedBadge: 'Возможна подмена',
verifiedBadge: 'Проверено',
tamperedCount: 'Записей с ошибкой проверки: {{count}}',
integrityFailedCount: 'Несовпадение хэша: {{count}}',
chainFailedCount: 'Разрыв связи: {{count}}',
levels: {
off: {
label: 'Трассировка выключена',
@@ -2808,6 +2810,17 @@ const ruRU = {
member_role_update: 'Изменение роли участника',
member_remove: 'Удаление участника',
member_view: 'Просмотр участников',
plugin_view: 'Просмотр страниц расширения',
plugin_config: 'Изменение настроек расширения',
plugin_install: 'Установка расширения',
plugin_upgrade: 'Обновление расширения',
page_view: 'Просмотр страницы расширения',
skill_view: 'Просмотр навыка',
skill_install: 'Установка навыка',
knowledge_base_view: 'Просмотр базы знаний',
knowledge_base_update: 'Изменение базы знаний',
mcp_view: 'Просмотр сервера MCP',
mcp_config: 'Изменение сервера MCP',
export: 'Экспорт данных',
execute: 'Выполнение задачи',
debug: 'Отладка задачи',
+13
View File
@@ -2705,6 +2705,8 @@ const thTH = {
tamperedBadge: 'อาจถูกแก้ไข',
verifiedBadge: 'ตรวจสอบผ่าน',
tamperedCount: 'มี {{count}} บันทึกที่ตรวจสอบไม่ผ่าน',
integrityFailedCount: 'แฮชไม่ตรงกัน {{count}} รายการ',
chainFailedCount: 'ลิงก์ขาด {{count}} รายการ',
levels: {
off: {
label: 'ปิดการติดตาม',
@@ -2735,6 +2737,17 @@ const thTH = {
member_role_update: 'แก้ไขบทบาทสมาชิก',
member_remove: 'ลบสมาชิก',
member_view: 'ดูสมาชิก',
plugin_view: 'ดูหน้าส่วนขยาย',
plugin_config: 'แก้ไขการตั้งค่าส่วนขยาย',
plugin_install: 'ติดตั้งส่วนขยาย',
plugin_upgrade: 'อัปเกรดส่วนขยาย',
page_view: 'ดูหน้าส่วนขยาย',
skill_view: 'ดูทักษะ',
skill_install: 'ติดตั้งทักษะ',
knowledge_base_view: 'ดูฐานความรู้',
knowledge_base_update: 'แก้ไขฐานความรู้',
mcp_view: 'ดูเซิร์ฟเวอร์ MCP',
mcp_config: 'แก้ไขเซิร์ฟเวอร์ MCP',
export: 'ส่งออกข้อมูล',
execute: 'รันงาน',
debug: 'ดีบักงาน',
+13
View File
@@ -2740,6 +2740,8 @@ const viVN = {
tamperedBadge: 'Có thể bị sửa',
verifiedBadge: 'Đã xác minh',
tamperedCount: '{{count}} bản ghi không vượt qua kiểm tra',
integrityFailedCount: '{{count}} mã băm không khớp',
chainFailedCount: '{{count}} liên kết bị đứt',
levels: {
off: {
label: 'Tắt truy vết',
@@ -2770,6 +2772,17 @@ const viVN = {
member_role_update: 'Cập nhật vai trò thành viên',
member_remove: 'Xóa thành viên',
member_view: 'Xem thành viên',
plugin_view: 'Xem trang tiện ích',
plugin_config: 'Thay đổi cấu hình tiện ích',
plugin_install: 'Cài đặt tiện ích',
plugin_upgrade: 'Nâng cấp tiện ích',
page_view: 'Xem trang tiện ích',
skill_view: 'Xem kỹ năng',
skill_install: 'Cài đặt kỹ năng',
knowledge_base_view: 'Xem cơ sở tri thức',
knowledge_base_update: 'Thay đổi cơ sở tri thức',
mcp_view: 'Xem máy chủ MCP',
mcp_config: 'Thay đổi máy chủ MCP',
export: 'Xuất dữ liệu',
execute: 'Chạy tác vụ',
debug: 'Gỡ lỗi tác vụ',
+13
View File
@@ -2602,6 +2602,8 @@ const zhHans = {
tamperedBadge: '可能被篡改',
verifiedBadge: '校验通过',
tamperedCount: '{{count}} 条记录校验异常',
integrityFailedCount: '{{count}} 条哈希不匹配',
chainFailedCount: '{{count}} 条链路断裂',
levels: {
off: {
label: '关闭溯源',
@@ -2632,6 +2634,17 @@ const zhHans = {
member_role_update: '修改成员角色',
member_remove: '移除成员',
member_view: '查看成员',
plugin_view: '查看扩展页面',
plugin_config: '修改扩展配置',
plugin_install: '安装扩展',
plugin_upgrade: '升级扩展',
page_view: '查看扩展页面',
skill_view: '查看技能',
skill_install: '安装技能',
knowledge_base_view: '查看知识库',
knowledge_base_update: '修改知识库',
mcp_view: '查看 MCP 服务器',
mcp_config: '修改 MCP 服务器',
export: '导出数据',
execute: '执行任务',
debug: '调试任务',
+13
View File
@@ -2603,6 +2603,8 @@ const zhHant = {
tamperedBadge: '可能被竄改',
verifiedBadge: '驗證通過',
tamperedCount: '{{count}} 筆記錄驗證異常',
integrityFailedCount: '{{count}} 筆雜湊不符',
chainFailedCount: '{{count}} 筆鏈結中斷',
levels: {
off: {
label: '關閉溯源',
@@ -2633,6 +2635,17 @@ const zhHant = {
member_role_update: '修改成員角色',
member_remove: '移除成員',
member_view: '查看成員',
plugin_view: '查看擴充頁面',
plugin_config: '修改擴充設定',
plugin_install: '安裝擴充',
plugin_upgrade: '升級擴充',
page_view: '查看擴充頁面',
skill_view: '查看技能',
skill_install: '安裝技能',
knowledge_base_view: '查看知識庫',
knowledge_base_update: '修改知識庫',
mcp_view: '查看 MCP 伺服器',
mcp_config: '修改 MCP 伺服器',
export: '匯出資料',
execute: '執行任務',
debug: '偵錯任務',