chore: 保存 Agent 安全优化前基线

This commit is contained in:
Logan.Li committed 2026-09-02 23:31:38 +08:00
1 parent 08696896f9
commit ff016347cd
116 files changed
+3858 -2485

No files matched your search

+8
View File
@@ -31,6 +31,14 @@ describe('Agent command guardrail', () => {
expect(agentCommandNeedsConfirmation('critical', 'strict')).toBe(false)
})
it('confirm-all still auto-runs only the read-only whitelist', () => {
expect(agentCommandNeedsConfirmation('safe', 'relaxed', true)).toBe(false)
expect(agentCommandNeedsConfirmation('low', 'relaxed', true)).toBe(true)
expect(agentCommandNeedsConfirmation('medium', 'strict', true)).toBe(true)
expect(agentCommandNeedsConfirmation('high', 'relaxed', true)).toBe(true)
expect(agentCommandNeedsConfirmation('critical', 'relaxed', true)).toBe(false)
})
it('fingerprints similar temp-path commands for session Always', () => {
expect(agentCommandAllowFingerprint('rm /tmp/tmp.3RUZRHTwk2', 'high')).toBe(
agentCommandAllowFingerprint('rm /tmp/tmp.ABCDEFG123', 'high')
+58
View File
@@ -0,0 +1,58 @@
import { describe, expect, it } from 'vitest'
import { compareBySortOrder, groupSessionsInDisplayOrder } from '../../src/utils/sessionGroups'
import type { Session } from '../../src/stores/sessionStore'
function session(id: string, sortOrder?: number, group?: string): Session {
return {
id,
name: id,
host: `${id}.example.com`,
port: 22,
username: 'root',
authType: 'key',
...(sortOrder !== undefined ? { sortOrder } : {}),
...(group !== undefined ? { group } : {}),
}
}
describe('compareBySortOrder', () => {
it('sorts explicit sortOrder ascending', () => {
const rows = [{ sortOrder: 2 }, { sortOrder: 0 }, { sortOrder: 1 }]
expect([...rows].sort(compareBySortOrder).map((r) => r.sortOrder)).toEqual([0, 1, 2])
})
it('keeps rows without sortOrder after ordered rows', () => {
const rows = [{ sortOrder: undefined }, { sortOrder: 0 }, {}, { sortOrder: 1 }]
const sorted = [...rows].sort(compareBySortOrder)
expect(sorted.map((r) => r.sortOrder ?? null)).toEqual([0, 1, null, null])
})
})
describe('groupSessionsInDisplayOrder', () => {
it('filters one group and orders by manual order with legacy rows last', () => {
const sessions = [
session('legacy-a'),
session('ordered-b', 1, 'prod'),
session('ordered-a', 0, 'prod'),
session('legacy-b'),
session('other', 0, 'staging'),
]
expect(groupSessionsInDisplayOrder(sessions, 'prod').map((s) => s.id)).toEqual(['ordered-a', 'ordered-b'])
expect(groupSessionsInDisplayOrder(sessions, 'default').map((s) => s.id)).toEqual(['legacy-a', 'legacy-b'])
})
it('preserves storage order among legacy rows (stable sort)', () => {
const sessions = [session('first'), session('second'), session('third')]
expect(groupSessionsInDisplayOrder(sessions, 'default').map((s) => s.id)).toEqual(['first', 'second', 'third'])
})
it('rewriting 0..n-1 makes the manual order authoritative', () => {
const sessions = [session('a'), session('b'), session('c')]
const reordered = ['c', 'a', 'b']
const rewritten = reordered.map((id, index) => ({
...sessions.find((s) => s.id === id)!,
sortOrder: index,
}))
expect(rewritten.sort(compareBySortOrder).map((s) => s.id)).toEqual(['c', 'a', 'b'])
})
})
+31
View File
@@ -0,0 +1,31 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { flushShellBootstrap } from '../../src/utils/shellIO'
describe('flushShellBootstrap', () => {
beforeEach(() => {
vi.mocked(window.opsxApi.localOpenOutput).mockClear()
vi.mocked(window.opsxApi.sshShellOpenOutput).mockClear()
vi.mocked(window.opsxApi.localOpenOutput).mockResolvedValue({
success: true,
data: [98, 97, 115, 104],
})
vi.mocked(window.opsxApi.sshShellOpenOutput).mockResolvedValue({
success: true,
data: [109, 111, 116, 100],
})
})
it('opens buffered local PTY output for local-* ids', async () => {
const boot = await flushShellBootstrap('local-abc')
expect(window.opsxApi.localOpenOutput).toHaveBeenCalledWith('local-abc')
expect(window.opsxApi.sshShellOpenOutput).not.toHaveBeenCalled()
expect(boot).toEqual(new Uint8Array([98, 97, 115, 104]))
})
it('opens buffered SSH output for remote shell ids', async () => {
const boot = await flushShellBootstrap('shell-abc')
expect(window.opsxApi.sshShellOpenOutput).toHaveBeenCalledWith('shell-abc')
expect(window.opsxApi.localOpenOutput).not.toHaveBeenCalled()
expect(boot).toEqual(new Uint8Array([109, 111, 116, 100]))
})
})