@@ -23,7 +23,7 @@ const CLEANUP_SKIPPED: SandboxExecCleanupDeps = {
2323function depsFor ( status : number , restartGateway = vi . fn ( ( ) => ( { ok : true } ) ) ) : ExecSandboxDeps {
2424 return {
2525 resolveBinary : ( ) => "openshell" ,
26- selectGateway : ( ) => ( { outcome : "unregistered " , gatewayName : null } ) ,
26+ selectGateway : ( ) => ( { outcome : "selected " , gatewayName : "nemoclaw-alpha" } ) ,
2727 run : ( ) => ( { status } ) ,
2828 cleanupDeps : CLEANUP_SKIPPED ,
2929 restartGateway,
@@ -196,9 +196,7 @@ describe("Google Chat pairing approval gateway activation (#8553)", () => {
196196
197197 expect ( restartGateway ) . toHaveBeenCalledOnce ( ) ;
198198 expect ( exitCode ) . toBe ( 1 ) ;
199- expect ( errorSpy ) . toHaveBeenCalledWith (
200- expect . stringContaining ( "approval was not rolled back" ) ,
201- ) ;
199+ expect ( errorSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( "approval was not rolled back" ) ) ;
202200 expect ( errorSpy ) . toHaveBeenCalledWith (
203201 expect . stringContaining ( "nemoclaw alpha gateway restart" ) ,
204202 ) ;
@@ -257,6 +255,34 @@ describe("Google Chat pairing approval gateway activation (#8553)", () => {
257255 expect ( exitCode ) . toBe ( 0 ) ;
258256 } ) ;
259257
258+ it ( "does not activate or claim managed recovery without an owning gateway" , async ( ) => {
259+ const restartGateway = vi . fn ( ( ) => ( { ok : true } ) ) ;
260+ const deps = depsFor ( 0 , restartGateway ) ;
261+ deps . selectGateway = ( ) => ( { outcome : "unregistered" , gatewayName : null } ) ;
262+ deps . cleanupDeps = {
263+ getSandbox : ( ) => {
264+ throw new Error ( "invalid registry JSON" ) ;
265+ } ,
266+ inspectMutableConfigPerms : CLEANUP_SKIPPED . inspectMutableConfigPerms ,
267+ repairMutableConfigPerms : CLEANUP_SKIPPED . repairMutableConfigPerms ,
268+ } ;
269+ const errorSpy = vi . spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
270+
271+ const exitCode = await runAndCaptureExit (
272+ [ "openclaw" , "pairing" , "approve" , "googlechat" , "ABCD1234" ] ,
273+ deps ,
274+ ) ;
275+
276+ expect ( restartGateway ) . not . toHaveBeenCalled ( ) ;
277+ expect ( exitCode ) . toBe ( 1 ) ;
278+ expect ( errorSpy ) . not . toHaveBeenCalledWith (
279+ expect . stringContaining ( "managed gateway activation failed" ) ,
280+ ) ;
281+ expect ( errorSpy ) . not . toHaveBeenCalledWith (
282+ expect . stringContaining ( "nemoclaw alpha gateway restart" ) ,
283+ ) ;
284+ } ) ;
285+
260286 it ( "fails closed when the recorded sandbox identity cannot be read" , async ( ) => {
261287 const restartGateway = vi . fn ( ( ) => ( { ok : true } ) ) ;
262288 const deps = depsFor ( 0 , restartGateway ) ;
0 commit comments