Repository: akuity/kargo
Pull request #1611 (2024-03-13 13:46:02)

feat(api/cli): add verification management endpoints
Fixes: #1581

This pull requests adds mechanisms to:

1. Reverify the Freight of a Stage
2. Abort a (long-)running verification for the Freight of a Stage

Both are implemented through annotations (`kargo.akuity.io/reverify` and `kargo.akuity.io/abort`), allowing the behavior to be triggered outside of the API/CLI by annotating the Stage with the respective annotation using the ID of the existing verification information for the Stage as the value.

In addition to this, a `kargo verify stage (NAME) [--abort]` command has been added to make the features available to CLI users.

---

There is more to cover here in the future, e.g. keeping track of a "stack" of `VerificationInfo` objects to provide an historical overview, and to detect changes as mentioned in https://github.com/akuity/kargo/issues/1581#issuecomment-1981166069. However, they are out of scope for this pull request and should be handled as separate feature requests. 

netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *docs-kargo-akuity-io* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 974730e9c6c362774b34d716fb0216d33d9d971a |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/docs-kargo-akuity-io/deploys/65f1ae1d901b300008fa4154 |
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/akuity/kargo/pull/1611?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) Report
Attention: Patch coverage is `43.52941%` with `96 lines` in your changes are missing coverage. Please review.
> Project coverage is 21.12%. Comparing base [(`11c5939`)](https://app.codecov.io/gh/akuity/kargo/commit/11c5939029e5f0c9c4e8864278d4573057ccfda7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) to head [(`974730e`)](https://app.codecov.io/gh/akuity/kargo/pull/1611?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).

| [Files](https://app.codecov.io/gh/akuity/kargo/pull/1611?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) | Patch % | Lines |
|---|---|---|
| [internal/cli/cmd/verify/stage.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-aW50ZXJuYWwvY2xpL2NtZC92ZXJpZnkvc3RhZ2UuZ28=) | 0.00% | [51 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [...nternal/api/request\_stage\_verification\_v1alpha1.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-aW50ZXJuYWwvYXBpL3JlcXVlc3Rfc3RhZ2VfdmVyaWZpY2F0aW9uX3YxYWxwaGExLmdv) | 0.00% | [15 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [internal/cli/cmd/verify/verify.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-aW50ZXJuYWwvY2xpL2NtZC92ZXJpZnkvdmVyaWZ5Lmdv) | 0.00% | [11 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [...ice/v1alpha1/svcv1alpha1connect/service.connect.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-cGtnL2FwaS9zZXJ2aWNlL3YxYWxwaGExL3N2Y3YxYWxwaGExY29ubmVjdC9zZXJ2aWNlLmNvbm5lY3QuZ28=) | 62.50% | [6 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [internal/controller/stages/stages.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-aW50ZXJuYWwvY29udHJvbGxlci9zdGFnZXMvc3RhZ2VzLmdv) | 82.14% | [5 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [api/v1alpha1/stage\_helpers.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-YXBpL3YxYWxwaGExL3N0YWdlX2hlbHBlcnMuZ28=) | 88.57% | [2 Missing and 2 partials :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [internal/controller/stages/verification.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-aW50ZXJuYWwvY29udHJvbGxlci9zdGFnZXMvdmVyaWZpY2F0aW9uLmdv) | 76.92% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |
| [cmd/cli/root.go](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity#diff-Y21kL2NsaS9yb290Lmdv) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/akuity/kargo/pull/1611?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1611      +/-   ##
==========================================
+ Coverage   21.06%   21.12%   +0.06%     
==========================================
  Files         197      200       +3     
  Lines       29015    29226     +211     
==========================================
+ Hits         6111     6174      +63     
- Misses      22624    22771     +147     
- Partials      280      281       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/akuity/kargo/pull/1611?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).


Patch:
diff --git a/api/service/v1alpha1/service.proto b/api/service/v1alpha1/service.proto
index 1d744e3b..58488d13 100644
--- a/api/service/v1alpha1/service.proto
+++ b/api/service/v1alpha1/service.proto
@@ -53,6 +53,11 @@ service KargoService {
   rpc QueryFreight(QueryFreightRequest) returns (QueryFreightResponse);
   rpc UpdateFreightAlias(UpdateFreightAliasRequest) returns (UpdateFreightAliasResponse);
 
+  /* Verification APIs */
+
+  rpc Reverify(ReverifyRequest) returns (ReverifyResponse);
+  rpc AbortVerification(AbortVerificationRequest) returns (AbortVerificationResponse);
+
   /* Warehouse APIs */
 
   rpc ListWarehouses(ListWarehousesRequest) returns (ListWarehousesResponse);
@@ -372,6 +377,24 @@ message UpdateFreightAliasResponse {
   /* explicitly empty */
 }
 
+message ReverifyRequest {
+  string project = 1;
+  string stage = 2;
+}
+
+message ReverifyResponse {
+  /* explicitly empty */
+}
+
+message AbortVerificationRequest {
+  string project = 1;
+  string stage = 2;
+}
+
+message AbortVerificationResponse {
+  /* explicitly empty */
+}
+
 message ListWarehousesRequest {
   string project = 1;
 }
diff --git a/api/v1alpha1/annotations.go b/api/v1alpha1/annotations.go
index 5fdfde77..5e3150fa 100644
--- a/api/v1alpha1/annotations.go
+++ b/api/v1alpha1/annotations.go
@@ -3,6 +3,9 @@ package v1alpha1
 const (
 	AnnotationKeyRefresh = "kargo.akuity.io/refresh"
 
+	AnnotationKeyReverify = "kargo.akuity.io/reverify"
+	AnnotationKeyAbort    = "kargo.akuity.io/abort"
+
 	AnnotationKeyOIDCEmails   = "rbac.kargo.akuity.io/email"
 	AnnotationKeyOIDCGroups   = "rbac.kargo.akuity.io/groups"
 	AnnotationKeyOIDCSubjects = "rbac.kargo.akuity.io/sub"
diff --git a/api/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go
index 34c86cd2..bd6af4dd 100644
--- a/api/v1alpha1/generated.pb.go
+++ b/api/v1alpha1/generated.pb.go
@@ -1781,207 +1781,207 @@ func init() {
 }
 
 var fileDescriptor_e26b7f7bbc391025 = []byte{
-	// 3188 bytes of a gzipped FileDescriptorProto
+	// 3194 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3b, 0xcf, 0x8f, 0x1c, 0x47,
 	0xd5, 0xee, 0x99, 0xf1, 0xec, 0xce, 0x5b, 0xef, 0xaf, 0xf2, 0xda, 0xd9, 0x6c, 0x3e, 0xaf, 0xad,
 	0xfe, 0xf2, 0x45, 0x89, 0x92, 0xcc, 0x7c, 0xb6, 0xb3, 0x89, 0xe3, 0xe4, 0x4b, 0xbe, 0x99, 0x75,
 	0x6c, 0x6f, 0x62, 0x3b, 0x43, 0xad, 0xed, 0x84, 0xfc, 0x10, 0xd4, 0xce, 0xd4, 0xce, 0x74, 0x76,
-	0xa6, 0xbb, 0xd3, 0xd5, 0xb3, 0x66, 0x09, 0x02, 0x02, 0x41, 0xe4, 0x42, 0x40, 0x82, 0x43, 0x38,
-	0x21, 0x01, 0x82, 0x13, 0xdc, 0x38, 0x20, 0x0e, 0x1c, 0xb8, 0x44, 0x1c, 0x50, 0xc4, 0x01, 0x72,
-	0xb2, 0x92, 0x45, 0x70, 0x40, 0x82, 0x3f, 0xc0, 0x12, 0x12, 0xaa, 0x1f, 0xdd, 0x5d, 0xdd, 0xd3,
-	0xb3, 0xdb, 0x3d, 0xb1, 0xad, 0x70, 0x9b, 0x7d, 0xbf, 0xeb, 0xd5, 0xab, 0xf7, 0x5e, 0xbd, 0xae,
-	0x85, 0xc7, 0x3a, 0x96, 0xdf, 0x1d, 0x6c, 0x54, 0x5b, 0x4e, 0xbf, 0x46, 0xb6, 0x06, 0x96, 0xbf,
-	0x53, 0xdb, 0x22, 0x5e, 0xc7, 0xa9, 0x11, 0xd7, 0xaa, 0x6d, 0x9f, 0x24, 0x3d, 0xb7, 0x4b, 0x4e,
-	0xd6, 0x3a, 0xd4, 0xa6, 0x1e, 0xf1, 0x69, 0xbb, 0xea, 0x7a, 0x8e, 0xef, 0xa0, 0xfb, 0x23, 0xae,
-	0xaa, 0xe4, 0xaa, 0x0a, 0xae, 0x2a, 0x71, 0xad, 0x6a, 0xc0, 0xb5, 0xf4, 0xa8, 0x26, 0xbb, 0xe3,
-	0x74, 0x9c, 0x9a, 0x60, 0xde, 0x18, 0x6c, 0x8a, 0xbf, 0xc4, 0x1f, 0xe2, 0x97, 0x14, 0xba, 0xf4,
-	0xd8, 0xd6, 0x19, 0x56, 0xb5, 0x84, 0xe6, 0x3e, 0x69, 0x75, 0x2d, 0x9b, 0x7a, 0x3b, 0x35, 0x77,
-	0xab, 0xc3, 0x01, 0xac, 0xd6, 0xa7, 0x3e, 0xa9, 0x6d, 0x0f, 0x99, 0xb2, 0x54, 0x1b, 0xc5, 0xe5,
-	0x0d, 0x6c, 0xdf, 0xea, 0xd3, 0x21, 0x86, 0xc7, 0xf7, 0x63, 0x60, 0xad, 0x2e, 0xed, 0x93, 0x24,
-	0x9f, 0xf9, 0x1a, 0x1c, 0xae, 0xdb, 0xa4, 0xb7, 0xc3, 0x2c, 0x86, 0x07, 0x76, 0xdd, 0xeb, 0x0c,
-	0xfa, 0xd4, 0xf6, 0xd1, 0x09, 0x28, 0xd9, 0xa4, 0x4f, 0x17, 0x8d, 0x13, 0xc6, 0x83, 0x95, 0xc6,
-	0xa1, 0x0f, 0x6e, 0x1e, 0x3f, 0xb0, 0x7b, 0xf3, 0x78, 0xe9, 0x0a, 0xe9, 0x53, 0x2c, 0x30, 0xe8,
-	0xbf, 0xe1, 0xe0, 0x36, 0xe9, 0x0d, 0xe8, 0x62, 0x41, 0x90, 0x4c, 0x2b, 0x92, 0x83, 0xd7, 0x39,
-	0x10, 0x4b, 0x9c, 0xf9, 0xcd, 0x62, 0x4c, 0xfc, 0x65, 0xea, 0x93, 0x36, 0xf1, 0x09, 0xea, 0x43,
-	0xb9, 0x47, 0x36, 0x68, 0x8f, 0x2d, 0x1a, 0x27, 0x8a, 0x0f, 0x4e, 0x9d, 0x7a, 0xae, 0x9a, 0xc5,
-	0xf5, 0xd5, 0x14, 0x51, 0xd5, 0x4b, 0x42, 0xce, 0x73, 0xb6, 0xef, 0xed, 0x34, 0x66, 0x94, 0x11,
-	0x65, 0x09, 0xc4, 0x4a, 0x09, 0x7a, 0xdb, 0x80, 0x29, 0x62, 0xdb, 0x8e, 0x4f, 0x7c, 0xcb, 0xb1,
-	0xd9, 0x62, 0x41, 0x28, 0x7d, 0x7e, 0x7c, 0xa5, 0xf5, 0x48, 0x98, 0xd4, 0x7c, 0x58, 0x69, 0x9e,
-	0xd2, 0x30, 0x58, 0xd7, 0xb9, 0xf4, 0x24, 0x4c, 0x69, 0xa6, 0xa2, 0x39, 0x28, 0x6e, 0xd1, 0x1d,
-	0xe9, 0x5f, 0xcc, 0x7f, 0xa2, 0x85, 0x98, 0x43, 0x95, 0x07, 0xcf, 0x16, 0xce, 0x18, 0x4b, 0xcf,
-	0xc0, 0x5c, 0x52, 0x61, 0x1e, 0x7e, 0xf3, 0x3d, 0x03, 0x16, 0xb4, 0x55, 0x60, 0xba, 0x49, 0x3d,
-	0x6a, 0xb7, 0x28, 0xaa, 0x41, 0x85, 0xef, 0x25, 0x73, 0x49, 0x2b, 0xd8, 0xea, 0x79, 0xb5, 0x90,
-	0xca, 0x95, 0x00, 0x81, 0x23, 0x9a, 0x30, 0x2c, 0x0a, 0x7b, 0x85, 0x85, 0xdb, 0x25, 0x8c, 0x2e,
-	0x16, 0xe3, 0x61, 0xd1, 0xe4, 0x40, 0x2c, 0x71, 0xe6, 0xff, 0xc1, 0xbd, 0x81, 0x3d, 0x57, 0x69,
-	0xdf, 0xed, 0x11, 0x9f, 0x46, 0x46, 0xed, 0x1b, 0x7a, 0xe6, 0x2c, 0x4c, 0xd7, 0x5d, 0xd7, 0x73,
-	0xb6, 0x69, 0x7b, 0xdd, 0x27, 0x1d, 0x6a, 0x7e, 0xc3, 0x80, 0x23, 0x75, 0xaf, 0xe3, 0xac, 0x9e,
+	0xa6, 0xbb, 0xd3, 0xd5, 0xb3, 0x66, 0x09, 0x02, 0x12, 0x82, 0xc8, 0x85, 0x80, 0x04, 0x87, 0x70,
+	0x42, 0x02, 0x04, 0x27, 0xb8, 0x71, 0x40, 0x1c, 0x38, 0x70, 0x89, 0x38, 0xa0, 0x88, 0x03, 0xe4,
+	0x64, 0x25, 0x8b, 0xb8, 0x20, 0xc1, 0x1f, 0x60, 0x09, 0x09, 0xd5, 0x8f, 0xee, 0xae, 0xee, 0xe9,
+	0xd9, 0xed, 0x9e, 0xd8, 0x56, 0xb8, 0xcd, 0xbe, 0xdf, 0xfd, 0xea, 0xd5, 0x7b, 0xaf, 0x5e, 0xd5,
+	0xc2, 0x63, 0x1d, 0xcb, 0xef, 0x0e, 0x36, 0xaa, 0x2d, 0xa7, 0x5f, 0x23, 0x5b, 0x03, 0xcb, 0xdf,
+	0xa9, 0x6d, 0x11, 0xaf, 0xe3, 0xd4, 0x88, 0x6b, 0xd5, 0xb6, 0x4f, 0x92, 0x9e, 0xdb, 0x25, 0x27,
+	0x6b, 0x1d, 0x6a, 0x53, 0x8f, 0xf8, 0xb4, 0x5d, 0x75, 0x3d, 0xc7, 0x77, 0xd0, 0xfd, 0x11, 0x57,
+	0x55, 0x72, 0x55, 0x05, 0x57, 0x95, 0xb8, 0x56, 0x35, 0xe0, 0x5a, 0x7a, 0x54, 0x93, 0xdd, 0x71,
+	0x3a, 0x4e, 0x4d, 0x30, 0x6f, 0x0c, 0x36, 0xc5, 0x5f, 0xe2, 0x0f, 0xf1, 0x4b, 0x0a, 0x5d, 0x7a,
+	0x6c, 0xeb, 0x0c, 0xab, 0x5a, 0x42, 0x73, 0x9f, 0xb4, 0xba, 0x96, 0x4d, 0xbd, 0x9d, 0x9a, 0xbb,
+	0xd5, 0xe1, 0x00, 0x56, 0xeb, 0x53, 0x9f, 0xd4, 0xb6, 0x87, 0x4c, 0x59, 0xaa, 0x8d, 0xe2, 0xf2,
+	0x06, 0xb6, 0x6f, 0xf5, 0xe9, 0x10, 0xc3, 0xe3, 0xfb, 0x31, 0xb0, 0x56, 0x97, 0xf6, 0x49, 0x92,
+	0xcf, 0x7c, 0x0d, 0x0e, 0xd7, 0x6d, 0xd2, 0xdb, 0x61, 0x16, 0xc3, 0x03, 0xbb, 0xee, 0x75, 0x06,
+	0x7d, 0x6a, 0xfb, 0xe8, 0x04, 0x94, 0x6c, 0xd2, 0xa7, 0x8b, 0xc6, 0x09, 0xe3, 0xc1, 0x4a, 0xe3,
+	0xd0, 0x87, 0x37, 0x8f, 0x1f, 0xd8, 0xbd, 0x79, 0xbc, 0x74, 0x85, 0xf4, 0x29, 0x16, 0x18, 0xf4,
+	0xdf, 0x70, 0x70, 0x9b, 0xf4, 0x06, 0x74, 0xb1, 0x20, 0x48, 0xa6, 0x15, 0xc9, 0xc1, 0xeb, 0x1c,
+	0x88, 0x25, 0xce, 0xfc, 0x56, 0x31, 0x26, 0xfe, 0x32, 0xf5, 0x49, 0x9b, 0xf8, 0x04, 0xf5, 0xa1,
+	0xdc, 0x23, 0x1b, 0xb4, 0xc7, 0x16, 0x8d, 0x13, 0xc5, 0x07, 0xa7, 0x4e, 0x3d, 0x57, 0xcd, 0xe2,
+	0xfa, 0x6a, 0x8a, 0xa8, 0xea, 0x25, 0x21, 0xe7, 0x39, 0xdb, 0xf7, 0x76, 0x1a, 0x33, 0xca, 0x88,
+	0xb2, 0x04, 0x62, 0xa5, 0x04, 0xbd, 0x6d, 0xc0, 0x14, 0xb1, 0x6d, 0xc7, 0x27, 0xbe, 0xe5, 0xd8,
+	0x6c, 0xb1, 0x20, 0x94, 0x3e, 0x3f, 0xbe, 0xd2, 0x7a, 0x24, 0x4c, 0x6a, 0x3e, 0xac, 0x34, 0x4f,
+	0x69, 0x18, 0xac, 0xeb, 0x5c, 0x7a, 0x12, 0xa6, 0x34, 0x53, 0xd1, 0x1c, 0x14, 0xb7, 0xe8, 0x8e,
+	0xf4, 0x2f, 0xe6, 0x3f, 0xd1, 0x42, 0xcc, 0xa1, 0xca, 0x83, 0x67, 0x0b, 0x67, 0x8c, 0xa5, 0x67,
+	0x60, 0x2e, 0xa9, 0x30, 0x0f, 0xbf, 0xf9, 0xbe, 0x01, 0x0b, 0xda, 0x57, 0x60, 0xba, 0x49, 0x3d,
+	0x6a, 0xb7, 0x28, 0xaa, 0x41, 0x85, 0xaf, 0x25, 0x73, 0x49, 0x2b, 0x58, 0xea, 0x79, 0xf5, 0x21,
+	0x95, 0x2b, 0x01, 0x02, 0x47, 0x34, 0x61, 0x58, 0x14, 0xf6, 0x0a, 0x0b, 0xb7, 0x4b, 0x18, 0x5d,
+	0x2c, 0xc6, 0xc3, 0xa2, 0xc9, 0x81, 0x58, 0xe2, 0xcc, 0xff, 0x83, 0x7b, 0x03, 0x7b, 0xae, 0xd2,
+	0xbe, 0xdb, 0x23, 0x3e, 0x8d, 0x8c, 0xda, 0x37, 0xf4, 0xcc, 0x59, 0x98, 0xae, 0xbb, 0xae, 0xe7,
+	0x6c, 0xd3, 0xf6, 0xba, 0x4f, 0x3a, 0xd4, 0x7c, 0xc7, 0x80, 0x23, 0x75, 0xaf, 0xe3, 0xac, 0x9e,
 	0xab, 0xbb, 0xee, 0x45, 0x4a, 0x7a, 0x7e, 0x77, 0xdd, 0x27, 0xfe, 0x80, 0xa1, 0x67, 0xa0, 0xcc,
 	0xc4, 0x2f, 0x25, 0xee, 0x81, 0x20, 0x42, 0x24, 0xfe, 0xd6, 0xcd, 0xe3, 0x0b, 0x29, 0x8c, 0x14,
-	0x2b, 0x2e, 0xf4, 0x10, 0x4c, 0xf4, 0x29, 0x63, 0xa4, 0x13, 0xac, 0x79, 0x56, 0x09, 0x98, 0xb8,
-	0x2c, 0xc1, 0x38, 0xc0, 0x9b, 0xbf, 0x2f, 0xc0, 0x6c, 0x28, 0x4b, 0xa9, 0xbf, 0x03, 0x0e, 0x1e,
-	0xc0, 0xa1, 0xae, 0xb6, 0x42, 0xe1, 0xe7, 0xa9, 0x53, 0x4f, 0x65, 0x8c, 0xe5, 0x34, 0x27, 0x35,
-	0x16, 0x94, 0x9a, 0x43, 0x3a, 0x14, 0xc7, 0xd4, 0xa0, 0x3e, 0x00, 0xdb, 0xb1, 0x5b, 0x4a, 0x69,
-	0x49, 0x28, 0x7d, 0x32, 0xa7, 0xd2, 0xf5, 0x50, 0x40, 0x03, 0x29, 0x95, 0x10, 0xc1, 0xb0, 0xa6,
-	0xc0, 0xfc, 0xa5, 0x01, 0x87, 0x53, 0xf8, 0xd0, 0xd3, 0x89, 0xfd, 0xbc, 0x7f, 0x68, 0x3f, 0xd1,
-	0x10, 0x5b, 0xb4, 0x9b, 0x8f, 0xc0, 0xa4, 0x47, 0xb7, 0x2d, 0x66, 0x39, 0xb6, 0xf2, 0xf0, 0x9c,
-	0xe2, 0x9f, 0xc4, 0x0a, 0x8e, 0x43, 0x0a, 0xf4, 0x30, 0x54, 0x82, 0xdf, 0xdc, 0xcd, 0x45, 0x1e,
-	0xce, 0x7c, 0xe3, 0x02, 0x52, 0x86, 0x23, 0xbc, 0xf9, 0x0f, 0x43, 0xdb, 0xfd, 0x6b, 0x6e, 0x9b,
-	0xf8, 0x94, 0x07, 0x0f, 0x71, 0xdd, 0x2b, 0x51, 0x30, 0x87, 0xc1, 0x53, 0x97, 0x60, 0x1c, 0xe0,
-	0xd1, 0x19, 0x38, 0xa4, 0x7e, 0xca, 0x58, 0x91, 0xd6, 0x85, 0x1b, 0x53, 0xd7, 0x70, 0x38, 0x46,
-	0x89, 0x06, 0x30, 0xcd, 0x9c, 0x81, 0xd7, 0xa2, 0x52, 0xa9, 0xb4, 0x74, 0xea, 0xd4, 0x99, 0x3c,
-	0x7b, 0xb3, 0xae, 0x09, 0x68, 0x1c, 0x51, 0x4a, 0xa7, 0x75, 0x28, 0xc3, 0x71, 0x2d, 0xe6, 0x9b,
-	0x00, 0x92, 0xf7, 0x22, 0xed, 0xf5, 0x51, 0x0b, 0xca, 0x56, 0x9f, 0x74, 0x68, 0x90, 0xcf, 0x73,
-	0x85, 0x23, 0x97, 0xb0, 0xc6, 0xb9, 0x95, 0x01, 0x61, 0x16, 0x17, 0x40, 0x86, 0x95, 0x68, 0xf3,
-	0xfd, 0xf0, 0x94, 0x27, 0x38, 0x78, 0xd2, 0x11, 0x34, 0xca, 0xcd, 0x61, 0xd2, 0x11, 0x34, 0x58,
-	0xe2, 0xd0, 0x31, 0x99, 0x31, 0xa5, 0x67, 0xa7, 0x14, 0x49, 0xf1, 0x05, 0xba, 0x23, 0xd3, 0xe7,
-	0x53, 0x41, 0xfa, 0x94, 0x89, 0xeb, 0x7f, 0x62, 0xf5, 0x8c, 0xe7, 0x09, 0x4d, 0xa1, 0x80, 0x5d,
-	0xdd, 0x71, 0xc3, 0x3a, 0xf7, 0x56, 0xb0, 0xf9, 0x2f, 0x0c, 0x98, 0xef, 0xf4, 0xad, 0x2f, 0x53,
-	0xd4, 0x4d, 0xb8, 0xe4, 0xff, 0xf3, 0xb8, 0x24, 0x14, 0x93, 0xc5, 0x2f, 0x1e, 0x2c, 0x8d, 0xe6,
-	0xca, 0xe6, 0x9b, 0x1a, 0x54, 0x06, 0x8c, 0x9e, 0xb3, 0x3a, 0x94, 0xf9, 0xc2, 0x43, 0x93, 0x51,
-	0x9e, 0xba, 0x16, 0x20, 0x70, 0x44, 0x63, 0xfe, 0xbd, 0x00, 0x68, 0x38, 0x76, 0x78, 0xc4, 0x7b,
-	0xd4, 0x75, 0xae, 0xe1, 0x4b, 0xc9, 0x88, 0xc7, 0x12, 0x8c, 0x03, 0x3c, 0xb7, 0xab, 0xd5, 0x25,
-	0x9e, 0x9f, 0xec, 0x1f, 0x56, 0x39, 0x10, 0x4b, 0x1c, 0x6a, 0xc2, 0xc2, 0x40, 0x48, 0xbe, 0x4a,
-	0xbc, 0x0e, 0xf5, 0x83, 0x93, 0x27, 0xf6, 0x68, 0xb2, 0xf1, 0x5f, 0x8a, 0x67, 0xe1, 0x5a, 0x0a,
-	0x0d, 0x4e, 0xe5, 0x44, 0x1b, 0x50, 0xd9, 0x0a, 0xdc, 0xa4, 0xd2, 0xd8, 0xca, 0x58, 0x3b, 0x23,
-	0x73, 0x41, 0xf8, 0x27, 0x8e, 0xc4, 0xa2, 0x2b, 0x50, 0xea, 0xd2, 0x5e, 0x7f, 0xf1, 0xa0, 0x10,
-	0xff, 0xbf, 0x79, 0xcf, 0x42, 0x63, 0x92, 0xa7, 0x7c, 0xfe, 0x0b, 0x0b, 0x39, 0xe6, 0xd7, 0x40,
-	0x7a, 0x25, 0x8f, 0x7b, 0xf7, 0x2f, 0x24, 0x0f, 0xc1, 0xc4, 0x36, 0xf5, 0x42, 0x77, 0x6a, 0xc2,
-	0xae, 0x4b, 0x30, 0x0e, 0xf0, 0xe6, 0xcf, 0x0c, 0x98, 0x17, 0x16, 0xac, 0x0f, 0x36, 0x58, 0xcb,
-	0xb3, 0x5c, 0xde, 0x88, 0xdc, 0x5e, 0x6b, 0xce, 0xc1, 0x1c, 0xa3, 0xfd, 0x6d, 0xea, 0xad, 0x3a,
-	0x36, 0xf3, 0x3d, 0x62, 0xd9, 0xbe, 0x32, 0x6b, 0x51, 0x51, 0xcf, 0xad, 0x27, 0xf0, 0x78, 0x88,
-	0xc3, 0xfc, 0x69, 0x09, 0x26, 0xce, 0x7b, 0xd4, 0xea, 0x74, 0x7d, 0xf4, 0x45, 0x98, 0xec, 0xab,
-	0x7e, 0x4d, 0xd8, 0xc7, 0x77, 0x42, 0x36, 0xc9, 0x55, 0xbd, 0x49, 0xae, 0xba, 0x5b, 0x1d, 0x0e,
-	0x60, 0x55, 0x4e, 0x5d, 0xdd, 0x3e, 0x59, 0x7d, 0x71, 0xe3, 0x0d, 0xda, 0xf2, 0x79, 0xaf, 0x17,
-	0x95, 0xa9, 0x08, 0x86, 0x43, 0xa9, 0x3c, 0x84, 0x49, 0xcf, 0x22, 0x6c, 0x71, 0x22, 0x1e, 0xc2,
-	0x75, 0x0e, 0xc4, 0x12, 0xc7, 0x8f, 0xd6, 0x0d, 0xe2, 0xd1, 0xae, 0x33, 0x60, 0x74, 0x71, 0x32,
-	0xde, 0x02, 0xbc, 0x14, 0x20, 0x70, 0x44, 0x83, 0x5e, 0x81, 0x89, 0x96, 0xd3, 0xef, 0x5b, 0x7e,
-	0x90, 0xca, 0x6b, 0xd9, 0x02, 0xe8, 0x82, 0xe5, 0xaf, 0x0a, 0xbe, 0x68, 0x1f, 0xe4, 0xdf, 0x0c,
-	0x07, 0x02, 0xd1, 0x7a, 0x98, 0x94, 0x4a, 0x42, 0xf4, 0xc3, 0xd9, 0x44, 0x8b, 0x5c, 0x31, 0x2a,
-	0xff, 0x70, 0xa1, 0xe2, 0xb4, 0xb2, 0xc5, 0x83, 0x79, 0x84, 0x8a, 0x80, 0x8a, 0x84, 0x8a, 0x3f,
-	0x19, 0x56, 0xa2, 0xd0, 0xab, 0x61, 0xa1, 0x2f, 0x8b, 0xbd, 0x3b, 0x9d, 0x4d, 0xa8, 0xda, 0x7c,
-	0xd5, 0x65, 0xcc, 0xc4, 0xbb, 0x83, 0xa0, 0x0f, 0x30, 0x7f, 0x6b, 0xc0, 0x94, 0xa2, 0xbc, 0x64,
-	0x31, 0x1f, 0xbd, 0x36, 0x14, 0x2a, 0xd5, 0x6c, 0xa1, 0xc2, 0xb9, 0x45, 0xa0, 0x84, 0x7d, 0x44,
-	0x00, 0xd1, 0xc2, 0x04, 0xc3, 0x41, 0xcb, 0xa7, 0xfd, 0xe0, 0xda, 0xf1, 0x68, 0xae, 0x95, 0x68,
-	0x09, 0x9b, 0xcb, 0xc0, 0x52, 0x94, 0xf9, 0xd7, 0x22, 0xcc, 0x29, 0x8a, 0x1c, 0x9d, 0x73, 0x3c,
-	0x18, 0xcb, 0xf9, 0x82, 0xb1, 0x70, 0xe7, 0x82, 0xb1, 0x78, 0x27, 0x82, 0xb1, 0x74, 0xfb, 0x82,
-	0xf1, 0x4b, 0x30, 0xb7, 0x4d, 0x3d, 0x6b, 0xd3, 0x6a, 0x89, 0x2b, 0xd8, 0x9a, 0xbd, 0xe9, 0xa8,
-	0xe4, 0xfe, 0x78, 0x36, 0xf1, 0xd7, 0x13, 0xdc, 0x8d, 0x05, 0x9e, 0xd0, 0x92, 0x50, 0x3c, 0xa4,
-	0xc5, 0xfc, 0x67, 0x11, 0xa6, 0x63, 0x31, 0x8d, 0x6e, 0x00, 0x48, 0x2a, 0xda, 0x5e, 0xb3, 0x55,
-	0x6f, 0xb1, 0x3a, 0xc6, 0xe1, 0x50, 0x36, 0x71, 0x29, 0xf2, 0x0a, 0x1b, 0xe6, 0xba, 0x08, 0x81,
-	0x35, 0x55, 0xe8, 0x2d, 0x98, 0x22, 0xea, 0xd6, 0x75, 0xde, 0xf1, 0x54, 0x38, 0x9c, 0x1b, 0x47,
-	0x73, 0x3d, 0x12, 0x93, 0xbc, 0x3d, 0x47, 0x18, 0xac, 0x6b, 0x5b, 0xf2, 0x60, 0x36, 0x61, 0x6f,
-	0xca, 0x0d, 0x78, 0x4d, 0xbf, 0x01, 0x67, 0x4e, 0x19, 0x81, 0x5c, 0x71, 0x95, 0xd4, 0xaf, 0xdd,
-	0x0c, 0xe6, 0x92, 0x96, 0xde, 0x36, 0xa5, 0xb1, 0xfb, 0xab, 0x7e, 0x57, 0xff, 0x55, 0x01, 0x2a,
-	0xe1, 0xe1, 0xc9, 0x53, 0x62, 0x97, 0xa0, 0x60, 0xb5, 0x55, 0x81, 0x05, 0x45, 0x55, 0x58, 0x3b,
-	0x87, 0x0b, 0x56, 0x1b, 0x3d, 0x00, 0xe5, 0x0d, 0x8f, 0xd8, 0xad, 0xae, 0x2a, 0xa9, 0x61, 0x9c,
-	0x37, 0x04, 0x14, 0x2b, 0x2c, 0x6f, 0x91, 0x7d, 0xd2, 0x11, 0x6d, 0x91, 0xd6, 0x22, 0x5f, 0x25,
-	0x1d, 0xcc, 0xe1, 0xe8, 0x02, 0xcc, 0xcb, 0x3b, 0xe1, 0x6a, 0x97, 0xb6, 0xb6, 0xa4, 0x89, 0xe2,
-	0x1c, 0x54, 0x1a, 0xf7, 0x2a, 0xe2, 0xf9, 0x8b, 0x49, 0x02, 0x3c, 0xcc, 0xa3, 0xdf, 0xaa, 0xcb,
-	0x7b, 0xdf, 0xaa, 0xb9, 0xe9, 0x64, 0xe0, 0x77, 0x1d, 0x4f, 0x15, 0xd9, 0xd0, 0xf4, 0xba, 0x80,
-	0x62, 0x85, 0x35, 0x0f, 0xc3, 0xfc, 0x05, 0xcb, 0xbf, 0x38, 0xd8, 0x68, 0x0e, 0x7a, 0x3d, 0x4c,
-	0xdf, 0x1c, 0xf0, 0x2e, 0xf5, 0xe7, 0x07, 0x61, 0xfa, 0x82, 0xe5, 0x0b, 0x5f, 0xe5, 0x6e, 0x50,
-	0xd7, 0xe1, 0x88, 0x65, 0x33, 0xda, 0x1a, 0x78, 0x74, 0x7d, 0xcb, 0x72, 0xaf, 0x5e, 0x5a, 0x17,
-	0x91, 0xb2, 0xa3, 0xfa, 0xe3, 0x63, 0x8a, 0xf1, 0xc8, 0x5a, 0x1a, 0x11, 0x4e, 0xe7, 0x45, 0xa7,
-	0x00, 0x3c, 0x4a, 0xda, 0x0d, 0x7d, 0x37, 0xc2, 0x83, 0x87, 0x43, 0x0c, 0xd6, 0xa8, 0xd0, 0x0a,
-	0x4c, 0xdd, 0xf0, 0x2c, 0x9f, 0x2a, 0x26, 0xb9, 0x3b, 0xe1, 0x91, 0x79, 0x29, 0x42, 0x61, 0x9d,
-	0x0e, 0x6d, 0xc3, 0x94, 0x1b, 0xf9, 0x42, 0xe5, 0xab, 0x8c, 0x99, 0x42, 0x73, 0x62, 0xd3, 0x73,
-	0xfa, 0x0e, 0xcf, 0x47, 0x97, 0x69, 0xab, 0x4b, 0x6c, 0x8b, 0xf5, 0x1b, 0xb3, 0x5c, 0xaf, 0x46,
-	0x82, 0x75, 0x45, 0xa8, 0x03, 0x65, 0x8f, 0xda, 0x6d, 0xea, 0xa9, 0xca, 0x9d, 0x51, 0xe5, 0x0b,
-	0x1c, 0x84, 0x05, 0x63, 0x8a, 0x4a, 0xe0, 0x5b, 0x2e, 0xb1, 0x58, 0x89, 0x47, 0xb6, 0xde, 0xca,
-	0x4f, 0x08, 0x5d, 0xf5, 0x8c, 0xba, 0x02, 0xb6, 0x14, 0x4d, 0xa3, 0xdb, 0xfa, 0x57, 0x54, 0x5b,
-	0x3f, 0x29, 0x54, 0x3d, 0x9d, 0x4d, 0x15, 0x6f, 0xe3, 0x53, 0xb4, 0x24, 0x5b, 0xfc, 0x3f, 0x15,
-	0x61, 0xf6, 0x82, 0x35, 0x76, 0x7f, 0xed, 0xc3, 0x3d, 0xb2, 0xaa, 0xae, 0xd3, 0x1e, 0x6d, 0x71,
-	0xee, 0x75, 0xdf, 0x23, 0x3e, 0xed, 0x04, 0xf7, 0xdd, 0xb3, 0x8a, 0xf5, 0x9e, 0xd5, 0x74, 0xb2,
-	0x5b, 0xa3, 0x51, 0x78, 0x94, 0xe8, 0xcc, 0x69, 0x25, 0xad, 0xb7, 0x2f, 0xe5, 0xed, 0xed, 0x79,
-	0xef, 0x42, 0x7a, 0x3d, 0xe7, 0xc6, 0x55, 0xd2, 0x61, 0x2a, 0xeb, 0x84, 0xbd, 0x4b, 0x3d, 0x40,
-	0xe0, 0x88, 0x06, 0x55, 0x01, 0xac, 0x8e, 0xed, 0x78, 0x54, 0x70, 0x94, 0xc5, 0x00, 0x67, 0x86,
-	0x9f, 0xb3, 0xb5, 0x10, 0x8a, 0x35, 0x8a, 0xd1, 0x07, 0x7e, 0x62, 0xfc, 0x03, 0x6f, 0xfe, 0xc1,
-	0x80, 0xb2, 0xcc, 0x89, 0x68, 0x25, 0x31, 0xbb, 0x3a, 0x36, 0x34, 0xbb, 0x9a, 0x4a, 0x1b, 0x41,
-	0x9a, 0x50, 0xb6, 0x18, 0x1b, 0x50, 0xd9, 0x81, 0x55, 0xe4, 0x51, 0x58, 0x13, 0x10, 0xac, 0x30,
-	0xc8, 0x02, 0x20, 0xc1, 0xf0, 0x29, 0x68, 0xa7, 0x56, 0xf2, 0x4e, 0xe7, 0x12, 0x93, 0xb9, 0x10,
-	0xc1, 0xb0, 0x26, 0xdc, 0xfc, 0xb1, 0x01, 0xf7, 0xf2, 0xc0, 0x15, 0x2d, 0xd2, 0x39, 0xea, 0xf2,
-	0xb3, 0x68, 0xb7, 0x76, 0x54, 0x7e, 0x15, 0xf9, 0xcd, 0x75, 0x98, 0xe5, 0x3b, 0x9e, 0x2a, 0x93,
-	0x7a, 0x7e, 0x0b, 0x30, 0x58, 0xa3, 0xca, 0x70, 0x39, 0xac, 0x41, 0x45, 0x74, 0x62, 0x4d, 0xe2,
-	0x07, 0xb1, 0x16, 0x6e, 0xfd, 0x6a, 0x80, 0xc0, 0x11, 0x8d, 0xf9, 0x47, 0x03, 0x66, 0xc7, 0x1a,
-	0x12, 0x3d, 0x03, 0x33, 0xa2, 0x16, 0xb3, 0xf3, 0x56, 0x8f, 0x0a, 0x75, 0xd2, 0xaa, 0xa3, 0x8a,
-	0x7a, 0xe6, 0x7a, 0x0c, 0x8b, 0x13, 0xd4, 0xc1, 0x90, 0xa9, 0xb8, 0xdf, 0x90, 0xa9, 0x34, 0xc6,
-	0x90, 0xe9, 0x63, 0x03, 0x8e, 0xa6, 0xa7, 0x13, 0xf4, 0x7a, 0x62, 0xd8, 0xb4, 0x92, 0x3d, 0x39,
-	0x65, 0x98, 0x30, 0xf1, 0x94, 0xae, 0x9a, 0x6a, 0xd9, 0xf5, 0x3d, 0x9b, 0x5d, 0x7c, 0x6a, 0x98,
-	0x8c, 0x6a, 0xb4, 0xcd, 0x5f, 0x18, 0x20, 0xf7, 0x23, 0x4f, 0xf2, 0x3b, 0x05, 0xd0, 0x51, 0x45,
-	0x1e, 0x5f, 0x52, 0xfb, 0x15, 0xc6, 0xdc, 0x85, 0x10, 0x83, 0x35, 0xaa, 0xa0, 0xd3, 0x29, 0x8e,
-	0xe8, 0x74, 0x1e, 0x80, 0x72, 0x5b, 0x0e, 0xc3, 0x4a, 0xf1, 0xcc, 0xa6, 0x26, 0x61, 0x0a, 0x6b,
-	0xbe, 0x57, 0x82, 0x79, 0x61, 0xef, 0xb8, 0x89, 0x7b, 0x1c, 0xdb, 0x5d, 0x38, 0x2a, 0xf6, 0x65,
-	0x38, 0xd7, 0xcb, 0xe5, 0x9c, 0x51, 0xfc, 0x47, 0xd7, 0x52, 0xa9, 0x6e, 0x8d, 0xc4, 0xe0, 0x11,
-	0x72, 0xff, 0x53, 0x12, 0xf8, 0x23, 0x30, 0xe9, 0xf6, 0x88, 0xbf, 0xe9, 0x78, 0x7d, 0xd5, 0x2d,
-	0x86, 0xd7, 0xf2, 0xa6, 0x82, 0xe3, 0x90, 0x62, 0x74, 0xba, 0x9f, 0xfc, 0x14, 0xe9, 0xde, 0x86,
-	0xa3, 0x5a, 0x23, 0x73, 0xe7, 0xe7, 0xb0, 0xdf, 0x32, 0xe0, 0xd8, 0x9e, 0x9d, 0x13, 0x6a, 0x27,
-	0x52, 0xc3, 0xd3, 0xb9, 0xdb, 0xb1, 0x2c, 0x33, 0xe8, 0xf7, 0x0c, 0x58, 0x18, 0x7f, 0xfc, 0x7c,
-	0x02, 0x4a, 0x6e, 0x94, 0x6b, 0xc3, 0x0a, 0x20, 0x32, 0xac, 0xc0, 0xc4, 0x1d, 0x53, 0xcc, 0xe0,
-	0x98, 0xb7, 0x0d, 0xb8, 0x6f, 0x8f, 0x36, 0x0f, 0x6d, 0x24, 0xdc, 0x72, 0x36, 0x67, 0xe7, 0x98,
-	0xc5, 0x29, 0x3f, 0x2c, 0xc0, 0x44, 0xd3, 0x73, 0xde, 0xa0, 0xad, 0xbb, 0x31, 0x8d, 0x7c, 0x11,
-	0x4a, 0xcc, 0xa5, 0x2d, 0x75, 0x0f, 0x3d, 0x99, 0xb1, 0xd1, 0x97, 0xe6, 0xad, 0xbb, 0xb4, 0x25,
-	0x7b, 0x52, 0xfe, 0x0b, 0x0b, 0x41, 0xda, 0x08, 0xae, 0x98, 0xe7, 0x6a, 0x1b, 0x88, 0xdc, 0x7f,
-	0x04, 0xa7, 0x28, 0x3f, 0xb3, 0x23, 0x38, 0x65, 0xdf, 0x88, 0x11, 0xdc, 0x77, 0xa2, 0x15, 0x70,
-	0xa7, 0xa1, 0xaf, 0xc2, 0xbc, 0x1b, 0xc4, 0x59, 0xd3, 0xe9, 0x59, 0x2d, 0x2b, 0x6f, 0x39, 0x6e,
-	0xc6, 0xd8, 0x77, 0xa2, 0x4b, 0x75, 0x33, 0x29, 0x17, 0x0f, 0xab, 0x32, 0x1d, 0x98, 0x8e, 0xb9,
-	0x1e, 0x9d, 0x0e, 0x3e, 0xc5, 0xc7, 0xdb, 0x4d, 0xf9, 0x29, 0xfe, 0xd6, 0xcd, 0xe3, 0x87, 0x14,
-	0xb9, 0xfe, 0x69, 0x3e, 0xcf, 0x07, 0xef, 0x1f, 0x15, 0xa0, 0x12, 0x5a, 0x76, 0x17, 0x02, 0xfc,
-	0x73, 0xb1, 0x00, 0x3f, 0x9d, 0xd3, 0xa7, 0xa9, 0x21, 0xfe, 0x7a, 0x22, 0xc4, 0xf3, 0x6e, 0xd4,
-	0x3e, 0x41, 0xfe, 0x03, 0x43, 0xec, 0x89, 0xa4, 0x5d, 0xb3, 0x37, 0x9d, 0x0c, 0x23, 0x5a, 0x02,
-	0x13, 0x9b, 0x72, 0x5a, 0xa6, 0x16, 0xfa, 0x78, 0xae, 0x11, 0x5b, 0x38, 0x0d, 0x8e, 0x36, 0x2e,
-	0xc0, 0x04, 0x72, 0xcd, 0xdf, 0xe9, 0x66, 0xdd, 0x85, 0xd3, 0x77, 0x35, 0x7e, 0xfa, 0x6a, 0x39,
-	0x9d, 0x3c, 0xe2, 0xfc, 0x7d, 0xbb, 0x00, 0x87, 0x87, 0x13, 0x3b, 0x43, 0x0c, 0x66, 0x3a, 0xfa,
-	0xcc, 0x27, 0x38, 0x84, 0xa7, 0x33, 0x4f, 0xae, 0x23, 0xde, 0xa8, 0xef, 0x8f, 0x81, 0x19, 0x4e,
-	0xa8, 0x40, 0x6f, 0xc1, 0x1c, 0x89, 0x7f, 0xfd, 0x0f, 0x56, 0x9b, 0xf7, 0x1a, 0xa6, 0x14, 0x87,
-	0x8d, 0x55, 0x02, 0xc1, 0xf0, 0x90, 0x22, 0xf3, 0x5d, 0x03, 0x66, 0x13, 0xb9, 0x83, 0xd7, 0x5d,
-	0xe6, 0xa7, 0xd4, 0x5d, 0x35, 0x70, 0x14, 0x38, 0xd4, 0x84, 0x05, 0x32, 0xf0, 0x9d, 0x90, 0xf7,
-	0x39, 0x9b, 0x6c, 0xf4, 0x68, 0x5b, 0x75, 0x1e, 0xe1, 0xe7, 0xd5, 0x7a, 0x0a, 0x0d, 0x4e, 0xe5,
-	0x34, 0xbf, 0xa0, 0x45, 0x96, 0xc8, 0x8a, 0x99, 0xec, 0x78, 0x28, 0x1e, 0xf3, 0x95, 0x3d, 0x62,
-	0xf7, 0x27, 0x05, 0x6d, 0xad, 0x2a, 0xd1, 0xad, 0xc4, 0x13, 0xdd, 0xf1, 0x64, 0xa2, 0x9b, 0x89,
-	0x9c, 0x33, 0x5e, 0xaa, 0x43, 0x6f, 0x6a, 0xe7, 0xa3, 0x98, 0x67, 0xe4, 0x9e, 0x30, 0xb5, 0x1a,
-	0xbc, 0x20, 0x93, 0x73, 0xef, 0xf0, 0xd0, 0x04, 0xe0, 0xe8, 0xd0, 0x2c, 0x3d, 0x05, 0xd3, 0x31,
-	0xe2, 0x5c, 0x2f, 0xbe, 0xbe, 0x02, 0xc7, 0xf6, 0x1c, 0xe1, 0xf1, 0xda, 0x2e, 0xed, 0x57, 0xc7,
-	0xfd, 0x89, 0xcc, 0x87, 0x23, 0x3e, 0x62, 0x95, 0xd3, 0x08, 0x09, 0xc6, 0x4a, 0xa4, 0xf9, 0x7e,
-	0x01, 0xe6, 0xf8, 0xe1, 0x88, 0x5d, 0x8a, 0x9a, 0x50, 0xec, 0x58, 0xbe, 0x52, 0xb7, 0x92, 0x59,
-	0x9d, 0x2e, 0xa3, 0x31, 0xc1, 0x2f, 0x69, 0xfc, 0x24, 0x72, 0x51, 0xe8, 0xe5, 0xa0, 0xb5, 0x2c,
-	0xe4, 0x59, 0xc2, 0xd0, 0x75, 0xad, 0x51, 0x19, 0xea, 0x47, 0x5f, 0x0e, 0xde, 0x26, 0x14, 0xf3,
-	0x48, 0x1e, 0xfa, 0x42, 0x2e, 0x25, 0xeb, 0x0f, 0x1a, 0xcc, 0xef, 0x17, 0x40, 0x86, 0xfe, 0x5d,
-	0xa8, 0x97, 0x97, 0x63, 0xf5, 0x32, 0x63, 0xd6, 0x15, 0xc6, 0xa5, 0xd6, 0xca, 0xcf, 0x27, 0x6a,
-	0xe5, 0xc9, 0x3c, 0x02, 0xf7, 0xae, 0x93, 0xbf, 0x31, 0xa0, 0x22, 0xe8, 0xee, 0x42, 0x31, 0x6a,
-	0xc6, 0x8b, 0xd1, 0xc3, 0x39, 0x56, 0x31, 0xa2, 0x10, 0x7d, 0xb7, 0xa8, 0xac, 0x0f, 0x13, 0x5e,
-	0x97, 0x78, 0x6d, 0x75, 0x41, 0x8e, 0x12, 0x1e, 0x07, 0x62, 0x89, 0x43, 0x3d, 0x98, 0x66, 0x5a,
-	0xa0, 0x30, 0xb5, 0xce, 0x8c, 0x25, 0x4a, 0x8f, 0x31, 0xd6, 0x98, 0x17, 0x6f, 0xb5, 0x74, 0x10,
-	0x8e, 0x0b, 0x47, 0xef, 0x18, 0x70, 0xd8, 0x1d, 0xae, 0x94, 0x2a, 0x30, 0x9e, 0xcc, 0x99, 0xc9,
-	0x22, 0x01, 0x8d, 0x7b, 0x76, 0x6f, 0x1e, 0x4f, 0xab, 0xc1, 0x38, 0x4d, 0x1d, 0xea, 0xc2, 0x21,
-	0xfd, 0xfb, 0xa6, 0x0a, 0xa3, 0x53, 0xf9, 0xbf, 0xa0, 0x36, 0xe6, 0x76, 0x6f, 0x1e, 0x3f, 0xa4,
-	0x43, 0x70, 0x4c, 0xb2, 0xf9, 0xe7, 0x12, 0x4c, 0x69, 0x71, 0x87, 0x4e, 0xc6, 0x0b, 0xc4, 0x7d,
-	0xc9, 0x02, 0x01, 0x82, 0x38, 0x56, 0x1c, 0x3c, 0x98, 0x69, 0x0d, 0x3c, 0x8f, 0xda, 0xfe, 0xf9,
-	0xdb, 0xd2, 0x8d, 0x21, 0xde, 0x44, 0xac, 0xc6, 0x24, 0xe2, 0x84, 0x06, 0xde, 0xfa, 0x75, 0x2d,
-	0x26, 0x26, 0xa7, 0xb2, 0xc8, 0x7c, 0xea, 0xd6, 0xef, 0xa2, 0x14, 0x87, 0x03, 0xb9, 0xa8, 0x09,
-	0x65, 0xf9, 0x39, 0x4e, 0x7d, 0xc5, 0x78, 0x24, 0xeb, 0x24, 0x8f, 0xf3, 0xc8, 0x64, 0x2f, 0x7f,
+	0x2b, 0x2e, 0xf4, 0x10, 0x4c, 0xf4, 0x29, 0x63, 0xa4, 0x13, 0x7c, 0xf3, 0xac, 0x12, 0x30, 0x71,
+	0x59, 0x82, 0x71, 0x80, 0x37, 0xff, 0x50, 0x80, 0xd9, 0x50, 0x96, 0x52, 0x7f, 0x07, 0x1c, 0x3c,
+	0x80, 0x43, 0x5d, 0xed, 0x0b, 0x85, 0x9f, 0xa7, 0x4e, 0x3d, 0x95, 0x31, 0x96, 0xd3, 0x9c, 0xd4,
+	0x58, 0x50, 0x6a, 0x0e, 0xe9, 0x50, 0x1c, 0x53, 0x83, 0xfa, 0x00, 0x6c, 0xc7, 0x6e, 0x29, 0xa5,
+	0x25, 0xa1, 0xf4, 0xc9, 0x9c, 0x4a, 0xd7, 0x43, 0x01, 0x0d, 0xa4, 0x54, 0x42, 0x04, 0xc3, 0x9a,
+	0x02, 0xf3, 0x57, 0x06, 0x1c, 0x4e, 0xe1, 0x43, 0x4f, 0x27, 0xd6, 0xf3, 0xfe, 0xa1, 0xf5, 0x44,
+	0x43, 0x6c, 0xd1, 0x6a, 0x3e, 0x02, 0x93, 0x1e, 0xdd, 0xb6, 0x98, 0xe5, 0xd8, 0xca, 0xc3, 0x73,
+	0x8a, 0x7f, 0x12, 0x2b, 0x38, 0x0e, 0x29, 0xd0, 0xc3, 0x50, 0x09, 0x7e, 0x73, 0x37, 0x17, 0x79,
+	0x38, 0xf3, 0x85, 0x0b, 0x48, 0x19, 0x8e, 0xf0, 0xe6, 0x3f, 0x0c, 0x6d, 0xf5, 0xaf, 0xb9, 0x6d,
+	0xe2, 0x53, 0x1e, 0x3c, 0xc4, 0x75, 0xaf, 0x44, 0xc1, 0x1c, 0x06, 0x4f, 0x5d, 0x82, 0x71, 0x80,
+	0x47, 0x67, 0xe0, 0x90, 0xfa, 0x29, 0x63, 0x45, 0x5a, 0x17, 0x2e, 0x4c, 0x5d, 0xc3, 0xe1, 0x18,
+	0x25, 0x1a, 0xc0, 0x34, 0x73, 0x06, 0x5e, 0x8b, 0x4a, 0xa5, 0xd2, 0xd2, 0xa9, 0x53, 0x67, 0xf2,
+	0xac, 0xcd, 0xba, 0x26, 0xa0, 0x71, 0x44, 0x29, 0x9d, 0xd6, 0xa1, 0x0c, 0xc7, 0xb5, 0x98, 0x6f,
+	0x02, 0x48, 0xde, 0x8b, 0xb4, 0xd7, 0x47, 0x2d, 0x28, 0x5b, 0x7d, 0xd2, 0xa1, 0x41, 0x3e, 0xcf,
+	0x15, 0x8e, 0x5c, 0xc2, 0x1a, 0xe7, 0x56, 0x06, 0x84, 0x59, 0x5c, 0x00, 0x19, 0x56, 0xa2, 0xcd,
+	0x0f, 0xc2, 0x5d, 0x9e, 0xe0, 0xe0, 0x49, 0x47, 0xd0, 0x28, 0x37, 0x87, 0x49, 0x47, 0xd0, 0x60,
+	0x89, 0x43, 0xc7, 0x64, 0xc6, 0x94, 0x9e, 0x9d, 0x52, 0x24, 0xc5, 0x17, 0xe8, 0x8e, 0x4c, 0x9f,
+	0x4f, 0x05, 0xe9, 0x53, 0x26, 0xae, 0xff, 0x89, 0xd5, 0x33, 0x9e, 0x27, 0x34, 0x85, 0x02, 0x76,
+	0x75, 0xc7, 0x0d, 0xeb, 0xdc, 0x5b, 0xc1, 0xe2, 0xbf, 0x30, 0x60, 0xbe, 0xd3, 0xb7, 0xbe, 0x4a,
+	0x51, 0x37, 0xe1, 0x92, 0xff, 0xcf, 0xe3, 0x92, 0x50, 0x4c, 0x16, 0xbf, 0x78, 0xb0, 0x34, 0x9a,
+	0x2b, 0x9b, 0x6f, 0x6a, 0x50, 0x19, 0x30, 0x7a, 0xce, 0xea, 0x50, 0xe6, 0x0b, 0x0f, 0x4d, 0x46,
+	0x79, 0xea, 0x5a, 0x80, 0xc0, 0x11, 0x8d, 0xf9, 0xf7, 0x02, 0xa0, 0xe1, 0xd8, 0xe1, 0x11, 0xef,
+	0x51, 0xd7, 0xb9, 0x86, 0x2f, 0x25, 0x23, 0x1e, 0x4b, 0x30, 0x0e, 0xf0, 0xdc, 0xae, 0x56, 0x97,
+	0x78, 0x7e, 0xb2, 0x7f, 0x58, 0xe5, 0x40, 0x2c, 0x71, 0xa8, 0x09, 0x0b, 0x03, 0x21, 0xf9, 0x2a,
+	0xf1, 0x3a, 0xd4, 0x0f, 0x76, 0x9e, 0x58, 0xa3, 0xc9, 0xc6, 0x7f, 0x29, 0x9e, 0x85, 0x6b, 0x29,
+	0x34, 0x38, 0x95, 0x13, 0x6d, 0x40, 0x65, 0x2b, 0x70, 0x93, 0x4a, 0x63, 0x2b, 0x63, 0xad, 0x8c,
+	0xcc, 0x05, 0xe1, 0x9f, 0x38, 0x12, 0x8b, 0xae, 0x40, 0xa9, 0x4b, 0x7b, 0xfd, 0xc5, 0x83, 0x42,
+	0xfc, 0xff, 0xe6, 0xdd, 0x0b, 0x8d, 0x49, 0x9e, 0xf2, 0xf9, 0x2f, 0x2c, 0xe4, 0x98, 0xdf, 0x00,
+	0xe9, 0x95, 0x3c, 0xee, 0xdd, 0xbf, 0x90, 0x3c, 0x04, 0x13, 0xdb, 0xd4, 0x0b, 0xdd, 0xa9, 0x09,
+	0xbb, 0x2e, 0xc1, 0x38, 0xc0, 0x9b, 0x3f, 0x37, 0x60, 0x5e, 0x58, 0xb0, 0x3e, 0xd8, 0x60, 0x2d,
+	0xcf, 0x72, 0x79, 0x23, 0x72, 0x7b, 0xad, 0x39, 0x07, 0x73, 0x8c, 0xf6, 0xb7, 0xa9, 0xb7, 0xea,
+	0xd8, 0xcc, 0xf7, 0x88, 0x65, 0xfb, 0xca, 0xac, 0x45, 0x45, 0x3d, 0xb7, 0x9e, 0xc0, 0xe3, 0x21,
+	0x0e, 0xf3, 0x67, 0x25, 0x98, 0x38, 0xef, 0x51, 0xab, 0xd3, 0xf5, 0xd1, 0x97, 0x61, 0xb2, 0xaf,
+	0xfa, 0x35, 0x61, 0x1f, 0x5f, 0x09, 0xd9, 0x24, 0x57, 0xf5, 0x26, 0xb9, 0xea, 0x6e, 0x75, 0x38,
+	0x80, 0x55, 0x39, 0x75, 0x75, 0xfb, 0x64, 0xf5, 0xc5, 0x8d, 0x37, 0x68, 0xcb, 0xe7, 0xbd, 0x5e,
+	0x54, 0xa6, 0x22, 0x18, 0x0e, 0xa5, 0xf2, 0x10, 0x26, 0x3d, 0x8b, 0xb0, 0xc5, 0x89, 0x78, 0x08,
+	0xd7, 0x39, 0x10, 0x4b, 0x1c, 0xdf, 0x5a, 0x37, 0x88, 0x47, 0xbb, 0xce, 0x80, 0xd1, 0xc5, 0xc9,
+	0x78, 0x0b, 0xf0, 0x52, 0x80, 0xc0, 0x11, 0x0d, 0x7a, 0x05, 0x26, 0x5a, 0x4e, 0xbf, 0x6f, 0xf9,
+	0x41, 0x2a, 0xaf, 0x65, 0x0b, 0xa0, 0x0b, 0x96, 0xbf, 0x2a, 0xf8, 0xa2, 0x75, 0x90, 0x7f, 0x33,
+	0x1c, 0x08, 0x44, 0xeb, 0x61, 0x52, 0x2a, 0x09, 0xd1, 0x0f, 0x67, 0x13, 0x2d, 0x72, 0xc5, 0xa8,
+	0xfc, 0xc3, 0x85, 0x8a, 0xdd, 0xca, 0x16, 0x0f, 0xe6, 0x11, 0x2a, 0x02, 0x2a, 0x12, 0x2a, 0xfe,
+	0x64, 0x58, 0x89, 0x42, 0xaf, 0x86, 0x85, 0xbe, 0x2c, 0xd6, 0xee, 0x74, 0x36, 0xa1, 0x6a, 0xf1,
+	0x55, 0x97, 0x31, 0x13, 0xef, 0x0e, 0x82, 0x3e, 0xc0, 0xfc, 0x9d, 0x01, 0x53, 0x8a, 0xf2, 0x92,
+	0xc5, 0x7c, 0xf4, 0xda, 0x50, 0xa8, 0x54, 0xb3, 0x85, 0x0a, 0xe7, 0x16, 0x81, 0x12, 0xf6, 0x11,
+	0x01, 0x44, 0x0b, 0x13, 0x0c, 0x07, 0x2d, 0x9f, 0xf6, 0x83, 0x63, 0xc7, 0xa3, 0xb9, 0xbe, 0x44,
+	0x4b, 0xd8, 0x5c, 0x06, 0x96, 0xa2, 0xcc, 0xbf, 0x15, 0x61, 0x4e, 0x51, 0xe4, 0xe8, 0x9c, 0xe3,
+	0xc1, 0x58, 0xce, 0x17, 0x8c, 0x85, 0x3b, 0x17, 0x8c, 0xc5, 0x3b, 0x11, 0x8c, 0xa5, 0xdb, 0x17,
+	0x8c, 0x5f, 0x81, 0xb9, 0x6d, 0xea, 0x59, 0x9b, 0x56, 0x4b, 0x1c, 0xc1, 0xd6, 0xec, 0x4d, 0x47,
+	0x25, 0xf7, 0xc7, 0xb3, 0x89, 0xbf, 0x9e, 0xe0, 0x6e, 0x2c, 0xf0, 0x84, 0x96, 0x84, 0xe2, 0x21,
+	0x2d, 0xe6, 0x3f, 0x8b, 0x30, 0x1d, 0x8b, 0x69, 0x74, 0x03, 0x40, 0x52, 0xd1, 0xf6, 0x9a, 0xad,
+	0x7a, 0x8b, 0xd5, 0x31, 0x36, 0x87, 0xb2, 0x89, 0x4b, 0x91, 0x47, 0xd8, 0x30, 0xd7, 0x45, 0x08,
+	0xac, 0xa9, 0x42, 0x6f, 0xc1, 0x14, 0x51, 0xa7, 0xae, 0xf3, 0x8e, 0xa7, 0xc2, 0xe1, 0xdc, 0x38,
+	0x9a, 0xeb, 0x91, 0x98, 0xe4, 0xe9, 0x39, 0xc2, 0x60, 0x5d, 0xdb, 0x92, 0x07, 0xb3, 0x09, 0x7b,
+	0x53, 0x4e, 0xc0, 0x6b, 0xfa, 0x09, 0x38, 0x73, 0xca, 0x08, 0xe4, 0x8a, 0xa3, 0xa4, 0x7e, 0xec,
+	0x66, 0x30, 0x97, 0xb4, 0xf4, 0xb6, 0x29, 0x8d, 0x9d, 0x5f, 0xf5, 0xb3, 0xfa, 0xaf, 0x0b, 0x50,
+	0x09, 0x37, 0x4f, 0x9e, 0x12, 0xbb, 0x04, 0x05, 0xab, 0xad, 0x0a, 0x2c, 0x28, 0xaa, 0xc2, 0xda,
+	0x39, 0x5c, 0xb0, 0xda, 0xe8, 0x01, 0x28, 0x6f, 0x78, 0xc4, 0x6e, 0x75, 0x55, 0x49, 0x0d, 0xe3,
+	0xbc, 0x21, 0xa0, 0x58, 0x61, 0x79, 0x8b, 0xec, 0x93, 0x8e, 0x68, 0x8b, 0xb4, 0x16, 0xf9, 0x2a,
+	0xe9, 0x60, 0x0e, 0x47, 0x17, 0x60, 0x5e, 0x9e, 0x09, 0x57, 0xbb, 0xb4, 0xb5, 0x25, 0x4d, 0x14,
+	0xfb, 0xa0, 0xd2, 0xb8, 0x57, 0x11, 0xcf, 0x5f, 0x4c, 0x12, 0xe0, 0x61, 0x1e, 0xfd, 0x54, 0x5d,
+	0xde, 0xfb, 0x54, 0xcd, 0x4d, 0x27, 0x03, 0xbf, 0xeb, 0x78, 0xaa, 0xc8, 0x86, 0xa6, 0xd7, 0x05,
+	0x14, 0x2b, 0xac, 0x79, 0x18, 0xe6, 0x2f, 0x58, 0xfe, 0xc5, 0xc1, 0x46, 0x73, 0xd0, 0xeb, 0x61,
+	0xfa, 0xe6, 0x80, 0x77, 0xa9, 0xbf, 0x38, 0x08, 0xd3, 0x17, 0x2c, 0x5f, 0xf8, 0x2a, 0x77, 0x83,
+	0xba, 0x0e, 0x47, 0x2c, 0x9b, 0xd1, 0xd6, 0xc0, 0xa3, 0xeb, 0x5b, 0x96, 0x7b, 0xf5, 0xd2, 0xba,
+	0x88, 0x94, 0x1d, 0xd5, 0x1f, 0x1f, 0x53, 0x8c, 0x47, 0xd6, 0xd2, 0x88, 0x70, 0x3a, 0x2f, 0x3a,
+	0x05, 0xe0, 0x51, 0xd2, 0x6e, 0xe8, 0xab, 0x11, 0x6e, 0x3c, 0x1c, 0x62, 0xb0, 0x46, 0x85, 0x56,
+	0x60, 0xea, 0x86, 0x67, 0xf9, 0x54, 0x31, 0xc9, 0xd5, 0x09, 0xb7, 0xcc, 0x4b, 0x11, 0x0a, 0xeb,
+	0x74, 0x68, 0x1b, 0xa6, 0xdc, 0xc8, 0x17, 0x2a, 0x5f, 0x65, 0xcc, 0x14, 0x9a, 0x13, 0x9b, 0x9e,
+	0xd3, 0x77, 0x78, 0x3e, 0xba, 0x4c, 0x5b, 0x5d, 0x62, 0x5b, 0xac, 0xdf, 0x98, 0xe5, 0x7a, 0x35,
+	0x12, 0xac, 0x2b, 0x42, 0x1d, 0x28, 0x7b, 0xd4, 0x6e, 0x53, 0x4f, 0x55, 0xee, 0x8c, 0x2a, 0x5f,
+	0xe0, 0x20, 0x2c, 0x18, 0x53, 0x54, 0x02, 0x5f, 0x72, 0x89, 0xc5, 0x4a, 0x3c, 0xb2, 0xf5, 0x56,
+	0x7e, 0x42, 0xe8, 0xaa, 0x67, 0xd4, 0x15, 0xb0, 0xa5, 0x68, 0x1a, 0xdd, 0xd6, 0xbf, 0xa2, 0xda,
+	0xfa, 0x49, 0xa1, 0xea, 0xe9, 0x6c, 0xaa, 0x78, 0x1b, 0x9f, 0xa2, 0x25, 0xd9, 0xe2, 0xff, 0xb9,
+	0x08, 0xb3, 0x17, 0xac, 0xb1, 0xfb, 0x6b, 0x1f, 0xee, 0x91, 0x55, 0x75, 0x9d, 0xf6, 0x68, 0x8b,
+	0x73, 0xaf, 0xfb, 0x1e, 0xf1, 0x69, 0x27, 0x38, 0xef, 0x9e, 0x55, 0xac, 0xf7, 0xac, 0xa6, 0x93,
+	0xdd, 0x1a, 0x8d, 0xc2, 0xa3, 0x44, 0x67, 0x4e, 0x2b, 0x69, 0xbd, 0x7d, 0x29, 0x6f, 0x6f, 0xcf,
+	0x7b, 0x17, 0xd2, 0xeb, 0x39, 0x37, 0xae, 0x92, 0x0e, 0x53, 0x59, 0x27, 0xec, 0x5d, 0xea, 0x01,
+	0x02, 0x47, 0x34, 0xa8, 0x0a, 0x60, 0x75, 0x6c, 0xc7, 0xa3, 0x82, 0xa3, 0x2c, 0x06, 0x38, 0x33,
+	0x7c, 0x9f, 0xad, 0x85, 0x50, 0xac, 0x51, 0x8c, 0xde, 0xf0, 0x13, 0xe3, 0x6f, 0x78, 0xf3, 0x8f,
+	0x06, 0x94, 0x65, 0x4e, 0x44, 0x2b, 0x89, 0xd9, 0xd5, 0xb1, 0xa1, 0xd9, 0xd5, 0x54, 0xda, 0x08,
+	0xd2, 0x84, 0xb2, 0xc5, 0xd8, 0x80, 0xca, 0x0e, 0xac, 0x22, 0xb7, 0xc2, 0x9a, 0x80, 0x60, 0x85,
+	0x41, 0x16, 0x00, 0x09, 0x86, 0x4f, 0x41, 0x3b, 0xb5, 0x92, 0x77, 0x3a, 0x97, 0x98, 0xcc, 0x85,
+	0x08, 0x86, 0x35, 0xe1, 0xe6, 0x4f, 0x0c, 0xb8, 0x97, 0x07, 0xae, 0x68, 0x91, 0xce, 0x51, 0x97,
+	0xef, 0x45, 0xbb, 0xb5, 0xa3, 0xf2, 0xab, 0xc8, 0x6f, 0xae, 0xc3, 0x2c, 0xdf, 0xf1, 0x54, 0x99,
+	0xd4, 0xf3, 0x5b, 0x80, 0xc1, 0x1a, 0x55, 0x86, 0xc3, 0x61, 0x0d, 0x2a, 0xa2, 0x13, 0x6b, 0x12,
+	0x3f, 0x88, 0xb5, 0x70, 0xe9, 0x57, 0x03, 0x04, 0x8e, 0x68, 0xcc, 0x3f, 0x19, 0x30, 0x3b, 0xd6,
+	0x90, 0xe8, 0x19, 0x98, 0x11, 0xb5, 0x98, 0x9d, 0xb7, 0x7a, 0x54, 0xa8, 0x93, 0x56, 0x1d, 0x55,
+	0xd4, 0x33, 0xd7, 0x63, 0x58, 0x9c, 0xa0, 0x0e, 0x86, 0x4c, 0xc5, 0xfd, 0x86, 0x4c, 0xa5, 0x31,
+	0x86, 0x4c, 0x9f, 0x18, 0x70, 0x34, 0x3d, 0x9d, 0xa0, 0xd7, 0x13, 0xc3, 0xa6, 0x95, 0xec, 0xc9,
+	0x29, 0xc3, 0x84, 0x89, 0xa7, 0x74, 0xd5, 0x54, 0xcb, 0xae, 0xef, 0xd9, 0xec, 0xe2, 0x53, 0xc3,
+	0x64, 0x54, 0xa3, 0x6d, 0xfe, 0xd2, 0x00, 0xb9, 0x1e, 0x79, 0x92, 0xdf, 0x29, 0x80, 0x8e, 0x2a,
+	0xf2, 0xf8, 0x92, 0x5a, 0xaf, 0x30, 0xe6, 0x2e, 0x84, 0x18, 0xac, 0x51, 0x05, 0x9d, 0x4e, 0x71,
+	0x44, 0xa7, 0xf3, 0x00, 0x94, 0xdb, 0x72, 0x18, 0x56, 0x8a, 0x67, 0x36, 0x35, 0x09, 0x53, 0x58,
+	0xf3, 0xfd, 0x12, 0xcc, 0x0b, 0x7b, 0xc7, 0x4d, 0xdc, 0xe3, 0xd8, 0xee, 0xc2, 0x51, 0xb1, 0x2e,
+	0xc3, 0xb9, 0x5e, 0x7e, 0xce, 0x19, 0xc5, 0x7f, 0x74, 0x2d, 0x95, 0xea, 0xd6, 0x48, 0x0c, 0x1e,
+	0x21, 0xf7, 0x3f, 0x25, 0x81, 0x3f, 0x02, 0x93, 0x6e, 0x8f, 0xf8, 0x9b, 0x8e, 0xd7, 0x57, 0xdd,
+	0x62, 0x78, 0x2c, 0x6f, 0x2a, 0x38, 0x0e, 0x29, 0x46, 0xa7, 0xfb, 0xc9, 0xcf, 0x90, 0xee, 0x6d,
+	0x38, 0xaa, 0x35, 0x32, 0x77, 0x7e, 0x0e, 0xfb, 0x6d, 0x03, 0x8e, 0xed, 0xd9, 0x39, 0xa1, 0x76,
+	0x22, 0x35, 0x3c, 0x9d, 0xbb, 0x1d, 0xcb, 0x32, 0x83, 0x7e, 0xdf, 0x80, 0x85, 0xf1, 0xc7, 0xcf,
+	0x27, 0xa0, 0xe4, 0x46, 0xb9, 0x36, 0xac, 0x00, 0x22, 0xc3, 0x0a, 0x4c, 0xdc, 0x31, 0xc5, 0x0c,
+	0x8e, 0x79, 0xdb, 0x80, 0xfb, 0xf6, 0x68, 0xf3, 0xd0, 0x46, 0xc2, 0x2d, 0x67, 0x73, 0x76, 0x8e,
+	0x59, 0x9c, 0xf2, 0xa3, 0x02, 0x4c, 0x34, 0x3d, 0xe7, 0x0d, 0xda, 0xba, 0x1b, 0xd3, 0xc8, 0x17,
+	0xa1, 0xc4, 0x5c, 0xda, 0x52, 0xe7, 0xd0, 0x93, 0x19, 0x1b, 0x7d, 0x69, 0xde, 0xba, 0x4b, 0x5b,
+	0xb2, 0x27, 0xe5, 0xbf, 0xb0, 0x10, 0xa4, 0x8d, 0xe0, 0x8a, 0x79, 0x8e, 0xb6, 0x81, 0xc8, 0xfd,
+	0x47, 0x70, 0x8a, 0xf2, 0x73, 0x3b, 0x82, 0x53, 0xf6, 0x8d, 0x18, 0xc1, 0x7d, 0x37, 0xfa, 0x02,
+	0xee, 0x34, 0xf4, 0x75, 0x98, 0x77, 0x83, 0x38, 0x6b, 0x3a, 0x3d, 0xab, 0x65, 0xe5, 0x2d, 0xc7,
+	0xcd, 0x18, 0xfb, 0x4e, 0x74, 0xa8, 0x6e, 0x26, 0xe5, 0xe2, 0x61, 0x55, 0xa6, 0x03, 0xd3, 0x31,
+	0xd7, 0xa3, 0xd3, 0xc1, 0x55, 0x7c, 0xbc, 0xdd, 0x94, 0x57, 0xf1, 0xb7, 0x6e, 0x1e, 0x3f, 0xa4,
+	0xc8, 0xf5, 0xab, 0xf9, 0x3c, 0x17, 0xde, 0x3f, 0x2e, 0x40, 0x25, 0xb4, 0xec, 0x2e, 0x04, 0xf8,
+	0x17, 0x62, 0x01, 0x7e, 0x3a, 0xa7, 0x4f, 0x53, 0x43, 0xfc, 0xf5, 0x44, 0x88, 0xe7, 0x5d, 0xa8,
+	0x7d, 0x82, 0xfc, 0x87, 0x86, 0x58, 0x13, 0x49, 0xbb, 0x66, 0x6f, 0x3a, 0x19, 0x46, 0xb4, 0x04,
+	0x26, 0x36, 0xe5, 0xb4, 0x4c, 0x7d, 0xe8, 0xe3, 0xb9, 0x46, 0x6c, 0xe1, 0x34, 0x38, 0x5a, 0xb8,
+	0x00, 0x13, 0xc8, 0x35, 0x7f, 0xaf, 0x9b, 0x75, 0x17, 0x76, 0xdf, 0xd5, 0xf8, 0xee, 0xab, 0xe5,
+	0x74, 0xf2, 0x88, 0xfd, 0xf7, 0x9d, 0x02, 0x1c, 0x1e, 0x4e, 0xec, 0x0c, 0x31, 0x98, 0xe9, 0xe8,
+	0x33, 0x9f, 0x60, 0x13, 0x9e, 0xce, 0x3c, 0xb9, 0x8e, 0x78, 0xa3, 0xbe, 0x3f, 0x06, 0x66, 0x38,
+	0xa1, 0x02, 0xbd, 0x05, 0x73, 0x24, 0x7e, 0xfb, 0x1f, 0x7c, 0x6d, 0xde, 0x63, 0x98, 0x52, 0x1c,
+	0x36, 0x56, 0x09, 0x04, 0xc3, 0x43, 0x8a, 0xcc, 0xf7, 0x0c, 0x98, 0x4d, 0xe4, 0x0e, 0x5e, 0x77,
+	0x99, 0x9f, 0x52, 0x77, 0xd5, 0xc0, 0x51, 0xe0, 0x50, 0x13, 0x16, 0xc8, 0xc0, 0x77, 0x42, 0xde,
+	0xe7, 0x6c, 0xb2, 0xd1, 0xa3, 0x6d, 0xd5, 0x79, 0x84, 0xd7, 0xab, 0xf5, 0x14, 0x1a, 0x9c, 0xca,
+	0x69, 0x7e, 0x49, 0x8b, 0x2c, 0x91, 0x15, 0x33, 0xd9, 0xf1, 0x50, 0x3c, 0xe6, 0x2b, 0x7b, 0xc4,
+	0xee, 0x4f, 0x0b, 0xda, 0xb7, 0xaa, 0x44, 0xb7, 0x12, 0x4f, 0x74, 0xc7, 0x93, 0x89, 0x6e, 0x26,
+	0x72, 0xce, 0x78, 0xa9, 0x0e, 0xbd, 0xa9, 0xed, 0x8f, 0x62, 0x9e, 0x91, 0x7b, 0xc2, 0xd4, 0x6a,
+	0xf0, 0x82, 0x4c, 0xce, 0xbd, 0xc3, 0x4d, 0x13, 0x80, 0xa3, 0x4d, 0xb3, 0xf4, 0x14, 0x4c, 0xc7,
+	0x88, 0x73, 0xbd, 0xf8, 0xfa, 0x1a, 0x1c, 0xdb, 0x73, 0x84, 0xc7, 0x6b, 0xbb, 0xb4, 0x5f, 0x6d,
+	0xf7, 0x27, 0x32, 0x6f, 0x8e, 0xf8, 0x88, 0x55, 0x4e, 0x23, 0x24, 0x18, 0x2b, 0x91, 0xe6, 0x07,
+	0x05, 0x98, 0xe3, 0x9b, 0x23, 0x76, 0x28, 0x6a, 0x42, 0xb1, 0x63, 0xf9, 0x4a, 0xdd, 0x4a, 0x66,
+	0x75, 0xba, 0x8c, 0xc6, 0x04, 0x3f, 0xa4, 0xf1, 0x9d, 0xc8, 0x45, 0xa1, 0x97, 0x83, 0xd6, 0xb2,
+	0x90, 0xe7, 0x13, 0x86, 0x8e, 0x6b, 0x8d, 0xca, 0x50, 0x3f, 0xfa, 0x72, 0xf0, 0x36, 0xa1, 0x98,
+	0x47, 0xf2, 0xd0, 0x0d, 0xb9, 0x94, 0xac, 0x3f, 0x68, 0x30, 0x7f, 0x50, 0x00, 0x19, 0xfa, 0x77,
+	0xa1, 0x5e, 0x5e, 0x8e, 0xd5, 0xcb, 0x8c, 0x59, 0x57, 0x18, 0x97, 0x5a, 0x2b, 0xbf, 0x98, 0xa8,
+	0x95, 0x27, 0xf3, 0x08, 0xdc, 0xbb, 0x4e, 0xfe, 0xd6, 0x80, 0x8a, 0xa0, 0xbb, 0x0b, 0xc5, 0xa8,
+	0x19, 0x2f, 0x46, 0x0f, 0xe7, 0xf8, 0x8a, 0x11, 0x85, 0xe8, 0x7b, 0x45, 0x65, 0x7d, 0x98, 0xf0,
+	0xba, 0xc4, 0x6b, 0xab, 0x03, 0x72, 0x94, 0xf0, 0x38, 0x10, 0x4b, 0x1c, 0xea, 0xc1, 0x34, 0xd3,
+	0x02, 0x85, 0xa9, 0xef, 0xcc, 0x58, 0xa2, 0xf4, 0x18, 0x63, 0x8d, 0x79, 0xf1, 0x56, 0x4b, 0x07,
+	0xe1, 0xb8, 0x70, 0xf4, 0xae, 0x01, 0x87, 0xdd, 0xe1, 0x4a, 0xa9, 0x02, 0xe3, 0xc9, 0x9c, 0x99,
+	0x2c, 0x12, 0xd0, 0xb8, 0x67, 0xf7, 0xe6, 0xf1, 0xb4, 0x1a, 0x8c, 0xd3, 0xd4, 0xa1, 0x2e, 0x1c,
+	0xd2, 0xef, 0x37, 0x55, 0x18, 0x9d, 0xca, 0x7f, 0x83, 0xda, 0x98, 0xdb, 0xbd, 0x79, 0xfc, 0x90,
+	0x0e, 0xc1, 0x31, 0xc9, 0xe6, 0x5f, 0x4a, 0x30, 0xa5, 0xc5, 0x1d, 0x3a, 0x19, 0x2f, 0x10, 0xf7,
+	0x25, 0x0b, 0x04, 0x08, 0xe2, 0x58, 0x71, 0xf0, 0x60, 0xa6, 0x35, 0xf0, 0x3c, 0x6a, 0xfb, 0xe7,
+	0x6f, 0x4b, 0x37, 0x86, 0x78, 0x13, 0xb1, 0x1a, 0x93, 0x88, 0x13, 0x1a, 0x78, 0xeb, 0xd7, 0xb5,
+	0x98, 0x98, 0x9c, 0xca, 0x22, 0xf3, 0x99, 0x5b, 0xbf, 0x8b, 0x52, 0x1c, 0x0e, 0xe4, 0xa2, 0x26,
+	0x94, 0xe5, 0x75, 0x9c, 0xba, 0xc5, 0x78, 0x24, 0xeb, 0x24, 0x8f, 0xf3, 0xc8, 0x64, 0x2f, 0x7f,
 	0x63, 0x25, 0x47, 0xaf, 0xa2, 0x95, 0x7d, 0xaa, 0xe8, 0xf3, 0x80, 0x9c, 0x0d, 0x46, 0xbd, 0x6d,
 	0xda, 0xbe, 0x20, 0x9f, 0xa1, 0xf3, 0x30, 0x28, 0x9f, 0x30, 0x1e, 0x2c, 0x36, 0x96, 0x14, 0x17,
-	0x7a, 0x71, 0x88, 0x02, 0xa7, 0x70, 0xa1, 0x01, 0xcc, 0x29, 0xef, 0x85, 0xf1, 0xa7, 0xbe, 0x01,
-	0xe5, 0xbd, 0x18, 0x44, 0xdf, 0xe3, 0x57, 0x13, 0x02, 0xf1, 0x90, 0x0a, 0x73, 0x05, 0xe6, 0x65,
-	0x60, 0xe9, 0xa5, 0x6d, 0xff, 0x17, 0xcb, 0xbf, 0x36, 0x20, 0x7e, 0x44, 0xe3, 0x2f, 0x31, 0x8c,
-	0x0c, 0x2f, 0x31, 0x6e, 0xc0, 0xcc, 0xc0, 0x65, 0xbe, 0x47, 0x49, 0x5f, 0x58, 0x10, 0x24, 0xb0,
-	0x27, 0xf2, 0xa4, 0x61, 0xbd, 0x38, 0x85, 0xad, 0xed, 0xb5, 0x98, 0x58, 0x9c, 0x50, 0x63, 0xfe,
-	0xab, 0x00, 0xb1, 0xb3, 0x86, 0xde, 0x35, 0x60, 0x9e, 0x24, 0x9e, 0x6f, 0x07, 0x4d, 0xf6, 0xb3,
-	0xf9, 0xde, 0xd4, 0x0f, 0xbd, 0xfe, 0x8e, 0xee, 0xbc, 0x49, 0x12, 0x86, 0x87, 0x95, 0x8a, 0xcc,
-	0x46, 0x86, 0xdf, 0xe7, 0xe7, 0xcb, 0x6c, 0x29, 0x0f, 0xfc, 0x65, 0x66, 0x4b, 0x41, 0xe0, 0x34,
-	0x75, 0xe8, 0x55, 0x28, 0x11, 0xaf, 0x13, 0x7c, 0x78, 0xc9, 0xaf, 0x36, 0xf8, 0xb7, 0x8b, 0x28,
-	0x76, 0xea, 0x5e, 0x87, 0x61, 0x21, 0xd4, 0xfc, 0x9b, 0x01, 0x43, 0x2f, 0x45, 0xd0, 0x99, 0x78,
-	0x46, 0x33, 0x93, 0x19, 0x6d, 0x5e, 0xe7, 0x18, 0xb7, 0xeb, 0xed, 0xc3, 0x94, 0xb6, 0x5a, 0x95,
-	0xaf, 0xcf, 0xe6, 0x5e, 0x9d, 0x96, 0x97, 0xe4, 0x7f, 0x48, 0x44, 0x18, 0x5d, 0xbe, 0x39, 0x0b,
-	0xd3, 0xb1, 0xb7, 0x18, 0x62, 0xc0, 0x10, 0x9e, 0x85, 0xcf, 0xea, 0x80, 0x21, 0x34, 0xf0, 0x76,
-	0x0e, 0x18, 0x22, 0xa1, 0x7b, 0x37, 0x4e, 0xfc, 0x26, 0x1f, 0xd2, 0x7e, 0x66, 0x6f, 0xf2, 0xa1,
-	0x85, 0x23, 0x1a, 0xa8, 0x77, 0xf4, 0x55, 0x88, 0x26, 0x8a, 0x0d, 0xf7, 0x47, 0x39, 0xea, 0x61,
-	0xf2, 0xee, 0xa1, 0x3d, 0x69, 0xdf, 0xa3, 0x4d, 0x12, 0xd7, 0xe8, 0x84, 0xe3, 0xf5, 0xd3, 0x52,
-	0x1c, 0xab, 0xba, 0x15, 0xc6, 0xa9, 0x6e, 0x8d, 0xe7, 0x3f, 0xf8, 0x64, 0xf9, 0xc0, 0x87, 0x9f,
-	0x2c, 0x1f, 0xf8, 0xe8, 0x93, 0xe5, 0x03, 0x5f, 0xdf, 0x5d, 0x36, 0x3e, 0xd8, 0x5d, 0x36, 0x3e,
-	0xdc, 0x5d, 0x36, 0x3e, 0xda, 0x5d, 0x36, 0x3e, 0xde, 0x5d, 0x36, 0xbe, 0xf7, 0x97, 0xe5, 0x03,
-	0xaf, 0xdc, 0x9f, 0xe5, 0xbf, 0xdc, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x94, 0x83, 0x79,
-	0x0c, 0x37, 0x00, 0x00,
+	0x7a, 0x71, 0x88, 0x02, 0xa7, 0x70, 0xa1, 0x01, 0xcc, 0x29, 0xef, 0x85, 0xf1, 0xa7, 0xee, 0x80,
+	0xf2, 0x1e, 0x0c, 0xa2, 0xfb, 0xf8, 0xd5, 0x84, 0x40, 0x3c, 0xa4, 0xc2, 0x5c, 0x81, 0x79, 0x19,
+	0x58, 0x7a, 0x69, 0xdb, 0xff, 0xc5, 0xf2, 0x6f, 0x0c, 0x88, 0x6f, 0xd1, 0xf8, 0x4b, 0x0c, 0x23,
+	0xc3, 0x4b, 0x8c, 0x1b, 0x30, 0x33, 0x70, 0x99, 0xef, 0x51, 0xd2, 0x17, 0x16, 0x04, 0x09, 0xec,
+	0x89, 0x3c, 0x69, 0x58, 0x2f, 0x4e, 0x61, 0x6b, 0x7b, 0x2d, 0x26, 0x16, 0x27, 0xd4, 0x98, 0xff,
+	0x2a, 0x40, 0x6c, 0xaf, 0xa1, 0xf7, 0x0c, 0x98, 0x27, 0x89, 0xe7, 0xdb, 0x41, 0x93, 0xfd, 0x6c,
+	0xbe, 0x37, 0xf5, 0x43, 0xaf, 0xbf, 0xa3, 0x33, 0x6f, 0x92, 0x84, 0xe1, 0x61, 0xa5, 0x22, 0xb3,
+	0x91, 0xe1, 0xf7, 0xf9, 0xf9, 0x32, 0x5b, 0xca, 0x03, 0x7f, 0x99, 0xd9, 0x52, 0x10, 0x38, 0x4d,
+	0x1d, 0x7a, 0x15, 0x4a, 0xc4, 0xeb, 0x04, 0x17, 0x2f, 0xf9, 0xd5, 0x06, 0xff, 0x76, 0x11, 0xc5,
+	0x4e, 0xdd, 0xeb, 0x30, 0x2c, 0x84, 0x9a, 0xef, 0x14, 0x60, 0xe8, 0xa5, 0x88, 0xba, 0xed, 0x2f,
+	0xa5, 0xde, 0xf6, 0x9f, 0x89, 0x67, 0x3b, 0x33, 0x99, 0xed, 0xe6, 0x75, 0x69, 0xe3, 0x76, 0xc4,
+	0x7d, 0x98, 0xd2, 0x3c, 0xa1, 0x72, 0xf9, 0xd9, 0xdc, 0x5f, 0xae, 0xe5, 0x2c, 0xf9, 0xdf, 0x13,
+	0x11, 0x46, 0x97, 0x6f, 0xce, 0xc2, 0x74, 0xec, 0x9d, 0x86, 0x18, 0x3e, 0x84, 0xfb, 0xe4, 0xf3,
+	0x3a, 0x7c, 0x08, 0x0d, 0xbc, 0x9d, 0xc3, 0x87, 0x48, 0xe8, 0xde, 0x4d, 0x15, 0x3f, 0xe5, 0x87,
+	0xb4, 0x9f, 0xdb, 0x53, 0x7e, 0x68, 0xe1, 0x88, 0xe6, 0xea, 0x5d, 0xfd, 0x2b, 0x44, 0x83, 0xc5,
+	0x86, 0x7b, 0xa7, 0x1c, 0xb5, 0x32, 0x79, 0x2e, 0xd1, 0x9e, 0xbb, 0xef, 0xd1, 0x42, 0x89, 0x23,
+	0x76, 0xc2, 0xf1, 0xfa, 0x6e, 0x29, 0x8e, 0x55, 0xf9, 0x0a, 0xe3, 0x54, 0xbe, 0xc6, 0xf3, 0x1f,
+	0x7e, 0xba, 0x7c, 0xe0, 0xa3, 0x4f, 0x97, 0x0f, 0x7c, 0xfc, 0xe9, 0xf2, 0x81, 0x6f, 0xee, 0x2e,
+	0x1b, 0x1f, 0xee, 0x2e, 0x1b, 0x1f, 0xed, 0x2e, 0x1b, 0x1f, 0xef, 0x2e, 0x1b, 0x9f, 0xec, 0x2e,
+	0x1b, 0xdf, 0xff, 0xeb, 0xf2, 0x81, 0x57, 0xee, 0xcf, 0xf2, 0x1f, 0x70, 0xff, 0x0e, 0x00, 0x00,
+	0xff, 0xff, 0x34, 0x9e, 0xc3, 0xd8, 0x28, 0x37, 0x00, 0x00,
 }
 
 func (m *AnalysisRunArgument) Marshal() (dAtA []byte, err error) {
@@ -4626,6 +4626,11 @@ func (m *VerificationInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	i -= len(m.ID)
+	copy(dAtA[i:], m.ID)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.ID)))
+	i--
+	dAtA[i] = 0x22
 	if m.AnalysisRun != nil {
 		{
 			size, err := m.AnalysisRun.MarshalToSizedBuffer(dAtA[:i])
@@ -5852,6 +5857,8 @@ func (m *VerificationInfo) Size() (n int) {
 		l = m.AnalysisRun.Size()
 		n += 1 + l + sovGenerated(uint64(l))
 	}
+	l = len(m.ID)
+	n += 1 + l + sovGenerated(uint64(l))
 	return n
 }
 
@@ -6758,6 +6765,7 @@ func (this *VerificationInfo) String() string {
 		`Phase:` + fmt.Sprintf("%v", this.Phase) + `,`,
 		`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
 		`AnalysisRun:` + strings.Replace(this.AnalysisRun.String(), "AnalysisRunReference", "AnalysisRunReference", 1) + `,`,
+		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -15237,6 +15245,38 @@ func (m *VerificationInfo) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto
index 976ad00c..c09c8b51 100644
--- a/api/v1alpha1/generated.proto
+++ b/api/v1alpha1/generated.proto
@@ -1012,6 +1012,9 @@ message Verification {
 // VerificationInfo contains information about the currently running
 // Verification process.
 message VerificationInfo {
+  // ID is the identifier of the Verification process.
+  optional string id = 4;
+
   // Phase describes the current phase of the Verification process. Generally,
   // this will be a reflection of the underlying AnalysisRun's phase, however,
   // there are exceptions to this, such as in the case where an AnalysisRun
diff --git a/api/v1alpha1/helpers.go b/api/v1alpha1/helpers.go
index c8cf1bb9..e4c03c81 100644
--- a/api/v1alpha1/helpers.go
+++ b/api/v1alpha1/helpers.go
@@ -3,25 +3,24 @@ package v1alpha1
 import (
 	"context"
 	"fmt"
-	"time"
 
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-func refreshObject(
-	ctx context.Context,
-	c client.Client,
-	obj client.Object,
-	nowFunc func() time.Time,
-) error {
-	patchBytes := []byte(
-		fmt.Sprintf(
-			`{"metadata":{"annotations":{"%s":"%s"}}}`,
-			AnnotationKeyRefresh,
-			nowFunc().UTC().Format(time.RFC3339),
-		),
-	)
+func ClearAnnotations(ctx context.Context, c client.Client, obj client.Object, keys ...string) error {
+	if len(keys) == 0 {
+		return nil
+	}
+
+	patchBytes := []byte(`{"metadata":{"annotations":{`)
+	for i, key := range keys {
+		if i > 0 {
+			patchBytes = append(patchBytes, ',')
+		}
+		patchBytes = append(patchBytes, fmt.Sprintf(`"%s":null`, key)...)
+	}
+	patchBytes = append(patchBytes, "}}}"...)
 	patch := client.RawPatch(types.MergePatchType, patchBytes)
 	if err := c.Patch(ctx, obj, patch); err != nil {
 		return fmt.Errorf("patch annotation: %w", err)
@@ -29,12 +28,14 @@ func refreshObject(
 	return nil
 }
 
-func clearRefreshObject(
-	ctx context.Context,
-	c client.Client,
-	obj client.Object,
-) error {
-	patchBytes := []byte(fmt.Sprintf(`{"metadata":{"annotations":{"%s":null}}}`, AnnotationKeyRefresh))
+func patchAnnotation(ctx context.Context, c client.Client, obj client.Object, key, value string) error {
+	patchBytes := []byte(
+		fmt.Sprintf(
+			`{"metadata":{"annotations":{"%s":"%s"}}}`,
+			key,
+			value,
+		),
+	)
 	patch := client.RawPatch(types.MergePatchType, patchBytes)
 	if err := c.Patch(ctx, obj, patch); err != nil {
 		return fmt.Errorf("patch annotation: %w", err)
diff --git a/api/v1alpha1/promotion_helpers.go b/api/v1alpha1/promotion_helpers.go
index 310ba17b..e0604bb4 100644
--- a/api/v1alpha1/promotion_helpers.go
+++ b/api/v1alpha1/promotion_helpers.go
@@ -48,30 +48,8 @@ func RefreshPromotion(
 			Name:      namespacedName.Name,
 		},
 	}
-	if err := refreshObject(ctx, c, promo, time.Now); err != nil {
+	if err := patchAnnotation(ctx, c, promo, AnnotationKeyRefresh, time.Now().Format(time.RFC3339)); err != nil {
 		return nil, fmt.Errorf("refresh: %w", err)
 	}
 	return promo, nil
 }
-
-// ClearPromotionRefresh is called by the Promotion controller to clear the refresh
-// annotation on the Promotion (if present).
-func ClearPromotionRefresh(
-	ctx context.Context,
-	c client.Client,
-	promo *Promotion,
-) error {
-	if promo.Annotations == nil {
-		return nil
-	}
-	if _, ok := promo.Annotations[AnnotationKeyRefresh]; !ok {
-		return nil
-	}
-	newPromo := Promotion{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      promo.Name,
-			Namespace: promo.Namespace,
-		},
-	}
-	return clearRefreshObject(ctx, c, &newPromo)
-}
diff --git a/api/v1alpha1/stage_helpers.go b/api/v1alpha1/stage_helpers.go
index 002e6d8f..41fe0674 100644
--- a/api/v1alpha1/stage_helpers.go
+++ b/api/v1alpha1/stage_helpers.go
@@ -2,6 +2,7 @@ package v1alpha1
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"time"
 
@@ -48,32 +49,77 @@ func RefreshStage(
 			Name:      namespacedName.Name,
 		},
 	}
-	if err := refreshObject(ctx, c, stage, time.Now); err != nil {
+	if err := patchAnnotation(ctx, c, stage, AnnotationKeyRefresh, time.Now().Format(time.RFC3339)); err != nil {
 		return nil, fmt.Errorf("refresh: %w", err)
 	}
 	return stage, nil
 }
 
-// ClearStageRefresh is called by the Stage controller to clear the refresh
-// annotation on the Stage (if present). A client (e.g. UI) who requested a
-// Stage refresh, can wait until the annotation is cleared, to understand that
-// the controller successfully reconciled the Stage after the refresh request.
-func ClearStageRefresh(
+// ReverifyStageFreight forces reconfirmation of the verification of the
+// Freight associated with a Stage by setting an AnnotationKeyReverify
+// annotation on the Stage, causing the controller to rerun the verification.
+// The annotation value is the identifier of the existing VerificationInfo for
+// the Stage.
+func ReverifyStageFreight(
 	ctx context.Context,
 	c client.Client,
-	stage *Stage,
+	namespacedName types.NamespacedName,
 ) error {
-	if stage.Annotations == nil {
-		return nil
+	stage, err := GetStage(ctx, c, namespacedName)
+	if err != nil || stage == nil {
+		if stage == nil {
+			err = fmt.Errorf("Stage %q in namespace %q not found", namespacedName.Name, namespacedName.Namespace)
+		}
+		return err
+	}
+
+	curFreight := stage.Status.CurrentFreight
+	if curFreight == nil {
+		return errors.New("stage has no current freight")
+	}
+	if curFreight.VerificationInfo == nil {
+		return errors.New("stage has no existing verification info")
+	}
+	if curFreight.VerificationInfo.ID == "" {
+		return fmt.Errorf("stage verification info has no ID")
+	}
+
+	return patchAnnotation(ctx, c, stage, AnnotationKeyReverify, curFreight.VerificationInfo.ID)
+}
+
+// AbortStageFreightVerification forces aborting the verification of the
+// Freight associated with a Stage by setting an AnnotationKeyAbort
+// annotation on the Stage, causing the controller to abort the verification.
+// The annotation value is the identifier of the existing VerificationInfo for
+// the Stage.
+func AbortStageFreightVerification(
+	ctx context.Context,
+	c client.Client,
+	namespacedName types.NamespacedName,
+) error {
+	stage, err := GetStage(ctx, c, namespacedName)
+	if err != nil || stage == nil {
+		if stage == nil {
+			err = fmt.Errorf("Stage %q in namespace %q not found", namespacedName.Name, namespacedName.Namespace)
+		}
+		return err
 	}
-	if _, ok := stage.Annotations[AnnotationKeyRefresh]; !ok {
+
+	curFreight := stage.Status.CurrentFreight
+	if curFreight == nil {
+		return errors.New("stage has no current freight")
+	}
+	if curFreight.VerificationInfo == nil {
+		return errors.New("stage has no existing verification info")
+	}
+	if stage.Status.CurrentFreight.VerificationInfo.Phase.IsTerminal() {
+		// The verification is already in a terminal phase, so we can skip the
+		// abort request.
 		return nil
 	}
-	newStage := Stage{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      stage.Name,
-			Namespace: stage.Namespace,
-		},
+	if curFreight.VerificationInfo.ID == "" {
+		return fmt.Errorf("stage verification info has no ID")
 	}
-	return clearRefreshObject(ctx, c, &newStage)
+
+	return patchAnnotation(ctx, c, stage, AnnotationKeyAbort, curFreight.VerificationInfo.ID)
 }
diff --git a/api/v1alpha1/stage_types.go b/api/v1alpha1/stage_types.go
index 485f8603..9b622d91 100644
--- a/api/v1alpha1/stage_types.go
+++ b/api/v1alpha1/stage_types.go
@@ -40,6 +40,9 @@ const (
 	// VerificationPhaseError denotes a verification process that has completed
 	// with an error.
 	VerificationPhaseError VerificationPhase = "Error"
+	// VerificationPhaseAborted denotes a verification process that has been
+	// aborted.
+	VerificationPhaseAborted VerificationPhase = "Aborted"
 	// VerificationPhaseInconclusive denotes a verification process that has
 	// completed with an inconclusive result.
 	VerificationPhaseInconclusive VerificationPhase = "Inconclusive"
@@ -49,7 +52,7 @@ const (
 func (v *VerificationPhase) IsTerminal() bool {
 	switch *v {
 	case VerificationPhaseSuccessful, VerificationPhaseFailed,
-		VerificationPhaseError, VerificationPhaseInconclusive:
+		VerificationPhaseError, VerificationPhaseAborted, VerificationPhaseInconclusive:
 		return true
 	default:
 		return false
@@ -728,6 +731,8 @@ type AnalysisRunArgument struct {
 // VerificationInfo contains information about the currently running
 // Verification process.
 type VerificationInfo struct {
+	// ID is the identifier of the Verification process.
+	ID string `json:"id,omitempty" protobuf:"bytes,4,opt,name=id"`
 	// Phase describes the current phase of the Verification process. Generally,
 	// this will be a reflection of the underlying AnalysisRun's phase, however,
 	// there are exceptions to this, such as in the case where an AnalysisRun
diff --git a/api/v1alpha1/warehouse_helpers.go b/api/v1alpha1/warehouse_helpers.go
index 61c81b4b..71e1d549 100644
--- a/api/v1alpha1/warehouse_helpers.go
+++ b/api/v1alpha1/warehouse_helpers.go
@@ -48,32 +48,14 @@ func RefreshWarehouse(
 			Name:      namespacedName.Name,
 		},
 	}
-	if err := refreshObject(ctx, c, warehouse, time.Now); err != nil {
+	if err := patchAnnotation(
+		ctx,
+		c,
+		warehouse,
+		AnnotationKeyRefresh,
+		time.Now().Format(time.RFC3339),
+	); err != nil {
 		return nil, fmt.Errorf("refresh: %w", err)
 	}
 	return warehouse, nil
 }
-
-// ClearWarehouseRefresh is called by the Warehouse controller to clear the refresh
-// annotation on the Warehouse (if present). A client (e.g. UI) who requested a
-// Warehouse refresh, can wait until the annotation is cleared, to understand that
-// the controller successfully reconciled the Warehouse after the refresh request.
-func ClearWarehouseRefresh(
-	ctx context.Context,
-	c client.Client,
-	wh *Warehouse,
-) error {
-	if wh.Annotations == nil {
-		return nil
-	}
-	if _, ok := wh.Annotations[AnnotationKeyRefresh]; !ok {
-		return nil
-	}
-	newWh := Warehouse{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      wh.Name,
-			Namespace: wh.Namespace,
-		},
-	}
-	return clearRefreshObject(ctx, c, &newWh)
-}
diff --git a/charts/kargo/crds/kargo.akuity.io_stages.yaml b/charts/kargo/crds/kargo.akuity.io_stages.yaml
index 02ece9d6..54d63fc4 100644
--- a/charts/kargo/crds/kargo.akuity.io_stages.yaml
+++ b/charts/kargo/crds/kargo.akuity.io_stages.yaml
@@ -687,6 +687,9 @@ spec:
                         - namespace
                         - phase
                         type: object
+                      id:
+                        description: ID is the identifier of the Verification process.
+                        type: string
                       message:
                         description: |-
                           Message may contain additional information about why the verification
@@ -838,6 +841,10 @@ spec:
                             - namespace
                             - phase
                             type: object
+                          id:
+                            description: ID is the identifier of the Verification
+                              process.
+                            type: string
                           message:
                             description: |-
                               Message may contain additional information about why the verification
@@ -1055,6 +1062,9 @@ spec:
                           - namespace
                           - phase
                           type: object
+                        id:
+                          description: ID is the identifier of the Verification process.
+                          type: string
                         message:
                           description: |-
                             Message may contain additional information about why the verification
diff --git a/charts/kargo/templates/controller/cluster-roles.yaml b/charts/kargo/templates/controller/cluster-roles.yaml
index 904161f4..d48d9fb0 100644
--- a/charts/kargo/templates/controller/cluster-roles.yaml
+++ b/charts/kargo/templates/controller/cluster-roles.yaml
@@ -111,6 +111,7 @@ rules:
   - create
   - get
   - list
+  - patch
   - watch
   - deletecollection
 {{- end }}
diff --git a/cmd/cli/root.go b/cmd/cli/root.go
index 6582da93..27728b53 100644
--- a/cmd/cli/root.go
+++ b/cmd/cli/root.go
@@ -20,6 +20,7 @@ import (
 	"github.com/akuity/kargo/internal/cli/cmd/refresh"
 	"github.com/akuity/kargo/internal/cli/cmd/server"
 	"github.com/akuity/kargo/internal/cli/cmd/update"
+	"github.com/akuity/kargo/internal/cli/cmd/verify"
 	"github.com/akuity/kargo/internal/cli/cmd/version"
 	clicfg "github.com/akuity/kargo/internal/cli/config"
 	"github.com/akuity/kargo/internal/cli/io"
@@ -52,6 +53,7 @@ func NewRootCommand(cfg clicfg.CLIConfig) *cobra.Command {
 	cmd.AddCommand(update.NewCommand(cfg, streams))
 	cmd.AddCommand(dashboard.NewCommand(cfg))
 	cmd.AddCommand(promote.NewCommand(cfg, streams))
+	cmd.AddCommand(verify.NewCommand(cfg))
 	cmd.AddCommand(version.NewCommand(cfg, streams))
 	cmd.AddCommand(server.NewCommand())
 	cmd.AddCommand(
diff --git a/internal/api/abort_verification_v1alpha1.go b/internal/api/abort_verification_v1alpha1.go
new file mode 100644
index 00000000..f8428752
--- /dev/null
+++ b/internal/api/abort_verification_v1alpha1.go
@@ -0,0 +1,38 @@
+package api
+
+import (
+	"context"
+
+	"connectrpc.com/connect"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	kargoapi "github.com/akuity/kargo/api/v1alpha1"
+	svcv1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1"
+)
+
+func (s *server) AbortVerification(
+	ctx context.Context,
+	req *connect.Request[svcv1alpha1.AbortVerificationRequest],
+) (*connect.Response[svcv1alpha1.AbortVerificationResponse], error) {
+	project := req.Msg.GetProject()
+	if err := validateFieldNotEmpty("project", project); err != nil {
+		return nil, err
+	}
+	stage := req.Msg.GetStage()
+	if err := validateFieldNotEmpty("stage", stage); err != nil {
+		return nil, err
+	}
+
+	if err := s.validateProjectExists(ctx, project); err != nil {
+		return nil, err
+	}
+
+	objKey := client.ObjectKey{
+		Namespace: project,
+		Name:      stage,
+	}
+	if err := kargoapi.AbortStageFreightVerification(ctx, s.client, objKey); err != nil {
+		return nil, err
+	}
+	return connect.NewResponse(&svcv1alpha1.AbortVerificationResponse{}), nil
+}
diff --git a/internal/api/reverify_v1alpha1.go b/internal/api/reverify_v1alpha1.go
new file mode 100644
index 00000000..ce3afecc
--- /dev/null
+++ b/internal/api/reverify_v1alpha1.go
@@ -0,0 +1,38 @@
+package api
+
+import (
+	"context"
+
+	"connectrpc.com/connect"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	kargoapi "github.com/akuity/kargo/api/v1alpha1"
+	svcv1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1"
+)
+
+func (s *server) Reverify(
+	ctx context.Context,
+	req *connect.Request[svcv1alpha1.ReverifyRequest],
+) (*connect.Response[svcv1alpha1.ReverifyResponse], error) {
+	project := req.Msg.GetProject()
+	if err := validateFieldNotEmpty("project", project); err != nil {
+		return nil, err
+	}
+	stage := req.Msg.GetStage()
+	if err := validateFieldNotEmpty("stage", stage); err != nil {
+		return nil, err
+	}
+
+	if err := s.validateProjectExists(ctx, project); err != nil {
+		return nil, err
+	}
+
+	objKey := client.ObjectKey{
+		Namespace: project,
+		Name:      stage,
+	}
+	if err := kargoapi.ReverifyStageFreight(ctx, s.client, objKey); err != nil {
+		return nil, err
+	}
+	return connect.NewResponse(&svcv1alpha1.ReverifyResponse{}), nil
+}
diff --git a/internal/cli/cmd/verify/stage.go b/internal/cli/cmd/verify/stage.go
new file mode 100644
index 00000000..c6f039df
--- /dev/null
+++ b/internal/cli/cmd/verify/stage.go
@@ -0,0 +1,134 @@
+package verify
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"strings"
+
+	"connectrpc.com/connect"
+	"github.com/spf13/cobra"
+
+	"github.com/akuity/kargo/internal/cli/client"
+	"github.com/akuity/kargo/internal/cli/config"
+	"github.com/akuity/kargo/internal/cli/option"
+	v1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1"
+)
+
+type verifyStageOptions struct {
+	Config        config.CLIConfig
+	ClientOptions client.Options
+
+	Project string
+	Name    string
+	Abort   bool
+}
+
+func newVerifyStageCommand(cfg config.CLIConfig) *cobra.Command {
+	cmdOpts := &verifyStageOptions{
+		Config: cfg,
+	}
+
+	cmd := &cobra.Command{
+		Use:   "stage [--project=project] (NAME) [--abort]",
+		Short: "(Re)run or abort the verification of the stage's current freight",
+		Args:  option.ExactArgs(1),
+		Example: `
+# Rerun the verification of the stage's current freight
+kargo verify stage --project=my-project my-stage
+
+# Rerun the verification of a stage in the default project
+kargo config set-project my-project
+kargo verify stage my-stage
+
+# Abort the verification of a stage's current freight
+kargo verify stage --project=my-project my-stage --abort
+
+# Abort the verification of a stage in the default project
+kargo config set-project my-project
+kargo verify stage my-stage --abort
+`,
+		RunE: func(cmd *cobra.Command, args []string) error {
+			cmdOpts.complete(args)
+
+			if err := cmdOpts.validate(); err != nil {
+				return err
+			}
+
+			return cmdOpts.run(cmd.Context())
+		},
+	}
+
+	// Register the option flags on the command.
+	cmdOpts.addFlags(cmd)
+
+	return cmd
+}
+
+// addFlags adds the flags for the verify stage options to the provided command.
+func (o *verifyStageOptions) addFlags(cmd *cobra.Command) {
+	o.ClientOptions.AddFlags(cmd.PersistentFlags())
+
+	option.Project(
+		cmd.Flags(), &o.Project, o.Config.Project,
+		"The project the stage belongs to. If not set, the default project will be used.",
+	)
+	cmd.Flags().BoolVar(&o.Abort, "abort", false, "If set, the verification will be aborted.")
+}
+
+// complete sets the options from the command arguments.
+func (o *verifyStageOptions) complete(args []string) {
+	o.Name = strings.TrimSpace(strings.ToLower(args[0]))
+}
+
+// validate performs validation of the options. If the options are invalid, an
+// error is returned.
+func (o *verifyStageOptions) validate() error {
+	var errs []error
+	// While the flags are marked as required, a user could still provide an empty
+	// string. This is a check to ensure that the flags are not empty.
+	if o.Project == "" {
+		errs = append(errs, fmt.Errorf("%s is required", option.ProjectFlag))
+	}
+	if o.Name == "" {
+		errs = append(errs, errors.New("name is required"))
+	}
+	return errors.Join(errs...)
+}
+
+// run requests a rerun of the stage verification.
+func (o *verifyStageOptions) run(ctx context.Context) error {
+	kargoSvcCli, err := client.GetClientFromConfig(ctx, o.Config, o.ClientOptions)
+	if err != nil {
+		return fmt.Errorf("get client from config: %w", err)
+	}
+
+	if o.Abort {
+		if _, err := kargoSvcCli.AbortVerification(
+			ctx,
+			connect.NewRequest(
+				&v1alpha1.AbortVerificationRequest{
+					Project: o.Project,
+					Stage:   o.Name,
+				},
+			),
+		); err != nil {
+			return fmt.Errorf("abort verification: %w", err)
+		}
+		return nil
+	}
+
+	if _, err := kargoSvcCli.Reverify(
+		ctx,
+		connect.NewRequest(
+			&v1alpha1.ReverifyRequest{
+				Project: o.Project,
+				Stage:   o.Name,
+			},
+		),
+	); err != nil {
+		return fmt.Errorf("reverify stage: %w", err)
+	}
+
+	return nil
+}
diff --git a/internal/cli/cmd/verify/verify.go b/internal/cli/cmd/verify/verify.go
new file mode 100644
index 00000000..c39494ec
--- /dev/null
+++ b/internal/cli/cmd/verify/verify.go
@@ -0,0 +1,25 @@
+package verify
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/akuity/kargo/internal/cli/config"
+	"github.com/akuity/kargo/internal/cli/option"
+)
+
+func NewCommand(cfg config.CLIConfig) *cobra.Command {
+	cmd := &cobra.Command{
+		Use:   "verify SUBCOMMAND",
+		Short: "Verify a stage",
+		Args:  option.NoArgs,
+		Example: `
+# Verify a stage
+kargo verify stage --project=my-project my-stage
+`,
+	}
+
+	// Register subcommands.
+	cmd.AddCommand(newVerifyStageCommand(cfg))
+
+	return cmd
+}
diff --git a/internal/controller/promotions/promotions.go b/internal/controller/promotions/promotions.go
index 12649533..f137629b 100644
--- a/internal/controller/promotions/promotions.go
+++ b/internal/controller/promotions/promotions.go
@@ -72,7 +72,11 @@ func SetupReconcilerWithManager(
 		For(&kargoapi.Promotion{}).
 		WithEventFilter(changePredicate).
 		WithEventFilter(shardPredicate).
-		WithEventFilter(kargo.IgnoreClearRefreshUpdates{}).
+		WithEventFilter(kargo.IgnoreAnnotationRemoval{
+			Annotations: []string{
+				kargoapi.AnnotationKeyRefresh,
+			},
+		}).
 		WithOptions(controller.CommonOptions()).
 		Build(reconciler)
 	if err != nil {
@@ -235,9 +239,15 @@ func (r *reconciler) Reconcile(
 	if err != nil {
 		logger.Errorf("error updating Promotion status: %s", err)
 	}
-	if clearRefreshErr := kargoapi.ClearPromotionRefresh(ctx, r.kargoClient, promo); clearRefreshErr != nil {
+	if clearRefreshErr := kargoapi.ClearAnnotations(
+		ctx,
+		r.kargoClient,
+		promo,
+		kargoapi.AnnotationKeyRefresh,
+	); clearRefreshErr != nil {
 		logger.Errorf("error clearing Promotion refresh annotation: %s", clearRefreshErr)
 	}
+
 	if err != nil {
 		// Controller runtime automatically gives us a progressive backoff if err is
 		// not nil
diff --git a/internal/controller/stages/stages.go b/internal/controller/stages/stages.go
index c0bca2d6..f171b060 100644
--- a/internal/controller/stages/stages.go
+++ b/internal/controller/stages/stages.go
@@ -2,6 +2,7 @@ package stages
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"sort"
 	"time"
@@ -88,6 +89,11 @@ type reconciler struct {
 		*kargoapi.Stage,
 	) *kargoapi.VerificationInfo
 
+	abortVerificationFn func(
+		context.Context,
+		*kargoapi.Stage,
+	) *kargoapi.VerificationInfo
+
 	getVerificationInfoFn func(
 		context.Context,
 		*kargoapi.Stage,
@@ -117,6 +123,13 @@ type reconciler struct {
 		...client.CreateOption,
 	) error
 
+	patchAnalysisRunFn func(
+		context.Context,
+		client.Object,
+		client.Patch,
+		...client.PatchOption,
+	) error
+
 	getAnalysisRunFn func(
 		context.Context,
 		client.Client,
@@ -305,7 +318,13 @@ func SetupReconcilerWithManager(
 			),
 		).
 		WithEventFilter(shardPredicate).
-		WithEventFilter(kargo.IgnoreClearRefreshUpdates{}).
+		WithEventFilter(kargo.IgnoreAnnotationRemoval{
+			Annotations: []string{
+				kargoapi.AnnotationKeyRefresh,
+				kargoapi.AnnotationKeyReverify,
+				kargoapi.AnnotationKeyAbort,
+			},
+		}).
 		WithOptions(controller.CommonOptions()).
 		Build(
 			newReconciler(
@@ -445,12 +464,14 @@ func newReconciler(
 	r.getArgoCDAppFn = argocd.GetApplication
 	// Freight verification:
 	r.startVerificationFn = r.startVerification
+	r.abortVerificationFn = r.abortVerification
 	r.getVerificationInfoFn = r.getVerificationInfo
 	r.getAnalysisTemplateFn = rollouts.GetAnalysisTemplate
 	r.listAnalysisRunsFn = r.kargoClient.List
 	r.buildAnalysisRunFn = r.buildAnalysisRun
 	if rolloutsClient != nil {
 		r.createAnalysisRunFn = r.rolloutsClient.Create
+		r.patchAnalysisRunFn = r.rolloutsClient.Patch
 	}
 	r.getAnalysisRunFn = rollouts.GetAnalysisRun
 	r.getFreightFn = kargoapi.GetFreight
@@ -532,19 +553,23 @@ func (r *reconciler) Reconcile(
 	if updateErr != nil {
 		logger.Errorf("error updating Stage status: %s", updateErr)
 	}
-	clearRefreshErr := kargoapi.ClearStageRefresh(ctx, r.kargoClient, stage)
-	if clearRefreshErr != nil {
-		logger.Errorf("error clearing Stage refresh annotation: %s", clearRefreshErr)
+	clearErr := kargoapi.ClearAnnotations(
+		ctx,
+		r.kargoClient,
+		stage,
+		kargoapi.AnnotationKeyRefresh,
+		kargoapi.AnnotationKeyReverify,
+		kargoapi.AnnotationKeyAbort,
+	)
+	if clearErr != nil {
+		logger.Errorf("error clearing Stage annotations: %s", clearErr)
 	}
 
 	// If we had no error, but couldn't update, then we DO have an error. But we
 	// do it this way so that a failure to update is never counted as THE failure
 	// when something else more serious occurred first.
 	if err == nil {
-		err = updateErr
-	}
-	if err == nil {
-		err = clearRefreshErr
+		err = errors.Join(updateErr, clearErr)
 	}
 	logger.Debug("done reconciling Stage")
 
@@ -706,30 +731,53 @@ func (r *reconciler) syncNormalStage(
 		}
 
 		// Initiate or follow-up on verification if required
-		// NOTE: If stage cache is stale, phase can be StagePhaseNotApplicable
-		//       even though current freight is not empty in that case
-		//       check if verification step is necessary and if yes execute
-		//       step irrespective of phase
-		if (status.Phase == kargoapi.StagePhaseVerifying || status.Phase == kargoapi.StagePhaseNotApplicable) &&
-			stage.Spec.Verification != nil {
-			if status.CurrentFreight.VerificationInfo == nil {
-				if status.Health == nil || status.Health.Status == kargoapi.HealthStateHealthy {
-					log.Debug("starting verification")
-					status.CurrentFreight.VerificationInfo = r.startVerificationFn(ctx, stage)
+		if stage.Spec.Verification != nil {
+			// Confirm if a reverification is requested. If so, clear the
+			// verification info to start the verification process again.
+			info := status.CurrentFreight.VerificationInfo
+			if info != nil && info.ID != "" && info.Phase.IsTerminal() {
+				if v, ok := stage.GetAnnotations()[kargoapi.AnnotationKeyReverify]; ok && v == info.ID {
+					logger.Debug("rerunning verification")
+					status.Phase = kargoapi.StagePhaseVerifying
+					status.CurrentFreight.VerificationInfo = nil
 				}
-			} else {
-				log.Debug("checking verification results")
-				status.CurrentFreight.VerificationInfo = r.getVerificationInfoFn(ctx, stage)
 			}
-			if status.CurrentFreight.VerificationInfo != nil {
-				log.Debugf(
-					"verification phase is %s",
-					status.CurrentFreight.VerificationInfo.Phase,
-				)
-				if status.CurrentFreight.VerificationInfo.Phase.IsTerminal() {
-					// Verification is complete
-					status.Phase = kargoapi.StagePhaseSteady
-					log.Debug("verification is complete")
+
+			// NOTE: If stage cache is stale, phase can be StagePhaseNotApplicable
+			//       even though current freight is not empty in that case
+			//       check if verification step is necessary and if yes execute
+			//       step irrespective of phase
+			if status.Phase == kargoapi.StagePhaseVerifying || status.Phase == kargoapi.StagePhaseNotApplicable {
+				if status.CurrentFreight.VerificationInfo == nil {
+					if status.Health == nil || status.Health.Status == kargoapi.HealthStateHealthy {
+						log.Debug("starting verification")
+						status.CurrentFreight.VerificationInfo = r.startVerificationFn(ctx, stage)
+					}
+				} else {
+					log.Debug("checking verification results")
+					status.CurrentFreight.VerificationInfo = r.getVerificationInfoFn(ctx, stage)
+
+					// Abort the verification if it's still running and the Stage has
+					// been marked to do so.
+					newInfo := status.CurrentFreight.VerificationInfo
+					if newInfo.ID != "" && !newInfo.Phase.IsTerminal() {
+						if v, ok := stage.GetAnnotations()[kargoapi.AnnotationKeyAbort]; ok && v == newInfo.ID {
+							log.Debug("aborting verification")
+							status.CurrentFreight.VerificationInfo = r.abortVerificationFn(ctx, stage)
+						}
+					}
+				}
+
+				if status.CurrentFreight.VerificationInfo != nil {
+					log.Debugf(
+						"verification phase is %s",
+						status.CurrentFreight.VerificationInfo.Phase,
+					)
+					if status.CurrentFreight.VerificationInfo.Phase.IsTerminal() {
+						// Verification is complete
+						status.Phase = kargoapi.StagePhaseSteady
+						log.Debug("verification is complete")
+					}
 				}
 			}
 		}
diff --git a/internal/controller/stages/verification.go b/internal/controller/stages/verification.go
index b03c9409..6ba80fec 100644
--- a/internal/controller/stages/verification.go
+++ b/internal/controller/stages/verification.go
@@ -3,8 +3,10 @@ package stages
 import (
 	"context"
 	"fmt"
+	"sort"
 	"strings"
 
+	"github.com/google/uuid"
 	"github.com/oklog/ulid/v2"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
@@ -22,6 +24,7 @@ func (r *reconciler) startVerification(
 ) *kargoapi.VerificationInfo {
 	if r.rolloutsClient == nil {
 		return &kargoapi.VerificationInfo{
+			ID:    uuid.NewString(),
 			Phase: kargoapi.VerificationPhaseError,
 			Message: "Rollouts integration is disabled on this controller; " +
 				"cannot start verification",
@@ -32,41 +35,54 @@ func (r *reconciler) startVerification(
 
 	namespace := r.getAnalysisRunNamespace(stage)
 
-	// Check for existing AnalysisRun
-	analysisRuns := rollouts.AnalysisRunList{}
-	if err := r.listAnalysisRunsFn(
-		ctx,
-		&analysisRuns,
-		&client.ListOptions{
-			Namespace: namespace,
-			LabelSelector: labels.SelectorFromSet(
-				map[string]string{
-					kargoapi.StageLabelKey:   stage.Name,
-					kargoapi.FreightLabelKey: stage.Status.CurrentFreight.Name,
-				},
-			),
-		},
-	); err != nil {
-		return &kargoapi.VerificationInfo{
-			Phase: kargoapi.VerificationPhaseError,
-			Message: fmt.Errorf(
-				"error listing AnalysisRuns for Stage %q and Freight %q in namespace %q: %w",
-				stage.Name,
-				stage.Status.CurrentFreight.Name,
-				namespace,
-				err,
-			).Error(),
-		}
-	}
-	if len(analysisRuns.Items) > 0 {
-		logger.Debug("AnalysisRun already exists for Freight")
-		return &kargoapi.VerificationInfo{
-			Phase: kargoapi.VerificationPhase(analysisRuns.Items[0].Status.Phase),
-			AnalysisRun: &kargoapi.AnalysisRunReference{
-				Name:      analysisRuns.Items[0].Name,
-				Namespace: analysisRuns.Items[0].Namespace,
-				Phase:     string(analysisRuns.Items[0].Status.Phase),
+	// If the stage does not have a reverification annotation, check if there is
+	// an existing AnalysisRun for the Stage and Freight. If there is, return
+	// the status of this AnalysisRun.
+	if _, ok := stage.GetAnnotations()[kargoapi.AnnotationKeyReverify]; !ok {
+		analysisRuns := rollouts.AnalysisRunList{}
+		if err := r.listAnalysisRunsFn(
+			ctx,
+			&analysisRuns,
+			&client.ListOptions{
+				Namespace: namespace,
+				LabelSelector: labels.SelectorFromSet(
+					map[string]string{
+						kargoapi.StageLabelKey:   stage.Name,
+						kargoapi.FreightLabelKey: stage.Status.CurrentFreight.Name,
+					},
+				),
 			},
+		); err != nil {
+			return &kargoapi.VerificationInfo{
+				ID:    uuid.NewString(),
+				Phase: kargoapi.VerificationPhaseError,
+				Message: fmt.Errorf(
+					"error listing AnalysisRuns for Stage %q and Freight %q in namespace %q: %w",
+					stage.Name,
+					stage.Status.CurrentFreight.Name,
+					namespace,
+					err,
+				).Error(),
+			}
+		}
+		if len(analysisRuns.Items) > 0 {
+			// Sort the AnalysisRuns by creation timestamp, so that the most recent
+			// one is first.
+			sort.SliceStable(analysisRuns.Items, func(i, j int) bool {
+				return analysisRuns.Items[j].CreationTimestamp.Before(&analysisRuns.Items[i].CreationTimestamp)
+			})
+
+			logger.Debug("AnalysisRun already exists for Freight")
+			latestAnalysisRun := analysisRuns.Items[0]
+			return &kargoapi.VerificationInfo{
+				ID:    uuid.NewString(),
+				Phase: kargoapi.VerificationPhase(latestAnalysisRun.Status.Phase),
+				AnalysisRun: &kargoapi.AnalysisRunReference{
+					Name:      latestAnalysisRun.Name,
+					Namespace: latestAnalysisRun.Namespace,
+					Phase:     string(latestAnalysisRun.Status.Phase),
+				},
+			}
 		}
 	}
 
@@ -84,6 +100,7 @@ func (r *reconciler) startVerification(
 		)
 		if err != nil {
 			return &kargoapi.VerificationInfo{
+				ID:    uuid.NewString(),
 				Phase: kargoapi.VerificationPhaseError,
 				Message: fmt.Errorf(
 					"error getting AnalysisTemplate %q in namespace %q: %w",
@@ -95,6 +112,7 @@ func (r *reconciler) startVerification(
 		}
 		if template == nil {
 			return &kargoapi.VerificationInfo{
+				ID:    uuid.NewString(),
 				Phase: kargoapi.VerificationPhaseError,
 				Message: fmt.Errorf(
 					"AnalysisTemplate %q in namespace %q not found",
@@ -116,6 +134,7 @@ func (r *reconciler) startVerification(
 	)
 	if err != nil {
 		return &kargoapi.VerificationInfo{
+			ID:    uuid.NewString(),
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"error getting Freight %q in namespace %q: %w",
@@ -127,6 +146,7 @@ func (r *reconciler) startVerification(
 	}
 	if freight == nil {
 		return &kargoapi.VerificationInfo{
+			ID:    uuid.NewString(),
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"Freight %q in namespace %q not found",
@@ -139,6 +159,7 @@ func (r *reconciler) startVerification(
 	run, err := r.buildAnalysisRunFn(stage, freight, templates)
 	if err != nil {
 		return &kargoapi.VerificationInfo{
+			ID:    uuid.NewString(),
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"error building AnalysisRun for Stage %q and Freight %q in namespace %q: %w",
@@ -152,6 +173,7 @@ func (r *reconciler) startVerification(
 
 	if err := r.createAnalysisRunFn(ctx, run); err != nil {
 		return &kargoapi.VerificationInfo{
+			ID:    uuid.NewString(),
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"error creating AnalysisRun %q in namespace %q: %w",
@@ -163,6 +185,7 @@ func (r *reconciler) startVerification(
 	}
 
 	return &kargoapi.VerificationInfo{
+		ID:    uuid.NewString(),
 		Phase: kargoapi.VerificationPhasePending,
 		AnalysisRun: &kargoapi.AnalysisRunReference{
 			Name:      run.Name,
@@ -177,6 +200,7 @@ func (r *reconciler) getVerificationInfo(
 ) *kargoapi.VerificationInfo {
 	if r.rolloutsClient == nil {
 		return &kargoapi.VerificationInfo{
+			ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
 			Phase: kargoapi.VerificationPhaseError,
 			Message: "Rollouts integration is disabled on this controller; cannot " +
 				"get verification info",
@@ -195,6 +219,7 @@ func (r *reconciler) getVerificationInfo(
 	)
 	if err != nil {
 		return &kargoapi.VerificationInfo{
+			ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"error getting AnalysisRun %q in namespace %q: %w",
@@ -206,6 +231,7 @@ func (r *reconciler) getVerificationInfo(
 	}
 	if analysisRun == nil {
 		return &kargoapi.VerificationInfo{
+			ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
 			Phase: kargoapi.VerificationPhaseError,
 			Message: fmt.Errorf(
 				"AnalysisRun %q in namespace %q not found",
@@ -215,6 +241,7 @@ func (r *reconciler) getVerificationInfo(
 		}
 	}
 	return &kargoapi.VerificationInfo{
+		ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
 		Phase: kargoapi.VerificationPhase(analysisRun.Status.Phase),
 		AnalysisRun: &kargoapi.AnalysisRunReference{
 			Name:      analysisRun.Name,
@@ -224,6 +251,54 @@ func (r *reconciler) getVerificationInfo(
 	}
 }
 
+func (r *reconciler) abortVerification(
+	ctx context.Context,
+	stage *kargoapi.Stage,
+) *kargoapi.VerificationInfo {
+	if r.rolloutsClient == nil {
+		return &kargoapi.VerificationInfo{
+			ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
+			Phase: kargoapi.VerificationPhaseError,
+			Message: "Rollouts integration is disabled on this controller; cannot " +
+				"abort verification",
+		}
+	}
+
+	ar := &rollouts.AnalysisRun{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      stage.Status.CurrentFreight.VerificationInfo.AnalysisRun.Name,
+			Namespace: stage.Status.CurrentFreight.VerificationInfo.AnalysisRun.Namespace,
+		},
+	}
+	if err := r.patchAnalysisRunFn(
+		ctx,
+		ar,
+		client.RawPatch(types.MergePatchType, []byte(`{"spec":{"terminate":true}}`)),
+	); err != nil {
+		return &kargoapi.VerificationInfo{
+			ID:    stage.Status.CurrentFreight.VerificationInfo.ID,
+			Phase: kargoapi.VerificationPhaseError,
+			Message: fmt.Errorf(
+				"error terminating AnalysisRun %q in namespace %q: %w",
+				ar.Name,
+				ar.Namespace,
+				err,
+			).Error(),
+		}
+	}
+
+	// Return a new VerificationInfo with the same ID and a message indicating
+	// that the verification was aborted. The Phase will be set to Failed, as
+	// the verification was not successful.
+	// We do not use the further information from the AnalysisRun, as this
+	// will indicate a "Succeeded" phase due to Argo Rollouts behavior.
+	return &kargoapi.VerificationInfo{
+		ID:      stage.Status.CurrentFreight.VerificationInfo.ID,
+		Phase:   kargoapi.VerificationPhaseAborted,
+		Message: "Verification aborted by user",
+	}
+}
+
 // getAnalysisRunNamespace determines the namespace in which to create the
 // AnalysisRun resources.
 func (r *reconciler) getAnalysisRunNamespace(stage *kargoapi.Stage) string {
diff --git a/internal/controller/warehouses/warehouses.go b/internal/controller/warehouses/warehouses.go
index d4443850..375f36c4 100644
--- a/internal/controller/warehouses/warehouses.go
+++ b/internal/controller/warehouses/warehouses.go
@@ -119,7 +119,11 @@ func SetupReconcilerWithManager(
 			),
 		).
 		WithEventFilter(shardPredicate).
-		WithEventFilter(kargo.IgnoreClearRefreshUpdates{}).
+		WithEventFilter(kargo.IgnoreAnnotationRemoval{
+			Annotations: []string{
+				kargoapi.AnnotationKeyRefresh,
+			},
+		}).
 		WithOptions(controller.CommonOptions()).
 		Complete(newReconciler(mgr.GetClient(), credentialsDB)); err != nil {
 		return fmt.Errorf("error building Warehouse reconciler: %w", err)
@@ -195,7 +199,12 @@ func (r *reconciler) Reconcile(
 	if updateErr != nil {
 		logger.Errorf("error updating Warehouse status: %s", updateErr)
 	}
-	if clearRefreshErr := kargoapi.ClearWarehouseRefresh(ctx, r.client, warehouse); clearRefreshErr != nil {
+	if clearRefreshErr := kargoapi.ClearAnnotations(
+		ctx,
+		r.client,
+		warehouse,
+		kargoapi.AnnotationKeyRefresh,
+	); clearRefreshErr != nil {
 		logger.Errorf("error clearing Warehouse refresh annotation: %s", clearRefreshErr)
 	}
 
diff --git a/internal/kargo/kargo.go b/internal/kargo/kargo.go
index b2ac52b6..64a731cd 100644
--- a/internal/kargo/kargo.go
+++ b/internal/kargo/kargo.go
@@ -114,32 +114,34 @@ func (p PromoWentTerminal) Update(e event.UpdateEvent) bool {
 	return false
 }
 
-// IgnoreClearRefreshUpdates is a predicate that filters out update events if
-// the update was only to clear the refresh annotation. This prevents the
-// extra reconciliation that happens when reconcilers respond to refresh by
-// updating the object's annotations.
-type IgnoreClearRefreshUpdates struct {
+// IgnoreAnnotationRemoval is a predicate that ignores the removal of specific
+// Annotations in an update event. This is useful when we want to ignore
+// updates that only remove an annotation and nothing else, which may be the
+// case when the annotation(s) are cleared by the controller itself.
+type IgnoreAnnotationRemoval struct {
 	predicate.Funcs
+
+	Annotations []string
 }
 
-// Update returns false if the update event cleared the refresh annotation.
-// NOTE: this predicate assumes that the update was to clear the annotation and nothing else.
-// This is safe to assume as long as the ClearXxxxRefresh helpers are always used to clear
-// the refresh annotation.
-func (i IgnoreClearRefreshUpdates) Update(e event.UpdateEvent) bool {
+// Update returns false if the update event only removed any of the Annotations,
+// true otherwise.
+//
+// NOTE: this predicate assumes that the update was to clear the annotation and
+// nothing else. This is safe to assume as long as the helpers of the API are
+// always used to clear the respective annotation.
+func (i IgnoreAnnotationRemoval) Update(e event.UpdateEvent) bool {
 	if e.ObjectOld == nil || e.ObjectNew == nil {
 		return true
 	}
-	oldHasRefreshAnnotation := false
-	if oldAnnotations := e.ObjectOld.GetAnnotations(); oldAnnotations != nil {
-		_, oldHasRefreshAnnotation = oldAnnotations[kargoapi.AnnotationKeyRefresh]
-	}
-	newHasRefreshAnnotation := false
-	if newAnnotations := e.ObjectNew.GetAnnotations(); newAnnotations != nil {
-		_, newHasRefreshAnnotation = newAnnotations[kargoapi.AnnotationKeyRefresh]
-	}
-	if oldHasRefreshAnnotation && !newHasRefreshAnnotation {
-		return false
+	oldAnnotations := e.ObjectOld.GetAnnotations()
+	newAnnotations := e.ObjectNew.GetAnnotations()
+	for _, annotation := range i.Annotations {
+		_, oldHasAnnotation := oldAnnotations[annotation]
+		_, newHasAnnotation := newAnnotations[annotation]
+		if oldHasAnnotation && !newHasAnnotation {
+			return false
+		}
 	}
 	return true
 }
diff --git a/pkg/api/service/v1alpha1/service.pb.go b/pkg/api/service/v1alpha1/service.pb.go
index bbf5cc1c..bfc0cb43 100644
--- a/pkg/api/service/v1alpha1/service.pb.go
+++ b/pkg/api/service/v1alpha1/service.pb.go
@@ -3407,6 +3407,192 @@ func (*UpdateFreightAliasResponse) Descriptor() ([]byte, []int) {
 	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{62}
 }
 
+type ReverifyRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"`
+	Stage   string `protobuf:"bytes,2,opt,name=stage,proto3" json:"stage,omitempty"`
+}
+
+func (x *ReverifyRequest) Reset() {
+	*x = ReverifyRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_service_v1alpha1_service_proto_msgTypes[63]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ReverifyRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReverifyRequest) ProtoMessage() {}
+
+func (x *ReverifyRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_service_v1alpha1_service_proto_msgTypes[63]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReverifyRequest.ProtoReflect.Descriptor instead.
+func (*ReverifyRequest) Descriptor() ([]byte, []int) {
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{63}
+}
+
+func (x *ReverifyRequest) GetProject() string {
+	if x != nil {
+		return x.Project
+	}
+	return ""
+}
+
+func (x *ReverifyRequest) GetStage() string {
+	if x != nil {
+		return x.Stage
+	}
+	return ""
+}
+
+type ReverifyResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *ReverifyResponse) Reset() {
+	*x = ReverifyResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_service_v1alpha1_service_proto_msgTypes[64]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ReverifyResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReverifyResponse) ProtoMessage() {}
+
+func (x *ReverifyResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_service_v1alpha1_service_proto_msgTypes[64]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReverifyResponse.ProtoReflect.Descriptor instead.
+func (*ReverifyResponse) Descriptor() ([]byte, []int) {
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{64}
+}
+
+type AbortVerificationRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"`
+	Stage   string `protobuf:"bytes,2,opt,name=stage,proto3" json:"stage,omitempty"`
+}
+
+func (x *AbortVerificationRequest) Reset() {
+	*x = AbortVerificationRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_service_v1alpha1_service_proto_msgTypes[65]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AbortVerificationRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AbortVerificationRequest) ProtoMessage() {}
+
+func (x *AbortVerificationRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_service_v1alpha1_service_proto_msgTypes[65]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AbortVerificationRequest.ProtoReflect.Descriptor instead.
+func (*AbortVerificationRequest) Descriptor() ([]byte, []int) {
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{65}
+}
+
+func (x *AbortVerificationRequest) GetProject() string {
+	if x != nil {
+		return x.Project
+	}
+	return ""
+}
+
+func (x *AbortVerificationRequest) GetStage() string {
+	if x != nil {
+		return x.Stage
+	}
+	return ""
+}
+
+type AbortVerificationResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *AbortVerificationResponse) Reset() {
+	*x = AbortVerificationResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_service_v1alpha1_service_proto_msgTypes[66]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AbortVerificationResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AbortVerificationResponse) ProtoMessage() {}
+
+func (x *AbortVerificationResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_service_v1alpha1_service_proto_msgTypes[66]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AbortVerificationResponse.ProtoReflect.Descriptor instead.
+func (*AbortVerificationResponse) Descriptor() ([]byte, []int) {
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{66}
+}
+
 type ListWarehousesRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -3418,7 +3604,7 @@ type ListWarehousesRequest struct {
 func (x *ListWarehousesRequest) Reset() {
 	*x = ListWarehousesRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[63]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[67]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3431,7 +3617,7 @@ func (x *ListWarehousesRequest) String() string {
 func (*ListWarehousesRequest) ProtoMessage() {}
 
 func (x *ListWarehousesRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[63]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[67]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3444,7 +3630,7 @@ func (x *ListWarehousesRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListWarehousesRequest.ProtoReflect.Descriptor instead.
 func (*ListWarehousesRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{63}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{67}
 }
 
 func (x *ListWarehousesRequest) GetProject() string {
@@ -3465,7 +3651,7 @@ type ListWarehousesResponse struct {
 func (x *ListWarehousesResponse) Reset() {
 	*x = ListWarehousesResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[64]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[68]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3478,7 +3664,7 @@ func (x *ListWarehousesResponse) String() string {
 func (*ListWarehousesResponse) ProtoMessage() {}
 
 func (x *ListWarehousesResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[64]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[68]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3491,7 +3677,7 @@ func (x *ListWarehousesResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListWarehousesResponse.ProtoReflect.Descriptor instead.
 func (*ListWarehousesResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{64}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{68}
 }
 
 func (x *ListWarehousesResponse) GetWarehouses() []*v1alpha1.Warehouse {
@@ -3513,7 +3699,7 @@ type GetWarehouseRequest struct {
 func (x *GetWarehouseRequest) Reset() {
 	*x = GetWarehouseRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[65]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[69]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3526,7 +3712,7 @@ func (x *GetWarehouseRequest) String() string {
 func (*GetWarehouseRequest) ProtoMessage() {}
 
 func (x *GetWarehouseRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[65]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[69]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3539,7 +3725,7 @@ func (x *GetWarehouseRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetWarehouseRequest.ProtoReflect.Descriptor instead.
 func (*GetWarehouseRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{65}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{69}
 }
 
 func (x *GetWarehouseRequest) GetProject() string {
@@ -3567,7 +3753,7 @@ type GetWarehouseResponse struct {
 func (x *GetWarehouseResponse) Reset() {
 	*x = GetWarehouseResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[66]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[70]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3580,7 +3766,7 @@ func (x *GetWarehouseResponse) String() string {
 func (*GetWarehouseResponse) ProtoMessage() {}
 
 func (x *GetWarehouseResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[66]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[70]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3593,7 +3779,7 @@ func (x *GetWarehouseResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetWarehouseResponse.ProtoReflect.Descriptor instead.
 func (*GetWarehouseResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{66}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{70}
 }
 
 func (x *GetWarehouseResponse) GetWarehouse() *v1alpha1.Warehouse {
@@ -3615,7 +3801,7 @@ type WatchWarehousesRequest struct {
 func (x *WatchWarehousesRequest) Reset() {
 	*x = WatchWarehousesRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[67]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[71]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3628,7 +3814,7 @@ func (x *WatchWarehousesRequest) String() string {
 func (*WatchWarehousesRequest) ProtoMessage() {}
 
 func (x *WatchWarehousesRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[67]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[71]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3641,7 +3827,7 @@ func (x *WatchWarehousesRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use WatchWarehousesRequest.ProtoReflect.Descriptor instead.
 func (*WatchWarehousesRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{67}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{71}
 }
 
 func (x *WatchWarehousesRequest) GetProject() string {
@@ -3670,7 +3856,7 @@ type WatchWarehousesResponse struct {
 func (x *WatchWarehousesResponse) Reset() {
 	*x = WatchWarehousesResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[68]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[72]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3683,7 +3869,7 @@ func (x *WatchWarehousesResponse) String() string {
 func (*WatchWarehousesResponse) ProtoMessage() {}
 
 func (x *WatchWarehousesResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[68]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[72]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3696,7 +3882,7 @@ func (x *WatchWarehousesResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use WatchWarehousesResponse.ProtoReflect.Descriptor instead.
 func (*WatchWarehousesResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{68}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{72}
 }
 
 func (x *WatchWarehousesResponse) GetWarehouse() *v1alpha1.Warehouse {
@@ -3725,7 +3911,7 @@ type DeleteWarehouseRequest struct {
 func (x *DeleteWarehouseRequest) Reset() {
 	*x = DeleteWarehouseRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[69]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[73]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3738,7 +3924,7 @@ func (x *DeleteWarehouseRequest) String() string {
 func (*DeleteWarehouseRequest) ProtoMessage() {}
 
 func (x *DeleteWarehouseRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[69]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[73]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3751,7 +3937,7 @@ func (x *DeleteWarehouseRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DeleteWarehouseRequest.ProtoReflect.Descriptor instead.
 func (*DeleteWarehouseRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{69}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{73}
 }
 
 func (x *DeleteWarehouseRequest) GetProject() string {
@@ -3777,7 +3963,7 @@ type DeleteWarehouseResponse struct {
 func (x *DeleteWarehouseResponse) Reset() {
 	*x = DeleteWarehouseResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[70]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[74]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3790,7 +3976,7 @@ func (x *DeleteWarehouseResponse) String() string {
 func (*DeleteWarehouseResponse) ProtoMessage() {}
 
 func (x *DeleteWarehouseResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[70]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[74]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3803,7 +3989,7 @@ func (x *DeleteWarehouseResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DeleteWarehouseResponse.ProtoReflect.Descriptor instead.
 func (*DeleteWarehouseResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{70}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{74}
 }
 
 type RefreshWarehouseRequest struct {
@@ -3818,7 +4004,7 @@ type RefreshWarehouseRequest struct {
 func (x *RefreshWarehouseRequest) Reset() {
 	*x = RefreshWarehouseRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[71]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[75]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3831,7 +4017,7 @@ func (x *RefreshWarehouseRequest) String() string {
 func (*RefreshWarehouseRequest) ProtoMessage() {}
 
 func (x *RefreshWarehouseRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[71]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[75]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3844,7 +4030,7 @@ func (x *RefreshWarehouseRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RefreshWarehouseRequest.ProtoReflect.Descriptor instead.
 func (*RefreshWarehouseRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{71}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{75}
 }
 
 func (x *RefreshWarehouseRequest) GetProject() string {
@@ -3872,7 +4058,7 @@ type RefreshWarehouseResponse struct {
 func (x *RefreshWarehouseResponse) Reset() {
 	*x = RefreshWarehouseResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[72]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[76]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3885,7 +4071,7 @@ func (x *RefreshWarehouseResponse) String() string {
 func (*RefreshWarehouseResponse) ProtoMessage() {}
 
 func (x *RefreshWarehouseResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[72]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[76]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3898,7 +4084,7 @@ func (x *RefreshWarehouseResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RefreshWarehouseResponse.ProtoReflect.Descriptor instead.
 func (*RefreshWarehouseResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{72}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{76}
 }
 
 func (x *RefreshWarehouseResponse) GetWarehouse() *v1alpha1.Warehouse {
@@ -3925,7 +4111,7 @@ type CreateCredentialsRequest struct {
 func (x *CreateCredentialsRequest) Reset() {
 	*x = CreateCredentialsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[73]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[77]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -3938,7 +4124,7 @@ func (x *CreateCredentialsRequest) String() string {
 func (*CreateCredentialsRequest) ProtoMessage() {}
 
 func (x *CreateCredentialsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[73]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[77]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -3951,7 +4137,7 @@ func (x *CreateCredentialsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use CreateCredentialsRequest.ProtoReflect.Descriptor instead.
 func (*CreateCredentialsRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{73}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{77}
 }
 
 func (x *CreateCredentialsRequest) GetProject() string {
@@ -4014,7 +4200,7 @@ type CreateCredentialsResponse struct {
 func (x *CreateCredentialsResponse) Reset() {
 	*x = CreateCredentialsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[74]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[78]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4027,7 +4213,7 @@ func (x *CreateCredentialsResponse) String() string {
 func (*CreateCredentialsResponse) ProtoMessage() {}
 
 func (x *CreateCredentialsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[74]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[78]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4040,7 +4226,7 @@ func (x *CreateCredentialsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use CreateCredentialsResponse.ProtoReflect.Descriptor instead.
 func (*CreateCredentialsResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{74}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{78}
 }
 
 func (x *CreateCredentialsResponse) GetCredentials() *v1.Secret {
@@ -4062,7 +4248,7 @@ type DeleteCredentialsRequest struct {
 func (x *DeleteCredentialsRequest) Reset() {
 	*x = DeleteCredentialsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[75]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[79]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4075,7 +4261,7 @@ func (x *DeleteCredentialsRequest) String() string {
 func (*DeleteCredentialsRequest) ProtoMessage() {}
 
 func (x *DeleteCredentialsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[75]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[79]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4088,7 +4274,7 @@ func (x *DeleteCredentialsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DeleteCredentialsRequest.ProtoReflect.Descriptor instead.
 func (*DeleteCredentialsRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{75}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{79}
 }
 
 func (x *DeleteCredentialsRequest) GetProject() string {
@@ -4114,7 +4300,7 @@ type DeleteCredentialsResponse struct {
 func (x *DeleteCredentialsResponse) Reset() {
 	*x = DeleteCredentialsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[76]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[80]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4127,7 +4313,7 @@ func (x *DeleteCredentialsResponse) String() string {
 func (*DeleteCredentialsResponse) ProtoMessage() {}
 
 func (x *DeleteCredentialsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[76]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[80]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4140,7 +4326,7 @@ func (x *DeleteCredentialsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DeleteCredentialsResponse.ProtoReflect.Descriptor instead.
 func (*DeleteCredentialsResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{76}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{80}
 }
 
 type GetCredentialsRequest struct {
@@ -4155,7 +4341,7 @@ type GetCredentialsRequest struct {
 func (x *GetCredentialsRequest) Reset() {
 	*x = GetCredentialsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[77]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[81]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4168,7 +4354,7 @@ func (x *GetCredentialsRequest) String() string {
 func (*GetCredentialsRequest) ProtoMessage() {}
 
 func (x *GetCredentialsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[77]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[81]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4181,7 +4367,7 @@ func (x *GetCredentialsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetCredentialsRequest.ProtoReflect.Descriptor instead.
 func (*GetCredentialsRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{77}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{81}
 }
 
 func (x *GetCredentialsRequest) GetProject() string {
@@ -4209,7 +4395,7 @@ type GetCredentialsResponse struct {
 func (x *GetCredentialsResponse) Reset() {
 	*x = GetCredentialsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[78]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[82]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4222,7 +4408,7 @@ func (x *GetCredentialsResponse) String() string {
 func (*GetCredentialsResponse) ProtoMessage() {}
 
 func (x *GetCredentialsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[78]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[82]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4235,7 +4421,7 @@ func (x *GetCredentialsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetCredentialsResponse.ProtoReflect.Descriptor instead.
 func (*GetCredentialsResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{78}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{82}
 }
 
 func (x *GetCredentialsResponse) GetCredentials() *v1.Secret {
@@ -4256,7 +4442,7 @@ type ListCredentialsRequest struct {
 func (x *ListCredentialsRequest) Reset() {
 	*x = ListCredentialsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[79]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[83]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4269,7 +4455,7 @@ func (x *ListCredentialsRequest) String() string {
 func (*ListCredentialsRequest) ProtoMessage() {}
 
 func (x *ListCredentialsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[79]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[83]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4282,7 +4468,7 @@ func (x *ListCredentialsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListCredentialsRequest.ProtoReflect.Descriptor instead.
 func (*ListCredentialsRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{79}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{83}
 }
 
 func (x *ListCredentialsRequest) GetProject() string {
@@ -4303,7 +4489,7 @@ type ListCredentialsResponse struct {
 func (x *ListCredentialsResponse) Reset() {
 	*x = ListCredentialsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[80]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[84]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4316,7 +4502,7 @@ func (x *ListCredentialsResponse) String() string {
 func (*ListCredentialsResponse) ProtoMessage() {}
 
 func (x *ListCredentialsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[80]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[84]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4329,7 +4515,7 @@ func (x *ListCredentialsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListCredentialsResponse.ProtoReflect.Descriptor instead.
 func (*ListCredentialsResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{80}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{84}
 }
 
 func (x *ListCredentialsResponse) GetCredentials() []*v1.Secret {
@@ -4356,7 +4542,7 @@ type UpdateCredentialsRequest struct {
 func (x *UpdateCredentialsRequest) Reset() {
 	*x = UpdateCredentialsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[81]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[85]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4369,7 +4555,7 @@ func (x *UpdateCredentialsRequest) String() string {
 func (*UpdateCredentialsRequest) ProtoMessage() {}
 
 func (x *UpdateCredentialsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[81]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[85]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4382,7 +4568,7 @@ func (x *UpdateCredentialsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateCredentialsRequest.ProtoReflect.Descriptor instead.
 func (*UpdateCredentialsRequest) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{81}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{85}
 }
 
 func (x *UpdateCredentialsRequest) GetProject() string {
@@ -4445,7 +4631,7 @@ type UpdateCredentialsResponse struct {
 func (x *UpdateCredentialsResponse) Reset() {
 	*x = UpdateCredentialsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_service_v1alpha1_service_proto_msgTypes[82]
+		mi := &file_service_v1alpha1_service_proto_msgTypes[86]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -4458,7 +4644,7 @@ func (x *UpdateCredentialsResponse) String() string {
 func (*UpdateCredentialsResponse) ProtoMessage() {}
 
 func (x *UpdateCredentialsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_service_v1alpha1_service_proto_msgTypes[82]
+	mi := &file_service_v1alpha1_service_proto_msgTypes[86]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4471,7 +4657,7 @@ func (x *UpdateCredentialsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateCredentialsResponse.ProtoReflect.Descriptor instead.
 func (*UpdateCredentialsResponse) Descriptor() ([]byte, []int) {
-	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{82}
+	return file_service_v1alpha1_service_proto_rawDescGZIP(), []int{86}
 }
 
 func (x *UpdateCredentialsResponse) GetCredentials() *v1.Secret {
@@ -4866,7 +5052,19 @@ var file_service_v1alpha1_service_proto_rawDesc = []byte{
 	0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 0x20,
 	0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x1c, 0x0a,
 	0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x41, 0x6c,
-	0x69, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x4c,
+	0x69, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x41, 0x0a, 0x0f, 0x52,
+	0x65, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
+	0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x12,
+	0x0a, 0x10, 0x52, 0x65, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x4a, 0x0a, 0x18, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66,
+	0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
+	0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x1b,
+	0x0a, 0x19, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x4c,
 	0x69, 0x73, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71,
 	0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18,
 	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x69,
@@ -4981,7 +5179,7 @@ var file_service_v1alpha1_service_proto_rawDesc = []byte{
 	0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6b, 0x38, 0x73,
 	0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e,
 	0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
-	0x61, 0x6c, 0x73, 0x32, 0xd5, 0x26, 0x0a, 0x0c, 0x4b, 0x61, 0x72, 0x67, 0x6f, 0x53, 0x65, 0x72,
+	0x61, 0x6c, 0x73, 0x32, 0xd7, 0x28, 0x0a, 0x0c, 0x4b, 0x61, 0x72, 0x67, 0x6f, 0x53, 0x65, 0x72,
 	0x76, 0x69, 0x63, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73,
 	0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x37, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79,
 	0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
@@ -5204,111 +5402,127 @@ var file_service_v1alpha1_service_proto_rawDesc = []byte{
 	0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73,
 	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
 	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x41, 0x6c, 0x69,
-	0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x0e, 0x4c,
-	0x69, 0x73, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x12, 0x37, 0x2e,
-	0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
-	0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e,
+	0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x08, 0x52, 0x65,
+	0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x31, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e,
 	0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-	0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61,
-	0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x7d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65,
-	0x12, 0x35, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72,
+	0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x69,
+	0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x61, 0x6b, 0x75, 0x69,
+	0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76,
+	0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01,
+	0x0a, 0x11, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
+	0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x69,
+	0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x3b, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67,
+	0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+	0x61, 0x31, 0x2e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a,
+	0x0e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x12,
+	0x37, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67,
+	0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+	0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65,
+	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74,
+	0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
+	0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
+	0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x7d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75,
+	0x73, 0x65, 0x12, 0x35, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b,
+	0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61,
+	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75,
+	0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x61, 0x6b, 0x75, 0x69,
+	0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74,
+	0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68,
+	0x6f, 0x75, 0x73, 0x65, 0x73, 0x12, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69,
+	0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61,
+	0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x39, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67,
+	0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+	0x61, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73,
+	0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a,
+	0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65,
+	0x12, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72,
 	0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
-	0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79,
+	0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f,
+	0x75, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x61, 0x6b, 0x75,
+	0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65,
+	0x6c, 0x65, 0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
+	0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x12, 0x39, 0x2e, 0x61, 0x6b, 0x75,
+	0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65,
+	0x66, 0x72, 0x65, 0x73, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69,
+	0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
+	0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x8c, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64,
+	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79,
 	0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x61,
-	0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x88, 0x01, 0x0a, 0x0f, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75,
-	0x73, 0x65, 0x73, 0x12, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
+	0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
+	0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
 	0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31,
-	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x72, 0x65,
-	0x68, 0x6f, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e,
-	0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
-	0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x73,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x0f, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x12, 0x38,
-	0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f,
-	0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
-	0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73,
-	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74,
-	0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
-	0x74, 0x65, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x57,
-	0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x12, 0x39, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74,
-	0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72,
-	0x65, 0x73, 0x68, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65,
+	0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x8c, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65,
+	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e,
+	0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+	0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
+	0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b,
+	0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61,
+	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64,
+	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x83, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
+	0x6c, 0x73, 0x12, 0x37, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b,
+	0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61,
+	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
+	0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x61, 0x6b,
+	0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47,
+	0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72,
+	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69,
+	0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73,
+	0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
 	0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31,
-	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x57, 0x61,
-	0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x8c, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
-	0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69,
-	0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
-	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43,
-	0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x3b, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61,
-	0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c,
-	0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65,
 	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c,
-	0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
+	0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
 	0x69, 0x61, 0x6c, 0x73, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f,
 	0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76,
-	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72,
+	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72,
 	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 	0x1a, 0x3b, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72,
 	0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
-	0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
-	0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01,
-	0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
-	0x12, 0x37, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72,
-	0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
-	0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
-	0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69,
-	0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74,
-	0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x64,
-	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x38, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79,
-	0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43,
-	0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x39, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61,
-	0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c,
-	0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a,
-	0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
-	0x6c, 0x73, 0x12, 0x3a, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b,
-	0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61,
-	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64,
-	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b,
-	0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61, 0x72, 0x67, 0x6f,
-	0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
-	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
-	0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x97, 0x02, 0x0a, 0x24,
-	0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e, 0x6b, 0x61,
-	0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c,
-	0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f,
-	0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2f, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2f, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2f, 0x70, 0x6b,
-	0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31,
-	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x73, 0x76, 0x63, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
-	0x61, 0x31, 0xa2, 0x02, 0x04, 0x41, 0x49, 0x4b, 0x53, 0xaa, 0x02, 0x20, 0x41, 0x6b, 0x75, 0x69,
-	0x74, 0x79, 0x2e, 0x49, 0x6f, 0x2e, 0x4b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x20, 0x41,
-	0x6b, 0x75, 0x69, 0x74, 0x79, 0x5c, 0x49, 0x6f, 0x5c, 0x4b, 0x61, 0x72, 0x67, 0x6f, 0x5c, 0x53,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2,
-	0x02, 0x2c, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x5c, 0x49, 0x6f, 0x5c, 0x4b, 0x61, 0x72, 0x67,
-	0x6f, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68,
-	0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
-	0x24, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x49, 0x6f, 0x3a, 0x3a, 0x4b, 0x61, 0x72,
-	0x67, 0x6f, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x61,
-	0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
+	0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x97, 0x02,
+	0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x6f, 0x2e,
+	0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50,
+	0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2f, 0x6b, 0x61, 0x72, 0x67, 0x6f, 0x2f,
+	0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x73, 0x76, 0x63, 0x76, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x04, 0x41, 0x49, 0x4b, 0x53, 0xaa, 0x02, 0x20, 0x41, 0x6b,
+	0x75, 0x69, 0x74, 0x79, 0x2e, 0x49, 0x6f, 0x2e, 0x4b, 0x61, 0x72, 0x67, 0x6f, 0x2e, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02,
+	0x20, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x5c, 0x49, 0x6f, 0x5c, 0x4b, 0x61, 0x72, 0x67, 0x6f,
+	0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
+	0x31, 0xe2, 0x02, 0x2c, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x5c, 0x49, 0x6f, 0x5c, 0x4b, 0x61,
+	0x72, 0x67, 0x6f, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0xea, 0x02, 0x24, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x49, 0x6f, 0x3a, 0x3a, 0x4b,
+	0x61, 0x72, 0x67, 0x6f, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x3a, 0x3a, 0x56,
+	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -5323,7 +5537,7 @@ func file_service_v1alpha1_service_proto_rawDescGZIP() []byte {
 	return file_service_v1alpha1_service_proto_rawDescData
 }
 
-var file_service_v1alpha1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 85)
+var file_service_v1alpha1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 89)
 var file_service_v1alpha1_service_proto_goTypes = []interface{}{
 	(*ComponentVersions)(nil),                 // 0: akuity.io.kargo.service.v1alpha1.ComponentVersions
 	(*VersionInfo)(nil),                       // 1: akuity.io.kargo.service.v1alpha1.VersionInfo
@@ -5388,70 +5602,74 @@ var file_service_v1alpha1_service_proto_goTypes = []interface{}{
 	(*FreightList)(nil),                       // 60: akuity.io.kargo.service.v1alpha1.FreightList
 	(*UpdateFreightAliasRequest)(nil),         // 61: akuity.io.kargo.service.v1alpha1.UpdateFreightAliasRequest
 	(*UpdateFreightAliasResponse)(nil),        // 62: akuity.io.kargo.service.v1alpha1.UpdateFreightAliasResponse
-	(*ListWarehousesRequest)(nil),             // 63: akuity.io.kargo.service.v1alpha1.ListWarehousesRequest
-	(*ListWarehousesResponse)(nil),            // 64: akuity.io.kargo.service.v1alpha1.ListWarehousesResponse
-	(*GetWarehouseRequest)(nil),               // 65: akuity.io.kargo.service.v1alpha1.GetWarehouseRequest
-	(*GetWarehouseResponse)(nil),              // 66: akuity.io.kargo.service.v1alpha1.GetWarehouseResponse
-	(*WatchWarehousesRequest)(nil),            // 67: akuity.io.kargo.service.v1alpha1.WatchWarehousesRequest
-	(*WatchWarehousesResponse)(nil),           // 68: akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse
-	(*DeleteWarehouseRequest)(nil),            // 69: akuity.io.kargo.service.v1alpha1.DeleteWarehouseRequest
-	(*DeleteWarehouseResponse)(nil),           // 70: akuity.io.kargo.service.v1alpha1.DeleteWarehouseResponse
-	(*RefreshWarehouseRequest)(nil),           // 71: akuity.io.kargo.service.v1alpha1.RefreshWarehouseRequest
-	(*RefreshWarehouseResponse)(nil),          // 72: akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse
-	(*CreateCredentialsRequest)(nil),          // 73: akuity.io.kargo.service.v1alpha1.CreateCredentialsRequest
-	(*CreateCredentialsResponse)(nil),         // 74: akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse
-	(*DeleteCredentialsRequest)(nil),          // 75: akuity.io.kargo.service.v1alpha1.DeleteCredentialsRequest
-	(*DeleteCredentialsResponse)(nil),         // 76: akuity.io.kargo.service.v1alpha1.DeleteCredentialsResponse
-	(*GetCredentialsRequest)(nil),             // 77: akuity.io.kargo.service.v1alpha1.GetCredentialsRequest
-	(*GetCredentialsResponse)(nil),            // 78: akuity.io.kargo.service.v1alpha1.GetCredentialsResponse
-	(*ListCredentialsRequest)(nil),            // 79: akuity.io.kargo.service.v1alpha1.ListCredentialsRequest
-	(*ListCredentialsResponse)(nil),           // 80: akuity.io.kargo.service.v1alpha1.ListCredentialsResponse
-	(*UpdateCredentialsRequest)(nil),          // 81: akuity.io.kargo.service.v1alpha1.UpdateCredentialsRequest
-	(*UpdateCredentialsResponse)(nil),         // 82: akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse
-	nil,                                       // 83: akuity.io.kargo.service.v1alpha1.GetConfigResponse.ArgocdShardsEntry
-	nil,                                       // 84: akuity.io.kargo.service.v1alpha1.QueryFreightResponse.GroupsEntry
-	(*timestamppb.Timestamp)(nil),             // 85: google.protobuf.Timestamp
-	(*v1alpha1.Stage)(nil),                    // 86: github.com.akuity.kargo.api.v1alpha1.Stage
-	(*v1alpha1.Promotion)(nil),                // 87: github.com.akuity.kargo.api.v1alpha1.Promotion
-	(*v1alpha1.Project)(nil),                  // 88: github.com.akuity.kargo.api.v1alpha1.Project
-	(*v1alpha1.Freight)(nil),                  // 89: github.com.akuity.kargo.api.v1alpha1.Freight
-	(*v1alpha1.Warehouse)(nil),                // 90: github.com.akuity.kargo.api.v1alpha1.Warehouse
-	(*v1.Secret)(nil),                         // 91: k8s.io.api.core.v1.Secret
+	(*ReverifyRequest)(nil),                   // 63: akuity.io.kargo.service.v1alpha1.ReverifyRequest
+	(*ReverifyResponse)(nil),                  // 64: akuity.io.kargo.service.v1alpha1.ReverifyResponse
+	(*AbortVerificationRequest)(nil),          // 65: akuity.io.kargo.service.v1alpha1.AbortVerificationRequest
+	(*AbortVerificationResponse)(nil),         // 66: akuity.io.kargo.service.v1alpha1.AbortVerificationResponse
+	(*ListWarehousesRequest)(nil),             // 67: akuity.io.kargo.service.v1alpha1.ListWarehousesRequest
+	(*ListWarehousesResponse)(nil),            // 68: akuity.io.kargo.service.v1alpha1.ListWarehousesResponse
+	(*GetWarehouseRequest)(nil),               // 69: akuity.io.kargo.service.v1alpha1.GetWarehouseRequest
+	(*GetWarehouseResponse)(nil),              // 70: akuity.io.kargo.service.v1alpha1.GetWarehouseResponse
+	(*WatchWarehousesRequest)(nil),            // 71: akuity.io.kargo.service.v1alpha1.WatchWarehousesRequest
+	(*WatchWarehousesResponse)(nil),           // 72: akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse
+	(*DeleteWarehouseRequest)(nil),            // 73: akuity.io.kargo.service.v1alpha1.DeleteWarehouseRequest
+	(*DeleteWarehouseResponse)(nil),           // 74: akuity.io.kargo.service.v1alpha1.DeleteWarehouseResponse
+	(*RefreshWarehouseRequest)(nil),           // 75: akuity.io.kargo.service.v1alpha1.RefreshWarehouseRequest
+	(*RefreshWarehouseResponse)(nil),          // 76: akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse
+	(*CreateCredentialsRequest)(nil),          // 77: akuity.io.kargo.service.v1alpha1.CreateCredentialsRequest
+	(*CreateCredentialsResponse)(nil),         // 78: akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse
+	(*DeleteCredentialsRequest)(nil),          // 79: akuity.io.kargo.service.v1alpha1.DeleteCredentialsRequest
+	(*DeleteCredentialsResponse)(nil),         // 80: akuity.io.kargo.service.v1alpha1.DeleteCredentialsResponse
+	(*GetCredentialsRequest)(nil),             // 81: akuity.io.kargo.service.v1alpha1.GetCredentialsRequest
+	(*GetCredentialsResponse)(nil),            // 82: akuity.io.kargo.service.v1alpha1.GetCredentialsResponse
+	(*ListCredentialsRequest)(nil),            // 83: akuity.io.kargo.service.v1alpha1.ListCredentialsRequest
+	(*ListCredentialsResponse)(nil),           // 84: akuity.io.kargo.service.v1alpha1.ListCredentialsResponse
+	(*UpdateCredentialsRequest)(nil),          // 85: akuity.io.kargo.service.v1alpha1.UpdateCredentialsRequest
+	(*UpdateCredentialsResponse)(nil),         // 86: akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse
+	nil,                                       // 87: akuity.io.kargo.service.v1alpha1.GetConfigResponse.ArgocdShardsEntry
+	nil,                                       // 88: akuity.io.kargo.service.v1alpha1.QueryFreightResponse.GroupsEntry
+	(*timestamppb.Timestamp)(nil),             // 89: google.protobuf.Timestamp
+	(*v1alpha1.Stage)(nil),                    // 90: github.com.akuity.kargo.api.v1alpha1.Stage
+	(*v1alpha1.Promotion)(nil),                // 91: github.com.akuity.kargo.api.v1alpha1.Promotion
+	(*v1alpha1.Project)(nil),                  // 92: github.com.akuity.kargo.api.v1alpha1.Project
+	(*v1alpha1.Freight)(nil),                  // 93: github.com.akuity.kargo.api.v1alpha1.Freight
+	(*v1alpha1.Warehouse)(nil),                // 94: github.com.akuity.kargo.api.v1alpha1.Warehouse
+	(*v1.Secret)(nil),                         // 95: k8s.io.api.core.v1.Secret
 }
 var file_service_v1alpha1_service_proto_depIdxs = []int32{
 	1,  // 0: akuity.io.kargo.service.v1alpha1.ComponentVersions.server:type_name -> akuity.io.kargo.service.v1alpha1.VersionInfo
 	1,  // 1: akuity.io.kargo.service.v1alpha1.ComponentVersions.cli:type_name -> akuity.io.kargo.service.v1alpha1.VersionInfo
-	85, // 2: akuity.io.kargo.service.v1alpha1.VersionInfo.build_time:type_name -> google.protobuf.Timestamp
+	89, // 2: akuity.io.kargo.service.v1alpha1.VersionInfo.build_time:type_name -> google.protobuf.Timestamp
 	1,  // 3: akuity.io.kargo.service.v1alpha1.GetVersionInfoResponse.version_info:type_name -> akuity.io.kargo.service.v1alpha1.VersionInfo
-	83, // 4: akuity.io.kargo.service.v1alpha1.GetConfigResponse.argocd_shards:type_name -> akuity.io.kargo.service.v1alpha1.GetConfigResponse.ArgocdShardsEntry
+	87, // 4: akuity.io.kargo.service.v1alpha1.GetConfigResponse.argocd_shards:type_name -> akuity.io.kargo.service.v1alpha1.GetConfigResponse.ArgocdShardsEntry
 	9,  // 5: akuity.io.kargo.service.v1alpha1.GetPublicConfigResponse.oidc_config:type_name -> akuity.io.kargo.service.v1alpha1.OIDCConfig
 	13, // 6: akuity.io.kargo.service.v1alpha1.CreateResourceResponse.results:type_name -> akuity.io.kargo.service.v1alpha1.CreateResourceResult
 	16, // 7: akuity.io.kargo.service.v1alpha1.CreateOrUpdateResourceResponse.results:type_name -> akuity.io.kargo.service.v1alpha1.CreateOrUpdateResourceResult
 	19, // 8: akuity.io.kargo.service.v1alpha1.UpdateResourceResponse.results:type_name -> akuity.io.kargo.service.v1alpha1.UpdateResourceResult
 	22, // 9: akuity.io.kargo.service.v1alpha1.DeleteResourceResponse.results:type_name -> akuity.io.kargo.service.v1alpha1.DeleteResourceResult
-	86, // 10: akuity.io.kargo.service.v1alpha1.ListStagesResponse.stages:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
-	86, // 11: akuity.io.kargo.service.v1alpha1.GetStageResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
-	86, // 12: akuity.io.kargo.service.v1alpha1.WatchStagesResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
-	86, // 13: akuity.io.kargo.service.v1alpha1.RefreshStageResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
-	87, // 14: akuity.io.kargo.service.v1alpha1.ListPromotionsResponse.promotions:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	87, // 15: akuity.io.kargo.service.v1alpha1.WatchPromotionsResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	87, // 16: akuity.io.kargo.service.v1alpha1.GetPromotionResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	87, // 17: akuity.io.kargo.service.v1alpha1.WatchPromotionResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	88, // 18: akuity.io.kargo.service.v1alpha1.GetProjectResponse.project:type_name -> github.com.akuity.kargo.api.v1alpha1.Project
-	88, // 19: akuity.io.kargo.service.v1alpha1.ListProjectsResponse.projects:type_name -> github.com.akuity.kargo.api.v1alpha1.Project
-	89, // 20: akuity.io.kargo.service.v1alpha1.GetFreightResponse.freight:type_name -> github.com.akuity.kargo.api.v1alpha1.Freight
-	87, // 21: akuity.io.kargo.service.v1alpha1.PromoteToStageResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	87, // 22: akuity.io.kargo.service.v1alpha1.PromoteToStageSubscribersResponse.promotions:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
-	84, // 23: akuity.io.kargo.service.v1alpha1.QueryFreightResponse.groups:type_name -> akuity.io.kargo.service.v1alpha1.QueryFreightResponse.GroupsEntry
-	89, // 24: akuity.io.kargo.service.v1alpha1.FreightList.freight:type_name -> github.com.akuity.kargo.api.v1alpha1.Freight
-	90, // 25: akuity.io.kargo.service.v1alpha1.ListWarehousesResponse.warehouses:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
-	90, // 26: akuity.io.kargo.service.v1alpha1.GetWarehouseResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
-	90, // 27: akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
-	90, // 28: akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
-	91, // 29: akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
-	91, // 30: akuity.io.kargo.service.v1alpha1.GetCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
-	91, // 31: akuity.io.kargo.service.v1alpha1.ListCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
-	91, // 32: akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
+	90, // 10: akuity.io.kargo.service.v1alpha1.ListStagesResponse.stages:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
+	90, // 11: akuity.io.kargo.service.v1alpha1.GetStageResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
+	90, // 12: akuity.io.kargo.service.v1alpha1.WatchStagesResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
+	90, // 13: akuity.io.kargo.service.v1alpha1.RefreshStageResponse.stage:type_name -> github.com.akuity.kargo.api.v1alpha1.Stage
+	91, // 14: akuity.io.kargo.service.v1alpha1.ListPromotionsResponse.promotions:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	91, // 15: akuity.io.kargo.service.v1alpha1.WatchPromotionsResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	91, // 16: akuity.io.kargo.service.v1alpha1.GetPromotionResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	91, // 17: akuity.io.kargo.service.v1alpha1.WatchPromotionResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	92, // 18: akuity.io.kargo.service.v1alpha1.GetProjectResponse.project:type_name -> github.com.akuity.kargo.api.v1alpha1.Project
+	92, // 19: akuity.io.kargo.service.v1alpha1.ListProjectsResponse.projects:type_name -> github.com.akuity.kargo.api.v1alpha1.Project
+	93, // 20: akuity.io.kargo.service.v1alpha1.GetFreightResponse.freight:type_name -> github.com.akuity.kargo.api.v1alpha1.Freight
+	91, // 21: akuity.io.kargo.service.v1alpha1.PromoteToStageResponse.promotion:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	91, // 22: akuity.io.kargo.service.v1alpha1.PromoteToStageSubscribersResponse.promotions:type_name -> github.com.akuity.kargo.api.v1alpha1.Promotion
+	88, // 23: akuity.io.kargo.service.v1alpha1.QueryFreightResponse.groups:type_name -> akuity.io.kargo.service.v1alpha1.QueryFreightResponse.GroupsEntry
+	93, // 24: akuity.io.kargo.service.v1alpha1.FreightList.freight:type_name -> github.com.akuity.kargo.api.v1alpha1.Freight
+	94, // 25: akuity.io.kargo.service.v1alpha1.ListWarehousesResponse.warehouses:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
+	94, // 26: akuity.io.kargo.service.v1alpha1.GetWarehouseResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
+	94, // 27: akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
+	94, // 28: akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse.warehouse:type_name -> github.com.akuity.kargo.api.v1alpha1.Warehouse
+	95, // 29: akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
+	95, // 30: akuity.io.kargo.service.v1alpha1.GetCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
+	95, // 31: akuity.io.kargo.service.v1alpha1.ListCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
+	95, // 32: akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse.credentials:type_name -> k8s.io.api.core.v1.Secret
 	5,  // 33: akuity.io.kargo.service.v1alpha1.GetConfigResponse.ArgocdShardsEntry.value:type_name -> akuity.io.kargo.service.v1alpha1.ArgoCDShard
 	60, // 34: akuity.io.kargo.service.v1alpha1.QueryFreightResponse.GroupsEntry.value:type_name -> akuity.io.kargo.service.v1alpha1.FreightList
 	2,  // 35: akuity.io.kargo.service.v1alpha1.KargoService.GetVersionInfo:input_type -> akuity.io.kargo.service.v1alpha1.GetVersionInfoRequest
@@ -5481,55 +5699,59 @@ var file_service_v1alpha1_service_proto_depIdxs = []int32{
 	56, // 59: akuity.io.kargo.service.v1alpha1.KargoService.PromoteToStageSubscribers:input_type -> akuity.io.kargo.service.v1alpha1.PromoteToStageSubscribersRequest
 	58, // 60: akuity.io.kargo.service.v1alpha1.KargoService.QueryFreight:input_type -> akuity.io.kargo.service.v1alpha1.QueryFreightRequest
 	61, // 61: akuity.io.kargo.service.v1alpha1.KargoService.UpdateFreightAlias:input_type -> akuity.io.kargo.service.v1alpha1.UpdateFreightAliasRequest
-	63, // 62: akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses:input_type -> akuity.io.kargo.service.v1alpha1.ListWarehousesRequest
-	65, // 63: akuity.io.kargo.service.v1alpha1.KargoService.GetWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.GetWarehouseRequest
-	67, // 64: akuity.io.kargo.service.v1alpha1.KargoService.WatchWarehouses:input_type -> akuity.io.kargo.service.v1alpha1.WatchWarehousesRequest
-	69, // 65: akuity.io.kargo.service.v1alpha1.KargoService.DeleteWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.DeleteWarehouseRequest
-	71, // 66: akuity.io.kargo.service.v1alpha1.KargoService.RefreshWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.RefreshWarehouseRequest
-	73, // 67: akuity.io.kargo.service.v1alpha1.KargoService.CreateCredentials:input_type -> akuity.io.kargo.service.v1alpha1.CreateCredentialsRequest
-	75, // 68: akuity.io.kargo.service.v1alpha1.KargoService.DeleteCredentials:input_type -> akuity.io.kargo.service.v1alpha1.DeleteCredentialsRequest
-	77, // 69: akuity.io.kargo.service.v1alpha1.KargoService.GetCredentials:input_type -> akuity.io.kargo.service.v1alpha1.GetCredentialsRequest
-	79, // 70: akuity.io.kargo.service.v1alpha1.KargoService.ListCredentials:input_type -> akuity.io.kargo.service.v1alpha1.ListCredentialsRequest
-	81, // 71: akuity.io.kargo.service.v1alpha1.KargoService.UpdateCredentials:input_type -> akuity.io.kargo.service.v1alpha1.UpdateCredentialsRequest
-	3,  // 72: akuity.io.kargo.service.v1alpha1.KargoService.GetVersionInfo:output_type -> akuity.io.kargo.service.v1alpha1.GetVersionInfoResponse
-	6,  // 73: akuity.io.kargo.service.v1alpha1.KargoService.GetConfig:output_type -> akuity.io.kargo.service.v1alpha1.GetConfigResponse
-	8,  // 74: akuity.io.kargo.service.v1alpha1.KargoService.GetPublicConfig:output_type -> akuity.io.kargo.service.v1alpha1.GetPublicConfigResponse
-	11, // 75: akuity.io.kargo.service.v1alpha1.KargoService.AdminLogin:output_type -> akuity.io.kargo.service.v1alpha1.AdminLoginResponse
-	14, // 76: akuity.io.kargo.service.v1alpha1.KargoService.CreateResource:output_type -> akuity.io.kargo.service.v1alpha1.CreateResourceResponse
-	17, // 77: akuity.io.kargo.service.v1alpha1.KargoService.CreateOrUpdateResource:output_type -> akuity.io.kargo.service.v1alpha1.CreateOrUpdateResourceResponse
-	20, // 78: akuity.io.kargo.service.v1alpha1.KargoService.UpdateResource:output_type -> akuity.io.kargo.service.v1alpha1.UpdateResourceResponse
-	23, // 79: akuity.io.kargo.service.v1alpha1.KargoService.DeleteResource:output_type -> akuity.io.kargo.service.v1alpha1.DeleteResourceResponse
-	25, // 80: akuity.io.kargo.service.v1alpha1.KargoService.ListStages:output_type -> akuity.io.kargo.service.v1alpha1.ListStagesResponse
-	27, // 81: akuity.io.kargo.service.v1alpha1.KargoService.GetStage:output_type -> akuity.io.kargo.service.v1alpha1.GetStageResponse
-	29, // 82: akuity.io.kargo.service.v1alpha1.KargoService.WatchStages:output_type -> akuity.io.kargo.service.v1alpha1.WatchStagesResponse
-	31, // 83: akuity.io.kargo.service.v1alpha1.KargoService.DeleteStage:output_type -> akuity.io.kargo.service.v1alpha1.DeleteStageResponse
-	33, // 84: akuity.io.kargo.service.v1alpha1.KargoService.RefreshStage:output_type -> akuity.io.kargo.service.v1alpha1.RefreshStageResponse
-	35, // 85: akuity.io.kargo.service.v1alpha1.KargoService.ListPromotions:output_type -> akuity.io.kargo.service.v1alpha1.ListPromotionsResponse
-	37, // 86: akuity.io.kargo.service.v1alpha1.KargoService.WatchPromotions:output_type -> akuity.io.kargo.service.v1alpha1.WatchPromotionsResponse
-	39, // 87: akuity.io.kargo.service.v1alpha1.KargoService.GetPromotion:output_type -> akuity.io.kargo.service.v1alpha1.GetPromotionResponse
-	41, // 88: akuity.io.kargo.service.v1alpha1.KargoService.WatchPromotion:output_type -> akuity.io.kargo.service.v1alpha1.WatchPromotionResponse
-	43, // 89: akuity.io.kargo.service.v1alpha1.KargoService.DeleteProject:output_type -> akuity.io.kargo.service.v1alpha1.DeleteProjectResponse
-	45, // 90: akuity.io.kargo.service.v1alpha1.KargoService.GetProject:output_type -> akuity.io.kargo.service.v1alpha1.GetProjectResponse
-	47, // 91: akuity.io.kargo.service.v1alpha1.KargoService.ListProjects:output_type -> akuity.io.kargo.service.v1alpha1.ListProjectsResponse
-	49, // 92: akuity.io.kargo.service.v1alpha1.KargoService.ApproveFreight:output_type -> akuity.io.kargo.service.v1alpha1.ApproveFreightResponse
-	51, // 93: akuity.io.kargo.service.v1alpha1.KargoService.DeleteFreight:output_type -> akuity.io.kargo.service.v1alpha1.DeleteFreightResponse
-	53, // 94: akuity.io.kargo.service.v1alpha1.KargoService.GetFreight:output_type -> akuity.io.kargo.service.v1alpha1.GetFreightResponse
-	55, // 95: akuity.io.kargo.service.v1alpha1.KargoService.PromoteToStage:output_type -> akuity.io.kargo.service.v1alpha1.PromoteToStageResponse
-	57, // 96: akuity.io.kargo.service.v1alpha1.KargoService.PromoteToStageSubscribers:output_type -> akuity.io.kargo.service.v1alpha1.PromoteToStageSubscribersResponse
-	59, // 97: akuity.io.kargo.service.v1alpha1.KargoService.QueryFreight:output_type -> akuity.io.kargo.service.v1alpha1.QueryFreightResponse
-	62, // 98: akuity.io.kargo.service.v1alpha1.KargoService.UpdateFreightAlias:output_type -> akuity.io.kargo.service.v1alpha1.UpdateFreightAliasResponse
-	64, // 99: akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses:output_type -> akuity.io.kargo.service.v1alpha1.ListWarehousesResponse
-	66, // 100: akuity.io.kargo.service.v1alpha1.KargoService.GetWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.GetWarehouseResponse
-	68, // 101: akuity.io.kargo.service.v1alpha1.KargoService.WatchWarehouses:output_type -> akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse
-	70, // 102: akuity.io.kargo.service.v1alpha1.KargoService.DeleteWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.DeleteWarehouseResponse
-	72, // 103: akuity.io.kargo.service.v1alpha1.KargoService.RefreshWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse
-	74, // 104: akuity.io.kargo.service.v1alpha1.KargoService.CreateCredentials:output_type -> akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse
-	76, // 105: akuity.io.kargo.service.v1alpha1.KargoService.DeleteCredentials:output_type -> akuity.io.kargo.service.v1alpha1.DeleteCredentialsResponse
-	78, // 106: akuity.io.kargo.service.v1alpha1.KargoService.GetCredentials:output_type -> akuity.io.kargo.service.v1alpha1.GetCredentialsResponse
-	80, // 107: akuity.io.kargo.service.v1alpha1.KargoService.ListCredentials:output_type -> akuity.io.kargo.service.v1alpha1.ListCredentialsResponse
-	82, // 108: akuity.io.kargo.service.v1alpha1.KargoService.UpdateCredentials:output_type -> akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse
-	72, // [72:109] is the sub-list for method output_type
-	35, // [35:72] is the sub-list for method input_type
+	63, // 62: akuity.io.kargo.service.v1alpha1.KargoService.Reverify:input_type -> akuity.io.kargo.service.v1alpha1.ReverifyRequest
+	65, // 63: akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification:input_type -> akuity.io.kargo.service.v1alpha1.AbortVerificationRequest
+	67, // 64: akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses:input_type -> akuity.io.kargo.service.v1alpha1.ListWarehousesRequest
+	69, // 65: akuity.io.kargo.service.v1alpha1.KargoService.GetWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.GetWarehouseRequest
+	71, // 66: akuity.io.kargo.service.v1alpha1.KargoService.WatchWarehouses:input_type -> akuity.io.kargo.service.v1alpha1.WatchWarehousesRequest
+	73, // 67: akuity.io.kargo.service.v1alpha1.KargoService.DeleteWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.DeleteWarehouseRequest
+	75, // 68: akuity.io.kargo.service.v1alpha1.KargoService.RefreshWarehouse:input_type -> akuity.io.kargo.service.v1alpha1.RefreshWarehouseRequest
+	77, // 69: akuity.io.kargo.service.v1alpha1.KargoService.CreateCredentials:input_type -> akuity.io.kargo.service.v1alpha1.CreateCredentialsRequest
+	79, // 70: akuity.io.kargo.service.v1alpha1.KargoService.DeleteCredentials:input_type -> akuity.io.kargo.service.v1alpha1.DeleteCredentialsRequest
+	81, // 71: akuity.io.kargo.service.v1alpha1.KargoService.GetCredentials:input_type -> akuity.io.kargo.service.v1alpha1.GetCredentialsRequest
+	83, // 72: akuity.io.kargo.service.v1alpha1.KargoService.ListCredentials:input_type -> akuity.io.kargo.service.v1alpha1.ListCredentialsRequest
+	85, // 73: akuity.io.kargo.service.v1alpha1.KargoService.UpdateCredentials:input_type -> akuity.io.kargo.service.v1alpha1.UpdateCredentialsRequest
+	3,  // 74: akuity.io.kargo.service.v1alpha1.KargoService.GetVersionInfo:output_type -> akuity.io.kargo.service.v1alpha1.GetVersionInfoResponse
+	6,  // 75: akuity.io.kargo.service.v1alpha1.KargoService.GetConfig:output_type -> akuity.io.kargo.service.v1alpha1.GetConfigResponse
+	8,  // 76: akuity.io.kargo.service.v1alpha1.KargoService.GetPublicConfig:output_type -> akuity.io.kargo.service.v1alpha1.GetPublicConfigResponse
+	11, // 77: akuity.io.kargo.service.v1alpha1.KargoService.AdminLogin:output_type -> akuity.io.kargo.service.v1alpha1.AdminLoginResponse
+	14, // 78: akuity.io.kargo.service.v1alpha1.KargoService.CreateResource:output_type -> akuity.io.kargo.service.v1alpha1.CreateResourceResponse
+	17, // 79: akuity.io.kargo.service.v1alpha1.KargoService.CreateOrUpdateResource:output_type -> akuity.io.kargo.service.v1alpha1.CreateOrUpdateResourceResponse
+	20, // 80: akuity.io.kargo.service.v1alpha1.KargoService.UpdateResource:output_type -> akuity.io.kargo.service.v1alpha1.UpdateResourceResponse
+	23, // 81: akuity.io.kargo.service.v1alpha1.KargoService.DeleteResource:output_type -> akuity.io.kargo.service.v1alpha1.DeleteResourceResponse
+	25, // 82: akuity.io.kargo.service.v1alpha1.KargoService.ListStages:output_type -> akuity.io.kargo.service.v1alpha1.ListStagesResponse
+	27, // 83: akuity.io.kargo.service.v1alpha1.KargoService.GetStage:output_type -> akuity.io.kargo.service.v1alpha1.GetStageResponse
+	29, // 84: akuity.io.kargo.service.v1alpha1.KargoService.WatchStages:output_type -> akuity.io.kargo.service.v1alpha1.WatchStagesResponse
+	31, // 85: akuity.io.kargo.service.v1alpha1.KargoService.DeleteStage:output_type -> akuity.io.kargo.service.v1alpha1.DeleteStageResponse
+	33, // 86: akuity.io.kargo.service.v1alpha1.KargoService.RefreshStage:output_type -> akuity.io.kargo.service.v1alpha1.RefreshStageResponse
+	35, // 87: akuity.io.kargo.service.v1alpha1.KargoService.ListPromotions:output_type -> akuity.io.kargo.service.v1alpha1.ListPromotionsResponse
+	37, // 88: akuity.io.kargo.service.v1alpha1.KargoService.WatchPromotions:output_type -> akuity.io.kargo.service.v1alpha1.WatchPromotionsResponse
+	39, // 89: akuity.io.kargo.service.v1alpha1.KargoService.GetPromotion:output_type -> akuity.io.kargo.service.v1alpha1.GetPromotionResponse
+	41, // 90: akuity.io.kargo.service.v1alpha1.KargoService.WatchPromotion:output_type -> akuity.io.kargo.service.v1alpha1.WatchPromotionResponse
+	43, // 91: akuity.io.kargo.service.v1alpha1.KargoService.DeleteProject:output_type -> akuity.io.kargo.service.v1alpha1.DeleteProjectResponse
+	45, // 92: akuity.io.kargo.service.v1alpha1.KargoService.GetProject:output_type -> akuity.io.kargo.service.v1alpha1.GetProjectResponse
+	47, // 93: akuity.io.kargo.service.v1alpha1.KargoService.ListProjects:output_type -> akuity.io.kargo.service.v1alpha1.ListProjectsResponse
+	49, // 94: akuity.io.kargo.service.v1alpha1.KargoService.ApproveFreight:output_type -> akuity.io.kargo.service.v1alpha1.ApproveFreightResponse
+	51, // 95: akuity.io.kargo.service.v1alpha1.KargoService.DeleteFreight:output_type -> akuity.io.kargo.service.v1alpha1.DeleteFreightResponse
+	53, // 96: akuity.io.kargo.service.v1alpha1.KargoService.GetFreight:output_type -> akuity.io.kargo.service.v1alpha1.GetFreightResponse
+	55, // 97: akuity.io.kargo.service.v1alpha1.KargoService.PromoteToStage:output_type -> akuity.io.kargo.service.v1alpha1.PromoteToStageResponse
+	57, // 98: akuity.io.kargo.service.v1alpha1.KargoService.PromoteToStageSubscribers:output_type -> akuity.io.kargo.service.v1alpha1.PromoteToStageSubscribersResponse
+	59, // 99: akuity.io.kargo.service.v1alpha1.KargoService.QueryFreight:output_type -> akuity.io.kargo.service.v1alpha1.QueryFreightResponse
+	62, // 100: akuity.io.kargo.service.v1alpha1.KargoService.UpdateFreightAlias:output_type -> akuity.io.kargo.service.v1alpha1.UpdateFreightAliasResponse
+	64, // 101: akuity.io.kargo.service.v1alpha1.KargoService.Reverify:output_type -> akuity.io.kargo.service.v1alpha1.ReverifyResponse
+	66, // 102: akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification:output_type -> akuity.io.kargo.service.v1alpha1.AbortVerificationResponse
+	68, // 103: akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses:output_type -> akuity.io.kargo.service.v1alpha1.ListWarehousesResponse
+	70, // 104: akuity.io.kargo.service.v1alpha1.KargoService.GetWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.GetWarehouseResponse
+	72, // 105: akuity.io.kargo.service.v1alpha1.KargoService.WatchWarehouses:output_type -> akuity.io.kargo.service.v1alpha1.WatchWarehousesResponse
+	74, // 106: akuity.io.kargo.service.v1alpha1.KargoService.DeleteWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.DeleteWarehouseResponse
+	76, // 107: akuity.io.kargo.service.v1alpha1.KargoService.RefreshWarehouse:output_type -> akuity.io.kargo.service.v1alpha1.RefreshWarehouseResponse
+	78, // 108: akuity.io.kargo.service.v1alpha1.KargoService.CreateCredentials:output_type -> akuity.io.kargo.service.v1alpha1.CreateCredentialsResponse
+	80, // 109: akuity.io.kargo.service.v1alpha1.KargoService.DeleteCredentials:output_type -> akuity.io.kargo.service.v1alpha1.DeleteCredentialsResponse
+	82, // 110: akuity.io.kargo.service.v1alpha1.KargoService.GetCredentials:output_type -> akuity.io.kargo.service.v1alpha1.GetCredentialsResponse
+	84, // 111: akuity.io.kargo.service.v1alpha1.KargoService.ListCredentials:output_type -> akuity.io.kargo.service.v1alpha1.ListCredentialsResponse
+	86, // 112: akuity.io.kargo.service.v1alpha1.KargoService.UpdateCredentials:output_type -> akuity.io.kargo.service.v1alpha1.UpdateCredentialsResponse
+	74, // [74:113] is the sub-list for method output_type
+	35, // [35:74] is the sub-list for method input_type
 	35, // [35:35] is the sub-list for extension type_name
 	35, // [35:35] is the sub-list for extension extendee
 	0,  // [0:35] is the sub-list for field type_name
@@ -6298,7 +6520,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListWarehousesRequest); i {
+			switch v := v.(*ReverifyRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6310,7 +6532,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListWarehousesResponse); i {
+			switch v := v.(*ReverifyResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6322,7 +6544,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetWarehouseRequest); i {
+			switch v := v.(*AbortVerificationRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6334,7 +6556,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetWarehouseResponse); i {
+			switch v := v.(*AbortVerificationResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6346,7 +6568,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WatchWarehousesRequest); i {
+			switch v := v.(*ListWarehousesRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6358,7 +6580,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WatchWarehousesResponse); i {
+			switch v := v.(*ListWarehousesResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6370,7 +6592,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeleteWarehouseRequest); i {
+			switch v := v.(*GetWarehouseRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6382,7 +6604,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeleteWarehouseResponse); i {
+			switch v := v.(*GetWarehouseResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6394,7 +6616,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*RefreshWarehouseRequest); i {
+			switch v := v.(*WatchWarehousesRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6406,7 +6628,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*RefreshWarehouseResponse); i {
+			switch v := v.(*WatchWarehousesResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6418,7 +6640,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreateCredentialsRequest); i {
+			switch v := v.(*DeleteWarehouseRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6430,7 +6652,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreateCredentialsResponse); i {
+			switch v := v.(*DeleteWarehouseResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6442,7 +6664,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeleteCredentialsRequest); i {
+			switch v := v.(*RefreshWarehouseRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6454,7 +6676,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeleteCredentialsResponse); i {
+			switch v := v.(*RefreshWarehouseResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6466,7 +6688,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetCredentialsRequest); i {
+			switch v := v.(*CreateCredentialsRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6478,7 +6700,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetCredentialsResponse); i {
+			switch v := v.(*CreateCredentialsResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6490,7 +6712,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListCredentialsRequest); i {
+			switch v := v.(*DeleteCredentialsRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6502,7 +6724,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListCredentialsResponse); i {
+			switch v := v.(*DeleteCredentialsResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6514,7 +6736,7 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*UpdateCredentialsRequest); i {
+			switch v := v.(*GetCredentialsRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -6526,6 +6748,54 @@ func file_service_v1alpha1_service_proto_init() {
 			}
 		}
 		file_service_v1alpha1_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetCredentialsResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_service_v1alpha1_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ListCredentialsRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_service_v1alpha1_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ListCredentialsResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_service_v1alpha1_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateCredentialsRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_service_v1alpha1_service_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*UpdateCredentialsResponse); i {
 			case 0:
 				return &v.state
@@ -6564,7 +6834,7 @@ func file_service_v1alpha1_service_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_service_v1alpha1_service_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   85,
+			NumMessages:   89,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/pkg/api/service/v1alpha1/svcv1alpha1connect/service.connect.go b/pkg/api/service/v1alpha1/svcv1alpha1connect/service.connect.go
index e0e48b29..ee46b31f 100644
--- a/pkg/api/service/v1alpha1/svcv1alpha1connect/service.connect.go
+++ b/pkg/api/service/v1alpha1/svcv1alpha1connect/service.connect.go
@@ -108,6 +108,11 @@ const (
 	// KargoServiceUpdateFreightAliasProcedure is the fully-qualified name of the KargoService's
 	// UpdateFreightAlias RPC.
 	KargoServiceUpdateFreightAliasProcedure = "/akuity.io.kargo.service.v1alpha1.KargoService/UpdateFreightAlias"
+	// KargoServiceReverifyProcedure is the fully-qualified name of the KargoService's Reverify RPC.
+	KargoServiceReverifyProcedure = "/akuity.io.kargo.service.v1alpha1.KargoService/Reverify"
+	// KargoServiceAbortVerificationProcedure is the fully-qualified name of the KargoService's
+	// AbortVerification RPC.
+	KargoServiceAbortVerificationProcedure = "/akuity.io.kargo.service.v1alpha1.KargoService/AbortVerification"
 	// KargoServiceListWarehousesProcedure is the fully-qualified name of the KargoService's
 	// ListWarehouses RPC.
 	KargoServiceListWarehousesProcedure = "/akuity.io.kargo.service.v1alpha1.KargoService/ListWarehouses"
@@ -172,6 +177,8 @@ type KargoServiceClient interface {
 	PromoteToStageSubscribers(context.Context, *connect.Request[v1alpha1.PromoteToStageSubscribersRequest]) (*connect.Response[v1alpha1.PromoteToStageSubscribersResponse], error)
 	QueryFreight(context.Context, *connect.Request[v1alpha1.QueryFreightRequest]) (*connect.Response[v1alpha1.QueryFreightResponse], error)
 	UpdateFreightAlias(context.Context, *connect.Request[v1alpha1.UpdateFreightAliasRequest]) (*connect.Response[v1alpha1.UpdateFreightAliasResponse], error)
+	Reverify(context.Context, *connect.Request[v1alpha1.ReverifyRequest]) (*connect.Response[v1alpha1.ReverifyResponse], error)
+	AbortVerification(context.Context, *connect.Request[v1alpha1.AbortVerificationRequest]) (*connect.Response[v1alpha1.AbortVerificationResponse], error)
 	ListWarehouses(context.Context, *connect.Request[v1alpha1.ListWarehousesRequest]) (*connect.Response[v1alpha1.ListWarehousesResponse], error)
 	GetWarehouse(context.Context, *connect.Request[v1alpha1.GetWarehouseRequest]) (*connect.Response[v1alpha1.GetWarehouseResponse], error)
 	WatchWarehouses(context.Context, *connect.Request[v1alpha1.WatchWarehousesRequest]) (*connect.ServerStreamForClient[v1alpha1.WatchWarehousesResponse], error)
@@ -330,6 +337,16 @@ func NewKargoServiceClient(httpClient connect.HTTPClient, baseURL string, opts .
 			baseURL+KargoServiceUpdateFreightAliasProcedure,
 			opts...,
 		),
+		reverify: connect.NewClient[v1alpha1.ReverifyRequest, v1alpha1.ReverifyResponse](
+			httpClient,
+			baseURL+KargoServiceReverifyProcedure,
+			opts...,
+		),
+		abortVerification: connect.NewClient[v1alpha1.AbortVerificationRequest, v1alpha1.AbortVerificationResponse](
+			httpClient,
+			baseURL+KargoServiceAbortVerificationProcedure,
+			opts...,
+		),
 		listWarehouses: connect.NewClient[v1alpha1.ListWarehousesRequest, v1alpha1.ListWarehousesResponse](
 			httpClient,
 			baseURL+KargoServiceListWarehousesProcedure,
@@ -412,6 +429,8 @@ type kargoServiceClient struct {
 	promoteToStageSubscribers *connect.Client[v1alpha1.PromoteToStageSubscribersRequest, v1alpha1.PromoteToStageSubscribersResponse]
 	queryFreight              *connect.Client[v1alpha1.QueryFreightRequest, v1alpha1.QueryFreightResponse]
 	updateFreightAlias        *connect.Client[v1alpha1.UpdateFreightAliasRequest, v1alpha1.UpdateFreightAliasResponse]
+	reverify                  *connect.Client[v1alpha1.ReverifyRequest, v1alpha1.ReverifyResponse]
+	abortVerification         *connect.Client[v1alpha1.AbortVerificationRequest, v1alpha1.AbortVerificationResponse]
 	listWarehouses            *connect.Client[v1alpha1.ListWarehousesRequest, v1alpha1.ListWarehousesResponse]
 	getWarehouse              *connect.Client[v1alpha1.GetWarehouseRequest, v1alpha1.GetWarehouseResponse]
 	watchWarehouses           *connect.Client[v1alpha1.WatchWarehousesRequest, v1alpha1.WatchWarehousesResponse]
@@ -561,6 +580,16 @@ func (c *kargoServiceClient) UpdateFreightAlias(ctx context.Context, req *connec
 	return c.updateFreightAlias.CallUnary(ctx, req)
 }
 
+// Reverify calls akuity.io.kargo.service.v1alpha1.KargoService.Reverify.
+func (c *kargoServiceClient) Reverify(ctx context.Context, req *connect.Request[v1alpha1.ReverifyRequest]) (*connect.Response[v1alpha1.ReverifyResponse], error) {
+	return c.reverify.CallUnary(ctx, req)
+}
+
+// AbortVerification calls akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification.
+func (c *kargoServiceClient) AbortVerification(ctx context.Context, req *connect.Request[v1alpha1.AbortVerificationRequest]) (*connect.Response[v1alpha1.AbortVerificationResponse], error) {
+	return c.abortVerification.CallUnary(ctx, req)
+}
+
 // ListWarehouses calls akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses.
 func (c *kargoServiceClient) ListWarehouses(ctx context.Context, req *connect.Request[v1alpha1.ListWarehousesRequest]) (*connect.Response[v1alpha1.ListWarehousesResponse], error) {
 	return c.listWarehouses.CallUnary(ctx, req)
@@ -644,6 +673,8 @@ type KargoServiceHandler interface {
 	PromoteToStageSubscribers(context.Context, *connect.Request[v1alpha1.PromoteToStageSubscribersRequest]) (*connect.Response[v1alpha1.PromoteToStageSubscribersResponse], error)
 	QueryFreight(context.Context, *connect.Request[v1alpha1.QueryFreightRequest]) (*connect.Response[v1alpha1.QueryFreightResponse], error)
 	UpdateFreightAlias(context.Context, *connect.Request[v1alpha1.UpdateFreightAliasRequest]) (*connect.Response[v1alpha1.UpdateFreightAliasResponse], error)
+	Reverify(context.Context, *connect.Request[v1alpha1.ReverifyRequest]) (*connect.Response[v1alpha1.ReverifyResponse], error)
+	AbortVerification(context.Context, *connect.Request[v1alpha1.AbortVerificationRequest]) (*connect.Response[v1alpha1.AbortVerificationResponse], error)
 	ListWarehouses(context.Context, *connect.Request[v1alpha1.ListWarehousesRequest]) (*connect.Response[v1alpha1.ListWarehousesResponse], error)
 	GetWarehouse(context.Context, *connect.Request[v1alpha1.GetWarehouseRequest]) (*connect.Response[v1alpha1.GetWarehouseResponse], error)
 	WatchWarehouses(context.Context, *connect.Request[v1alpha1.WatchWarehousesRequest], *connect.ServerStream[v1alpha1.WatchWarehousesResponse]) error
@@ -798,6 +829,16 @@ func NewKargoServiceHandler(svc KargoServiceHandler, opts ...connect.HandlerOpti
 		svc.UpdateFreightAlias,
 		opts...,
 	)
+	kargoServiceReverifyHandler := connect.NewUnaryHandler(
+		KargoServiceReverifyProcedure,
+		svc.Reverify,
+		opts...,
+	)
+	kargoServiceAbortVerificationHandler := connect.NewUnaryHandler(
+		KargoServiceAbortVerificationProcedure,
+		svc.AbortVerification,
+		opts...,
+	)
 	kargoServiceListWarehousesHandler := connect.NewUnaryHandler(
 		KargoServiceListWarehousesProcedure,
 		svc.ListWarehouses,
@@ -904,6 +945,10 @@ func NewKargoServiceHandler(svc KargoServiceHandler, opts ...connect.HandlerOpti
 			kargoServiceQueryFreightHandler.ServeHTTP(w, r)
 		case KargoServiceUpdateFreightAliasProcedure:
 			kargoServiceUpdateFreightAliasHandler.ServeHTTP(w, r)
+		case KargoServiceReverifyProcedure:
+			kargoServiceReverifyHandler.ServeHTTP(w, r)
+		case KargoServiceAbortVerificationProcedure:
+			kargoServiceAbortVerificationHandler.ServeHTTP(w, r)
 		case KargoServiceListWarehousesProcedure:
 			kargoServiceListWarehousesHandler.ServeHTTP(w, r)
 		case KargoServiceGetWarehouseProcedure:
@@ -1041,6 +1086,14 @@ func (UnimplementedKargoServiceHandler) UpdateFreightAlias(context.Context, *con
 	return nil, connect.NewError(connect.CodeUnimplemented, errors.New("akuity.io.kargo.service.v1alpha1.KargoService.UpdateFreightAlias is not implemented"))
 }
 
+func (UnimplementedKargoServiceHandler) Reverify(context.Context, *connect.Request[v1alpha1.ReverifyRequest]) (*connect.Response[v1alpha1.ReverifyResponse], error) {
+	return nil, connect.NewError(connect.CodeUnimplemented, errors.New("akuity.io.kargo.service.v1alpha1.KargoService.Reverify is not implemented"))
+}
+
+func (UnimplementedKargoServiceHandler) AbortVerification(context.Context, *connect.Request[v1alpha1.AbortVerificationRequest]) (*connect.Response[v1alpha1.AbortVerificationResponse], error) {
+	return nil, connect.NewError(connect.CodeUnimplemented, errors.New("akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification is not implemented"))
+}
+
 func (UnimplementedKargoServiceHandler) ListWarehouses(context.Context, *connect.Request[v1alpha1.ListWarehousesRequest]) (*connect.Response[v1alpha1.ListWarehousesResponse], error) {
 	return nil, connect.NewError(connect.CodeUnimplemented, errors.New("akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses is not implemented"))
 }
diff --git a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
index 476c3207..7adad0bc 100644
--- a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
+++ b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
@@ -567,6 +567,10 @@
                   ],
                   "type": "object"
                 },
+                "id": {
+                  "description": "ID is the identifier of the Verification process.",
+                  "type": "string"
+                },
                 "message": {
                   "description": "Message may contain additional information about why the verification\nprocess is in its current phase.",
                   "type": "string"
@@ -707,6 +711,10 @@
                       ],
                       "type": "object"
                     },
+                    "id": {
+                      "description": "ID is the identifier of the Verification process.",
+                      "type": "string"
+                    },
                     "message": {
                       "description": "Message may contain additional information about why the verification\nprocess is in its current phase.",
                       "type": "string"
@@ -932,6 +940,10 @@
                     ],
                     "type": "object"
                   },
+                  "id": {
+                    "description": "ID is the identifier of the Verification process.",
+                    "type": "string"
+                  },
                   "message": {
                     "description": "Message may contain additional information about why the verification\nprocess is in its current phase.",
                     "type": "string"
diff --git a/ui/src/gen/service/v1alpha1/service-KargoService_connectquery.ts b/ui/src/gen/service/v1alpha1/service-KargoService_connectquery.ts
index 04e50403..cf90140e 100644
--- a/ui/src/gen/service/v1alpha1/service-KargoService_connectquery.ts
+++ b/ui/src/gen/service/v1alpha1/service-KargoService_connectquery.ts
@@ -5,7 +5,7 @@
 
 import { createQueryService } from "@bufbuild/connect-query";
 import { MethodKind } from "@bufbuild/protobuf";
-import { AdminLoginRequest, AdminLoginResponse, ApproveFreightRequest, ApproveFreightResponse, CreateCredentialsRequest, CreateCredentialsResponse, CreateOrUpdateResourceRequest, CreateOrUpdateResourceResponse, CreateResourceRequest, CreateResourceResponse, DeleteCredentialsRequest, DeleteCredentialsResponse, DeleteFreightRequest, DeleteFreightResponse, DeleteProjectRequest, DeleteProjectResponse, DeleteResourceRequest, DeleteResourceResponse, DeleteStageRequest, DeleteStageResponse, DeleteWarehouseRequest, DeleteWarehouseResponse, GetConfigRequest, GetConfigResponse, GetCredentialsRequest, GetCredentialsResponse, GetFreightRequest, GetFreightResponse, GetProjectRequest, GetProjectResponse, GetPromotionRequest, GetPromotionResponse, GetPublicConfigRequest, GetPublicConfigResponse, GetStageRequest, GetStageResponse, GetVersionInfoRequest, GetVersionInfoResponse, GetWarehouseRequest, GetWarehouseResponse, ListCredentialsRequest, ListCredentialsResponse, ListProjectsRequest, ListProjectsResponse, ListPromotionsRequest, ListPromotionsResponse, ListStagesRequest, ListStagesResponse, ListWarehousesRequest, ListWarehousesResponse, PromoteToStageRequest, PromoteToStageResponse, PromoteToStageSubscribersRequest, PromoteToStageSubscribersResponse, QueryFreightRequest, QueryFreightResponse, RefreshStageRequest, RefreshStageResponse, RefreshWarehouseRequest, RefreshWarehouseResponse, UpdateCredentialsRequest, UpdateCredentialsResponse, UpdateFreightAliasRequest, UpdateFreightAliasResponse, UpdateResourceRequest, UpdateResourceResponse } from "./service_pb.js";
+import { AbortVerificationRequest, AbortVerificationResponse, AdminLoginRequest, AdminLoginResponse, ApproveFreightRequest, ApproveFreightResponse, CreateCredentialsRequest, CreateCredentialsResponse, CreateOrUpdateResourceRequest, CreateOrUpdateResourceResponse, CreateResourceRequest, CreateResourceResponse, DeleteCredentialsRequest, DeleteCredentialsResponse, DeleteFreightRequest, DeleteFreightResponse, DeleteProjectRequest, DeleteProjectResponse, DeleteResourceRequest, DeleteResourceResponse, DeleteStageRequest, DeleteStageResponse, DeleteWarehouseRequest, DeleteWarehouseResponse, GetConfigRequest, GetConfigResponse, GetCredentialsRequest, GetCredentialsResponse, GetFreightRequest, GetFreightResponse, GetProjectRequest, GetProjectResponse, GetPromotionRequest, GetPromotionResponse, GetPublicConfigRequest, GetPublicConfigResponse, GetStageRequest, GetStageResponse, GetVersionInfoRequest, GetVersionInfoResponse, GetWarehouseRequest, GetWarehouseResponse, ListCredentialsRequest, ListCredentialsResponse, ListProjectsRequest, ListProjectsResponse, ListPromotionsRequest, ListPromotionsResponse, ListStagesRequest, ListStagesResponse, ListWarehousesRequest, ListWarehousesResponse, PromoteToStageRequest, PromoteToStageResponse, PromoteToStageSubscribersRequest, PromoteToStageSubscribersResponse, QueryFreightRequest, QueryFreightResponse, RefreshStageRequest, RefreshStageResponse, RefreshWarehouseRequest, RefreshWarehouseResponse, ReverifyRequest, ReverifyResponse, UpdateCredentialsRequest, UpdateCredentialsResponse, UpdateFreightAliasRequest, UpdateFreightAliasResponse, UpdateResourceRequest, UpdateResourceResponse } from "./service_pb.js";
 
 export const typeName = "akuity.io.kargo.service.v1alpha1.KargoService";
 
@@ -422,6 +422,40 @@ export const updateFreightAlias = createQueryService({
   },
 }).updateFreightAlias;
 
+/**
+ * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.Reverify
+ */
+export const reverify = createQueryService({
+  service: {
+    methods: {
+      reverify: {
+        name: "Reverify",
+        kind: MethodKind.Unary,
+        I: ReverifyRequest,
+        O: ReverifyResponse,
+      },
+    },
+    typeName: "akuity.io.kargo.service.v1alpha1.KargoService",
+  },
+}).reverify;
+
+/**
+ * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification
+ */
+export const abortVerification = createQueryService({
+  service: {
+    methods: {
+      abortVerification: {
+        name: "AbortVerification",
+        kind: MethodKind.Unary,
+        I: AbortVerificationRequest,
+        O: AbortVerificationResponse,
+      },
+    },
+    typeName: "akuity.io.kargo.service.v1alpha1.KargoService",
+  },
+}).abortVerification;
+
 /**
  * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses
  */
diff --git a/ui/src/gen/service/v1alpha1/service_connect.ts b/ui/src/gen/service/v1alpha1/service_connect.ts
index 3d1cd8ff..1c8c6446 100644
--- a/ui/src/gen/service/v1alpha1/service_connect.ts
+++ b/ui/src/gen/service/v1alpha1/service_connect.ts
@@ -3,7 +3,7 @@
 /* eslint-disable */
 // @ts-nocheck
 
-import { AdminLoginRequest, AdminLoginResponse, ApproveFreightRequest, ApproveFreightResponse, CreateCredentialsRequest, CreateCredentialsResponse, CreateOrUpdateResourceRequest, CreateOrUpdateResourceResponse, CreateResourceRequest, CreateResourceResponse, DeleteCredentialsRequest, DeleteCredentialsResponse, DeleteFreightRequest, DeleteFreightResponse, DeleteProjectRequest, DeleteProjectResponse, DeleteResourceRequest, DeleteResourceResponse, DeleteStageRequest, DeleteStageResponse, DeleteWarehouseRequest, DeleteWarehouseResponse, GetConfigRequest, GetConfigResponse, GetCredentialsRequest, GetCredentialsResponse, GetFreightRequest, GetFreightResponse, GetProjectRequest, GetProjectResponse, GetPromotionRequest, GetPromotionResponse, GetPublicConfigRequest, GetPublicConfigResponse, GetStageRequest, GetStageResponse, GetVersionInfoRequest, GetVersionInfoResponse, GetWarehouseRequest, GetWarehouseResponse, ListCredentialsRequest, ListCredentialsResponse, ListProjectsRequest, ListProjectsResponse, ListPromotionsRequest, ListPromotionsResponse, ListStagesRequest, ListStagesResponse, ListWarehousesRequest, ListWarehousesResponse, PromoteToStageRequest, PromoteToStageResponse, PromoteToStageSubscribersRequest, PromoteToStageSubscribersResponse, QueryFreightRequest, QueryFreightResponse, RefreshStageRequest, RefreshStageResponse, RefreshWarehouseRequest, RefreshWarehouseResponse, UpdateCredentialsRequest, UpdateCredentialsResponse, UpdateFreightAliasRequest, UpdateFreightAliasResponse, UpdateResourceRequest, UpdateResourceResponse, WatchPromotionRequest, WatchPromotionResponse, WatchPromotionsRequest, WatchPromotionsResponse, WatchStagesRequest, WatchStagesResponse, WatchWarehousesRequest, WatchWarehousesResponse } from "./service_pb.js";
+import { AbortVerificationRequest, AbortVerificationResponse, AdminLoginRequest, AdminLoginResponse, ApproveFreightRequest, ApproveFreightResponse, CreateCredentialsRequest, CreateCredentialsResponse, CreateOrUpdateResourceRequest, CreateOrUpdateResourceResponse, CreateResourceRequest, CreateResourceResponse, DeleteCredentialsRequest, DeleteCredentialsResponse, DeleteFreightRequest, DeleteFreightResponse, DeleteProjectRequest, DeleteProjectResponse, DeleteResourceRequest, DeleteResourceResponse, DeleteStageRequest, DeleteStageResponse, DeleteWarehouseRequest, DeleteWarehouseResponse, GetConfigRequest, GetConfigResponse, GetCredentialsRequest, GetCredentialsResponse, GetFreightRequest, GetFreightResponse, GetProjectRequest, GetProjectResponse, GetPromotionRequest, GetPromotionResponse, GetPublicConfigRequest, GetPublicConfigResponse, GetStageRequest, GetStageResponse, GetVersionInfoRequest, GetVersionInfoResponse, GetWarehouseRequest, GetWarehouseResponse, ListCredentialsRequest, ListCredentialsResponse, ListProjectsRequest, ListProjectsResponse, ListPromotionsRequest, ListPromotionsResponse, ListStagesRequest, ListStagesResponse, ListWarehousesRequest, ListWarehousesResponse, PromoteToStageRequest, PromoteToStageResponse, PromoteToStageSubscribersRequest, PromoteToStageSubscribersResponse, QueryFreightRequest, QueryFreightResponse, RefreshStageRequest, RefreshStageResponse, RefreshWarehouseRequest, RefreshWarehouseResponse, ReverifyRequest, ReverifyResponse, UpdateCredentialsRequest, UpdateCredentialsResponse, UpdateFreightAliasRequest, UpdateFreightAliasResponse, UpdateResourceRequest, UpdateResourceResponse, WatchPromotionRequest, WatchPromotionResponse, WatchPromotionsRequest, WatchPromotionsResponse, WatchStagesRequest, WatchStagesResponse, WatchWarehousesRequest, WatchWarehousesResponse } from "./service_pb.js";
 import { MethodKind } from "@bufbuild/protobuf";
 
 /**
@@ -260,6 +260,24 @@ export const KargoService = {
       O: UpdateFreightAliasResponse,
       kind: MethodKind.Unary,
     },
+    /**
+     * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.Reverify
+     */
+    reverify: {
+      name: "Reverify",
+      I: ReverifyRequest,
+      O: ReverifyResponse,
+      kind: MethodKind.Unary,
+    },
+    /**
+     * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.AbortVerification
+     */
+    abortVerification: {
+      name: "AbortVerification",
+      I: AbortVerificationRequest,
+      O: AbortVerificationResponse,
+      kind: MethodKind.Unary,
+    },
     /**
      * @generated from rpc akuity.io.kargo.service.v1alpha1.KargoService.ListWarehouses
      */
diff --git a/ui/src/gen/service/v1alpha1/service_pb.ts b/ui/src/gen/service/v1alpha1/service_pb.ts
index 71bccf18..4f19fe3f 100644
--- a/ui/src/gen/service/v1alpha1/service_pb.ts
+++ b/ui/src/gen/service/v1alpha1/service_pb.ts
@@ -2620,6 +2620,158 @@ export class UpdateFreightAliasResponse extends Message<UpdateFreightAliasRespon
   }
 }
 
+/**
+ * @generated from message akuity.io.kargo.service.v1alpha1.ReverifyRequest
+ */
+export class ReverifyRequest extends Message<ReverifyRequest> {
+  /**
+   * @generated from field: string project = 1;
+   */
+  project = "";
+
+  /**
+   * @generated from field: string stage = 2;
+   */
+  stage = "";
+
+  constructor(data?: PartialMessage<ReverifyRequest>) {
+    super();
+    proto3.util.initPartial(data, this);
+  }
+
+  static readonly runtime: typeof proto3 = proto3;
+  static readonly typeName = "akuity.io.kargo.service.v1alpha1.ReverifyRequest";
+  static readonly fields: FieldList = proto3.util.newFieldList(() => [
+    { no: 1, name: "project", kind: "scalar", T: 9 /* ScalarType.STRING */ },
+    { no: 2, name: "stage", kind: "scalar", T: 9 /* ScalarType.STRING */ },
+  ]);
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ReverifyRequest {
+    return new ReverifyRequest().fromBinary(bytes, options);
+  }
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ReverifyRequest {
+    return new ReverifyRequest().fromJson(jsonValue, options);
+  }
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ReverifyRequest {
+    return new ReverifyRequest().fromJsonString(jsonString, options);
+  }
+
+  static equals(a: ReverifyRequest | PlainMessage<ReverifyRequest> | undefined, b: ReverifyRequest | PlainMessage<ReverifyRequest> | undefined): boolean {
+    return proto3.util.equals(ReverifyRequest, a, b);
+  }
+}
+
+/**
+ * explicitly empty 
+ *
+ * @generated from message akuity.io.kargo.service.v1alpha1.ReverifyResponse
+ */
+export class ReverifyResponse extends Message<ReverifyResponse> {
+  constructor(data?: PartialMessage<ReverifyResponse>) {
+    super();
+    proto3.util.initPartial(data, this);
+  }
+
+  static readonly runtime: typeof proto3 = proto3;
+  static readonly typeName = "akuity.io.kargo.service.v1alpha1.ReverifyResponse";
+  static readonly fields: FieldList = proto3.util.newFieldList(() => [
+  ]);
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ReverifyResponse {
+    return new ReverifyResponse().fromBinary(bytes, options);
+  }
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ReverifyResponse {
+    return new ReverifyResponse().fromJson(jsonValue, options);
+  }
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ReverifyResponse {
+    return new ReverifyResponse().fromJsonString(jsonString, options);
+  }
+
+  static equals(a: ReverifyResponse | PlainMessage<ReverifyResponse> | undefined, b: ReverifyResponse | PlainMessage<ReverifyResponse> | undefined): boolean {
+    return proto3.util.equals(ReverifyResponse, a, b);
+  }
+}
+
+/**
+ * @generated from message akuity.io.kargo.service.v1alpha1.AbortVerificationRequest
+ */
+export class AbortVerificationRequest extends Message<AbortVerificationRequest> {
+  /**
+   * @generated from field: string project = 1;
+   */
+  project = "";
+
+  /**
+   * @generated from field: string stage = 2;
+   */
+  stage = "";
+
+  constructor(data?: PartialMessage<AbortVerificationRequest>) {
+    super();
+    proto3.util.initPartial(data, this);
+  }
+
+  static readonly runtime: typeof proto3 = proto3;
+  static readonly typeName = "akuity.io.kargo.service.v1alpha1.AbortVerificationRequest";
+  static readonly fields: FieldList = proto3.util.newFieldList(() => [
+    { no: 1, name: "project", kind: "scalar", T: 9 /* ScalarType.STRING */ },
+    { no: 2, name: "stage", kind: "scalar", T: 9 /* ScalarType.STRING */ },
+  ]);
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): AbortVerificationRequest {
+    return new AbortVerificationRequest().fromBinary(bytes, options);
+  }
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): AbortVerificationRequest {
+    return new AbortVerificationRequest().fromJson(jsonValue, options);
+  }
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): AbortVerificationRequest {
+    return new AbortVerificationRequest().fromJsonString(jsonString, options);
+  }
+
+  static equals(a: AbortVerificationRequest | PlainMessage<AbortVerificationRequest> | undefined, b: AbortVerificationRequest | PlainMessage<AbortVerificationRequest> | undefined): boolean {
+    return proto3.util.equals(AbortVerificationRequest, a, b);
+  }
+}
+
+/**
+ * explicitly empty 
+ *
+ * @generated from message akuity.io.kargo.service.v1alpha1.AbortVerificationResponse
+ */
+export class AbortVerificationResponse extends Message<AbortVerificationResponse> {
+  constructor(data?: PartialMessage<AbortVerificationResponse>) {
+    super();
+    proto3.util.initPartial(data, this);
+  }
+
+  static readonly runtime: typeof proto3 = proto3;
+  static readonly typeName = "akuity.io.kargo.service.v1alpha1.AbortVerificationResponse";
+  static readonly fields: FieldList = proto3.util.newFieldList(() => [
+  ]);
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): AbortVerificationResponse {
+    return new AbortVerificationResponse().fromBinary(bytes, options);
+  }
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): AbortVerificationResponse {
+    return new AbortVerificationResponse().fromJson(jsonValue, options);
+  }
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): AbortVerificationResponse {
+    return new AbortVerificationResponse().fromJsonString(jsonString, options);
+  }
+
+  static equals(a: AbortVerificationResponse | PlainMessage<AbortVerificationResponse> | undefined, b: AbortVerificationResponse | PlainMessage<AbortVerificationResponse> | undefined): boolean {
+    return proto3.util.equals(AbortVerificationResponse, a, b);
+  }
+}
+
 /**
  * @generated from message akuity.io.kargo.service.v1alpha1.ListWarehousesRequest
  */
diff --git a/ui/src/gen/v1alpha1/generated_pb.ts b/ui/src/gen/v1alpha1/generated_pb.ts
index ef73469b..4fc1efb6 100644
--- a/ui/src/gen/v1alpha1/generated_pb.ts
+++ b/ui/src/gen/v1alpha1/generated_pb.ts
@@ -3402,6 +3402,13 @@ export class Verification extends Message<Verification> {
  * @generated from message github.com.akuity.kargo.api.v1alpha1.VerificationInfo
  */
 export class VerificationInfo extends Message<VerificationInfo> {
+  /**
+   * ID is the identifier of the Verification process.
+   *
+   * @generated from field: optional string id = 4;
+   */
+  id?: string;
+
   /**
    * Phase describes the current phase of the Verification process. Generally,
    * this will be a reflection of the underlying AnalysisRun's phase, however,
@@ -3436,6 +3443,7 @@ export class VerificationInfo extends Message<VerificationInfo> {
   static readonly runtime: typeof proto2 = proto2;
   static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.VerificationInfo";
   static readonly fields: FieldList = proto2.util.newFieldList(() => [
+    { no: 4, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
     { no: 1, name: "phase", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
     { no: 2, name: "message", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
     { no: 3, name: "analysisRun", kind: "message", T: AnalysisRunReference, opt: true },


Test patch:
diff --git a/api/v1alpha1/helpers_test.go b/api/v1alpha1/helpers_test.go
index 57645d8e..0472b797 100644
--- a/api/v1alpha1/helpers_test.go
+++ b/api/v1alpha1/helpers_test.go
@@ -3,7 +3,6 @@ package v1alpha1
 import (
 	"context"
 	"testing"
-	"time"
 
 	"github.com/stretchr/testify/require"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -12,7 +11,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
-func Test_refreshObject(t *testing.T) {
+func TestClearAnnotations(t *testing.T) {
 	scheme := k8sruntime.NewScheme()
 	require.NoError(t, SchemeBuilder.AddToScheme(scheme))
 
@@ -23,13 +22,134 @@ func Test_refreshObject(t *testing.T) {
 			WithObjects(obj...).
 			Build()
 	}
-	mockNow := func() time.Time {
-		return time.Date(2023, 11, 2, 0, 0, 0, 0, time.UTC)
+
+	testCases := []struct {
+		name       string
+		client     client.Client
+		obj        client.Object
+		keys       []string
+		assertions func(*testing.T, client.Object, error)
+	}{
+		{
+			name:   "no keys",
+			client: newFakeClient(),
+			obj:    nil,
+			keys:   nil,
+			assertions: func(t *testing.T, _ client.Object, err error) {
+				require.NoError(t, err)
+			},
+		},
+		{
+			name: "no annotations",
+			client: newFakeClient(&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+				},
+			}),
+			obj: &Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+				},
+			},
+			keys: []string{"key"},
+			assertions: func(t *testing.T, _ client.Object, err error) {
+				require.NoError(t, err)
+			},
+		},
+		{
+			name:   "not found",
+			client: newFakeClient(),
+			obj: &Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+				},
+			},
+			keys: []string{"key"},
+			assertions: func(t *testing.T, _ client.Object, err error) {
+				require.ErrorContains(t, err, "patch annotation")
+			},
+		},
+		{
+			name: "clear one",
+			client: newFakeClient(&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+					Annotations: map[string]string{
+						"key1": "value1",
+						"key2": "value2",
+					},
+				},
+			}),
+			obj: &Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+				},
+			},
+			keys: []string{"key1"},
+			assertions: func(t *testing.T, obj client.Object, err error) {
+				require.NoError(t, err)
+				require.Contains(t, obj.GetAnnotations(), "key2")
+				require.NotContains(t, obj.GetAnnotations(), "key1")
+			},
+		},
+		{
+			name: "clear two",
+			client: newFakeClient(&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+					Annotations: map[string]string{
+						"key1": "value1",
+						"key2": "value2",
+					},
+				},
+			}),
+			obj: &Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "stage",
+				},
+			},
+			keys: []string{"key1", "key2"},
+			assertions: func(t *testing.T, obj client.Object, err error) {
+				require.NoError(t, err)
+				require.NotContains(t, obj.GetAnnotations(), "key2")
+				require.NotContains(t, obj.GetAnnotations(), "key1")
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			err := ClearAnnotations(context.TODO(), tc.client, tc.obj, tc.keys...)
+			tc.assertions(t, tc.obj, err)
+		})
+	}
+}
+
+func Test_patchAnnotation(t *testing.T) {
+	scheme := k8sruntime.NewScheme()
+	require.NoError(t, SchemeBuilder.AddToScheme(scheme))
+
+	t.Parallel()
+	newFakeClient := func(obj ...client.Object) client.Client {
+		return fake.NewClientBuilder().
+			WithScheme(scheme).
+			WithObjects(obj...).
+			Build()
 	}
+
 	testCases := map[string]struct {
 		obj         client.Object
-		cli         client.Client
-		nowFunc     func() time.Time
+		client      client.Client
+		key         string
+		value       string
 		errExpected bool
 	}{
 		"stage": {
@@ -39,31 +159,33 @@ func Test_refreshObject(t *testing.T) {
 					Name:      "stage",
 				},
 			},
-			cli: newFakeClient(&Stage{
+			client: newFakeClient(&Stage{
 				ObjectMeta: metav1.ObjectMeta{
 					Namespace: "test",
 					Name:      "stage",
 				},
 			}),
-			nowFunc: mockNow,
+			key:   "key",
+			value: "value",
 		},
-		"stage with refresh annotation key": {
+		"stage with existing annotation": {
 			obj: &Stage{
 				ObjectMeta: metav1.ObjectMeta{
 					Namespace: "test",
 					Name:      "stage",
 				},
 			},
-			cli: newFakeClient(&Stage{
+			client: newFakeClient(&Stage{
 				ObjectMeta: metav1.ObjectMeta{
 					Namespace: "test",
 					Name:      "stage",
 					Annotations: map[string]string{
-						AnnotationKeyRefresh: time.Date(2023, 11, 1, 0, 0, 0, 0, time.UTC).Format(time.RFC3339),
+						"key": "value",
 					},
 				},
 			}),
-			nowFunc: mockNow,
+			key:   "key",
+			value: "value2",
 		},
 		"non-existing stage": {
 			obj: &Stage{
@@ -72,23 +194,22 @@ func Test_refreshObject(t *testing.T) {
 					Name:      "stage",
 				},
 			},
-			cli:         newFakeClient(),
-			nowFunc:     mockNow,
+			client:      newFakeClient(),
+			key:         "key",
+			value:       "value",
 			errExpected: true,
 		},
 	}
 	for name, tc := range testCases {
 		tc := tc
 		t.Run(name, func(t *testing.T) {
-			err := refreshObject(context.Background(), tc.cli, tc.obj, tc.nowFunc)
+			err := patchAnnotation(context.Background(), tc.client, tc.obj, tc.key, tc.value)
 			if tc.errExpected {
 				require.Error(t, err)
 				return
 			}
-			require.Contains(t, tc.obj.GetAnnotations(), AnnotationKeyRefresh)
-			actual, err := time.Parse(time.RFC3339, tc.obj.GetAnnotations()[AnnotationKeyRefresh])
-			require.NoError(t, err)
-			require.Equal(t, tc.nowFunc(), actual)
+			require.Contains(t, tc.obj.GetAnnotations(), tc.key)
+			require.Equal(t, tc.obj.GetAnnotations()[tc.key], tc.value)
 		})
 	}
 }
diff --git a/api/v1alpha1/stage_helpers_test.go b/api/v1alpha1/stage_helpers_test.go
index 43d08b2e..15833468 100644
--- a/api/v1alpha1/stage_helpers_test.go
+++ b/api/v1alpha1/stage_helpers_test.go
@@ -62,3 +62,246 @@ func TestGetStage(t *testing.T) {
 		})
 	}
 }
+
+func TestReverifyStageFreight(t *testing.T) {
+	scheme := k8sruntime.NewScheme()
+	require.NoError(t, SchemeBuilder.AddToScheme(scheme))
+
+	t.Run("not found", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).Build()
+
+		err := ReverifyStageFreight(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "not found")
+	})
+
+	t.Run("missing current freight", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+			},
+		).Build()
+
+		err := ReverifyStageFreight(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage has no current freight")
+	})
+
+	t.Run("missing verification info", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{},
+				},
+			},
+		).Build()
+
+		err := ReverifyStageFreight(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage has no existing verification info")
+	})
+
+	t.Run("missing verification info ID", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{
+						VerificationInfo: &VerificationInfo{},
+					},
+				},
+			},
+		).Build()
+
+		err := ReverifyStageFreight(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage verification info has no ID")
+	})
+
+	t.Run("success", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{
+						VerificationInfo: &VerificationInfo{
+							ID: "fake-id",
+						},
+					},
+				},
+			},
+		).Build()
+
+		err := ReverifyStageFreight(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+
+		stage, err := GetStage(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+		require.Equal(t, "fake-id", stage.Annotations[AnnotationKeyReverify])
+	})
+}
+
+func TestAbortStageFreightVerification(t *testing.T) {
+	scheme := k8sruntime.NewScheme()
+	require.NoError(t, SchemeBuilder.AddToScheme(scheme))
+
+	t.Run("not found", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "not found")
+	})
+
+	t.Run("missing current freight", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+			},
+		).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage has no current freight")
+	})
+
+	t.Run("missing verification info", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{},
+				},
+			},
+		).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage has no existing verification info")
+	})
+
+	t.Run("missing verification info ID", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{
+						VerificationInfo: &VerificationInfo{},
+					},
+				},
+			},
+		).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.ErrorContains(t, err, "stage verification info has no ID")
+	})
+
+	t.Run("verification in terminal phase", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{
+						VerificationInfo: &VerificationInfo{
+							ID:    "fake-id",
+							Phase: VerificationPhaseError,
+						},
+					},
+				},
+			},
+		).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+
+		stage, err := GetStage(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+		_, ok := stage.Annotations[AnnotationKeyAbort]
+		require.False(t, ok)
+	})
+
+	t.Run("success", func(t *testing.T) {
+		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
+			&Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "fake-stage",
+					Namespace: "fake-namespace",
+				},
+				Status: StageStatus{
+					CurrentFreight: &FreightReference{
+						VerificationInfo: &VerificationInfo{
+							ID: "fake-id",
+						},
+					},
+				},
+			},
+		).Build()
+
+		err := AbortStageFreightVerification(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+
+		stage, err := GetStage(context.TODO(), c, types.NamespacedName{
+			Namespace: "fake-namespace",
+			Name:      "fake-stage",
+		})
+		require.NoError(t, err)
+		require.Equal(t, "fake-id", stage.Annotations[AnnotationKeyAbort])
+	})
+}
diff --git a/internal/controller/stages/stages_test.go b/internal/controller/stages/stages_test.go
index d3b33ecd..0f3314e0 100644
--- a/internal/controller/stages/stages_test.go
+++ b/internal/controller/stages/stages_test.go
@@ -233,7 +233,7 @@ func TestSyncControlFlowStage(t *testing.T) {
 				},
 			},
 			assertions: func(
-				initialStatus kargoapi.StageStatus,
+				_ kargoapi.StageStatus,
 				newStatus kargoapi.StageStatus,
 				err error,
 			) {
@@ -321,6 +321,122 @@ func TestSyncNormalStage(t *testing.T) {
 			},
 		},
 
+		{
+			name: "reverification requested",
+			stage: &kargoapi.Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						kargoapi.AnnotationKeyReverify: "fake-id",
+					},
+				},
+				Spec: &kargoapi.StageSpec{
+					PromotionMechanisms: &kargoapi.PromotionMechanisms{},
+					Verification:        &kargoapi.Verification{},
+				},
+				Status: kargoapi.StageStatus{
+					Phase: kargoapi.StagePhaseSteady,
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID:    "fake-id",
+							Phase: kargoapi.VerificationPhaseFailed,
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name: "fake-analysis-run",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				hasNonTerminalPromotionsFn: noNonTerminalPromotionsFn,
+				checkHealthFn: func(
+					context.Context,
+					kargoapi.FreightReference,
+					[]kargoapi.ArgoCDAppUpdate,
+				) *kargoapi.Health {
+					return nil
+				},
+				startVerificationFn: func(
+					context.Context,
+					*kargoapi.Stage,
+				) *kargoapi.VerificationInfo {
+					return &kargoapi.VerificationInfo{
+						ID:      "new-fake-id",
+						Phase:   kargoapi.VerificationPhasePending,
+						Message: "Awaiting reconfirmation",
+						AnalysisRun: &kargoapi.AnalysisRunReference{
+							Name: "new-fake-analysis-run",
+						},
+					}
+				},
+			},
+			assertions: func(
+				_ kargoapi.StageStatus,
+				newStatus kargoapi.StageStatus,
+				err error,
+			) {
+				require.NoError(t, err)
+				require.NotNil(t, newStatus.CurrentFreight)
+				require.Equal(t, kargoapi.StagePhaseVerifying, newStatus.Phase)
+				require.Equal(
+					t,
+					&kargoapi.VerificationInfo{
+						ID:      "new-fake-id",
+						Phase:   kargoapi.VerificationPhasePending,
+						Message: "Awaiting reconfirmation",
+						AnalysisRun: &kargoapi.AnalysisRunReference{
+							Name: "new-fake-analysis-run",
+						},
+					},
+					newStatus.CurrentFreight.VerificationInfo,
+				)
+			},
+		},
+
+		{
+			name: "ignores reverification request if conditions are not met",
+			stage: &kargoapi.Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						kargoapi.AnnotationKeyReverify: "wrong-fake-analysis-run",
+					},
+				},
+				Spec: &kargoapi.StageSpec{
+					PromotionMechanisms: &kargoapi.PromotionMechanisms{},
+					Verification:        &kargoapi.Verification{},
+				},
+				Status: kargoapi.StageStatus{
+					Phase: kargoapi.StagePhaseSteady,
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							Phase: kargoapi.VerificationPhaseFailed,
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name: "fake-analysis-run",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				hasNonTerminalPromotionsFn: noNonTerminalPromotionsFn,
+				checkHealthFn: func(
+					context.Context,
+					kargoapi.FreightReference,
+					[]kargoapi.ArgoCDAppUpdate,
+				) *kargoapi.Health {
+					return nil
+				},
+			},
+			assertions: func(
+				initialStatus kargoapi.StageStatus,
+				newStatus kargoapi.StageStatus,
+				err error,
+			) {
+				require.NoError(t, err)
+				require.NotNil(t, newStatus.CurrentFreight)
+				require.Equal(t, initialStatus, newStatus)
+			},
+		},
+
 		{
 			name: "error starting verification",
 			stage: &kargoapi.Stage{
@@ -429,6 +545,141 @@ func TestSyncNormalStage(t *testing.T) {
 			},
 		},
 
+		{
+			name: "verification aborted",
+			stage: &kargoapi.Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						kargoapi.AnnotationKeyAbort: "fake-id",
+					},
+				},
+				Spec: &kargoapi.StageSpec{
+					PromotionMechanisms: &kargoapi.PromotionMechanisms{},
+					Verification:        &kargoapi.Verification{},
+				},
+				Status: kargoapi.StageStatus{
+					Phase: kargoapi.StagePhaseVerifying,
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID:    "fake-id",
+							Phase: kargoapi.VerificationPhasePending,
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name: "fake-analysis-run",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				hasNonTerminalPromotionsFn: noNonTerminalPromotionsFn,
+				checkHealthFn: func(
+					context.Context,
+					kargoapi.FreightReference,
+					[]kargoapi.ArgoCDAppUpdate,
+				) *kargoapi.Health {
+					return nil
+				},
+				getVerificationInfoFn: func(
+					_ context.Context,
+					s *kargoapi.Stage,
+				) *kargoapi.VerificationInfo {
+					return s.Status.CurrentFreight.VerificationInfo
+				},
+				abortVerificationFn: func(
+					context.Context,
+					*kargoapi.Stage,
+				) *kargoapi.VerificationInfo {
+					return &kargoapi.VerificationInfo{
+						Phase:   kargoapi.VerificationPhaseAborted,
+						Message: "aborted",
+					}
+				},
+			},
+			assertions: func(
+				_ kargoapi.StageStatus,
+				newStatus kargoapi.StageStatus,
+				err error,
+			) {
+				require.NoError(t, err)
+				require.NotNil(t, newStatus.CurrentFreight)
+				require.Equal(
+					t,
+					&kargoapi.VerificationInfo{
+						Phase:   kargoapi.VerificationPhaseAborted,
+						Message: "aborted",
+					},
+					newStatus.CurrentFreight.VerificationInfo,
+				)
+
+				// Phase should be changed to Steady
+				require.Equal(t, kargoapi.StagePhaseSteady, newStatus.Phase)
+			},
+		},
+
+		{
+			name: "verification abort conditions not met",
+			stage: &kargoapi.Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						kargoapi.AnnotationKeyAbort: "fake-id",
+					},
+				},
+				Spec: &kargoapi.StageSpec{
+					PromotionMechanisms: &kargoapi.PromotionMechanisms{},
+					Verification:        &kargoapi.Verification{},
+				},
+				Status: kargoapi.StageStatus{
+					Phase: kargoapi.StagePhaseVerifying,
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID:    "fake-id",
+							Phase: kargoapi.VerificationPhasePending,
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name: "fake-analysis-run",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				hasNonTerminalPromotionsFn: noNonTerminalPromotionsFn,
+				checkHealthFn: func(
+					context.Context,
+					kargoapi.FreightReference,
+					[]kargoapi.ArgoCDAppUpdate,
+				) *kargoapi.Health {
+					return nil
+				},
+				getVerificationInfoFn: func(
+					_ context.Context,
+					s *kargoapi.Stage,
+				) *kargoapi.VerificationInfo {
+					i := s.Status.CurrentFreight.VerificationInfo.DeepCopy()
+					i.Phase = kargoapi.VerificationPhaseError
+					return i
+				},
+				abortVerificationFn: func(
+					context.Context,
+					*kargoapi.Stage,
+				) *kargoapi.VerificationInfo {
+					// Should not be called
+					return &kargoapi.VerificationInfo{
+						Phase:   kargoapi.VerificationPhaseAborted,
+						Message: "aborted",
+					}
+				},
+			},
+			assertions: func(
+				_ kargoapi.StageStatus,
+				newStatus kargoapi.StageStatus,
+				err error,
+			) {
+				require.NoError(t, err)
+				require.NotNil(t, newStatus.CurrentFreight)
+				require.Equal(t, kargoapi.VerificationPhaseError, newStatus.CurrentFreight.VerificationInfo.Phase)
+			},
+		},
+
 		{
 			name: "error marking Freight as verified in Stage",
 			stage: &kargoapi.Stage{
diff --git a/internal/controller/stages/verification_test.go b/internal/controller/stages/verification_test.go
index d3526a30..244be56d 100644
--- a/internal/controller/stages/verification_test.go
+++ b/internal/controller/stages/verification_test.go
@@ -22,12 +22,12 @@ func TestStartVerification(t *testing.T) {
 		name       string
 		stage      *kargoapi.Stage
 		reconciler *reconciler
-		assertions func(*kargoapi.VerificationInfo)
+		assertions func(*testing.T, *kargoapi.VerificationInfo)
 	}{
 		{
 			name:       "rollouts integration not enabled",
 			reconciler: &reconciler{},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.Contains(
 					t,
 					vi.Message,
@@ -54,13 +54,13 @@ func TestStartVerification(t *testing.T) {
 					return errors.New("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error listing AnalysisRuns for Stage")
 			},
 		},
 		{
-			name: "Analysis run already exists",
+			name: "AnalysisRun already exists",
 			stage: &kargoapi.Stage{
 				Status: kargoapi.StageStatus{
 					CurrentFreight: &kargoapi.FreightReference{
@@ -81,11 +81,86 @@ func TestStartVerification(t *testing.T) {
 					return nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Empty(t, vi.Message)
 			},
 		},
+		{
+			name: "AnalysisRun already exists but reverification is requested",
+			stage: &kargoapi.Stage{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						kargoapi.AnnotationKeyReverify: "fake-id",
+					},
+				},
+				Spec: &kargoapi.StageSpec{
+					Verification: &kargoapi.Verification{
+						AnalysisTemplates: []kargoapi.AnalysisTemplateReference{{}},
+					},
+				},
+				Status: kargoapi.StageStatus{
+					CurrentFreight: &kargoapi.FreightReference{
+						Name: "fake-id",
+					},
+				},
+			},
+			reconciler: &reconciler{
+				rolloutsClient: fake.NewClientBuilder().Build(),
+				listAnalysisRunsFn: func(
+					_ context.Context,
+					objList client.ObjectList,
+					_ ...client.ListOption,
+				) error {
+					analysisRuns, ok := objList.(*rollouts.AnalysisRunList)
+					require.True(t, ok)
+					analysisRuns.Items = []rollouts.AnalysisRun{{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "fake-run",
+						},
+					}}
+					return nil
+				},
+				getAnalysisTemplateFn: func(
+					context.Context,
+					client.Client,
+					types.NamespacedName,
+				) (*rollouts.AnalysisTemplate, error) {
+					return &rollouts.AnalysisTemplate{}, nil
+				},
+				getFreightFn: func(ctx context.Context, c client.Client, name types.NamespacedName) (*kargoapi.Freight, error) {
+					return &kargoapi.Freight{}, nil
+				},
+				buildAnalysisRunFn: func(
+					*kargoapi.Stage,
+					*kargoapi.Freight,
+					[]*rollouts.AnalysisTemplate,
+				) (*rollouts.AnalysisRun, error) {
+					return &rollouts.AnalysisRun{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "new-fake-run",
+							Namespace: "fake-namespace",
+						},
+					}, nil
+				},
+				createAnalysisRunFn: func(
+					context.Context,
+					client.Object,
+					...client.CreateOption,
+				) error {
+					return nil
+				},
+			},
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
+				require.NotNilf(t, vi, "expected non-nil VerificationInfo")
+				require.NotEmptyf(t, vi.ID, "expected non-empty VerificationInfo.ID")
+				require.Equal(t, kargoapi.VerificationPhasePending, vi.Phase)
+				require.Equal(t, &kargoapi.AnalysisRunReference{
+					Name:      "new-fake-run",
+					Namespace: "fake-namespace",
+				}, vi.AnalysisRun)
+			},
+		},
 		{
 			name: "error getting AnalysisTemplate",
 			stage: &kargoapi.Stage{
@@ -117,7 +192,7 @@ func TestStartVerification(t *testing.T) {
 					return nil, errors.New("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error getting AnalysisTemplate")
@@ -154,7 +229,7 @@ func TestStartVerification(t *testing.T) {
 					return nil, nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "AnalysisTemplate")
 				require.Contains(t, vi.Message, "not found")
@@ -198,7 +273,7 @@ func TestStartVerification(t *testing.T) {
 					return nil, fmt.Errorf("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error getting Freight")
@@ -242,7 +317,7 @@ func TestStartVerification(t *testing.T) {
 					return nil, nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "Freight")
 				require.Contains(t, vi.Message, "not found")
@@ -292,7 +367,7 @@ func TestStartVerification(t *testing.T) {
 					return nil, errors.New("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error building AnalysisRun for Stage")
@@ -350,7 +425,7 @@ func TestStartVerification(t *testing.T) {
 					return errors.New("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error creating AnalysisRun")
@@ -409,24 +484,21 @@ func TestStartVerification(t *testing.T) {
 					return nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
-				require.Equal(
-					t,
-					&kargoapi.VerificationInfo{
-						Phase: kargoapi.VerificationPhasePending,
-						AnalysisRun: &kargoapi.AnalysisRunReference{
-							Name:      "fake-run",
-							Namespace: "fake-namespace",
-						},
-					},
-					vi,
-				)
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
+				require.NotNilf(t, vi, "expected non-nil VerificationInfo")
+				require.NotEmptyf(t, vi.ID, "expected non-empty VerificationInfo.ID")
+				require.Equal(t, kargoapi.VerificationPhasePending, vi.Phase)
+				require.Equal(t, &kargoapi.AnalysisRunReference{
+					Name:      "fake-run",
+					Namespace: "fake-namespace",
+				}, vi.AnalysisRun)
 			},
 		},
 	}
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
 			testCase.assertions(
+				t,
 				testCase.reconciler.startVerification(
 					context.Background(),
 					testCase.stage,
@@ -441,12 +513,19 @@ func TestGetVerificationInfo(t *testing.T) {
 		name       string
 		stage      *kargoapi.Stage
 		reconciler *reconciler
-		assertions func(*kargoapi.VerificationInfo)
+		assertions func(*testing.T, *kargoapi.VerificationInfo)
 	}{
 		{
 			name:       "rollouts integration not enabled",
 			reconciler: &reconciler{},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			stage: &kargoapi.Stage{
+				Status: kargoapi.StageStatus{
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{},
+					},
+				},
+			},
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(
 					t,
@@ -479,7 +558,7 @@ func TestGetVerificationInfo(t *testing.T) {
 					return nil, errors.New("something went wrong")
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "something went wrong")
 				require.Contains(t, vi.Message, "error getting AnalysisRun")
@@ -509,7 +588,7 @@ func TestGetVerificationInfo(t *testing.T) {
 					return nil, nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.NotNil(t, vi)
 				require.Contains(t, vi.Message, "AnalysisRun")
 				require.Contains(t, vi.Message, "not found")
@@ -547,7 +626,7 @@ func TestGetVerificationInfo(t *testing.T) {
 					}, nil
 				},
 			},
-			assertions: func(vi *kargoapi.VerificationInfo) {
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
 				require.Equal(
 					t,
 					&kargoapi.VerificationInfo{
@@ -566,6 +645,7 @@ func TestGetVerificationInfo(t *testing.T) {
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
 			testCase.assertions(
+				t,
 				testCase.reconciler.getVerificationInfo(
 					context.Background(),
 					testCase.stage,
@@ -575,6 +655,115 @@ func TestGetVerificationInfo(t *testing.T) {
 	}
 }
 
+func TestAbortVerification(t *testing.T) {
+	testCases := []struct {
+		name       string
+		stage      *kargoapi.Stage
+		reconciler *reconciler
+		assertions func(*testing.T, *kargoapi.VerificationInfo)
+	}{
+		{
+			name:       "rollouts integration not enabled",
+			reconciler: &reconciler{},
+			stage: &kargoapi.Stage{
+				Status: kargoapi.StageStatus{
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID: "fake-id",
+						},
+					},
+				},
+			},
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
+				require.NotNil(t, vi)
+				require.Equal(t, vi.ID, "fake-id")
+				require.Contains(
+					t,
+					vi.Message,
+					"Rollouts integration is disabled on this controller",
+				)
+			},
+		},
+		{
+			name: "error patching AnalysisRun",
+			stage: &kargoapi.Stage{
+				Status: kargoapi.StageStatus{
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID: "fake-id",
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name:      "fake-run",
+								Namespace: "fake-namespace",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				rolloutsClient: fake.NewClientBuilder().Build(),
+				patchAnalysisRunFn: func(
+					context.Context,
+					client.Object,
+					client.Patch,
+					...client.PatchOption,
+				) error {
+					return errors.New("something went wrong")
+				},
+			},
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
+				require.NotNil(t, vi)
+				require.Equal(t, "fake-id", vi.ID)
+				require.Contains(t, vi.Message, "AnalysisRun")
+				require.Contains(t, vi.Message, "something went wrong")
+			},
+		},
+		{
+			name: "success",
+			stage: &kargoapi.Stage{
+				Status: kargoapi.StageStatus{
+					CurrentFreight: &kargoapi.FreightReference{
+						VerificationInfo: &kargoapi.VerificationInfo{
+							ID: "fake-id",
+							AnalysisRun: &kargoapi.AnalysisRunReference{
+								Name:      "fake-run",
+								Namespace: "fake-namespace",
+							},
+						},
+					},
+				},
+			},
+			reconciler: &reconciler{
+				rolloutsClient: fake.NewClientBuilder().Build(),
+				patchAnalysisRunFn: func(
+					context.Context,
+					client.Object,
+					client.Patch,
+					...client.PatchOption,
+				) error {
+					return nil
+				},
+			},
+			assertions: func(t *testing.T, vi *kargoapi.VerificationInfo) {
+				require.NotNil(t, vi)
+				require.Equal(t, "fake-id", vi.ID)
+				require.Equal(t, kargoapi.VerificationPhaseAborted, vi.Phase)
+				require.Equal(t, "Verification aborted by user", vi.Message)
+			},
+		},
+	}
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			testCase.assertions(
+				t,
+				testCase.reconciler.abortVerification(
+					context.Background(),
+					testCase.stage,
+				),
+			)
+		})
+	}
+}
+
 func TestBuildAnalysisRun(t *testing.T) {
 	freight := &kargoapi.Freight{
 		ObjectMeta: metav1.ObjectMeta{
diff --git a/internal/kargo/kargo_test.go b/internal/kargo/kargo_test.go
index 543013f7..4a7550de 100644
--- a/internal/kargo/kargo_test.go
+++ b/internal/kargo/kargo_test.go
@@ -96,7 +96,7 @@ func TestNewPromotion(t *testing.T) {
 	}
 }
 
-func TestIgnoreClearRefreshUpdates(t *testing.T) {
+func TestIgnoreAnnotationRemovalUpdates(t *testing.T) {
 	testCases := []struct {
 		name     string
 		old      client.Object
@@ -110,7 +110,7 @@ func TestIgnoreClearRefreshUpdates(t *testing.T) {
 			expected: true,
 		},
 		{
-			name: "refresh cleared",
+			name: "annotation removed",
 			old: &kargoapi.Stage{
 				ObjectMeta: metav1.ObjectMeta{
 					Annotations: map[string]string{
@@ -126,7 +126,7 @@ func TestIgnoreClearRefreshUpdates(t *testing.T) {
 			expected: false,
 		},
 		{
-			name: "refresh set",
+			name: "annotation set",
 			old: &kargoapi.Stage{
 				ObjectMeta: metav1.ObjectMeta{
 					Annotations: map[string]string{},
@@ -145,12 +145,14 @@ func TestIgnoreClearRefreshUpdates(t *testing.T) {
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			icru := IgnoreClearRefreshUpdates{}
+			p := IgnoreAnnotationRemoval{
+				Annotations: []string{kargoapi.AnnotationKeyRefresh},
+			}
 			e := event.UpdateEvent{
 				ObjectOld: tc.old,
 				ObjectNew: tc.new,
 			}
-			require.Equal(t, tc.expected, icru.Update(e))
+			require.Equal(t, tc.expected, p.Update(e))
 		})
 	}
 }