@@ -294,6 +294,8 @@ export class ChannelPaginatorsOrchestrator extends WithSubscriptions {
294294 EventHandlerPipeline < EventHandlerContext >
295295 > ( ) ;
296296 protected ownershipResolver ?: PaginatorOwnershipResolver ;
297+ /** Track paginators already wrapped with ownership-aware filtering */
298+ protected _wrappedForOwnership = new WeakSet < ChannelPaginator > ( ) ;
297299
298300 protected static readonly defaultEventHandlers : ChannelPaginatorsOrchestratorEventHandlers =
299301 {
@@ -330,6 +332,8 @@ export class ChannelPaginatorsOrchestrator extends WithSubscriptions {
330332 for ( const [ type , handlers ] of Object . entries ( finalEventHandlers ) ) {
331333 if ( handlers ) this . ensurePipeline ( type ) . replaceAll ( handlers ) ;
332334 }
335+ // Ensure ownership rules are applied to initial paginators' query results
336+ this . paginators . forEach ( ( p ) => this . wrapPaginatorFiltering ( p ) ) ;
333337 }
334338
335339 get paginators ( ) : ChannelPaginator [ ] {
@@ -369,6 +373,46 @@ export class ChannelPaginatorsOrchestrator extends WithSubscriptions {
369373 return new Set ( this . ownershipResolver ?.( { channel, matchingPaginators } ) ?? [ ] ) ;
370374 }
371375
376+ /**
377+ * Filter a page of query results for a specific paginator according to ownership rules.
378+ * If no owners are specified by the resolver, all matching paginators keep the item.
379+ */
380+ protected filterItemsByOwnership ( {
381+ paginator,
382+ items,
383+ } : {
384+ paginator : ChannelPaginator ;
385+ items : Channel [ ] ;
386+ } ) : Channel [ ] {
387+ if ( ! items . length ) return items ;
388+ const result : Channel [ ] = [ ] ;
389+ for ( const ch of items ) {
390+ const matchingPaginators = this . paginators . filter ( ( p ) => p . matchesFilter ( ch ) ) ;
391+ const ownerIds = this . resolveOwnership ( ch , matchingPaginators ) ;
392+ const noOwnersOrPaginatorIsOwner =
393+ ownerIds . size === 0 || ownerIds . has ( paginator . id ) ;
394+
395+ if ( noOwnersOrPaginatorIsOwner ) {
396+ result . push ( ch ) ;
397+ }
398+ }
399+ return result ;
400+ }
401+
402+ /**
403+ * Wrap paginator.filterQueryResults so that ownership rules are applied whenever
404+ * the paginator ingests results from a server query (first page and subsequent pages).
405+ */
406+ protected wrapPaginatorFiltering ( paginator : ChannelPaginator ) {
407+ if ( this . _wrappedForOwnership . has ( paginator ) ) return ;
408+ const original = paginator . filterQueryResults . bind ( paginator ) ;
409+ paginator . filterQueryResults = ( items : Channel [ ] ) => {
410+ const filtered = original ( items ) as Channel [ ] ;
411+ return this . filterItemsByOwnership ( { paginator, items : filtered } ) ;
412+ } ;
413+ this . _wrappedForOwnership . add ( paginator ) ;
414+ }
415+
372416 getPaginatorById ( id : string ) {
373417 return this . paginators . find ( ( p ) => p . id === id ) ;
374418 }
@@ -392,6 +436,8 @@ export class ChannelPaginatorsOrchestrator extends WithSubscriptions {
392436 ) ;
393437 paginators . splice ( validIndex , 0 , paginator ) ;
394438 this . state . partialNext ( { paginators } ) ;
439+ // Wrap newly inserted paginator to enforce ownership on query results
440+ this . wrapPaginatorFiltering ( paginator ) ;
395441 }
396442
397443 addEventHandler ( {
0 commit comments