mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 18:57:09 +00:00
fix(drift): reconcile the drift ledger on deploy and timestamp its history (#1405)
* fix(drift): reconcile the drift ledger on deploy and timestamp its history
The drift ledger (persisted history + activity timeline) only advanced
when someone clicked re-check on a stack's Drift tab, so the history could
sit indefinitely out of sync with the live status: a stack reading
"drifted" live while its history still said "resolved". Two corrections:
- Deploy and update reconcile the ledger against the just-deployed runtime
(the rollback route re-deploys through deployStack, so it is covered),
resolving what the change fixed and recording what it left.
- Every authoritative reconcile stamps the dossier last-checked time, and
the Drift tab labels its history "checked {time}" so a stale finding
reads as history, not a claim about the live status above it.
Adds the last_drift_check_at column and tests across the ledger reconcile
stamp, reconcileStack, the deploy hook, and the panel.
* fix(drift): stamp last-checked inside the ledger transaction
Move the dossier last-checked stamp into the same transaction as the
finding insert/resolve, so the "checked {time}" the Drift tab shows can
never persist without the ledger update it describes. The stamp still runs
on a no-op authoritative check (a transaction that only stamps), keeping
the history "as of" honest. Adds a test that a failed deploy does not
reconcile the ledger.
This commit is contained in:
@@ -90,6 +90,8 @@ export interface StackDossier extends StackDossierFields {
|
||||
source_hash?: string | null;
|
||||
/** SHA-256 of the parsed compose model at the last deploy (ignores comments/whitespace). */
|
||||
rendered_hash?: string | null;
|
||||
/** When the drift ledger was last reconciled for this stack (re-check, deploy, or background scan); null if never. */
|
||||
last_drift_check_at?: number | null;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
}
|
||||
@@ -1284,6 +1286,7 @@ export class DatabaseService {
|
||||
custom_notes TEXT NOT NULL DEFAULT '',
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL,
|
||||
last_drift_check_at INTEGER,
|
||||
UNIQUE(node_id, stack_name)
|
||||
);
|
||||
|
||||
@@ -1669,6 +1672,7 @@ export class DatabaseService {
|
||||
private migrateStackDossierHashes(): void {
|
||||
this.tryAddColumn('stack_dossiers', 'source_hash', 'TEXT');
|
||||
this.tryAddColumn('stack_dossiers', 'rendered_hash', 'TEXT');
|
||||
this.tryAddColumn('stack_dossiers', 'last_drift_check_at', 'INTEGER');
|
||||
}
|
||||
|
||||
private migrateGitSourceMultiFile(): void {
|
||||
@@ -2338,6 +2342,22 @@ export class DatabaseService {
|
||||
).run(nodeId, stackName, sourceHash, renderedHash, now, now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stamp when the drift ledger was last reconciled for a stack (re-check, deploy,
|
||||
* or background scan). Mirrors setStackDossierHashes: creates a notes-empty row
|
||||
* if none exists, otherwise updates only this column so operator notes and their
|
||||
* updated_at are left untouched.
|
||||
*/
|
||||
public setStackDossierDriftCheck(nodeId: number, stackName: string, checkedAt: number): void {
|
||||
const now = Date.now();
|
||||
this.db.prepare(
|
||||
`INSERT INTO stack_dossiers (node_id, stack_name, last_drift_check_at, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT(node_id, stack_name) DO UPDATE SET
|
||||
last_drift_check_at = excluded.last_drift_check_at`
|
||||
).run(nodeId, stackName, checkedAt, now, now);
|
||||
}
|
||||
|
||||
// --- Stack Drift Findings (the persisted drift ledger) ---
|
||||
|
||||
public insertDriftFinding(f: Omit<StackDriftFindingRow, 'id' | 'resolved_at'>): number {
|
||||
|
||||
Reference in New Issue
Block a user