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

adutra pushed a commit to branch feature/iceberg-1.11
in repository https://gitbox.apache.org/repos/asf/polaris.git


The following commit(s) were added to refs/heads/feature/iceberg-1.11 by this 
push:
     new 5aadc851e [Iceberg 1.11] Update REST spec (#3687)
5aadc851e is described below

commit 5aadc851e1df24e3e0a99f5d4951e067a69f5984
Author: Alexandre Dutra <[email protected]>
AuthorDate: Tue Feb 10 09:49:25 2026 +0100

    [Iceberg 1.11] Update REST spec (#3687)
---
 .../catalog/iceberg/IcebergCatalogAdapter.java     |  20 +-
 .../IcebergRestCatalogEventServiceDelegator.java   |  83 +++++-
 .../admin/PolarisS3InteroperabilityTest.java       |   3 +
 .../iceberg/CommitTransactionEventTest.java        |   4 +
 .../iceberg/IcebergAllowedLocationTest.java        |   4 +
 .../iceberg/IcebergOverlappingTableTest.java       |   3 +
 .../service/catalog/io/FileIOExceptionsTest.java   |  18 +-
 .../generated/bundled-polaris-catalog-service.yaml | 235 +++++++++++++---
 spec/iceberg-rest-catalog-open-api.yaml            | 296 +++++++++++++++++----
 9 files changed, 550 insertions(+), 116 deletions(-)

diff --git 
a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
 
b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
index a240186d0..69735c357 100644
--- 
a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
+++ 
b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
@@ -31,6 +31,7 @@ import jakarta.ws.rs.core.SecurityContext;
 import java.time.Clock;
 import java.util.EnumSet;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.function.Function;
 import org.apache.iceberg.MetadataUpdate;
 import org.apache.iceberg.catalog.Namespace;
@@ -141,6 +142,7 @@ public class IcebergCatalogAdapter
   public Response createNamespace(
       String prefix,
       CreateNamespaceRequest createNamespaceRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     validateIcebergProperties(realmConfig, 
createNamespaceRequest.properties());
@@ -217,7 +219,11 @@ public class IcebergCatalogAdapter
 
   @Override
   public Response dropNamespace(
-      String prefix, String namespace, RealmContext realmContext, 
SecurityContext securityContext) {
+      String prefix,
+      String namespace,
+      UUID idempotencyKey,
+      RealmContext realmContext,
+      SecurityContext securityContext) {
     Namespace ns = decodeNamespace(namespace);
     return withCatalog(
         securityContext,
@@ -233,6 +239,7 @@ public class IcebergCatalogAdapter
       String prefix,
       String namespace,
       UpdateNamespacePropertiesRequest updateNamespacePropertiesRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     validateIcebergProperties(realmConfig, 
updateNamespacePropertiesRequest.updates());
@@ -268,6 +275,7 @@ public class IcebergCatalogAdapter
       String namespace,
       CreateTableRequest createTableRequest,
       String accessDelegationMode,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     validateIcebergProperties(realmConfig, createTableRequest.properties());
@@ -388,6 +396,7 @@ public class IcebergCatalogAdapter
       String prefix,
       String namespace,
       String table,
+      UUID idempotencyKey,
       Boolean purgeRequested,
       RealmContext realmContext,
       SecurityContext securityContext) {
@@ -411,6 +420,8 @@ public class IcebergCatalogAdapter
       String prefix,
       String namespace,
       RegisterTableRequest registerTableRequest,
+      String accessDelegationMode,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     Namespace ns = decodeNamespace(namespace);
@@ -429,6 +440,7 @@ public class IcebergCatalogAdapter
   public Response renameTable(
       String prefix,
       RenameTableRequest renameTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     return withCatalog(
@@ -446,6 +458,7 @@ public class IcebergCatalogAdapter
       String namespace,
       String table,
       CommitTableRequest commitTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     commitTableRequest.updates().stream()
@@ -515,6 +528,7 @@ public class IcebergCatalogAdapter
       String prefix,
       String namespace,
       String table,
+      String planId,
       RealmContext realmContext,
       SecurityContext securityContext) {
     Namespace ns = decodeNamespace(namespace);
@@ -572,6 +586,7 @@ public class IcebergCatalogAdapter
       String prefix,
       String namespace,
       String view,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     Namespace ns = decodeNamespace(namespace);
@@ -589,6 +604,7 @@ public class IcebergCatalogAdapter
   public Response renameView(
       String prefix,
       RenameTableRequest renameTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     return withCatalog(
@@ -606,6 +622,7 @@ public class IcebergCatalogAdapter
       String namespace,
       String view,
       CommitViewRequest commitViewRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     UpdateTableRequest revisedRequest =
@@ -627,6 +644,7 @@ public class IcebergCatalogAdapter
   public Response commitTransaction(
       String prefix,
       CommitTransactionRequest commitTransactionRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     commitTransactionRequest.tableChanges().stream()
diff --git 
a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
 
b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
index ee3def12a..f4a098105 100644
--- 
a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
+++ 
b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
@@ -27,6 +27,7 @@ import jakarta.inject.Inject;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.SecurityContext;
 import java.util.List;
+import java.util.UUID;
 import org.apache.iceberg.TableMetadata;
 import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.rest.requests.CommitTransactionRequest;
@@ -90,6 +91,7 @@ public class IcebergRestCatalogEventServiceDelegator
   public Response createNamespace(
       String prefix,
       CreateNamespaceRequest createNamespaceRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -101,7 +103,8 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.CATALOG_NAME, catalogName)
                 .put(EventAttributes.CREATE_NAMESPACE_REQUEST, 
createNamespaceRequest)));
     Response resp =
-        delegate.createNamespace(prefix, createNamespaceRequest, realmContext, 
securityContext);
+        delegate.createNamespace(
+            prefix, createNamespaceRequest, idempotencyKey, realmContext, 
securityContext);
     CreateNamespaceResponse createNamespaceResponse = 
(CreateNamespaceResponse) resp.getEntity();
     polarisEventListener.onEvent(
         new PolarisEvent(
@@ -192,7 +195,11 @@ public class IcebergRestCatalogEventServiceDelegator
 
   @Override
   public Response dropNamespace(
-      String prefix, String namespace, RealmContext realmContext, 
SecurityContext securityContext) {
+      String prefix,
+      String namespace,
+      UUID idempotencyKey,
+      RealmContext realmContext,
+      SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
     polarisEventListener.onEvent(
         new PolarisEvent(
@@ -201,7 +208,8 @@ public class IcebergRestCatalogEventServiceDelegator
             new EventAttributeMap()
                 .put(EventAttributes.CATALOG_NAME, catalogName)
                 .put(EventAttributes.NAMESPACE, decodeNamespace(namespace))));
-    Response resp = delegate.dropNamespace(prefix, namespace, realmContext, 
securityContext);
+    Response resp =
+        delegate.dropNamespace(prefix, namespace, idempotencyKey, 
realmContext, securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_DROP_NAMESPACE,
@@ -217,6 +225,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String prefix,
       String namespace,
       UpdateNamespacePropertiesRequest updateNamespacePropertiesRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -233,7 +242,12 @@ public class IcebergRestCatalogEventServiceDelegator
                     updateNamespacePropertiesRequest)));
     Response resp =
         delegate.updateProperties(
-            prefix, namespace, updateNamespacePropertiesRequest, realmContext, 
securityContext);
+            prefix,
+            namespace,
+            updateNamespacePropertiesRequest,
+            idempotencyKey,
+            realmContext,
+            securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_UPDATE_NAMESPACE_PROPERTIES,
@@ -253,6 +267,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String namespace,
       CreateTableRequest createTableRequest,
       String accessDelegationMode,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -272,6 +287,7 @@ public class IcebergRestCatalogEventServiceDelegator
             namespace,
             createTableRequest,
             accessDelegationMode,
+            idempotencyKey,
             realmContext,
             securityContext);
     if (!createTableRequest.stageCreate()) {
@@ -397,6 +413,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String prefix,
       String namespace,
       String table,
+      UUID idempotencyKey,
       Boolean purgeRequested,
       RealmContext realmContext,
       SecurityContext securityContext) {
@@ -412,7 +429,14 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.TABLE_NAME, table)
                 .put(EventAttributes.PURGE_REQUESTED, purgeRequested)));
     Response resp =
-        delegate.dropTable(prefix, namespace, table, purgeRequested, 
realmContext, securityContext);
+        delegate.dropTable(
+            prefix,
+            namespace,
+            table,
+            idempotencyKey,
+            purgeRequested,
+            realmContext,
+            securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_DROP_TABLE,
@@ -430,6 +454,8 @@ public class IcebergRestCatalogEventServiceDelegator
       String prefix,
       String namespace,
       RegisterTableRequest registerTableRequest,
+      String accessDelegationMode,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -444,7 +470,13 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.REGISTER_TABLE_REQUEST, 
registerTableRequest)));
     Response resp =
         delegate.registerTable(
-            prefix, namespace, registerTableRequest, realmContext, 
securityContext);
+            prefix,
+            namespace,
+            registerTableRequest,
+            accessDelegationMode,
+            idempotencyKey,
+            realmContext,
+            securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_REGISTER_TABLE,
@@ -461,6 +493,7 @@ public class IcebergRestCatalogEventServiceDelegator
   public Response renameTable(
       String prefix,
       RenameTableRequest renameTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -471,7 +504,9 @@ public class IcebergRestCatalogEventServiceDelegator
             new EventAttributeMap()
                 .put(EventAttributes.CATALOG_NAME, catalogName)
                 .put(EventAttributes.RENAME_TABLE_REQUEST, 
renameTableRequest)));
-    Response resp = delegate.renameTable(prefix, renameTableRequest, 
realmContext, securityContext);
+    Response resp =
+        delegate.renameTable(
+            prefix, renameTableRequest, idempotencyKey, realmContext, 
securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_RENAME_TABLE,
@@ -488,6 +523,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String namespace,
       String table,
       CommitTableRequest commitTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -503,7 +539,13 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.UPDATE_TABLE_REQUEST, 
commitTableRequest)));
     Response resp =
         delegate.updateTable(
-            prefix, namespace, table, commitTableRequest, realmContext, 
securityContext);
+            prefix,
+            namespace,
+            table,
+            commitTableRequest,
+            idempotencyKey,
+            realmContext,
+            securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_UPDATE_TABLE,
@@ -584,6 +626,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String prefix,
       String namespace,
       String table,
+      String planId,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -597,7 +640,7 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.NAMESPACE, namespaceObj)
                 .put(EventAttributes.TABLE_NAME, table)));
     Response resp =
-        delegate.loadCredentials(prefix, namespace, table, realmContext, 
securityContext);
+        delegate.loadCredentials(prefix, namespace, table, planId, 
realmContext, securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_LOAD_CREDENTIALS,
@@ -673,6 +716,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String prefix,
       String namespace,
       String view,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -685,7 +729,8 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.CATALOG_NAME, catalogName)
                 .put(EventAttributes.NAMESPACE, namespaceObj)
                 .put(EventAttributes.VIEW_NAME, view)));
-    Response resp = delegate.dropView(prefix, namespace, view, realmContext, 
securityContext);
+    Response resp =
+        delegate.dropView(prefix, namespace, view, idempotencyKey, 
realmContext, securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_DROP_VIEW,
@@ -701,6 +746,7 @@ public class IcebergRestCatalogEventServiceDelegator
   public Response renameView(
       String prefix,
       RenameTableRequest renameTableRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -711,7 +757,9 @@ public class IcebergRestCatalogEventServiceDelegator
             new EventAttributeMap()
                 .put(EventAttributes.CATALOG_NAME, catalogName)
                 .put(EventAttributes.RENAME_TABLE_REQUEST, 
renameTableRequest)));
-    Response resp = delegate.renameView(prefix, renameTableRequest, 
realmContext, securityContext);
+    Response resp =
+        delegate.renameView(
+            prefix, renameTableRequest, idempotencyKey, realmContext, 
securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_RENAME_VIEW,
@@ -728,6 +776,7 @@ public class IcebergRestCatalogEventServiceDelegator
       String namespace,
       String view,
       CommitViewRequest commitViewRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -743,7 +792,13 @@ public class IcebergRestCatalogEventServiceDelegator
                 .put(EventAttributes.COMMIT_VIEW_REQUEST, commitViewRequest)));
     Response resp =
         delegate.replaceView(
-            prefix, namespace, view, commitViewRequest, realmContext, 
securityContext);
+            prefix,
+            namespace,
+            view,
+            commitViewRequest,
+            idempotencyKey,
+            realmContext,
+            securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_REPLACE_VIEW,
@@ -761,6 +816,7 @@ public class IcebergRestCatalogEventServiceDelegator
   public Response commitTransaction(
       String prefix,
       CommitTransactionRequest commitTransactionRequest,
+      UUID idempotencyKey,
       RealmContext realmContext,
       SecurityContext securityContext) {
     String catalogName = prefixParser.prefixToCatalogName(prefix);
@@ -783,7 +839,8 @@ public class IcebergRestCatalogEventServiceDelegator
                   .put(EventAttributes.UPDATE_TABLE_REQUEST, req)));
     }
     Response resp =
-        delegate.commitTransaction(prefix, commitTransactionRequest, 
realmContext, securityContext);
+        delegate.commitTransaction(
+            prefix, commitTransactionRequest, idempotencyKey, realmContext, 
securityContext);
     polarisEventListener.onEvent(
         new PolarisEvent(
             PolarisEventType.AFTER_COMMIT_TRANSACTION,
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisS3InteroperabilityTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisS3InteroperabilityTest.java
index d984234a6..6f849e3ad 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisS3InteroperabilityTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisS3InteroperabilityTest.java
@@ -28,6 +28,7 @@ import jakarta.ws.rs.core.Response;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.function.Supplier;
 import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.exceptions.ForbiddenException;
@@ -134,6 +135,7 @@ public class PolarisS3InteroperabilityTest {
             .createNamespace(
                 catalogName,
                 createNamespaceRequest,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
@@ -165,6 +167,7 @@ public class PolarisS3InteroperabilityTest {
                 namespace,
                 createTableRequest,
                 null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/CommitTransactionEventTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/CommitTransactionEventTest.java
index 46822e28e..917bb9367 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/CommitTransactionEventTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/CommitTransactionEventTest.java
@@ -27,6 +27,7 @@ import jakarta.ws.rs.core.Response;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import org.apache.iceberg.MetadataUpdate;
 import org.apache.iceberg.TableMetadata;
 import org.apache.iceberg.UpdateRequirement;
@@ -177,6 +178,7 @@ public class CommitTransactionEventTest {
             .createNamespace(
                 catalog,
                 createNamespaceRequest,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
@@ -197,6 +199,7 @@ public class CommitTransactionEventTest {
             namespace,
             createTableRequest,
             null,
+            new UUID(0L, 0L) /* TODO UUID v7 */,
             services.realmContext(),
             services.securityContext());
   }
@@ -235,6 +238,7 @@ public class CommitTransactionEventTest {
           .commitTransaction(
               catalog,
               generateCommitTransactionRequest(shouldFail, table1Name, 
table2Name),
+              new UUID(0L, 0L) /* TODO UUID v7 */,
               testServices.realmContext(),
               testServices.securityContext());
     } catch (Exception ignored) {
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergAllowedLocationTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergAllowedLocationTest.java
index d7a48e481..361b34f79 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergAllowedLocationTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergAllowedLocationTest.java
@@ -102,6 +102,7 @@ public class IcebergAllowedLocationTest {
                     namespace,
                     createTableRequest,
                     null,
+                    new UUID(0L, 0L) /* TODO UUID v7 */,
                     services.realmContext(),
                     services.securityContext()));
   }
@@ -131,6 +132,7 @@ public class IcebergAllowedLocationTest {
                 namespace,
                 createTableRequest,
                 null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext());
 
@@ -327,6 +329,7 @@ public class IcebergAllowedLocationTest {
                 namespace,
                 createTableRequest,
                 null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext());
     
assertThat(createResponse.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
@@ -401,6 +404,7 @@ public class IcebergAllowedLocationTest {
             .createNamespace(
                 catalog,
                 createNamespaceRequest,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergOverlappingTableTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergOverlappingTableTest.java
index d73fd3d1f..9f9adc94f 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergOverlappingTableTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergOverlappingTableTest.java
@@ -76,6 +76,7 @@ public class IcebergOverlappingTableTest {
                 namespace,
                 createTableRequest,
                 null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       return response.getStatus();
@@ -99,6 +100,7 @@ public class IcebergOverlappingTableTest {
                 namespace,
                 createTableRequest,
                 null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       if (response.getStatus() != Response.Status.OK.getStatusCode()) {
@@ -149,6 +151,7 @@ public class IcebergOverlappingTableTest {
             .createNamespace(
                 catalog,
                 createNamespaceRequest,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOExceptionsTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOExceptionsTest.java
index fbc98fa85..3dba4a5f1 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOExceptionsTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOExceptionsTest.java
@@ -30,6 +30,7 @@ import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.stream.Stream;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.catalog.Namespace;
@@ -108,6 +109,7 @@ public class FileIOExceptionsTest {
             .createNamespace(
                 FileIOExceptionsTest.catalog,
                 
CreateNamespaceRequest.builder().withNamespace(Namespace.of("ns1")).build(),
+                new UUID(0L, 0L) /* TODO UUID v7 */,
                 services.realmContext(),
                 services.securityContext())) {
       assertThat(res.getStatus()).isEqualTo(200);
@@ -128,7 +130,13 @@ public class FileIOExceptionsTest {
         services
             .restApi()
             .createTable(
-                catalog, "ns1", request, null, services.realmContext(), 
services.securityContext());
+                catalog,
+                "ns1",
+                request,
+                null,
+                new UUID(0L, 0L) /* TODO UUID v7 */,
+                services.realmContext(),
+                services.securityContext());
     res.close();
   }
 
@@ -137,7 +145,13 @@ public class FileIOExceptionsTest {
         services
             .restApi()
             .dropTable(
-                catalog, "ns1", "t1", false, services.realmContext(), 
services.securityContext());
+                catalog,
+                "ns1",
+                "t1",
+                new UUID(0L, 0L) /* TODO UUID v7 */,
+                false,
+                services.realmContext(),
+                services.securityContext());
     res.close();
   }
 
diff --git a/spec/generated/bundled-polaris-catalog-service.yaml 
b/spec/generated/bundled-polaris-catalog-service.yaml
index 7dffb017d..53cbe35bc 100644
--- a/spec/generated/bundled-polaris-catalog-service.yaml
+++ b/spec/generated/bundled-polaris-catalog-service.yaml
@@ -90,6 +90,7 @@ paths:
                   warehouse: s3://bucket/warehouse/
                 defaults:
                   clients: '4'
+                idempotency-key-lifetime: PT30M
                 endpoints:
                   - GET /v1/{prefix}/namespaces/{namespace}
                   - GET /v1/{prefix}/namespaces
@@ -168,12 +169,10 @@ paths:
       parameters:
         - $ref: '#/components/parameters/page-token'
         - $ref: '#/components/parameters/page-size'
-        - $ref: '#/components/parameters/prefix'
         - name: parent
           in: query
-          description: An optional namespace, underneath which to list 
namespaces. If not provided or empty, all top-level namespaces should be 
listed. If parent is a multipart namespace, the parts must be separated by the 
unit separator (`0x1F`) byte.
+          description: An optional namespace, underneath which to list 
namespaces. If not provided, all top-level namespaces should be listed. For 
backward compatibility, empty string is treated as absent for now. If parent is 
a multipart namespace, the parts must be separated by the namespace separator 
as indicated via the /config override `namespace-separator`, which defaults to 
the unit separator `0x1F` byte (url encoded `%1F`). To be compatible with older 
clients, servers must use bo [...]
           required: false
-          allowEmptyValue: true
           schema:
             type: string
           example: accounting%1Ftax
@@ -205,6 +204,8 @@ paths:
       tags:
         - Catalog API
       summary: Create a namespace
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: Create a namespace, with an optional set of properties. The 
server might also add properties, such as `last_modified_time` etc.
       operationId: createNamespace
       requestBody:
@@ -308,6 +309,8 @@ paths:
         - Catalog API
       summary: Drop a namespace from the catalog. Namespace must be empty.
       operationId: dropNamespace
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       responses:
         '204':
           description: Success, no content
@@ -326,6 +329,15 @@ paths:
               examples:
                 NoSuchNamespaceExample:
                   $ref: '#/components/examples/NoSuchNamespaceError'
+        '409':
+          description: Not Empty - Namespace to delete is not empty.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/IcebergErrorResponse'
+              examples:
+                NamespaceNotEmptyExample:
+                  $ref: '#/components/examples/NamespaceNotEmptyError'
         '419':
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
         '503':
@@ -341,6 +353,8 @@ paths:
         - Catalog API
       summary: Set or remove properties on a namespace
       operationId: updateProperties
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: |-
         Set and/or remove properties on a namespace. The request body 
specifies a list of properties to remove and a map of key value pairs to update.
         Properties that are not in the request are not modified or removed by 
this call.
@@ -400,8 +414,6 @@ paths:
       description: Return all table identifiers under this namespace
       operationId: listTables
       parameters:
-        - $ref: '#/components/parameters/prefix'
-        - $ref: '#/components/parameters/namespace'
         - $ref: '#/components/parameters/page-token'
         - $ref: '#/components/parameters/page-size'
       responses:
@@ -440,9 +452,8 @@ paths:
         If `stage-create` is true, the table is not created, but table 
metadata is initialized and returned. The service should prepare as needed for 
a commit to the table commit endpoint to complete the create transaction. The 
client uses the returned metadata to begin a transaction. To commit the 
transaction, the client sends all create and subsequent changes to the table 
commit route. Changes from the table create operation include changes like 
AddSchemaUpdate and SetCurrentSchemaUpda [...]
       operationId: createTable
       parameters:
-        - $ref: '#/components/parameters/prefix'
-        - $ref: '#/components/parameters/namespace'
         - $ref: '#/components/parameters/data-access'
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         required: true
         content:
@@ -474,7 +485,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/IcebergErrorResponse'
               examples:
-                NamespaceAlreadyExists:
+                TableAlreadyExists:
                   $ref: '#/components/examples/TableAlreadyExistsError'
         '419':
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -490,6 +501,9 @@ paths:
       tags:
         - Catalog API
       summary: Register a table in the given namespace using given metadata 
file location
+      parameters:
+        - $ref: '#/components/parameters/data-access'
+        - $ref: '#/components/parameters/idempotency-key'
       description: Register a table using given metadata file location.
       operationId: registerTable
       requestBody:
@@ -523,7 +537,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/IcebergErrorResponse'
               examples:
-                NamespaceAlreadyExists:
+                TableAlreadyExists:
                   $ref: '#/components/examples/TableAlreadyExistsError'
         '419':
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -550,13 +564,10 @@ paths:
 
         The catalog configuration may contain credentials that should be used 
for subsequent requests for the table. The configuration key "token" is used to 
pass an access token to be used as a bearer token for table requests. 
Otherwise, a token may be passed using a RFC 8693 token type as a configuration 
key. For example, "urn:ietf:params:oauth:token-type:jwt=<JWT-token>".
       parameters:
-        - $ref: '#/components/parameters/prefix'
-        - $ref: '#/components/parameters/namespace'
-        - $ref: '#/components/parameters/table'
         - $ref: '#/components/parameters/data-access'
         - name: If-None-Match
           in: header
-          description: An optional header that allows the server to return 304 
(Not Modified) if the metadata is current. The content is the value of the ETag 
received in a CreateTableResponse or LoadTableResponse.
+          description: An optional header that allows the server to return 304 
(Not Modified) if the metadata is current. The content is the value of the ETag 
received in a CreateTableResponse, LoadTableResponse or CommitTableResponse.
           required: false
           schema:
             type: string
@@ -602,6 +613,8 @@ paths:
         - Catalog API
       summary: Commit updates to a table
       operationId: updateTable
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: |-
         Commit updates to a table.
 
@@ -695,6 +708,7 @@ paths:
       operationId: dropTable
       description: Remove a table from the catalog
       parameters:
+        - $ref: '#/components/parameters/idempotency-key'
         - name: purgeRequested
           in: query
           required: false
@@ -766,6 +780,13 @@ paths:
         - Catalog API
       summary: Load vended credentials for a table from the catalog
       operationId: loadCredentials
+      parameters:
+        - name: planId
+          in: query
+          required: false
+          schema:
+            type: string
+          description: The plan ID that has been used for server-side scan 
planning
       description: Load vended credentials for a table from the catalog.
       responses:
         '200':
@@ -798,6 +819,8 @@ paths:
       tags:
         - Catalog API
       summary: Rename a table from its current name to a new name
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: Rename a table from one identifier to another. It's valid 
to move a table across namespaces, but the server implementation is not 
required to support it.
       operationId: renameTable
       requestBody:
@@ -900,6 +923,8 @@ paths:
         - Catalog API
       summary: Commit updates to multiple tables in an atomic operation
       operationId: commitTransaction
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         description: |-
           Commit updates to multiple tables in an atomic operation
@@ -994,8 +1019,6 @@ paths:
       description: Return all view identifiers under this namespace
       operationId: listViews
       parameters:
-        - $ref: '#/components/parameters/prefix'
-        - $ref: '#/components/parameters/namespace'
         - $ref: '#/components/parameters/page-token'
         - $ref: '#/components/parameters/page-size'
       responses:
@@ -1059,7 +1082,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorModel'
               examples:
-                NamespaceAlreadyExists:
+                ViewAlreadyExists:
                   $ref: '#/components/examples/ViewAlreadyExistsError'
         '419':
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -1114,6 +1137,8 @@ paths:
         - Catalog API
       summary: Replace a view
       operationId: replaceView
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: Commit updates to a view.
       requestBody:
         required: true
@@ -1199,6 +1224,8 @@ paths:
       summary: Drop a view from the catalog
       operationId: dropView
       description: Remove a view from the catalog
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       responses:
         '204':
           description: Success, no content
@@ -1253,6 +1280,8 @@ paths:
       summary: Rename a view from its current name to a new name
       description: Rename a view from one identifier to another. It's valid to 
move a view across namespaces, but the server implementation is not required to 
support it.
       operationId: renameView
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         description: Current view identifier to rename and new view identifier 
to rename to
         content:
@@ -1959,6 +1988,11 @@ components:
             - POST /v1/{prefix}/namespaces
             - GET /v1/{prefix}/namespaces/{namespace}/tables/{table}
             - GET /v1/{prefix}/namespaces/{namespace}/views/{view}
+        idempotency-key-lifetime:
+          type: string
+          format: duration
+          description: Client reuse window for an Idempotency-Key (ISO-8601 
duration, e.g., PT30M, PT24H). Interpreted as the maximum time from the first 
submission using a key to the last retry during which a client may reuse that 
key. Servers SHOULD accept retries for at least this duration and MAY include a 
grace period to account for delays/clock skew. Clients SHOULD NOT reuse an 
Idempotency-Key after this window elapses; they SHOULD generate a new key for 
any subsequent attempt. Pre [...]
+          example: PT30M
     ErrorModel:
       type: object
       description: JSON error payload returned in a response with further 
details on the error
@@ -2355,7 +2389,7 @@ components:
       example: 123.456
     DecimalTypeValue:
       type: string
-      description: Decimal type values are serialized as strings. Decimals 
with a positive scale serialize as numeric plain  text, while decimals with a 
negative scale use scientific notation and the exponent will be equal to the  
negated scale. For instance, a decimal with a positive scale is '123.4500', 
with zero scale is '2',  and with a negative scale is '2E+20'
+      description: Decimal type values are serialized as strings. Decimals 
with a positive scale serialize as numeric plain text, while decimals with a 
negative scale use scientific notation and the exponent will be equal to the 
negated scale. For instance, a decimal with a positive scale is '123.4500', 
with zero scale is '2', and with a negative scale is '2E+20'
       example: '123.4500'
     StringTypeValue:
       type: string
@@ -2366,7 +2400,7 @@ components:
       pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
       maxLength: 36
       minLength: 36
-      description: UUID type values are serialized as a 36-character lowercase 
string in standard UUID format as specified  by RFC-4122
+      description: UUID type values are serialized as a 36-character lowercase 
string in standard UUID format as specified by RFC-4122
       example: eb26bdb1-a1d8-4aa6-990e-da940875492c
     DateTypeValue:
       type: string
@@ -2383,7 +2417,7 @@ components:
       example: '2007-12-03T10:15:30.123456'
     TimestampTzTypeValue:
       type: string
-      description: TimestampTz type values follow the 
'YYYY-MM-DDTHH:MM:SS.ssssss+00:00' ISO-8601 format with microsecond precision,  
and a timezone offset (+00:00 for UTC)
+      description: TimestampTz type values follow the 
'YYYY-MM-DDTHH:MM:SS.ssssss+00:00' ISO-8601 format with microsecond precision, 
and a timezone offset (+00:00 for UTC)
       example: '2007-12-03T10:15:30.123456+00:00'
     TimestampNanoTypeValue:
       type: string
@@ -2391,11 +2425,11 @@ components:
       example: '2007-12-03T10:15:30.123456789'
     TimestampTzNanoTypeValue:
       type: string
-      description: Timestamp_ns type values follow the 
'YYYY-MM-DDTHH:MM:SS.sssssssss+00:00' ISO-8601 format with nanosecond  
precision, and a timezone offset (+00:00 for UTC)
+      description: Timestamp_ns type values follow the 
'YYYY-MM-DDTHH:MM:SS.sssssssss+00:00' ISO-8601 format with nanosecond 
precision, and a timezone offset (+00:00 for UTC)
       example: '2007-12-03T10:15:30.123456789+00:00'
     FixedTypeValue:
       type: string
-      description: Fixed length type values are stored and serialized as an 
uppercase hexadecimal string  preserving the fixed length
+      description: Fixed length type values are stored and serialized as an 
uppercase hexadecimal string preserving the fixed length
       example: 78797A
     BinaryTypeValue:
       type: string
@@ -2551,6 +2585,24 @@ components:
           type: object
           additionalProperties:
             type: string
+    EncryptedKey:
+      type: object
+      required:
+        - key-id
+        - encrypted-key-metadata
+      properties:
+        key-id:
+          type: string
+        encrypted-key-metadata:
+          type: string
+          format: byte
+          contentEncoding: base64
+        encrypted-by-id:
+          type: string
+        properties:
+          type: object
+          additionalProperties:
+            type: string
     Snapshot:
       type: object
       required:
@@ -2574,6 +2626,14 @@ components:
         manifest-list:
           type: string
           description: Location of the snapshot's manifest list file
+        first-row-id:
+          type: integer
+          format: int64
+          description: The first _row_id assigned to the first row in the 
first data file in the first manifest
+        added-rows:
+          type: integer
+          format: int64
+          description: The upper bound of the number of rows with assigned row 
IDs
         summary:
           type: object
           required:
@@ -2715,7 +2775,7 @@ components:
         format-version:
           type: integer
           minimum: 1
-          maximum: 2
+          maximum: 3
         table-uuid:
           type: string
         location:
@@ -2723,6 +2783,10 @@ components:
         last-updated-ms:
           type: integer
           format: int64
+        next-row-id:
+          type: integer
+          format: int64
+          description: A long higher than all assigned row IDs; the next 
snapshot's first-row-id.
         properties:
           type: object
           additionalProperties:
@@ -2749,6 +2813,10 @@ components:
             $ref: '#/components/schemas/SortOrder'
         default-sort-order-id:
           type: integer
+        encryption-keys:
+          type: array
+          items:
+            $ref: '#/components/schemas/EncryptedKey'
         snapshots:
           type: array
           items:
@@ -2802,15 +2870,15 @@ components:
 
         ## General Configurations
 
-        - `token`: Authorization bearer token to use for table requests if 
OAuth2 security is enabled 
+        - `token`: Authorization bearer token to use for table requests if 
OAuth2 security is enabled
 
         ## AWS Configurations
 
         The following configurations should be respected when working with 
tables stored in AWS S3
          - `client.region`: region to configure client for making requests to 
AWS
          - `s3.access-key-id`: id for credentials that provide access to the 
data in S3
-         - `s3.secret-access-key`: secret for credentials that provide access 
to data in S3 
-         - `s3.session-token`: if present, this value should be used for as 
the session token 
+         - `s3.secret-access-key`: secret for credentials that provide access 
to data in S3
+         - `s3.session-token`: if present, this value should be used for as 
the session token
          - `s3.remote-signing-enabled`: if `true` remote signing should be 
performed as described in the `s3-signer-open-api.yaml` specification
          - `s3.cross-region-access-enabled`: if `true`, S3 Cross-Region bucket 
access is enabled
 
@@ -2825,6 +2893,7 @@ components:
         metadata-location:
           type: string
           description: May be null if the table is staged as part of a 
transaction
+          nullable: true
         metadata:
           $ref: '#/components/schemas/TableMetadata'
         config:
@@ -2845,6 +2914,10 @@ components:
           type: string
         metadata-location:
           type: string
+        overwrite:
+          description: Whether to overwrite table metadata if the table 
already exists
+          type: boolean
+          default: false
     TableRequirement:
       type: object
       discriminator:
@@ -2888,7 +2961,10 @@ components:
         uuid:
           type: string
     AssertRefSnapshotId:
-      description: The table branch or tag identified by the requirement's 
`ref` must reference the requirement's `snapshot-id`; if `snapshot-id` is 
`null` or missing, the ref must not already exist
+      description: |
+        The table branch or tag identified by the requirement's `ref` must 
reference the requirement's `snapshot-id`.
+        The `snapshot-id` field is required in this object, but in the case of 
a `null`
+        the ref must not already exist.
       allOf:
         - $ref: '#/components/schemas/TableRequirement'
       required:
@@ -2903,6 +2979,7 @@ components:
         snapshot-id:
           type: integer
           format: int64
+          nullable: true
     AssertLastAssignedFieldId:
       description: The table's last assigned column id must match the 
requirement's `last-assigned-field-id`
       allOf:
@@ -3001,7 +3078,9 @@ components:
           set-partition-statistics: 
'#/components/schemas/SetPartitionStatisticsUpdate'
           remove-partition-statistics: 
'#/components/schemas/RemovePartitionStatisticsUpdate'
           remove-partition-specs: 
'#/components/schemas/RemovePartitionSpecsUpdate'
-          enable-row-lineage: '#/components/schemas/EnableRowLineageUpdate'
+          remove-schemas: '#/components/schemas/RemoveSchemasUpdate'
+          add-encryption-key: '#/components/schemas/AddEncryptionKeyUpdate'
+          remove-encryption-key: 
'#/components/schemas/RemoveEncryptionKeyUpdate'
       type: object
       required:
         - action
@@ -3312,13 +3391,41 @@ components:
           type: array
           items:
             type: integer
-    EnableRowLineageUpdate:
+    RemoveSchemasUpdate:
       allOf:
         - $ref: '#/components/schemas/BaseUpdate'
+      required:
+        - schema-ids
       properties:
         action:
           type: string
-          const: enable-row-lineage
+          const: remove-schemas
+        schema-ids:
+          type: array
+          items:
+            type: integer
+    AddEncryptionKeyUpdate:
+      allOf:
+        - $ref: '#/components/schemas/BaseUpdate'
+      required:
+        - encryption-key
+      properties:
+        action:
+          type: string
+          const: add-encryption-key
+        encryption-key:
+          $ref: '#/components/schemas/EncryptedKey'
+    RemoveEncryptionKeyUpdate:
+      allOf:
+        - $ref: '#/components/schemas/BaseUpdate'
+      required:
+        - key-id
+      properties:
+        action:
+          type: string
+          const: remove-encryption-key
+        key-id:
+          type: string
     TableUpdate:
       anyOf:
         - $ref: '#/components/schemas/AssignUUIDUpdate'
@@ -3338,8 +3445,12 @@ components:
         - $ref: '#/components/schemas/RemovePropertiesUpdate'
         - $ref: '#/components/schemas/SetStatisticsUpdate'
         - $ref: '#/components/schemas/RemoveStatisticsUpdate'
+        - $ref: '#/components/schemas/SetPartitionStatisticsUpdate'
+        - $ref: '#/components/schemas/RemovePartitionStatisticsUpdate'
         - $ref: '#/components/schemas/RemovePartitionSpecsUpdate'
-        - $ref: '#/components/schemas/EnableRowLineageUpdate'
+        - $ref: '#/components/schemas/RemoveSchemasUpdate'
+        - $ref: '#/components/schemas/AddEncryptionKeyUpdate'
+        - $ref: '#/components/schemas/RemoveEncryptionKeyUpdate'
     CommitTableRequest:
       type: object
       required:
@@ -3499,7 +3610,7 @@ components:
         values:
           type: array
           items:
-            type: object
+            $ref: '#/components/schemas/PrimitiveTypeValue'
     LiteralExpression:
       type: object
       required:
@@ -3521,13 +3632,12 @@ components:
         term:
           $ref: '#/components/schemas/Term'
         value:
-          type: object
+          $ref: '#/components/schemas/PrimitiveTypeValue'
     UnaryExpression:
       type: object
       required:
         - type
         - term
-        - value
       properties:
         type:
           $ref: '#/components/schemas/ExpressionType'
@@ -3538,8 +3648,6 @@ components:
             - not-nan
         term:
           $ref: '#/components/schemas/Term'
-        value:
-          type: object
     CounterResult:
       type: object
       required:
@@ -4108,7 +4216,7 @@ components:
               type: BadRequestException
               code: 400
     UnauthorizedResponse:
-      description: Unauthorized. Authentication is required and has failed or 
has not yet been provided.
+      description: Unauthorized. The REST Catalog SHOULD respond with the 401 
UnauthorizedResponse when the access token provided is expired, revoked, 
malformed, or invalid for other reasons. The client MAY request a new access 
token and retry the request.
       content:
         application/json:
           schema:
@@ -4130,7 +4238,7 @@ components:
               type: NotAuthorizedException
               code: 403
     AuthenticationTimeoutResponse:
-      description: Credentials have timed out. If possible, the client should 
refresh credentials and retry.
+      description: This is an optional status response type that the REST 
Catalog can issue when the token has expired. The client MAY request a new 
access token and retry the request. 401 UnauthorizedResponse SHOULD be 
preferred over this response type on token expiry.
       content:
         application/json:
           schema:
@@ -4142,9 +4250,8 @@ components:
               code: 419
     ServiceUnavailableResponse:
       description: |-
-        The service is not ready to handle the request. The client should wait 
and retry.
-
-        The service may additionally send a Retry-After header to indicate 
when to retry.
+        The service is not ready to handle the request, request could have 
been partially processed.
+        The service may additionally send a Retry-After header to indicate 
when to retry, a non idempotent request should only be retried by the client 
when the Retry-After header is present.
       content:
         application/json:
           schema:
@@ -4268,6 +4375,9 @@ components:
         application/json:
           schema:
             $ref: '#/components/schemas/CommitTableResponse'
+      headers:
+        etag:
+          $ref: '#/components/headers/etag'
     LoadCredentialsResponse:
       description: Table credentials result when loading credentials for a 
table
       content:
@@ -4347,7 +4457,6 @@ components:
       name: pageToken
       in: query
       required: false
-      allowEmptyValue: true
       schema:
         $ref: '#/components/schemas/PageToken'
     page-size:
@@ -4358,11 +4467,40 @@ components:
       schema:
         type: integer
         minimum: 1
+    idempotency-key:
+      name: Idempotency-Key
+      in: header
+      required: false
+      schema:
+        type: string
+        format: uuid
+        minLength: 36
+        maxLength: 36
+        example: 017F22E2-79B0-7CC3-98C4-DC0C0C07398F
+      description: |
+        Optional client-provided idempotency key for safe request retries.
+
+        When present, the server ensures no additional effects for requests 
that carry the same
+        Idempotency-Key. If a prior request with this key has been finalized, 
the server returns
+        an equivalent final response without re-running the operation. The 
response body may
+        reflect a newer state of the catalog than existed at the time of the 
commit.
+
+        Finalization rules:
+        - Finalize & replay: 200, 201, 204, and deterministic terminal 4xx 
(including 409
+          such as AlreadyExists, NamespaceNotEmpty, etc.)
+        - Do not finalize (not stored/replayed): 5xx
+
+        Key Requirements:
+        - Key format: UUIDv7 in string form (RFC 9562).
+        - The idempotency key must be globally unique (no reuse across 
different operations).
+        - Catalogs SHOULD NOT expire keys before the end of the advertised 
token lifetime.
+        - If Idempotency-Key is used, clients MUST reuse the same key when 
retrying the same
+          logical operation and MUST generate a new key for a different 
operation.
     namespace:
       name: namespace
       in: path
       required: true
-      description: A namespace identifier as a single string. Multipart 
namespace parts should be separated by the unit separator (`0x1F`) byte.
+      description: A namespace identifier as a single string. Multipart 
namespace parts must be separated by the namespace separator as indicated via 
the /config override `namespace-separator`, which defaults to the unit 
separator `0x1F` byte (url encoded `%1F`). To be compatible with older clients, 
servers must use both the advertised separator and `0x1F` as valid separators 
when decoding namespaces. The `namespace-separator` should be provided in a url 
encoded form.
       schema:
         type: string
       examples:
@@ -4378,7 +4516,7 @@ components:
 
         Specific properties and handling for `vended-credentials` is 
documented in the `LoadTableResult` schema section of this spec document.
 
-        The protocol and specification for `remote-signing` is documented in  
the `s3-signer-open-api.yaml` OpenApi spec in the `aws` module.
+        The protocol and specification for `remote-signing` is documented in 
the `s3-signer-open-api.yaml` OpenApi spec in the `aws` module.
       required: false
       schema:
         type: string
@@ -4452,6 +4590,13 @@ components:
           message: The given namespace already exists
           type: AlreadyExistsException
           code: 409
+    NamespaceNotEmptyError:
+      summary: The requested namespace is not empty
+      value:
+        error:
+          message: The given namespace is not empty
+          type: NamespaceNotEmptyException
+          code: 409
     UpdateAndRemoveNamespacePropertiesRequest:
       summary: An update namespace properties request with both properties to 
remove and properties to upsert.
       value:
@@ -4606,7 +4751,9 @@ components:
     etag:
       name: ETag
       in: header
-      description: Identifies a unique version of the table metadata.
+      description: |-
+        Identifies a unique version of the table metadata.
+        Implementations that support ETags should produce unique tags for 
responses that return different metadata content but represent the same version 
of table metadata.  For example, the `snapshots` query parameter may result in 
different metadata representations depending on whether `refs` or `all` is 
provided, therefore should have distinct ETags.
       required: false
       schema:
         type: string
diff --git a/spec/iceberg-rest-catalog-open-api.yaml 
b/spec/iceberg-rest-catalog-open-api.yaml
index b0140faea..50ed54a6a 100644
--- a/spec/iceberg-rest-catalog-open-api.yaml
+++ b/spec/iceberg-rest-catalog-open-api.yaml
@@ -19,7 +19,8 @@
 
 # CODE_COPIED_TO_POLARIS
 
-# Apache Iceberg Version: 1.10.0
+# Apache Iceberg Version: 1.11.0
+# commit SHA: 459332131f429484177d45acabea8903a45acc4e
 
 ---
 openapi: 3.1.1
@@ -151,6 +152,7 @@ paths:
                 "defaults": {
                   "clients": "4"
                 },
+                "idempotency-key-lifetime": "PT30M",
                 "endpoints": [
                   "GET /v1/{prefix}/namespaces/{namespace}",
                   "GET /v1/{prefix}/namespaces",
@@ -199,13 +201,13 @@ paths:
         This endpoint is used for three purposes -
 
         1. To exchange client credentials (client ID and secret) for an access 
token
-        This uses the client credentials flow.
+           This uses the client credentials flow.
 
         2. To exchange a client token and an identity token for a more 
specific access token
-        This uses the token exchange flow.
+           This uses the token exchange flow.
 
         3. To exchange an access token for one with the same claims and a 
refreshed expiration period
-        This uses the token exchange flow.
+           This uses the token exchange flow.
 
 
         For example, a catalog client may be configured with client 
credentials from the OAuth2
@@ -264,10 +266,13 @@ paths:
           in: query
           description:
             An optional namespace, underneath which to list namespaces.
-            If not provided or empty, all top-level namespaces should be 
listed.
-            If parent is a multipart namespace, the parts must be separated by 
the unit separator (`0x1F`) byte.
+            If not provided, all top-level namespaces should be listed.
+            For backward compatibility, empty string is treated as absent for 
now.
+            If parent is a multipart namespace, the parts must be separated by 
the namespace separator as
+            indicated via the /config override `namespace-separator`, which 
defaults to the unit separator `0x1F` byte (url encoded `%1F`).
+            To be compatible with older clients, servers must use both the 
advertised separator and `0x1F` as valid separators when decoding namespaces.
+            The `namespace-separator` should be provided in a url encoded form.
           required: false
-          allowEmptyValue: true
           schema:
             type: string
           example: "accounting%1Ftax"
@@ -300,6 +305,8 @@ paths:
       tags:
         - Catalog API
       summary: Create a namespace
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Create a namespace, with an optional set of properties.
         The server might also add properties, such as `last_modified_time` etc.
@@ -410,6 +417,8 @@ paths:
         - Catalog API
       summary: Drop a namespace from the catalog. Namespace must be empty.
       operationId: dropNamespace
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       responses:
         204:
           description: Success, no content
@@ -454,6 +463,8 @@ paths:
         - Catalog API
       summary: Set or remove properties on a namespace
       operationId: updateProperties
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Set and/or remove properties on a namespace.
         The request body specifies a list of properties to remove and a map
@@ -566,6 +577,7 @@ paths:
       operationId: createTable
       parameters:
         - $ref: '#/components/parameters/data-access'
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         required: true
         content:
@@ -597,7 +609,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/IcebergErrorResponse'
               examples:
-                NamespaceAlreadyExists:
+                TableAlreadyExists:
                   $ref: '#/components/examples/TableAlreadyExistsError'
         419:
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -628,7 +640,7 @@ paths:
         point-in-time scan of the latest snapshot in the table's main branch.
 
 
-        Responses must include a valid status listed below. A "cancelled" 
status is considered invalid for this endpoint.  
+        Responses must include a valid status listed below. A "cancelled" 
status is considered invalid for this endpoint.
 
         - When "completed" the planning operation has produced plan tasks and
           file scan tasks that must be returned in the response (not fetched
@@ -655,6 +667,8 @@ paths:
           needed by calling cancelPlanning. Cancellation is not necessary after
           fetchScanTasks has been used to fetch scan tasks for each plan task.
       operationId: planTableScan
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         content:
           application/json:
@@ -762,6 +776,8 @@ paths:
         - Catalog API
       summary: Cancels scan planning for a plan-id
       operationId: cancelPlanning
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: >
         Cancels scan planning for a plan-id.
 
@@ -790,6 +806,7 @@ paths:
         404:
           description:
             Not Found
+            - NoSuchPlanIdException, the plan-id does not exist
             - NoSuchTableException, the table does not exist
             - NoSuchNamespaceException, the namespace does not exist
           content:
@@ -797,6 +814,8 @@ paths:
               schema:
                 $ref: '#/components/schemas/IcebergErrorResponse'
               examples:
+                PlanIdDoesNotExist:
+                  $ref: '#/components/examples/NoSuchPlanIdError'
                 TableDoesNotExist:
                   $ref: '#/components/examples/NoSuchTableError'
                 NamespaceDoesNotExist:
@@ -820,6 +839,8 @@ paths:
         - Catalog API
       summary: Fetches result tasks for a plan task
       operationId: fetchScanTasks
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description: Fetches result tasks for a plan task.
       requestBody:
         content:
@@ -859,8 +880,6 @@ paths:
         5XX:
           $ref: '#/components/responses/ServerErrorResponse'
 
-
-
   /v1/{prefix}/namespaces/{namespace}/register:
     parameters:
       - $ref: '#/components/parameters/prefix'
@@ -870,6 +889,9 @@ paths:
       tags:
         - Catalog API
       summary: Register a table in the given namespace using given metadata 
file location
+      parameters:
+        - $ref: '#/components/parameters/data-access'
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Register a table using given metadata file location.
 
@@ -905,7 +927,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/IcebergErrorResponse'
               examples:
-                NamespaceAlreadyExists:
+                TableAlreadyExists:
                   $ref: '#/components/examples/TableAlreadyExistsError'
         419:
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -947,8 +969,8 @@ paths:
           in: header
           description:
             An optional header that allows the server to return 304 (Not 
Modified) if the metadata
-            is current. The content is the value of the ETag received in a 
CreateTableResponse or
-            LoadTableResponse.
+            is current. The content is the value of the ETag received in a 
CreateTableResponse,
+            LoadTableResponse or CommitTableResponse.
           required: false
           schema:
             type: string
@@ -958,7 +980,7 @@ paths:
             The snapshots to return in the body of the metadata. Setting the 
value to `all` would
             return the full set of snapshots currently valid for the table. 
Setting the value to
             `refs` would load all snapshots referenced by branches or tags.
-            
+
             Default if no param is provided is `all`.
           required: false
           schema:
@@ -999,6 +1021,8 @@ paths:
         - Catalog API
       summary: Commit updates to a table
       operationId: updateTable
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Commit updates to a table.
 
@@ -1119,6 +1143,7 @@ paths:
       operationId: dropTable
       description: Remove a table from the catalog
       parameters:
+        - $ref: '#/components/parameters/idempotency-key'
         - name: purgeRequested
           in: query
           required: false
@@ -1196,6 +1221,13 @@ paths:
         - Catalog API
       summary: Load vended credentials for a table from the catalog
       operationId: loadCredentials
+      parameters:
+        - name: planId
+          in: query
+          required: false
+          schema:
+            type: string
+          description: The plan ID that has been used for server-side scan 
planning
       description: Load vended credentials for a table from the catalog.
       responses:
         200:
@@ -1231,6 +1263,8 @@ paths:
       tags:
         - Catalog API
       summary: Rename a table from its current name to a new name
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Rename a table from one identifier to another. It's valid to move a 
table
         across namespaces, but the server implementation is not required to 
support it.
@@ -1338,6 +1372,8 @@ paths:
         - Catalog API
       summary: Commit updates to multiple tables in an atomic operation
       operationId: commitTransaction
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         description:
           Commit updates to multiple tables in an atomic operation
@@ -1521,7 +1557,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorModel'
               examples:
-                NamespaceAlreadyExists:
+                ViewAlreadyExists:
                   $ref: '#/components/examples/ViewAlreadyExistsError'
         419:
           $ref: '#/components/responses/AuthenticationTimeoutResponse'
@@ -1587,6 +1623,8 @@ paths:
         - Catalog API
       summary: Replace a view
       operationId: replaceView
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       description:
         Commit updates to a view.
       requestBody:
@@ -1688,6 +1726,8 @@ paths:
       summary: Drop a view from the catalog
       operationId: dropView
       description: Remove a view from the catalog
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       responses:
         204:
           description: Success, no content
@@ -1749,6 +1789,8 @@ paths:
         Rename a view from one identifier to another. It's valid to move a view
         across namespaces, but the server implementation is not required to 
support it.
       operationId: renameView
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
       requestBody:
         description: Current view identifier to rename and new view identifier 
to rename to
         content:
@@ -1799,6 +1841,60 @@ paths:
         5XX:
           $ref: '#/components/responses/ServerErrorResponse'
 
+  /v1/{prefix}/namespaces/{namespace}/register-view:
+    parameters:
+      - $ref: '#/components/parameters/prefix'
+      - $ref: '#/components/parameters/namespace'
+
+    post:
+      tags:
+        - Catalog API
+      summary: Register a view in the catalog
+      parameters:
+        - $ref: '#/components/parameters/idempotency-key'
+      description:
+        Register a view in the given namespace using given metadata file 
location.
+
+      operationId: registerView
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/RegisterViewRequest'
+      responses:
+        200:
+          $ref: '#/components/responses/LoadViewResponse'
+        400:
+          $ref: '#/components/responses/BadRequestErrorResponse'
+        401:
+          $ref: '#/components/responses/UnauthorizedResponse'
+        403:
+          $ref: '#/components/responses/ForbiddenResponse'
+        404:
+          description: Not Found - The namespace specified does not exist
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/IcebergErrorResponse'
+              examples:
+                NamespaceNotFound:
+                  $ref: '#/components/examples/NoSuchNamespaceError'
+        409:
+          description: Conflict - The identifier already exists as a table or 
view
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/IcebergErrorResponse'
+              examples:
+                ViewAlreadyExists:
+                  $ref: '#/components/examples/ViewAlreadyExistsError'
+        419:
+          $ref: '#/components/responses/AuthenticationTimeoutResponse'
+        503:
+          $ref: '#/components/responses/ServiceUnavailableResponse'
+        5XX:
+          $ref: '#/components/responses/ServerErrorResponse'
 
 components:
   #######################################################
@@ -1811,7 +1907,10 @@ components:
       required: true
       description:
         A namespace identifier as a single string.
-        Multipart namespace parts should be separated by the unit separator 
(`0x1F`) byte.
+        Multipart namespace parts must be separated by the namespace separator 
as
+        indicated via the /config override `namespace-separator`, which 
defaults to the unit separator `0x1F` byte (url encoded `%1F`).
+        To be compatible with older clients, servers must use both the 
advertised separator and `0x1F` as valid separators when decoding namespaces.
+        The `namespace-separator` should be provided in a url encoded form.
       schema:
         type: string
       examples:
@@ -1861,13 +1960,13 @@ components:
         Optional signal to the server that the client supports delegated access
         via a comma-separated list of access mechanisms.  The server may choose
         to supply access via any or none of the requested mechanisms.
-        
-        
+
+
         Specific properties and handling for `vended-credentials` is documented
         in the `LoadTableResult` schema section of this spec document.
-        
-        
-        The protocol and specification for `remote-signing` is documented in 
+
+
+        The protocol and specification for `remote-signing` is documented in
         the `s3-signer-open-api.yaml` OpenApi spec in the `aws` module.
 
       required: false
@@ -1884,7 +1983,6 @@ components:
       name: pageToken
       in: query
       required: false
-      allowEmptyValue: true
       schema:
         $ref: '#/components/schemas/PageToken'
 
@@ -1902,10 +2000,46 @@ components:
     etag:
       name: ETag
       in: header
-      description: Identifies a unique version of the table metadata.
+      description:
+        Identifies a unique version of the table metadata.
+
+        Implementations that support ETags should produce unique tags for 
responses that return
+        different metadata content but represent the same version of table 
metadata.  For example,
+        the `snapshots` query parameter may result in different metadata 
representations depending
+        on whether `refs` or `all` is provided, therefore should have distinct 
ETags.
+      required: false
+      schema:
+        type: string
+
+    idempotency-key:
+      name: Idempotency-Key
+      in: header
       required: false
       schema:
         type: string
+        format: uuid
+        minLength: 36
+        maxLength: 36
+        example: "017F22E2-79B0-7CC3-98C4-DC0C0C07398F"
+      description: |
+        Optional client-provided idempotency key for safe request retries.
+
+        When present, the server ensures no additional effects for requests 
that carry the same
+        Idempotency-Key. If a prior request with this key has been finalized, 
the server returns
+        an equivalent final response without re-running the operation. The 
response body may
+        reflect a newer state of the catalog than existed at the time of the 
commit.
+
+        Finalization rules:
+        - Finalize & replay: 200, 201, 204, and deterministic terminal 4xx 
(including 409
+          such as AlreadyExists, NamespaceNotEmpty, etc.)
+        - Do not finalize (not stored/replayed): 5xx
+
+        Key Requirements:
+        - Key format: UUIDv7 in string form (RFC 9562).
+        - The idempotency key must be globally unique (no reuse across 
different operations).
+        - Catalogs SHOULD NOT expire keys before the end of the advertised 
token lifetime.
+        - If Idempotency-Key is used, clients MUST reuse the same key when 
retrying the same
+          logical operation and MUST generate a new key for a different 
operation.
 
   ##############################
   # Application Schema Objects #
@@ -1970,6 +2104,18 @@ components:
             "GET /v1/{prefix}/namespaces/{namespace}/tables/{table}",
             "GET /v1/{prefix}/namespaces/{namespace}/views/{view}"
           ]
+        idempotency-key-lifetime:
+          type: string
+          format: duration
+          description:
+            Client reuse window for an Idempotency-Key (ISO-8601 duration, 
e.g., PT30M, PT24H).
+            Interpreted as the maximum time from the first submission using a 
key to the last retry
+            during which a client may reuse that key. Servers SHOULD accept 
retries for at least this
+            duration and MAY include a grace period to account for 
delays/clock skew. Clients SHOULD NOT
+            reuse an Idempotency-Key after this window elapses; they SHOULD 
generate a new key for any
+            subsequent attempt. Presence of this field indicates the server 
supports Idempotency-Key
+            semantics for mutation endpoints. If absent, clients MUST assume 
idempotency is not supported.
+          example: PT30M
 
     CreateNamespaceRequest:
       type: object
@@ -2024,20 +2170,20 @@ components:
         An opaque token that allows clients to make use of pagination for list 
APIs
         (e.g. ListTables). Clients may initiate the first paginated request by 
sending an empty
         query parameter `pageToken` to the server.
-        
+
         Servers that support pagination should identify the `pageToken` 
parameter and return a
         `next-page-token` in the response if there are more results available. 
 After the initial
         request, the value of `next-page-token` from each response must be 
used as the `pageToken`
         parameter value for the next request. The server must return `null` 
value for the
         `next-page-token` in the last response.
-        
+
         Servers that support pagination must return all results in a single 
response with the value
         of `next-page-token` set to `null` if the query parameter `pageToken` 
is not set in the
         request.
-        
+
         Servers that do not support pagination should ignore the `pageToken` 
parameter and return
         all results in a single response. The `next-page-token` must be 
omitted from the response.
-        
+
         Clients must interpret either `null` or missing response value of 
`next-page-token` as
         the end of the listing results.
 
@@ -2246,15 +2392,12 @@ components:
       required:
         - type
         - term
-        - value
       properties:
         type:
           $ref: '#/components/schemas/ExpressionType'
           enum: ["is-null", "not-null", "is-nan", "not-nan"]
         term:
           $ref: '#/components/schemas/Term'
-        value:
-          type: object
 
     LiteralExpression:
       type: object
@@ -2269,7 +2412,7 @@ components:
         term:
           $ref: '#/components/schemas/Term'
         value:
-          type: object
+          $ref: '#/components/schemas/PrimitiveTypeValue'
 
     SetExpression:
       type: object
@@ -2286,7 +2429,7 @@ components:
         values:
           type: array
           items:
-            type: object
+            $ref: '#/components/schemas/PrimitiveTypeValue'
 
     Term:
       oneOf:
@@ -2402,7 +2545,7 @@ components:
           type: string
         encrypted-key-metadata:
           type: string
-          format: byte # for compatibility
+          format: byte  # for compatibility
           contentEncoding: base64
         encrypted-by-id:
           type: string
@@ -2438,6 +2581,10 @@ components:
           type: integer
           format: int64
           description: The first _row_id assigned to the first row in the 
first data file in the first manifest
+        added-rows:
+          type: integer
+          format: int64
+          description: The upper bound of the number of rows with assigned row 
IDs
         summary:
           type: object
           required:
@@ -3078,6 +3225,8 @@ components:
         - $ref: '#/components/schemas/RemovePropertiesUpdate'
         - $ref: '#/components/schemas/SetStatisticsUpdate'
         - $ref: '#/components/schemas/RemoveStatisticsUpdate'
+        - $ref: '#/components/schemas/SetPartitionStatisticsUpdate'
+        - $ref: '#/components/schemas/RemovePartitionStatisticsUpdate'
         - $ref: '#/components/schemas/RemovePartitionSpecsUpdate'
         - $ref: '#/components/schemas/RemoveSchemasUpdate'
         - $ref: '#/components/schemas/AddEncryptionKeyUpdate'
@@ -3286,21 +3435,21 @@ components:
 
 
         The `config` map returns table-specific configuration for the table's 
resources, including its HTTP client and FileIO. For example, config may 
contain a specific FileIO implementation class for the table depending on its 
underlying storage.
-        
-        
+
+
         The following configurations should be respected by clients:
-        
+
         ## General Configurations
-        
-        - `token`: Authorization bearer token to use for table requests if 
OAuth2 security is enabled 
-        
+
+        - `token`: Authorization bearer token to use for table requests if 
OAuth2 security is enabled
+
         ## AWS Configurations
-        
+
         The following configurations should be respected when working with 
tables stored in AWS S3
          - `client.region`: region to configure client for making requests to 
AWS
          - `s3.access-key-id`: id for credentials that provide access to the 
data in S3
-         - `s3.secret-access-key`: secret for credentials that provide access 
to data in S3 
-         - `s3.session-token`: if present, this value should be used for as 
the session token 
+         - `s3.secret-access-key`: secret for credentials that provide access 
to data in S3
+         - `s3.session-token`: if present, this value should be used for as 
the session token
          - `s3.remote-signing-enabled`: if `true` remote signing should be 
performed as described in the `s3-signer-open-api.yaml` specification
          - `s3.cross-region-access-enabled`: if `true`, S3 Cross-Region bucket 
access is enabled
 
@@ -3373,12 +3522,24 @@ components:
             status:
               $ref: '#/components/schemas/PlanStatus'
               const: "completed"
+            storage-credentials:
+              type: array
+              description:
+                Storage credentials for accessing the files returned in the 
scan result.
+
+                If the server returns storage credentials as part of the 
completed scan
+                planning response, the expectation is for the client to use 
these credentials
+                to read the files returned in the FileScanTasks as part of the 
scan result.
+              items:
+                $ref: '#/components/schemas/StorageCredential'
 
     CompletedPlanningWithIDResult:
       type: object
       allOf:
         - $ref: '#/components/schemas/CompletedPlanningResult'
         - type: object
+          required:
+            - plan-id
           properties:
             plan-id:
               description: ID used to track a planning request
@@ -3401,6 +3562,7 @@ components:
       type: object
       required:
         - status
+        - plan-id
       properties:
         status:
           $ref: '#/components/schemas/PlanStatus'
@@ -3596,6 +3758,17 @@ components:
           additionalProperties:
             type: string
 
+    RegisterViewRequest:
+      type: object
+      required:
+        - name
+        - metadata-location
+      properties:
+        name:
+          type: string
+        metadata-location:
+          type: string
+
     TokenType:
       type: string
       enum:
@@ -4112,9 +4285,9 @@ components:
     DecimalTypeValue:
       type: string
       description:
-        "Decimal type values are serialized as strings. Decimals with a 
positive scale serialize as numeric plain 
-        text, while decimals with a negative scale use scientific notation and 
the exponent will be equal to the 
-        negated scale. For instance, a decimal with a positive scale is 
'123.4500', with zero scale is '2', 
+        "Decimal type values are serialized as strings. Decimals with a 
positive scale serialize as numeric plain
+        text, while decimals with a negative scale use scientific notation and 
the exponent will be equal to the
+        negated scale. For instance, a decimal with a positive scale is 
'123.4500', with zero scale is '2',
         and with a negative scale is '2E+20'"
       example: "123.4500"
 
@@ -4129,7 +4302,7 @@ components:
       maxLength: 36
       minLength: 36
       description:
-        "UUID type values are serialized as a 36-character lowercase string in 
standard UUID format as specified 
+        "UUID type values are serialized as a 36-character lowercase string in 
standard UUID format as specified
         by RFC-4122"
       example: "eb26bdb1-a1d8-4aa6-990e-da940875492c"
 
@@ -4155,7 +4328,7 @@ components:
     TimestampTzTypeValue:
       type: string
       description:
-        "TimestampTz type values follow the 'YYYY-MM-DDTHH:MM:SS.ssssss+00:00' 
ISO-8601 format with microsecond precision, 
+        "TimestampTz type values follow the 'YYYY-MM-DDTHH:MM:SS.ssssss+00:00' 
ISO-8601 format with microsecond precision,
         and a timezone offset (+00:00 for UTC)"
       example: "2007-12-03T10:15:30.123456+00:00"
 
@@ -4168,14 +4341,14 @@ components:
     TimestampTzNanoTypeValue:
       type: string
       description:
-        "Timestamp_ns type values follow the 
'YYYY-MM-DDTHH:MM:SS.sssssssss+00:00' ISO-8601 format with nanosecond 
+        "Timestamp_ns type values follow the 
'YYYY-MM-DDTHH:MM:SS.sssssssss+00:00' ISO-8601 format with nanosecond
         precision, and a timezone offset (+00:00 for UTC)"
       example: "2007-12-03T10:15:30.123456789+00:00"
 
     FixedTypeValue:
       type: string
       description:
-        "Fixed length type values are stored and serialized as an uppercase 
hexadecimal string 
+        "Fixed length type values are stored and serialized as an uppercase 
hexadecimal string
         preserving the fixed length"
       example: "78797A"
 
@@ -4201,7 +4374,7 @@ components:
       example:
         {
           "keys": [ 1, 2 ],
-          "values": [ 100,200 ]
+          "values": [ 100, 200 ]
         }
 
     ValueMap:
@@ -4403,6 +4576,14 @@ components:
           description:
             Expression used to filter the table data
           $ref: '#/components/schemas/Expression'
+        min-rows-requested:
+          description:
+            The minimum number of rows requested for the scan. This is used as 
a hint
+            to the server to not have to return more rows than necessary. It 
is not required
+            for the server to return that many rows since the scan may not 
produce that
+            many rows. The server can also return more rows than requested.
+          type: integer
+          format: int64
         case-sensitive:
           description: Enables case sensitive field matching for filter and 
select
           type: boolean
@@ -4440,14 +4621,14 @@ components:
 
         The nested field name follows these rules
         - Nested struct fields are named by concatenating field names at each
-        struct level using dot (`.`) delimiter, e.g.
-        employer.contact_info.address.zip_code
+          struct level using dot (`.`) delimiter, e.g.
+          employer.contact_info.address.zip_code
         - Nested fields in a map key are named using the keyword `key`, e.g.
-        employee_address_map.key.first_name
+          employee_address_map.key.first_name
         - Nested fields in a map value are named using the keyword `value`,
-        e.g. employee_address_map.value.zip_code
+          e.g. employee_address_map.value.zip_code
         - Nested fields in a list are named using the keyword `element`, e.g.
-        employees.element.first_name
+          employees.element.first_name
       type: string
 
     FetchScanTasksRequest:
@@ -4756,6 +4937,9 @@ components:
         application/json:
           schema:
             $ref: '#/components/schemas/CommitTableResponse'
+      headers:
+        etag:
+          $ref: '#/components/parameters/etag'
 
     LoadCredentialsResponse:
       description: Table credentials result when loading credentials for a 
table

Reply via email to