Repository: akuity/kargo
Pull request #1645 (2024-03-18 12:59:05)

feat(controller): record verification history Stage
Fixes: #1638

This adds a `VerificationHistory` field to the `FreightReference` of a Stage, containing a list of the last 10 verification attempts. Technically, I would say this addition makes the `VerificationInfo` field obsolete. But I kept it for backwards compatibility reasons.

To ensure the AnalysisRun reference for a verification item is always kept around whenever we can (either in the error message, or as `AnalysisRunReference`), aborting an AnalysisRun will now maintain the reference information.

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


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 3dcbcc5974a2ba15a787f69290dc0e4023f679e8 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/docs-kargo-akuity-io/deploys/65f83a9c42d8900008c38f14 |
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/akuity/kargo/pull/1645?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 44.23%. Comparing base [(`1e1e2de`)](https://app.codecov.io/gh/akuity/kargo/commit/1e1e2de97e634d6b1c81554cdd88ea0c6a06df19?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) to head [(`3dcbcc5`)](https://app.codecov.io/gh/akuity/kargo/pull/1645?dropdown=coverage&src=pr&el=desc&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    #1645      +/-   ##
==========================================
+ Coverage   44.14%   44.23%   +0.09%     
==========================================
  Files         199      199              
  Lines       12728    12749      +21     
==========================================
+ Hits         5619     5640      +21     
  Misses       6868     6868              
  Partials      241      241              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/akuity/kargo/pull/1645?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/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go
index 6bf12908..36671953 100644
--- a/api/v1alpha1/generated.pb.go
+++ b/api/v1alpha1/generated.pb.go
@@ -1781,207 +1781,209 @@ func init() {
 }
 
 var fileDescriptor_e26b7f7bbc391025 = []byte{
-	// 3199 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, 0x12, 0x40, 0xe4, 0x42, 0x40, 0x82, 0x43, 0x38,
-	0x21, 0x01, 0x02, 0x71, 0x80, 0x1b, 0x07, 0xc4, 0x81, 0x03, 0x97, 0x88, 0x03, 0x8a, 0x38, 0x40,
-	0x4e, 0x56, 0xb2, 0x88, 0x0b, 0x12, 0xfc, 0x01, 0x96, 0x90, 0x50, 0xfd, 0xe8, 0xee, 0xea, 0x9e,
-	0x9e, 0xdd, 0xee, 0x89, 0x6d, 0x85, 0xdb, 0xec, 0xfb, 0xdd, 0xaf, 0x5e, 0xbd, 0xf7, 0xea, 0x55,
-	0x2d, 0x3c, 0xd6, 0xb1, 0xfc, 0xee, 0x60, 0xa3, 0xda, 0x72, 0xfa, 0x35, 0xb2, 0x35, 0xb0, 0xfc,
-	0x9d, 0xda, 0x16, 0xf1, 0x3a, 0x4e, 0x8d, 0xb8, 0x56, 0x6d, 0xfb, 0x24, 0xe9, 0xb9, 0x5d, 0x72,
-	0xb2, 0xd6, 0xa1, 0x36, 0xf5, 0x88, 0x4f, 0xdb, 0x55, 0xd7, 0x73, 0x7c, 0x07, 0xdd, 0x1f, 0x71,
-	0x55, 0x25, 0x57, 0x55, 0x70, 0x55, 0x89, 0x6b, 0x55, 0x03, 0xae, 0xa5, 0x47, 0x35, 0xd9, 0x1d,
-	0xa7, 0xe3, 0xd4, 0x04, 0xf3, 0xc6, 0x60, 0x53, 0xfc, 0x25, 0xfe, 0x10, 0xbf, 0xa4, 0xd0, 0xa5,
-	0xc7, 0xb6, 0xce, 0xb0, 0xaa, 0x25, 0x34, 0xf7, 0x49, 0xab, 0x6b, 0xd9, 0xd4, 0xdb, 0xa9, 0xb9,
-	0x5b, 0x1d, 0x0e, 0x60, 0xb5, 0x3e, 0xf5, 0x49, 0x6d, 0x7b, 0xc8, 0x94, 0xa5, 0xda, 0x28, 0x2e,
-	0x6f, 0x60, 0xfb, 0x56, 0x9f, 0x0e, 0x31, 0x3c, 0xbe, 0x1f, 0x03, 0x6b, 0x75, 0x69, 0x9f, 0x24,
-	0xf9, 0xcc, 0xd7, 0xe0, 0x70, 0xdd, 0x26, 0xbd, 0x1d, 0x66, 0x31, 0x3c, 0xb0, 0xeb, 0x5e, 0x67,
-	0xd0, 0xa7, 0xb6, 0x8f, 0x4e, 0x40, 0xc9, 0x26, 0x7d, 0xba, 0x68, 0x9c, 0x30, 0x1e, 0xac, 0x34,
-	0x0e, 0x7d, 0x70, 0xf3, 0xf8, 0x81, 0xdd, 0x9b, 0xc7, 0x4b, 0x57, 0x48, 0x9f, 0x62, 0x81, 0x41,
-	0xff, 0x0d, 0x07, 0xb7, 0x49, 0x6f, 0x40, 0x17, 0x0b, 0x82, 0x64, 0x5a, 0x91, 0x1c, 0xbc, 0xce,
-	0x81, 0x58, 0xe2, 0xcc, 0x6f, 0x14, 0x63, 0xe2, 0x2f, 0x53, 0x9f, 0xb4, 0x89, 0x4f, 0x50, 0x1f,
-	0xca, 0x3d, 0xb2, 0x41, 0x7b, 0x6c, 0xd1, 0x38, 0x51, 0x7c, 0x70, 0xea, 0xd4, 0x73, 0xd5, 0x2c,
-	0xae, 0xaf, 0xa6, 0x88, 0xaa, 0x5e, 0x12, 0x72, 0x9e, 0xb3, 0x7d, 0x6f, 0xa7, 0x31, 0xa3, 0x8c,
-	0x28, 0x4b, 0x20, 0x56, 0x4a, 0xd0, 0xdb, 0x06, 0x4c, 0x11, 0xdb, 0x76, 0x7c, 0xe2, 0x5b, 0x8e,
-	0xcd, 0x16, 0x0b, 0x42, 0xe9, 0xf3, 0xe3, 0x2b, 0xad, 0x47, 0xc2, 0xa4, 0xe6, 0xc3, 0x4a, 0xf3,
-	0x94, 0x86, 0xc1, 0xba, 0xce, 0xa5, 0x27, 0x61, 0x4a, 0x33, 0x15, 0xcd, 0x41, 0x71, 0x8b, 0xee,
-	0x48, 0xff, 0x62, 0xfe, 0x13, 0x2d, 0xc4, 0x1c, 0xaa, 0x3c, 0x78, 0xb6, 0x70, 0xc6, 0x58, 0x7a,
-	0x06, 0xe6, 0x92, 0x0a, 0xf3, 0xf0, 0x9b, 0xef, 0x19, 0xb0, 0xa0, 0x7d, 0x05, 0xa6, 0x9b, 0xd4,
-	0xa3, 0x76, 0x8b, 0xa2, 0x1a, 0x54, 0xf8, 0x5a, 0x32, 0x97, 0xb4, 0x82, 0xa5, 0x9e, 0x57, 0x1f,
-	0x52, 0xb9, 0x12, 0x20, 0x70, 0x44, 0x13, 0x86, 0x45, 0x61, 0xaf, 0xb0, 0x70, 0xbb, 0x84, 0xd1,
-	0xc5, 0x62, 0x3c, 0x2c, 0x9a, 0x1c, 0x88, 0x25, 0xce, 0xfc, 0x3f, 0xb8, 0x37, 0xb0, 0xe7, 0x2a,
-	0xed, 0xbb, 0x3d, 0xe2, 0xd3, 0xc8, 0xa8, 0x7d, 0x43, 0xcf, 0x9c, 0x85, 0xe9, 0xba, 0xeb, 0x7a,
-	0xce, 0x36, 0x6d, 0xaf, 0xfb, 0xa4, 0x43, 0xcd, 0x77, 0x0c, 0x38, 0x52, 0xf7, 0x3a, 0xce, 0xea,
-	0xb9, 0xba, 0xeb, 0x5e, 0xa4, 0xa4, 0xe7, 0x77, 0xd7, 0x7d, 0xe2, 0x0f, 0x18, 0x7a, 0x06, 0xca,
-	0x4c, 0xfc, 0x52, 0xe2, 0x1e, 0x08, 0x22, 0x44, 0xe2, 0x6f, 0xdd, 0x3c, 0xbe, 0x90, 0xc2, 0x48,
-	0xb1, 0xe2, 0x42, 0x0f, 0xc1, 0x44, 0x9f, 0x32, 0x46, 0x3a, 0xc1, 0x37, 0xcf, 0x2a, 0x01, 0x13,
-	0x97, 0x25, 0x18, 0x07, 0x78, 0xf3, 0x0f, 0x05, 0x98, 0x0d, 0x65, 0x29, 0xf5, 0x77, 0xc0, 0xc1,
-	0x03, 0x38, 0xd4, 0xd5, 0xbe, 0x50, 0xf8, 0x79, 0xea, 0xd4, 0x53, 0x19, 0x63, 0x39, 0xcd, 0x49,
-	0x8d, 0x05, 0xa5, 0xe6, 0x90, 0x0e, 0xc5, 0x31, 0x35, 0xa8, 0x0f, 0xc0, 0x76, 0xec, 0x96, 0x52,
-	0x5a, 0x12, 0x4a, 0x9f, 0xcc, 0xa9, 0x74, 0x3d, 0x14, 0xd0, 0x40, 0x4a, 0x25, 0x44, 0x30, 0xac,
-	0x29, 0x30, 0x7f, 0x65, 0xc0, 0xe1, 0x14, 0x3e, 0xf4, 0x74, 0x62, 0x3d, 0xef, 0x1f, 0x5a, 0x4f,
-	0x34, 0xc4, 0x16, 0xad, 0xe6, 0x23, 0x30, 0xe9, 0xd1, 0x6d, 0x8b, 0x59, 0x8e, 0xad, 0x3c, 0x3c,
-	0xa7, 0xf8, 0x27, 0xb1, 0x82, 0xe3, 0x90, 0x02, 0x3d, 0x0c, 0x95, 0xe0, 0x37, 0x77, 0x73, 0x91,
-	0x87, 0x33, 0x5f, 0xb8, 0x80, 0x94, 0xe1, 0x08, 0x6f, 0xfe, 0xc3, 0xd0, 0x56, 0xff, 0x9a, 0xdb,
-	0x26, 0x3e, 0xe5, 0xc1, 0x43, 0x5c, 0xf7, 0x4a, 0x14, 0xcc, 0x61, 0xf0, 0xd4, 0x25, 0x18, 0x07,
-	0x78, 0x74, 0x06, 0x0e, 0xa9, 0x9f, 0x32, 0x56, 0xa4, 0x75, 0xe1, 0xc2, 0xd4, 0x35, 0x1c, 0x8e,
-	0x51, 0xa2, 0x01, 0x4c, 0x33, 0x67, 0xe0, 0xb5, 0xa8, 0x54, 0x2a, 0x2d, 0x9d, 0x3a, 0x75, 0x26,
-	0xcf, 0xda, 0xac, 0x6b, 0x02, 0x1a, 0x47, 0x94, 0xd2, 0x69, 0x1d, 0xca, 0x70, 0x5c, 0x8b, 0xf9,
-	0x26, 0x80, 0xe4, 0xbd, 0x48, 0x7b, 0x7d, 0xd4, 0x82, 0xb2, 0xd5, 0x27, 0x1d, 0x1a, 0xe4, 0xf3,
-	0x5c, 0xe1, 0xc8, 0x25, 0xac, 0x71, 0x6e, 0x65, 0x40, 0x98, 0xc5, 0x05, 0x90, 0x61, 0x25, 0xda,
-	0x7c, 0x3f, 0xdc, 0xe5, 0x09, 0x0e, 0x9e, 0x74, 0x04, 0x8d, 0x72, 0x73, 0x98, 0x74, 0x04, 0x0d,
-	0x96, 0x38, 0x74, 0x4c, 0x66, 0x4c, 0xe9, 0xd9, 0x29, 0x45, 0x52, 0x7c, 0x81, 0xee, 0xc8, 0xf4,
-	0xf9, 0x54, 0x90, 0x3e, 0x65, 0xe2, 0xfa, 0x9f, 0x58, 0x3d, 0xe3, 0x79, 0x42, 0x53, 0x28, 0x60,
-	0x57, 0x77, 0xdc, 0xb0, 0xce, 0xbd, 0x15, 0x2c, 0xfe, 0x0b, 0x03, 0xe6, 0x3b, 0x7d, 0xeb, 0xcb,
-	0x14, 0x75, 0x13, 0x2e, 0xf9, 0xff, 0x3c, 0x2e, 0x09, 0xc5, 0x64, 0xf1, 0x8b, 0x07, 0x4b, 0xa3,
-	0xb9, 0xb2, 0xf9, 0xa6, 0x06, 0x95, 0x01, 0xa3, 0xe7, 0xac, 0x0e, 0x65, 0xbe, 0xf0, 0xd0, 0x64,
-	0x94, 0xa7, 0xae, 0x05, 0x08, 0x1c, 0xd1, 0x98, 0x7f, 0x2f, 0x00, 0x1a, 0x8e, 0x1d, 0x1e, 0xf1,
-	0x1e, 0x75, 0x9d, 0x6b, 0xf8, 0x52, 0x32, 0xe2, 0xb1, 0x04, 0xe3, 0x00, 0xcf, 0xed, 0x6a, 0x75,
-	0x89, 0xe7, 0x27, 0xfb, 0x87, 0x55, 0x0e, 0xc4, 0x12, 0x87, 0x9a, 0xb0, 0x30, 0x10, 0x92, 0xaf,
-	0x12, 0xaf, 0x43, 0xfd, 0x60, 0xe7, 0x89, 0x35, 0x9a, 0x6c, 0xfc, 0x97, 0xe2, 0x59, 0xb8, 0x96,
-	0x42, 0x83, 0x53, 0x39, 0xd1, 0x06, 0x54, 0xb6, 0x02, 0x37, 0xa9, 0x34, 0xb6, 0x32, 0xd6, 0xca,
-	0xc8, 0x5c, 0x10, 0xfe, 0x89, 0x23, 0xb1, 0xe8, 0x0a, 0x94, 0xba, 0xb4, 0xd7, 0x5f, 0x3c, 0x28,
-	0xc4, 0xff, 0x6f, 0xde, 0xbd, 0xd0, 0x98, 0xe4, 0x29, 0x9f, 0xff, 0xc2, 0x42, 0x8e, 0xf9, 0x35,
-	0x90, 0x5e, 0xc9, 0xe3, 0xde, 0xfd, 0x0b, 0xc9, 0x43, 0x30, 0xb1, 0x4d, 0xbd, 0xd0, 0x9d, 0x9a,
-	0xb0, 0xeb, 0x12, 0x8c, 0x03, 0xbc, 0xf9, 0x33, 0x03, 0xe6, 0x85, 0x05, 0xeb, 0x83, 0x0d, 0xd6,
-	0xf2, 0x2c, 0x97, 0x37, 0x22, 0xb7, 0xd7, 0x9a, 0x73, 0x30, 0xc7, 0x68, 0x7f, 0x9b, 0x7a, 0xab,
-	0x8e, 0xcd, 0x7c, 0x8f, 0x58, 0xb6, 0xaf, 0xcc, 0x5a, 0x54, 0xd4, 0x73, 0xeb, 0x09, 0x3c, 0x1e,
-	0xe2, 0x30, 0x7f, 0x5a, 0x82, 0x89, 0xf3, 0x1e, 0xb5, 0x3a, 0x5d, 0x1f, 0x7d, 0x11, 0x26, 0xfb,
-	0xaa, 0x5f, 0x13, 0xf6, 0xf1, 0x95, 0x90, 0x4d, 0x72, 0x55, 0x6f, 0x92, 0xab, 0xee, 0x56, 0x87,
-	0x03, 0x58, 0x95, 0x53, 0x57, 0xb7, 0x4f, 0x56, 0x5f, 0xdc, 0x78, 0x83, 0xb6, 0x7c, 0xde, 0xeb,
-	0x45, 0x65, 0x2a, 0x82, 0xe1, 0x50, 0x2a, 0x0f, 0x61, 0xd2, 0xb3, 0x08, 0x5b, 0x9c, 0x88, 0x87,
-	0x70, 0x9d, 0x03, 0xb1, 0xc4, 0xf1, 0xad, 0x75, 0x83, 0x78, 0xb4, 0xeb, 0x0c, 0x18, 0x5d, 0x9c,
-	0x8c, 0xb7, 0x00, 0x2f, 0x05, 0x08, 0x1c, 0xd1, 0xa0, 0x57, 0x60, 0xa2, 0xe5, 0xf4, 0xfb, 0x96,
-	0x1f, 0xa4, 0xf2, 0x5a, 0xb6, 0x00, 0xba, 0x60, 0xf9, 0xab, 0x82, 0x2f, 0x5a, 0x07, 0xf9, 0x37,
-	0xc3, 0x81, 0x40, 0xb4, 0x1e, 0x26, 0xa5, 0x92, 0x10, 0xfd, 0x70, 0x36, 0xd1, 0x22, 0x57, 0x8c,
-	0xca, 0x3f, 0x5c, 0xa8, 0xd8, 0xad, 0x6c, 0xf1, 0x60, 0x1e, 0xa1, 0x22, 0xa0, 0x22, 0xa1, 0xe2,
-	0x4f, 0x86, 0x95, 0x28, 0xf4, 0x6a, 0x58, 0xe8, 0xcb, 0x62, 0xed, 0x4e, 0x67, 0x13, 0xaa, 0x16,
-	0x5f, 0x75, 0x19, 0x33, 0xf1, 0xee, 0x20, 0xe8, 0x03, 0xcc, 0xdf, 0x19, 0x30, 0xa5, 0x28, 0x2f,
-	0x59, 0xcc, 0x47, 0xaf, 0x0d, 0x85, 0x4a, 0x35, 0x5b, 0xa8, 0x70, 0x6e, 0x11, 0x28, 0x61, 0x1f,
-	0x11, 0x40, 0xb4, 0x30, 0xc1, 0x70, 0xd0, 0xf2, 0x69, 0x3f, 0x38, 0x76, 0x3c, 0x9a, 0xeb, 0x4b,
-	0xb4, 0x84, 0xcd, 0x65, 0x60, 0x29, 0xca, 0xfc, 0x5b, 0x11, 0xe6, 0x14, 0x45, 0x8e, 0xce, 0x39,
-	0x1e, 0x8c, 0xe5, 0x7c, 0xc1, 0x58, 0xb8, 0x73, 0xc1, 0x58, 0xbc, 0x13, 0xc1, 0x58, 0xba, 0x7d,
-	0xc1, 0xf8, 0x25, 0x98, 0xdb, 0xa6, 0x9e, 0xb5, 0x69, 0xb5, 0xc4, 0x11, 0x6c, 0xcd, 0xde, 0x74,
-	0x54, 0x72, 0x7f, 0x3c, 0x9b, 0xf8, 0xeb, 0x09, 0xee, 0xc6, 0x02, 0x4f, 0x68, 0x49, 0x28, 0x1e,
-	0xd2, 0x62, 0xfe, 0xb3, 0x08, 0xd3, 0xb1, 0x98, 0x46, 0x37, 0x00, 0x24, 0x15, 0x6d, 0xaf, 0xd9,
-	0xaa, 0xb7, 0x58, 0x1d, 0x63, 0x73, 0x28, 0x9b, 0xb8, 0x14, 0x79, 0x84, 0x0d, 0x73, 0x5d, 0x84,
-	0xc0, 0x9a, 0x2a, 0xf4, 0x16, 0x4c, 0x11, 0x75, 0xea, 0x3a, 0xef, 0x78, 0x2a, 0x1c, 0xce, 0x8d,
-	0xa3, 0xb9, 0x1e, 0x89, 0x49, 0x9e, 0x9e, 0x23, 0x0c, 0xd6, 0xb5, 0x2d, 0x79, 0x30, 0x9b, 0xb0,
-	0x37, 0xe5, 0x04, 0xbc, 0xa6, 0x9f, 0x80, 0x33, 0xa7, 0x8c, 0x40, 0xae, 0x38, 0x4a, 0xea, 0xc7,
-	0x6e, 0x06, 0x73, 0x49, 0x4b, 0x6f, 0x9b, 0xd2, 0xd8, 0xf9, 0x55, 0x3f, 0xab, 0xff, 0xba, 0x00,
-	0x95, 0x70, 0xf3, 0xe4, 0x29, 0xb1, 0x4b, 0x50, 0xb0, 0xda, 0xaa, 0xc0, 0x82, 0xa2, 0x2a, 0xac,
-	0x9d, 0xc3, 0x05, 0xab, 0x8d, 0x1e, 0x80, 0xf2, 0x86, 0x47, 0xec, 0x56, 0x57, 0x95, 0xd4, 0x30,
-	0xce, 0x1b, 0x02, 0x8a, 0x15, 0x96, 0xb7, 0xc8, 0x3e, 0xe9, 0x88, 0xb6, 0x48, 0x6b, 0x91, 0xaf,
-	0x92, 0x0e, 0xe6, 0x70, 0x74, 0x01, 0xe6, 0xe5, 0x99, 0x70, 0xb5, 0x4b, 0x5b, 0x5b, 0xd2, 0x44,
-	0xb1, 0x0f, 0x2a, 0x8d, 0x7b, 0x15, 0xf1, 0xfc, 0xc5, 0x24, 0x01, 0x1e, 0xe6, 0xd1, 0x4f, 0xd5,
-	0xe5, 0xbd, 0x4f, 0xd5, 0xdc, 0x74, 0x32, 0xf0, 0xbb, 0x8e, 0xa7, 0x8a, 0x6c, 0x68, 0x7a, 0x5d,
-	0x40, 0xb1, 0xc2, 0x9a, 0x87, 0x61, 0xfe, 0x82, 0xe5, 0x5f, 0x1c, 0x6c, 0x34, 0x07, 0xbd, 0x1e,
-	0xa6, 0x6f, 0x0e, 0x78, 0x97, 0xfa, 0xf3, 0x83, 0x30, 0x7d, 0xc1, 0xf2, 0x85, 0xaf, 0x72, 0x37,
-	0xa8, 0xeb, 0x70, 0xc4, 0xb2, 0x19, 0x6d, 0x0d, 0x3c, 0xba, 0xbe, 0x65, 0xb9, 0x57, 0x2f, 0xad,
-	0x8b, 0x48, 0xd9, 0x51, 0xfd, 0xf1, 0x31, 0xc5, 0x78, 0x64, 0x2d, 0x8d, 0x08, 0xa7, 0xf3, 0xa2,
-	0x53, 0x00, 0x1e, 0x25, 0xed, 0x86, 0xbe, 0x1a, 0xe1, 0xc6, 0xc3, 0x21, 0x06, 0x6b, 0x54, 0x68,
-	0x05, 0xa6, 0x6e, 0x78, 0x96, 0x4f, 0x15, 0x93, 0x5c, 0x9d, 0x70, 0xcb, 0xbc, 0x14, 0xa1, 0xb0,
-	0x4e, 0x87, 0xb6, 0x61, 0xca, 0x8d, 0x7c, 0xa1, 0xf2, 0x55, 0xc6, 0x4c, 0xa1, 0x39, 0xb1, 0xe9,
-	0x39, 0x7d, 0x87, 0xe7, 0xa3, 0xcb, 0xb4, 0xd5, 0x25, 0xb6, 0xc5, 0xfa, 0x8d, 0x59, 0xae, 0x57,
-	0x23, 0xc1, 0xba, 0x22, 0xd4, 0x81, 0xb2, 0x47, 0xed, 0x36, 0xf5, 0x54, 0xe5, 0xce, 0xa8, 0xf2,
-	0x05, 0x0e, 0xc2, 0x82, 0x31, 0x45, 0x25, 0xf0, 0x25, 0x97, 0x58, 0xac, 0xc4, 0x23, 0x5b, 0x6f,
-	0xe5, 0x27, 0x84, 0xae, 0x7a, 0x46, 0x5d, 0x01, 0x5b, 0x8a, 0xa6, 0xd1, 0x6d, 0xfd, 0x2b, 0xaa,
-	0xad, 0x9f, 0x14, 0xaa, 0x9e, 0xce, 0xa6, 0x8a, 0xb7, 0xf1, 0x29, 0x5a, 0x92, 0x2d, 0xfe, 0x9f,
-	0x8b, 0x30, 0x7b, 0xc1, 0x1a, 0xbb, 0xbf, 0xf6, 0xe1, 0x1e, 0x59, 0x55, 0xd7, 0x69, 0x8f, 0xb6,
-	0x38, 0xf7, 0xba, 0xef, 0x11, 0x9f, 0x76, 0x82, 0xf3, 0xee, 0x59, 0xc5, 0x7a, 0xcf, 0x6a, 0x3a,
-	0xd9, 0xad, 0xd1, 0x28, 0x3c, 0x4a, 0x74, 0xe6, 0xb4, 0x92, 0xd6, 0xdb, 0x97, 0xf2, 0xf6, 0xf6,
-	0xbc, 0x77, 0x21, 0xbd, 0x9e, 0x73, 0xe3, 0x2a, 0xe9, 0x30, 0x95, 0x75, 0xc2, 0xde, 0xa5, 0x1e,
-	0x20, 0x70, 0x44, 0x83, 0xaa, 0x00, 0x56, 0xc7, 0x76, 0x3c, 0x2a, 0x38, 0xca, 0x62, 0x80, 0x33,
-	0xc3, 0xf7, 0xd9, 0x5a, 0x08, 0xc5, 0x1a, 0xc5, 0xe8, 0x0d, 0x3f, 0x31, 0xfe, 0x86, 0x37, 0xff,
-	0x68, 0x40, 0x59, 0xe6, 0x44, 0xb4, 0x92, 0x98, 0x5d, 0x1d, 0x1b, 0x9a, 0x5d, 0x4d, 0xa5, 0x8d,
-	0x20, 0x4d, 0x28, 0x5b, 0x8c, 0x0d, 0xa8, 0xec, 0xc0, 0x2a, 0x72, 0x2b, 0xac, 0x09, 0x08, 0x56,
-	0x18, 0x64, 0x01, 0x90, 0x60, 0xf8, 0x14, 0xb4, 0x53, 0x2b, 0x79, 0xa7, 0x73, 0x89, 0xc9, 0x5c,
-	0x88, 0x60, 0x58, 0x13, 0x6e, 0xfe, 0xd8, 0x80, 0x7b, 0x79, 0xe0, 0x8a, 0x16, 0xe9, 0x1c, 0x75,
-	0xf9, 0x5e, 0xb4, 0x5b, 0x3b, 0x2a, 0xbf, 0x8a, 0xfc, 0xe6, 0x3a, 0xcc, 0xf2, 0x1d, 0x4f, 0x95,
-	0x49, 0x3d, 0xbf, 0x05, 0x18, 0xac, 0x51, 0x65, 0x38, 0x1c, 0xd6, 0xa0, 0x22, 0x3a, 0xb1, 0x26,
-	0xf1, 0x83, 0x58, 0x0b, 0x97, 0x7e, 0x35, 0x40, 0xe0, 0x88, 0xc6, 0xfc, 0x93, 0x01, 0xb3, 0x63,
-	0x0d, 0x89, 0x9e, 0x81, 0x19, 0x51, 0x8b, 0xd9, 0x79, 0xab, 0x47, 0x85, 0x3a, 0x69, 0xd5, 0x51,
-	0x45, 0x3d, 0x73, 0x3d, 0x86, 0xc5, 0x09, 0xea, 0x60, 0xc8, 0x54, 0xdc, 0x6f, 0xc8, 0x54, 0x1a,
-	0x63, 0xc8, 0xf4, 0xb1, 0x01, 0x47, 0xd3, 0xd3, 0x09, 0x7a, 0x3d, 0x31, 0x6c, 0x5a, 0xc9, 0x9e,
-	0x9c, 0x32, 0x4c, 0x98, 0x78, 0x4a, 0x57, 0x4d, 0xb5, 0xec, 0xfa, 0x9e, 0xcd, 0x2e, 0x3e, 0x35,
-	0x4c, 0x46, 0x35, 0xda, 0xe6, 0x2f, 0x0d, 0x90, 0xeb, 0x91, 0x27, 0xf9, 0x9d, 0x02, 0xe8, 0xa8,
-	0x22, 0x8f, 0x2f, 0xa9, 0xf5, 0x0a, 0x63, 0xee, 0x42, 0x88, 0xc1, 0x1a, 0x55, 0xd0, 0xe9, 0x14,
-	0x47, 0x74, 0x3a, 0x0f, 0x40, 0xb9, 0x2d, 0x87, 0x61, 0xa5, 0x78, 0x66, 0x53, 0x93, 0x30, 0x85,
-	0x35, 0xdf, 0x2b, 0xc1, 0xbc, 0xb0, 0x77, 0xdc, 0xc4, 0x3d, 0x8e, 0xed, 0x2e, 0x1c, 0x15, 0xeb,
-	0x32, 0x9c, 0xeb, 0xe5, 0xe7, 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, 0xc7, 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, 0x0e, 0x3d, 0x99, 0xb1, 0xd1, 0x97, 0xe6, 0xad, 0xbb, 0xb4,
-	0x25, 0x7b, 0x52, 0xfe, 0x0b, 0x0b, 0x41, 0xda, 0x08, 0xae, 0x98, 0xe7, 0x68, 0x1b, 0x88, 0xdc,
-	0x7f, 0x04, 0xa7, 0x28, 0x3f, 0xb3, 0x23, 0x38, 0x65, 0xdf, 0x88, 0x11, 0xdc, 0x77, 0xa2, 0x2f,
-	0xe0, 0x4e, 0x43, 0x5f, 0x85, 0x79, 0x37, 0x88, 0xb3, 0xa6, 0xd3, 0xb3, 0x5a, 0x56, 0xde, 0x72,
-	0xdc, 0x8c, 0xb1, 0xef, 0x44, 0x87, 0xea, 0x66, 0x52, 0x2e, 0x1e, 0x56, 0x65, 0x3a, 0x30, 0x1d,
-	0x73, 0x3d, 0x3a, 0x1d, 0x5c, 0xc5, 0xc7, 0xdb, 0x4d, 0x79, 0x15, 0x7f, 0xeb, 0xe6, 0xf1, 0x43,
-	0x8a, 0x5c, 0xbf, 0x9a, 0xcf, 0x73, 0xe1, 0xfd, 0xa3, 0x02, 0x54, 0x42, 0xcb, 0xee, 0x42, 0x80,
-	0x7f, 0x2e, 0x16, 0xe0, 0xa7, 0x73, 0xfa, 0x34, 0x35, 0xc4, 0x5f, 0x4f, 0x84, 0x78, 0xde, 0x85,
-	0xda, 0x27, 0xc8, 0x7f, 0x60, 0x88, 0x35, 0x91, 0xb4, 0x6b, 0xf6, 0xa6, 0x93, 0x61, 0x44, 0x4b,
-	0x60, 0x62, 0x53, 0x4e, 0xcb, 0xd4, 0x87, 0x3e, 0x9e, 0x6b, 0xc4, 0x16, 0x4e, 0x83, 0xa3, 0x85,
-	0x0b, 0x30, 0x81, 0x5c, 0xf3, 0xf7, 0xba, 0x59, 0x77, 0x61, 0xf7, 0x5d, 0x8d, 0xef, 0xbe, 0x5a,
-	0x4e, 0x27, 0x8f, 0xd8, 0x7f, 0xdf, 0x2e, 0xc0, 0xe1, 0xe1, 0xc4, 0xce, 0x10, 0x83, 0x99, 0x8e,
-	0x3e, 0xf3, 0x09, 0x36, 0xe1, 0xe9, 0xcc, 0x93, 0xeb, 0x88, 0x37, 0xea, 0xfb, 0x63, 0x60, 0x86,
-	0x13, 0x2a, 0xd0, 0x5b, 0x30, 0x47, 0xe2, 0xb7, 0xff, 0xc1, 0xd7, 0xe6, 0x3d, 0x86, 0x29, 0xc5,
-	0x61, 0x63, 0x95, 0x40, 0x30, 0x3c, 0xa4, 0xc8, 0x7c, 0xd7, 0x80, 0xd9, 0x44, 0xee, 0xe0, 0x75,
-	0x97, 0xf9, 0x29, 0x75, 0x57, 0x0d, 0x1c, 0x05, 0x0e, 0x35, 0x61, 0x81, 0x0c, 0x7c, 0x27, 0xe4,
-	0x7d, 0xce, 0x26, 0x1b, 0x3d, 0xda, 0x56, 0x9d, 0x47, 0x78, 0xbd, 0x5a, 0x4f, 0xa1, 0xc1, 0xa9,
-	0x9c, 0xe6, 0x17, 0xb4, 0xc8, 0x12, 0x59, 0x31, 0x93, 0x1d, 0x0f, 0xc5, 0x63, 0xbe, 0xb2, 0x47,
-	0xec, 0xfe, 0xa4, 0xa0, 0x7d, 0xab, 0x4a, 0x74, 0x2b, 0xf1, 0x44, 0x77, 0x3c, 0x99, 0xe8, 0x66,
-	0x22, 0xe7, 0x8c, 0x97, 0xea, 0xd0, 0x9b, 0xda, 0xfe, 0x28, 0xe6, 0x19, 0xb9, 0x27, 0x4c, 0xad,
-	0x06, 0x2f, 0xc8, 0xe4, 0xdc, 0x3b, 0xdc, 0x34, 0x01, 0x38, 0xda, 0x34, 0x4b, 0x4f, 0xc1, 0x74,
-	0x8c, 0x38, 0xd7, 0x8b, 0xaf, 0xaf, 0xc0, 0xb1, 0x3d, 0x47, 0x78, 0xbc, 0xb6, 0x4b, 0xfb, 0xd5,
-	0x76, 0x7f, 0x22, 0xf3, 0xe6, 0x88, 0x8f, 0x58, 0xe5, 0x34, 0x42, 0x82, 0xb1, 0x12, 0x69, 0xbe,
-	0x5f, 0x80, 0x39, 0xbe, 0x39, 0x62, 0x87, 0xa2, 0x26, 0x14, 0x3b, 0x96, 0xaf, 0xd4, 0xad, 0x64,
-	0x56, 0xa7, 0xcb, 0x68, 0x4c, 0xf0, 0x43, 0x1a, 0xdf, 0x89, 0x5c, 0x14, 0x7a, 0x39, 0x68, 0x2d,
-	0x0b, 0x79, 0x3e, 0x61, 0xe8, 0xb8, 0xd6, 0xa8, 0x0c, 0xf5, 0xa3, 0x2f, 0x07, 0x6f, 0x13, 0x8a,
-	0x79, 0x24, 0x0f, 0xdd, 0x90, 0x4b, 0xc9, 0xfa, 0x83, 0x06, 0xf3, 0xfb, 0x05, 0x90, 0xa1, 0x7f,
-	0x17, 0xea, 0xe5, 0xe5, 0x58, 0xbd, 0xcc, 0x98, 0x75, 0x85, 0x71, 0xa9, 0xb5, 0xf2, 0xf3, 0x89,
-	0x5a, 0x79, 0x32, 0x8f, 0xc0, 0xbd, 0xeb, 0xe4, 0x6f, 0x0d, 0xa8, 0x08, 0xba, 0xbb, 0x50, 0x8c,
-	0x9a, 0xf1, 0x62, 0xf4, 0x70, 0x8e, 0xaf, 0x18, 0x51, 0x88, 0xbe, 0x5b, 0x54, 0xd6, 0x87, 0x09,
-	0xaf, 0x4b, 0xbc, 0xb6, 0x3a, 0x20, 0x47, 0x09, 0x8f, 0x03, 0xb1, 0xc4, 0xa1, 0x1e, 0x4c, 0x33,
-	0x2d, 0x50, 0x98, 0xfa, 0xce, 0x8c, 0x25, 0x4a, 0x8f, 0x31, 0xd6, 0x98, 0x17, 0x6f, 0xb5, 0x74,
-	0x10, 0x8e, 0x0b, 0x47, 0xdf, 0x34, 0xe0, 0xb0, 0x3b, 0x5c, 0x29, 0x55, 0x60, 0x3c, 0x99, 0x33,
-	0x93, 0x45, 0x02, 0x1a, 0xf7, 0xec, 0xde, 0x3c, 0x9e, 0x56, 0x83, 0x71, 0x9a, 0x3a, 0xd4, 0x85,
-	0x43, 0xfa, 0xfd, 0xa6, 0x0a, 0xa3, 0x53, 0xf9, 0x6f, 0x50, 0x1b, 0x73, 0xbb, 0x37, 0x8f, 0x1f,
-	0xd2, 0x21, 0x38, 0x26, 0xd9, 0xfc, 0x4b, 0x09, 0xa6, 0xb4, 0xb8, 0x43, 0x27, 0xe3, 0x05, 0xe2,
-	0xbe, 0x64, 0x81, 0x00, 0x41, 0x1c, 0x2b, 0x0e, 0x1e, 0xcc, 0xb4, 0x06, 0x9e, 0x47, 0x6d, 0xff,
-	0xfc, 0x6d, 0xe9, 0xc6, 0x10, 0x6f, 0x22, 0x56, 0x63, 0x12, 0x71, 0x42, 0x03, 0x6f, 0xfd, 0xba,
-	0x16, 0x13, 0x93, 0x53, 0x59, 0x64, 0x3e, 0x75, 0xeb, 0x77, 0x51, 0x8a, 0xc3, 0x81, 0x5c, 0xd4,
-	0x84, 0xb2, 0xbc, 0x8e, 0x53, 0xb7, 0x18, 0x8f, 0x64, 0x9d, 0xe4, 0x71, 0x1e, 0x99, 0xec, 0xe5,
-	0x6f, 0xac, 0xe4, 0xe8, 0x55, 0xb4, 0xb2, 0x4f, 0x15, 0x7d, 0x1e, 0x90, 0xb3, 0xc1, 0xa8, 0xb7,
-	0x4d, 0xdb, 0x17, 0xe4, 0x33, 0x74, 0x1e, 0x06, 0xe5, 0x13, 0xc6, 0x83, 0xc5, 0xc6, 0x92, 0xe2,
-	0x42, 0x2f, 0x0e, 0x51, 0xe0, 0x14, 0x2e, 0x34, 0x80, 0x39, 0xe5, 0xbd, 0x30, 0xfe, 0xd4, 0x1d,
-	0x50, 0xde, 0x83, 0x41, 0x74, 0x1f, 0xbf, 0x9a, 0x10, 0x88, 0x87, 0x54, 0x98, 0x2b, 0x30, 0x2f,
-	0x03, 0x4b, 0x2f, 0x6d, 0xfb, 0xbf, 0x58, 0xfe, 0x8d, 0x01, 0xf1, 0x2d, 0x1a, 0x7f, 0x89, 0x61,
-	0x64, 0x78, 0x89, 0x71, 0x03, 0x66, 0x06, 0x2e, 0xf3, 0x3d, 0x4a, 0xfa, 0xc2, 0x82, 0x20, 0x81,
-	0x3d, 0x91, 0x27, 0x0d, 0xeb, 0xc5, 0x29, 0x6c, 0x6d, 0xaf, 0xc5, 0xc4, 0xe2, 0x84, 0x1a, 0xf3,
-	0x5f, 0x05, 0x88, 0xed, 0x35, 0xf4, 0xae, 0x01, 0xf3, 0x24, 0xf1, 0x7c, 0x3b, 0x68, 0xb2, 0x9f,
-	0xcd, 0xf7, 0xa6, 0x7e, 0xe8, 0xf5, 0x77, 0x74, 0xe6, 0x4d, 0x92, 0x30, 0x3c, 0xac, 0x54, 0x64,
-	0x36, 0x32, 0xfc, 0x3e, 0x3f, 0x5f, 0x66, 0x4b, 0x79, 0xe0, 0x2f, 0x33, 0x5b, 0x0a, 0x02, 0xa7,
-	0xa9, 0x43, 0xaf, 0x42, 0x89, 0x78, 0x9d, 0xe0, 0xe2, 0x25, 0xbf, 0xda, 0xe0, 0xdf, 0x2e, 0xa2,
-	0xd8, 0xa9, 0x7b, 0x1d, 0x86, 0x85, 0x50, 0xf3, 0x9d, 0x02, 0x0c, 0xbd, 0x14, 0x51, 0xb7, 0xfd,
-	0xa5, 0xd4, 0xdb, 0xfe, 0x33, 0xf1, 0x6c, 0x67, 0x26, 0xb3, 0xdd, 0xbc, 0x2e, 0x6d, 0xdc, 0x8e,
-	0xb8, 0x0f, 0x53, 0x9a, 0x27, 0x54, 0x2e, 0x3f, 0x9b, 0xfb, 0xcb, 0xb5, 0x9c, 0x25, 0xff, 0x7b,
-	0x22, 0xc2, 0xe8, 0xf2, 0xcd, 0x59, 0x98, 0x8e, 0xbd, 0xd3, 0x10, 0xc3, 0x87, 0x70, 0x9f, 0x7c,
-	0x56, 0x87, 0x0f, 0xa1, 0x81, 0xb7, 0x73, 0xf8, 0x10, 0x09, 0xdd, 0xbb, 0xa9, 0xe2, 0xa7, 0xfc,
-	0x90, 0xf6, 0x33, 0x7b, 0xca, 0x0f, 0x2d, 0x1c, 0xd1, 0x5c, 0xfd, 0x42, 0xff, 0x8a, 0x78, 0x83,
-	0x55, 0xd8, 0xa3, 0xc1, 0x62, 0xc3, 0x0d, 0x56, 0x8e, 0x82, 0x9a, 0x3c, 0xbc, 0x68, 0x6f, 0xe2,
-	0xf7, 0xe8, 0xb3, 0xc4, 0x39, 0x3c, 0xb1, 0x3a, 0xfa, 0x96, 0x2a, 0x8e, 0x55, 0x1e, 0x0b, 0xe3,
-	0x94, 0xc7, 0xc6, 0xf3, 0x1f, 0x7c, 0xb2, 0x7c, 0xe0, 0xc3, 0x4f, 0x96, 0x0f, 0x7c, 0xf4, 0xc9,
-	0xf2, 0x81, 0xaf, 0xef, 0x2e, 0x1b, 0x1f, 0xec, 0x2e, 0x1b, 0x1f, 0xee, 0x2e, 0x1b, 0x1f, 0xed,
-	0x2e, 0x1b, 0x1f, 0xef, 0x2e, 0x1b, 0xdf, 0xfb, 0xeb, 0xf2, 0x81, 0x57, 0xee, 0xcf, 0xf2, 0x6f,
-	0x72, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xfa, 0x3d, 0xf6, 0x4d, 0x37, 0x00, 0x00,
+	// 3225 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3b, 0xcd, 0x8f, 0x1c, 0x47,
+	0xbd, 0xee, 0x99, 0xf1, 0xec, 0xce, 0x6f, 0xbd, 0x5f, 0xb5, 0x6b, 0x67, 0xb3, 0x79, 0x5e, 0x5b,
+	0xfd, 0xf2, 0xa2, 0x44, 0x49, 0x66, 0x9e, 0xed, 0x6c, 0xe2, 0x38, 0x79, 0xc9, 0x9b, 0x59, 0xc7,
+	0xf6, 0x26, 0xb6, 0x33, 0xd4, 0xda, 0x4e, 0xc8, 0x87, 0xa0, 0x76, 0xa6, 0x3c, 0xd3, 0xd9, 0x99,
+	0xee, 0x4e, 0x57, 0xcf, 0x9a, 0x25, 0x08, 0x48, 0x20, 0x22, 0x17, 0x02, 0x12, 0x1c, 0xc2, 0x09,
+	0x09, 0x10, 0x88, 0x03, 0xdc, 0x38, 0x20, 0x0e, 0x1c, 0xb8, 0x44, 0x1c, 0x50, 0xc4, 0x01, 0x72,
+	0xb2, 0x92, 0xe5, 0x86, 0x14, 0xfe, 0x00, 0x4b, 0x48, 0xa8, 0x3e, 0xba, 0xbb, 0xba, 0xa7, 0x67,
+	0xb7, 0x7b, 0xb0, 0xad, 0x70, 0xeb, 0xa9, 0xdf, 0x67, 0xff, 0xea, 0x57, 0xbf, 0xaf, 0xae, 0x81,
+	0xc7, 0x3a, 0x96, 0xdf, 0x1d, 0x6c, 0x56, 0x5b, 0x4e, 0xbf, 0x46, 0xb6, 0x06, 0x96, 0xbf, 0x53,
+	0xdb, 0x22, 0x5e, 0xc7, 0xa9, 0x11, 0xd7, 0xaa, 0x6d, 0x9f, 0x20, 0x3d, 0xb7, 0x4b, 0x4e, 0xd4,
+	0x3a, 0xd4, 0xa6, 0x1e, 0xf1, 0x69, 0xbb, 0xea, 0x7a, 0x8e, 0xef, 0xa0, 0xfb, 0x23, 0xaa, 0xaa,
+	0xa4, 0xaa, 0x0a, 0xaa, 0x2a, 0x71, 0xad, 0x6a, 0x40, 0xb5, 0xfc, 0xa8, 0xc6, 0xbb, 0xe3, 0x74,
+	0x9c, 0x9a, 0x20, 0xde, 0x1c, 0x5c, 0x17, 0xbf, 0xc4, 0x0f, 0xf1, 0x24, 0x99, 0x2e, 0x3f, 0xb6,
+	0x75, 0x9a, 0x55, 0x2d, 0x21, 0xb9, 0x4f, 0x5a, 0x5d, 0xcb, 0xa6, 0xde, 0x4e, 0xcd, 0xdd, 0xea,
+	0xf0, 0x05, 0x56, 0xeb, 0x53, 0x9f, 0xd4, 0xb6, 0x87, 0x54, 0x59, 0xae, 0x8d, 0xa2, 0xf2, 0x06,
+	0xb6, 0x6f, 0xf5, 0xe9, 0x10, 0xc1, 0xe3, 0xfb, 0x11, 0xb0, 0x56, 0x97, 0xf6, 0x49, 0x92, 0xce,
+	0x7c, 0x0d, 0x16, 0xea, 0x36, 0xe9, 0xed, 0x30, 0x8b, 0xe1, 0x81, 0x5d, 0xf7, 0x3a, 0x83, 0x3e,
+	0xb5, 0x7d, 0x74, 0x1c, 0x4a, 0x36, 0xe9, 0xd3, 0x25, 0xe3, 0xb8, 0xf1, 0x60, 0xa5, 0x71, 0xe8,
+	0xc3, 0x9b, 0xc7, 0x0e, 0xec, 0xde, 0x3c, 0x56, 0xba, 0x4c, 0xfa, 0x14, 0x0b, 0x08, 0xfa, 0x6f,
+	0x38, 0xb8, 0x4d, 0x7a, 0x03, 0xba, 0x54, 0x10, 0x28, 0xd3, 0x0a, 0xe5, 0xe0, 0x35, 0xbe, 0x88,
+	0x25, 0xcc, 0xfc, 0x56, 0x31, 0xc6, 0xfe, 0x12, 0xf5, 0x49, 0x9b, 0xf8, 0x04, 0xf5, 0xa1, 0xdc,
+	0x23, 0x9b, 0xb4, 0xc7, 0x96, 0x8c, 0xe3, 0xc5, 0x07, 0xa7, 0x4e, 0x3e, 0x57, 0xcd, 0x62, 0xfa,
+	0x6a, 0x0a, 0xab, 0xea, 0x45, 0xc1, 0xe7, 0x39, 0xdb, 0xf7, 0x76, 0x1a, 0x33, 0x4a, 0x89, 0xb2,
+	0x5c, 0xc4, 0x4a, 0x08, 0x7a, 0xdb, 0x80, 0x29, 0x62, 0xdb, 0x8e, 0x4f, 0x7c, 0xcb, 0xb1, 0xd9,
+	0x52, 0x41, 0x08, 0x7d, 0x7e, 0x7c, 0xa1, 0xf5, 0x88, 0x99, 0x94, 0xbc, 0xa0, 0x24, 0x4f, 0x69,
+	0x10, 0xac, 0xcb, 0x5c, 0x7e, 0x12, 0xa6, 0x34, 0x55, 0xd1, 0x1c, 0x14, 0xb7, 0xe8, 0x8e, 0xb4,
+	0x2f, 0xe6, 0x8f, 0x68, 0x31, 0x66, 0x50, 0x65, 0xc1, 0x33, 0x85, 0xd3, 0xc6, 0xf2, 0x33, 0x30,
+	0x97, 0x14, 0x98, 0x87, 0xde, 0x7c, 0xdf, 0x80, 0x45, 0xed, 0x2d, 0x30, 0xbd, 0x4e, 0x3d, 0x6a,
+	0xb7, 0x28, 0xaa, 0x41, 0x85, 0xef, 0x25, 0x73, 0x49, 0x2b, 0xd8, 0xea, 0x79, 0xf5, 0x22, 0x95,
+	0xcb, 0x01, 0x00, 0x47, 0x38, 0xa1, 0x5b, 0x14, 0xf6, 0x72, 0x0b, 0xb7, 0x4b, 0x18, 0x5d, 0x2a,
+	0xc6, 0xdd, 0xa2, 0xc9, 0x17, 0xb1, 0x84, 0x99, 0xff, 0x07, 0xf7, 0x06, 0xfa, 0x5c, 0xa1, 0x7d,
+	0xb7, 0x47, 0x7c, 0x1a, 0x29, 0xb5, 0xaf, 0xeb, 0x99, 0xb3, 0x30, 0x5d, 0x77, 0x5d, 0xcf, 0xd9,
+	0xa6, 0xed, 0x0d, 0x9f, 0x74, 0xa8, 0xf9, 0x8e, 0x01, 0x87, 0xeb, 0x5e, 0xc7, 0x59, 0x3b, 0x5b,
+	0x77, 0xdd, 0x0b, 0x94, 0xf4, 0xfc, 0xee, 0x86, 0x4f, 0xfc, 0x01, 0x43, 0xcf, 0x40, 0x99, 0x89,
+	0x27, 0xc5, 0xee, 0x81, 0xc0, 0x43, 0x24, 0xfc, 0xd6, 0xcd, 0x63, 0x8b, 0x29, 0x84, 0x14, 0x2b,
+	0x2a, 0xf4, 0x10, 0x4c, 0xf4, 0x29, 0x63, 0xa4, 0x13, 0xbc, 0xf3, 0xac, 0x62, 0x30, 0x71, 0x49,
+	0x2e, 0xe3, 0x00, 0x6e, 0xfe, 0xb1, 0x00, 0xb3, 0x21, 0x2f, 0x25, 0xfe, 0x0e, 0x18, 0x78, 0x00,
+	0x87, 0xba, 0xda, 0x1b, 0x0a, 0x3b, 0x4f, 0x9d, 0x7c, 0x2a, 0xa3, 0x2f, 0xa7, 0x19, 0xa9, 0xb1,
+	0xa8, 0xc4, 0x1c, 0xd2, 0x57, 0x71, 0x4c, 0x0c, 0xea, 0x03, 0xb0, 0x1d, 0xbb, 0xa5, 0x84, 0x96,
+	0x84, 0xd0, 0x27, 0x73, 0x0a, 0xdd, 0x08, 0x19, 0x34, 0x90, 0x12, 0x09, 0xd1, 0x1a, 0xd6, 0x04,
+	0x98, 0xbf, 0x36, 0x60, 0x21, 0x85, 0x0e, 0x3d, 0x9d, 0xd8, 0xcf, 0xfb, 0x87, 0xf6, 0x13, 0x0d,
+	0x91, 0x45, 0xbb, 0xf9, 0x08, 0x4c, 0x7a, 0x74, 0xdb, 0x62, 0x96, 0x63, 0x2b, 0x0b, 0xcf, 0x29,
+	0xfa, 0x49, 0xac, 0xd6, 0x71, 0x88, 0x81, 0x1e, 0x86, 0x4a, 0xf0, 0xcc, 0xcd, 0x5c, 0xe4, 0xee,
+	0xcc, 0x37, 0x2e, 0x40, 0x65, 0x38, 0x82, 0x9b, 0x9f, 0x19, 0xda, 0xee, 0x5f, 0x75, 0xdb, 0xc4,
+	0xa7, 0xdc, 0x79, 0x88, 0xeb, 0x5e, 0x8e, 0x9c, 0x39, 0x74, 0x9e, 0xba, 0x5c, 0xc6, 0x01, 0x1c,
+	0x9d, 0x86, 0x43, 0xea, 0x51, 0xfa, 0x8a, 0xd4, 0x2e, 0xdc, 0x98, 0xba, 0x06, 0xc3, 0x31, 0x4c,
+	0x34, 0x80, 0x69, 0xe6, 0x0c, 0xbc, 0x16, 0x95, 0x42, 0xa5, 0xa6, 0x53, 0x27, 0x4f, 0xe7, 0xd9,
+	0x9b, 0x0d, 0x8d, 0x41, 0xe3, 0xb0, 0x12, 0x3a, 0xad, 0xaf, 0x32, 0x1c, 0x97, 0x62, 0xbe, 0x09,
+	0x20, 0x69, 0x2f, 0xd0, 0x5e, 0x1f, 0xb5, 0xa0, 0x6c, 0xf5, 0x49, 0x87, 0x06, 0xf1, 0x3c, 0x97,
+	0x3b, 0x72, 0x0e, 0xeb, 0x9c, 0x5a, 0x29, 0x10, 0x46, 0x71, 0xb1, 0xc8, 0xb0, 0x62, 0x6d, 0x7e,
+	0x10, 0x9e, 0xf2, 0x04, 0x05, 0x0f, 0x3a, 0x02, 0x47, 0x99, 0x39, 0x0c, 0x3a, 0x02, 0x07, 0x4b,
+	0x18, 0x3a, 0x2a, 0x23, 0xa6, 0xb4, 0xec, 0x94, 0x42, 0x29, 0xbe, 0x40, 0x77, 0x64, 0xf8, 0x7c,
+	0x2a, 0x08, 0x9f, 0x32, 0x70, 0xfd, 0x4f, 0x2c, 0x9f, 0xf1, 0x38, 0xa1, 0x09, 0x14, 0x6b, 0x57,
+	0x76, 0xdc, 0x30, 0xcf, 0xbd, 0x15, 0x6c, 0xfe, 0x0b, 0x03, 0xe6, 0x3b, 0x7d, 0xeb, 0xab, 0x14,
+	0x75, 0x13, 0x26, 0xf9, 0xff, 0x3c, 0x26, 0x09, 0xd9, 0x64, 0xb1, 0x8b, 0x07, 0xcb, 0xa3, 0xa9,
+	0xb2, 0xd9, 0xa6, 0x06, 0x95, 0x01, 0xa3, 0x67, 0xad, 0x0e, 0x65, 0xbe, 0xb0, 0xd0, 0x64, 0x14,
+	0xa7, 0xae, 0x06, 0x00, 0x1c, 0xe1, 0x98, 0x7f, 0x2f, 0x00, 0x1a, 0xf6, 0x1d, 0xee, 0xf1, 0x1e,
+	0x75, 0x9d, 0xab, 0xf8, 0x62, 0xd2, 0xe3, 0xb1, 0x5c, 0xc6, 0x01, 0x9c, 0xeb, 0xd5, 0xea, 0x12,
+	0xcf, 0x4f, 0xd6, 0x0f, 0x6b, 0x7c, 0x11, 0x4b, 0x18, 0x6a, 0xc2, 0xe2, 0x40, 0x70, 0xbe, 0x42,
+	0xbc, 0x0e, 0xf5, 0x83, 0x93, 0x27, 0xf6, 0x68, 0xb2, 0xf1, 0x5f, 0x8a, 0x66, 0xf1, 0x6a, 0x0a,
+	0x0e, 0x4e, 0xa5, 0x44, 0x9b, 0x50, 0xd9, 0x0a, 0xcc, 0xa4, 0xc2, 0xd8, 0xea, 0x58, 0x3b, 0x23,
+	0x63, 0x41, 0xf8, 0x13, 0x47, 0x6c, 0xd1, 0x65, 0x28, 0x75, 0x69, 0xaf, 0xbf, 0x74, 0x50, 0xb0,
+	0xff, 0xdf, 0xbc, 0x67, 0xa1, 0x31, 0xc9, 0x43, 0x3e, 0x7f, 0xc2, 0x82, 0x8f, 0xf9, 0x0d, 0x90,
+	0x56, 0xc9, 0x63, 0xde, 0xfd, 0x13, 0xc9, 0x43, 0x30, 0xb1, 0x4d, 0xbd, 0xd0, 0x9c, 0x1a, 0xb3,
+	0x6b, 0x72, 0x19, 0x07, 0x70, 0xf3, 0xe7, 0x06, 0xcc, 0x0b, 0x0d, 0x36, 0x06, 0x9b, 0xac, 0xe5,
+	0x59, 0x2e, 0x2f, 0x44, 0x6e, 0xaf, 0x36, 0x67, 0x61, 0x8e, 0xd1, 0xfe, 0x36, 0xf5, 0xd6, 0x1c,
+	0x9b, 0xf9, 0x1e, 0xb1, 0x6c, 0x5f, 0xa9, 0xb5, 0xa4, 0xb0, 0xe7, 0x36, 0x12, 0x70, 0x3c, 0x44,
+	0x61, 0xfe, 0xac, 0x04, 0x13, 0xe7, 0x3c, 0x6a, 0x75, 0xba, 0x3e, 0xfa, 0x32, 0x4c, 0xf6, 0x55,
+	0xbd, 0x26, 0xf4, 0xe3, 0x3b, 0x21, 0x8b, 0xe4, 0xaa, 0x5e, 0x24, 0x57, 0xdd, 0xad, 0x0e, 0x5f,
+	0x60, 0x55, 0x8e, 0x5d, 0xdd, 0x3e, 0x51, 0x7d, 0x71, 0xf3, 0x0d, 0xda, 0xf2, 0x79, 0xad, 0x17,
+	0xa5, 0xa9, 0x68, 0x0d, 0x87, 0x5c, 0xb9, 0x0b, 0x93, 0x9e, 0x45, 0xd8, 0xd2, 0x44, 0xdc, 0x85,
+	0xeb, 0x7c, 0x11, 0x4b, 0x18, 0x3f, 0x5a, 0x37, 0x88, 0x47, 0xbb, 0xce, 0x80, 0xd1, 0xa5, 0xc9,
+	0x78, 0x09, 0xf0, 0x52, 0x00, 0xc0, 0x11, 0x0e, 0x7a, 0x05, 0x26, 0x5a, 0x4e, 0xbf, 0x6f, 0xf9,
+	0x41, 0x28, 0xaf, 0x65, 0x73, 0xa0, 0xf3, 0x96, 0xbf, 0x26, 0xe8, 0xa2, 0x7d, 0x90, 0xbf, 0x19,
+	0x0e, 0x18, 0xa2, 0x8d, 0x30, 0x28, 0x95, 0x04, 0xeb, 0x87, 0xb3, 0xb1, 0x16, 0xb1, 0x62, 0x54,
+	0xfc, 0xe1, 0x4c, 0xc5, 0x69, 0x65, 0x4b, 0x07, 0xf3, 0x30, 0x15, 0x0e, 0x15, 0x31, 0x15, 0x3f,
+	0x19, 0x56, 0xac, 0xd0, 0xab, 0x61, 0xa2, 0x2f, 0x8b, 0xbd, 0x3b, 0x95, 0x8d, 0xa9, 0xda, 0x7c,
+	0x55, 0x65, 0xcc, 0xc4, 0xab, 0x83, 0xa0, 0x0e, 0x30, 0x7f, 0x6f, 0xc0, 0x94, 0xc2, 0xbc, 0x68,
+	0x31, 0x1f, 0xbd, 0x36, 0xe4, 0x2a, 0xd5, 0x6c, 0xae, 0xc2, 0xa9, 0x85, 0xa3, 0x84, 0x75, 0x44,
+	0xb0, 0xa2, 0xb9, 0x09, 0x86, 0x83, 0x96, 0x4f, 0xfb, 0x41, 0xdb, 0xf1, 0x68, 0xae, 0x37, 0xd1,
+	0x02, 0x36, 0xe7, 0x81, 0x25, 0x2b, 0xf3, 0xb3, 0x12, 0xcc, 0x29, 0x8c, 0x1c, 0x95, 0x73, 0xdc,
+	0x19, 0xcb, 0xf9, 0x9c, 0xb1, 0x70, 0xe7, 0x9c, 0xb1, 0x78, 0x27, 0x9c, 0xb1, 0x74, 0xfb, 0x9c,
+	0xf1, 0x2b, 0x30, 0xb7, 0x4d, 0x3d, 0xeb, 0xba, 0xd5, 0x12, 0x2d, 0xd8, 0xba, 0x7d, 0xdd, 0x51,
+	0xc1, 0xfd, 0xf1, 0x6c, 0xec, 0xaf, 0x25, 0xa8, 0x1b, 0x8b, 0x3c, 0xa0, 0x25, 0x57, 0xf1, 0x90,
+	0x14, 0xf4, 0xae, 0x01, 0x0b, 0xfa, 0xe2, 0x05, 0x8b, 0xf9, 0x8e, 0xb7, 0xb3, 0x34, 0x21, 0x5e,
+	0x6e, 0x5c, 0xe9, 0xf7, 0xa9, 0xf7, 0x5c, 0xb8, 0x36, 0xcc, 0x1a, 0xa7, 0xc9, 0x33, 0xff, 0x51,
+	0x84, 0xe9, 0xd8, 0xd9, 0x42, 0x37, 0x00, 0x24, 0x22, 0x6d, 0xaf, 0xdb, 0xaa, 0xc6, 0x59, 0x1b,
+	0xe3, 0x90, 0x2a, 0xed, 0x38, 0x17, 0xd9, 0x4a, 0x87, 0x31, 0x37, 0x02, 0x60, 0x4d, 0x14, 0x7a,
+	0x0b, 0xa6, 0x88, 0xea, 0xfe, 0xce, 0x39, 0x9e, 0x72, 0xcb, 0xb3, 0xe3, 0x48, 0xae, 0x47, 0x6c,
+	0x92, 0x5d, 0x7c, 0x04, 0xc1, 0xba, 0xb4, 0x65, 0x0f, 0x66, 0x13, 0xfa, 0xa6, 0x74, 0xe2, 0xeb,
+	0x7a, 0x27, 0x9e, 0x39, 0x74, 0x05, 0x7c, 0x45, 0x4b, 0xab, 0xb7, 0xff, 0x0c, 0xe6, 0x92, 0x9a,
+	0xde, 0x36, 0xa1, 0xb1, 0x3e, 0x5a, 0x9f, 0x19, 0xfc, 0xa6, 0x00, 0x95, 0xf0, 0x10, 0xe7, 0x49,
+	0xf5, 0xcb, 0x50, 0xb0, 0xda, 0x2a, 0xd1, 0x83, 0xc2, 0x2a, 0xac, 0x9f, 0xc5, 0x05, 0xab, 0x8d,
+	0x1e, 0x80, 0xf2, 0xa6, 0x47, 0xec, 0x56, 0x57, 0xa5, 0xf6, 0xf0, 0xbc, 0x35, 0xc4, 0x2a, 0x56,
+	0x50, 0x5e, 0xaa, 0xfb, 0xa4, 0x23, 0xca, 0x33, 0xad, 0x54, 0xbf, 0x42, 0x3a, 0x98, 0xaf, 0xa3,
+	0xf3, 0x30, 0x2f, 0x7b, 0xd3, 0xb5, 0x2e, 0x6d, 0x6d, 0x49, 0x15, 0xc5, 0x79, 0xac, 0x34, 0xee,
+	0x55, 0xc8, 0xf3, 0x17, 0x92, 0x08, 0x78, 0x98, 0x46, 0xef, 0xee, 0xcb, 0x7b, 0x77, 0xf7, 0x5c,
+	0x75, 0x32, 0xf0, 0xbb, 0x8e, 0xa7, 0x92, 0x7d, 0xa8, 0x7a, 0x5d, 0xac, 0x62, 0x05, 0x35, 0x17,
+	0x60, 0xfe, 0xbc, 0xe5, 0x5f, 0x18, 0x6c, 0x36, 0x07, 0xbd, 0x1e, 0xa6, 0x6f, 0x0e, 0x78, 0xb5,
+	0xfc, 0x8b, 0x83, 0x30, 0x7d, 0xde, 0xf2, 0x85, 0xad, 0x72, 0x17, 0xca, 0x1b, 0x70, 0xd8, 0xb2,
+	0x19, 0x6d, 0x0d, 0x3c, 0xba, 0xb1, 0x65, 0xb9, 0x57, 0x2e, 0x6e, 0x08, 0x4f, 0xd9, 0x51, 0x75,
+	0xfa, 0x51, 0x45, 0x78, 0x78, 0x3d, 0x0d, 0x09, 0xa7, 0xd3, 0xa2, 0x93, 0x00, 0x1e, 0x25, 0xed,
+	0x86, 0xbe, 0x1b, 0xe1, 0xc1, 0xc3, 0x21, 0x04, 0x6b, 0x58, 0x68, 0x15, 0xa6, 0x6e, 0x78, 0x96,
+	0x4f, 0x15, 0x91, 0xdc, 0x9d, 0xf0, 0xc8, 0xbc, 0x14, 0x81, 0xb0, 0x8e, 0x87, 0xb6, 0x61, 0xca,
+	0x8d, 0x6c, 0xa1, 0xe2, 0x66, 0xc6, 0x48, 0xa1, 0x19, 0xb1, 0xe9, 0x39, 0x7d, 0x87, 0x87, 0xa4,
+	0x4b, 0xb4, 0xd5, 0x25, 0xb6, 0xc5, 0xfa, 0x8d, 0x59, 0x2e, 0x57, 0x43, 0xc1, 0xba, 0x20, 0xd4,
+	0x81, 0xb2, 0x47, 0xed, 0x36, 0xf5, 0x54, 0x05, 0x91, 0x51, 0xe4, 0x0b, 0x7c, 0x09, 0x0b, 0xc2,
+	0x14, 0x91, 0xc0, 0xb7, 0x5c, 0x42, 0xb1, 0x62, 0x8f, 0x6c, 0xbd, 0xa5, 0x98, 0x10, 0xb2, 0xea,
+	0x19, 0x65, 0x05, 0x64, 0x29, 0x92, 0x46, 0xb7, 0x17, 0xaf, 0xa8, 0xf6, 0x62, 0x52, 0x88, 0x7a,
+	0x3a, 0x9b, 0x28, 0xde, 0x4e, 0xa4, 0x48, 0x49, 0xb6, 0x1a, 0x7f, 0x29, 0xc2, 0xec, 0x79, 0x6b,
+	0xec, 0x3a, 0xdf, 0x87, 0x7b, 0x64, 0x76, 0xdf, 0xa0, 0x3d, 0xda, 0xe2, 0xd4, 0x1b, 0xbe, 0x47,
+	0x7c, 0xda, 0x09, 0xfa, 0xee, 0x33, 0x8a, 0xf4, 0x9e, 0xb5, 0x74, 0xb4, 0x5b, 0xa3, 0x41, 0x78,
+	0x14, 0xeb, 0xcc, 0x61, 0x25, 0xad, 0xc7, 0x28, 0xe5, 0xed, 0x31, 0x78, 0x0d, 0x45, 0x7a, 0x3d,
+	0xe7, 0xc6, 0x15, 0xd2, 0x61, 0x2a, 0xea, 0x84, 0x35, 0x54, 0x3d, 0x00, 0xe0, 0x08, 0x07, 0x55,
+	0x01, 0xac, 0x8e, 0xed, 0x78, 0x54, 0x50, 0x94, 0xc5, 0x20, 0x69, 0x86, 0x9f, 0xb3, 0xf5, 0x70,
+	0x15, 0x6b, 0x18, 0xa3, 0x0f, 0xfc, 0xc4, 0xf8, 0x07, 0xde, 0xfc, 0x93, 0x01, 0x65, 0x19, 0x13,
+	0xd1, 0x6a, 0x62, 0x86, 0x76, 0x74, 0x68, 0x86, 0x36, 0x95, 0x36, 0x0a, 0x35, 0xa1, 0x6c, 0x31,
+	0x36, 0xa0, 0xb2, 0x12, 0xac, 0xc8, 0xa3, 0xb0, 0x2e, 0x56, 0xb0, 0x82, 0x20, 0x0b, 0x80, 0x04,
+	0x43, 0xb0, 0xa0, 0xac, 0x5b, 0xcd, 0x3b, 0x25, 0x4c, 0x4c, 0x08, 0x43, 0x00, 0xc3, 0x1a, 0x73,
+	0xf3, 0x27, 0x06, 0xdc, 0xcb, 0x1d, 0x57, 0x94, 0x6a, 0x67, 0xa9, 0xcb, 0xcf, 0xa2, 0xdd, 0xda,
+	0x51, 0xf1, 0x55, 0xc4, 0x37, 0xd7, 0x61, 0x96, 0xa8, 0x96, 0x8c, 0x64, 0x7c, 0x0b, 0x20, 0x58,
+	0xc3, 0xca, 0xd0, 0xa4, 0xd6, 0xa0, 0x22, 0x2a, 0xc2, 0x26, 0xf1, 0x03, 0x5f, 0x0b, 0xb7, 0x7e,
+	0x2d, 0x00, 0xe0, 0x08, 0xc7, 0xfc, 0xb3, 0x01, 0xb3, 0x63, 0x0d, 0xab, 0x9e, 0x81, 0x19, 0x91,
+	0x8b, 0xd9, 0x39, 0xab, 0x47, 0x85, 0x38, 0xa9, 0xd5, 0x11, 0x85, 0x3d, 0x73, 0x2d, 0x06, 0xc5,
+	0x09, 0xec, 0x60, 0xd8, 0x55, 0xdc, 0x6f, 0xd8, 0x55, 0x1a, 0x63, 0xd8, 0xf5, 0x89, 0x01, 0x47,
+	0xd2, 0xc3, 0x09, 0x7a, 0x3d, 0x31, 0xf4, 0x5a, 0xcd, 0x1e, 0x9c, 0x32, 0x4c, 0xba, 0x78, 0x48,
+	0x57, 0xc5, 0xbd, 0xac, 0xfa, 0x9e, 0xcd, 0xce, 0x3e, 0xd5, 0x4d, 0x46, 0x15, 0xfc, 0xe6, 0xaf,
+	0x0c, 0x90, 0xfb, 0x91, 0x27, 0xf8, 0x9d, 0x04, 0xe8, 0xa8, 0x24, 0x8f, 0x2f, 0xaa, 0xfd, 0x0a,
+	0x7d, 0xee, 0x7c, 0x08, 0xc1, 0x1a, 0x56, 0x50, 0xe9, 0x14, 0x47, 0x54, 0x3a, 0x0f, 0x40, 0xb9,
+	0x2d, 0x87, 0x72, 0xa5, 0x78, 0x64, 0x53, 0x13, 0x39, 0x05, 0x35, 0xdf, 0x2f, 0xc1, 0xbc, 0xd0,
+	0x77, 0xdc, 0xc0, 0x3d, 0x8e, 0xee, 0x2e, 0x1c, 0x11, 0xfb, 0x32, 0x1c, 0xeb, 0xe5, 0xeb, 0x9c,
+	0x56, 0xf4, 0x47, 0xd6, 0x53, 0xb1, 0x6e, 0x8d, 0x84, 0xe0, 0x11, 0x7c, 0xff, 0x53, 0x02, 0xf8,
+	0x23, 0x30, 0xe9, 0xf6, 0x88, 0x7f, 0xdd, 0xf1, 0xfa, 0xaa, 0x5a, 0x0c, 0xc7, 0x03, 0x4d, 0xb5,
+	0x8e, 0x43, 0x8c, 0xd1, 0xe1, 0x7e, 0xf2, 0xdf, 0x08, 0xf7, 0x36, 0x1c, 0xd1, 0x0a, 0x99, 0x3b,
+	0x3f, 0x0f, 0x7e, 0xd7, 0x80, 0xa3, 0x7b, 0x56, 0x4e, 0xa8, 0x9d, 0x08, 0x0d, 0x4f, 0xe7, 0x2e,
+	0xc7, 0xb2, 0xcc, 0xc2, 0xdf, 0x37, 0x60, 0x71, 0xfc, 0x31, 0xf8, 0x71, 0x28, 0xb9, 0x51, 0xac,
+	0x0d, 0x33, 0x80, 0x88, 0xb0, 0x02, 0x12, 0x37, 0x4c, 0x31, 0x83, 0x61, 0xde, 0x36, 0xe0, 0xbe,
+	0x3d, 0xca, 0x3c, 0xb4, 0x99, 0x30, 0xcb, 0x99, 0x9c, 0x95, 0x63, 0x16, 0xa3, 0xfc, 0xa8, 0x00,
+	0x13, 0x4d, 0xcf, 0x79, 0x83, 0xb6, 0xee, 0xc6, 0x54, 0xf4, 0x45, 0x28, 0x31, 0x97, 0xb6, 0x54,
+	0x1f, 0x7a, 0x22, 0x63, 0xa1, 0x2f, 0xd5, 0xdb, 0x70, 0x69, 0x4b, 0xd6, 0xa4, 0xfc, 0x09, 0x0b,
+	0x46, 0xda, 0x28, 0xb0, 0x98, 0xa7, 0xb5, 0x0d, 0x58, 0xee, 0x3f, 0x0a, 0x54, 0x98, 0x9f, 0xdb,
+	0x51, 0xa0, 0xd2, 0x6f, 0xc4, 0x28, 0xf0, 0xbb, 0xd1, 0x1b, 0x70, 0xa3, 0xa1, 0xaf, 0xc3, 0xbc,
+	0x1b, 0xf8, 0x59, 0xd3, 0xe9, 0x59, 0x2d, 0x2b, 0x6f, 0x3a, 0x6e, 0xc6, 0xc8, 0x77, 0xa2, 0xa6,
+	0xba, 0x99, 0xe4, 0x8b, 0x87, 0x45, 0x99, 0x0e, 0x4c, 0xc7, 0x4c, 0x8f, 0x4e, 0x05, 0x57, 0x02,
+	0xe2, 0xe5, 0xa6, 0xbc, 0x12, 0x70, 0xeb, 0xe6, 0xb1, 0x43, 0x0a, 0x5d, 0xbf, 0x22, 0x90, 0xe7,
+	0xc3, 0xfb, 0x8f, 0x0b, 0x50, 0x09, 0x35, 0xbb, 0x0b, 0x0e, 0xfe, 0x85, 0x98, 0x83, 0x9f, 0xca,
+	0x69, 0xd3, 0x54, 0x17, 0x7f, 0x3d, 0xe1, 0xe2, 0x79, 0x37, 0x6a, 0x1f, 0x27, 0xff, 0xa1, 0x21,
+	0xf6, 0x44, 0xe2, 0x8a, 0xb9, 0xe2, 0xfe, 0xa3, 0x62, 0x02, 0x13, 0xd7, 0xe5, 0xb4, 0x4c, 0xbd,
+	0xe8, 0xe3, 0xb9, 0x46, 0x6c, 0xe1, 0x54, 0x3a, 0xda, 0xb8, 0x00, 0x12, 0xf0, 0x35, 0xff, 0xa0,
+	0xab, 0x75, 0x17, 0x4e, 0xdf, 0x95, 0xf8, 0xe9, 0xab, 0xe5, 0x34, 0xf2, 0x88, 0xf3, 0xf7, 0x9d,
+	0x02, 0x2c, 0x0c, 0x07, 0x76, 0x86, 0x18, 0xcc, 0x74, 0xf4, 0x99, 0x4f, 0x70, 0x08, 0x4f, 0x65,
+	0x9e, 0xa0, 0x47, 0xb4, 0x51, 0xdd, 0x1f, 0x5b, 0x66, 0x38, 0x21, 0x02, 0xbd, 0x05, 0x73, 0x24,
+	0x7e, 0x0b, 0x21, 0x78, 0xdb, 0xbc, 0x6d, 0x98, 0x12, 0x1c, 0x16, 0x56, 0x09, 0x00, 0xc3, 0x43,
+	0x82, 0xcc, 0xf7, 0x0c, 0x98, 0x4d, 0xc4, 0x0e, 0x9e, 0x77, 0x99, 0x9f, 0x92, 0x77, 0xd5, 0xc0,
+	0x51, 0xc0, 0x50, 0x13, 0x16, 0xc9, 0xc0, 0x77, 0x42, 0xda, 0xe7, 0x6c, 0xb2, 0xd9, 0xa3, 0x6d,
+	0x55, 0x79, 0x84, 0x9f, 0x79, 0xeb, 0x29, 0x38, 0x38, 0x95, 0xd2, 0xfc, 0x92, 0xe6, 0x59, 0x22,
+	0x2a, 0x66, 0xd2, 0xe3, 0xa1, 0xb8, 0xcf, 0x57, 0xf6, 0xf0, 0xdd, 0x9f, 0x16, 0xb4, 0x77, 0x55,
+	0x81, 0x6e, 0x35, 0x1e, 0xe8, 0x8e, 0x25, 0x03, 0xdd, 0x4c, 0x64, 0x9c, 0xf1, 0x42, 0x1d, 0x7a,
+	0x53, 0x3b, 0x1f, 0xc5, 0x3c, 0x23, 0xf7, 0x84, 0xaa, 0xd5, 0xe0, 0x26, 0x9b, 0x9c, 0x7b, 0x87,
+	0x87, 0x26, 0x58, 0x8e, 0x0e, 0xcd, 0xf2, 0x53, 0x30, 0x1d, 0x43, 0xce, 0x75, 0xf3, 0xec, 0x6b,
+	0x70, 0x74, 0xcf, 0x11, 0x1e, 0xcf, 0xed, 0x52, 0x7f, 0x75, 0xdc, 0x9f, 0xc8, 0x7c, 0x38, 0xe2,
+	0x23, 0x56, 0x39, 0x8d, 0x90, 0xcb, 0x58, 0xb1, 0x34, 0x3f, 0x28, 0xc0, 0x1c, 0x3f, 0x1c, 0xb1,
+	0xa6, 0xa8, 0x09, 0xc5, 0x8e, 0xe5, 0x2b, 0x71, 0xab, 0x99, 0xc5, 0xe9, 0x3c, 0x1a, 0x13, 0xbc,
+	0x49, 0xe3, 0x27, 0x91, 0xb3, 0x42, 0x2f, 0x07, 0xa5, 0x65, 0x21, 0xcf, 0x2b, 0x0c, 0xb5, 0x6b,
+	0x8d, 0xca, 0x50, 0x3d, 0xfa, 0x72, 0x70, 0x47, 0xa2, 0x98, 0x87, 0xf3, 0xd0, 0x97, 0x7a, 0xc9,
+	0x59, 0xbf, 0x58, 0x61, 0xfe, 0xa0, 0x00, 0xd2, 0xf5, 0xef, 0x42, 0xbe, 0xbc, 0x14, 0xcb, 0x97,
+	0x19, 0xa3, 0xae, 0x50, 0x2e, 0x35, 0x57, 0x7e, 0x31, 0x91, 0x2b, 0x4f, 0xe4, 0x61, 0xb8, 0x77,
+	0x9e, 0xfc, 0x9d, 0x01, 0x15, 0x81, 0x77, 0x17, 0x92, 0x51, 0x33, 0x9e, 0x8c, 0x1e, 0xce, 0xf1,
+	0x16, 0x23, 0x12, 0xd1, 0xf7, 0x8a, 0x4a, 0xfb, 0x30, 0xe0, 0x75, 0x89, 0xd7, 0x56, 0x0d, 0x72,
+	0x14, 0xf0, 0xf8, 0x22, 0x96, 0x30, 0xd4, 0x83, 0x69, 0xa6, 0x39, 0x0a, 0x53, 0xef, 0x99, 0x31,
+	0x45, 0xe9, 0x3e, 0xc6, 0x1a, 0xf3, 0xe2, 0xce, 0x98, 0xbe, 0x84, 0xe3, 0xcc, 0xd1, 0xb7, 0x0d,
+	0x58, 0x70, 0x87, 0x33, 0xa5, 0x72, 0x8c, 0x27, 0x73, 0x46, 0xb2, 0x88, 0x41, 0xe3, 0x9e, 0xdd,
+	0x9b, 0xc7, 0xd2, 0x72, 0x30, 0x4e, 0x13, 0x87, 0xba, 0x70, 0x48, 0xff, 0xc4, 0xa9, 0xdc, 0xe8,
+	0x64, 0xfe, 0x6f, 0xa9, 0x8d, 0xb9, 0xdd, 0x9b, 0xc7, 0x0e, 0xe9, 0x2b, 0x38, 0xc6, 0xd9, 0xfc,
+	0x6b, 0x09, 0xa6, 0x34, 0xbf, 0x43, 0x27, 0xe2, 0x09, 0xe2, 0xbe, 0x64, 0x82, 0x00, 0x81, 0x1c,
+	0x4b, 0x0e, 0x1e, 0xcc, 0xb4, 0x06, 0x9e, 0x47, 0x6d, 0xff, 0xdc, 0x6d, 0xa9, 0xc6, 0x10, 0x2f,
+	0x22, 0xd6, 0x62, 0x1c, 0x71, 0x42, 0x02, 0x2f, 0xfd, 0xba, 0xea, 0x3b, 0x73, 0x31, 0xcf, 0x77,
+	0xe6, 0xd1, 0xa5, 0x5f, 0xf0, 0x6d, 0x39, 0xe0, 0x8b, 0x9a, 0x50, 0x96, 0x9f, 0xe3, 0xd4, 0x57,
+	0x8c, 0x47, 0xb2, 0x4e, 0xf2, 0x38, 0x8d, 0x0c, 0xf6, 0xf2, 0x19, 0x2b, 0x3e, 0x7a, 0x16, 0xad,
+	0xec, 0x93, 0x45, 0x9f, 0x07, 0xe4, 0x6c, 0x32, 0xea, 0x6d, 0xd3, 0xf6, 0x79, 0x79, 0x1d, 0x9e,
+	0xbb, 0x41, 0xf9, 0xb8, 0xf1, 0x60, 0xb1, 0xb1, 0xac, 0xa8, 0xd0, 0x8b, 0x43, 0x18, 0x38, 0x85,
+	0x0a, 0x0d, 0x60, 0x4e, 0x59, 0x2f, 0xf4, 0x3f, 0xf5, 0x0d, 0x28, 0x6f, 0x63, 0x10, 0xdd, 0x0b,
+	0x58, 0x4b, 0x30, 0xc4, 0x43, 0x22, 0xcc, 0x55, 0x98, 0x97, 0x8e, 0xa5, 0xa7, 0xb6, 0xfd, 0x6f,
+	0x4e, 0xff, 0xd6, 0x80, 0xf8, 0x11, 0x8d, 0xdf, 0x08, 0x31, 0x32, 0xdc, 0x08, 0xb9, 0x01, 0x33,
+	0x03, 0x97, 0xf9, 0x1e, 0x25, 0x7d, 0xa1, 0x41, 0x10, 0xc0, 0x9e, 0xc8, 0x13, 0x86, 0xf5, 0xe4,
+	0x14, 0x96, 0xb6, 0x57, 0x63, 0x6c, 0x71, 0x42, 0x8c, 0xf9, 0xcf, 0x02, 0xc4, 0xce, 0x1a, 0x7a,
+	0xcf, 0x80, 0x79, 0x92, 0xb8, 0x46, 0x1e, 0x14, 0xd9, 0xcf, 0xe6, 0xbb, 0xdb, 0x3f, 0x74, 0x0b,
+	0x3d, 0xea, 0x79, 0x93, 0x28, 0x0c, 0x0f, 0x0b, 0x15, 0x91, 0x8d, 0x0c, 0xff, 0x4f, 0x20, 0x5f,
+	0x64, 0x4b, 0xf9, 0xa3, 0x81, 0x8c, 0x6c, 0x29, 0x00, 0x9c, 0x26, 0x0e, 0xbd, 0x0a, 0x25, 0xe2,
+	0x75, 0x82, 0x0f, 0x2f, 0xf9, 0xc5, 0x06, 0x7f, 0xff, 0x88, 0x7c, 0xa7, 0xee, 0x75, 0x18, 0x16,
+	0x4c, 0xcd, 0x77, 0x0a, 0x30, 0x74, 0x63, 0x45, 0x7d, 0xed, 0x2f, 0xa5, 0x7e, 0xed, 0x3f, 0x1d,
+	0x8f, 0x76, 0x66, 0x32, 0xda, 0xcd, 0xeb, 0xdc, 0xc6, 0xad, 0x88, 0xfb, 0x30, 0xa5, 0x59, 0x42,
+	0xc5, 0xf2, 0x33, 0xb9, 0xdf, 0x5c, 0x8b, 0x59, 0xf2, 0x5f, 0x1c, 0x11, 0x44, 0xe7, 0x6f, 0xce,
+	0xc2, 0x74, 0xec, 0x9e, 0x86, 0x18, 0x3e, 0x84, 0xe7, 0xe4, 0xf3, 0x3a, 0x7c, 0x08, 0x15, 0xbc,
+	0x9d, 0xc3, 0x87, 0x88, 0xe9, 0xde, 0x45, 0x15, 0xef, 0xf2, 0x43, 0xdc, 0xcf, 0x6d, 0x97, 0x1f,
+	0x6a, 0x38, 0xa2, 0xb8, 0xfa, 0xa5, 0xfe, 0x16, 0xf1, 0x02, 0xab, 0xb0, 0x47, 0x81, 0xc5, 0x86,
+	0x0b, 0xac, 0x1c, 0x09, 0x35, 0xd9, 0xbc, 0x68, 0x77, 0xf3, 0xf7, 0xa8, 0xb3, 0x44, 0x1f, 0x9e,
+	0xd8, 0x1d, 0xfd, 0x48, 0x15, 0xc7, 0x4a, 0x8f, 0x85, 0x71, 0xd2, 0x63, 0xe3, 0xf9, 0x0f, 0x3f,
+	0x5d, 0x39, 0xf0, 0xd1, 0xa7, 0x2b, 0x07, 0x3e, 0xfe, 0x74, 0xe5, 0xc0, 0x37, 0x77, 0x57, 0x8c,
+	0x0f, 0x77, 0x57, 0x8c, 0x8f, 0x76, 0x57, 0x8c, 0x8f, 0x77, 0x57, 0x8c, 0x4f, 0x76, 0x57, 0x8c,
+	0xef, 0xff, 0x6d, 0xe5, 0xc0, 0x2b, 0xf7, 0x67, 0xf9, 0xbb, 0xde, 0xbf, 0x02, 0x00, 0x00, 0xff,
+	0xff, 0x42, 0x3b, 0xfa, 0x4d, 0xd5, 0x37, 0x00, 0x00,
 }
 
 func (m *AnalysisRunArgument) Marshal() (dAtA []byte, err error) {
@@ -2803,6 +2805,20 @@ func (m *FreightReference) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if len(m.VerificationHistory) > 0 {
+		for iNdEx := len(m.VerificationHistory) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.VerificationHistory[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGenerated(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x3a
+		}
+	}
 	i -= len(m.Warehouse)
 	copy(dAtA[i:], m.Warehouse)
 	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Warehouse)))
@@ -5199,6 +5215,12 @@ func (m *FreightReference) Size() (n int) {
 	}
 	l = len(m.Warehouse)
 	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.VerificationHistory) > 0 {
+		for _, e := range m.VerificationHistory {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
 	return n
 }
 
@@ -6228,6 +6250,11 @@ func (this *FreightReference) String() string {
 		repeatedStringForCharts += strings.Replace(strings.Replace(f.String(), "Chart", "Chart", 1), `&`, ``, 1) + ","
 	}
 	repeatedStringForCharts += "}"
+	repeatedStringForVerificationHistory := "[]VerificationInfo{"
+	for _, f := range this.VerificationHistory {
+		repeatedStringForVerificationHistory += strings.Replace(strings.Replace(f.String(), "VerificationInfo", "VerificationInfo", 1), `&`, ``, 1) + ","
+	}
+	repeatedStringForVerificationHistory += "}"
 	s := strings.Join([]string{`&FreightReference{`,
 		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
 		`Commits:` + repeatedStringForCommits + `,`,
@@ -6235,6 +6262,7 @@ func (this *FreightReference) String() string {
 		`Charts:` + repeatedStringForCharts + `,`,
 		`VerificationInfo:` + strings.Replace(this.VerificationInfo.String(), "VerificationInfo", "VerificationInfo", 1) + `,`,
 		`Warehouse:` + fmt.Sprintf("%v", this.Warehouse) + `,`,
+		`VerificationHistory:` + repeatedStringForVerificationHistory + `,`,
 		`}`,
 	}, "")
 	return s
@@ -9677,6 +9705,40 @@ func (m *FreightReference) Unmarshal(dAtA []byte) error {
 			}
 			m.Warehouse = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field VerificationHistory", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.VerificationHistory = append(m.VerificationHistory, VerificationInfo{})
+			if err := m.VerificationHistory[len(m.VerificationHistory)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto
index 4a11785a..5f2e4996 100644
--- a/api/v1alpha1/generated.proto
+++ b/api/v1alpha1/generated.proto
@@ -332,6 +332,10 @@ message FreightReference {
   // VerificationInfo is information about any verification process that was
   // associated with this Freight for this Stage.
   optional VerificationInfo verificationInfo = 5;
+
+  // VerificationHistory is a stack of recent VerificationInfo. By default,
+  // the last ten VerificationInfo are stored.
+  repeated VerificationInfo verificationHistory = 7;
 }
 
 // FreightStatus describes a piece of Freight's most recently observed state.
diff --git a/api/v1alpha1/helpers.go b/api/v1alpha1/helpers.go
index e4c03c81..4da7384d 100644
--- a/api/v1alpha1/helpers.go
+++ b/api/v1alpha1/helpers.go
@@ -6,8 +6,31 @@ import (
 
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
 
+func AddFinalizer(ctx context.Context, c client.Client, obj client.Object) error {
+	if controllerutil.AddFinalizer(obj, FinalizerName) {
+		patchBytes := []byte(`{"metadata":{"finalizers":[`)
+		for i, finalizer := range obj.GetFinalizers() {
+			if i > 0 {
+				patchBytes = append(patchBytes, ',')
+			}
+			patchBytes = append(patchBytes, fmt.Sprintf("%q", finalizer)...)
+		}
+		patchBytes = append(patchBytes, "]}}"...)
+		if err := c.Patch(
+			ctx,
+			obj,
+			client.RawPatch(types.MergePatchType, patchBytes),
+		); err != nil {
+			return fmt.Errorf("patch annotation: %w", err)
+		}
+		return nil
+	}
+	return nil
+}
+
 func ClearAnnotations(ctx context.Context, c client.Client, obj client.Object, keys ...string) error {
 	if len(keys) == 0 {
 		return nil
diff --git a/api/v1alpha1/promotion_types.go b/api/v1alpha1/promotion_types.go
index ff85b6c7..438566cb 100644
--- a/api/v1alpha1/promotion_types.go
+++ b/api/v1alpha1/promotion_types.go
@@ -41,6 +41,7 @@ func (p *PromotionPhase) IsTerminal() bool {
 //+kubebuilder:resource:shortName={promo,promos}
 //+kubebuilder:object:root=true
 //+kubebuilder:subresource:status
+//+kubebuilder:printcolumn:name=Shard,type=string,JSONPath=`.metadata.labels.kargo\.akuity\.io/shard`
 //+kubebuilder:printcolumn:name=Stage,type=string,JSONPath=`.spec.stage`
 //+kubebuilder:printcolumn:name=Freight,type=string,JSONPath=`.spec.freight`
 //+kubebuilder:printcolumn:name=Phase,type=string,JSONPath=`.status.phase`
diff --git a/api/v1alpha1/stage_types.go b/api/v1alpha1/stage_types.go
index 9b622d91..bdc4b3a4 100644
--- a/api/v1alpha1/stage_types.go
+++ b/api/v1alpha1/stage_types.go
@@ -114,6 +114,7 @@ const (
 
 //+kubebuilder:object:root=true
 //+kubebuilder:subresource:status
+//+kubebuilder:printcolumn:name=Shard,type=string,JSONPath=`.spec.shard`
 //+kubebuilder:printcolumn:name=Current Freight,type=string,JSONPath=`.status.currentFreight.name`
 //+kubebuilder:printcolumn:name=Health,type=string,JSONPath=`.status.health.status`
 //+kubebuilder:printcolumn:name=Phase,type=string,JSONPath=`.status.phase`
@@ -539,19 +540,22 @@ type FreightReference struct {
 	// VerificationInfo is information about any verification process that was
 	// associated with this Freight for this Stage.
 	VerificationInfo *VerificationInfo `json:"verificationInfo,omitempty" protobuf:"bytes,5,opt,name=verificationInfo"`
+	// VerificationHistory is a stack of recent VerificationInfo. By default,
+	// the last ten VerificationInfo are stored.
+	VerificationHistory VerificationInfoStack `json:"verificationHistory,omitempty" protobuf:"bytes,7,rep,name=verificationHistory"`
 }
 
 type FreightReferenceStack []FreightReference
 
-// Empty returns a bool indicating whether or not the FreightReferenceStack is
-// empty. nil counts as empty.
+// Empty returns a bool indicating whether the FreightReferenceStack is
+// empty. Nil counts as empty.
 func (f FreightReferenceStack) Empty() bool {
 	return len(f) == 0
 }
 
 // Pop removes and returns the leading element from a FreightReferenceStack. If
 // the FreightReferenceStack is empty, the FreightReferenceStack is not modified
-// and a empty FreightReference is returned instead. A boolean is also returned
+// and an empty FreightReference is returned instead. A boolean is also returned
 // indicating whether the returned FreightReference came from the top of the
 // stack (true) or is a zero value for that type (false).
 func (f *FreightReferenceStack) Pop() (FreightReference, bool) {
@@ -575,7 +579,7 @@ func (f FreightReferenceStack) Top() (FreightReference, bool) {
 	return item, true
 }
 
-// Push pushes one or more Freight onto the FreightStack. The order of
+// Push pushes one or more Freight onto the FreightReferenceStack. The order of
 // the new elements at the top of the stack will be equal to the order in which
 // they were passed to this function. i.e. The first new element passed will be
 // the element at the top of the stack. If resulting modification grow the depth
@@ -583,9 +587,9 @@ func (f FreightReferenceStack) Top() (FreightReference, bool) {
 // Modified to contain only the top 10 elements.
 func (f *FreightReferenceStack) Push(freight ...FreightReference) {
 	*f = append(freight, *f...)
-	const max = 10
-	if len(*f) > max {
-		*f = (*f)[:max]
+	const maxSize = 10
+	if len(*f) > maxSize {
+		*f = (*f)[:maxSize]
 	}
 }
 
@@ -746,6 +750,39 @@ type VerificationInfo struct {
 	AnalysisRun *AnalysisRunReference `json:"analysisRun,omitempty" protobuf:"bytes,3,opt,name=analysisRun"`
 }
 
+type VerificationInfoStack []VerificationInfo
+
+// UpdateOrPush updates the VerificationInfo with the same ID as the provided
+// VerificationInfo or appends the provided VerificationInfo to the stack if no
+// such VerificationInfo is found.
+//
+// The order of existing items in the stack is preserved, and new items without
+// a matching ID are appended to the top of the stack. If the stack grows beyond
+// 10 items, the bottom items are removed.
+func (v *VerificationInfoStack) UpdateOrPush(info ...VerificationInfo) {
+	var newStack VerificationInfoStack
+	for _, i := range info {
+		var found bool
+		for vi, item := range *v {
+			if i.ID == item.ID {
+				(*v)[vi] = i
+				found = true
+				break
+			}
+		}
+		if !found {
+			newStack = append(newStack, i)
+		}
+	}
+
+	*v = append(newStack, *v...)
+
+	const maxSize = 10
+	if len(*v) > maxSize {
+		*v = (*v)[:maxSize]
+	}
+}
+
 // AnalysisRunReference is a reference to an AnalysisRun.
 type AnalysisRunReference struct {
 	// Namespace is the namespace of the AnalysisRun.
diff --git a/api/v1alpha1/warehouse_types.go b/api/v1alpha1/warehouse_types.go
index ec1580fc..bc1e13df 100644
--- a/api/v1alpha1/warehouse_types.go
+++ b/api/v1alpha1/warehouse_types.go
@@ -24,6 +24,8 @@ const (
 
 //+kubebuilder:object:root=true
 //+kubebuilder:subresource:status
+//+kubebuilder:printcolumn:name=Shard,type=string,JSONPath=`.spec.shard`
+//+kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`
 
 // Warehouse is a source of Freight.
 type Warehouse struct {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 22c83b71..8ece9b7f 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -392,6 +392,13 @@ func (in *FreightReference) DeepCopyInto(out *FreightReference) {
 		*out = new(VerificationInfo)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.VerificationHistory != nil {
+		in, out := &in.VerificationHistory, &out.VerificationHistory
+		*out = make(VerificationInfoStack, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FreightReference.
@@ -1249,6 +1256,27 @@ func (in *VerificationInfo) DeepCopy() *VerificationInfo {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in VerificationInfoStack) DeepCopyInto(out *VerificationInfoStack) {
+	{
+		in := &in
+		*out = make(VerificationInfoStack, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerificationInfoStack.
+func (in VerificationInfoStack) DeepCopy() VerificationInfoStack {
+	if in == nil {
+		return nil
+	}
+	out := new(VerificationInfoStack)
+	in.DeepCopyInto(out)
+	return *out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *VerifiedStage) DeepCopyInto(out *VerifiedStage) {
 	*out = *in
diff --git a/charts/kargo/crds/kargo.akuity.io_promotions.yaml b/charts/kargo/crds/kargo.akuity.io_promotions.yaml
index 2d74ffad..0da701b5 100644
--- a/charts/kargo/crds/kargo.akuity.io_promotions.yaml
+++ b/charts/kargo/crds/kargo.akuity.io_promotions.yaml
@@ -18,6 +18,9 @@ spec:
   scope: Namespaced
   versions:
   - additionalPrinterColumns:
+    - jsonPath: .metadata.labels.kargo\.akuity\.io/shard
+      name: Shard
+      type: string
     - jsonPath: .spec.stage
       name: Stage
       type: string
diff --git a/charts/kargo/crds/kargo.akuity.io_stages.yaml b/charts/kargo/crds/kargo.akuity.io_stages.yaml
index 54d63fc4..b037e5cc 100644
--- a/charts/kargo/crds/kargo.akuity.io_stages.yaml
+++ b/charts/kargo/crds/kargo.akuity.io_stages.yaml
@@ -15,6 +15,9 @@ spec:
   scope: Namespaced
   versions:
   - additionalPrinterColumns:
+    - jsonPath: .spec.shard
+      name: Shard
+      type: string
     - jsonPath: .status.currentFreight.name
       name: Current Freight
       type: string
@@ -662,6 +665,52 @@ spec:
                       the contents of the Freight. i.e. Two pieces of Freight can be compared for
                       equality by comparing their Names.
                     type: string
+                  verificationHistory:
+                    description: |-
+                      VerificationHistory is a stack of recent VerificationInfo. By default,
+                      the last ten VerificationInfo are stored.
+                    items:
+                      description: |-
+                        VerificationInfo contains information about the currently running
+                        Verification process.
+                      properties:
+                        analysisRun:
+                          description: |-
+                            AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements
+                            the Verification process.
+                          properties:
+                            name:
+                              description: Name is the name of the AnalysisRun.
+                              type: string
+                            namespace:
+                              description: Namespace is the namespace of the AnalysisRun.
+                              type: string
+                            phase:
+                              description: Phase is the last observed phase of the
+                                AnalysisRun referenced by Name.
+                              type: string
+                          required:
+                          - name
+                          - 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
+                            process is in its current phase.
+                          type: string
+                        phase:
+                          description: |-
+                            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
+                            cannot be launched successfully.
+                          type: string
+                      type: object
+                    type: array
                   verificationInfo:
                     description: |-
                       VerificationInfo is information about any verification process that was
@@ -816,6 +865,53 @@ spec:
                           the contents of the Freight. i.e. Two pieces of Freight can be compared for
                           equality by comparing their Names.
                         type: string
+                      verificationHistory:
+                        description: |-
+                          VerificationHistory is a stack of recent VerificationInfo. By default,
+                          the last ten VerificationInfo are stored.
+                        items:
+                          description: |-
+                            VerificationInfo contains information about the currently running
+                            Verification process.
+                          properties:
+                            analysisRun:
+                              description: |-
+                                AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements
+                                the Verification process.
+                              properties:
+                                name:
+                                  description: Name is the name of the AnalysisRun.
+                                  type: string
+                                namespace:
+                                  description: Namespace is the namespace of the AnalysisRun.
+                                  type: string
+                                phase:
+                                  description: Phase is the last observed phase of
+                                    the AnalysisRun referenced by Name.
+                                  type: string
+                              required:
+                              - name
+                              - 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
+                                process is in its current phase.
+                              type: string
+                            phase:
+                              description: |-
+                                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
+                                cannot be launched successfully.
+                              type: string
+                          type: object
+                        type: array
                       verificationInfo:
                         description: |-
                           VerificationInfo is information about any verification process that was
@@ -1037,6 +1133,53 @@ spec:
                         the contents of the Freight. i.e. Two pieces of Freight can be compared for
                         equality by comparing their Names.
                       type: string
+                    verificationHistory:
+                      description: |-
+                        VerificationHistory is a stack of recent VerificationInfo. By default,
+                        the last ten VerificationInfo are stored.
+                      items:
+                        description: |-
+                          VerificationInfo contains information about the currently running
+                          Verification process.
+                        properties:
+                          analysisRun:
+                            description: |-
+                              AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements
+                              the Verification process.
+                            properties:
+                              name:
+                                description: Name is the name of the AnalysisRun.
+                                type: string
+                              namespace:
+                                description: Namespace is the namespace of the AnalysisRun.
+                                type: string
+                              phase:
+                                description: Phase is the last observed phase of the
+                                  AnalysisRun referenced by Name.
+                                type: string
+                            required:
+                            - name
+                            - 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
+                              process is in its current phase.
+                            type: string
+                          phase:
+                            description: |-
+                              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
+                              cannot be launched successfully.
+                            type: string
+                        type: object
+                      type: array
                     verificationInfo:
                       description: |-
                         VerificationInfo is information about any verification process that was
diff --git a/charts/kargo/crds/kargo.akuity.io_warehouses.yaml b/charts/kargo/crds/kargo.akuity.io_warehouses.yaml
index bdc2f504..0a6305b6 100644
--- a/charts/kargo/crds/kargo.akuity.io_warehouses.yaml
+++ b/charts/kargo/crds/kargo.akuity.io_warehouses.yaml
@@ -14,7 +14,14 @@ spec:
     singular: warehouse
   scope: Namespaced
   versions:
-  - name: v1alpha1
+  - additionalPrinterColumns:
+    - jsonPath: .spec.shard
+      name: Shard
+      type: string
+    - jsonPath: .metadata.creationTimestamp
+      name: Age
+      type: date
+    name: v1alpha1
     schema:
       openAPIV3Schema:
         description: Warehouse is a source of Freight.
diff --git a/internal/cli/cmd/get/get.go b/internal/cli/cmd/get/get.go
index 6e932a5d..0cc6fee8 100644
--- a/internal/cli/cmd/get/get.go
+++ b/internal/cli/cmd/get/get.go
@@ -84,6 +84,8 @@ func printObjects[T runtime.Object](
 		printObj = newPromotionTable(list)
 	case *kargoapi.Stage:
 		printObj = newStageTable(list)
+	case *kargoapi.Warehouse:
+		printObj = newWarehouseTable(list)
 	default:
 		printObj = list
 	}
diff --git a/internal/cli/cmd/get/promotions.go b/internal/cli/cmd/get/promotions.go
index 1f762b4f..3785b919 100644
--- a/internal/cli/cmd/get/promotions.go
+++ b/internal/cli/cmd/get/promotions.go
@@ -172,9 +172,14 @@ func newPromotionTable(list *metav1.List) *metav1.Table {
 	rows := make([]metav1.TableRow, len(list.Items))
 	for i, item := range list.Items {
 		promo := item.Object.(*kargoapi.Promotion) // nolint: forcetypeassert
+		var shard string
+		if promo.Labels != nil {
+			shard = promo.Labels[kargoapi.ShardLabelKey]
+		}
 		rows[i] = metav1.TableRow{
 			Cells: []any{
 				promo.GetName(),
+				shard,
 				promo.Spec.Stage,
 				promo.Spec.Freight,
 				promo.GetStatus().Phase,
@@ -186,6 +191,7 @@ func newPromotionTable(list *metav1.List) *metav1.Table {
 	return &metav1.Table{
 		ColumnDefinitions: []metav1.TableColumnDefinition{
 			{Name: "Name", Type: "string"},
+			{Name: "Shard", Type: "string"},
 			{Name: "Stage", Type: "string"},
 			{Name: "Freight", Type: "string"},
 			{Name: "Phase", Type: "string"},
diff --git a/internal/cli/cmd/get/stages.go b/internal/cli/cmd/get/stages.go
index 069ca29d..967e8fc7 100644
--- a/internal/cli/cmd/get/stages.go
+++ b/internal/cli/cmd/get/stages.go
@@ -170,6 +170,7 @@ func newStageTable(list *metav1.List) *metav1.Table {
 		rows[i] = metav1.TableRow{
 			Cells: []any{
 				stage.Name,
+				stage.Spec.Shard,
 				currentFreightID,
 				health,
 				stage.Status.Phase,
@@ -181,6 +182,7 @@ func newStageTable(list *metav1.List) *metav1.Table {
 	return &metav1.Table{
 		ColumnDefinitions: []metav1.TableColumnDefinition{
 			{Name: "Name", Type: "string"},
+			{Name: "Shard", Type: "string"},
 			{Name: "Current Freight", Type: "string"},
 			{Name: "Health", Type: "string"},
 			{Name: "Phase", Type: "string"},
diff --git a/internal/cli/cmd/get/warehouse.go b/internal/cli/cmd/get/warehouse.go
index 5c5d70b5..29f92160 100644
--- a/internal/cli/cmd/get/warehouse.go
+++ b/internal/cli/cmd/get/warehouse.go
@@ -5,9 +5,12 @@ import (
 	"errors"
 	"fmt"
 	"slices"
+	"time"
 
 	"connectrpc.com/connect"
 	"github.com/spf13/cobra"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/duration"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
 	"k8s.io/cli-runtime/pkg/genericiooptions"
 
@@ -155,3 +158,26 @@ func (o *getWarehousesOptions) run(ctx context.Context) error {
 	}
 	return errors.Join(errs...)
 }
+
+func newWarehouseTable(list *metav1.List) *metav1.Table {
+	rows := make([]metav1.TableRow, len(list.Items))
+	for i, item := range list.Items {
+		warehouse := item.Object.(*kargoapi.Warehouse) // nolint: forcetypeassert
+		rows[i] = metav1.TableRow{
+			Cells: []any{
+				warehouse.Name,
+				warehouse.Spec.Shard,
+				duration.HumanDuration(time.Since(warehouse.CreationTimestamp.Time)),
+			},
+			Object: list.Items[i],
+		}
+	}
+	return &metav1.Table{
+		ColumnDefinitions: []metav1.TableColumnDefinition{
+			{Name: "Name", Type: "string"},
+			{Name: "Shard", Type: "string"},
+			{Name: "Age", Type: "string"},
+		},
+		Rows: rows,
+	}
+}
diff --git a/internal/controller/stages/stages.go b/internal/controller/stages/stages.go
index f171b060..d2cc4db2 100644
--- a/internal/controller/stages/stages.go
+++ b/internal/controller/stages/stages.go
@@ -533,10 +533,17 @@ func (r *reconciler) Reconcile(
 				err = fmt.Errorf("error removing finalizer: %w", err)
 			}
 		}
-	} else if stage.Spec.PromotionMechanisms == nil {
-		newStatus, err = r.syncControlFlowStage(ctx, stage)
 	} else {
-		newStatus, err = r.syncNormalStage(ctx, stage)
+		err = kargoapi.AddFinalizer(ctx, r.kargoClient, stage)
+		if err != nil {
+			newStatus = stage.Status
+		} else {
+			if stage.Spec.PromotionMechanisms == nil {
+				newStatus, err = r.syncControlFlowStage(ctx, stage)
+			} else {
+				newStatus, err = r.syncNormalStage(ctx, stage)
+			}
+		}
 	}
 	if err != nil {
 		newStatus.Message = err.Error()
@@ -780,6 +787,14 @@ func (r *reconciler) syncNormalStage(
 					}
 				}
 			}
+
+			// Update the verification history with the latest verification info.
+			// NOTE: We do this regardless of the phase of the verification process,
+			// to ensure we add any previous verification attempt which may have
+			// been recorded before we started tracking history.
+			if status.CurrentFreight.VerificationInfo != nil {
+				status.CurrentFreight.VerificationHistory.UpdateOrPush(*status.CurrentFreight.VerificationInfo)
+			}
 		}
 
 		// If health is not applicable or healthy
diff --git a/internal/controller/stages/verification.go b/internal/controller/stages/verification.go
index 6ba80fec..ca4081ba 100644
--- a/internal/controller/stages/verification.go
+++ b/internal/controller/stages/verification.go
@@ -296,6 +296,10 @@ func (r *reconciler) abortVerification(
 		ID:      stage.Status.CurrentFreight.VerificationInfo.ID,
 		Phase:   kargoapi.VerificationPhaseAborted,
 		Message: "Verification aborted by user",
+		AnalysisRun: &kargoapi.AnalysisRunReference{
+			Name:      ar.Name,
+			Namespace: ar.Namespace,
+		},
 	}
 }
 
diff --git a/internal/webhook/stage/webhook.go b/internal/webhook/stage/webhook.go
index e51edd16..20e0d3f9 100644
--- a/internal/webhook/stage/webhook.go
+++ b/internal/webhook/stage/webhook.go
@@ -4,14 +4,12 @@ import (
 	"context"
 	"fmt"
 
-	admissionv1 "k8s.io/api/admission/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/validation/field"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
-	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	admission "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	kargoapi "github.com/akuity/kargo/api/v1alpha1"
@@ -61,7 +59,7 @@ func newWebhook(kubeClient client.Client) *webhook {
 	return w
 }
 
-func (w *webhook) Default(ctx context.Context, obj runtime.Object) error {
+func (w *webhook) Default(_ context.Context, obj runtime.Object) error {
 	stage := obj.(*kargoapi.Stage) // nolint: forcetypeassert
 
 	// Sync the convenience shard field with the shard label
@@ -74,19 +72,6 @@ func (w *webhook) Default(ctx context.Context, obj runtime.Object) error {
 		stage.Spec.Shard = stage.Labels[kargoapi.ShardLabelKey]
 	}
 
-	req, err := admission.RequestFromContext(ctx)
-	if err != nil {
-		return apierrors.NewInternalError(
-			fmt.Errorf("error getting admission request from context: %w", err),
-		)
-	}
-
-	// Determine if this is a create or update. We don't want to add a finalizer
-	// during update, because that would make it impossible to remove!
-	if req.Operation == admissionv1.Create {
-		controllerutil.AddFinalizer(stage, kargoapi.FinalizerName)
-	}
-
 	return nil
 }
 
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 7adad0bc..e8c01834 100644
--- a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
+++ b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
@@ -541,6 +541,51 @@
               "description": "Name is system-assigned identifier that is derived deterministically from\nthe contents of the Freight. i.e. Two pieces of Freight can be compared for\nequality by comparing their Names.",
               "type": "string"
             },
+            "verificationHistory": {
+              "description": "VerificationHistory is a stack of recent VerificationInfo. By default,\nthe last ten VerificationInfo are stored.",
+              "items": {
+                "description": "VerificationInfo contains information about the currently running\nVerification process.",
+                "properties": {
+                  "analysisRun": {
+                    "description": "AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements\nthe Verification process.",
+                    "properties": {
+                      "name": {
+                        "description": "Name is the name of the AnalysisRun.",
+                        "type": "string"
+                      },
+                      "namespace": {
+                        "description": "Namespace is the namespace of the AnalysisRun.",
+                        "type": "string"
+                      },
+                      "phase": {
+                        "description": "Phase is the last observed phase of the AnalysisRun referenced by Name.",
+                        "type": "string"
+                      }
+                    },
+                    "required": [
+                      "name",
+                      "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\nprocess is in its current phase.",
+                    "type": "string"
+                  },
+                  "phase": {
+                    "description": "Phase describes the current phase of the Verification process. Generally,\nthis will be a reflection of the underlying AnalysisRun's phase, however,\nthere are exceptions to this, such as in the case where an AnalysisRun\ncannot be launched successfully.",
+                    "type": "string"
+                  }
+                },
+                "type": "object"
+              },
+              "type": "array"
+            },
             "verificationInfo": {
               "description": "VerificationInfo is information about any verification process that was\nassociated with this Freight for this Stage.",
               "properties": {
@@ -685,6 +730,51 @@
                   "description": "Name is system-assigned identifier that is derived deterministically from\nthe contents of the Freight. i.e. Two pieces of Freight can be compared for\nequality by comparing their Names.",
                   "type": "string"
                 },
+                "verificationHistory": {
+                  "description": "VerificationHistory is a stack of recent VerificationInfo. By default,\nthe last ten VerificationInfo are stored.",
+                  "items": {
+                    "description": "VerificationInfo contains information about the currently running\nVerification process.",
+                    "properties": {
+                      "analysisRun": {
+                        "description": "AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements\nthe Verification process.",
+                        "properties": {
+                          "name": {
+                            "description": "Name is the name of the AnalysisRun.",
+                            "type": "string"
+                          },
+                          "namespace": {
+                            "description": "Namespace is the namespace of the AnalysisRun.",
+                            "type": "string"
+                          },
+                          "phase": {
+                            "description": "Phase is the last observed phase of the AnalysisRun referenced by Name.",
+                            "type": "string"
+                          }
+                        },
+                        "required": [
+                          "name",
+                          "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\nprocess is in its current phase.",
+                        "type": "string"
+                      },
+                      "phase": {
+                        "description": "Phase describes the current phase of the Verification process. Generally,\nthis will be a reflection of the underlying AnalysisRun's phase, however,\nthere are exceptions to this, such as in the case where an AnalysisRun\ncannot be launched successfully.",
+                        "type": "string"
+                      }
+                    },
+                    "type": "object"
+                  },
+                  "type": "array"
+                },
                 "verificationInfo": {
                   "description": "VerificationInfo is information about any verification process that was\nassociated with this Freight for this Stage.",
                   "properties": {
@@ -914,6 +1004,51 @@
                 "description": "Name is system-assigned identifier that is derived deterministically from\nthe contents of the Freight. i.e. Two pieces of Freight can be compared for\nequality by comparing their Names.",
                 "type": "string"
               },
+              "verificationHistory": {
+                "description": "VerificationHistory is a stack of recent VerificationInfo. By default,\nthe last ten VerificationInfo are stored.",
+                "items": {
+                  "description": "VerificationInfo contains information about the currently running\nVerification process.",
+                  "properties": {
+                    "analysisRun": {
+                      "description": "AnalysisRun is a reference to the Argo Rollouts AnalysisRun that implements\nthe Verification process.",
+                      "properties": {
+                        "name": {
+                          "description": "Name is the name of the AnalysisRun.",
+                          "type": "string"
+                        },
+                        "namespace": {
+                          "description": "Namespace is the namespace of the AnalysisRun.",
+                          "type": "string"
+                        },
+                        "phase": {
+                          "description": "Phase is the last observed phase of the AnalysisRun referenced by Name.",
+                          "type": "string"
+                        }
+                      },
+                      "required": [
+                        "name",
+                        "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\nprocess is in its current phase.",
+                      "type": "string"
+                    },
+                    "phase": {
+                      "description": "Phase describes the current phase of the Verification process. Generally,\nthis will be a reflection of the underlying AnalysisRun's phase, however,\nthere are exceptions to this, such as in the case where an AnalysisRun\ncannot be launched successfully.",
+                      "type": "string"
+                    }
+                  },
+                  "type": "object"
+                },
+                "type": "array"
+              },
               "verificationInfo": {
                 "description": "VerificationInfo is information about any verification process that was\nassociated with this Freight for this Stage.",
                 "properties": {
diff --git a/ui/src/gen/v1alpha1/generated_pb.ts b/ui/src/gen/v1alpha1/generated_pb.ts
index c04a135d..a08b274d 100644
--- a/ui/src/gen/v1alpha1/generated_pb.ts
+++ b/ui/src/gen/v1alpha1/generated_pb.ts
@@ -1124,6 +1124,14 @@ export class FreightReference extends Message<FreightReference> {
    */
   verificationInfo?: VerificationInfo;
 
+  /**
+   * VerificationHistory is a stack of recent VerificationInfo. By default,
+   * the last ten VerificationInfo are stored.
+   *
+   * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.VerificationInfo verificationHistory = 7;
+   */
+  verificationHistory: VerificationInfo[] = [];
+
   constructor(data?: PartialMessage<FreightReference>) {
     super();
     proto2.util.initPartial(data, this);
@@ -1138,6 +1146,7 @@ export class FreightReference extends Message<FreightReference> {
     { no: 3, name: "images", kind: "message", T: Image, repeated: true },
     { no: 4, name: "charts", kind: "message", T: Chart, repeated: true },
     { no: 5, name: "verificationInfo", kind: "message", T: VerificationInfo, opt: true },
+    { no: 7, name: "verificationHistory", kind: "message", T: VerificationInfo, repeated: true },
   ]);
 
   static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): FreightReference {


Test patch:
diff --git a/api/v1alpha1/helpers_test.go b/api/v1alpha1/helpers_test.go
index 0472b797..17176b65 100644
--- a/api/v1alpha1/helpers_test.go
+++ b/api/v1alpha1/helpers_test.go
@@ -7,10 +7,47 @@ import (
 	"github.com/stretchr/testify/require"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	k8sruntime "k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
 
+func TestAddFinalizer(t *testing.T) {
+	const testNamespace = "fake-namespace"
+	const testStageName = "fake-stage"
+
+	ctx := context.Background()
+
+	stage := &Stage{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: testNamespace,
+			Name:      testStageName,
+		},
+	}
+
+	scheme := k8sruntime.NewScheme()
+	err := AddToScheme(scheme)
+	require.NoError(t, err)
+	c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(stage).Build()
+
+	err = AddFinalizer(ctx, c, stage)
+	require.NoError(t, err)
+
+	patchedStage := &Stage{}
+	err = c.Get(
+		ctx,
+		types.NamespacedName{
+			Namespace: testNamespace,
+			Name:      testStageName,
+		},
+		patchedStage,
+	)
+	require.NoError(t, err)
+
+	require.True(t, controllerutil.ContainsFinalizer(patchedStage, FinalizerName))
+}
+
 func TestClearAnnotations(t *testing.T) {
 	scheme := k8sruntime.NewScheme()
 	require.NoError(t, SchemeBuilder.AddToScheme(scheme))
diff --git a/api/v1alpha1/stage_types_test.go b/api/v1alpha1/stage_types_test.go
index e7eec04d..ae9a759c 100644
--- a/api/v1alpha1/stage_types_test.go
+++ b/api/v1alpha1/stage_types_test.go
@@ -149,3 +149,52 @@ func TestFreightReferenceStackPush(t *testing.T) {
 		})
 	}
 }
+
+func TestVerificationInfoStack_UpdateOrPush(t *testing.T) {
+	testCases := []struct {
+		name          string
+		stack         VerificationInfoStack
+		newInfo       []VerificationInfo
+		expectedStack VerificationInfoStack
+	}{
+		{
+			name:          "initial stack is nil",
+			stack:         nil,
+			newInfo:       []VerificationInfo{{ID: "foo"}, {ID: "bar"}},
+			expectedStack: VerificationInfoStack{{ID: "foo"}, {ID: "bar"}},
+		},
+		{
+			name:          "initial stack is not nil",
+			stack:         VerificationInfoStack{{ID: "foo"}},
+			newInfo:       []VerificationInfo{{ID: "bar"}, {ID: "baz"}},
+			expectedStack: VerificationInfoStack{{ID: "bar"}, {ID: "baz"}, {ID: "foo"}},
+		},
+		{
+			name:    "initial stack has matching IDs",
+			stack:   VerificationInfoStack{{ID: "foo"}, {ID: "bar"}},
+			newInfo: []VerificationInfo{{ID: "bar", Phase: VerificationPhaseFailed}, {ID: "baz"}, {ID: "zab"}},
+			expectedStack: VerificationInfoStack{
+				{ID: "baz"},
+				{ID: "zab"},
+				{ID: "foo"},
+				{ID: "bar", Phase: VerificationPhaseFailed},
+			},
+		},
+		{
+			name: "initial stack is full",
+			stack: VerificationInfoStack{
+				{}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+			},
+			newInfo: []VerificationInfo{{ID: "foo"}},
+			expectedStack: VerificationInfoStack{
+				{ID: "foo"}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+			},
+		},
+	}
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			testCase.stack.UpdateOrPush(testCase.newInfo...)
+			require.Equal(t, testCase.expectedStack, testCase.stack)
+		})
+	}
+}
diff --git a/internal/controller/stages/stages_test.go b/internal/controller/stages/stages_test.go
index 142279db..c1da97c2 100644
--- a/internal/controller/stages/stages_test.go
+++ b/internal/controller/stages/stages_test.go
@@ -422,6 +422,14 @@ func TestSyncNormalStage(t *testing.T) {
 								Name: "fake-analysis-run",
 							},
 						},
+						VerificationHistory: []kargoapi.VerificationInfo{
+							{
+								Phase: kargoapi.VerificationPhaseFailed,
+								AnalysisRun: &kargoapi.AnalysisRunReference{
+									Name: "fake-analysis-run",
+								},
+							},
+						},
 					},
 				},
 			},
@@ -487,16 +495,25 @@ func TestSyncNormalStage(t *testing.T) {
 				require.NoError(t, err)
 				require.NotNil(t, newStatus.CurrentFreight)
 				require.Equal(t, kargoapi.StagePhaseSteady, newStatus.Phase)
+
+				expectInfo := kargoapi.VerificationInfo{
+					Phase:   kargoapi.VerificationPhaseError,
+					Message: "something went wrong",
+				}
+
 				require.Equal(
 					t,
-					&kargoapi.VerificationInfo{
-						Phase:   kargoapi.VerificationPhaseError,
-						Message: "something went wrong",
-					},
+					&expectInfo,
 					newStatus.CurrentFreight.VerificationInfo,
 				)
+				require.Equal(
+					t,
+					kargoapi.VerificationInfoStack{expectInfo},
+					newStatus.CurrentFreight.VerificationHistory,
+				)
 				// Everything else should be returned unchanged
 				newStatus.CurrentFreight.VerificationInfo = nil
+				newStatus.CurrentFreight.VerificationHistory = nil
 				newStatus.Phase = initialStatus.Phase
 				require.Equal(t, initialStatus, newStatus)
 			},
diff --git a/internal/controller/stages/verification_test.go b/internal/controller/stages/verification_test.go
index 210ada53..026ae41e 100644
--- a/internal/controller/stages/verification_test.go
+++ b/internal/controller/stages/verification_test.go
@@ -752,6 +752,10 @@ func TestAbortVerification(t *testing.T) {
 				require.Equal(t, "fake-id", vi.ID)
 				require.Equal(t, kargoapi.VerificationPhaseAborted, vi.Phase)
 				require.Equal(t, "Verification aborted by user", vi.Message)
+				require.Equal(t, &kargoapi.AnalysisRunReference{
+					Name:      "fake-run",
+					Namespace: "fake-namespace",
+				}, vi.AnalysisRun)
 			},
 		},
 	}
diff --git a/internal/webhook/stage/webhook_test.go b/internal/webhook/stage/webhook_test.go
index 36a41bcc..0fcfcf19 100644
--- a/internal/webhook/stage/webhook_test.go
+++ b/internal/webhook/stage/webhook_test.go
@@ -12,7 +12,6 @@ import (
 	"k8s.io/apimachinery/pkg/util/validation/field"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
-	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	kargoapi "github.com/akuity/kargo/api/v1alpha1"
@@ -78,34 +77,6 @@ func TestDefault(t *testing.T) {
 				require.Equal(t, testShardName, stage.Spec.Shard)
 			},
 		},
-		{
-			name:      "finalizer gets added on create",
-			operation: admissionv1.Create,
-			stage: &kargoapi.Stage{
-				Spec: &kargoapi.StageSpec{},
-			},
-			assertions: func(t *testing.T, stage *kargoapi.Stage, err error) {
-				require.NoError(t, err)
-				require.True(
-					t,
-					controllerutil.ContainsFinalizer(stage, kargoapi.FinalizerName),
-				)
-			},
-		},
-		{
-			name:      "finalizer does not get added on update",
-			operation: admissionv1.Update,
-			stage: &kargoapi.Stage{
-				Spec: &kargoapi.StageSpec{},
-			},
-			assertions: func(t *testing.T, stage *kargoapi.Stage, err error) {
-				require.NoError(t, err)
-				require.False(
-					t,
-					controllerutil.ContainsFinalizer(stage, kargoapi.FinalizerName),
-				)
-			},
-		},
 	}
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {