==============================================================================
Demo 5 -- filterObject: mutability, container types, and the silent no-op
==============================================================================
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.

@PreFilter needs a MUTABLE argument -- and does not tell you when it is not
---------------------------------------------------------------------------
      method body saw: [Account[1,alice,100], Account[3,alice,300]]
  new ArrayList<>(..)                            ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  List.of(..)  (immutable)                       ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  List.copyOf(..)  (immutable)                   ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  Arrays.asList(..)                              ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  Collections.unmodifiableList(..)               ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  stream().toList()  (unmodifiable since 16)     ALLOWED  -> (void)
      method body saw: [Account[1,alice,100], Account[3,alice,300]]
  stream().collect(toList())  (ArrayList)        ALLOWED  -> (void)
  Account[]  (arrays rejected outright)          DENIED   -> IllegalStateException: Pre-filtering on array types is not supported. Using a Collection will solve this problem.

  Read the second and third lines again: bob's account reached the method
  body. @PreFilter filters by CLEARING the caller's collection and adding
  the survivors back. On an immutable list that throws, and
  DefaultMethodSecurityExpressionHandler.filterCollection catches the
  UnsupportedOperationException and returns a fresh list instead -- which
  PreFilterAuthorizationMethodInterceptor.invoke then discards, because it
  ignores filter()'s return value entirely. No exception, no WARN, no 403.

The only trace it leaves (same call, logger at TRACE)
-----------------------------------------------------
      method body saw: [Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  List.of(..) with TRACE on                      ALLOWED  -> (void)

What @PostFilter accepts as a return type
-----------------------------------------
  List<Account>                                  ALLOWED  -> [Account[1,alice,100], Account[3,alice,300]]
  Account[]                                      ALLOWED  -> [Account[1,alice,100], Account[3,alice,300]]
  Stream<Account> (collected here)               ALLOWED  -> [alice, alice]
  Map<String, Account>                           ALLOWED  -> {acct-1=Account[1,alice,100], acct-3=Account[3,alice,300]}
  Optional<Account>  (alice's)                   DENIED   -> IllegalArgumentException: Filter target must be a collection, array, map or stream type, but was Optional[Account[1,alice,100]]
  Optional<Account>  (bob's)                     DENIED   -> IllegalArgumentException: Filter target must be a collection, array, map or stream type, but was Optional[Account[2,bob,200]]
  List.of(..)  (immutable return)                ALLOWED  -> [Account[1,alice,100], Account[3,alice,300]]
  Ledger  (a type Spring Security does not know) DENIED   -> IllegalArgumentException: Filter target must be a collection, array, map or stream type, but was Ledger[Account[1,alice,100], Account[2,bob,200], Account[3,alice,300]]
  Page<Account>  (real Spring Data PageImpl)     DENIED   -> IllegalArgumentException: Filter target must be a collection, array, map or stream type, but was Page 1 of 1 containing com.ankurm.methodsec.Account instances

Identity: does @PostFilter hand back the same object?
-----------------------------------------------------
  returned == the list the method returned : true
  the method's own list, after filtering   : [Account[1,alice,100], Account[3,alice,300]]

  @PostFilter mutates the returned collection in place and hands the same
  reference back. If that collection is a cached or shared instance, you
  have just deleted rows from it for every future caller.
