@@ -48,6 +48,25 @@ describe("gateway-smoke", () => {
4848 } ;
4949 }
5050
51+ function connectHelloResponse ( scopes : string [ ] = [ ] ) {
52+ return {
53+ ok : true ,
54+ payload : {
55+ auth : { role : "operator" , scopes } ,
56+ features : { events : [ ] , methods : [ "health" ] } ,
57+ policy : {
58+ maxBufferedBytes : 1024 * 1024 ,
59+ maxPayload : 256 * 1024 ,
60+ tickIntervalMs : 1000 ,
61+ } ,
62+ protocol : 1 ,
63+ server : { connId : "test-conn" , version : "dev" } ,
64+ snapshot : { } ,
65+ type : "hello-ok" ,
66+ } ,
67+ } ;
68+ }
69+
5170 async function listenGatewaySmokeServer ( ) {
5271 const requests : Array < { method : string ; params ?: unknown ; timeout ?: number } > = [ ] ;
5372 server = createServer ( ) ;
@@ -62,7 +81,7 @@ describe("gateway-smoke", () => {
6281 } ;
6382 requests . push ( { method : frame . method , params : frame . params } ) ;
6483 if ( frame . method === "connect" ) {
65- ws . send ( JSON . stringify ( { id : frame . id , ok : true , payload : { } , type : "res" } ) ) ;
84+ ws . send ( JSON . stringify ( { id : frame . id , type : "res" , ... connectHelloResponse ( ) } ) ) ;
6685 return ;
6786 }
6887 if ( frame . method === "health" ) {
@@ -72,9 +91,9 @@ describe("gateway-smoke", () => {
7291 if ( frame . method === "chat.history" ) {
7392 ws . send (
7493 JSON . stringify ( {
94+ error : "missing scope: operator.read" ,
7595 id : frame . id ,
76- ok : true ,
77- payload : { messages : [ ] } ,
96+ ok : false ,
7897 type : "res" ,
7998 } ) ,
8099 ) ;
@@ -162,19 +181,14 @@ describe("gateway-smoke", () => {
162181 ) ;
163182
164183 expect ( code ) . toBe ( 0 ) ;
165- expect ( loopback . requests . map ( ( request ) => request . method ) ) . toEqual ( [
166- "connect" ,
167- "health" ,
168- "chat.history" ,
169- ] ) ;
184+ expect ( loopback . requests . map ( ( request ) => request . method ) ) . toEqual ( [ "connect" , "health" ] ) ;
170185 expect ( loopback . requests [ 0 ] ?. params ) . toMatchObject ( {
171186 auth : { token : "secret-token" } ,
172187 client : { id : "openclaw-ios" } ,
173188 role : "operator" ,
174189 scopes : [ "operator.read" , "operator.write" , "operator.admin" ] ,
175190 } ) ;
176- expect ( loopback . requests [ 2 ] ?. params ) . toEqual ( { sessionKey : "main" } ) ;
177- expect ( stdout ) . toEqual ( [ "ok: connected + health + chat.history" ] ) ;
191+ expect ( stdout ) . toEqual ( [ "ok: connected + health" ] ) ;
178192 expect ( stderr ) . toEqual ( [ ] ) ;
179193 } ) ;
180194
@@ -210,11 +224,10 @@ describe("gateway-smoke", () => {
210224 expect ( stderr ) . toEqual ( [ "connect failed: bad token" ] ) ;
211225 } ) ;
212226
213- it ( "requires connect, health, and chat history in order" , async ( ) => {
227+ it ( "requires connect and health in order" , async ( ) => {
214228 const fake = createSmokeDeps ( {
215- connect : { ok : true } ,
229+ connect : connectHelloResponse ( ) ,
216230 health : healthResponse ( ) ,
217- "chat.history" : { ok : true , payload : { messages : [ ] } } ,
218231 } ) ;
219232
220233 const code = await runGatewaySmoke (
@@ -227,55 +240,49 @@ describe("gateway-smoke", () => {
227240 expect ( fake . calls ) . toEqual ( [
228241 { method : "connect" , timeout : undefined } ,
229242 { method : "health" , timeout : undefined } ,
230- { method : "chat.history" , timeout : 15000 } ,
231243 ] ) ;
232- expect ( fake . stdout ) . toEqual ( [ "ok: connected + health + chat.history " ] ) ;
244+ expect ( fake . stdout ) . toEqual ( [ "ok: connected + health" ] ) ;
233245 expect ( fake . stderr ) . toEqual ( [ ] ) ;
234246 } ) ;
235247
236- it ( "fails when chat history success is missing message evidence" , async ( ) => {
248+ it ( "fails when connect success is missing hello evidence" , async ( ) => {
237249 const fake = createSmokeDeps ( {
238250 connect : { ok : true } ,
239- health : healthResponse ( ) ,
240- "chat.history" : { ok : true } ,
241251 } ) ;
242252
243253 const code = await runGatewaySmoke (
244254 { token : "secret-token" , urlRaw : "ws://127.0.0.1:12345" } ,
245255 fake . deps ,
246256 ) ;
247257
248- expect ( code ) . toBe ( 4 ) ;
258+ expect ( code ) . toBe ( 2 ) ;
249259 expect ( fake . closed ) . toBe ( 1 ) ;
250- expect ( fake . calls ) . toEqual ( [
251- { method : "connect" , timeout : undefined } ,
252- { method : "health" , timeout : undefined } ,
253- { method : "chat.history" , timeout : 15000 } ,
254- ] ) ;
260+ expect ( fake . calls ) . toEqual ( [ { method : "connect" , timeout : undefined } ] ) ;
255261 expect ( fake . stdout ) . toEqual ( [ ] ) ;
256- expect ( fake . stderr ) . toEqual ( [ "chat.history failed: missing messages array " ] ) ;
262+ expect ( fake . stderr ) . toEqual ( [ "connect failed: missing hello-ok payload " ] ) ;
257263 } ) ;
258264
259- it ( "fails when chat history messages are not an array " , async ( ) => {
265+ it ( "fails when the unpaired iOS-shaped connect keeps operator scopes " , async ( ) => {
260266 const fake = createSmokeDeps ( {
261- connect : { ok : true } ,
262- health : healthResponse ( ) ,
263- "chat.history" : { ok : true , payload : { messages : { } } } ,
267+ connect : connectHelloResponse ( [ "operator.read" ] ) ,
264268 } ) ;
265269
266270 const code = await runGatewaySmoke (
267271 { token : "secret-token" , urlRaw : "ws://127.0.0.1:12345" } ,
268272 fake . deps ,
269273 ) ;
270274
271- expect ( code ) . toBe ( 4 ) ;
275+ expect ( code ) . toBe ( 2 ) ;
272276 expect ( fake . closed ) . toBe ( 1 ) ;
273- expect ( fake . stderr ) . toEqual ( [ "chat.history failed: missing messages array" ] ) ;
277+ expect ( fake . calls ) . toEqual ( [ { method : "connect" , timeout : undefined } ] ) ;
278+ expect ( fake . stderr ) . toEqual ( [
279+ "connect failed: unpaired iOS smoke unexpectedly received operator scopes" ,
280+ ] ) ;
274281 } ) ;
275282
276283 it ( "fails after connect when health is unavailable" , async ( ) => {
277284 const fake = createSmokeDeps ( {
278- connect : { ok : true } ,
285+ connect : connectHelloResponse ( ) ,
279286 health : { ok : false , error : "not healthy" } ,
280287 } ) ;
281288
@@ -292,7 +299,7 @@ describe("gateway-smoke", () => {
292299
293300 it ( "fails when health success is missing summary evidence" , async ( ) => {
294301 const fake = createSmokeDeps ( {
295- connect : { ok : true } ,
302+ connect : connectHelloResponse ( ) ,
296303 health : { ok : true } ,
297304 } ) ;
298305
@@ -307,9 +314,9 @@ describe("gateway-smoke", () => {
307314 expect ( fake . stderr ) . toEqual ( [ "health failed: missing health summary payload" ] ) ;
308315 } ) ;
309316
310- it ( "fails after health when chat history is unavailable " , async ( ) => {
317+ it ( "does not call scoped chat history for an unpaired iOS-shaped client " , async ( ) => {
311318 const fake = createSmokeDeps ( {
312- connect : { ok : true } ,
319+ connect : connectHelloResponse ( ) ,
313320 health : healthResponse ( ) ,
314321 "chat.history" : { ok : false , error : "session store unavailable" } ,
315322 } ) ;
@@ -319,13 +326,12 @@ describe("gateway-smoke", () => {
319326 fake . deps ,
320327 ) ;
321328
322- expect ( code ) . toBe ( 4 ) ;
329+ expect ( code ) . toBe ( 0 ) ;
323330 expect ( fake . closed ) . toBe ( 1 ) ;
324331 expect ( fake . calls ) . toEqual ( [
325332 { method : "connect" , timeout : undefined } ,
326333 { method : "health" , timeout : undefined } ,
327- { method : "chat.history" , timeout : 15000 } ,
328334 ] ) ;
329- expect ( fake . stderr ) . toEqual ( [ "chat.history failed: session store unavailable" ] ) ;
335+ expect ( fake . stderr ) . toEqual ( [ ] ) ;
330336 } ) ;
331337} ) ;
0 commit comments