Preserve deleted server history

Retain historical server identities, results, and evidence after deletion. Mark archived entries as Deleted and prevent old work from targeting servers that reuse the same name.

Fixes #16.
This commit is contained in:
2026-09-27 21:48:55 -04:00
parent 53b29f726c
commit 981fb27c1c
61 changed files with 929 additions and 223 deletions
+2 -2
View File
@@ -33,7 +33,7 @@ export async function GET({ params }: { params: { id: string } }) {
const events = db().prepare('SELECT id, created_at, message FROM beta_events WHERE beta_id = ? ORDER BY id').all(id);
const campaign = db().prepare("SELECT id FROM deployments WHERE beta_id = ? AND action = 'promote' ORDER BY started_at DESC LIMIT 1").get(id) as { id: string } | undefined;
const promotion = campaign ? { ...campaign,
pending: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state NOT IN ('done','failed','cancelled')").get(campaign.id) as { n: number }).n,
failed: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state = 'failed'").get(campaign.id) as { n: number }).n } : null;
pending: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND server_deleted_at IS NULL AND restart_state NOT IN ('done','failed','cancelled')").get(campaign.id) as { n: number }).n,
failed: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND server_deleted_at IS NULL AND restart_state = 'failed'").get(campaign.id) as { n: number }).n } : null;
return json({ beta, scripts, servers, events, test: testView(id), promotion });
}
+3 -2
View File
@@ -19,11 +19,12 @@ export async function POST({ params, request }: { params: { id: string }; reques
if (!body.server) return json({ ok: false, error: 'server is required' }, { status: 400 });
const row = db()
.prepare('SELECT stage, restarted_at, healthy_at FROM beta_servers WHERE beta_id = ? AND server = ?')
.prepare('SELECT stage, restarted_at, healthy_at, server_deleted_at FROM beta_servers WHERE beta_id = ? AND server = ?')
.get(betaId, body.server) as
| { stage: string; restarted_at: string | null; healthy_at: string | null }
| { stage: string; restarted_at: string | null; healthy_at: string | null; server_deleted_at: string | null }
| undefined;
if (!row) return json({ ok: false, error: 'no such beta_server' }, { status: 404 });
if (row.server_deleted_at) return json({ ok: false, error: 'This beta server was deleted; open a new beta for its replacement.' }, { status: 409 });
if (row.stage !== 'failed') return json({ ok: false, error: `stage is ${row.stage}, not failed` }, { status: 409 });
// Best-effort resume point: if we already got past restart, go back to
@@ -17,6 +17,9 @@ export async function POST({ params, request }: { params: { id: string }; reques
if (!['running', 'ready-promote'].includes(beta.state)) return json({ error: 'Beta is closed' }, { status: 409 });
try {
const body = await request.json();
if (db().prepare('SELECT 1 FROM beta_servers WHERE beta_id = ? AND server_deleted_at IS NOT NULL').get(id)) {
return json({ ok: false, error: 'A beta server was deleted. Roll back this beta and open a new one to collect fresh evidence.' }, { status: 409 });
}
const plan = parseBetaPlan(JSON.parse(stored.plan));
if (body.action === 'sign-off') {
if (!['active', 'passed'].includes(stored.outcome)) throw new Error('Resume or retry the test before signing off');