Repository: googleapis/java-storage
Pull request #2425 (2024-02-23 09:13:06)

deps: update dependency net.jqwik:jqwik to v1.8.3
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [net.jqwik:jqwik](https://jqwik.net/) ([source](https://togithub.com/jqwik-team/jqwik)) | `1.8.2` -> `1.8.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/net.jqwik:jqwik/1.8.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/net.jqwik:jqwik/1.8.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/net.jqwik:jqwik/1.8.2/1.8.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/net.jqwik:jqwik/1.8.2/1.8.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>jqwik-team/jqwik (net.jqwik:jqwik)</summary>

### [`v1.8.3`](https://togithub.com/jqwik-team/jqwik/releases/tag/1.8.3): Platform Upgrade and a few Fixes

[Compare Source](https://togithub.com/jqwik-team/jqwik/compare/1.8.2...1.8.3)

##### New and Enhanced Features

-   Upgraded to KotlinX 1.8.0

-   Upgraded to JUnit Platform 1.10.2

-   Upgraded to Kotlin 1.9.22

##### Breaking Changes

*No breaking changes*

##### Bug Fixes

-   Shrinking of strings with uniqueChars() constraint did not work properly.
    See [issue 541](https://togithub.com/jqwik-team/jqwik/issues/541).

-   Fixed integer generation bug with uniform distribution.
    See [issue 544](https://togithub.com/jqwik-team/jqwik/issues/544):

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-storage).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->



Patch:
diff --git a/README.md b/README.md
index fe5244ca..b8a64db0 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies:
 <dependency>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-storage</artifactId>
-  <version>2.33.0</version>
+  <version>2.34.0</version>
 </dependency>
 
 ```
@@ -237,6 +237,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/
 | Create Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) |
 | Create Bucket Dual Region | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) |
 | Create Bucket Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) |
+| Create Bucket With Object Retention | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithObjectRetention.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithObjectRetention.java) |
 | Create Bucket With Storage Class And Location | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) |
 | Create Bucket With Turbo Replication | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) |
 | Delete Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) |
@@ -322,6 +323,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/
 | Rotate Object Encryption Key | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/RotateObjectEncryptionKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/RotateObjectEncryptionKey.java) |
 | Set Event Based Hold | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/SetEventBasedHold.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/SetEventBasedHold.java) |
 | Set Object Metadata | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/SetObjectMetadata.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/SetObjectMetadata.java) |
+| Set Object Retention Policy | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/SetObjectRetentionPolicy.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/SetObjectRetentionPolicy.java) |
 | Set Temporary Hold | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/SetTemporaryHold.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/SetTemporaryHold.java) |
 | Stream Object Download | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/StreamObjectDownload.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/StreamObjectDownload.java) |
 | Stream Object Upload | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/object/StreamObjectUpload.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/object/StreamObjectUpload.java) |
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
index 4034eb12..83ed6ef7 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageSettings.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageSettings.java
index 9a8b62b7..8c3a2fdd 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageSettings.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import static com.google.storage.v2.StorageClient.ListNotificationConfigsPagedRe
 import static com.google.storage.v2.StorageClient.ListObjectsPagedResponse;
 
 import com.google.api.core.ApiFunction;
-import com.google.api.core.BetaApi;
 import com.google.api.gax.core.GoogleCredentialsProvider;
 import com.google.api.gax.core.InstantiatingExecutorProvider;
 import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
@@ -293,7 +292,6 @@ public class StorageSettings extends ClientSettings<StorageSettings> {
     return StorageStubSettings.defaultTransportChannelProvider();
   }
 
-  @BetaApi("The surface for customizing headers is not stable yet and may change in the future.")
   public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() {
     return StorageStubSettings.defaultApiClientHeaderProviderBuilder();
   }
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/package-info.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/package-info.java
index 0fc96216..0b7d686c 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/package-info.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageCallableFactory.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageCallableFactory.java
index 4f7f2864..553b1d50 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageCallableFactory.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageCallableFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageStub.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageStub.java
index 0d32d339..1fe477aa 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageStub.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/GrpcStorageStub.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStub.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStub.java
index 5476d4aa..81048896 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStub.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStub.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStubSettings.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStubSettings.java
index a1b9f34d..e4787eb0 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStubSettings.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/stub/StorageStubSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import static com.google.storage.v2.StorageClient.ListObjectsPagedResponse;
 
 import com.google.api.core.ApiFunction;
 import com.google.api.core.ApiFuture;
-import com.google.api.core.BetaApi;
 import com.google.api.gax.core.GaxProperties;
 import com.google.api.gax.core.GoogleCredentialsProvider;
 import com.google.api.gax.core.InstantiatingExecutorProvider;
@@ -678,7 +677,6 @@ public class StorageStubSettings extends StubSettings<StorageStubSettings> {
     return defaultGrpcTransportProviderBuilder().build();
   }
 
-  @BetaApi("The surface for customizing headers is not stable yet and may change in the future.")
   public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() {
     return ApiClientHeaderProvider.newBuilder()
         .setGeneratedLibToken("gapic", GaxProperties.getLibraryVersion(StorageStubSettings.class))
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlClient.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlClient.java
index 10ac2d09..5a782fb2 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlClient.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlSettings.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlSettings.java
index fc29f030..c7f37fa4 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlSettings.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/StorageControlSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package com.google.storage.control.v2;
 import static com.google.storage.control.v2.StorageControlClient.ListFoldersPagedResponse;
 
 import com.google.api.core.ApiFunction;
-import com.google.api.core.BetaApi;
 import com.google.api.gax.core.GoogleCredentialsProvider;
 import com.google.api.gax.core.InstantiatingExecutorProvider;
 import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
@@ -148,7 +147,6 @@ public class StorageControlSettings extends ClientSettings<StorageControlSetting
     return StorageControlStubSettings.defaultTransportChannelProvider();
   }
 
-  @BetaApi("The surface for customizing headers is not stable yet and may change in the future.")
   public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() {
     return StorageControlStubSettings.defaultApiClientHeaderProviderBuilder();
   }
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/package-info.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/package-info.java
index e40eb295..126dd95d 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/package-info.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlCallableFactory.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlCallableFactory.java
index 24311e75..a2dc5b44 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlCallableFactory.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlCallableFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlStub.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlStub.java
index 6e630f3b..3bd55270 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlStub.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/GrpcStorageControlStub.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStub.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStub.java
index 19bee2f6..681466af 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStub.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStub.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java
index 225b5684..c65cddfc 100644
--- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java
+++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -277,7 +277,6 @@ public class StorageControlStubSettings extends StubSettings<StorageControlStubS
     return defaultGrpcTransportProviderBuilder().build();
   }
 
-  @BetaApi("The surface for customizing headers is not stable yet and may change in the future.")
   public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() {
     return ApiClientHeaderProvider.newBuilder()
         .setGeneratedLibToken(
diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml
index 7f599bcc..48c4ff2d 100644
--- a/google-cloud-storage/pom.xml
+++ b/google-cloud-storage/pom.xml
@@ -248,7 +248,7 @@
     <dependency>
       <groupId>net.jqwik</groupId>
       <artifactId>jqwik</artifactId>
-      <version>1.8.2</version>
+      <version>1.8.3</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/pom.xml b/pom.xml
index 1e724000..23422704 100644
--- a/pom.xml
+++ b/pom.xml
@@ -185,7 +185,7 @@
       <dependency>
         <groupId>com.google.truth</groupId>
         <artifactId>truth</artifactId>
-        <version>1.4.0</version>
+        <version>1.4.1</version>
         <scope>test</scope>
         <exclusions>
           <exclusion>
diff --git a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/BucketName.java b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/BucketName.java
index 410eec92..7a301a30 100644
--- a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/BucketName.java
+++ b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/BucketName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/FolderName.java b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/FolderName.java
index a52b0a63..1fc3d295 100644
--- a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/FolderName.java
+++ b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/FolderName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/StorageLayoutName.java b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/StorageLayoutName.java
index 3e81f069..8aa4914d 100644
--- a/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/StorageLayoutName.java
+++ b/proto-google-cloud-storage-control-v2/src/main/java/com/google/storage/control/v2/StorageLayoutName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
index 204313bf..32b659c4 100644
--- a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
+++ b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
@@ -55,4 +55,15 @@
     <className>com/google/storage/v2/*</className>
     <method>* *SoftDeleted*(*)</method>
   </difference>
+
+  <difference>
+    <differenceType>7012</differenceType>
+    <className>com/google/storage/v2/*</className>
+    <method>* *SoftDeleteTime*(*)</method>
+  </difference>
+  <difference>
+    <differenceType>7012</differenceType>
+    <className>com/google/storage/v2/*</className>
+    <method>* *HardDeleteTime*(*)</method>
+  </difference>
 </differences>
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketName.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketName.java
index d2643c96..fec84c52 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketName.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/CryptoKeyName.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/CryptoKeyName.java
index a9d2ffd7..cc44f3f4 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/CryptoKeyName.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/CryptoKeyName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationConfigName.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationConfigName.java
index 3a0c0a36..9d1091b7 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationConfigName.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationConfigName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
index 7748d810..13e834eb 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
@@ -1471,6 +1471,136 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     return customTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : customTime_;
   }
 
+  public static final int SOFT_DELETE_TIME_FIELD_NUMBER = 28;
+  private com.google.protobuf.Timestamp softDeleteTime_;
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return Whether the softDeleteTime field is set.
+   */
+  @java.lang.Override
+  public boolean hasSoftDeleteTime() {
+    return ((bitField0_ & 0x00000400) != 0);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return The softDeleteTime.
+   */
+  @java.lang.Override
+  public com.google.protobuf.Timestamp getSoftDeleteTime() {
+    return softDeleteTime_ == null
+        ? com.google.protobuf.Timestamp.getDefaultInstance()
+        : softDeleteTime_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   */
+  @java.lang.Override
+  public com.google.protobuf.TimestampOrBuilder getSoftDeleteTimeOrBuilder() {
+    return softDeleteTime_ == null
+        ? com.google.protobuf.Timestamp.getDefaultInstance()
+        : softDeleteTime_;
+  }
+
+  public static final int HARD_DELETE_TIME_FIELD_NUMBER = 29;
+  private com.google.protobuf.Timestamp hardDeleteTime_;
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return Whether the hardDeleteTime field is set.
+   */
+  @java.lang.Override
+  public boolean hasHardDeleteTime() {
+    return ((bitField0_ & 0x00000800) != 0);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return The hardDeleteTime.
+   */
+  @java.lang.Override
+  public com.google.protobuf.Timestamp getHardDeleteTime() {
+    return hardDeleteTime_ == null
+        ? com.google.protobuf.Timestamp.getDefaultInstance()
+        : hardDeleteTime_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   */
+  @java.lang.Override
+  public com.google.protobuf.TimestampOrBuilder getHardDeleteTimeOrBuilder() {
+    return hardDeleteTime_ == null
+        ? com.google.protobuf.Timestamp.getDefaultInstance()
+        : hardDeleteTime_;
+  }
+
   private byte memoizedIsInitialized = -1;
 
   @java.lang.Override
@@ -1565,6 +1695,12 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
       com.google.protobuf.GeneratedMessageV3.writeString(output, 27, etag_);
     }
+    if (((bitField0_ & 0x00000400) != 0)) {
+      output.writeMessage(28, getSoftDeleteTime());
+    }
+    if (((bitField0_ & 0x00000800) != 0)) {
+      output.writeMessage(29, getHardDeleteTime());
+    }
     getUnknownFields().writeTo(output);
   }
 
@@ -1664,6 +1800,12 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
       size += com.google.protobuf.GeneratedMessageV3.computeStringSize(27, etag_);
     }
+    if (((bitField0_ & 0x00000400) != 0)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(28, getSoftDeleteTime());
+    }
+    if (((bitField0_ & 0x00000800) != 0)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(29, getHardDeleteTime());
+    }
     size += getUnknownFields().getSerializedSize();
     memoizedSize = size;
     return size;
@@ -1736,6 +1878,14 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     if (hasCustomTime()) {
       if (!getCustomTime().equals(other.getCustomTime())) return false;
     }
+    if (hasSoftDeleteTime() != other.hasSoftDeleteTime()) return false;
+    if (hasSoftDeleteTime()) {
+      if (!getSoftDeleteTime().equals(other.getSoftDeleteTime())) return false;
+    }
+    if (hasHardDeleteTime() != other.hasHardDeleteTime()) return false;
+    if (hasHardDeleteTime()) {
+      if (!getHardDeleteTime().equals(other.getHardDeleteTime())) return false;
+    }
     if (!getUnknownFields().equals(other.getUnknownFields())) return false;
     return true;
   }
@@ -1825,6 +1975,14 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
       hash = (37 * hash) + CUSTOM_TIME_FIELD_NUMBER;
       hash = (53 * hash) + getCustomTime().hashCode();
     }
+    if (hasSoftDeleteTime()) {
+      hash = (37 * hash) + SOFT_DELETE_TIME_FIELD_NUMBER;
+      hash = (53 * hash) + getSoftDeleteTime().hashCode();
+    }
+    if (hasHardDeleteTime()) {
+      hash = (37 * hash) + HARD_DELETE_TIME_FIELD_NUMBER;
+      hash = (53 * hash) + getHardDeleteTime().hashCode();
+    }
     hash = (29 * hash) + getUnknownFields().hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -1994,6 +2152,8 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
         getOwnerFieldBuilder();
         getCustomerEncryptionFieldBuilder();
         getCustomTimeFieldBuilder();
+        getSoftDeleteTimeFieldBuilder();
+        getHardDeleteTimeFieldBuilder();
       }
     }
 
@@ -2070,6 +2230,16 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
         customTimeBuilder_.dispose();
         customTimeBuilder_ = null;
       }
+      softDeleteTime_ = null;
+      if (softDeleteTimeBuilder_ != null) {
+        softDeleteTimeBuilder_.dispose();
+        softDeleteTimeBuilder_ = null;
+      }
+      hardDeleteTime_ = null;
+      if (hardDeleteTimeBuilder_ != null) {
+        hardDeleteTimeBuilder_.dispose();
+        hardDeleteTimeBuilder_ = null;
+      }
       return this;
     }
 
@@ -2216,6 +2386,16 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
         result.customTime_ = customTimeBuilder_ == null ? customTime_ : customTimeBuilder_.build();
         to_bitField0_ |= 0x00000200;
       }
+      if (((from_bitField0_ & 0x08000000) != 0)) {
+        result.softDeleteTime_ =
+            softDeleteTimeBuilder_ == null ? softDeleteTime_ : softDeleteTimeBuilder_.build();
+        to_bitField0_ |= 0x00000400;
+      }
+      if (((from_bitField0_ & 0x10000000) != 0)) {
+        result.hardDeleteTime_ =
+            hardDeleteTimeBuilder_ == null ? hardDeleteTime_ : hardDeleteTimeBuilder_.build();
+        to_bitField0_ |= 0x00000800;
+      }
       result.bitField0_ |= to_bitField0_;
     }
 
@@ -2388,6 +2568,12 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
       if (other.hasCustomTime()) {
         mergeCustomTime(other.getCustomTime());
       }
+      if (other.hasSoftDeleteTime()) {
+        mergeSoftDeleteTime(other.getSoftDeleteTime());
+      }
+      if (other.hasHardDeleteTime()) {
+        mergeHardDeleteTime(other.getHardDeleteTime());
+      }
       this.mergeUnknownFields(other.getUnknownFields());
       onChanged();
       return this;
@@ -2592,6 +2778,18 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
                 bitField0_ |= 0x00000004;
                 break;
               } // case 218
+            case 226:
+              {
+                input.readMessage(getSoftDeleteTimeFieldBuilder().getBuilder(), extensionRegistry);
+                bitField0_ |= 0x08000000;
+                break;
+              } // case 226
+            case 234:
+              {
+                input.readMessage(getHardDeleteTimeFieldBuilder().getBuilder(), extensionRegistry);
+                bitField0_ |= 0x10000000;
+                break;
+              } // case 234
             default:
               {
                 if (!super.parseUnknownField(input, extensionRegistry, tag)) {
@@ -6634,6 +6832,466 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
       return customTimeBuilder_;
     }
 
+    private com.google.protobuf.Timestamp softDeleteTime_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.protobuf.Timestamp,
+            com.google.protobuf.Timestamp.Builder,
+            com.google.protobuf.TimestampOrBuilder>
+        softDeleteTimeBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return Whether the softDeleteTime field is set.
+     */
+    public boolean hasSoftDeleteTime() {
+      return ((bitField0_ & 0x08000000) != 0);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return The softDeleteTime.
+     */
+    public com.google.protobuf.Timestamp getSoftDeleteTime() {
+      if (softDeleteTimeBuilder_ == null) {
+        return softDeleteTime_ == null
+            ? com.google.protobuf.Timestamp.getDefaultInstance()
+            : softDeleteTime_;
+      } else {
+        return softDeleteTimeBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder setSoftDeleteTime(com.google.protobuf.Timestamp value) {
+      if (softDeleteTimeBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        softDeleteTime_ = value;
+      } else {
+        softDeleteTimeBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x08000000;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder setSoftDeleteTime(com.google.protobuf.Timestamp.Builder builderForValue) {
+      if (softDeleteTimeBuilder_ == null) {
+        softDeleteTime_ = builderForValue.build();
+      } else {
+        softDeleteTimeBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x08000000;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder mergeSoftDeleteTime(com.google.protobuf.Timestamp value) {
+      if (softDeleteTimeBuilder_ == null) {
+        if (((bitField0_ & 0x08000000) != 0)
+            && softDeleteTime_ != null
+            && softDeleteTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
+          getSoftDeleteTimeBuilder().mergeFrom(value);
+        } else {
+          softDeleteTime_ = value;
+        }
+      } else {
+        softDeleteTimeBuilder_.mergeFrom(value);
+      }
+      if (softDeleteTime_ != null) {
+        bitField0_ |= 0x08000000;
+        onChanged();
+      }
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder clearSoftDeleteTime() {
+      bitField0_ = (bitField0_ & ~0x08000000);
+      softDeleteTime_ = null;
+      if (softDeleteTimeBuilder_ != null) {
+        softDeleteTimeBuilder_.dispose();
+        softDeleteTimeBuilder_ = null;
+      }
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public com.google.protobuf.Timestamp.Builder getSoftDeleteTimeBuilder() {
+      bitField0_ |= 0x08000000;
+      onChanged();
+      return getSoftDeleteTimeFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public com.google.protobuf.TimestampOrBuilder getSoftDeleteTimeOrBuilder() {
+      if (softDeleteTimeBuilder_ != null) {
+        return softDeleteTimeBuilder_.getMessageOrBuilder();
+      } else {
+        return softDeleteTime_ == null
+            ? com.google.protobuf.Timestamp.getDefaultInstance()
+            : softDeleteTime_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. This is the time when the object became soft-deleted.
+     *
+     * Soft-deleted objects are only accessible if a soft_delete_policy is
+     * enabled. Also see hard_delete_time.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.protobuf.Timestamp,
+            com.google.protobuf.Timestamp.Builder,
+            com.google.protobuf.TimestampOrBuilder>
+        getSoftDeleteTimeFieldBuilder() {
+      if (softDeleteTimeBuilder_ == null) {
+        softDeleteTimeBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.protobuf.Timestamp,
+                com.google.protobuf.Timestamp.Builder,
+                com.google.protobuf.TimestampOrBuilder>(
+                getSoftDeleteTime(), getParentForChildren(), isClean());
+        softDeleteTime_ = null;
+      }
+      return softDeleteTimeBuilder_;
+    }
+
+    private com.google.protobuf.Timestamp hardDeleteTime_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.protobuf.Timestamp,
+            com.google.protobuf.Timestamp.Builder,
+            com.google.protobuf.TimestampOrBuilder>
+        hardDeleteTimeBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return Whether the hardDeleteTime field is set.
+     */
+    public boolean hasHardDeleteTime() {
+      return ((bitField0_ & 0x10000000) != 0);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return The hardDeleteTime.
+     */
+    public com.google.protobuf.Timestamp getHardDeleteTime() {
+      if (hardDeleteTimeBuilder_ == null) {
+        return hardDeleteTime_ == null
+            ? com.google.protobuf.Timestamp.getDefaultInstance()
+            : hardDeleteTime_;
+      } else {
+        return hardDeleteTimeBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder setHardDeleteTime(com.google.protobuf.Timestamp value) {
+      if (hardDeleteTimeBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        hardDeleteTime_ = value;
+      } else {
+        hardDeleteTimeBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x10000000;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder setHardDeleteTime(com.google.protobuf.Timestamp.Builder builderForValue) {
+      if (hardDeleteTimeBuilder_ == null) {
+        hardDeleteTime_ = builderForValue.build();
+      } else {
+        hardDeleteTimeBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x10000000;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder mergeHardDeleteTime(com.google.protobuf.Timestamp value) {
+      if (hardDeleteTimeBuilder_ == null) {
+        if (((bitField0_ & 0x10000000) != 0)
+            && hardDeleteTime_ != null
+            && hardDeleteTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
+          getHardDeleteTimeBuilder().mergeFrom(value);
+        } else {
+          hardDeleteTime_ = value;
+        }
+      } else {
+        hardDeleteTimeBuilder_.mergeFrom(value);
+      }
+      if (hardDeleteTime_ != null) {
+        bitField0_ |= 0x10000000;
+        onChanged();
+      }
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public Builder clearHardDeleteTime() {
+      bitField0_ = (bitField0_ & ~0x10000000);
+      hardDeleteTime_ = null;
+      if (hardDeleteTimeBuilder_ != null) {
+        hardDeleteTimeBuilder_.dispose();
+        hardDeleteTimeBuilder_ = null;
+      }
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public com.google.protobuf.Timestamp.Builder getHardDeleteTimeBuilder() {
+      bitField0_ |= 0x10000000;
+      onChanged();
+      return getHardDeleteTimeFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    public com.google.protobuf.TimestampOrBuilder getHardDeleteTimeOrBuilder() {
+      if (hardDeleteTimeBuilder_ != null) {
+        return hardDeleteTimeBuilder_.getMessageOrBuilder();
+      } else {
+        return hardDeleteTime_ == null
+            ? com.google.protobuf.Timestamp.getDefaultInstance()
+            : hardDeleteTime_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. The time when the object will be permanently deleted.
+     *
+     * Only set when an object becomes soft-deleted with a soft_delete_policy.
+     * Otherwise, the object will not be accessible.
+     * </pre>
+     *
+     * <code>
+     * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.protobuf.Timestamp,
+            com.google.protobuf.Timestamp.Builder,
+            com.google.protobuf.TimestampOrBuilder>
+        getHardDeleteTimeFieldBuilder() {
+      if (hardDeleteTimeBuilder_ == null) {
+        hardDeleteTimeBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.protobuf.Timestamp,
+                com.google.protobuf.Timestamp.Builder,
+                com.google.protobuf.TimestampOrBuilder>(
+                getHardDeleteTime(), getParentForChildren(), isClean());
+        hardDeleteTime_ = null;
+      }
+      return hardDeleteTimeBuilder_;
+    }
+
     @java.lang.Override
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
index ce96b444..db5ea216 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
@@ -939,4 +939,104 @@ public interface ObjectOrBuilder
    * <code>.google.protobuf.Timestamp custom_time = 26;</code>
    */
   com.google.protobuf.TimestampOrBuilder getCustomTimeOrBuilder();
+
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return Whether the softDeleteTime field is set.
+   */
+  boolean hasSoftDeleteTime();
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return The softDeleteTime.
+   */
+  com.google.protobuf.Timestamp getSoftDeleteTime();
+  /**
+   *
+   *
+   * <pre>
+   * Output only. This is the time when the object became soft-deleted.
+   *
+   * Soft-deleted objects are only accessible if a soft_delete_policy is
+   * enabled. Also see hard_delete_time.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp soft_delete_time = 28 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   */
+  com.google.protobuf.TimestampOrBuilder getSoftDeleteTimeOrBuilder();
+
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return Whether the hardDeleteTime field is set.
+   */
+  boolean hasHardDeleteTime();
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   *
+   * @return The hardDeleteTime.
+   */
+  com.google.protobuf.Timestamp getHardDeleteTime();
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The time when the object will be permanently deleted.
+   *
+   * Only set when an object becomes soft-deleted with a soft_delete_policy.
+   * Otherwise, the object will not be accessible.
+   * </pre>
+   *
+   * <code>
+   * optional .google.protobuf.Timestamp hard_delete_time = 29 [(.google.api.field_behavior) = OUTPUT_ONLY];
+   * </code>
+   */
+  com.google.protobuf.TimestampOrBuilder getHardDeleteTimeOrBuilder();
 }
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ProjectName.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ProjectName.java
index b8d7aa7b..1788c480 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ProjectName.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ProjectName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
index 6d6bbc9b..7c9d8f22 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
@@ -762,7 +762,7 @@ public final class StorageProto {
           + "/{project}/buckets/{bucket}/notification"
           + "Configs/{notification_config}\"L\n\022Custome"
           + "rEncryption\022\034\n\024encryption_algorithm\030\001 \001("
-          + "\t\022\030\n\020key_sha256_bytes\030\003 \001(\014\"\202\t\n\006Object\022\021"
+          + "\t\022\030\n\020key_sha256_bytes\030\003 \001(\014\"\254\n\n\006Object\022\021"
           + "\n\004name\030\001 \001(\tB\003\340A\005\0225\n\006bucket\030\002 \001(\tB%\340A\005\372A"
           + "\037\n\035storage.googleapis.com/Bucket\022\014\n\004etag"
           + "\030\033 \001(\t\022\027\n\ngeneration\030\003 \001(\003B\003\340A\005\022\033\n\016metag"
@@ -789,154 +789,158 @@ public final class StorageProto {
           + "\030\030 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\022B\n"
           + "\023customer_encryption\030\031 \001(\0132%.google.stor"
           + "age.v2.CustomerEncryption\022/\n\013custom_time"
-          + "\030\032 \001(\0132\032.google.protobuf.Timestamp\032/\n\rMe"
-          + "tadataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:"
-          + "\0028\001B\023\n\021_event_based_hold\"\316\001\n\023ObjectAcces"
-          + "sControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\016\n\006en"
-          + "tity\030\003 \001(\t\022\027\n\nentity_alt\030\t \001(\tB\003\340A\003\022\021\n\te"
-          + "ntity_id\030\004 \001(\t\022\014\n\004etag\030\010 \001(\t\022\r\n\005email\030\005 "
-          + "\001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014project_team\030\007 \001("
-          + "\0132\036.google.storage.v2.ProjectTeam\"l\n\023Lis"
-          + "tObjectsResponse\022*\n\007objects\030\001 \003(\0132\031.goog"
-          + "le.storage.v2.Object\022\020\n\010prefixes\030\002 \003(\t\022\027"
-          + "\n\017next_page_token\030\003 \001(\t\"3\n\013ProjectTeam\022\026"
-          + "\n\016project_number\030\001 \001(\t\022\014\n\004team\030\002 \001(\t\"\'\n\016"
-          + "ServiceAccount\022\025\n\remail_address\030\001 \001(\t\"*\n"
-          + "\005Owner\022\016\n\006entity\030\001 \001(\t\022\021\n\tentity_id\030\002 \001("
-          + "\t\"C\n\014ContentRange\022\r\n\005start\030\001 \001(\003\022\013\n\003end\030"
-          + "\002 \001(\003\022\027\n\017complete_length\030\003 \001(\0032\252\'\n\007Stora"
-          + "ge\022r\n\014DeleteBucket\022&.google.storage.v2.D"
-          + "eleteBucketRequest\032\026.google.protobuf.Emp"
-          + "ty\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004name\022\013{bucket=**}\022o"
-          + "\n\tGetBucket\022#.google.storage.v2.GetBucke"
-          + "tRequest\032\031.google.storage.v2.Bucket\"\"\332A\004"
-          + "name\212\323\344\223\002\025\022\023\n\004name\022\013{bucket=**}\022\253\001\n\014Crea"
-          + "teBucket\022&.google.storage.v2.CreateBucke"
-          + "tRequest\032\031.google.storage.v2.Bucket\"X\332A\027"
-          + "parent,bucket,bucket_id\212\323\344\223\0028\022\026\n\006parent\022"
-          + "\014{project=**}\022\036\n\016bucket.project\022\014{projec"
-          + "t=**}\022\205\001\n\013ListBuckets\022%.google.storage.v"
-          + "2.ListBucketsRequest\032&.google.storage.v2"
-          + ".ListBucketsResponse\"\'\332A\006parent\212\323\344\223\002\030\022\026\n"
-          + "\006parent\022\014{project=**}\022\223\001\n\031LockBucketRete"
-          + "ntionPolicy\0223.google.storage.v2.LockBuck"
-          + "etRetentionPolicyRequest\032\031.google.storag"
-          + "e.v2.Bucket\"&\332A\006bucket\212\323\344\223\002\027\022\025\n\006bucket\022\013"
-          + "{bucket=**}\022u\n\014GetIamPolicy\022\".google.iam"
-          + ".v1.GetIamPolicyRequest\032\025.google.iam.v1."
-          + "Policy\"*\332A\010resource\212\323\344\223\002\031\022\027\n\010resource\022\013{"
-          + "bucket=**}\022|\n\014SetIamPolicy\022\".google.iam."
-          + "v1.SetIamPolicyRequest\032\025.google.iam.v1.P"
-          + "olicy\"1\332A\017resource,policy\212\323\344\223\002\031\022\027\n\010resou"
-          + "rce\022\013{bucket=**}\022\327\001\n\022TestIamPermissions\022"
-          + "(.google.iam.v1.TestIamPermissionsReques"
-          + "t\032).google.iam.v1.TestIamPermissionsResp"
-          + "onse\"l\332A\024resource,permissions\212\323\344\223\002O\022\027\n\010r"
-          + "esource\022\013{bucket=**}\0224\n\010resource\022({bucke"
-          + "t=projects/*/buckets/*}/objects/**\022\212\001\n\014U"
-          + "pdateBucket\022&.google.storage.v2.UpdateBu"
-          + "cketRequest\032\031.google.storage.v2.Bucket\"7"
-          + "\332A\022bucket,update_mask\212\323\344\223\002\034\022\032\n\013bucket.na"
-          + "me\022\013{bucket=**}\022\237\001\n\030DeleteNotificationCo"
-          + "nfig\0222.google.storage.v2.DeleteNotificat"
-          + "ionConfigRequest\032\026.google.protobuf.Empty"
-          + "\"7\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=project"
-          + "s/*/buckets/*}/**\022\250\001\n\025GetNotificationCon"
-          + "fig\022/.google.storage.v2.GetNotificationC"
-          + "onfigRequest\032%.google.storage.v2.Notific"
-          + "ationConfig\"7\332A\004name\212\323\344\223\002*\022(\n\004name\022 {buc"
-          + "ket=projects/*/buckets/*}/**\022\261\001\n\030CreateN"
-          + "otificationConfig\0222.google.storage.v2.Cr"
-          + "eateNotificationConfigRequest\032%.google.s"
-          + "torage.v2.NotificationConfig\":\332A\032parent,"
-          + "notification_config\212\323\344\223\002\027\022\025\n\006parent\022\013{bu"
-          + "cket=**}\022\250\001\n\027ListNotificationConfigs\0221.g"
-          + "oogle.storage.v2.ListNotificationConfigs"
-          + "Request\0322.google.storage.v2.ListNotifica"
-          + "tionConfigsResponse\"&\332A\006parent\212\323\344\223\002\027\022\025\n\006"
-          + "parent\022\013{bucket=**}\022~\n\rComposeObject\022\'.g"
-          + "oogle.storage.v2.ComposeObjectRequest\032\031."
-          + "google.storage.v2.Object\")\212\323\344\223\002#\022!\n\022dest"
-          + "ination.bucket\022\013{bucket=**}\022\230\001\n\014DeleteOb"
-          + "ject\022&.google.storage.v2.DeleteObjectReq"
-          + "uest\032\026.google.protobuf.Empty\"H\332A\rbucket,"
-          + "object\332A\030bucket,object,generation\212\323\344\223\002\027\022"
-          + "\025\n\006bucket\022\013{bucket=**}\022\215\001\n\rRestoreObject"
-          + "\022\'.google.storage.v2.RestoreObjectReques"
-          + "t\032\031.google.storage.v2.Object\"8\332A\030bucket,"
-          + "object,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{buck"
-          + "et=**}\022\272\001\n\024CancelResumableWrite\022..google"
-          + ".storage.v2.CancelResumableWriteRequest\032"
-          + "/.google.storage.v2.CancelResumableWrite"
-          + "Response\"A\332A\tupload_id\212\323\344\223\002/\022-\n\tupload_i"
-          + "d\022 {bucket=projects/*/buckets/*}/**\022\225\001\n\t"
-          + "GetObject\022#.google.storage.v2.GetObjectR"
-          + "equest\032\031.google.storage.v2.Object\"H\332A\rbu"
-          + "cket,object\332A\030bucket,object,generation\212\323"
-          + "\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\245\001\n\nReadObje"
-          + "ct\022$.google.storage.v2.ReadObjectRequest"
-          + "\032%.google.storage.v2.ReadObjectResponse\""
-          + "H\332A\rbucket,object\332A\030bucket,object,genera"
-          + "tion\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}0\001\022\214\001\n\014"
-          + "UpdateObject\022&.google.storage.v2.UpdateO"
-          + "bjectRequest\032\031.google.storage.v2.Object\""
-          + "9\332A\022object,update_mask\212\323\344\223\002\036\022\034\n\robject.b"
-          + "ucket\022\013{bucket=**}\022`\n\013WriteObject\022%.goog"
-          + "le.storage.v2.WriteObjectRequest\032&.googl"
-          + "e.storage.v2.WriteObjectResponse\"\000(\001\022n\n\017"
-          + "BidiWriteObject\022).google.storage.v2.Bidi"
-          + "WriteObjectRequest\032*.google.storage.v2.B"
-          + "idiWriteObjectResponse\"\000(\0010\001\022\204\001\n\013ListObj"
-          + "ects\022%.google.storage.v2.ListObjectsRequ"
-          + "est\032&.google.storage.v2.ListObjectsRespo"
-          + "nse\"&\332A\006parent\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket="
-          + "**}\022\230\001\n\rRewriteObject\022\'.google.storage.v"
-          + "2.RewriteObjectRequest\032\".google.storage."
-          + "v2.RewriteResponse\":\212\323\344\223\0024\022\017\n\rsource_buc"
-          + "ket\022!\n\022destination_bucket\022\013{bucket=**}\022\256"
-          + "\001\n\023StartResumableWrite\022-.google.storage."
-          + "v2.StartResumableWriteRequest\032..google.s"
-          + "torage.v2.StartResumableWriteResponse\"8\212"
-          + "\323\344\223\0022\0220\n!write_object_spec.resource.buck"
-          + "et\022\013{bucket=**}\022\256\001\n\020QueryWriteStatus\022*.g"
-          + "oogle.storage.v2.QueryWriteStatusRequest"
-          + "\032+.google.storage.v2.QueryWriteStatusRes"
-          + "ponse\"A\332A\tupload_id\212\323\344\223\002/\022-\n\tupload_id\022 "
-          + "{bucket=projects/*/buckets/*}/**\022\200\001\n\021Get"
-          + "ServiceAccount\022+.google.storage.v2.GetSe"
-          + "rviceAccountRequest\032!.google.storage.v2."
-          + "ServiceAccount\"\033\332A\007project\212\323\344\223\002\013\022\t\n\007proj"
-          + "ect\022\225\001\n\rCreateHmacKey\022\'.google.storage.v"
-          + "2.CreateHmacKeyRequest\032(.google.storage."
-          + "v2.CreateHmacKeyResponse\"1\332A\035project,ser"
-          + "vice_account_email\212\323\344\223\002\013\022\t\n\007project\022w\n\rD"
-          + "eleteHmacKey\022\'.google.storage.v2.DeleteH"
-          + "macKeyRequest\032\026.google.protobuf.Empty\"%\332"
-          + "A\021access_id,project\212\323\344\223\002\013\022\t\n\007project\022}\n\n"
-          + "GetHmacKey\022$.google.storage.v2.GetHmacKe"
-          + "yRequest\032\".google.storage.v2.HmacKeyMeta"
-          + "data\"%\332A\021access_id,project\212\323\344\223\002\013\022\t\n\007proj"
-          + "ect\022|\n\014ListHmacKeys\022&.google.storage.v2."
-          + "ListHmacKeysRequest\032\'.google.storage.v2."
-          + "ListHmacKeysResponse\"\033\332A\007project\212\323\344\223\002\013\022\t"
-          + "\n\007project\022\235\001\n\rUpdateHmacKey\022\'.google.sto"
-          + "rage.v2.UpdateHmacKeyRequest\032\".google.st"
-          + "orage.v2.HmacKeyMetadata\"?\332A\024hmac_key,up"
-          + "date_mask\212\323\344\223\002\"\022 \n\020hmac_key.project\022\014{pr"
-          + "oject=**}\032\247\002\312A\026storage.googleapis.com\322A\212"
-          + "\002https://www.googleapis.com/auth/cloud-p"
-          + "latform,https://www.googleapis.com/auth/"
-          + "cloud-platform.read-only,https://www.goo"
-          + "gleapis.com/auth/devstorage.full_control"
-          + ",https://www.googleapis.com/auth/devstor"
-          + "age.read_only,https://www.googleapis.com"
-          + "/auth/devstorage.read_writeB\342\001\n\025com.goog"
-          + "le.storage.v2B\014StorageProtoP\001Z>cloud.goo"
-          + "gle.com/go/storage/internal/apiv2/storag"
-          + "epb;storagepb\352Ax\n!cloudkms.googleapis.co"
-          + "m/CryptoKey\022Sprojects/{project}/location"
-          + "s/{location}/keyRings/{key_ring}/cryptoK"
-          + "eys/{crypto_key}b\006proto3"
+          + "\030\032 \001(\0132\032.google.protobuf.Timestamp\022>\n\020so"
+          + "ft_delete_time\030\034 \001(\0132\032.google.protobuf.T"
+          + "imestampB\003\340A\003H\001\210\001\001\022>\n\020hard_delete_time\030\035"
+          + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003H\002\210"
+          + "\001\001\032/\n\rMetadataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005valu"
+          + "e\030\002 \001(\t:\0028\001B\023\n\021_event_based_holdB\023\n\021_sof"
+          + "t_delete_timeB\023\n\021_hard_delete_time\"\316\001\n\023O"
+          + "bjectAccessControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002"
+          + " \001(\t\022\016\n\006entity\030\003 \001(\t\022\027\n\nentity_alt\030\t \001(\t"
+          + "B\003\340A\003\022\021\n\tentity_id\030\004 \001(\t\022\014\n\004etag\030\010 \001(\t\022\r"
+          + "\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014project"
+          + "_team\030\007 \001(\0132\036.google.storage.v2.ProjectT"
+          + "eam\"l\n\023ListObjectsResponse\022*\n\007objects\030\001 "
+          + "\003(\0132\031.google.storage.v2.Object\022\020\n\010prefix"
+          + "es\030\002 \003(\t\022\027\n\017next_page_token\030\003 \001(\t\"3\n\013Pro"
+          + "jectTeam\022\026\n\016project_number\030\001 \001(\t\022\014\n\004team"
+          + "\030\002 \001(\t\"\'\n\016ServiceAccount\022\025\n\remail_addres"
+          + "s\030\001 \001(\t\"*\n\005Owner\022\016\n\006entity\030\001 \001(\t\022\021\n\tenti"
+          + "ty_id\030\002 \001(\t\"C\n\014ContentRange\022\r\n\005start\030\001 \001"
+          + "(\003\022\013\n\003end\030\002 \001(\003\022\027\n\017complete_length\030\003 \001(\003"
+          + "2\252\'\n\007Storage\022r\n\014DeleteBucket\022&.google.st"
+          + "orage.v2.DeleteBucketRequest\032\026.google.pr"
+          + "otobuf.Empty\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004name\022\013{bu"
+          + "cket=**}\022o\n\tGetBucket\022#.google.storage.v"
+          + "2.GetBucketRequest\032\031.google.storage.v2.B"
+          + "ucket\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004name\022\013{bucket=**"
+          + "}\022\253\001\n\014CreateBucket\022&.google.storage.v2.C"
+          + "reateBucketRequest\032\031.google.storage.v2.B"
+          + "ucket\"X\332A\027parent,bucket,bucket_id\212\323\344\223\0028\022"
+          + "\026\n\006parent\022\014{project=**}\022\036\n\016bucket.projec"
+          + "t\022\014{project=**}\022\205\001\n\013ListBuckets\022%.google"
+          + ".storage.v2.ListBucketsRequest\032&.google."
+          + "storage.v2.ListBucketsResponse\"\'\332A\006paren"
+          + "t\212\323\344\223\002\030\022\026\n\006parent\022\014{project=**}\022\223\001\n\031Lock"
+          + "BucketRetentionPolicy\0223.google.storage.v"
+          + "2.LockBucketRetentionPolicyRequest\032\031.goo"
+          + "gle.storage.v2.Bucket\"&\332A\006bucket\212\323\344\223\002\027\022\025"
+          + "\n\006bucket\022\013{bucket=**}\022u\n\014GetIamPolicy\022\"."
+          + "google.iam.v1.GetIamPolicyRequest\032\025.goog"
+          + "le.iam.v1.Policy\"*\332A\010resource\212\323\344\223\002\031\022\027\n\010r"
+          + "esource\022\013{bucket=**}\022|\n\014SetIamPolicy\022\".g"
+          + "oogle.iam.v1.SetIamPolicyRequest\032\025.googl"
+          + "e.iam.v1.Policy\"1\332A\017resource,policy\212\323\344\223\002"
+          + "\031\022\027\n\010resource\022\013{bucket=**}\022\327\001\n\022TestIamPe"
+          + "rmissions\022(.google.iam.v1.TestIamPermiss"
+          + "ionsRequest\032).google.iam.v1.TestIamPermi"
+          + "ssionsResponse\"l\332A\024resource,permissions\212"
+          + "\323\344\223\002O\022\027\n\010resource\022\013{bucket=**}\0224\n\010resour"
+          + "ce\022({bucket=projects/*/buckets/*}/object"
+          + "s/**\022\212\001\n\014UpdateBucket\022&.google.storage.v"
+          + "2.UpdateBucketRequest\032\031.google.storage.v"
+          + "2.Bucket\"7\332A\022bucket,update_mask\212\323\344\223\002\034\022\032\n"
+          + "\013bucket.name\022\013{bucket=**}\022\237\001\n\030DeleteNoti"
+          + "ficationConfig\0222.google.storage.v2.Delet"
+          + "eNotificationConfigRequest\032\026.google.prot"
+          + "obuf.Empty\"7\332A\004name\212\323\344\223\002*\022(\n\004name\022 {buck"
+          + "et=projects/*/buckets/*}/**\022\250\001\n\025GetNotif"
+          + "icationConfig\022/.google.storage.v2.GetNot"
+          + "ificationConfigRequest\032%.google.storage."
+          + "v2.NotificationConfig\"7\332A\004name\212\323\344\223\002*\022(\n\004"
+          + "name\022 {bucket=projects/*/buckets/*}/**\022\261"
+          + "\001\n\030CreateNotificationConfig\0222.google.sto"
+          + "rage.v2.CreateNotificationConfigRequest\032"
+          + "%.google.storage.v2.NotificationConfig\":"
+          + "\332A\032parent,notification_config\212\323\344\223\002\027\022\025\n\006p"
+          + "arent\022\013{bucket=**}\022\250\001\n\027ListNotificationC"
+          + "onfigs\0221.google.storage.v2.ListNotificat"
+          + "ionConfigsRequest\0322.google.storage.v2.Li"
+          + "stNotificationConfigsResponse\"&\332A\006parent"
+          + "\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}\022~\n\rCompose"
+          + "Object\022\'.google.storage.v2.ComposeObject"
+          + "Request\032\031.google.storage.v2.Object\")\212\323\344\223"
+          + "\002#\022!\n\022destination.bucket\022\013{bucket=**}\022\230\001"
+          + "\n\014DeleteObject\022&.google.storage.v2.Delet"
+          + "eObjectRequest\032\026.google.protobuf.Empty\"H"
+          + "\332A\rbucket,object\332A\030bucket,object,generat"
+          + "ion\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\215\001\n\rRes"
+          + "toreObject\022\'.google.storage.v2.RestoreOb"
+          + "jectRequest\032\031.google.storage.v2.Object\"8"
+          + "\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006buc"
+          + "ket\022\013{bucket=**}\022\272\001\n\024CancelResumableWrit"
+          + "e\022..google.storage.v2.CancelResumableWri"
+          + "teRequest\032/.google.storage.v2.CancelResu"
+          + "mableWriteResponse\"A\332A\tupload_id\212\323\344\223\002/\022-"
+          + "\n\tupload_id\022 {bucket=projects/*/buckets/"
+          + "*}/**\022\225\001\n\tGetObject\022#.google.storage.v2."
+          + "GetObjectRequest\032\031.google.storage.v2.Obj"
+          + "ect\"H\332A\rbucket,object\332A\030bucket,object,ge"
+          + "neration\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\245\001"
+          + "\n\nReadObject\022$.google.storage.v2.ReadObj"
+          + "ectRequest\032%.google.storage.v2.ReadObjec"
+          + "tResponse\"H\332A\rbucket,object\332A\030bucket,obj"
+          + "ect,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket="
+          + "**}0\001\022\214\001\n\014UpdateObject\022&.google.storage."
+          + "v2.UpdateObjectRequest\032\031.google.storage."
+          + "v2.Object\"9\332A\022object,update_mask\212\323\344\223\002\036\022\034"
+          + "\n\robject.bucket\022\013{bucket=**}\022`\n\013WriteObj"
+          + "ect\022%.google.storage.v2.WriteObjectReque"
+          + "st\032&.google.storage.v2.WriteObjectRespon"
+          + "se\"\000(\001\022n\n\017BidiWriteObject\022).google.stora"
+          + "ge.v2.BidiWriteObjectRequest\032*.google.st"
+          + "orage.v2.BidiWriteObjectResponse\"\000(\0010\001\022\204"
+          + "\001\n\013ListObjects\022%.google.storage.v2.ListO"
+          + "bjectsRequest\032&.google.storage.v2.ListOb"
+          + "jectsResponse\"&\332A\006parent\212\323\344\223\002\027\022\025\n\006parent"
+          + "\022\013{bucket=**}\022\230\001\n\rRewriteObject\022\'.google"
+          + ".storage.v2.RewriteObjectRequest\032\".googl"
+          + "e.storage.v2.RewriteResponse\":\212\323\344\223\0024\022\017\n\r"
+          + "source_bucket\022!\n\022destination_bucket\022\013{bu"
+          + "cket=**}\022\256\001\n\023StartResumableWrite\022-.googl"
+          + "e.storage.v2.StartResumableWriteRequest\032"
+          + "..google.storage.v2.StartResumableWriteR"
+          + "esponse\"8\212\323\344\223\0022\0220\n!write_object_spec.res"
+          + "ource.bucket\022\013{bucket=**}\022\256\001\n\020QueryWrite"
+          + "Status\022*.google.storage.v2.QueryWriteSta"
+          + "tusRequest\032+.google.storage.v2.QueryWrit"
+          + "eStatusResponse\"A\332A\tupload_id\212\323\344\223\002/\022-\n\tu"
+          + "pload_id\022 {bucket=projects/*/buckets/*}/"
+          + "**\022\200\001\n\021GetServiceAccount\022+.google.storag"
+          + "e.v2.GetServiceAccountRequest\032!.google.s"
+          + "torage.v2.ServiceAccount\"\033\332A\007project\212\323\344\223"
+          + "\002\013\022\t\n\007project\022\225\001\n\rCreateHmacKey\022\'.google"
+          + ".storage.v2.CreateHmacKeyRequest\032(.googl"
+          + "e.storage.v2.CreateHmacKeyResponse\"1\332A\035p"
+          + "roject,service_account_email\212\323\344\223\002\013\022\t\n\007pr"
+          + "oject\022w\n\rDeleteHmacKey\022\'.google.storage."
+          + "v2.DeleteHmacKeyRequest\032\026.google.protobu"
+          + "f.Empty\"%\332A\021access_id,project\212\323\344\223\002\013\022\t\n\007p"
+          + "roject\022}\n\nGetHmacKey\022$.google.storage.v2"
+          + ".GetHmacKeyRequest\032\".google.storage.v2.H"
+          + "macKeyMetadata\"%\332A\021access_id,project\212\323\344\223"
+          + "\002\013\022\t\n\007project\022|\n\014ListHmacKeys\022&.google.s"
+          + "torage.v2.ListHmacKeysRequest\032\'.google.s"
+          + "torage.v2.ListHmacKeysResponse\"\033\332A\007proje"
+          + "ct\212\323\344\223\002\013\022\t\n\007project\022\235\001\n\rUpdateHmacKey\022\'."
+          + "google.storage.v2.UpdateHmacKeyRequest\032\""
+          + ".google.storage.v2.HmacKeyMetadata\"?\332A\024h"
+          + "mac_key,update_mask\212\323\344\223\002\"\022 \n\020hmac_key.pr"
+          + "oject\022\014{project=**}\032\247\002\312A\026storage.googlea"
+          + "pis.com\322A\212\002https://www.googleapis.com/au"
+          + "th/cloud-platform,https://www.googleapis"
+          + ".com/auth/cloud-platform.read-only,https"
+          + "://www.googleapis.com/auth/devstorage.fu"
+          + "ll_control,https://www.googleapis.com/au"
+          + "th/devstorage.read_only,https://www.goog"
+          + "leapis.com/auth/devstorage.read_writeB\342\001"
+          + "\n\025com.google.storage.v2B\014StorageProtoP\001Z"
+          + ">cloud.google.com/go/storage/internal/ap"
+          + "iv2/storagepb;storagepb\352Ax\n!cloudkms.goo"
+          + "gleapis.com/CryptoKey\022Sprojects/{project"
+          + "}/locations/{location}/keyRings/{key_rin"
+          + "g}/cryptoKeys/{crypto_key}b\006proto3"
     };
     descriptor =
         com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
@@ -1712,6 +1716,8 @@ public final class StorageProto {
               "Owner",
               "CustomerEncryption",
               "CustomTime",
+              "SoftDeleteTime",
+              "HardDeleteTime",
             });
     internal_static_google_storage_v2_Object_MetadataEntry_descriptor =
         internal_static_google_storage_v2_Object_descriptor.getNestedTypes().get(0);
diff --git a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
index de6e27ea..a8516a58 100644
--- a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
+++ b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
@@ -2458,6 +2458,20 @@ message Object {
 
   // A user-specified timestamp set on an object.
   google.protobuf.Timestamp custom_time = 26;
+
+  // Output only. This is the time when the object became soft-deleted.
+  //
+  // Soft-deleted objects are only accessible if a soft_delete_policy is
+  // enabled. Also see hard_delete_time.
+  optional google.protobuf.Timestamp soft_delete_time = 28
+      [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Output only. The time when the object will be permanently deleted.
+  //
+  // Only set when an object becomes soft-deleted with a soft_delete_policy.
+  // Otherwise, the object will not be accessible.
+  optional google.protobuf.Timestamp hard_delete_time = 29
+      [(google.api.field_behavior) = OUTPUT_ONLY];
 }
 
 // An access-control entry.
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index f93fbd2f..4b6b9313 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -30,7 +30,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage</artifactId>
-      <version>2.33.0</version>
+      <version>2.34.0</version>
     </dependency>
     <!-- [END storage_install_without_bom] -->
 
@@ -43,7 +43,7 @@
     <dependency>
       <groupId>com.google.truth</groupId>
       <artifactId>truth</artifactId>
-      <version>1.4.0</version>
+      <version>1.4.1</version>
       <scope>test</scope>
     </dependency>
       <dependency>
diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml
index 861096ac..0f8edc2a 100644
--- a/samples/native-image-sample/pom.xml
+++ b/samples/native-image-sample/pom.xml
@@ -55,7 +55,7 @@
     <dependency>
       <groupId>com.google.truth</groupId>
       <artifactId>truth</artifactId>
-      <version>1.4.0</version>
+      <version>1.4.1</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -134,7 +134,7 @@
           <plugin>
             <groupId>org.graalvm.buildtools</groupId>
             <artifactId>native-maven-plugin</artifactId>
-            <version>0.10.0</version>
+            <version>0.10.1</version>
             <extensions>true</extensions>
             <configuration>
               <mainClass>com.example.storage.NativeImageStorageSample</mainClass>
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 33f142aa..2c845a10 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -40,7 +40,7 @@
     <dependency>
       <groupId>com.google.truth</groupId>
       <artifactId>truth</artifactId>
-      <version>1.4.0</version>
+      <version>1.4.1</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 497c95d7..007949d9 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -54,7 +54,7 @@
     <dependency>
       <groupId>com.google.truth</groupId>
       <artifactId>truth</artifactId>
-      <version>1.4.0</version>
+      <version>1.4.1</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithObjectRetention.java b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithObjectRetention.java
new file mode 100644
index 00000000..5854a6da
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithObjectRetention.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed 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 com.example.storage.bucket;
+
+// [START storage_create_bucket_with_object_retention]
+
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class CreateBucketWithObjectRetention {
+  public static void createBucketWithObjectRetention(String projectId, String bucketName) {
+    // The ID of your GCP project
+    // String projectId = "your-project-id";
+
+    // The ID to give your GCS bucket
+    // String bucketName = "your-unique-bucket-name";
+
+    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+
+    Bucket bucket =
+        storage.create(
+            BucketInfo.of(bucketName), Storage.BucketTargetOption.enableObjectRetention(true));
+
+    System.out.println(
+        "Created bucket "
+            + bucket.getName()
+            + " with object retention enabled setting: "
+            + bucket.getObjectRetention().getMode().toString());
+  }
+}
+
+// [END storage_create_bucket_with_object_retention]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketMetadata.java b/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketMetadata.java
index 95dd5c41..742120f8 100644
--- a/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketMetadata.java
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketMetadata.java
@@ -56,6 +56,7 @@ public class GetBucketMetadata {
     System.out.println("StorageClass: " + bucket.getStorageClass().name());
     System.out.println("TimeCreated: " + bucket.getCreateTime());
     System.out.println("VersioningEnabled: " + bucket.versioningEnabled());
+    System.out.println("ObjectRetention: " + bucket.getObjectRetention());
     if (bucket.getLabels() != null) {
       System.out.println("\n\n\nLabels:");
       for (Map.Entry<String, String> label : bucket.getLabels().entrySet()) {
diff --git a/samples/snippets/src/main/java/com/example/storage/object/GetObjectMetadata.java b/samples/snippets/src/main/java/com/example/storage/object/GetObjectMetadata.java
index 74e452c3..4b6eb42e 100644
--- a/samples/snippets/src/main/java/com/example/storage/object/GetObjectMetadata.java
+++ b/samples/snippets/src/main/java/com/example/storage/object/GetObjectMetadata.java
@@ -68,6 +68,7 @@ public class GetObjectMetadata {
     System.out.println("StorageClass: " + blob.getStorageClass());
     System.out.println("TimeCreated: " + new Date(blob.getCreateTime()));
     System.out.println("Last Metadata Update: " + new Date(blob.getUpdateTime()));
+    System.out.println("Object Retention Policy: " + blob.getRetention());
     Boolean temporaryHoldIsEnabled = (blob.getTemporaryHold() != null && blob.getTemporaryHold());
     System.out.println("temporaryHold: " + (temporaryHoldIsEnabled ? "enabled" : "disabled"));
     Boolean eventBasedHoldIsEnabled =
diff --git a/samples/snippets/src/main/java/com/example/storage/object/SetObjectRetentionPolicy.java b/samples/snippets/src/main/java/com/example/storage/object/SetObjectRetentionPolicy.java
new file mode 100644
index 00000000..6903445a
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/object/SetObjectRetentionPolicy.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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 com.example.storage.object;
+
+// [START storage_set_object_retention_policy]
+
+import static java.time.OffsetDateTime.now;
+
+import com.google.cloud.storage.Blob;
+import com.google.cloud.storage.BlobId;
+import com.google.cloud.storage.BlobInfo.Retention;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageException;
+import com.google.cloud.storage.StorageOptions;
+
+public class SetObjectRetentionPolicy {
+  public static void setObjectRetentionPolicy(
+      String projectId, String bucketName, String objectName) throws StorageException {
+    // The ID of your GCP project
+    // String projectId = "your-project-id";
+
+    // The ID of your GCS bucket that has object retention enabled
+    // String bucketName = "your-unique-bucket-name";
+
+    // The ID of your GCS object
+    // String objectName = "your-object-name";
+
+    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+    BlobId blobId = BlobId.of(bucketName, objectName);
+    Blob blob = storage.get(blobId);
+    if (blob == null) {
+      System.out.println("The object " + objectName + " was not found in " + bucketName);
+      return;
+    }
+
+    Blob updated =
+        blob.toBuilder()
+            .setRetention(
+                Retention.newBuilder()
+                    .setMode(Retention.Mode.UNLOCKED)
+                    .setRetainUntilTime(now().plusDays(10))
+                    .build())
+            .build()
+            .update();
+
+    System.out.println("Retention policy for object " + objectName + " was set to:");
+    System.out.println(updated.getRetention().toString());
+
+    // To modify an existing policy on an Unlocked object, pass in the override parameter
+    blob.toBuilder()
+        .setRetention(
+            updated.getRetention().toBuilder().setRetainUntilTime(now().plusDays(9)).build())
+        .build()
+        .update(Storage.BlobTargetOption.overrideUnlockedRetention(true));
+
+    System.out.println("Retention policy for object " + objectName + " was updated to:");
+    System.out.println(storage.get(blobId).getRetention().toString());
+  }
+}
+
+// [END storage_set_object_retention_policy]


Test patch:
diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorage.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorage.java
index 5f04f6e6..3bee4c25 100644
--- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorage.java
+++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorageImpl.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorageImpl.java
index 33da2cdb..3d39e9d2 100644
--- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorageImpl.java
+++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/MockStorageImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
index b9a9d14f..82a4c7b9 100644
--- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
+++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1382,6 +1382,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -1636,6 +1638,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -1708,6 +1712,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -1817,6 +1823,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -1886,6 +1894,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -1955,6 +1965,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -2027,6 +2039,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -2170,6 +2184,8 @@ public class StorageClientTest {
             .setOwner(Owner.newBuilder().build())
             .setCustomerEncryption(CustomerEncryption.newBuilder().build())
             .setCustomTime(Timestamp.newBuilder().build())
+            .setSoftDeleteTime(Timestamp.newBuilder().build())
+            .setHardDeleteTime(Timestamp.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
 
diff --git a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControl.java b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControl.java
index 0f8d5ed3..6dbac59d 100644
--- a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControl.java
+++ b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControlImpl.java b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControlImpl.java
index b2f2c078..0177422a 100644
--- a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControlImpl.java
+++ b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/MockStorageControlImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/StorageControlClientTest.java b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/StorageControlClientTest.java
index b29a26d8..8559283b 100644
--- a/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/StorageControlClientTest.java
+++ b/google-cloud-storage-control/src/test/java/com/google/storage/control/v2/StorageControlClientTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile b/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile
index 1638c439..3d168312 100644
--- a/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile
+++ b/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile
@@ -1,1 +1,1 @@
-FROM gcr.io/cloud-devrel-public-resources/storage-testbench:v0.40.0
+FROM gcr.io/cloud-devrel-public-resources/storage-testbench:v0.41.0
diff --git a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
index 5bc17937..2f61fdbb 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
@@ -30,6 +30,7 @@ import com.example.storage.bucket.AddBucketLabel;
 import com.example.storage.bucket.ChangeDefaultStorageClass;
 import com.example.storage.bucket.ConfigureBucketCors;
 import com.example.storage.bucket.CreateBucket;
+import com.example.storage.bucket.CreateBucketWithObjectRetention;
 import com.example.storage.bucket.CreateBucketWithStorageClassAndLocation;
 import com.example.storage.bucket.CreateBucketWithTurboReplication;
 import com.example.storage.bucket.DeleteBucket;
@@ -265,6 +266,7 @@ public class ITBucketSnippets {
     assertTrue(snippetOutput.contains("Labels:"));
     assertTrue(snippetOutput.contains("k=v"));
     assertTrue(snippetOutput.contains("Lifecycle Rules:"));
+    assertTrue(snippetOutput.contains("ObjectRetention: " + bucket.getObjectRetention()));
   }
 
   @Test
@@ -662,10 +664,14 @@ public class ITBucketSnippets {
     String tempBucket = RemoteStorageHelper.generateBucketName();
     Bucket bucket = storage.create(BucketInfo.of(tempBucket));
     assertNotNull(bucket);
-    SetRetentionPolicy.setRetentionPolicy(PROJECT_ID, tempBucket, 5L);
-    assertEquals(5L, (long) storage.get(tempBucket).getRetentionPeriod());
-    LockRetentionPolicy.lockRetentionPolicy(PROJECT_ID, tempBucket);
-    assertTrue(storage.get(tempBucket).retentionPolicyIsLocked());
+    try {
+      SetRetentionPolicy.setRetentionPolicy(PROJECT_ID, tempBucket, 5L);
+      assertEquals(5L, (long) storage.get(tempBucket).getRetentionPeriod());
+      LockRetentionPolicy.lockRetentionPolicy(PROJECT_ID, tempBucket);
+      assertTrue(storage.get(tempBucket).retentionPolicyIsLocked());
+    } finally {
+      storage.delete(tempBucket);
+    }
   }
 
   @Test
@@ -682,4 +688,18 @@ public class ITBucketSnippets {
     DisableUniformBucketLevelAccess.disableUniformBucketLevelAccess(PROJECT_ID, BUCKET);
     assertFalse(storage.get(BUCKET).getIamConfiguration().isUniformBucketLevelAccessEnabled());
   }
+
+  @Test
+  public void testCreateBucketWithObjectRetention() {
+    String tempBucket = RemoteStorageHelper.generateBucketName();
+
+    try {
+      CreateBucketWithObjectRetention.createBucketWithObjectRetention(PROJECT_ID, tempBucket);
+      assertNotNull(storage.get(tempBucket).getObjectRetention());
+      String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
+      assertTrue(snippetOutput.contains("Enabled"));
+    } finally {
+      storage.delete(tempBucket);
+    }
+  }
 }
diff --git a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
index 7d7b69d4..feca2ca8 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
@@ -47,6 +47,7 @@ import com.example.storage.object.MakeObjectPublic;
 import com.example.storage.object.MoveObject;
 import com.example.storage.object.RotateObjectEncryptionKey;
 import com.example.storage.object.SetObjectMetadata;
+import com.example.storage.object.SetObjectRetentionPolicy;
 import com.example.storage.object.StreamObjectDownload;
 import com.example.storage.object.StreamObjectUpload;
 import com.example.storage.object.UploadEncryptedObject;
@@ -229,6 +230,7 @@ public class ITObjectSnippets {
     assertTrue(snippetOutput.contains("eventBasedHold: disabled"));
     assertTrue(snippetOutput.contains("User metadata:"));
     assertTrue(snippetOutput.contains("k=v"));
+    assertTrue(snippetOutput.contains("Object Retention Policy: " + remoteBlob.getRetention()));
   }
 
   @Test
@@ -434,4 +436,28 @@ public class ITObjectSnippets {
     assertEquals("value", firstBlobMetadata.get("keyToAddOrUpdate"));
     assertEquals("value", secondBlobMetadata.get("keyToAddOrUpdate"));
   }
+
+  @Test
+  public void testSetObjectRetentionPolicy() {
+    String tempBucket = RemoteStorageHelper.generateBucketName();
+    storage.create(
+        BucketInfo.of(tempBucket), Storage.BucketTargetOption.enableObjectRetention(true));
+    String retentionBlob = "retentionblob";
+    storage.create(BlobInfo.newBuilder(tempBucket, retentionBlob).build());
+    assertNull(storage.get(tempBucket, retentionBlob).getRetention());
+    try {
+      SetObjectRetentionPolicy.setObjectRetentionPolicy(PROJECT_ID, tempBucket, retentionBlob);
+      assertNotNull(storage.get(tempBucket, retentionBlob).getRetention());
+    } finally {
+
+      storage
+          .get(tempBucket, retentionBlob)
+          .toBuilder()
+          .setRetention(null)
+          .build()
+          .update(Storage.BlobTargetOption.overrideUnlockedRetention(true));
+      storage.delete(tempBucket, retentionBlob);
+      storage.delete(tempBucket);
+    }
+  }
 }