feat: audit log / history timeline on instance detail page
Adds an instance_history table that records every field change: - createInstance logs a 'created' event - updateInstance diffs old vs new and logs one row per changed field (name, state, stack, vmid, tailscale_ip, all service flags) - History is stored under the new vmid when vmid changes New endpoint: GET /api/instances/:vmid/history The 'timestamps' section on the detail page is replaced with a grid timeline showing timestamp | field | old → new for each event. State changes are colour-coded (deployed=green, testing=amber, degraded=red). Boolean service flags display as on/off. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -239,6 +239,26 @@ describe('DELETE /api/instances/:vmid', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ── GET /api/instances/:vmid/history ─────────────────────────────────────────
|
||||
|
||||
describe('GET /api/instances/:vmid/history', () => {
|
||||
it('returns history events for a known vmid', async () => {
|
||||
await request(app).post('/api/instances').send(base)
|
||||
const res = await request(app).get('/api/instances/100/history')
|
||||
expect(res.status).toBe(200)
|
||||
expect(res.body).toBeInstanceOf(Array)
|
||||
expect(res.body[0].field).toBe('created')
|
||||
})
|
||||
|
||||
it('returns 404 for unknown vmid', async () => {
|
||||
expect((await request(app).get('/api/instances/999/history')).status).toBe(404)
|
||||
})
|
||||
|
||||
it('returns 400 for non-numeric vmid', async () => {
|
||||
expect((await request(app).get('/api/instances/abc/history')).status).toBe(400)
|
||||
})
|
||||
})
|
||||
|
||||
// ── GET /api/export ───────────────────────────────────────────────────────────
|
||||
|
||||
describe('GET /api/export', () => {
|
||||
|
||||
Reference in New Issue
Block a user