Add configurable history and storage retention policies

This commit is contained in:
2026-10-05 22:48:04 -04:00
parent 7c98df4fb0
commit 3952c4c938
37 changed files with 963 additions and 82 deletions
+2 -1
View File
@@ -41,5 +41,6 @@ export async function GET({ params }: { params: { id: string } }) {
const events = db().prepare('SELECT id, created_at, message FROM campaign_events WHERE deployment_id = ? ORDER BY id').all(params.id);
const watchdog = db().prepare('SELECT incident_id FROM watchdog_actions WHERE campaign_id = ? LIMIT 1').get(params.id) as { incident_id: string } | undefined;
return json({ deployment: dep, servers, files, scripts, events, watchdogIncidentId: watchdog?.incident_id ?? null });
const fileContentsExpired = !!db().prepare("SELECT 1 FROM retention_expirations WHERE category='file-content' AND record_id=?").get(params.id);
return json({ fileContentsExpired, deployment: dep, servers, files, scripts, events, watchdogIncidentId: watchdog?.incident_id ?? null });
}
@@ -5,6 +5,9 @@ import { db } from '$lib/server/db/index.js';
// so the DiffViewer can render a unified diff without a second query.
export async function GET({ params }: { params: { id: string; fileId: string } }) {
if (db().prepare("SELECT 1 FROM retention_expirations WHERE category='file-content' AND record_id=?").get(params.id)) {
return json({ error: 'File contents expired under the retention policy.' }, { status: 410 });
}
const row = db()
.prepare(
`SELECT verb, rel_path, sha256_before, sha256_after, content_before, content_after
@@ -1,11 +1,10 @@
import { json } from '@sveltejs/kit';
import { getServer } from '$lib/server/fleet/servers.js';
import { listTelemetryRequests } from '$lib/server/fleet/telemetry-requests.js';
import { TELEMETRY_REQUEST_RETENTION } from '$lib/telemetry-diagnostics.js';
import { listTelemetryRequests, telemetryRetention } from '$lib/server/fleet/telemetry-requests.js';
export async function GET({ params }: { params: { name: string } }) {
if (!getServer(params.name)) return json({ ok: false, error: 'no such server' }, { status: 404 });
return json({ ok: true, requests: listTelemetryRequests(params.name), retention: TELEMETRY_REQUEST_RETENTION }, {
return json({ ok: true, requests: listTelemetryRequests(params.name), retention: telemetryRetention() }, {
headers: { 'Cache-Control': 'no-store' }
});
}
@@ -0,0 +1,11 @@
import { json } from '@sveltejs/kit';
import { retentionPreview, retentionControls, sampleRetentionPreview, setRetentionControl } from '$lib/server/retention.js';
import { gameFileRetentionPreview } from '$lib/server/game-files/index.js';
export function GET() {
return json({ policies: [...retentionPreview(),...sampleRetentionPreview(),...gameFileRetentionPreview()], controls: retentionControls() }, { headers: { 'Cache-Control': 'no-store' } });
}
export async function POST({ request }: { request: Request }) {
try { setRetentionControl(await request.json()); return json({ ok: true }); }
catch (error) { return json({ error: (error as Error).message }, { status: 400 }); }
}
@@ -0,0 +1,10 @@
import { json } from '@sveltejs/kit';
import { validateFleetSettings } from '$lib/fleet-settings.js';
import { retentionPreview,retentionControls,sampleRetentionPreview } from '$lib/server/retention.js';
import { gameFileRetentionPreview } from '$lib/server/game-files/index.js';
export async function POST({ request }: { request: Request }) {
try {
const settings = validateFleetSettings(await request.json());
return json({ policies:[...retentionPreview(settings),...sampleRetentionPreview(settings),...gameFileRetentionPreview(settings)],controls:retentionControls() },{ headers:{'Cache-Control':'no-store'} });
} catch (error) { return json({error:(error as Error).message},{status:400}); }
}