@@ -201,6 +201,7 @@ describe("createPluginApprovalHandlers", () => {
201201
202202 // Resolve the approval so the handler can complete
203203 const approvalId = acceptedApprovalId ( respond as unknown as MockCallSource ) ;
204+ expect ( manager . getSnapshot ( approvalId ) ?. requestedByClientId ) . toBe ( "test-client" ) ;
204205 manager . resolve ( approvalId , "allow-once" ) ;
205206
206207 await handlerPromise ;
@@ -468,6 +469,52 @@ describe("createPluginApprovalHandlers", () => {
468469 manager . resolve ( approvalId , "allow-once" ) ;
469470 await handlerPromise ;
470471 } ) ;
472+
473+ it ( "lists only plugin approvals owned by the caller" , async ( ) => {
474+ const handlers = createPluginApprovalHandlers ( manager ) ;
475+ const visible = manager . create (
476+ { title : "Visible" , description : "D" } ,
477+ 60_000 ,
478+ "plugin:visible" ,
479+ ) ;
480+ visible . requestedByDeviceId = "device-owner" ;
481+ visible . requestedByConnId = "conn-owner" ;
482+ visible . requestedByClientId = "client-owner" ;
483+ void manager . register ( visible , 60_000 ) ;
484+
485+ const hidden = manager . create ( { title : "Hidden" , description : "D" } , 60_000 , "plugin:hidden" ) ;
486+ hidden . requestedByDeviceId = "device-other" ;
487+ hidden . requestedByConnId = "conn-other" ;
488+ hidden . requestedByClientId = "client-other" ;
489+ void manager . register ( hidden , 60_000 ) ;
490+
491+ const listRespond = vi . fn ( ) ;
492+ await handlers [ "plugin.approval.list" ] (
493+ createMockOptions (
494+ "plugin.approval.list" ,
495+ { } ,
496+ {
497+ respond : listRespond ,
498+ client : {
499+ connId : "conn-owner" ,
500+ connect : {
501+ client : { id : "client-owner" } ,
502+ device : { id : "device-owner" } ,
503+ } ,
504+ } as GatewayRequestHandlerOptions [ "client" ] ,
505+ } ,
506+ ) ,
507+ ) ;
508+
509+ expect ( responseCall ( listRespond as unknown as MockCallSource ) . ok ) . toBe ( true ) ;
510+ const approvals = requireArray (
511+ responseCall ( listRespond as unknown as MockCallSource ) . result ,
512+ "approval list" ,
513+ ) ;
514+ expect ( approvals . map ( ( entry ) => requireRecord ( entry , "approval" ) . id ) ) . toEqual ( [
515+ "plugin:visible" ,
516+ ] ) ;
517+ } ) ;
471518 } ) ;
472519
473520 describe ( "plugin.approval.waitDecision" , ( ) => {
@@ -542,6 +589,74 @@ describe("createPluginApprovalHandlers", () => {
542589 expect ( resolvedBroadcast . options ) . toEqual ( { dropIfSlow : true } ) ;
543590 } ) ;
544591
592+ it ( "resolves only plugin approvals owned by the caller" , async ( ) => {
593+ const handlers = createPluginApprovalHandlers ( manager ) ;
594+ const visible = manager . create (
595+ { title : "Visible" , description : "D" } ,
596+ 60_000 ,
597+ "plugin:abcd-visible" ,
598+ ) ;
599+ visible . requestedByDeviceId = "device-owner" ;
600+ visible . requestedByConnId = "conn-owner" ;
601+ visible . requestedByClientId = "client-owner" ;
602+ void manager . register ( visible , 60_000 ) ;
603+
604+ const hidden = manager . create (
605+ { title : "Hidden" , description : "D" } ,
606+ 60_000 ,
607+ "plugin:abcd-hidden" ,
608+ ) ;
609+ hidden . requestedByDeviceId = "device-other" ;
610+ hidden . requestedByConnId = "conn-other" ;
611+ hidden . requestedByClientId = "client-other" ;
612+ void manager . register ( hidden , 60_000 ) ;
613+
614+ const ownerClient = {
615+ connId : "conn-owner" ,
616+ connect : {
617+ client : { id : "client-owner" } ,
618+ device : { id : "device-owner" } ,
619+ } ,
620+ } as GatewayRequestHandlerOptions [ "client" ] ;
621+ const resolveRespond = vi . fn ( ) ;
622+ await handlers [ "plugin.approval.resolve" ] (
623+ createMockOptions (
624+ "plugin.approval.resolve" ,
625+ {
626+ id : "plugin:abcd" ,
627+ decision : "allow-once" ,
628+ } ,
629+ {
630+ respond : resolveRespond ,
631+ client : ownerClient ,
632+ } ,
633+ ) ,
634+ ) ;
635+ expect ( resolveRespond ) . toHaveBeenCalledWith ( true , { ok : true } , undefined ) ;
636+ expect ( manager . getSnapshot ( visible . id ) ?. decision ) . toBe ( "allow-once" ) ;
637+ expect ( manager . getSnapshot ( hidden . id ) ?. decision ) . toBeUndefined ( ) ;
638+
639+ const hiddenRespond = vi . fn ( ) ;
640+ await handlers [ "plugin.approval.resolve" ] (
641+ createMockOptions (
642+ "plugin.approval.resolve" ,
643+ {
644+ id : hidden . id ,
645+ decision : "deny" ,
646+ } ,
647+ {
648+ respond : hiddenRespond ,
649+ client : ownerClient ,
650+ } ,
651+ ) ,
652+ ) ;
653+ expect ( responseCall ( hiddenRespond as unknown as MockCallSource ) . ok ) . toBe ( false ) ;
654+ const error = responseError ( hiddenRespond as unknown as MockCallSource ) ;
655+ expect ( error . code ) . toBe ( "INVALID_REQUEST" ) ;
656+ expect ( error . message ) . toBe ( "unknown or expired approval id" ) ;
657+ expect ( manager . getSnapshot ( hidden . id ) ?. decision ) . toBeUndefined ( ) ;
658+ } ) ;
659+
545660 it ( "rejects decisions outside plugin approval allowed decisions" , async ( ) => {
546661 const handlers = createPluginApprovalHandlers ( manager ) ;
547662 const record = manager . create (
0 commit comments