#pragma once #include #include #include #include #include namespace ota::rollback { enum class Phase { Idle, Assess, RestoreData, SelectPrevious, CheckPrevious, Recovered, SeparateRecovery }; enum class Slot { A, B }; struct Data { int schema = 1; std::vector records{1, 2, 3, 4}; }; // These are assumed complete durable records, not a storage implementation. struct Storage { Phase phase = Phase::Idle; Slot running = Slot::B; std::string failed_release = "system-2"; std::string previous_release = "system-1"; std::set blocked_releases; std::string failure_reason; std::string recovery_reason; bool report_pending = false; bool window_open = true; bool target_eligible = true; int attempts_left = 2; int boots_requested = 0; Data data; std::optional backup; bool backup_valid = false; bool restore_authorized = false; std::size_t records_lost = 0; int restores = 0; }; class Coordinator { public: explicit Coordinator(Storage &storage); void start(const std::string &reason); void advance(bool previous_healthy = true); // Call once for an actual reset, not merely a coordinator restart. void after_reset(); private: Storage &storage_; void stop(const std::string &reason); }; bool terminal(Phase phase); bool can_offer(const Storage &storage, const std::string &release); const char *name(Phase phase); const std::vector &scenarios(); Storage run_scenario(const std::string &scenario); }// namespace ota::rollback