This is an automated email from the ASF dual-hosted git repository.

roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 95ce9f5a23 [#13859] fix(authz): expose inaccessible object tag and 
policy associations (#13863)
95ce9f5a23 is described below

commit 95ce9f5a230decdfabb5249c0d7910543a32402c
Author: roryqi <[email protected]>
AuthorDate: Fri Oct 16 15:41:26 2026 +0800

    [#13859] fix(authz): expose inaccessible object tag and policy associations 
(#13863)
    
    ### What changes were proposed in this pull request?
    
    Add authorization-filtering indicators to metadata object tag and policy
    list responses:
    
    - `hasInaccessibleTags`
    - `hasInaccessiblePolicies`
    
    The indicators are included in both name and detailed responses. Tag and
    policy associations are aggregated before authorization filtering so
    direct and inherited associations follow the same behavior.
    
    ### Why are the changes needed?
    
    When all associated tags or policies are inaccessible, the APIs
    currently return an empty list indistinguishable from an object with no
    associations.
    
    The new fields indicate whether associations were omitted without
    exposing their names, count, details, or inheritance source.
    
    Fix: #13859
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. The metadata object tag and policy list APIs add boolean fields
    indicating whether inaccessible associations were omitted.
    
    ### How was this patch tested?
    
    - Common response DTO unit tests
    - Metadata object tag and policy REST tests
    - Tag and policy Docker authorization integration tests
    - `./gradlew :docs:build`
    - Spotless checks
---
 .../org/apache/gravitino/policy/PolicyList.java    | 61 +++++++++++++++
 .../apache/gravitino/policy/SupportsPolicies.java  | 27 +++++++
 .../org/apache/gravitino/tag/SupportsTags.java     | 26 +++++++
 .../java/org/apache/gravitino/tag/TagList.java     | 61 +++++++++++++++
 .../apache/gravitino/client/BaseSchemaCatalog.java | 22 ++++++
 .../org/apache/gravitino/client/GenericColumn.java | 11 +++
 .../apache/gravitino/client/GenericFileset.java    | 22 ++++++
 .../apache/gravitino/client/GenericFunction.java   | 11 +++
 .../org/apache/gravitino/client/GenericModel.java  | 22 ++++++
 .../org/apache/gravitino/client/GenericSchema.java | 22 ++++++
 .../gravitino/client/GenericSemanticModel.java     | 26 +++++++
 .../org/apache/gravitino/client/GenericTopic.java  | 22 ++++++
 .../org/apache/gravitino/client/GenericView.java   | 11 +++
 .../client/MetadataObjectPolicyOperations.java     | 31 +++++---
 .../client/MetadataObjectTagOperations.java        | 32 +++++---
 .../apache/gravitino/client/RelationalTable.java   | 22 ++++++
 .../gravitino/client/TestSupportPolicies.java      | 23 +++---
 .../apache/gravitino/client/TestSupportTags.java   | 21 +++--
 .../test/authorization/PolicyAuthorizationIT.java  | 89 ++++++++++++++++++++++
 .../TagOperationsAuthorizationIT.java              | 61 +++++++++++++++
 .../client-python/gravitino/api/tag/__init__.py    |  2 +
 .../gravitino/api/tag/supports_tags.py             | 17 +++++
 .../gravitino/api/tag/{__init__.py => tag_list.py} | 24 ++++--
 .../gravitino/client/base_schema_catalog.py        |  7 ++
 .../gravitino/client/generic_column.py             |  7 ++
 .../gravitino/client/generic_fileset.py            |  9 ++-
 .../gravitino/client/generic_function.py           |  9 +++
 .../gravitino/client/generic_model.py              |  8 +-
 .../gravitino/client/generic_schema.py             |  7 ++
 .../gravitino/client/generic_semantic_model.py     |  7 ++
 .../client-python/gravitino/client/generic_view.py |  7 ++
 .../client/metadata_object_tag_operations.py       | 30 +++++---
 .../gravitino/client/relational_table.py           |  7 ++
 .../gravitino/dto/responses/tag_response.py        | 13 +++-
 clients/client-python/tests/unittests/mock_base.py |  4 +-
 .../client-python/tests/unittests/test_tag_api.py  | 54 +++++++++++--
 ....java => MetadataObjectPolicyListResponse.java} | 51 +++++--------
 ...nse.java => MetadataObjectTagListResponse.java} | 46 +++++------
 .../gravitino/dto/responses/NameListResponse.java  |  2 +
 .../dto/responses/PolicyListResponse.java          |  2 +
 ...stResponse.java => PolicyNameListResponse.java} | 47 +++++-------
 .../gravitino/dto/responses/TagListResponse.java   |  2 +
 ...gListResponse.java => TagNameListResponse.java} | 47 +++++-------
 .../gravitino/dto/responses/TestResponses.java     | 78 +++++++++++++++++++
 docs/manage-policies-in-gravitino.md               | 35 ++++++++-
 docs/manage-tags-in-gravitino.md                   | 48 ++++++++++--
 docs/open-api/policies.yaml                        | 50 ++++++++++--
 docs/open-api/tags.yaml                            | 50 ++++++++++--
 .../web/rest/MetadataObjectPolicyOperations.java   | 11 ++-
 .../web/rest/MetadataObjectTagOperations.java      | 37 +++++----
 .../rest/TestMetadataObjectPolicyOperations.java   | 19 +++--
 .../web/rest/TestMetadataObjectTagOperations.java  |  9 ++-
 52 files changed, 1148 insertions(+), 221 deletions(-)

diff --git a/api/src/main/java/org/apache/gravitino/policy/PolicyList.java 
b/api/src/main/java/org/apache/gravitino/policy/PolicyList.java
new file mode 100644
index 0000000000..11281e61b7
--- /dev/null
+++ b/api/src/main/java/org/apache/gravitino/policy/PolicyList.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.policy;
+
+import com.google.common.base.Preconditions;
+import org.apache.gravitino.annotation.Evolving;
+
+/**
+ * A list of visible policies and whether authorization filtering omitted 
other policies.
+ *
+ * @param <T> The type of the returned policy names or policy objects.
+ */
+@Evolving
+public final class PolicyList<T> {
+
+  private final T[] policies;
+  private final boolean hasInaccessiblePolicies;
+
+  /**
+   * Creates a policy list.
+   *
+   * @param policies The visible policy names or policy objects.
+   * @param hasInaccessiblePolicies Whether one or more inaccessible policies 
were omitted.
+   */
+  public PolicyList(T[] policies, boolean hasInaccessiblePolicies) {
+    Preconditions.checkArgument(policies != null, "Policies must not be null");
+    this.policies = policies.clone();
+    this.hasInaccessiblePolicies = hasInaccessiblePolicies;
+  }
+
+  /**
+   * @return The visible policy names or policy objects.
+   */
+  public T[] policies() {
+    return policies.clone();
+  }
+
+  /**
+   * @return True if one or more inaccessible policies were omitted, false 
otherwise.
+   */
+  public boolean hasInaccessiblePolicies() {
+    return hasInaccessiblePolicies;
+  }
+}
diff --git 
a/api/src/main/java/org/apache/gravitino/policy/SupportsPolicies.java 
b/api/src/main/java/org/apache/gravitino/policy/SupportsPolicies.java
index af0ed772c6..21651678f0 100644
--- a/api/src/main/java/org/apache/gravitino/policy/SupportsPolicies.java
+++ b/api/src/main/java/org/apache/gravitino/policy/SupportsPolicies.java
@@ -33,8 +33,35 @@ public interface SupportsPolicies {
    */
   String[] listPolicies();
 
+  /**
+   * List the visible policy names and whether authorization filtering omitted 
other policies.
+   *
+   * <p>The default implementation preserves compatibility with existing 
implementations but cannot
+   * detect omitted policies. Implementations that support authorization 
filtering should override
+   * this method.
+   *
+   * @return The visible policy names and authorization-filtering status.
+   */
+  default PolicyList<String> listPoliciesWithVisibility() {
+    return new PolicyList<>(listPolicies(), false);
+  }
+
   /**
    * @return The policies that apply to the metadata object.
    */
   Policy[] listPolicyInfos();
+
+  /**
+   * List the visible policies with details and whether authorization 
filtering omitted other
+   * policies.
+   *
+   * <p>The default implementation preserves compatibility with existing 
implementations but cannot
+   * detect omitted policies. Implementations that support authorization 
filtering should override
+   * this method.
+   *
+   * @return The visible policies and authorization-filtering status.
+   */
+  default PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return new PolicyList<>(listPolicyInfos(), false);
+  }
 }
diff --git a/api/src/main/java/org/apache/gravitino/tag/SupportsTags.java 
b/api/src/main/java/org/apache/gravitino/tag/SupportsTags.java
index 67805d1782..21184fc431 100644
--- a/api/src/main/java/org/apache/gravitino/tag/SupportsTags.java
+++ b/api/src/main/java/org/apache/gravitino/tag/SupportsTags.java
@@ -37,6 +37,19 @@ public interface SupportsTags {
    */
   String[] listTags();
 
+  /**
+   * List the visible tag names and whether authorization filtering omitted 
other tags.
+   *
+   * <p>The default implementation preserves compatibility with existing 
implementations but cannot
+   * detect omitted tags. Implementations that support authorization filtering 
should override this
+   * method.
+   *
+   * @return The visible tag names and authorization-filtering status.
+   */
+  default TagList<String> listTagsWithVisibility() {
+    return new TagList<>(listTags(), false);
+  }
+
   /**
    * List all the tags with details for the specific object.
    *
@@ -44,6 +57,19 @@ public interface SupportsTags {
    */
   Tag[] listTagsInfo();
 
+  /**
+   * List the visible tags with details and whether authorization filtering 
omitted other tags.
+   *
+   * <p>The default implementation preserves compatibility with existing 
implementations but cannot
+   * detect omitted tags. Implementations that support authorization filtering 
should override this
+   * method.
+   *
+   * @return The visible tags and authorization-filtering status.
+   */
+  default TagList<Tag> listTagsInfoWithVisibility() {
+    return new TagList<>(listTagsInfo(), false);
+  }
+
   /**
    * Get a tag by its name for the specific object.
    *
diff --git a/api/src/main/java/org/apache/gravitino/tag/TagList.java 
b/api/src/main/java/org/apache/gravitino/tag/TagList.java
new file mode 100644
index 0000000000..1eea86680f
--- /dev/null
+++ b/api/src/main/java/org/apache/gravitino/tag/TagList.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.tag;
+
+import com.google.common.base.Preconditions;
+import org.apache.gravitino.annotation.Evolving;
+
+/**
+ * A list of visible tags and whether authorization filtering omitted other 
tags.
+ *
+ * @param <T> The type of the returned tag names or tag objects.
+ */
+@Evolving
+public final class TagList<T> {
+
+  private final T[] tags;
+  private final boolean hasInaccessibleTags;
+
+  /**
+   * Creates a tag list.
+   *
+   * @param tags The visible tag names or tag objects.
+   * @param hasInaccessibleTags Whether one or more inaccessible tags were 
omitted.
+   */
+  public TagList(T[] tags, boolean hasInaccessibleTags) {
+    Preconditions.checkArgument(tags != null, "Tags must not be null");
+    this.tags = tags.clone();
+    this.hasInaccessibleTags = hasInaccessibleTags;
+  }
+
+  /**
+   * @return The visible tag names or tag objects.
+   */
+  public T[] tags() {
+    return tags.clone();
+  }
+
+  /**
+   * @return True if one or more inaccessible tags were omitted, false 
otherwise.
+   */
+  public boolean hasInaccessibleTags() {
+    return hasInaccessibleTags;
+  }
+}
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/BaseSchemaCatalog.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/BaseSchemaCatalog.java
index ca4b17ce0c..5fc840852f 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/BaseSchemaCatalog.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/BaseSchemaCatalog.java
@@ -54,12 +54,14 @@ import org.apache.gravitino.function.FunctionChange;
 import org.apache.gravitino.function.FunctionDefinition;
 import org.apache.gravitino.function.FunctionType;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.rest.RESTUtils;
 import org.apache.gravitino.secret.SecretBinding;
 import org.apache.gravitino.secret.SecretReference;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /**
@@ -311,11 +313,21 @@ abstract class BaseSchemaCatalog extends CatalogDTO
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) {
     return objectTagOperations.getTag(name);
@@ -336,11 +348,21 @@ abstract class BaseSchemaCatalog extends CatalogDTO
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   @Override
   public String[] listBindingRoleNames() {
     return objectRoleOperations.listBindingRoleNames();
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericColumn.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericColumn.java
index c7845db865..70994dcfd3 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericColumn.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericColumn.java
@@ -29,6 +29,7 @@ import org.apache.gravitino.rel.expressions.Expression;
 import org.apache.gravitino.rel.types.Type;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic column. */
@@ -63,11 +64,21 @@ public class GenericColumn implements Column, SupportsTags {
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFileset.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFileset.java
index 844621573d..c442ceb514 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFileset.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFileset.java
@@ -33,10 +33,12 @@ import org.apache.gravitino.dto.file.FilesetDTO;
 import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.file.Fileset;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.secret.SupportsSecrets;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic fileset. */
@@ -134,11 +136,21 @@ class GenericFileset
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
@@ -159,11 +171,21 @@ class GenericFileset
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   @Override
   public String[] listBindingRoleNames() {
     return objectRoleOperations.listBindingRoleNames();
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFunction.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFunction.java
index 2bb58b7ec3..a2f6eb1e7f 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFunction.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericFunction.java
@@ -32,6 +32,7 @@ import org.apache.gravitino.function.FunctionDefinition;
 import org.apache.gravitino.function.FunctionType;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic function. */
@@ -91,11 +92,21 @@ class GenericFunction implements Function, SupportsTags {
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModel.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModel.java
index f12177af4d..1967661785 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModel.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModel.java
@@ -31,10 +31,12 @@ import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.exceptions.TagAlreadyAssociatedException;
 import org.apache.gravitino.model.Model;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.secret.SupportsSecrets;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic model. */
@@ -132,11 +134,21 @@ class GenericModel implements Model, SupportsTags, 
SupportsPolicies, SupportsSec
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
@@ -158,8 +170,18 @@ class GenericModel implements Model, SupportsTags, 
SupportsPolicies, SupportsSec
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
+
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
 }
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSchema.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSchema.java
index 756e0640ab..348df64662 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSchema.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSchema.java
@@ -28,10 +28,12 @@ import org.apache.gravitino.authorization.SupportsRoles;
 import org.apache.gravitino.dto.SchemaDTO;
 import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.secret.SupportsSecrets;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic schema. */
@@ -108,11 +110,21 @@ class GenericSchema
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
@@ -133,11 +145,21 @@ class GenericSchema
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   @Override
   public String[] listBindingRoleNames() {
     return objectRoleOperations.listBindingRoleNames();
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSemanticModel.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSemanticModel.java
index e64d1483fc..f5074a30dc 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSemanticModel.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericSemanticModel.java
@@ -29,11 +29,13 @@ import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.MetadataObjects;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.semantic.SemanticModel;
 import org.apache.gravitino.semantic.SemanticModelDefinition;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** An immutable client-side Semantic Model returned by the Gravitino REST 
API. */
@@ -120,12 +122,24 @@ class GenericSemanticModel implements SemanticModel, 
SupportsTags, SupportsPolic
     return objectTagOperations.listTags();
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   /** {@inheritDoc} */
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   /** {@inheritDoc} */
   @Override
   public Tag getTag(String name) {
@@ -150,12 +164,24 @@ class GenericSemanticModel implements SemanticModel, 
SupportsTags, SupportsPolic
     return objectPolicyOperations.listPolicies();
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   /** {@inheritDoc} */
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   /** {@inheritDoc} */
   @Override
   public boolean equals(Object other) {
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericTopic.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericTopic.java
index 6ed87337eb..c8b3a80bac 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericTopic.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericTopic.java
@@ -30,10 +30,12 @@ import org.apache.gravitino.dto.messaging.TopicDTO;
 import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.messaging.Topic;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.secret.SupportsSecrets;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic topic. */
@@ -112,11 +114,21 @@ class GenericTopic
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
@@ -137,11 +149,21 @@ class GenericTopic
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   @Override
   public String[] listBindingRoleNames() {
     return objectRoleOperations.listBindingRoleNames();
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericView.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericView.java
index 7b0a0b6921..f4b1e9e935 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericView.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericView.java
@@ -34,6 +34,7 @@ import org.apache.gravitino.rel.View;
 import org.apache.gravitino.secret.SupportsSecrets;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a generic view. */
@@ -115,11 +116,21 @@ class GenericView implements View, SupportsTags, 
SupportsSecrets {
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectPolicyOperations.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectPolicyOperations.java
index 79292cee44..6028b3005d 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectPolicyOperations.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectPolicyOperations.java
@@ -23,9 +23,10 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Locale;
 import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.PolicyListResponse;
+import org.apache.gravitino.dto.responses.MetadataObjectPolicyListResponse;
+import org.apache.gravitino.dto.responses.PolicyNameListResponse;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.rest.RESTUtils;
 
@@ -52,30 +53,40 @@ class MetadataObjectPolicyOperations implements 
SupportsPolicies {
 
   @Override
   public String[] listPolicies() {
-    NameListResponse resp =
+    return listPoliciesWithVisibility().policies();
+  }
+
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    PolicyNameListResponse resp =
         restClient.get(
             policyRequestPath,
-            NameListResponse.class,
+            PolicyNameListResponse.class,
             Collections.emptyMap(),
             ErrorHandlers.policyErrorHandler());
 
     resp.validate();
-    return resp.getNames();
+    return new PolicyList<>(resp.getNames(), resp.hasInaccessiblePolicies());
   }
 
   @Override
   public Policy[] listPolicyInfos() {
-    PolicyListResponse resp =
+    return listPolicyInfosWithVisibility().policies();
+  }
+
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    MetadataObjectPolicyListResponse resp =
         restClient.get(
             policyRequestPath,
             ImmutableMap.of("details", "true"),
-            PolicyListResponse.class,
+            MetadataObjectPolicyListResponse.class,
             Collections.emptyMap(),
             ErrorHandlers.policyErrorHandler());
 
     resp.validate();
-    return Arrays.stream(resp.getPolicies())
-        .map(policyDTO -> new GenericPolicy(policyDTO))
-        .toArray(Policy[]::new);
+    Policy[] policies =
+        
Arrays.stream(resp.getPolicies()).map(GenericPolicy::new).toArray(Policy[]::new);
+    return new PolicyList<>(policies, resp.hasInaccessiblePolicies());
   }
 }
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectTagOperations.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectTagOperations.java
index c504c9a212..d29a82c4e7 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectTagOperations.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/MetadataObjectTagOperations.java
@@ -27,13 +27,15 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.dto.requests.TagValuesAssociateRequest;
 import org.apache.gravitino.dto.requests.TagsAssociateRequest;
+import org.apache.gravitino.dto.responses.MetadataObjectTagListResponse;
 import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.TagListResponse;
+import org.apache.gravitino.dto.responses.TagNameListResponse;
 import org.apache.gravitino.dto.responses.TagResponse;
 import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.rest.RESTUtils;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 import org.apache.hc.core5.http.HttpHeaders;
 
@@ -65,31 +67,43 @@ class MetadataObjectTagOperations implements SupportsTags {
 
   @Override
   public String[] listTags() {
-    NameListResponse resp =
+    return listTagsWithVisibility().tags();
+  }
+
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    TagNameListResponse resp =
         restClient.get(
             tagRequestPath,
-            NameListResponse.class,
+            TagNameListResponse.class,
             Collections.emptyMap(),
             ErrorHandlers.tagErrorHandler());
 
     resp.validate();
-    return resp.getNames();
+    return new TagList<>(resp.getNames(), resp.hasInaccessibleTags());
   }
 
   @Override
   public Tag[] listTagsInfo() {
-    TagListResponse resp =
+    return listTagsInfoWithVisibility().tags();
+  }
+
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    MetadataObjectTagListResponse resp =
         restClient.get(
             tagRequestPath,
             ImmutableMap.of("details", "true"),
-            TagListResponse.class,
+            MetadataObjectTagListResponse.class,
             Collections.emptyMap(),
             ErrorHandlers.tagErrorHandler());
 
     resp.validate();
-    return Arrays.stream(resp.getTags())
-        .map(tagDTO -> new GenericTag(tagDTO, restClient, metalakeName))
-        .toArray(Tag[]::new);
+    Tag[] tags =
+        Arrays.stream(resp.getTags())
+            .map(tagDTO -> new GenericTag(tagDTO, restClient, metalakeName))
+            .toArray(Tag[]::new);
+    return new TagList<>(tags, resp.hasInaccessibleTags());
   }
 
   @Override
diff --git 
a/clients/client-java/src/main/java/org/apache/gravitino/client/RelationalTable.java
 
b/clients/client-java/src/main/java/org/apache/gravitino/client/RelationalTable.java
index 36348080e2..b2eb7b627c 100644
--- 
a/clients/client-java/src/main/java/org/apache/gravitino/client/RelationalTable.java
+++ 
b/clients/client-java/src/main/java/org/apache/gravitino/client/RelationalTable.java
@@ -47,6 +47,7 @@ import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.exceptions.PartitionAlreadyExistsException;
 import org.apache.gravitino.exceptions.UnmodifiableStatisticException;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.rel.Column;
 import org.apache.gravitino.rel.SupportsPartitions;
@@ -68,6 +69,7 @@ import org.apache.gravitino.stats.SupportsPartitionStatistics;
 import org.apache.gravitino.stats.SupportsStatistics;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 
 /** Represents a relational table. */
@@ -391,11 +393,21 @@ class RelationalTable
     return objectTagOperations.listTags();
   }
 
+  @Override
+  public TagList<String> listTagsWithVisibility() {
+    return objectTagOperations.listTagsWithVisibility();
+  }
+
   @Override
   public Tag[] listTagsInfo() {
     return objectTagOperations.listTagsInfo();
   }
 
+  @Override
+  public TagList<Tag> listTagsInfoWithVisibility() {
+    return objectTagOperations.listTagsInfoWithVisibility();
+  }
+
   @Override
   public Tag getTag(String name) throws NoSuchTagException {
     return objectTagOperations.getTag(name);
@@ -416,11 +428,21 @@ class RelationalTable
     return objectPolicyOperations.listPolicies();
   }
 
+  @Override
+  public PolicyList<String> listPoliciesWithVisibility() {
+    return objectPolicyOperations.listPoliciesWithVisibility();
+  }
+
   @Override
   public Policy[] listPolicyInfos() {
     return objectPolicyOperations.listPolicyInfos();
   }
 
+  @Override
+  public PolicyList<Policy> listPolicyInfosWithVisibility() {
+    return objectPolicyOperations.listPolicyInfosWithVisibility();
+  }
+
   @Override
   public String[] listBindingRoleNames() {
     return objectRoleOperations.listBindingRoleNames();
diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportPolicies.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportPolicies.java
index a2033f306f..2e05dac76e 100644
--- 
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportPolicies.java
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportPolicies.java
@@ -44,14 +44,15 @@ import org.apache.gravitino.dto.policy.PolicyDTO;
 import org.apache.gravitino.dto.rel.ColumnDTO;
 import org.apache.gravitino.dto.rel.TableDTO;
 import org.apache.gravitino.dto.responses.ErrorResponse;
-import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.PolicyListResponse;
+import org.apache.gravitino.dto.responses.MetadataObjectPolicyListResponse;
+import org.apache.gravitino.dto.responses.PolicyNameListResponse;
 import org.apache.gravitino.dto.semantic.SemanticModelDTO;
 import org.apache.gravitino.dto.semantic.SemanticModelDefinitionDTO;
 import org.apache.gravitino.exceptions.NotFoundException;
 import org.apache.gravitino.file.Fileset;
 import org.apache.gravitino.messaging.Topic;
 import org.apache.gravitino.policy.Policy;
+import org.apache.gravitino.policy.PolicyList;
 import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.rel.Table;
 import org.apache.gravitino.rel.types.Types;
@@ -320,14 +321,15 @@ public class TestSupportPolicies extends TestBase {
             + "/policies";
 
     String[] policies = new String[] {"policy1", "policy2"};
-    NameListResponse resp = new NameListResponse(policies);
+    PolicyNameListResponse resp = new PolicyNameListResponse(policies, true);
     buildMockResource(Method.GET, path, null, resp, SC_OK);
 
-    String[] actualPolicies = supportsPolicies.listPolicies();
-    Assertions.assertArrayEquals(policies, actualPolicies);
+    PolicyList<String> policyList = 
supportsPolicies.listPoliciesWithVisibility();
+    Assertions.assertArrayEquals(policies, policyList.policies());
+    Assertions.assertTrue(policyList.hasInaccessiblePolicies());
 
     // Return empty list
-    NameListResponse resp1 = new NameListResponse(new String[0]);
+    PolicyNameListResponse resp1 = new PolicyNameListResponse(new String[0], 
false);
     buildMockResource(Method.GET, path, null, resp1, SC_OK);
 
     String[] actualPolicies1 = supportsPolicies.listPolicies();
@@ -378,19 +380,22 @@ public class TestSupportPolicies extends TestBase {
             .withAudit(AuditDTO.builder().withCreator("test").build())
             .build();
     PolicyDTO[] policies = new PolicyDTO[] {policy1, policy2};
-    PolicyListResponse resp = new PolicyListResponse(policies);
+    MetadataObjectPolicyListResponse resp = new 
MetadataObjectPolicyListResponse(policies, true);
     buildMockResource(
         Method.GET, path, Collections.singletonMap("details", "true"), null, 
resp, SC_OK);
 
-    Policy[] actualPolicies = supportsPolicies.listPolicyInfos();
+    PolicyList<Policy> policyList = 
supportsPolicies.listPolicyInfosWithVisibility();
+    Policy[] actualPolicies = policyList.policies();
     Assertions.assertEquals(2, actualPolicies.length);
     Assertions.assertEquals("policy1", actualPolicies[0].name());
     Assertions.assertEquals("policy2", actualPolicies[1].name());
     Assertions.assertFalse(actualPolicies[0].inherited().orElseThrow());
     Assertions.assertTrue(actualPolicies[1].inherited().orElseThrow());
+    Assertions.assertTrue(policyList.hasInaccessiblePolicies());
 
     // Return empty list
-    PolicyListResponse resp1 = new PolicyListResponse(new PolicyDTO[0]);
+    MetadataObjectPolicyListResponse resp1 =
+        new MetadataObjectPolicyListResponse(new PolicyDTO[0], false);
     buildMockResource(
         Method.GET, path, Collections.singletonMap("details", "true"), null, 
resp1, SC_OK);
 
diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportTags.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportTags.java
index 446fd2bf61..a2c2811106 100644
--- 
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportTags.java
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestSupportTags.java
@@ -46,8 +46,9 @@ import org.apache.gravitino.dto.rel.ViewDTO;
 import org.apache.gravitino.dto.requests.TagValuesAssociateRequest;
 import org.apache.gravitino.dto.requests.TagsAssociateRequest;
 import org.apache.gravitino.dto.responses.ErrorResponse;
+import org.apache.gravitino.dto.responses.MetadataObjectTagListResponse;
 import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.TagListResponse;
+import org.apache.gravitino.dto.responses.TagNameListResponse;
 import org.apache.gravitino.dto.responses.TagResponse;
 import org.apache.gravitino.dto.semantic.SemanticModelDTO;
 import org.apache.gravitino.dto.semantic.SemanticModelDefinitionDTO;
@@ -68,6 +69,7 @@ import org.apache.gravitino.semantic.SemanticModel;
 import org.apache.gravitino.semantic.SemanticModelDefinition;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.Tag;
+import org.apache.gravitino.tag.TagList;
 import org.apache.gravitino.tag.TagValue;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.Method;
@@ -582,14 +584,15 @@ public class TestSupportTags extends TestBase {
             + "/tags";
 
     String[] tags = new String[] {"tag1", "tag2"};
-    NameListResponse resp = new NameListResponse(tags);
+    TagNameListResponse resp = new TagNameListResponse(tags, true);
     buildMockResource(Method.GET, path, null, resp, SC_OK);
 
-    String[] actualTags = supportsTags.listTags();
-    Assertions.assertArrayEquals(tags, actualTags);
+    TagList<String> tagList = supportsTags.listTagsWithVisibility();
+    Assertions.assertArrayEquals(tags, tagList.tags());
+    Assertions.assertTrue(tagList.hasInaccessibleTags());
 
     // Return empty list
-    NameListResponse resp1 = new NameListResponse(new String[0]);
+    TagNameListResponse resp1 = new TagNameListResponse(new String[0], false);
     buildMockResource(Method.GET, path, null, resp1, SC_OK);
 
     String[] actualTags1 = supportsTags.listTags();
@@ -633,16 +636,18 @@ public class TestSupportTags extends TestBase {
             .withAudit(AuditDTO.builder().withCreator("test").build())
             .build();
     TagDTO[] tags = new TagDTO[] {tag1, tag2};
-    TagListResponse resp = new TagListResponse(tags);
+    MetadataObjectTagListResponse resp = new 
MetadataObjectTagListResponse(tags, true);
     buildMockResource(Method.GET, path, null, resp, SC_OK);
 
-    Tag[] actualTags = supportsTags.listTagsInfo();
+    TagList<Tag> tagList = supportsTags.listTagsInfoWithVisibility();
+    Tag[] actualTags = tagList.tags();
     Assertions.assertEquals(2, actualTags.length);
     Assertions.assertEquals("tag1", actualTags[0].name());
     Assertions.assertEquals("tag2", actualTags[1].name());
+    Assertions.assertTrue(tagList.hasInaccessibleTags());
 
     // Return empty list
-    TagListResponse resp1 = new TagListResponse(new TagDTO[0]);
+    MetadataObjectTagListResponse resp1 = new 
MetadataObjectTagListResponse(new TagDTO[0], false);
     buildMockResource(Method.GET, path, null, resp1, SC_OK);
 
     Tag[] actualTags1 = supportsTags.listTagsInfo();
diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/PolicyAuthorizationIT.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/PolicyAuthorizationIT.java
index dc8ec96d0b..754b975cb7 100644
--- 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/PolicyAuthorizationIT.java
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/PolicyAuthorizationIT.java
@@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -42,6 +43,8 @@ import 
org.apache.gravitino.integration.test.container.ContainerSuite;
 import org.apache.gravitino.integration.test.container.HiveContainer;
 import org.apache.gravitino.policy.PolicyChange;
 import org.apache.gravitino.policy.PolicyContents;
+import org.apache.gravitino.policy.PolicyList;
+import org.apache.gravitino.policy.SupportsPolicies;
 import org.apache.gravitino.rel.Column;
 import org.apache.gravitino.rel.TableCatalog;
 import org.apache.gravitino.rel.types.Types;
@@ -212,6 +215,73 @@ public class PolicyAuthorizationIT extends 
BaseRestApiAuthorizationIT {
     metalakeLoadByNormalUser.alterPolicy("policy2", 
PolicyChange.updateComment("222"));
   }
 
+  @Test
+  @Order(5)
+  public void testListPoliciesByMetadataObjectVisibility() throws Exception {
+    String hiddenTag = "hidden_policy_tag";
+    String visibleTag = "visible_policy_tag";
+    String allHiddenTable = "all_hidden_policy_table";
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    TableCatalog tableCatalog = 
gravitinoMetalake.loadCatalog(CATALOG).asTableCatalog();
+
+    gravitinoMetalake.grantPrivilegesToRole(
+        role,
+        MetadataObjects.of(ImmutableList.of(CATALOG, SCHEMA), 
MetadataObject.Type.SCHEMA),
+        ImmutableList.of(Privileges.SelectTable.allow(), 
Privileges.UseSchema.allow()));
+    tableCatalog.createTable(
+        NameIdentifier.of(SCHEMA, allHiddenTable),
+        createColumns(),
+        "test policy visibility indicators",
+        new HashMap<>());
+    gravitinoMetalake.createTag(hiddenTag, "hidden policy tag", Map.of());
+    gravitinoMetalake.createTag(visibleTag, "visible policy tag", Map.of());
+    gravitinoMetalake.addPolicyForTag(hiddenTag, "policy1");
+    gravitinoMetalake.addPolicyForTag(visibleTag, "policy2");
+
+    try {
+      tableCatalog
+          .loadTable(NameIdentifier.of(SCHEMA, allHiddenTable))
+          .supportsTags()
+          .associateTags(new String[] {hiddenTag}, null);
+      tableCatalog
+          .loadTable(NameIdentifier.of(SCHEMA, "table1"))
+          .supportsTags()
+          .associateTags(new String[] {hiddenTag, visibleTag}, null);
+
+      SupportsPolicies allHiddenPolicies =
+          normalUserClient
+              .loadMetalake(METALAKE)
+              .loadCatalog(CATALOG)
+              .asTableCatalog()
+              .loadTable(NameIdentifier.of(SCHEMA, allHiddenTable))
+              .supportsPolicies();
+      assertPolicyList(allHiddenPolicies, new String[0], true);
+
+      SupportsPolicies mixedPolicies =
+          normalUserClient
+              .loadMetalake(METALAKE)
+              .loadCatalog(CATALOG)
+              .asTableCatalog()
+              .loadTable(NameIdentifier.of(SCHEMA, "table1"))
+              .supportsPolicies();
+      assertPolicyList(mixedPolicies, new String[] {"policy2"}, true);
+    } finally {
+      tableCatalog
+          .loadTable(NameIdentifier.of(SCHEMA, allHiddenTable))
+          .supportsTags()
+          .associateTags(null, new String[] {hiddenTag});
+      tableCatalog
+          .loadTable(NameIdentifier.of(SCHEMA, "table1"))
+          .supportsTags()
+          .associateTags(null, new String[] {hiddenTag, visibleTag});
+      gravitinoMetalake.removePolicyFromTag(hiddenTag, "policy1");
+      gravitinoMetalake.removePolicyFromTag(visibleTag, "policy2");
+      gravitinoMetalake.deleteTag(hiddenTag);
+      gravitinoMetalake.deleteTag(visibleTag);
+      tableCatalog.dropTable(NameIdentifier.of(SCHEMA, allHiddenTable));
+    }
+  }
+
   @Test
   @Order(10)
   public void testDropPolicy() {
@@ -226,4 +296,23 @@ public class PolicyAuthorizationIT extends 
BaseRestApiAuthorizationIT {
     gravitinoMetalake.deletePolicy("policy1");
     metalakeLoadByNormalUser.deletePolicy("policy2");
   }
+
+  private void assertPolicyList(
+      SupportsPolicies supportsPolicies,
+      String[] expectedPolicyNames,
+      boolean hasInaccessiblePolicies) {
+    PolicyList<String> nameResult = 
supportsPolicies.listPoliciesWithVisibility();
+    String[] actualPolicyNames = nameResult.policies();
+    Arrays.sort(actualPolicyNames);
+    Arrays.sort(expectedPolicyNames);
+    Assertions.assertArrayEquals(expectedPolicyNames, actualPolicyNames);
+    Assertions.assertEquals(hasInaccessiblePolicies, 
nameResult.hasInaccessiblePolicies());
+
+    var detailsResult = supportsPolicies.listPolicyInfosWithVisibility();
+    String[] actualDetailNames =
+        Arrays.stream(detailsResult.policies()).map(policy -> 
policy.name()).toArray(String[]::new);
+    Arrays.sort(actualDetailNames);
+    Assertions.assertArrayEquals(expectedPolicyNames, actualDetailNames);
+    Assertions.assertEquals(hasInaccessiblePolicies, 
detailsResult.hasInaccessiblePolicies());
+  }
 }
diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/TagOperationsAuthorizationIT.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/TagOperationsAuthorizationIT.java
index 01780d8bee..6c76d0fdd9 100644
--- 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/TagOperationsAuthorizationIT.java
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/TagOperationsAuthorizationIT.java
@@ -48,6 +48,7 @@ import org.apache.gravitino.rel.TableCatalog;
 import org.apache.gravitino.rel.types.Types;
 import org.apache.gravitino.tag.SupportsTags;
 import org.apache.gravitino.tag.TagChange;
+import org.apache.gravitino.tag.TagList;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -281,6 +282,49 @@ public class TagOperationsAuthorizationIT extends 
BaseRestApiAuthorizationIT {
     String[] tagsLoadByNormalUser = tableSupportTagByNormalUser.listTags();
     Arrays.sort(tagsLoadByNormalUser);
     assertArrayEquals(new String[] {"tag2", "tag3"}, tagsLoadByNormalUser);
+
+    TagList<String> nameResult = 
tableSupportTagByNormalUser.listTagsWithVisibility();
+    Assertions.assertEquals(2, nameResult.tags().length);
+    Assertions.assertTrue(nameResult.hasInaccessibleTags());
+
+    var detailsResult = 
tableSupportTagByNormalUser.listTagsInfoWithVisibility();
+    Assertions.assertEquals(2, detailsResult.tags().length);
+    Assertions.assertTrue(detailsResult.hasInaccessibleTags());
+
+    String untaggedCatalog = "untagged_catalog";
+    Map<String, String> properties = Maps.newHashMap();
+    properties.put("metastore.uris", hmsUri);
+    gravitinoMetalake.createCatalog(
+        untaggedCatalog, Catalog.Type.RELATIONAL, "hive", "untagged catalog", 
properties);
+    gravitinoMetalake.grantPrivilegesToRole(
+        role,
+        MetadataObjects.of(ImmutableList.of(untaggedCatalog), 
MetadataObject.Type.CATALOG),
+        ImmutableList.of(Privileges.UseCatalog.allow()));
+
+    String tableWithOnlyInheritedHiddenTag = 
"table_with_only_inherited_hidden_tag";
+    TableCatalog tableCatalog = 
gravitinoMetalake.loadCatalog(CATALOG).asTableCatalog();
+    tableCatalog.createTable(
+        NameIdentifier.of(SCHEMA, tableWithOnlyInheritedHiddenTag),
+        createColumns(),
+        "test visibility indicators",
+        new HashMap<>());
+    try {
+      SupportsTags untaggedCatalogTags =
+          
normalUserClient.loadMetalake(METALAKE).loadCatalog(untaggedCatalog).supportsTags();
+      assertTagList(untaggedCatalogTags, new String[0], false);
+
+      SupportsTags inheritedHiddenTags =
+          normalUserClient
+              .loadMetalake(METALAKE)
+              .loadCatalog(CATALOG)
+              .asTableCatalog()
+              .loadTable(NameIdentifier.of(SCHEMA, 
tableWithOnlyInheritedHiddenTag))
+              .supportsTags();
+      assertTagList(inheritedHiddenTags, new String[0], true);
+    } finally {
+      tableCatalog.dropTable(NameIdentifier.of(SCHEMA, 
tableWithOnlyInheritedHiddenTag));
+      gravitinoMetalake.dropCatalog(untaggedCatalog, true);
+    }
   }
 
   @Test
@@ -467,4 +511,21 @@ public class TagOperationsAuthorizationIT extends 
BaseRestApiAuthorizationIT {
   private Column[] createColumns() {
     return new Column[] {Column.of("col1", Types.StringType.get())};
   }
+
+  private void assertTagList(
+      SupportsTags supportsTags, String[] expectedTagNames, boolean 
hasInaccessibleTags) {
+    TagList<String> nameResult = supportsTags.listTagsWithVisibility();
+    String[] actualTagNames = nameResult.tags();
+    Arrays.sort(actualTagNames);
+    Arrays.sort(expectedTagNames);
+    Assertions.assertArrayEquals(expectedTagNames, actualTagNames);
+    Assertions.assertEquals(hasInaccessibleTags, 
nameResult.hasInaccessibleTags());
+
+    var detailsResult = supportsTags.listTagsInfoWithVisibility();
+    String[] actualDetailNames =
+        Arrays.stream(detailsResult.tags()).map(tag -> 
tag.name()).toArray(String[]::new);
+    Arrays.sort(actualDetailNames);
+    Assertions.assertArrayEquals(expectedTagNames, actualDetailNames);
+    Assertions.assertEquals(hasInaccessibleTags, 
detailsResult.hasInaccessibleTags());
+  }
 }
diff --git a/clients/client-python/gravitino/api/tag/__init__.py 
b/clients/client-python/gravitino/api/tag/__init__.py
index 28b1469c2f..f464455d71 100644
--- a/clients/client-python/gravitino/api/tag/__init__.py
+++ b/clients/client-python/gravitino/api/tag/__init__.py
@@ -19,8 +19,10 @@ from __future__ import annotations
 
 from gravitino.api.tag.tag import Tag
 from gravitino.api.tag.tag_change import TagChange
+from gravitino.api.tag.tag_list import TagList
 
 __all__ = [
     "Tag",
     "TagChange",
+    "TagList",
 ]
diff --git a/clients/client-python/gravitino/api/tag/supports_tags.py 
b/clients/client-python/gravitino/api/tag/supports_tags.py
index 2e926fe1eb..e8d32474b3 100644
--- a/clients/client-python/gravitino/api/tag/supports_tags.py
+++ b/clients/client-python/gravitino/api/tag/supports_tags.py
@@ -20,6 +20,7 @@ from __future__ import annotations
 from abc import ABC, abstractmethod
 
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.exceptions.base import UnsupportedOperationException
 
 
@@ -38,6 +39,14 @@ class SupportsTags(ABC):
         """
         pass
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        """List visible tag names and report whether inaccessible tags were 
omitted.
+
+        The compatibility default cannot detect omitted tags. Implementations 
backed by
+        authorization-aware APIs should override this method.
+        """
+        return TagList(self.list_tags(), False)
+
     @abstractmethod
     def list_tags_info(self) -> list[Tag]:
         """List all the tags with details for the specific object.
@@ -47,6 +56,14 @@ class SupportsTags(ABC):
         """
         pass
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        """List visible tag details and report whether inaccessible tags were 
omitted.
+
+        The compatibility default cannot detect omitted tags. Implementations 
backed by
+        authorization-aware APIs should override this method.
+        """
+        return TagList(self.list_tags_info(), False)
+
     @abstractmethod
     def get_tag(self, name: str) -> Tag:
         """Get a tag by its name for the specific object.
diff --git a/clients/client-python/gravitino/api/tag/__init__.py 
b/clients/client-python/gravitino/api/tag/tag_list.py
similarity index 56%
copy from clients/client-python/gravitino/api/tag/__init__.py
copy to clients/client-python/gravitino/api/tag/tag_list.py
index 28b1469c2f..e7ed58ac17 100644
--- a/clients/client-python/gravitino/api/tag/__init__.py
+++ b/clients/client-python/gravitino/api/tag/tag_list.py
@@ -17,10 +17,22 @@
 
 from __future__ import annotations
 
-from gravitino.api.tag.tag import Tag
-from gravitino.api.tag.tag_change import TagChange
+from typing import Generic, TypeVar
 
-__all__ = [
-    "Tag",
-    "TagChange",
-]
+T = TypeVar("T")
+
+
+class TagList(Generic[T]):
+    """A list of visible tags and whether authorization filtering omitted 
others."""
+
+    def __init__(self, tags: list[T], has_inaccessible_tags: bool):
+        self._tags = list(tags)
+        self._has_inaccessible_tags = has_inaccessible_tags
+
+    def tags(self) -> list[T]:
+        """Return a copy of the visible tag names or tag objects."""
+        return list(self._tags)
+
+    def has_inaccessible_tags(self) -> bool:
+        """Return whether one or more inaccessible tags were omitted."""
+        return self._has_inaccessible_tags
diff --git a/clients/client-python/gravitino/client/base_schema_catalog.py 
b/clients/client-python/gravitino/client/base_schema_catalog.py
index 66483a3dac..39fe4fa1fe 100644
--- a/clients/client-python/gravitino/client/base_schema_catalog.py
+++ b/clients/client-python/gravitino/client/base_schema_catalog.py
@@ -34,6 +34,7 @@ from gravitino.api.secret import SecretBinding, 
SecretReference
 from gravitino.api.supports_schemas import SupportsSchemas
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.function_catalog_operations import 
FunctionCatalogOperations
 from gravitino.client.generic_schema import GenericSchema
 from gravitino.client.metadata_object_credential_operations import (
@@ -402,9 +403,15 @@ class BaseSchemaCatalog(
     def list_tags(self) -> List[str]:
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> List[Tag]:
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._object_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_column.py 
b/clients/client-python/gravitino/client/generic_column.py
index 79ea04020f..96995238c2 100644
--- a/clients/client-python/gravitino/client/generic_column.py
+++ b/clients/client-python/gravitino/client/generic_column.py
@@ -24,6 +24,7 @@ from gravitino.api.rel.expressions.expression import 
Expression
 from gravitino.api.rel.types.type import Type
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_tag_operations import 
MetadataObjectTagOperations
 from gravitino.utils import HTTPClient
 
@@ -84,9 +85,15 @@ class GenericColumn(Column, SupportsTags):
     def list_tags(self) -> list[str]:
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._object_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_fileset.py 
b/clients/client-python/gravitino/client/generic_fileset.py
index 750627288e..c4ed5569b2 100644
--- a/clients/client-python/gravitino/client/generic_fileset.py
+++ b/clients/client-python/gravitino/client/generic_fileset.py
@@ -19,12 +19,13 @@ from typing import Dict, List, Optional
 from gravitino.api.authorization.supports_roles import SupportsRoles
 from gravitino.api.credential.credential import Credential
 from gravitino.api.credential.supports_credentials import SupportsCredentials
-from gravitino.api.secret.supports_secrets import SupportsSecrets
 from gravitino.api.file.fileset import Fileset
 from gravitino.api.metadata_object import MetadataObject
 from gravitino.api.metadata_objects import MetadataObjects
+from gravitino.api.secret.supports_secrets import SupportsSecrets
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_credential_operations import (
     MetadataObjectCredentialOperations,
 )
@@ -120,9 +121,15 @@ class GenericFileset(
     def list_tags(self) -> List[str]:
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> List[Tag]:
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._object_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_function.py 
b/clients/client-python/gravitino/client/generic_function.py
index 66faaa939f..5230640859 100644
--- a/clients/client-python/gravitino/client/generic_function.py
+++ b/clients/client-python/gravitino/client/generic_function.py
@@ -24,6 +24,7 @@ from gravitino.api.metadata_object import MetadataObject
 from gravitino.api.metadata_objects import MetadataObjects
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_tag_operations import 
MetadataObjectTagOperations
 from gravitino.dto.audit_dto import AuditDTO
 from gravitino.dto.function.function_dto import FunctionDTO
@@ -90,10 +91,18 @@ class GenericFunction(Function, SupportsTags):
         """List the tag names associated with the function."""
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        """List visible tag names and authorization-filtering status."""
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         """List the tags associated with the function."""
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        """List visible tag details and authorization-filtering status."""
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         """Get an associated tag by name."""
         return self._object_tag_operations.get_tag(name)
diff --git a/clients/client-python/gravitino/client/generic_model.py 
b/clients/client-python/gravitino/client/generic_model.py
index 9a99e21bc6..9ca708eb20 100644
--- a/clients/client-python/gravitino/client/generic_model.py
+++ b/clients/client-python/gravitino/client/generic_model.py
@@ -24,7 +24,7 @@ from gravitino.api.metadata_object import MetadataObject
 from gravitino.api.metadata_objects import MetadataObjects
 from gravitino.api.model.model import Model
 from gravitino.api.secret.supports_secrets import SupportsSecrets
-from gravitino.api.tag import Tag
+from gravitino.api.tag import Tag, TagList
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.client.metadata_object_secret_operations import (
     MetadataObjectSecretOperations,
@@ -83,9 +83,15 @@ class GenericModel(Model, SupportsTags, SupportsSecrets):
     def list_tags(self) -> list[str]:
         return self._model_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._model_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._model_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._model_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._model_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_schema.py 
b/clients/client-python/gravitino/client/generic_schema.py
index a14944d29a..e3cd6b45bb 100644
--- a/clients/client-python/gravitino/client/generic_schema.py
+++ b/clients/client-python/gravitino/client/generic_schema.py
@@ -27,6 +27,7 @@ from gravitino.api.schema import Schema
 from gravitino.api.secret.supports_secrets import SupportsSecrets
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_role_operations import (
     MetadataObjectRoleOperations,
 )
@@ -99,9 +100,15 @@ class GenericSchema(
     def list_tags(self) -> list[str]:
         return self._metadata_object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._metadata_object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._metadata_object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return 
self._metadata_object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._metadata_object_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_semantic_model.py 
b/clients/client-python/gravitino/client/generic_semantic_model.py
index 950618d5c6..08251dacea 100644
--- a/clients/client-python/gravitino/client/generic_semantic_model.py
+++ b/clients/client-python/gravitino/client/generic_semantic_model.py
@@ -24,6 +24,7 @@ from gravitino.api.semantic.semantic_model import 
SemanticModel
 from gravitino.api.semantic.semantic_model_definition import 
SemanticModelDefinition
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_tag_operations import 
MetadataObjectTagOperations
 from gravitino.dto.semantic.semantic_model_dto import SemanticModelDTO
 from gravitino.namespace import Namespace
@@ -101,9 +102,15 @@ class GenericSemanticModel(SemanticModel, SupportsTags):
     def list_tags(self) -> list[str]:
         return self._model_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._model_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._model_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._model_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._model_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/client/generic_view.py 
b/clients/client-python/gravitino/client/generic_view.py
index 88a25a671e..0802b6f041 100644
--- a/clients/client-python/gravitino/client/generic_view.py
+++ b/clients/client-python/gravitino/client/generic_view.py
@@ -26,6 +26,7 @@ from gravitino.api.rel.view import View
 from gravitino.api.secret.supports_secrets import SupportsSecrets
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.metadata_object_secret_operations import (
     MetadataObjectSecretOperations,
 )
@@ -98,9 +99,15 @@ class GenericView(View, SupportsTags, SupportsSecrets):
     def list_tags(self) -> list[str]:
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._object_tag_operations.get_tag(name)
 
diff --git 
a/clients/client-python/gravitino/client/metadata_object_tag_operations.py 
b/clients/client-python/gravitino/client/metadata_object_tag_operations.py
index d0883bbc05..76a64bfc60 100644
--- a/clients/client-python/gravitino/client/metadata_object_tag_operations.py
+++ b/clients/client-python/gravitino/client/metadata_object_tag_operations.py
@@ -20,6 +20,7 @@ from __future__ import annotations
 from gravitino.api.metadata_object import MetadataObject
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.generic_tag import GenericTag
 from gravitino.dto.requests.tag_associate_request import (
     TagsAssociateRequest,
@@ -68,6 +69,9 @@ class MetadataObjectTagOperations(SupportsTags):
         )
 
     def list_tags(self) -> list[str]:
+        return self.list_tags_with_visibility().tags()
+
+    def list_tags_with_visibility(self) -> TagList[str]:
         response = self.rest_client.get(
             self.tag_request_path,
             params={},
@@ -78,9 +82,14 @@ class MetadataObjectTagOperations(SupportsTags):
         )
         list_tags_resp.validate()
 
-        return list_tags_resp.tag_names()
+        return TagList(
+            list_tags_resp.tag_names(), list_tags_resp.has_inaccessible_tags()
+        )
 
     def list_tags_info(self) -> list[Tag]:
+        return self.list_tags_info_with_visibility().tags()
+
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
         response = self.rest_client.get(
             self.tag_request_path,
             params={"details": "true"},
@@ -90,14 +99,17 @@ class MetadataObjectTagOperations(SupportsTags):
         list_info_resp = TagListResponse.from_json(response.body, 
infer_missing=True)
         list_info_resp.validate()
 
-        return [
-            GenericTag(
-                self.metalake_name,
-                tag_dto,
-                self.rest_client,
-            )
-            for tag_dto in list_info_resp.tags()
-        ]
+        return TagList(
+            [
+                GenericTag(
+                    self.metalake_name,
+                    tag_dto,
+                    self.rest_client,
+                )
+                for tag_dto in list_info_resp.tags()
+            ],
+            list_info_resp.has_inaccessible_tags(),
+        )
 
     def get_tag(self, name: str) -> Tag:
         Precondition.check_argument(
diff --git a/clients/client-python/gravitino/client/relational_table.py 
b/clients/client-python/gravitino/client/relational_table.py
index 8b81413a51..0ba96431ef 100644
--- a/clients/client-python/gravitino/client/relational_table.py
+++ b/clients/client-python/gravitino/client/relational_table.py
@@ -34,6 +34,7 @@ from gravitino.api.stats.statistic_value import StatisticValue
 from gravitino.api.stats.supports_statistics import SupportsStatistics
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag import Tag
+from gravitino.api.tag.tag_list import TagList
 from gravitino.client.generic_column import GenericColumn
 from gravitino.client.metadata_object_role_operations import (
     MetadataObjectRoleOperations,
@@ -262,9 +263,15 @@ class RelationalTable(
     def list_tags(self) -> list[str]:
         return self._object_tag_operations.list_tags()
 
+    def list_tags_with_visibility(self) -> TagList[str]:
+        return self._object_tag_operations.list_tags_with_visibility()
+
     def list_tags_info(self) -> list[Tag]:
         return self._object_tag_operations.list_tags_info()
 
+    def list_tags_info_with_visibility(self) -> TagList[Tag]:
+        return self._object_tag_operations.list_tags_info_with_visibility()
+
     def get_tag(self, name: str) -> Tag:
         return self._object_tag_operations.get_tag(name)
 
diff --git a/clients/client-python/gravitino/dto/responses/tag_response.py 
b/clients/client-python/gravitino/dto/responses/tag_response.py
index e0dea09e71..d72e9c27e2 100644
--- a/clients/client-python/gravitino/dto/responses/tag_response.py
+++ b/clients/client-python/gravitino/dto/responses/tag_response.py
@@ -20,7 +20,6 @@ from __future__ import annotations
 from dataclasses import dataclass, field
 
 from dataclasses_json import config, dataclass_json
-
 from gravitino.dto.responses.base_response import BaseResponse
 from gravitino.dto.tag_dto import TagDTO
 from gravitino.utils.precondition import Precondition
@@ -32,10 +31,16 @@ class TagNamesListResponse(BaseResponse):
     """Represents a response for a Tag Names List request."""
 
     _tags: list[str] = field(default_factory=list, 
metadata=config(field_name="names"))
+    _has_inaccessible_tags: bool = field(
+        default=False, metadata=config(field_name="hasInaccessibleTags")
+    )
 
     def tag_names(self) -> list[str]:
         return self._tags
 
+    def has_inaccessible_tags(self) -> bool:
+        return self._has_inaccessible_tags
+
     def validate(self) -> None:
         Precondition.check_argument(
             self._tags is not None, "Tag Names List response should have tags"
@@ -55,10 +60,16 @@ class TagListResponse(BaseResponse):
     _tags: list[TagDTO] = field(
         default_factory=list, metadata=config(field_name="tags")
     )
+    _has_inaccessible_tags: bool = field(
+        default=False, metadata=config(field_name="hasInaccessibleTags")
+    )
 
     def tags(self) -> list[TagDTO]:
         return self._tags
 
+    def has_inaccessible_tags(self) -> bool:
+        return self._has_inaccessible_tags
+
 
 @dataclass_json
 @dataclass
diff --git a/clients/client-python/tests/unittests/mock_base.py 
b/clients/client-python/tests/unittests/mock_base.py
index ca247d3170..28648f04d6 100644
--- a/clients/client-python/tests/unittests/mock_base.py
+++ b/clients/client-python/tests/unittests/mock_base.py
@@ -213,7 +213,9 @@ def mock_load_fileset(name: str, location: str):
         _audit=audit_dto,
     )
     return GenericFileset(
-        fileset, None, Namespace.of("metalake_demo", "fileset_catalog", "tmp")
+        fileset,
+        HTTPClient("http://localhost:9090";, is_debug=True),
+        Namespace.of("metalake_demo", "fileset_catalog", "tmp"),
     )
 
 
diff --git a/clients/client-python/tests/unittests/test_tag_api.py 
b/clients/client-python/tests/unittests/test_tag_api.py
index 5b24f3452b..889ad86f17 100644
--- a/clients/client-python/tests/unittests/test_tag_api.py
+++ b/clients/client-python/tests/unittests/test_tag_api.py
@@ -25,17 +25,17 @@ from gravitino.api.tag import Tag
 from gravitino.api.tag.supports_tags import SupportsTags
 from gravitino.api.tag.tag_change import TagChange
 from gravitino.client.generic_tag import GenericTag
-from gravitino.exceptions.base import (
-    IllegalArgumentException,
-    UnsupportedOperationException,
-)
 from gravitino.dto.responses.drop_response import DropResponse
-from gravitino.name_identifier import NameIdentifier
 from gravitino.dto.responses.tag_response import (
     TagListResponse,
     TagNamesListResponse,
     TagResponse,
 )
+from gravitino.exceptions.base import (
+    IllegalArgumentException,
+    UnsupportedOperationException,
+)
+from gravitino.name_identifier import NameIdentifier
 from tests.unittests import mock_base
 
 
@@ -80,6 +80,14 @@ class TestTagAPI(unittest.TestCase):
         self.assertIsNone(tag.assignment_values())
 
         supports_tags = LegacySupportsTags()
+        self.assertEqual([], supports_tags.list_tags_with_visibility().tags())
+        self.assertFalse(
+            supports_tags.list_tags_with_visibility().has_inaccessible_tags()
+        )
+        self.assertEqual([], 
supports_tags.list_tags_info_with_visibility().tags())
+        self.assertFalse(
+            
supports_tags.list_tags_info_with_visibility().has_inaccessible_tags()
+        )
         with self.assertRaises(UnsupportedOperationException):
             supports_tags.assign_tags([], [])
 
@@ -590,6 +598,24 @@ class TestObjectTagAPI(unittest.TestCase):
             self.assertIn("tagA", tags)
             self.assertIn("tagB", tags)
 
+    def test_fileset_list_tags_with_visibility(self, *mock_method) -> None:
+        """Test listing visible tag names and authorization-filtering 
status."""
+        client = GravitinoClient(
+            uri="http://localhost:8090";,
+            metalake_name=self._metalake_name,
+            check_version=False,
+        )
+        fileset = self._load_fileset(client)
+        response = TagNamesListResponse(0, ["tagA"], True)
+
+        with patch(
+            "gravitino.utils.http_client.HTTPClient.get",
+            return_value=mock_base.mock_http_response(response.to_json()),
+        ):
+            tag_list = fileset.list_tags_with_visibility()
+            self.assertEqual(["tagA"], tag_list.tags())
+            self.assertTrue(tag_list.has_inaccessible_tags())
+
     def test_fileset_list_tags_info(self, *mock_method) -> None:
         """Test listing tags with details on a fileset via REST API."""
         tag_dto = mock_base.build_tag_dto("tagA", "comment A")
@@ -612,6 +638,24 @@ class TestObjectTagAPI(unittest.TestCase):
             self.assertEqual("tagA", tags[0].name())
             self.assertEqual("comment A", tags[0].comment())
 
+    def test_fileset_list_tags_info_with_visibility(self, *mock_method) -> 
None:
+        """Test listing visible tag details and authorization-filtering 
status."""
+        client = GravitinoClient(
+            uri="http://localhost:8090";,
+            metalake_name=self._metalake_name,
+            check_version=False,
+        )
+        fileset = self._load_fileset(client)
+        response = TagListResponse(0, [mock_base.build_tag_dto("tagA")], True)
+
+        with patch(
+            "gravitino.utils.http_client.HTTPClient.get",
+            return_value=mock_base.mock_http_response(response.to_json()),
+        ):
+            tag_list = fileset.list_tags_info_with_visibility()
+            self.assertEqual(["tagA"], [tag.name() for tag in tag_list.tags()])
+            self.assertTrue(tag_list.has_inaccessible_tags())
+
     def test_fileset_get_tag(self, *mock_method) -> None:
         """Test getting a specific tag on a fileset via REST API."""
         tag_dto = mock_base.build_tag_dto("tagA", "comment A")
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
 
b/common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectPolicyListResponse.java
similarity index 50%
copy from 
common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
copy to 
common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectPolicyListResponse.java
index a260171c79..c4e402bd9d 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectPolicyListResponse.java
@@ -19,52 +19,41 @@
 package org.apache.gravitino.dto.responses;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
-import java.util.Arrays;
 import lombok.EqualsAndHashCode;
-import lombok.Getter;
 import lombok.ToString;
 import org.apache.gravitino.dto.policy.PolicyDTO;
 
-/** Represents a response for a list of policies. */
-@Getter
+/** Represents a response for policies associated with a metadata object. */
 @ToString
 @EqualsAndHashCode(callSuper = true)
-public class PolicyListResponse extends BaseResponse {
+public class MetadataObjectPolicyListResponse extends PolicyListResponse {
 
-  @JsonProperty("policies")
-  private final PolicyDTO[] policies;
+  @JsonProperty("hasInaccessiblePolicies")
+  private final boolean hasInaccessiblePolicies;
 
   /**
-   * Creates a new PolicyListResponse.
+   * Creates a new MetadataObjectPolicyListResponse.
    *
-   * @param policies The list of policies.
+   * @param policies The list of accessible policies.
+   * @param hasInaccessiblePolicies Whether inaccessible policies were omitted 
from the response.
    */
-  public PolicyListResponse(PolicyDTO[] policies) {
-    super(0);
-    this.policies = policies;
+  public MetadataObjectPolicyListResponse(PolicyDTO[] policies, boolean 
hasInaccessiblePolicies) {
+    super(policies);
+    this.hasInaccessiblePolicies = hasInaccessiblePolicies;
   }
 
-  /**
-   * This is the constructor that is used by Jackson deserializer to create an 
instance of
-   * PolicyListResponse.
-   */
-  public PolicyListResponse() {
+  /** Constructor used by Jackson deserializer. */
+  public MetadataObjectPolicyListResponse() {
     super();
-    this.policies = null;
+    this.hasInaccessiblePolicies = false;
   }
 
-  @Override
-  public void validate() throws IllegalArgumentException {
-    super.validate();
-
-    Preconditions.checkArgument(policies != null, "\"policies\" must not be 
null");
-    Arrays.stream(policies)
-        .forEach(
-            t -> {
-              Preconditions.checkArgument(t != null, "policy must not be 
null");
-              Preconditions.checkArgument(t.content() != null, "policy content 
must not be null");
-              t.content().validate();
-            });
+  /**
+   * Returns whether inaccessible policies were omitted from the response.
+   *
+   * @return true if at least one inaccessible policy was omitted, false 
otherwise
+   */
+  public boolean hasInaccessiblePolicies() {
+    return hasInaccessiblePolicies;
   }
 }
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java 
b/common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectTagListResponse.java
similarity index 54%
copy from 
common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
copy to 
common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectTagListResponse.java
index 93c324dfe4..f8dce56b20 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/MetadataObjectTagListResponse.java
@@ -19,47 +19,41 @@
 package org.apache.gravitino.dto.responses;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
-import java.util.Arrays;
 import lombok.EqualsAndHashCode;
-import lombok.Getter;
 import lombok.ToString;
 import org.apache.gravitino.dto.tag.TagDTO;
 
-/** Represents a response for a list of tags. */
-@Getter
+/** Represents a response for tags associated with a metadata object. */
 @ToString
 @EqualsAndHashCode(callSuper = true)
-public class TagListResponse extends BaseResponse {
+public class MetadataObjectTagListResponse extends TagListResponse {
 
-  @JsonProperty("tags")
-  private final TagDTO[] tags;
+  @JsonProperty("hasInaccessibleTags")
+  private final boolean hasInaccessibleTags;
 
   /**
-   * Creates a new TagListResponse.
+   * Creates a new MetadataObjectTagListResponse.
    *
-   * @param tags The list of tags.
+   * @param tags The list of accessible tags.
+   * @param hasInaccessibleTags Whether inaccessible tags were omitted from 
the response.
    */
-  public TagListResponse(TagDTO[] tags) {
-    super(0);
-    this.tags = tags;
+  public MetadataObjectTagListResponse(TagDTO[] tags, boolean 
hasInaccessibleTags) {
+    super(tags);
+    this.hasInaccessibleTags = hasInaccessibleTags;
   }
 
-  /**
-   * This is the constructor that is used by Jackson deserializer to create an 
instance of
-   * TagListResponse.
-   */
-  public TagListResponse() {
+  /** Constructor used by Jackson deserializer. */
+  public MetadataObjectTagListResponse() {
     super();
-    this.tags = null;
+    this.hasInaccessibleTags = false;
   }
 
-  @Override
-  public void validate() throws IllegalArgumentException {
-    super.validate();
-
-    Preconditions.checkArgument(tags != null, "\"tags\" must not be null");
-    Arrays.stream(tags)
-        .forEach(t -> Preconditions.checkArgument(t != null, "tag must not be 
null"));
+  /**
+   * Returns whether inaccessible tags were omitted from the response.
+   *
+   * @return true if at least one inaccessible tag was omitted, false otherwise
+   */
+  public boolean hasInaccessibleTags() {
+    return hasInaccessibleTags;
   }
 }
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/NameListResponse.java 
b/common/src/main/java/org/apache/gravitino/dto/responses/NameListResponse.java
index 0728165c5e..f6128b6b28 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/NameListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/NameListResponse.java
@@ -18,6 +18,7 @@
  */
 package org.apache.gravitino.dto.responses;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 import java.util.Arrays;
@@ -27,6 +28,7 @@ import lombok.ToString;
 import org.apache.commons.lang3.StringUtils;
 
 /** Represents a response for a list of entity names. */
+@JsonIgnoreProperties(ignoreUnknown = true)
 @Getter
 @ToString
 @EqualsAndHashCode(callSuper = true)
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
 
b/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
index a260171c79..6d754e8216 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java
@@ -18,6 +18,7 @@
  */
 package org.apache.gravitino.dto.responses;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 import java.util.Arrays;
@@ -27,6 +28,7 @@ import lombok.ToString;
 import org.apache.gravitino.dto.policy.PolicyDTO;
 
 /** Represents a response for a list of policies. */
+@JsonIgnoreProperties(ignoreUnknown = true)
 @Getter
 @ToString
 @EqualsAndHashCode(callSuper = true)
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java 
b/common/src/main/java/org/apache/gravitino/dto/responses/PolicyNameListResponse.java
similarity index 53%
copy from 
common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
copy to 
common/src/main/java/org/apache/gravitino/dto/responses/PolicyNameListResponse.java
index 93c324dfe4..351c9bb99a 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/PolicyNameListResponse.java
@@ -19,47 +19,40 @@
 package org.apache.gravitino.dto.responses;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
-import java.util.Arrays;
 import lombok.EqualsAndHashCode;
-import lombok.Getter;
 import lombok.ToString;
-import org.apache.gravitino.dto.tag.TagDTO;
 
-/** Represents a response for a list of tags. */
-@Getter
+/** Represents a response for a list of policy names. */
 @ToString
 @EqualsAndHashCode(callSuper = true)
-public class TagListResponse extends BaseResponse {
+public class PolicyNameListResponse extends NameListResponse {
 
-  @JsonProperty("tags")
-  private final TagDTO[] tags;
+  @JsonProperty("hasInaccessiblePolicies")
+  private final boolean hasInaccessiblePolicies;
 
   /**
-   * Creates a new TagListResponse.
+   * Creates a new PolicyNameListResponse.
    *
-   * @param tags The list of tags.
+   * @param names The list of accessible policy names.
+   * @param hasInaccessiblePolicies Whether inaccessible policies were omitted 
from the response.
    */
-  public TagListResponse(TagDTO[] tags) {
-    super(0);
-    this.tags = tags;
+  public PolicyNameListResponse(String[] names, boolean 
hasInaccessiblePolicies) {
+    super(names);
+    this.hasInaccessiblePolicies = hasInaccessiblePolicies;
   }
 
-  /**
-   * This is the constructor that is used by Jackson deserializer to create an 
instance of
-   * TagListResponse.
-   */
-  public TagListResponse() {
+  /** Constructor used by Jackson deserializer. */
+  public PolicyNameListResponse() {
     super();
-    this.tags = null;
+    this.hasInaccessiblePolicies = false;
   }
 
-  @Override
-  public void validate() throws IllegalArgumentException {
-    super.validate();
-
-    Preconditions.checkArgument(tags != null, "\"tags\" must not be null");
-    Arrays.stream(tags)
-        .forEach(t -> Preconditions.checkArgument(t != null, "tag must not be 
null"));
+  /**
+   * Returns whether inaccessible policies were omitted from the response.
+   *
+   * @return true if at least one inaccessible policy was omitted, false 
otherwise
+   */
+  public boolean hasInaccessiblePolicies() {
+    return hasInaccessiblePolicies;
   }
 }
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java 
b/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
index 93c324dfe4..1546cef918 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
@@ -18,6 +18,7 @@
  */
 package org.apache.gravitino.dto.responses;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 import java.util.Arrays;
@@ -27,6 +28,7 @@ import lombok.ToString;
 import org.apache.gravitino.dto.tag.TagDTO;
 
 /** Represents a response for a list of tags. */
+@JsonIgnoreProperties(ignoreUnknown = true)
 @Getter
 @ToString
 @EqualsAndHashCode(callSuper = true)
diff --git 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java 
b/common/src/main/java/org/apache/gravitino/dto/responses/TagNameListResponse.java
similarity index 54%
copy from 
common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
copy to 
common/src/main/java/org/apache/gravitino/dto/responses/TagNameListResponse.java
index 93c324dfe4..20c01b8955 100644
--- 
a/common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java
+++ 
b/common/src/main/java/org/apache/gravitino/dto/responses/TagNameListResponse.java
@@ -19,47 +19,40 @@
 package org.apache.gravitino.dto.responses;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
-import java.util.Arrays;
 import lombok.EqualsAndHashCode;
-import lombok.Getter;
 import lombok.ToString;
-import org.apache.gravitino.dto.tag.TagDTO;
 
-/** Represents a response for a list of tags. */
-@Getter
+/** Represents a response for a list of tag names. */
 @ToString
 @EqualsAndHashCode(callSuper = true)
-public class TagListResponse extends BaseResponse {
+public class TagNameListResponse extends NameListResponse {
 
-  @JsonProperty("tags")
-  private final TagDTO[] tags;
+  @JsonProperty("hasInaccessibleTags")
+  private final boolean hasInaccessibleTags;
 
   /**
-   * Creates a new TagListResponse.
+   * Creates a new TagNameListResponse.
    *
-   * @param tags The list of tags.
+   * @param names The list of accessible tag names.
+   * @param hasInaccessibleTags Whether inaccessible tags were omitted from 
the response.
    */
-  public TagListResponse(TagDTO[] tags) {
-    super(0);
-    this.tags = tags;
+  public TagNameListResponse(String[] names, boolean hasInaccessibleTags) {
+    super(names);
+    this.hasInaccessibleTags = hasInaccessibleTags;
   }
 
-  /**
-   * This is the constructor that is used by Jackson deserializer to create an 
instance of
-   * TagListResponse.
-   */
-  public TagListResponse() {
+  /** Constructor used by Jackson deserializer. */
+  public TagNameListResponse() {
     super();
-    this.tags = null;
+    this.hasInaccessibleTags = false;
   }
 
-  @Override
-  public void validate() throws IllegalArgumentException {
-    super.validate();
-
-    Preconditions.checkArgument(tags != null, "\"tags\" must not be null");
-    Arrays.stream(tags)
-        .forEach(t -> Preconditions.checkArgument(t != null, "tag must not be 
null"));
+  /**
+   * Returns whether inaccessible tags were omitted from the response.
+   *
+   * @return true if at least one inaccessible tag was omitted, false otherwise
+   */
+  public boolean hasInaccessibleTags() {
+    return hasInaccessibleTags;
   }
 }
diff --git 
a/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java 
b/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
index 2c5ab6bcb0..ec58f95593 100644
--- a/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
+++ b/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
@@ -48,6 +48,7 @@ import 
org.apache.gravitino.dto.authorization.SecurableObjectDTO;
 import org.apache.gravitino.dto.authorization.UserDTO;
 import org.apache.gravitino.dto.model.ModelDTO;
 import org.apache.gravitino.dto.model.ModelVersionDTO;
+import org.apache.gravitino.dto.policy.PolicyDTO;
 import org.apache.gravitino.dto.rel.ColumnDTO;
 import org.apache.gravitino.dto.rel.TableDTO;
 import org.apache.gravitino.dto.rel.partitioning.Partitioning;
@@ -390,6 +391,46 @@ public class TestResponses {
     assertEquals("\"names\" must not be null", e.getMessage());
   }
 
+  @Test
+  void testTagNameListResponse() throws JsonProcessingException {
+    String[] names = new String[] {"tag1", "tag2"};
+    TagNameListResponse response = new TagNameListResponse(names, true);
+    assertDoesNotThrow(response::validate);
+
+    String serJson = JsonUtils.objectMapper().writeValueAsString(response);
+    TagNameListResponse deserResponse =
+        JsonUtils.objectMapper().readValue(serJson, TagNameListResponse.class);
+    assertEquals(response, deserResponse);
+    assertArrayEquals(names, deserResponse.getNames());
+    assertTrue(deserResponse.hasInaccessibleTags());
+
+    NameListResponse backwardCompatibleResponse =
+        JsonUtils.objectMapper().readValue(serJson, NameListResponse.class);
+    assertArrayEquals(names, backwardCompatibleResponse.getNames());
+
+    assertFalse(new TagNameListResponse(new String[0], 
false).hasInaccessibleTags());
+  }
+
+  @Test
+  void testPolicyNameListResponse() throws JsonProcessingException {
+    String[] names = new String[] {"policy1", "policy2"};
+    PolicyNameListResponse response = new PolicyNameListResponse(names, true);
+    assertDoesNotThrow(response::validate);
+
+    String serJson = JsonUtils.objectMapper().writeValueAsString(response);
+    PolicyNameListResponse deserResponse =
+        JsonUtils.objectMapper().readValue(serJson, 
PolicyNameListResponse.class);
+    assertEquals(response, deserResponse);
+    assertArrayEquals(names, deserResponse.getNames());
+    assertTrue(deserResponse.hasInaccessiblePolicies());
+
+    NameListResponse backwardCompatibleResponse =
+        JsonUtils.objectMapper().readValue(serJson, NameListResponse.class);
+    assertArrayEquals(names, backwardCompatibleResponse.getNames());
+
+    assertFalse(new PolicyNameListResponse(new String[0], 
false).hasInaccessiblePolicies());
+  }
+
   @Test
   void testTagListResponse() throws JsonProcessingException {
     TagDTO tag1 = 
TagDTO.builder().withName("tag1").withComment("comment1").build();
@@ -409,6 +450,43 @@ public class TestResponses {
     assertEquals("\"tags\" must not be null", e.getMessage());
   }
 
+  @Test
+  void testMetadataObjectTagListResponse() throws JsonProcessingException {
+    TagDTO tag = TagDTO.builder().withName("tag1").build();
+    MetadataObjectTagListResponse response =
+        new MetadataObjectTagListResponse(new TagDTO[] {tag}, true);
+    assertDoesNotThrow(response::validate);
+
+    String serJson = JsonUtils.objectMapper().writeValueAsString(response);
+    MetadataObjectTagListResponse deserResponse =
+        JsonUtils.objectMapper().readValue(serJson, 
MetadataObjectTagListResponse.class);
+    assertEquals(response, deserResponse);
+    assertArrayEquals(new TagDTO[] {tag}, deserResponse.getTags());
+    assertTrue(deserResponse.hasInaccessibleTags());
+
+    TagListResponse backwardCompatibleResponse =
+        JsonUtils.objectMapper().readValue(serJson, TagListResponse.class);
+    assertArrayEquals(new TagDTO[] {tag}, 
backwardCompatibleResponse.getTags());
+  }
+
+  @Test
+  void testMetadataObjectPolicyListResponse() throws JsonProcessingException {
+    MetadataObjectPolicyListResponse response =
+        new MetadataObjectPolicyListResponse(new PolicyDTO[0], true);
+    assertDoesNotThrow(response::validate);
+
+    String serJson = JsonUtils.objectMapper().writeValueAsString(response);
+    MetadataObjectPolicyListResponse deserResponse =
+        JsonUtils.objectMapper().readValue(serJson, 
MetadataObjectPolicyListResponse.class);
+    assertEquals(response, deserResponse);
+    assertArrayEquals(new PolicyDTO[0], deserResponse.getPolicies());
+    assertTrue(deserResponse.hasInaccessiblePolicies());
+
+    PolicyListResponse backwardCompatibleResponse =
+        JsonUtils.objectMapper().readValue(serJson, PolicyListResponse.class);
+    assertArrayEquals(new PolicyDTO[0], 
backwardCompatibleResponse.getPolicies());
+  }
+
   @Test
   void testTagResponse() throws JsonProcessingException {
     TagDTO tag = 
TagDTO.builder().withName("tag1").withComment("comment1").build();
diff --git a/docs/manage-policies-in-gravitino.md 
b/docs/manage-policies-in-gravitino.md
index 110f9498db..9b1becb4ff 100644
--- a/docs/manage-policies-in-gravitino.md
+++ b/docs/manage-policies-in-gravitino.md
@@ -343,6 +343,10 @@ The response includes policies derived from effective tags 
assigned to the objec
 With `details=true`, the response returns full policy objects instead of 
policy names.
 Each policy includes an `inherited` field, which is `true` when it matches 
only through a tag
 assigned to an ancestor of the object. Disabled policies do not appear in this 
result.
+Both response modes include `hasInaccessiblePolicies`. Gravitino resolves 
policies from direct and
+inherited tag assignments before authorization filtering, so the flag also 
covers policies omitted
+from inherited associations. The flag reveals only that at least one policy 
was omitted; it does not
+reveal the policy's name, count, details, or inheritance source.
 
 <Tabs groupId='language' queryString>
 <TabItem value="shell" label="REST">
@@ -352,6 +356,16 @@ curl -X GET -H "Accept: application/vnd.gravitino.v1+json" 
\
   
"http://localhost:8090/api/metalakes/test/objects/table/catalog1.schema1.customers/policies?details=true";
 ```
 
+If every applicable policy is inaccessible, the response contains an empty 
list and sets the flag:
+
+```json
+{
+  "code": 0,
+  "policies": [],
+  "hasInaccessiblePolicies": true
+}
+```
+
 </TabItem>
 <TabItem value="java" label="Java">
 
@@ -360,9 +374,26 @@ Table customers =
     client.loadCatalog("catalog1")
         .asTableCatalog()
         .loadTable(NameIdentifier.of("schema1", "customers"));
-String[] policyNames = customers.supportsPolicies().listPolicies();
-Policy[] policies = customers.supportsPolicies().listPolicyInfos();
+PolicyList<String> nameList = 
customers.supportsPolicies().listPoliciesWithVisibility();
+String[] policyNames = nameList.policies();
+boolean omittedPolicies = nameList.hasInaccessiblePolicies();
+
+PolicyList<Policy> detailList = 
customers.supportsPolicies().listPolicyInfosWithVisibility();
+Policy[] policies = detailList.policies();
+boolean omittedPolicyDetails = detailList.hasInaccessiblePolicies();
 ```
 
+The existing `listPolicies()` and `listPolicyInfos()` methods continue to 
return only the visible
+arrays.
+
 </TabItem>
 </Tabs>
+
+Interpret the visible list and `hasInaccessiblePolicies` together:
+
+| Visible list | `hasInaccessiblePolicies` | Meaning |
+|---|---:|---|
+| Empty | `false` | No enabled policy applies to the object. |
+| Empty | `true` | All applicable policies are inaccessible. |
+| Non-empty | `true` | The response includes visible policies and omits at 
least one inaccessible policy. |
+| Non-empty | `false` | All applicable policies are visible. |
diff --git a/docs/manage-tags-in-gravitino.md b/docs/manage-tags-in-gravitino.md
index 5254582a1e..528c9dd18c 100644
--- a/docs/manage-tags-in-gravitino.md
+++ b/docs/manage-tags-in-gravitino.md
@@ -357,6 +357,10 @@ The response includes tags inherited from ancestors. With 
`details=true` each ta
 `inherited` field and its `assignmentValues`, which a plain name listing does 
not. An empty
 `assignmentValues` array means the tag is assigned without a value. 
`allowedValues` is null for an
 unrestricted tag, empty for a valueless-only tag, and otherwise contains the 
tag's allowed values.
+Both response modes include `hasInaccessibleTags`. Gravitino resolves direct 
and inherited tag
+assignments before authorization filtering, so the flag also covers 
inaccessible inherited tags.
+The flag reveals only that at least one tag was omitted; it does not reveal 
the tag's name, count,
+details, or inheritance source.
 
 <Tabs groupId='language' queryString>
 <TabItem value="shell" label="REST">
@@ -380,7 +384,18 @@ The response includes each tag's definition and assignment 
details:
       "assignmentValues": ["finance", "risk"],
       "inherited": false
     }
-  ]
+  ],
+  "hasInaccessibleTags": false
+}
+```
+
+If every effective tag is inaccessible, the response contains an empty list 
and sets the flag:
+
+```json
+{
+  "code": 0,
+  "tags": [],
+  "hasInaccessibleTags": true
 }
 ```
 
@@ -389,25 +404,48 @@ The response includes each tag's definition and 
assignment details:
 
 ```java
 Table customers = ...
-String[] tagNames = customers.supportsTags().listTags();
-Tag[] tags = customers.supportsTags().listTagsInfo();
+TagList<String> nameList = customers.supportsTags().listTagsWithVisibility();
+String[] tagNames = nameList.tags();
+boolean omittedTags = nameList.hasInaccessibleTags();
+
+TagList<Tag> detailList = 
customers.supportsTags().listTagsInfoWithVisibility();
+Tag[] tags = detailList.tags();
+boolean omittedTagDetails = detailList.hasInaccessibleTags();
 String[] values =
     tags[0].assignment().map(assignment -> assignment.values()).orElse(new 
String[0]);
 ```
 
+The existing `listTags()` and `listTagsInfo()` methods continue to return only 
the visible arrays.
+
 </TabItem>
 <TabItem value="python" label="Python">
 
 ```python
 customers = ...
-tag_names = customers.supports_tags().list_tags()
-tags = customers.supports_tags().list_tags_info()
+name_list = customers.supports_tags().list_tags_with_visibility()
+tag_names = name_list.tags()
+omitted_tags = name_list.has_inaccessible_tags()
+
+detail_list = customers.supports_tags().list_tags_info_with_visibility()
+tags = detail_list.tags()
+omitted_tag_details = detail_list.has_inaccessible_tags()
 values = tags[0].assignment_values()
 ```
 
+The existing `list_tags()` and `list_tags_info()` methods continue to return 
only the visible lists.
+
 </TabItem>
 </Tabs>
 
+Interpret the visible list and `hasInaccessibleTags` together:
+
+| Visible list | `hasInaccessibleTags` | Meaning |
+|---|---:|---|
+| Empty | `false` | The object has no effective tag assignments. |
+| Empty | `true` | All effective tag assignments are inaccessible. |
+| Non-empty | `true` | The response includes visible tags and omits at least 
one inaccessible tag. |
+| Non-empty | `false` | All effective tag assignments are visible. |
+
 ### Get One Tag on an Object
 
 <Tabs groupId='language' queryString>
diff --git a/docs/open-api/policies.yaml b/docs/open-api/policies.yaml
index e2310534b0..659a3313d2 100644
--- a/docs/open-api/policies.yaml
+++ b/docs/open-api/policies.yaml
@@ -224,13 +224,13 @@ paths:
             application/vnd.gravitino.v1+json:
               schema:
                 oneOf:
-                  - $ref: "./openapi.yaml#/components/schemas/NameListResponse"
-                  - $ref: "#/components/schemas/PolicyListResponse"
+                  - $ref: "#/components/schemas/PolicyNameListResponse"
+                  - $ref: 
"#/components/schemas/MetadataObjectPolicyListResponse"
               examples:
-                NameListResponse:
-                  $ref: "#/components/examples/NameListResponse"
-                PolicyListResponse:
-                  $ref: "#/components/examples/PolicyListResponse"
+                PolicyNameListResponse:
+                  $ref: "#/components/examples/PolicyNameListResponse"
+                MetadataObjectPolicyListResponse:
+                  $ref: 
"#/components/examples/MetadataObjectPolicyListResponse"
         "400":
           $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
         "404":
@@ -711,6 +711,30 @@ components:
           items:
             $ref: "#/components/schemas/Policy"
 
+    PolicyNameListResponse:
+      allOf:
+        - $ref: "./openapi.yaml#/components/schemas/NameListResponse"
+        - type: object
+          required:
+            - names
+            - hasInaccessiblePolicies
+          properties:
+            hasInaccessiblePolicies:
+              type: boolean
+              description: Whether one or more inaccessible policies were 
omitted from the response
+
+    MetadataObjectPolicyListResponse:
+      allOf:
+        - $ref: "#/components/schemas/PolicyListResponse"
+        - type: object
+          required:
+            - policies
+            - hasInaccessiblePolicies
+          properties:
+            hasInaccessiblePolicies:
+              type: boolean
+              description: Whether one or more inaccessible policies were 
omitted from the response
+
     MetadataObject:
       type: object
       description: A metadata object
@@ -1006,6 +1030,13 @@ components:
           $ref: "#/components/schemas/Policy"
 
   examples:
+    PolicyNameListResponse:
+      value: {
+        "code": 0,
+        "names": ["my_policy1"],
+        "hasInaccessiblePolicies": true
+      }
+
     NameListResponse:
       value: {
         "code": 0,
@@ -1046,6 +1077,13 @@ components:
         ]
       }
 
+    MetadataObjectPolicyListResponse:
+      value: {
+        "code": 0,
+        "policies": [],
+        "hasInaccessiblePolicies": true
+      }
+
     PolicyCreate:
       value: {
         "name": "my_policy1",
diff --git a/docs/open-api/tags.yaml b/docs/open-api/tags.yaml
index 33fa7dd56a..0d66d12ec5 100644
--- a/docs/open-api/tags.yaml
+++ b/docs/open-api/tags.yaml
@@ -197,13 +197,13 @@ paths:
             application/vnd.gravitino.v1+json:
               schema:
                 oneOf:
-                  - $ref: "./openapi.yaml#/components/schemas/NameListResponse"
-                  - $ref: "#/components/responses/TagListResponse"
+                  - $ref: "#/components/responses/TagNameListResponse"
+                  - $ref: 
"#/components/responses/MetadataObjectTagListResponse"
               examples:
-                NameListResponse:
-                  $ref: "#/components/examples/NameListResponse"
-                TagListResponse:
-                  $ref: "#/components/examples/TagListResponse"
+                TagNameListResponse:
+                  $ref: "#/components/examples/TagNameListResponse"
+                MetadataObjectTagListResponse:
+                  $ref: "#/components/examples/MetadataObjectTagListResponse"
         "400":
           $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
         "404":
@@ -781,6 +781,18 @@ components:
         selector:
           $ref: "./policies.yaml#/components/schemas/PolicyAssociationSelector"
 
+    TagNameListResponse:
+      allOf:
+        - $ref: "./openapi.yaml#/components/schemas/NameListResponse"
+        - type: object
+          required:
+            - names
+            - hasInaccessibleTags
+          properties:
+            hasInaccessibleTags:
+              type: boolean
+              description: Whether one or more inaccessible tags were omitted 
from the response
+
     TagListResponse:
       type: object
       properties:
@@ -796,6 +808,18 @@ components:
           items:
             $ref: "#/components/schemas/Tag"
 
+    MetadataObjectTagListResponse:
+      allOf:
+        - $ref: "#/components/responses/TagListResponse"
+        - type: object
+          required:
+            - tags
+            - hasInaccessibleTags
+          properties:
+            hasInaccessibleTags:
+              type: boolean
+              description: Whether one or more inaccessible tags were omitted 
from the response
+
     TagResponse:
       type: object
       properties:
@@ -824,6 +848,13 @@ components:
             $ref: "#/components/schemas/MetadataObject"
 
   examples:
+    TagNameListResponse:
+      value: {
+        "code": 0,
+        "names": ["my_tag1"],
+        "hasInaccessibleTags": true
+      }
+
     NameListResponse:
       value: {
         "code": 0,
@@ -862,6 +893,13 @@ components:
         ]
       }
 
+    MetadataObjectTagListResponse:
+      value: {
+        "code": 0,
+        "tags": [],
+        "hasInaccessibleTags": true
+      }
+
     TagCreate:
       value: {
         "name": "my_tag1",
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectPolicyOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectPolicyOperations.java
index 0788720b4d..9b533071aa 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectPolicyOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectPolicyOperations.java
@@ -39,8 +39,8 @@ import org.apache.gravitino.Entity;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.MetadataObjects;
 import org.apache.gravitino.dto.policy.PolicyDTO;
-import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.PolicyListResponse;
+import org.apache.gravitino.dto.responses.MetadataObjectPolicyListResponse;
+import org.apache.gravitino.dto.responses.PolicyNameListResponse;
 import org.apache.gravitino.meta.PolicyEntity;
 import org.apache.gravitino.metrics.MetricNames;
 import org.apache.gravitino.policy.PolicyDispatcher;
@@ -96,6 +96,7 @@ public class MetadataObjectPolicyOperations {
 
             PolicyEntity[] policies =
                 policyDispatcher.listPolicyInfosForMetadataObject(metalake, 
object);
+            int policyCount = policies.length;
             policies =
                 MetadataAuthzHelper.filterByExpression(
                     metalake,
@@ -103,6 +104,7 @@ public class MetadataObjectPolicyOperations {
                     Entity.EntityType.POLICY,
                     policies,
                     policy -> NameIdentifierUtil.ofPolicy(metalake, 
policy.name()));
+            boolean hasInaccessiblePolicies = policies.length < policyCount;
 
             PolicyDTO[] policyDTOs =
                 Arrays.stream(policies)
@@ -119,7 +121,8 @@ public class MetadataObjectPolicyOperations {
                   type,
                   fullName,
                   metalake);
-              return Utils.ok(new PolicyListResponse(policyDTOs));
+              return Utils.ok(
+                  new MetadataObjectPolicyListResponse(policyDTOs, 
hasInaccessiblePolicies));
 
             } else {
               String[] policyNames =
@@ -131,7 +134,7 @@ public class MetadataObjectPolicyOperations {
                   type,
                   fullName,
                   metalake);
-              return Utils.ok(new NameListResponse(policyNames));
+              return Utils.ok(new PolicyNameListResponse(policyNames, 
hasInaccessiblePolicies));
             }
           });
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectTagOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectTagOperations.java
index 66ac0fc8ab..c550b0c5b7 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectTagOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetadataObjectTagOperations.java
@@ -46,8 +46,9 @@ import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.MetadataObjects;
 import org.apache.gravitino.dto.requests.TagValuesAssociateRequest;
 import org.apache.gravitino.dto.requests.TagsAssociateRequest;
+import org.apache.gravitino.dto.responses.MetadataObjectTagListResponse;
 import org.apache.gravitino.dto.responses.NameListResponse;
-import org.apache.gravitino.dto.responses.TagListResponse;
+import org.apache.gravitino.dto.responses.TagNameListResponse;
 import org.apache.gravitino.dto.responses.TagResponse;
 import org.apache.gravitino.dto.tag.TagDTO;
 import org.apache.gravitino.dto.util.DTOConverters;
@@ -206,39 +207,35 @@ public class MetadataObjectTagOperations {
               }
             }
 
+            TagDTO[] tagDTOs = tags.values().toArray(new TagDTO[0]);
+            int tagCount = tagDTOs.length;
+            tagDTOs =
+                MetadataAuthzHelper.filterByExpression(
+                    metalake,
+                    
AuthorizationExpressionConstants.LOAD_TAG_AUTHORIZATION_EXPRESSION,
+                    Entity.EntityType.TAG,
+                    tagDTOs,
+                    tagDTO -> NameIdentifierUtil.ofTag(metalake, 
tagDTO.name()));
+            boolean hasInaccessibleTags = tagDTOs.length < tagCount;
+
             if (verbose) {
               LOG.info(
                   "List {} tags info for object type: {}, full name: {} under 
metalake: {}",
-                  tags.size(),
+                  tagDTOs.length,
                   type,
                   fullName,
                   metalake);
-              TagDTO[] tagDTOS = tags.values().toArray(new TagDTO[0]);
-              tagDTOS =
-                  MetadataAuthzHelper.filterByExpression(
-                      metalake,
-                      
AuthorizationExpressionConstants.LOAD_TAG_AUTHORIZATION_EXPRESSION,
-                      Entity.EntityType.TAG,
-                      tagDTOS,
-                      tagDTO -> NameIdentifierUtil.ofTag(metalake, 
tagDTO.name()));
-              return Utils.ok(new TagListResponse(tagDTOS));
+              return Utils.ok(new MetadataObjectTagListResponse(tagDTOs, 
hasInaccessibleTags));
 
             } else {
-              String[] tagNames = tags.keySet().toArray(new String[0]);
-              tagNames =
-                  MetadataAuthzHelper.filterByExpression(
-                      metalake,
-                      
AuthorizationExpressionConstants.LOAD_TAG_AUTHORIZATION_EXPRESSION,
-                      Entity.EntityType.TAG,
-                      tagNames,
-                      tagName -> NameIdentifierUtil.ofTag(metalake, tagName));
+              String[] tagNames = 
Arrays.stream(tagDTOs).map(TagDTO::name).toArray(String[]::new);
               LOG.info(
                   "List {} tags for object type: {}, full name: {} under 
metalake: {}",
                   tagNames.length,
                   type,
                   fullName,
                   metalake);
-              return Utils.ok(new NameListResponse(tagNames));
+              return Utils.ok(new TagNameListResponse(tagNames, 
hasInaccessibleTags));
             }
           });
 
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectPolicyOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectPolicyOperations.java
index e7703609d8..1d546ab84e 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectPolicyOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectPolicyOperations.java
@@ -42,8 +42,10 @@ import org.apache.gravitino.Config;
 import org.apache.gravitino.GravitinoEnv;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.MetadataObjects;
+import org.apache.gravitino.dto.responses.MetadataObjectPolicyListResponse;
 import org.apache.gravitino.dto.responses.NameListResponse;
 import org.apache.gravitino.dto.responses.PolicyListResponse;
+import org.apache.gravitino.dto.responses.PolicyNameListResponse;
 import org.apache.gravitino.meta.AuditInfo;
 import org.apache.gravitino.meta.PolicyEntity;
 import org.apache.gravitino.policy.Policy;
@@ -150,8 +152,10 @@ public class TestMetadataObjectPolicyOperations extends 
BaseOperationsTest {
 
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
 
-    PolicyListResponse policyListResponse = 
response.readEntity(PolicyListResponse.class);
+    MetadataObjectPolicyListResponse policyListResponse =
+        response.readEntity(MetadataObjectPolicyListResponse.class);
     Assertions.assertEquals(0, policyListResponse.getCode());
+    Assertions.assertFalse(policyListResponse.hasInaccessiblePolicies());
     Assertions.assertEquals(catalogPolicyInfos.length, 
policyListResponse.getPolicies().length);
 
     Map<String, Policy> resultPolicies =
@@ -172,8 +176,9 @@ public class TestMetadataObjectPolicyOperations extends 
BaseOperationsTest {
 
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response1.getStatus());
 
-    NameListResponse nameListResponse = 
response1.readEntity(NameListResponse.class);
+    PolicyNameListResponse nameListResponse = 
response1.readEntity(PolicyNameListResponse.class);
     Assertions.assertEquals(0, nameListResponse.getCode());
+    Assertions.assertFalse(nameListResponse.hasInaccessiblePolicies());
     Assertions.assertEquals(catalogPolicyInfos.length, 
nameListResponse.getNames().length);
     Assertions.assertArrayEquals(
         
Arrays.stream(catalogPolicyInfos).map(PolicyEntity::name).toArray(String[]::new),
@@ -390,14 +395,18 @@ public class TestMetadataObjectPolicyOperations extends 
BaseOperationsTest {
           operations.listPoliciesForMetadataObject(
               metalake, table.type().toString(), table.fullName(), true);
       Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
detailsResponse.getStatus());
-      Assertions.assertEquals(
-          0, ((PolicyListResponse) 
detailsResponse.getEntity()).getPolicies().length);
+      MetadataObjectPolicyListResponse details =
+          (MetadataObjectPolicyListResponse) detailsResponse.getEntity();
+      Assertions.assertEquals(0, details.getPolicies().length);
+      Assertions.assertTrue(details.hasInaccessiblePolicies());
 
       Response namesResponse =
           operations.listPoliciesForMetadataObject(
               metalake, table.type().toString(), table.fullName(), false);
       Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
namesResponse.getStatus());
-      Assertions.assertEquals(0, ((NameListResponse) 
namesResponse.getEntity()).getNames().length);
+      PolicyNameListResponse names = (PolicyNameListResponse) 
namesResponse.getEntity();
+      Assertions.assertEquals(0, names.getNames().length);
+      Assertions.assertTrue(names.hasInaccessiblePolicies());
     }
     Mockito.verify(policyManager, Mockito.never())
         .listPolicyInfosForMetadataObject(metalake, schema);
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectTagOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectTagOperations.java
index 02f9853063..188ec374fd 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectTagOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetadataObjectTagOperations.java
@@ -42,8 +42,10 @@ import 
org.apache.gravitino.dto.requests.TagValuesAssociateRequest;
 import org.apache.gravitino.dto.requests.TagsAssociateRequest;
 import org.apache.gravitino.dto.responses.ErrorConstants;
 import org.apache.gravitino.dto.responses.ErrorResponse;
+import org.apache.gravitino.dto.responses.MetadataObjectTagListResponse;
 import org.apache.gravitino.dto.responses.NameListResponse;
 import org.apache.gravitino.dto.responses.TagListResponse;
+import org.apache.gravitino.dto.responses.TagNameListResponse;
 import org.apache.gravitino.dto.responses.TagResponse;
 import org.apache.gravitino.exceptions.NoSuchTagException;
 import org.apache.gravitino.exceptions.TagAlreadyAssociatedException;
@@ -164,9 +166,11 @@ public class TestMetadataObjectTagOperations extends 
BaseOperationsTest {
 
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
 
-    TagListResponse tagListResponse = 
response.readEntity(TagListResponse.class);
+    MetadataObjectTagListResponse tagListResponse =
+        response.readEntity(MetadataObjectTagListResponse.class);
     Assertions.assertEquals(0, tagListResponse.getCode());
     Assertions.assertEquals(catalogTagInfos.length, 
tagListResponse.getTags().length);
+    Assertions.assertFalse(tagListResponse.hasInaccessibleTags());
 
     Map<String, Tag> resultTags =
         Arrays.stream(tagListResponse.getTags())
@@ -186,9 +190,10 @@ public class TestMetadataObjectTagOperations extends 
BaseOperationsTest {
 
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response1.getStatus());
 
-    NameListResponse nameListResponse = 
response1.readEntity(NameListResponse.class);
+    TagNameListResponse nameListResponse = 
response1.readEntity(TagNameListResponse.class);
     Assertions.assertEquals(0, nameListResponse.getCode());
     Assertions.assertEquals(catalogTagInfos.length, 
nameListResponse.getNames().length);
+    Assertions.assertFalse(nameListResponse.hasInaccessibleTags());
     Assertions.assertArrayEquals(
         Arrays.stream(catalogTagInfos).map(Tag::name).toArray(String[]::new),
         nameListResponse.getNames());

Reply via email to