mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-10-25 13:11:05 +00:00
bb85e08b36
* feat(gitops): capture a recovery point before Git-managed rollout applies A rollout rollback needs a recovery point that names the generation the node was running before the deploy, and Git-managed rollout applies did not create one. applyLocalUnderLock now captures the pre-deploy project (with the hub-supplied GitOps binding) before the incoming compose reaches disk, owns the recovery lifecycle from acquire through verified, and compensates from the recovery point when the apply fails. A remote target does the same over apply-local, and the request carries the binding because a leaf has no GitOps rows of its own. The binding resolves the deployed pointer for Direct mode and the ack's applied pointer for Blueprint mode: nothing writes the deploy-bound pointer for a Blueprint-managed stack. A re-capture that cannot resolve the owning application (a leaf backup, for example) carries the previous binding forward, since re-capturing does not change what the node is running. * feat(gitops): add rollout lifecycle controls and rollback coordination Adds the operator lifecycle routes for a Git-managed Blueprint rollout: pause and resume (application or one target), replan (re-derives placement and reopens review instead of invalidating an accurate one), supersede (withdraws the live authorization and reports the abandoned rollout), and rollback. Rollback restores an explicit prior application generation on one target, the failed targets, or every changed target in the frozen set. Selectable generations come from the application's rollout-generation history; targets already running the selected generation are out of scope; every target is authorized before any work starts; and the abandoned generation is superseded first so nothing can dispatch it mid-restore. Each target is restored from its own captured recovery point, in process for the local node and through the node's stack rollback route for a remote, where the node must confirm it restored the requested generation. Every exit records a terminal per-target result, and a partial failure lifts the application out of recovery rather than leaving a restore nobody drives. The application detail read and the Blueprint summary now carry the prior generations a rollback can select, plus the bound Blueprint's enabled state so the surfaces can withhold execution controls. * feat(gitops): add rollout controls to the GitOps application surfaces The GitOps application view and the Blueprint sheet's GitOps section gain a rollout controls row: pause and resume as first-row actions, with replan, supersede, and rollback behind the overflow menu and each destructive choice behind a confirmation. Rollback selects a prior generation and a target scope (one target, the failed targets, or every changed target) and states the configuration-versus-data boundary before anything runs. Controls are offered only from the projection's own statuses and gated by the permission the route requires, and execution controls are withheld while the bound Blueprint is disabled. The superseded rollout copy now covers an operator withdrawal as well as replacement. * docs(gitops): document rollout lifecycle controls and rollback Covers pausing, resuming, replanning, and superseding a rollout, the rollback generation and scope selection with its configuration-versus-data caveat, and the drift-enforce interaction that re-applies the current revision after a rollback. The GitOps portfolio page names the in-place actions on a Git-managed application, and What's New gains an entry for the lifecycle controls. * fix(gitops): sanitize logged error messages on rollout recovery paths CodeQL flagged log injection on the new rollout lifecycle and recovery handlers: a remote node's response body, a recovery row, or a candidate payload can reach the logged Error object, so the logs now record the sanitized message string instead. No behavior change. * fix(gitops): sanitize the logged target id on rollout recovery paths The target node id on these paths can come from the rollback request's scope selector, so CodeQL reads it as a user-provided value flowing into the log entry even though it is a number. Pass it through sanitizeForLog, the same barrier the other logged values use. No behavior change. * fix(gitops): hold rollout dispatch while it is paused Pause was recorded and rendered but no execution path honored it: boot-time reconstruction re-dispatched a paused rollout, and the sequential dispatch loop kept deploying targets the operator had paused. The adapter now blocks while the application is paused, re-reads the pause before every target, skips individually paused targets, and reports a hold instead of progress when nothing was dispatched because every remaining target is paused; reconstruction skips paused applications outright. A dispatch that pauses during the preflight window no longer mints or supersedes the authorization it is holding. The continuation a target resume triggers is covered by the route test: the queue is dispatched again and any still-paused target is skipped. * fix(gitops): continue the queue on target resume and refuse empty pauses A per-target resume cleared the pause but never continued the rollout, so the target it released waited for the next restart to be retried; the route now runs the same continuation as an application resume, and the adapter skips targets that are still individually paused. Pausing an application with no authorized rollout and no partial record is now refused with ROLLOUT_PAUSE_REFUSED: recording a hold on nothing makes the surface read as held when no rollout ever ran. * docs(gitops): state the per-node restore limit for rollout rollback A node keeps only the recovery generation captured immediately before its latest rollout, so an older selectable generation has nothing to restore from and is reported as a failed target. The rollback dialog and the feature page now say so instead of implying every listed generation is restorable.