@@ -416,7 +416,7 @@ class ControlServiceTests(unittest.TestCase):
416416 def setUp (self ):
417417 """Use a deterministic monotonic clock and synthetic service credentials."""
418418 self .now = 100.0
419- self .base = SimpleNamespace (args = {"control_handoff" : {"enabled" : True }, "user_id" : self .instance , "ge_cloud_direct" : True , "ge_cloud_key" : "synthetic-inverter-key" }, log = lambda * _ : None )
419+ self .base = SimpleNamespace (args = {"control_handoff" : {"enabled" : True }, "saas_config_version" : 7 , " user_id" : self .instance , "ge_cloud_direct" : True , "ge_cloud_key" : "synthetic-inverter-key" }, log = lambda * _ : None )
420420 self .service = ControlHandoffService (self .base , self .instance , self .boot , "https://service.invalid" , "synthetic-service-key" , clock = lambda : self .now )
421421
422422 def active (self , ** changes ):
@@ -437,6 +437,35 @@ def closing(self):
437437 data .pop ("lease_for_s" )
438438 return data
439439
440+ def test_loaded_revision_is_required_before_claiming_a_boot (self ):
441+ """An absent or malformed emitted revision cannot make a service request."""
442+ for value in (None , True , False , 0 , - 1 , "7" , 7.0 , 2147483648 ):
443+ self .base .args ["saas_config_version" ] = value
444+ with patch ("control_handoff.requests.post" ) as post , self .assertRaises (ControlAttachFailed ):
445+ self .service .attach ()
446+ post .assert_not_called ()
447+ self .assertIsNone (self .service .gate )
448+
449+ def test_stale_loaded_revision_cannot_start_components (self ):
450+ """A server epoch at another revision leaves startup's sentinel sealed."""
451+ from datetime import datetime , timezone
452+ import predbat as predbat_module
453+
454+ self .base .update_time = lambda ** _kwargs : None
455+ self .base .now_utc_real = datetime .now (timezone .utc )
456+ self .base .reset = lambda : None
457+ self .base .record_status = lambda * _args , ** _kwargs : None
458+ environment = {"SUPABASE_URL" : "https://service.invalid" , "SUPABASE_KEY" : "synthetic-service-key" }
459+ with patch .dict ("os.environ" , environment ), patch ("control_handoff.uuid.uuid4" , return_value = self .boot ), patch ("control_handoff.requests.post" , return_value = ServiceResponse (self .active (config_version = 8 ))), patch (
460+ "control_handoff.ControlHandoffService.start"
461+ ) as worker , patch .object (predbat_module , "Components" ) as components , self .assertRaises (ControlAttachFailed ):
462+ predbat_module .PredBat .initialize (self .base )
463+ worker .assert_not_called ()
464+ components .assert_not_called ()
465+ self .assertTrue (self .base .control_write_gate .snapshot ()["closed" ])
466+ with self .assertRaises (ControlWriteBlocked ):
467+ self .base .control_write_gate .admit ("givenergy" )
468+
440469 def test_attach_uses_service_credentials_and_exact_boot (self ):
441470 """Bind only the service-issued epoch and never follow credential redirects."""
442471 with patch ("control_handoff.requests.post" , return_value = ServiceResponse (self .active ())) as post :
0 commit comments