@@ -1232,7 +1232,7 @@ func TestHandleBindStreamFrameErrors(t *testing.T) {
12321232 Payload : protocol.BindStreamParams {
12331233 SessionID : "session-1" ,
12341234 },
1235- })
1235+ }, nil )
12361236 if response .Type != FrameTypeError {
12371237 t .Fatalf ("response type = %q, want %q" , response .Type , FrameTypeError )
12381238 }
@@ -1271,7 +1271,7 @@ func TestHandleBindStreamFrameErrors(t *testing.T) {
12711271 SessionID : "session-1" ,
12721272 Channel : "ipc" ,
12731273 },
1274- })
1274+ }, nil )
12751275 if response .Type != FrameTypeError {
12761276 t .Fatalf ("response type = %q, want %q" , response .Type , FrameTypeError )
12771277 }
@@ -1281,6 +1281,57 @@ func TestHandleBindStreamFrameErrors(t *testing.T) {
12811281 })
12821282}
12831283
1284+ func TestHandleBindStreamFrameRejectsSessionOutsideCurrentWorkspace (t * testing.T ) {
1285+ relay := NewStreamRelay (StreamRelayOptions {})
1286+ ctx , cancel := context .WithCancel (context .Background ())
1287+ defer cancel ()
1288+
1289+ connectionID := NewConnectionID ()
1290+ workspaceState := NewConnectionWorkspaceState ()
1291+ workspaceState .SetWorkspaceHash ("workspace-b" )
1292+ connectionCtx := WithConnectionID (ctx , connectionID )
1293+ connectionCtx = WithConnectionWorkspaceState (connectionCtx , workspaceState )
1294+ connectionCtx = WithStreamRelay (connectionCtx , relay )
1295+ if err := relay .RegisterConnection (ConnectionRegistration {
1296+ ConnectionID : connectionID ,
1297+ Channel : StreamChannelIPC ,
1298+ Context : connectionCtx ,
1299+ Cancel : cancel ,
1300+ Write : func (message RelayMessage ) error {
1301+ _ = message
1302+ return nil
1303+ },
1304+ Close : func () {},
1305+ }); err != nil {
1306+ t .Fatalf ("register connection: %v" , err )
1307+ }
1308+ defer relay .dropConnection (connectionID )
1309+
1310+ runtimeStub := & bootstrapRuntimeStub {
1311+ loadSessionFn : func (context.Context , LoadSessionInput ) (Session , error ) {
1312+ return Session {}, ErrRuntimeResourceNotFound
1313+ },
1314+ }
1315+ response := handleBindStreamFrame (connectionCtx , MessageFrame {
1316+ Type : FrameTypeRequest ,
1317+ Action : FrameActionBindStream ,
1318+ RequestID : "bind-cross-workspace" ,
1319+ Payload : protocol.BindStreamParams {
1320+ SessionID : "session-from-workspace-a" ,
1321+ Channel : "all" ,
1322+ },
1323+ }, runtimeStub )
1324+ if response .Type != FrameTypeError {
1325+ t .Fatalf ("response type = %q, want %q" , response .Type , FrameTypeError )
1326+ }
1327+ if response .Error == nil || response .Error .Code != ErrorCodeResourceNotFound .String () {
1328+ t .Fatalf ("response error = %#v, want resource_not_found" , response .Error )
1329+ }
1330+ if got := relay .ResolveFallbackSessionIDForWorkspace (connectionID , "workspace-b" ); got != "" {
1331+ t .Fatalf ("binding should not be written after validation failure, got fallback %q" , got )
1332+ }
1333+ }
1334+
12841335func TestHandleTriggerActionFrame (t * testing.T ) {
12851336 registerConnection := func (
12861337 t * testing.T ,
0 commit comments