[rust-3p] Update tuf to 0.3.0-beta7

Change-Id: I7b3ad95824b51e11925010fc33590f4eb9a5fa97
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693938
Commit-Queue: Erick Tryzelaar <etryzelaar@google.com>
Fuchsia-Auto-Submit: Erick Tryzelaar <etryzelaar@google.com>
Reviewed-by: Ben Keller <galbanum@google.com>
diff --git a/src/developer/ffx/lib/pkg/src/repository.rs b/src/developer/ffx/lib/pkg/src/repository.rs
index 6f5dc07..1a2ef84 100644
--- a/src/developer/ffx/lib/pkg/src/repository.rs
+++ b/src/developer/ffx/lib/pkg/src/repository.rs
@@ -34,8 +34,8 @@
         crypto::KeyType,
         interchange::Json,
         metadata::{
-            Metadata as _, MetadataPath, MetadataVersion, RawSignedMetadata, Role,
-            TargetDescription, TargetPath, TargetsMetadata,
+            Metadata as _, MetadataPath, MetadataVersion, RawSignedMetadata, TargetDescription,
+            TargetPath, TargetsMetadata,
         },
         repository::{EphemeralRepository, RepositoryProvider},
         verify::Verified,
@@ -335,8 +335,8 @@
             // https://github.com/heartsucker/rust-tuf/pull/318 lands.
             match client.update().await {
                 Ok(_) => {}
-                Err(err @ tuf::Error::ExpiredMetadata(Role::Root)) => {
-                    return Err(err.into());
+                Err(tuf::Error::ExpiredMetadata(path)) if path == MetadataPath::root() => {
+                    return Err(tuf::Error::ExpiredMetadata(path).into());
                 }
                 Err(tuf::Error::ExpiredMetadata(_)) => {}
                 Err(err) => {
@@ -595,16 +595,12 @@
     let raw_signed_meta = {
         // FIXME(http://fxbug.dev/92126) we really should be initializing trust, rather than just
         // trusting 1.root.json.
-        let root = tuf_repo
-            .fetch_metadata(&MetadataPath::from_role(&Role::Root), MetadataVersion::Number(1))
-            .await;
+        let root = tuf_repo.fetch_metadata(&MetadataPath::root(), MetadataVersion::Number(1)).await;
 
         // If we couldn't find 1.root.json, see if root.json exists and try to initialize trust with it.
         let mut root = match root {
             Err(tuf::Error::NotFound) => {
-                tuf_repo
-                    .fetch_metadata(&MetadataPath::from_role(&Role::Root), MetadataVersion::None)
-                    .await?
+                tuf_repo.fetch_metadata(&MetadataPath::root(), MetadataVersion::None).await?
             }
             Err(err) => return Err(err.into()),
             Ok(root) => root,
diff --git a/src/sys/pkg/bin/pkg-resolver/src/repository.rs b/src/sys/pkg/bin/pkg-resolver/src/repository.rs
index d6035a0..11b63ea 100644
--- a/src/sys/pkg/bin/pkg-resolver/src/repository.rs
+++ b/src/sys/pkg/bin/pkg-resolver/src/repository.rs
@@ -343,6 +343,7 @@
             path::{Path, PathBuf},
             sync::Arc,
         },
+        tuf::metadata::MetadataPath,
         updating_tuf_client::METADATA_CACHE_STALE_TIMEOUT,
     };
 
@@ -554,8 +555,10 @@
         assert_matches!(
             repo.get_merkle_at_path(&target_path).await,
             Err(MerkleForError::FetchTargetDescription(
-                extracted_path, TufError::MissingMetadata(tuf::metadata::Role::Snapshot)))
-            if extracted_path == "just-meta-far/0"
+                extracted_path, TufError::MissingMetadata(metadata_path)))
+            if
+                metadata_path == MetadataPath::snapshot() &&
+                extracted_path == "just-meta-far/0"
         );
     }
 
diff --git a/src/sys/pkg/bin/pkg-resolver/src/repository/local_provider.rs b/src/sys/pkg/bin/pkg-resolver/src/repository/local_provider.rs
index a483abc..05167c4 100644
--- a/src/sys/pkg/bin/pkg-resolver/src/repository/local_provider.rs
+++ b/src/sys/pkg/bin/pkg-resolver/src/repository/local_provider.rs
@@ -103,7 +103,6 @@
         fidl_fuchsia_pkg::LocalMirrorMarker,
         fuchsia_async as fasync,
         fuchsia_pkg_testing::{FakePkgLocalMirror, PackageBuilder, Repository, RepositoryBuilder},
-        tuf::metadata::Role,
     };
 
     struct TestEnv {
@@ -146,7 +145,7 @@
         let env = TestEnv::new().await;
         let mut result = env
             .provider
-            .fetch_metadata(&MetadataPath::from_role(&Role::Root), MetadataVersion::None)
+            .fetch_metadata(&MetadataPath::root(), MetadataVersion::None)
             .await
             .expect("fetch_metadata succeeds");
 
@@ -160,7 +159,7 @@
         let env = TestEnv::new().await;
         let mut result = env
             .provider
-            .fetch_metadata(&MetadataPath::from_role(&Role::Root), MetadataVersion::Number(1))
+            .fetch_metadata(&MetadataPath::root(), MetadataVersion::Number(1))
             .await
             .expect("fetch_metadata succeeds");
 
@@ -172,10 +171,8 @@
     #[fasync::run_singlethreaded(test)]
     async fn test_fetch_metadata_v4_fails() {
         let env = TestEnv::new().await;
-        let result = env
-            .provider
-            .fetch_metadata(&MetadataPath::from_role(&Role::Root), MetadataVersion::Number(4))
-            .await;
+        let result =
+            env.provider.fetch_metadata(&MetadataPath::root(), MetadataVersion::Number(4)).await;
 
         assert!(result.is_err());
     }
diff --git a/third_party/rust_crates/BUILD.gn b/third_party/rust_crates/BUILD.gn
index 568056f..17ab911 100644
--- a/third_party/rust_crates/BUILD.gn
+++ b/third_party/rust_crates/BUILD.gn
@@ -974,7 +974,7 @@
 }
 
 group("tuf") {
-  public_deps = [ ":tuf-v0_3_0-beta6" ]
+  public_deps = [ ":tuf-v0_3_0-beta7" ]
 }
 
 group("tui") {
@@ -11023,10 +11023,10 @@
   visibility = [ ":*" ]
 }
 
-rust_library("tuf-v0_3_0-beta6") {
+rust_library("tuf-v0_3_0-beta7") {
   crate_name = "tuf"
   crate_root = "//third_party/rust_crates/vendor/tuf/./src/lib.rs"
-  output_name = "tuf-952564b68aeb1a54"
+  output_name = "tuf-96c9a4f85a521c39"
   configs -= [ "//build/config/rust:2018_idioms" ]
 
   deps = []
@@ -11054,8 +11054,8 @@
   rustflags = [
     "--cap-lints=allow",
     "--edition=2018",
-    "-Cmetadata=952564b68aeb1a54",
-    "-Cextra-filename=-952564b68aeb1a54",
+    "-Cmetadata=96c9a4f85a521c39",
+    "-Cextra-filename=-96c9a4f85a521c39",
     "--cfg=feature=\"hyper_014\"",
   ]
 
diff --git a/third_party/rust_crates/Cargo.lock b/third_party/rust_crates/Cargo.lock
index c1d7a9e..1512db5 100644
--- a/third_party/rust_crates/Cargo.lock
+++ b/third_party/rust_crates/Cargo.lock
@@ -4301,9 +4301,9 @@
 
 [[package]]
 name = "tuf"
-version = "0.3.0-beta6"
+version = "0.3.0-beta7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10732acf3faedf67088c0e74d0e272d3081f6c0baafdb32a22d1703013a5f03e"
+checksum = "162303bc477f3f6e2919b4a0e2f4d5e421b13c430321251b3d68941b784ab354"
 dependencies = [
  "chrono",
  "data-encoding",
diff --git a/third_party/rust_crates/Cargo.toml b/third_party/rust_crates/Cargo.toml
index 02d6c21..adbecef 100644
--- a/third_party/rust_crates/Cargo.toml
+++ b/third_party/rust_crates/Cargo.toml
@@ -190,7 +190,7 @@
 strsim = "0.10.0"
 structopt = "0.2.14"
 tempfile = "3.2"
-tuf = { version = "0.3.0-beta6", default-features = false, features = ["hyper_014"] }
+tuf = { version = "0.3.0-beta7", default-features = false, features = ["hyper_014"] }
 tui = "0.16.0"
 termion = "1.5.3"
 test-case = "1.1.0"
diff --git a/third_party/rust_crates/vendor/tuf/.cargo-checksum.json b/third_party/rust_crates/vendor/tuf/.cargo-checksum.json
index f5e365d..902b25d 100644
--- a/third_party/rust_crates/vendor/tuf/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/tuf/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"1bfad60e2967b9119fd37046ab884729b5cc6ff9a26e75c185c65365802aa3af","LICENSE-APACHE":"2bdfac761d8c617b32c5e24c429518d71be44aac4aba1a6ac7aa196f929bb601","LICENSE-MIT":"61ed40687d2656636a04680013dffe41d5c724201edaa84045e0677b8e2064d6","README.md":"a18679a3942a9c8c279dc411e29030dab720745af669291b9398723b2c56956f","src/client.rs":"6e5c44c9c1de685f3932c2c6636a1c9c8f698b7da6eb988a0365e70de83d80ca","src/crypto.rs":"46c297f21c70a0861765cd30fe1fb7dc0e646ae8ca1cf8228143d613b565f4c8","src/database.rs":"7595fddcc45c08b47680ceae07ead14c1a3ec98c4dcfa6b601f2d3a09a5cebfb","src/error.rs":"9a0a051b3be5a7e56990ed02c83b2c41072e19e28f12ac4cf8c870dad0c0776a","src/format_hex.rs":"38b2ac4e7bd69a6edf2f35027600211452f084e6294415536cd305c3e849485a","src/interchange/cjson/mod.rs":"14ac2fe8adc1d2be53a29bfffedeba99b9cb435fbfb8c3d72b0fbcf51de8fffa","src/interchange/cjson/pretty.rs":"7948954ebbb88de1ddc1969600814ea23add7604ade51cb7927950002bee5f7f","src/interchange/cjson/shims.rs":"6f17283c0e331b0e5fe3b97340c913aef3869348828c4730164e126bd05f4a9a","src/interchange/mod.rs":"4ec7047ab6a6f9a256d056a4026e412dd4cb207451b24506629f614b08d897a8","src/lib.rs":"12f03d45f6772614c64d81c5f2962bd9d9042ca10c79443a67f13de24983209b","src/metadata.rs":"834c58bfd2e10a4806ae82fe7b21934955f9b323890f5e130c73cc4a8fa0a327","src/repo_builder.rs":"22fc6d0352bd0020c85da270d6a2ab78fe83988c7f32cc3634e68c1c60531d28","src/repository.rs":"a1052d6e34edbf1d71acb3475c2d6936ce59dde8ac870d20f4f1604e8f86fa32","src/repository/ephemeral.rs":"acbe838d2f3f040630eef1d2976fc486315cb315d7eea789f3e06dea8fb7adfd","src/repository/error_repo.rs":"ece7afa0010b56b6b4b8354488ae788a6c68747507b88534110f288910141afa","src/repository/file_system.rs":"022f2a47d0e154c410fc450d40f39345978ef443558cc5ef7c1c0e213464f6e7","src/repository/http.rs":"6a1630a73856a574fd3305e7955c9d36cedd7907ab6e9c3231ee044c79337c08","src/repository/track_repo.rs":"601b130aad6c669d90b3bd12c04fa768179d62c0dad42c2b284164980a699bf9","src/util.rs":"78d2ef67aae28ae421aafa70d5cc367b0d65ebd683cab444f00b51b26542fa40","src/verify.rs":"7e86461716e3c7d314f67da6f9de4142580cd48970fc10f4cd58b5e08da1ef56","tests/ed25519/ed25519-1":"39b04e2225d769fa8a3af913c40559b09cd5f4fb889827c3f6ce3fb99b727654","tests/ed25519/ed25519-1.pk8.der":"8db9bbc5ac4480f3cc645e610f7ed1d7ab69f5718cd12e275eaaeb107d704799","tests/ed25519/ed25519-1.pub":"afbe17fbfbc28b1e1220c162883da3f616f21d08a484c013cee9aae332989108","tests/ed25519/ed25519-1.spki.der":"a9fadf06b901e2504148310195981a4c64bf4ab13a51f98e37d90fe22ddd2456","tests/ed25519/ed25519-2.pk8.der":"dead09835a4a725c6278b22e1eeb1429b0827554503f3c101c93ffd567096d45","tests/ed25519/ed25519-3.pk8.der":"a95f7d893b13b5eea411bbc76b355219a86dd469e47efcc1cebfd327ea739a32","tests/ed25519/ed25519-4.pk8.der":"f0385d82f284eaaea6bf71a71d7a0961535562451c98b59da33660eed740606e","tests/ed25519/ed25519-5.pk8.der":"2a7566c8a1a56644fd0df47f2eaeba6a24432fe2b6461d33821f35b93bae70a3","tests/ed25519/ed25519-6.pk8.der":"6595ddaee0a08b59c14bc83a9dba4a7993ddd24cac7d46aed947269370ae7a1b","tests/integration.rs":"cc4d3d724a6513440af65804661292e4bb399206e68055da19b1dfebd435218b","tests/rsa/gen.sh":"1422883e49a63544b951bb1b76e98bf5a96e6e2353349d98ca2cac9ff7d0b4ac","tests/rsa/rsa-2048":"1ec467d90c163814dbf2e2de913f8b3714ee0f1cbd3eeb863112db818e3b92df","tests/rsa/rsa-2048.der":"3df4f04a2badbb2cd3e8204a9648cc8d4ee0094a740de1694be5e8348e7a5ccb","tests/rsa/rsa-2048.pk8.der":"8998d4d952040173a0d652207132d3bd62c668338190f150b184b2a8be3ae2f5","tests/rsa/rsa-2048.pkcs1.der":"6f541b7eb4af92d33bea3cb93d7b91af27042c1cd4dc9d70e2c78d9b883d9bba","tests/rsa/rsa-2048.spki.der":"960e2da59100772ecadff393e7d703fe5a7aed2600c63e7eef70daa61f671535","tests/rsa/rsa-4096.der":"9065496b699e242fb1b5e17a147322b0a3ede74752205ccfb05a07ef70c4e748","tests/rsa/rsa-4096.pk8.der":"af4c5b20cb762c238659764c7cfd4fe43b19ac3d971421cc82bdf3092416b3ac","tests/rsa/rsa-4096.pkcs1.der":"e5d5ceb6ecfe59e45b9766cc999ef2fad4897f245e191fad6ebdaba4ce79f97d","tests/rsa/rsa-4096.spki.der":"e0ad84cd41a33d6c6a671346565de376b3cd806011a965e9e427432748021de9","tests/simple_example.rs":"8444d37fc5a2105d2fc44ef8639da8b6591ff671e04c80804af8bffd47a10037"},"package":"10732acf3faedf67088c0e74d0e272d3081f6c0baafdb32a22d1703013a5f03e"}
\ No newline at end of file
+{"files":{"Cargo.toml":"135fe2bde1d4df41d20d6e2cc70a48e800982451e622e2260d44fa1a8aa9507d","LICENSE-APACHE":"2bdfac761d8c617b32c5e24c429518d71be44aac4aba1a6ac7aa196f929bb601","LICENSE-MIT":"61ed40687d2656636a04680013dffe41d5c724201edaa84045e0677b8e2064d6","README.md":"a18679a3942a9c8c279dc411e29030dab720745af669291b9398723b2c56956f","src/client.rs":"3d43f2c3694669c019c21c971b77ab364b05518757874c14111db104e7bd43a4","src/crypto.rs":"46c297f21c70a0861765cd30fe1fb7dc0e646ae8ca1cf8228143d613b565f4c8","src/database.rs":"6f3b5b0fdf4636db9e293b957371cc311c0fda937a8dfc6caecbd2bdeac91750","src/error.rs":"980bbbb1136e72eaa6068d363634cb5788f4d959b24e49ec471b452d3ffe924f","src/format_hex.rs":"38b2ac4e7bd69a6edf2f35027600211452f084e6294415536cd305c3e849485a","src/interchange/cjson/mod.rs":"14ac2fe8adc1d2be53a29bfffedeba99b9cb435fbfb8c3d72b0fbcf51de8fffa","src/interchange/cjson/pretty.rs":"7948954ebbb88de1ddc1969600814ea23add7604ade51cb7927950002bee5f7f","src/interchange/cjson/shims.rs":"ca1ac7ac79b8085f802fd0c092f84eda5afb683131d8b6c0446d9df3ce563a53","src/interchange/mod.rs":"4ec7047ab6a6f9a256d056a4026e412dd4cb207451b24506629f614b08d897a8","src/lib.rs":"12f03d45f6772614c64d81c5f2962bd9d9042ca10c79443a67f13de24983209b","src/metadata.rs":"9cbcdd04e3b52ab14f52ab0189a07925cdefb341edac00cab032712ec8749cc4","src/repo_builder.rs":"c235454f33905075087f05d7d1f3ef9809b79a5de1a54ce4d47a1da2c92dfe2f","src/repository.rs":"85685c434ff8e55292682125f6ef38643542e1b010d886f2af9812aeb1202411","src/repository/ephemeral.rs":"acbe838d2f3f040630eef1d2976fc486315cb315d7eea789f3e06dea8fb7adfd","src/repository/error_repo.rs":"ece7afa0010b56b6b4b8354488ae788a6c68747507b88534110f288910141afa","src/repository/file_system.rs":"029e7d09c11c290e4862729dd983d9d28018cb7dbe27760c2e2a34b0b5711874","src/repository/http.rs":"6a1630a73856a574fd3305e7955c9d36cedd7907ab6e9c3231ee044c79337c08","src/repository/track_repo.rs":"7c14ed2c041fc57eb63aa2137b11293403dc85ac4f6267b9f6b413d549bce3bc","src/util.rs":"78d2ef67aae28ae421aafa70d5cc367b0d65ebd683cab444f00b51b26542fa40","src/verify.rs":"7e86461716e3c7d314f67da6f9de4142580cd48970fc10f4cd58b5e08da1ef56","tests/ed25519/ed25519-1":"39b04e2225d769fa8a3af913c40559b09cd5f4fb889827c3f6ce3fb99b727654","tests/ed25519/ed25519-1.pk8.der":"8db9bbc5ac4480f3cc645e610f7ed1d7ab69f5718cd12e275eaaeb107d704799","tests/ed25519/ed25519-1.pub":"afbe17fbfbc28b1e1220c162883da3f616f21d08a484c013cee9aae332989108","tests/ed25519/ed25519-1.spki.der":"a9fadf06b901e2504148310195981a4c64bf4ab13a51f98e37d90fe22ddd2456","tests/ed25519/ed25519-2.pk8.der":"dead09835a4a725c6278b22e1eeb1429b0827554503f3c101c93ffd567096d45","tests/ed25519/ed25519-3.pk8.der":"a95f7d893b13b5eea411bbc76b355219a86dd469e47efcc1cebfd327ea739a32","tests/ed25519/ed25519-4.pk8.der":"f0385d82f284eaaea6bf71a71d7a0961535562451c98b59da33660eed740606e","tests/ed25519/ed25519-5.pk8.der":"2a7566c8a1a56644fd0df47f2eaeba6a24432fe2b6461d33821f35b93bae70a3","tests/ed25519/ed25519-6.pk8.der":"6595ddaee0a08b59c14bc83a9dba4a7993ddd24cac7d46aed947269370ae7a1b","tests/integration.rs":"4dc68fa351f4f80ca73dbde6a5e3edc6e53a76ff85f768d310ae237118d936fe","tests/rsa/gen.sh":"1422883e49a63544b951bb1b76e98bf5a96e6e2353349d98ca2cac9ff7d0b4ac","tests/rsa/rsa-2048":"1ec467d90c163814dbf2e2de913f8b3714ee0f1cbd3eeb863112db818e3b92df","tests/rsa/rsa-2048.der":"3df4f04a2badbb2cd3e8204a9648cc8d4ee0094a740de1694be5e8348e7a5ccb","tests/rsa/rsa-2048.pk8.der":"8998d4d952040173a0d652207132d3bd62c668338190f150b184b2a8be3ae2f5","tests/rsa/rsa-2048.pkcs1.der":"6f541b7eb4af92d33bea3cb93d7b91af27042c1cd4dc9d70e2c78d9b883d9bba","tests/rsa/rsa-2048.spki.der":"960e2da59100772ecadff393e7d703fe5a7aed2600c63e7eef70daa61f671535","tests/rsa/rsa-4096.der":"9065496b699e242fb1b5e17a147322b0a3ede74752205ccfb05a07ef70c4e748","tests/rsa/rsa-4096.pk8.der":"af4c5b20cb762c238659764c7cfd4fe43b19ac3d971421cc82bdf3092416b3ac","tests/rsa/rsa-4096.pkcs1.der":"e5d5ceb6ecfe59e45b9766cc999ef2fad4897f245e191fad6ebdaba4ce79f97d","tests/rsa/rsa-4096.spki.der":"e0ad84cd41a33d6c6a671346565de376b3cd806011a965e9e427432748021de9","tests/simple_example.rs":"8444d37fc5a2105d2fc44ef8639da8b6591ff671e04c80804af8bffd47a10037"},"package":"162303bc477f3f6e2919b4a0e2f4d5e421b13c430321251b3d68941b784ab354"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/tuf/Cargo.toml b/third_party/rust_crates/vendor/tuf/Cargo.toml
index c59faf8..a4a8496 100644
--- a/third_party/rust_crates/vendor/tuf/Cargo.toml
+++ b/third_party/rust_crates/vendor/tuf/Cargo.toml
@@ -12,13 +12,20 @@
 [package]
 edition = "2018"
 name = "tuf"
-version = "0.3.0-beta6"
-authors = ["heartsucker <heartsucker@autistici.org>", "Erick Tryzelaar <etryzelaar@google.com>"]
+version = "0.3.0-beta7"
+authors = [
+    "heartsucker <heartsucker@autistici.org>",
+    "Erick Tryzelaar <etryzelaar@google.com>",
+]
 description = "Library for The Update Framework (TUF)"
 homepage = "https://github.com/theupdateframework/rust-tuf"
 documentation = "https://docs.rs/tuf"
 readme = "README.md"
-keywords = ["security", "update", "repository"]
+keywords = [
+    "security",
+    "update",
+    "repository",
+]
 categories = ["cryptography"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/theupdateframework/rust-tuf"
@@ -26,6 +33,7 @@
 [lib]
 name = "tuf"
 path = "./src/lib.rs"
+
 [dependencies.chrono]
 version = "0.4"
 features = ["serde"]
@@ -55,7 +63,11 @@
 
 [dependencies.hyper_014]
 version = "0.14.15"
-features = ["stream", "client", "http1"]
+features = [
+    "stream",
+    "client",
+    "http1",
+]
 optional = true
 default-features = false
 package = "hyper"
@@ -92,6 +104,7 @@
 
 [dependencies.url]
 version = "2"
+
 [dev-dependencies.assert_matches]
 version = "1.5.0"
 
diff --git a/third_party/rust_crates/vendor/tuf/src/client.rs b/third_party/rust_crates/vendor/tuf/src/client.rs
index 3738672..81b28ea 100644
--- a/third_party/rust_crates/vendor/tuf/src/client.rs
+++ b/third_party/rust_crates/vendor/tuf/src/client.rs
@@ -51,7 +51,7 @@
 //! # }
 //! ```
 
-use chrono::offset::Utc;
+use chrono::{offset::Utc, DateTime};
 use futures_io::AsyncRead;
 use log::{error, warn};
 use std::future::Future;
@@ -62,8 +62,8 @@
 use crate::error::Error;
 use crate::interchange::DataInterchange;
 use crate::metadata::{
-    Metadata, MetadataPath, MetadataVersion, RawSignedMetadata, Role, RootMetadata,
-    SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata,
+    Metadata, MetadataPath, MetadataVersion, RawSignedMetadata, RootMetadata, SnapshotMetadata,
+    TargetDescription, TargetPath, TargetsMetadata,
 };
 use crate::repository::{Repository, RepositoryProvider, RepositoryStorage};
 use crate::verify::Verified;
@@ -128,7 +128,7 @@
     ///     .timestamp_key(public_key.clone())
     ///     .signed::<Json>(&private_key)?;
     ///
-    /// let root_path = MetadataPath::from_role(&Role::Root);
+    /// let root_path = MetadataPath::root();
     /// let root_version = MetadataVersion::Number(root_version);
     ///
     /// local.store_metadata(
@@ -148,7 +148,7 @@
     /// ```
     pub async fn with_trusted_local(config: Config, local: L, remote: R) -> Result<Self> {
         let (local, remote) = (Repository::new(local), Repository::new(remote));
-        let root_path = MetadataPath::from_role(&Role::Root);
+        let root_path = MetadataPath::root();
 
         // FIXME should this be MetadataVersion::None so we bootstrap with the latest version?
         let root_version = MetadataVersion::Number(1);
@@ -261,7 +261,7 @@
     ///     .timestamp_key(public_key.clone())
     ///     .signed::<Json>(&private_key)?;
     ///
-    /// let root_path = MetadataPath::from_role(&Role::Root);
+    /// let root_path = MetadataPath::root();
     /// let root_version = MetadataVersion::Number(root_version);
     ///
     /// remote.store_metadata(
@@ -295,7 +295,7 @@
     {
         let (mut local, remote) = (Repository::new(local), Repository::new(remote));
 
-        let root_path = MetadataPath::from_role(&Role::Root);
+        let root_path = MetadataPath::root();
         let (fetched, raw_root) = fetch_metadata_from_local_or_else_remote(
             &root_path,
             root_version,
@@ -374,13 +374,32 @@
         local: Repository<L, D>,
         remote: Repository<R, D>,
     ) -> Result<Self> {
+        let start_time = Utc::now();
+
         let res = async {
-            let _r = Self::update_root_with_repos(&config, &mut tuf, None, &local).await?;
-            let _ts = Self::update_timestamp_with_repos(&config, &mut tuf, None, &local).await?;
-            let _sn =
-                Self::update_snapshot_with_repos(&config, &mut tuf, None, &local, false).await?;
-            let _ta =
-                Self::update_targets_with_repos(&config, &mut tuf, None, &local, false).await?;
+            let _r =
+                Self::update_root_with_repos(&start_time, &config, &mut tuf, None, &local).await?;
+            let _ts =
+                Self::update_timestamp_with_repos(&start_time, &config, &mut tuf, None, &local)
+                    .await?;
+            let _sn = Self::update_snapshot_with_repos(
+                &start_time,
+                &config,
+                &mut tuf,
+                None,
+                &local,
+                false,
+            )
+            .await?;
+            let _ta = Self::update_targets_with_repos(
+                &start_time,
+                &config,
+                &mut tuf,
+                None,
+                &local,
+                false,
+            )
+            .await?;
 
             Ok(())
         }
@@ -405,10 +424,20 @@
     ///
     /// Returns `true` if an update occurred and `false` otherwise.
     pub async fn update(&mut self) -> Result<bool> {
-        let r = self.update_root().await?;
-        let ts = self.update_timestamp().await?;
-        let sn = self.update_snapshot().await?;
-        let ta = self.update_targets().await?;
+        self.update_with_start_time(&Utc::now()).await
+    }
+
+    /// Update TUF metadata from the remote repository, using the specified time to determine if
+    /// the metadata is expired.
+    ///
+    /// Returns `true` if an update occurred and `false` otherwise.
+    ///
+    /// **WARNING**: Using an older time opens up users to a freeze attack.
+    pub async fn update_with_start_time(&mut self, start_time: &DateTime<Utc>) -> Result<bool> {
+        let r = self.update_root(start_time).await?;
+        let ts = self.update_timestamp(start_time).await?;
+        let sn = self.update_snapshot(start_time).await?;
+        let ta = self.update_targets(start_time).await?;
 
         Ok(r || ts || sn || ta)
     }
@@ -462,8 +491,9 @@
     /// Update TUF root metadata from the remote repository.
     ///
     /// Returns `true` if an update occurred and `false` otherwise.
-    pub async fn update_root(&mut self) -> Result<bool> {
+    pub async fn update_root(&mut self, start_time: &DateTime<Utc>) -> Result<bool> {
         Self::update_root_with_repos(
+            start_time,
             &self.config,
             &mut self.tuf,
             Some(&mut self.local),
@@ -473,6 +503,7 @@
     }
 
     async fn update_root_with_repos<Remote>(
+        start_time: &DateTime<Utc>,
         config: &Config,
         tuf: &mut Database<D>,
         mut local: Option<&mut Repository<L, D>>,
@@ -481,7 +512,7 @@
     where
         Remote: RepositoryProvider<D>,
     {
-        let root_path = MetadataPath::from_role(&Role::Root);
+        let root_path = MetadataPath::root();
 
         let mut updated = false;
 
@@ -556,9 +587,9 @@
 
         // TODO: Consider moving the root metadata expiration check into `tuf::Database`, since that's
         // where we check timestamp/snapshot/targets/delegations for expiration.
-        if tuf.trusted_root().expires() <= &Utc::now() {
+        if tuf.trusted_root().expires() <= start_time {
             error!("Root metadata expired, potential freeze attack");
-            return Err(Error::ExpiredMetadata(Role::Root));
+            return Err(Error::ExpiredMetadata(MetadataPath::root()));
         }
 
         /////////////////////////////////////////
@@ -571,8 +602,9 @@
     }
 
     /// Returns `true` if an update occurred and `false` otherwise.
-    async fn update_timestamp(&mut self) -> Result<bool> {
+    async fn update_timestamp(&mut self, start_time: &DateTime<Utc>) -> Result<bool> {
         Self::update_timestamp_with_repos(
+            start_time,
             &self.config,
             &mut self.tuf,
             Some(&mut self.local),
@@ -582,6 +614,7 @@
     }
 
     async fn update_timestamp_with_repos<Remote>(
+        start_time: &DateTime<Utc>,
         config: &Config,
         tuf: &mut Database<D>,
         local: Option<&mut Repository<L, D>>,
@@ -590,7 +623,7 @@
     where
         Remote: RepositoryProvider<D>,
     {
-        let timestamp_path = MetadataPath::from_role(&Role::Timestamp);
+        let timestamp_path = MetadataPath::timestamp();
 
         /////////////////////////////////////////
         // TUF-1.0.9 §5.2:
@@ -609,7 +642,10 @@
             )
             .await?;
 
-        if tuf.update_timestamp(&raw_signed_timestamp)?.is_some() {
+        if tuf
+            .update_timestamp(start_time, &raw_signed_timestamp)?
+            .is_some()
+        {
             /////////////////////////////////////////
             // TUF-1.0.9 §5.2.4:
             //
@@ -633,9 +669,10 @@
     }
 
     /// Returns `true` if an update occurred and `false` otherwise.
-    async fn update_snapshot(&mut self) -> Result<bool> {
+    async fn update_snapshot(&mut self, start_time: &DateTime<Utc>) -> Result<bool> {
         let consistent_snapshot = self.tuf.trusted_root().consistent_snapshot();
         Self::update_snapshot_with_repos(
+            start_time,
             &self.config,
             &mut self.tuf,
             Some(&mut self.local),
@@ -646,6 +683,7 @@
     }
 
     async fn update_snapshot_with_repos<Remote>(
+        start_time: &DateTime<Utc>,
         config: &Config,
         tuf: &mut Database<D>,
         local: Option<&mut Repository<L, D>>,
@@ -657,7 +695,7 @@
     {
         let snapshot_description = match tuf.trusted_timestamp() {
             Some(ts) => Ok(ts.snapshot()),
-            None => Err(Error::MissingMetadata(Role::Timestamp)),
+            None => Err(Error::MissingMetadata(MetadataPath::timestamp())),
         }?
         .clone();
 
@@ -673,7 +711,7 @@
             MetadataVersion::None
         };
 
-        let snapshot_path = MetadataPath::from_role(&Role::Snapshot);
+        let snapshot_path = MetadataPath::snapshot();
 
         // https://theupdateframework.github.io/specification/v1.0.26/#update-snapshot 5.5.1:
 
@@ -693,7 +731,7 @@
 
         // https://theupdateframework.github.io/specification/v1.0.26/#update-snapshot 5.5.3 through
         // 5.5.6 are checked in [Database].
-        if tuf.update_snapshot(&raw_signed_snapshot)? {
+        if tuf.update_snapshot(start_time, &raw_signed_snapshot)? {
             // https://theupdateframework.github.io/specification/v1.0.26/#update-snapshot 5.5.7:
             //
             // Persist snapshot metadata. The client MUST write the file to non-volatile storage as
@@ -711,9 +749,10 @@
     }
 
     /// Returns `true` if an update occurred and `false` otherwise.
-    async fn update_targets(&mut self) -> Result<bool> {
+    async fn update_targets(&mut self, start_time: &DateTime<Utc>) -> Result<bool> {
         let consistent_snapshot = self.tuf.trusted_root().consistent_snapshot();
         Self::update_targets_with_repos(
+            start_time,
             &self.config,
             &mut self.tuf,
             Some(&mut self.local),
@@ -724,6 +763,7 @@
     }
 
     async fn update_targets_with_repos<Remote>(
+        start_time: &DateTime<Utc>,
         config: &Config,
         tuf: &mut Database<D>,
         local: Option<&mut Repository<L, D>>,
@@ -734,7 +774,7 @@
         Remote: RepositoryProvider<D>,
     {
         let targets_description = match tuf.trusted_snapshot() {
-            Some(sn) => match sn.meta().get(&MetadataPath::from_role(&Role::Targets)) {
+            Some(sn) => match sn.meta().get(&MetadataPath::targets()) {
                 Some(d) => Ok(d),
                 None => Err(Error::VerificationFailure(
                     "Snapshot metadata did not contain a description of the \
@@ -742,7 +782,7 @@
                         .into(),
                 )),
             },
-            None => Err(Error::MissingMetadata(Role::Snapshot)),
+            None => Err(Error::MissingMetadata(MetadataPath::snapshot())),
         }?
         .clone();
 
@@ -757,7 +797,7 @@
             MetadataVersion::None
         };
 
-        let targets_path = MetadataPath::from_role(&Role::Targets);
+        let targets_path = MetadataPath::targets();
 
         // https://theupdateframework.github.io/specification/v1.0.26/#update-targets 5.6.1:
         //
@@ -775,7 +815,7 @@
             .fetch_metadata(&targets_path, version, targets_length, target_hashes)
             .await?;
 
-        if tuf.update_targets(&raw_signed_targets)? {
+        if tuf.update_targets(start_time, &raw_signed_targets)? {
             /////////////////////////////////////////
             // TUF-1.0.9 §5.4.4:
             //
@@ -803,7 +843,23 @@
         &mut self,
         target: &TargetPath,
     ) -> Result<impl AsyncRead + Send + Unpin + '_> {
-        let target_description = self.fetch_target_description(target).await?;
+        self.fetch_target_with_start_time(target, &Utc::now()).await
+    }
+
+    /// Fetch a target from the remote repo.
+    ///
+    /// It is **critical** that none of the bytes written to the `write` are used until this future
+    /// returns `Ok`, as the hash of the target is not verified until all bytes are read from the
+    /// repository.
+    pub async fn fetch_target_with_start_time(
+        &mut self,
+        target: &TargetPath,
+        start_time: &DateTime<Utc>,
+    ) -> Result<impl AsyncRead + Send + Unpin + '_> {
+        let target_description = self
+            .fetch_target_description_with_start_time(target, start_time)
+            .await?;
+
         // TODO: Check the local repository to see if it already has the target.
         self.remote
             .fetch_target(
@@ -820,7 +876,23 @@
     /// returns `Ok`, as the hash of the target is not verified until all bytes are read from the
     /// repository.
     pub async fn fetch_target_to_local(&mut self, target: &TargetPath) -> Result<()> {
-        let target_description = self.fetch_target_description(target).await?;
+        self.fetch_target_to_local_with_start_time(target, &Utc::now())
+            .await
+    }
+
+    /// Fetch a target from the remote repo and write it to the local repo.
+    ///
+    /// It is **critical** that none of the bytes written to the `write` are used until this future
+    /// returns `Ok`, as the hash of the target is not verified until all bytes are read from the
+    /// repository.
+    pub async fn fetch_target_to_local_with_start_time(
+        &mut self,
+        target: &TargetPath,
+        start_time: &DateTime<Utc>,
+    ) -> Result<()> {
+        let target_description = self
+            .fetch_target_description_with_start_time(target, start_time)
+            .await?;
 
         // Since the async read we fetch from the remote repository has internal
         // lifetimes, we need to break up client into sub-objects so that rust
@@ -847,19 +919,40 @@
         &mut self,
         target: &TargetPath,
     ) -> Result<TargetDescription> {
+        self.fetch_target_description_with_start_time(target, &Utc::now())
+            .await
+    }
+
+    /// Fetch a target description from the remote repo and return it.
+    pub async fn fetch_target_description_with_start_time(
+        &mut self,
+        target: &TargetPath,
+        start_time: &DateTime<Utc>,
+    ) -> Result<TargetDescription> {
         let snapshot = self
             .tuf
             .trusted_snapshot()
-            .ok_or(Error::MissingMetadata(Role::Snapshot))?
+            .ok_or_else(|| Error::MissingMetadata(MetadataPath::snapshot()))?
             .clone();
+
+        /////////////////////////////////////////
+        // https://theupdateframework.github.io/specification/v1.0.30/#update-targets:
+        //
+        //     7. **Perform a pre-order depth-first search for metadata about the
+        //     desired target, beginning with the top-level targets role.** Note: If
+        //     any metadata requested in steps 5.6.7.1 - 5.6.7.2 cannot be downloaded nor
+        //     validated, end the search and report that the target cannot be found.
+
         let (_, target_description) = self
-            .lookup_target_description(false, 0, target, &snapshot, None)
+            .lookup_target_description(start_time, false, 0, target, &snapshot, None)
             .await;
+
         target_description
     }
 
     async fn lookup_target_description(
         &mut self,
+        start_time: &DateTime<Utc>,
         default_terminate: bool,
         current_depth: u32,
         target: &TargetPath,
@@ -879,11 +972,11 @@
         let (targets, targets_role) = match targets {
             Some((t, role)) => (t.clone(), role),
             None => match self.tuf.trusted_targets() {
-                Some(t) => (t.clone(), MetadataPath::from_role(&Role::Targets)),
+                Some(t) => (t.clone(), MetadataPath::targets()),
                 None => {
                     return (
                         default_terminate,
-                        Err(Error::MissingMetadata(Role::Targets)),
+                        Err(Error::MissingMetadata(MetadataPath::targets())),
                     );
                 }
             },
@@ -960,10 +1053,12 @@
                 }
             };
 
-            match self
-                .tuf
-                .update_delegation(&targets_role, delegation.role(), &raw_signed_meta)
-            {
+            match self.tuf.update_delegated_targets(
+                start_time,
+                &targets_role,
+                delegation.role(),
+                &raw_signed_meta,
+            ) {
                 Ok(_) => {
                     /////////////////////////////////////////
                     // TUF-1.0.9 §5.4.4:
@@ -994,6 +1089,7 @@
                         .clone();
                     let f: Pin<Box<dyn Future<Output = _>>> =
                         Box::pin(self.lookup_target_description(
+                            start_time,
                             delegation.terminating(),
                             current_depth + 1,
                             target,
@@ -1416,10 +1512,7 @@
                             MetadataVersion::Number(1),
                             metadata1.root().unwrap()
                         ),
-                        Track::FetchErr(
-                            MetadataPath::from_role(&Role::Root),
-                            MetadataVersion::Number(2)
-                        ),
+                        Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(2)),
                     ],
                 );
             }
@@ -1427,7 +1520,7 @@
                 assert_eq!(
                     client.local_repo().take_tracks(),
                     vec![Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
+                        MetadataPath::root(),
                         MetadataVersion::Number(2)
                     )],
                 );
@@ -1440,10 +1533,7 @@
                             MetadataVersion::Number(1),
                             metadata1.root().unwrap()
                         ),
-                        Track::FetchErr(
-                            MetadataPath::from_role(&Role::Root),
-                            MetadataVersion::Number(2)
-                        ),
+                        Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(2)),
                     ],
                 );
             }
@@ -1451,7 +1541,7 @@
                 assert_eq!(
                     client.local_repo().take_tracks(),
                     vec![Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
+                        MetadataPath::root(),
                         MetadataVersion::Number(2)
                     )],
                 );
@@ -1467,10 +1557,7 @@
             client.remote_repo().take_tracks(),
             vec![
                 Track::fetch_meta_found(MetadataVersion::Number(2), metadata2.root().unwrap()),
-                Track::FetchErr(
-                    MetadataPath::from_role(&Role::Root),
-                    MetadataVersion::Number(3)
-                ),
+                Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(3)),
                 Track::fetch_meta_found(MetadataVersion::None, metadata2.timestamp().unwrap()),
                 Track::fetch_meta_found(MetadataVersion::Number(2), metadata2.snapshot().unwrap()),
                 Track::fetch_meta_found(MetadataVersion::Number(2), metadata2.targets().unwrap()),
@@ -1495,10 +1582,7 @@
         assert_eq!(
             client.remote_repo().take_tracks(),
             vec![
-                Track::FetchErr(
-                    MetadataPath::from_role(&Role::Root),
-                    MetadataVersion::Number(3)
-                ),
+                Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(3)),
                 Track::fetch_meta_found(MetadataVersion::None, metadata2.timestamp().unwrap()),
             ]
         );
@@ -1549,14 +1633,8 @@
             assert_eq!(
                 client.local_repo().take_tracks(),
                 vec![
-                    Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
-                        MetadataVersion::Number(2)
-                    ),
-                    Track::FetchErr(
-                        MetadataPath::from_role(&Role::Timestamp),
-                        MetadataVersion::None
-                    )
+                    Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(2)),
+                    Track::FetchErr(MetadataPath::timestamp(), MetadataVersion::None)
                 ],
             );
 
@@ -1588,10 +1666,7 @@
                 client.remote_repo().take_tracks(),
                 vec![
                     Track::fetch_meta_found(MetadataVersion::Number(2), metadata2.root().unwrap()),
-                    Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
-                        MetadataVersion::Number(3)
-                    ),
+                    Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(3)),
                     Track::fetch_meta_found(MetadataVersion::None, metadata2.timestamp().unwrap()),
                     Track::fetch_meta_found(
                         MetadataVersion::Number(2),
@@ -1683,10 +1758,7 @@
                 client.local_repo().take_tracks(),
                 vec![
                     Track::fetch_meta_found(MetadataVersion::Number(2), metadata2.root().unwrap()),
-                    Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
-                        MetadataVersion::Number(3)
-                    )
+                    Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(3))
                 ],
             );
 
@@ -1728,7 +1800,7 @@
 
             local
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                     &mut junk_timestamp.as_bytes(),
                 )
@@ -1769,12 +1841,9 @@
             assert_eq!(
                 client.local_repo().take_tracks(),
                 vec![
-                    Track::FetchErr(
-                        MetadataPath::from_role(&Role::Root),
-                        MetadataVersion::Number(2)
-                    ),
+                    Track::FetchErr(MetadataPath::root(), MetadataVersion::Number(2)),
                     Track::FetchFound {
-                        path: MetadataPath::from_role(&Role::Timestamp),
+                        path: MetadataPath::timestamp(),
                         version: MetadataVersion::None,
                         metadata: junk_timestamp.into(),
                     },
@@ -1815,8 +1884,8 @@
             .await
             .unwrap();
 
-        let root_path = MetadataPath::from_role(&Role::Root);
-        let timestamp_path = MetadataPath::from_role(&Role::Timestamp);
+        let root_path = MetadataPath::root();
+        let timestamp_path = MetadataPath::timestamp();
 
         let targets_version;
         let snapshot_version;
@@ -2216,7 +2285,7 @@
             client
                 .local_repo_mut()
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                     &mut metadata2.timestamp().unwrap().as_bytes(),
                 )
@@ -2226,7 +2295,7 @@
             client
                 .remote_repo_mut()
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                     &mut metadata2.timestamp().unwrap().as_bytes(),
                 )
@@ -2241,7 +2310,7 @@
                 &timestamp2,
                 &fetch_metadata_to_string(
                     client.local_repo(),
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                 )
                 .await
@@ -2252,7 +2321,7 @@
                 &timestamp2,
                 &fetch_metadata_to_string(
                     client.remote_repo(),
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                 )
                 .await
@@ -2282,7 +2351,7 @@
                 .unwrap();
 
             repo.store_metadata(
-                &MetadataPath::from_role(&Role::Root),
+                &MetadataPath::root(),
                 MetadataVersion::Number(1),
                 &mut root.as_bytes(),
             )
@@ -2296,7 +2365,7 @@
                 .unwrap();
 
             repo.store_metadata(
-                &MetadataPath::from_role(&Role::Targets),
+                &MetadataPath::targets(),
                 MetadataVersion::Number(1),
                 &mut targets.as_bytes(),
             )
@@ -2308,17 +2377,14 @@
             let targets_description = MetadataDescription::new(1, None, HashMap::new()).unwrap();
 
             let snapshot = SnapshotMetadataBuilder::new()
-                .insert_metadata_description(
-                    MetadataPath::from_role(&Role::Targets),
-                    targets_description,
-                )
+                .insert_metadata_description(MetadataPath::targets(), targets_description)
                 .signed::<Json>(&KEYS[2])
                 .unwrap()
                 .to_raw()
                 .unwrap();
 
             repo.store_metadata(
-                &MetadataPath::from_role(&Role::Snapshot),
+                &MetadataPath::snapshot(),
                 MetadataVersion::Number(1),
                 &mut snapshot.as_bytes(),
             )
@@ -2337,7 +2403,7 @@
                     .unwrap();
 
             repo.store_metadata(
-                &MetadataPath::from_role(&Role::Timestamp),
+                &MetadataPath::timestamp(),
                 MetadataVersion::None,
                 &mut timestamp.as_bytes(),
             )
diff --git a/third_party/rust_crates/vendor/tuf/src/database.rs b/third_party/rust_crates/vendor/tuf/src/database.rs
index c90095d..e493664 100644
--- a/third_party/rust_crates/vendor/tuf/src/database.rs
+++ b/third_party/rust_crates/vendor/tuf/src/database.rs
@@ -1,6 +1,6 @@
 //! Components needed to verify TUF metadata and targets.
 
-use chrono::offset::Utc;
+use chrono::{offset::Utc, DateTime};
 use std::cmp::Ordering;
 use std::collections::{HashMap, HashSet};
 use std::marker::PhantomData;
@@ -9,9 +9,8 @@
 use crate::error::Error;
 use crate::interchange::DataInterchange;
 use crate::metadata::{
-    Delegations, Metadata, MetadataPath, RawSignedMetadata, RawSignedMetadataSet, Role,
-    RootMetadata, SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata,
-    TimestampMetadata,
+    Delegations, Metadata, MetadataPath, RawSignedMetadata, RawSignedMetadataSet, RootMetadata,
+    SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata, TimestampMetadata,
 };
 use crate::verify::{self, Verified};
 use crate::Result;
@@ -114,13 +113,33 @@
     where
         I: IntoIterator<Item = &'a PublicKey>,
     {
+        Self::from_metadata_with_trusted_keys_and_start_time(
+            &Utc::now(),
+            metadata_set,
+            root_threshold,
+            root_keys,
+        )
+    }
+
+    /// Create a new [`Database`] struct from a set of metadata that is assumed to be trusted. The
+    /// signed root metadata in the `metadata_set` must be signed with at least a `root_threshold`
+    /// of the provided root_keys. It is not necessary for the root metadata to contain these keys.
+    pub fn from_metadata_with_trusted_keys_and_start_time<'a, I>(
+        start_time: &DateTime<Utc>,
+        metadata_set: &RawSignedMetadataSet<D>,
+        root_threshold: u32,
+        root_keys: I,
+    ) -> Result<Self>
+    where
+        I: IntoIterator<Item = &'a PublicKey>,
+    {
         let mut db = if let Some(root) = metadata_set.root() {
             Database::from_root_with_trusted_keys(root, root_threshold, root_keys)?
         } else {
-            return Err(Error::MissingMetadata(Role::Root));
+            return Err(Error::MissingMetadata(MetadataPath::root()));
         };
 
-        db.update_metadata_after_root(metadata_set)?;
+        db.update_metadata_after_root(start_time, metadata_set)?;
 
         Ok(db)
     }
@@ -133,13 +152,27 @@
     /// signed properly. This exposes us to potential parser exploits. This method should only be
     /// used if the metadata is loaded from a trusted source.
     pub fn from_trusted_metadata(metadata_set: &RawSignedMetadataSet<D>) -> Result<Self> {
+        Self::from_trusted_metadata_with_start_time(metadata_set, &Utc::now())
+    }
+
+    /// Create a new [`Database`] struct from a set of metadata that is assumed to be trusted.
+    ///
+    /// **WARNING**: This is trust-on-first-use (TOFU) and offers weaker security guarantees than
+    /// the related method [`Database::from_metadata_with_trusted_keys`] because this method needs
+    /// to deserialize the root metadata from `metadata_set` before we have verified it has been
+    /// signed properly. This exposes us to potential parser exploits. This method should only be
+    /// used if the metadata is loaded from a trusted source.
+    pub fn from_trusted_metadata_with_start_time(
+        metadata_set: &RawSignedMetadataSet<D>,
+        start_time: &DateTime<Utc>,
+    ) -> Result<Self> {
         let mut db = if let Some(root) = metadata_set.root() {
             Database::from_trusted_root(root)?
         } else {
-            return Err(Error::MissingMetadata(Role::Root));
+            return Err(Error::MissingMetadata(MetadataPath::root()));
         };
 
-        db.update_metadata_after_root(metadata_set)?;
+        db.update_metadata_after_root(start_time, metadata_set)?;
 
         Ok(db)
     }
@@ -169,36 +202,17 @@
         &self.trusted_delegations
     }
 
-    fn trusted_timestamp_version(&self) -> u32 {
-        self.trusted_timestamp
-            .as_ref()
-            .map(|t| t.version())
-            .unwrap_or(0)
-    }
-
-    fn trusted_snapshot_version(&self) -> u32 {
-        self.trusted_snapshot
-            .as_ref()
-            .map(|t| t.version())
-            .unwrap_or(0)
-    }
-
-    fn trusted_targets_version(&self) -> u32 {
-        self.trusted_targets
-            .as_ref()
-            .map(|t| t.version())
-            .unwrap_or(0)
-    }
-
-    fn trusted_delegation_version(&self, role: &MetadataPath) -> u32 {
-        self.trusted_delegations
-            .get(role)
-            .map(|t| t.version())
-            .unwrap_or(0)
+    /// Verify and update metadata. Returns true if any of the metadata was updated.
+    pub fn update_metadata(&mut self, metadata: &RawSignedMetadataSet<D>) -> Result<bool> {
+        self.update_metadata_with_start_time(metadata, &Utc::now())
     }
 
     /// Verify and update metadata. Returns true if any of the metadata was updated.
-    pub fn update_metadata(&mut self, metadata: &RawSignedMetadataSet<D>) -> Result<bool> {
+    pub fn update_metadata_with_start_time(
+        &mut self,
+        metadata: &RawSignedMetadataSet<D>,
+        start_time: &DateTime<Utc>,
+    ) -> Result<bool> {
         let updated = if let Some(root) = metadata.root() {
             self.update_root(root)?;
             true
@@ -206,7 +220,7 @@
             false
         };
 
-        if self.update_metadata_after_root(metadata)? {
+        if self.update_metadata_after_root(start_time, metadata)? {
             Ok(true)
         } else {
             Ok(updated)
@@ -215,23 +229,24 @@
 
     fn update_metadata_after_root(
         &mut self,
+        start_time: &DateTime<Utc>,
         metadata_set: &RawSignedMetadataSet<D>,
     ) -> Result<bool> {
         let mut updated = false;
         if let Some(timestamp) = metadata_set.timestamp() {
-            if self.update_timestamp(timestamp)?.is_some() {
+            if self.update_timestamp(start_time, timestamp)?.is_some() {
                 updated = true;
             }
         }
 
         if let Some(snapshot) = metadata_set.snapshot() {
-            if self.update_snapshot(snapshot)? {
+            if self.update_snapshot(start_time, snapshot)? {
                 updated = true;
             }
         }
 
         if let Some(targets) = metadata_set.targets() {
-            if self.update_targets(targets)? {
+            if self.update_targets(start_time, targets)? {
                 updated = true;
             }
         }
@@ -338,6 +353,7 @@
     /// Returns a reference to the parsed metadata if the metadata was newer.
     pub fn update_timestamp(
         &mut self,
+        start_time: &DateTime<Utc>,
         raw_timestamp: &RawSignedMetadata<D, TimestampMetadata>,
     ) -> Result<Option<&Verified<TimestampMetadata>>> {
         let verified = {
@@ -371,20 +387,20 @@
             //     new timestamp metadata file is older than the trusted timestamp metadata file,
             //     discard it, abort the update cycle, and report the potential rollback attack.
 
-            let trusted_timestamp_version = self.trusted_timestamp_version();
-
-            match new_timestamp.version().cmp(&trusted_timestamp_version) {
-                Ordering::Less => {
-                    return Err(Error::VerificationFailure(format!(
-                        "Attempted to roll back timestamp metadata at version {} to {}.",
-                        trusted_timestamp_version,
-                        new_timestamp.version()
-                    )));
+            if let Some(trusted_timestamp) = &self.trusted_timestamp {
+                match new_timestamp.version().cmp(&trusted_timestamp.version()) {
+                    Ordering::Less => {
+                        return Err(Error::VerificationFailure(format!(
+                            "Attempted to roll back timestamp metadata at version {} to {}.",
+                            trusted_timestamp.version(),
+                            new_timestamp.version()
+                        )));
+                    }
+                    Ordering::Equal => {
+                        return Ok(None);
+                    }
+                    Ordering::Greater => {}
                 }
-                Ordering::Equal => {
-                    return Ok(None);
-                }
-                Ordering::Greater => {}
             }
 
             /////////////////////////////////////////
@@ -401,8 +417,10 @@
             // FIXME(#297): forgetting the trusted snapshot here is not part of the spec. Do we need to
             // do it?
 
-            if self.trusted_snapshot_version() != new_timestamp.snapshot().version() {
-                self.trusted_snapshot = None;
+            if let Some(trusted_snapshot) = &self.trusted_snapshot {
+                if trusted_snapshot.version() != new_timestamp.snapshot().version() {
+                    self.trusted_snapshot = None;
+                }
             }
 
             /////////////////////////////////////////
@@ -414,8 +432,8 @@
             //     timestamp metadata file has expired, discard it, abort the update cycle, and
             //     report the potential freeze attack.
 
-            if new_timestamp.expires() <= &Utc::now() {
-                return Err(Error::ExpiredMetadata(Role::Timestamp));
+            if new_timestamp.expires() <= start_time {
+                return Err(Error::ExpiredMetadata(MetadataPath::timestamp()));
             }
 
             new_timestamp
@@ -428,32 +446,34 @@
     /// Verify and update the snapshot metadata.
     pub fn update_snapshot(
         &mut self,
+        start_time: &DateTime<Utc>,
         raw_snapshot: &RawSignedMetadata<D, SnapshotMetadata>,
     ) -> Result<bool> {
         let verified = {
             /////////////////////////////////////////
             // FIXME(https://github.com/theupdateframework/specification/issues/113) Checking if
             // this metadata expired isn't part of the spec. Do we actually want to do this?
-            let trusted_root = self.trusted_root_unexpired()?;
-            let trusted_timestamp = self.trusted_timestamp_unexpired()?;
-            let trusted_snapshot_version = self.trusted_snapshot_version();
+            let trusted_root = self.trusted_root_unexpired(start_time)?;
+            let trusted_timestamp = self.trusted_timestamp_unexpired(start_time)?;
 
-            match trusted_timestamp
-                .snapshot()
-                .version()
-                .cmp(&trusted_snapshot_version)
-            {
-                Ordering::Less => {
-                    return Err(Error::VerificationFailure(format!(
-                        "Attempted to roll back snapshot metadata at version {} to {}.",
-                        trusted_snapshot_version,
-                        trusted_timestamp.snapshot().version()
-                    )));
+            if let Some(trusted_snapshot) = &self.trusted_snapshot {
+                match trusted_timestamp
+                    .snapshot()
+                    .version()
+                    .cmp(&trusted_snapshot.version())
+                {
+                    Ordering::Less => {
+                        return Err(Error::VerificationFailure(format!(
+                            "Attempted to roll back snapshot metadata at version {} to {}.",
+                            trusted_snapshot.version(),
+                            trusted_timestamp.snapshot().version()
+                        )));
+                    }
+                    Ordering::Equal => {
+                        return Ok(false);
+                    }
+                    Ordering::Greater => {}
                 }
-                Ordering::Equal => {
-                    return Ok(false);
-                }
-                Ordering::Greater => {}
             }
 
             /////////////////////////////////////////
@@ -511,12 +531,14 @@
             //     new snapshot metadata file is older than the trusted metadata file, discard it,
             //     abort the update cycle, and report the potential rollback attack.
 
-            if new_snapshot.version() < trusted_snapshot_version {
-                return Err(Error::VerificationFailure(format!(
-                    "Attempted to roll back snapshot metadata at version {} to {}",
-                    trusted_snapshot_version,
-                    new_snapshot.version(),
-                )));
+            if let Some(trusted_snapshot) = &self.trusted_snapshot {
+                if new_snapshot.version() < trusted_snapshot.version() {
+                    return Err(Error::VerificationFailure(format!(
+                        "Attempted to roll back snapshot metadata at version {} to {}",
+                        trusted_snapshot.version(),
+                        new_snapshot.version(),
+                    )));
+                }
             }
 
             /////////////////////////////////////////
@@ -557,7 +579,7 @@
             .unwrap_or(0)
             != verified
                 .meta()
-                .get(&MetadataPath::from_role(&Role::Targets))
+                .get(&MetadataPath::targets())
                 .map(|m| m.version())
                 .unwrap_or(0)
         {
@@ -602,106 +624,183 @@
     /// Verify and update the targets metadata.
     pub fn update_targets(
         &mut self,
+        start_time: &DateTime<Utc>,
         raw_targets: &RawSignedMetadata<D, TargetsMetadata>,
     ) -> Result<bool> {
         let verified = {
             // FIXME(https://github.com/theupdateframework/specification/issues/113) Checking if
             // this metadata expired isn't part of the spec. Do we actually want to do this?
-            let trusted_root = self.trusted_root_unexpired()?;
-            let trusted_snapshot = self.trusted_snapshot_unexpired()?;
+            let trusted_root = self.trusted_root_unexpired(start_time)?;
+            let trusted_targets_version = self.trusted_targets.as_ref().map(|t| t.version());
 
-            // FIXME(#295): TUF-1.0.5 §5.3.3.2 says this check should be done when updating the
-            // snapshot, not here.
-            let trusted_targets_description = trusted_snapshot
-                .meta()
-                .get(&MetadataPath::from_role(&Role::Targets))
+            self.verify_target_or_delegated_target(
+                start_time,
+                &MetadataPath::targets(),
+                raw_targets,
+                trusted_root.targets().threshold(),
+                trusted_root.targets_keys(),
+                trusted_targets_version,
+            )?
+        };
+
+        if let Some(verified) = verified {
+            self.trusted_targets = Some(verified);
+            Ok(true)
+        } else {
+            Ok(false)
+        }
+    }
+
+    /// Verify and update a delegation metadata.
+    pub fn update_delegated_targets(
+        &mut self,
+        start_time: &DateTime<Utc>,
+        parent_role: &MetadataPath,
+        role: &MetadataPath,
+        raw_delegated_targets: &RawSignedMetadata<D, TargetsMetadata>,
+    ) -> Result<bool> {
+        let verified = {
+            // FIXME(https://github.com/theupdateframework/specification/issues/113) Checking if
+            // this metadata expired isn't part of the spec. Do we actually want to do this?
+            let _ = self.trusted_root_unexpired(start_time)?;
+            let _ = self.trusted_snapshot_unexpired(start_time)?;
+            let trusted_targets = self.trusted_targets_unexpired(start_time)?;
+
+            if trusted_targets.delegations().is_none() {
+                return Err(Error::VerificationFailure(
+                    "Delegations not authorized".into(),
+                ));
+            };
+
+            let (threshold, keys) = self
+                .find_delegation_threshold_and_keys(parent_role, role)?
                 .ok_or_else(|| {
-                    Error::VerificationFailure(
-                        "Snapshot metadata had no description of the targets metadata".into(),
-                    )
+                    Error::VerificationFailure(format!(
+                        "The delegated targets role {:?} is not known to the delegating targets role {}",
+                        role, parent_role,
+                    ))
                 })?;
 
-            let trusted_targets_version = self.trusted_targets_version();
+            let trusted_delegated_targets_version =
+                self.trusted_delegations.get(role).map(|t| t.version());
 
-            match trusted_targets_description
-                .version()
-                .cmp(&trusted_targets_version)
-            {
+            self.verify_target_or_delegated_target(
+                start_time,
+                role,
+                raw_delegated_targets,
+                threshold,
+                keys.into_iter(),
+                trusted_delegated_targets_version,
+            )?
+        };
+
+        if let Some(verified) = verified {
+            let _ = self.trusted_delegations.insert(role.clone(), verified);
+            Ok(true)
+        } else {
+            Ok(false)
+        }
+    }
+
+    fn verify_target_or_delegated_target<'a>(
+        &self,
+        start_time: &DateTime<Utc>,
+        role: &MetadataPath,
+        raw_targets: &RawSignedMetadata<D, TargetsMetadata>,
+        trusted_targets_threshold: u32,
+        trusted_targets_keys: impl Iterator<Item = &'a PublicKey>,
+        trusted_targets_version: Option<u32>,
+    ) -> Result<Option<Verified<TargetsMetadata>>> {
+        // FIXME(https://github.com/theupdateframework/specification/issues/113) Checking if
+        // this metadata expired isn't part of the spec. Do we actually want to do this?
+        let trusted_snapshot = self.trusted_snapshot_unexpired(start_time)?;
+
+        let trusted_targets_description = trusted_snapshot.meta().get(role).ok_or_else(|| {
+            Error::VerificationFailure(format!(
+                "Snapshot metadata had no description of the {} metadata",
+                role
+            ))
+        })?;
+
+        /////////////////////////////////////////
+        // TUF-1.0.5 §5.4.1:
+        //
+        //     Check against snapshot metadata. The hashes and version number of the new
+        //     targets metadata file MUST match the hashes (if any) and version number listed
+        //     in the trusted snapshot metadata. This is done, in part, to prevent a
+        //     mix-and-match attack by man-in-the-middle attackers. If the new targets metadata
+        //     file does not match, discard it, abort the update cycle, and report the failure.
+
+        // FIXME: rust-tuf checks the hash during download, but it would be better if we
+        // checked the hash here to make it easier to validate we've correctly implemented the
+        // spec.
+
+        // NOTE(https://github.com/theupdateframework/specification/pull/112): Technically
+        // we're supposed to check the version before checking the signature, but we do it
+        // afterwards. That PR proposes formally moving the version check to after signature
+        // verification.
+
+        /////////////////////////////////////////
+        // TUF-1.0.5 §5.4.2:
+        //
+        //     Check for an arbitrary software attack. The new targets metadata file MUST have
+        //     been signed by a threshold of keys specified in the trusted root metadata file.
+        //     If the new targets metadata file is not signed as required, discard it, abort
+        //     the update cycle, and report the failure.
+
+        let new_targets = verify::verify_signatures(
+            raw_targets,
+            trusted_targets_threshold,
+            trusted_targets_keys,
+        )?;
+
+        /////////////////////////////////////////
+        // FIXME(https://github.com/theupdateframework/specification/pull/112): Actually check
+        // the version.
+
+        // FIXME(#295): TUF-1.0.5 §5.3.3.2 says this check should be done when updating the
+        // snapshot, not here.
+        if new_targets.version() != trusted_targets_description.version() {
+            return Err(Error::VerificationFailure(format!(
+                "The snapshot metadata reported that the {} metadata should be at \
+                     version {} but version {} was found instead.",
+                role,
+                trusted_targets_description.version(),
+                new_targets.version()
+            )));
+        }
+
+        if let Some(trusted_targets_version) = trusted_targets_version {
+            match new_targets.version().cmp(&trusted_targets_version) {
                 Ordering::Less => {
                     return Err(Error::VerificationFailure(format!(
-                        "Attempted to roll back targets metadata at version {} to {}.",
+                        "Attempted to roll back {} metadata at version {} to {}.",
+                        role,
                         trusted_targets_version,
                         trusted_targets_description.version()
                     )));
                 }
                 Ordering::Equal => {
-                    return Ok(false);
+                    return Ok(None);
                 }
                 Ordering::Greater => {}
             }
+        }
 
-            /////////////////////////////////////////
-            // TUF-1.0.5 §5.4.1:
-            //
-            //     Check against snapshot metadata. The hashes and version number of the new
-            //     targets metadata file MUST match the hashes (if any) and version number listed
-            //     in the trusted snapshot metadata. This is done, in part, to prevent a
-            //     mix-and-match attack by man-in-the-middle attackers. If the new targets metadata
-            //     file does not match, discard it, abort the update cycle, and report the failure.
+        /////////////////////////////////////////
+        // TUF-1.0.5 §5.4.3:
+        //
+        //     Check for a freeze attack. The latest known time should be lower than the
+        //     expiration timestamp in the new targets metadata file. If so, the new targets
+        //     metadata file becomes the trusted targets metadata file. If the new targets
+        //     metadata file is expired, discard it, abort the update cycle, and report the
+        //     potential freeze attack.
 
-            // FIXME: rust-tuf checks the hash during download, but it would be better if we
-            // checked the hash here to make it easier to validate we've correctly implemented the
-            // spec.
+        if new_targets.expires() <= start_time {
+            return Err(Error::ExpiredMetadata(role.clone()));
+        }
 
-            // NOTE(https://github.com/theupdateframework/specification/pull/112): Technically
-            // we're supposed to check the version before checking the signature, but we do it
-            // afterwards. That PR proposes formally moving the version check to after signature
-            // verification.
-
-            /////////////////////////////////////////
-            // TUF-1.0.5 §5.4.2:
-            //
-            //     Check for an arbitrary software attack. The new targets metadata file MUST have
-            //     been signed by a threshold of keys specified in the trusted root metadata file.
-            //     If the new targets metadata file is not signed as required, discard it, abort
-            //     the update cycle, and report the failure.
-
-            let new_targets = verify::verify_signatures(
-                raw_targets,
-                trusted_root.targets().threshold(),
-                trusted_root.targets_keys(),
-            )?;
-
-            /////////////////////////////////////////
-            // FIXME(https://github.com/theupdateframework/specification/pull/112): Actually check
-            // the version.
-
-            if new_targets.version() != trusted_targets_description.version() {
-                return Err(Error::VerificationFailure(format!(
-                    "The timestamp metadata reported that the targets metadata should be at \
-                     version {} but version {} was found instead.",
-                    trusted_targets_description.version(),
-                    new_targets.version()
-                )));
-            }
-
-            /////////////////////////////////////////
-            // TUF-1.0.5 §5.4.3:
-            //
-            //     Check for a freeze attack. The latest known time should be lower than the
-            //     expiration timestamp in the new targets metadata file. If so, the new targets
-            //     metadata file becomes the trusted targets metadata file. If the new targets
-            //     metadata file is expired, discard it, abort the update cycle, and report the
-            //     potential freeze attack.
-            if new_targets.expires() <= &Utc::now() {
-                return Err(Error::ExpiredMetadata(Role::Snapshot));
-            }
-
-            new_targets
-        };
-
-        self.trusted_targets = Some(verified);
-        Ok(true)
+        Ok(Some(new_targets))
     }
 
     /// Find the signing keys and metadata for the delegation given by `role`, as seen from the
@@ -710,20 +809,24 @@
         &self,
         parent_role: &MetadataPath,
         role: &MetadataPath,
-    ) -> Option<(u32, Vec<&PublicKey>)> {
+    ) -> Result<Option<(u32, Vec<&PublicKey>)>> {
         // Find the parent TargetsMetadata that is expected to refer to `role`.
-        let trusted_parent = {
-            if parent_role == &MetadataPath::from_role(&Role::Targets) {
-                self.trusted_targets()?
+        let trusted_parent = if parent_role == &MetadataPath::targets() {
+            if let Some(trusted_targets) = self.trusted_targets() {
+                trusted_targets
             } else {
-                self.trusted_delegations.get(parent_role)?
+                return Err(Error::MissingMetadata(parent_role.clone()));
             }
+        } else if let Some(trusted_parent) = self.trusted_delegations.get(parent_role) {
+            trusted_parent
+        } else {
+            return Err(Error::MissingMetadata(parent_role.clone()));
         };
 
         // Only consider targets metadata that define delegations.
         let trusted_delegations = match trusted_parent.delegations() {
             Some(d) => d,
-            None => return None,
+            None => return Ok(None),
         };
 
         for trusted_delegation in trusted_delegations.roles() {
@@ -744,103 +847,10 @@
                 })
                 .collect();
 
-            return Some((trusted_delegation.threshold(), authorized_keys));
+            return Ok(Some((trusted_delegation.threshold(), authorized_keys)));
         }
 
-        None
-    }
-
-    /// Verify and update a delegation metadata.
-    pub fn update_delegation(
-        &mut self,
-        parent_role: &MetadataPath,
-        role: &MetadataPath,
-        raw_delegation: &RawSignedMetadata<D, TargetsMetadata>,
-    ) -> Result<bool> {
-        let verified = {
-            // FIXME(https://github.com/theupdateframework/specification/issues/113) Checking if
-            // this metadata expired isn't part of the spec. Do we actually want to do this?
-            let _ = self.trusted_root_unexpired()?;
-            let trusted_snapshot = self.trusted_snapshot_unexpired()?;
-            let trusted_targets = self.trusted_targets_unexpired()?;
-
-            if trusted_targets.delegations().is_none() {
-                return Err(Error::VerificationFailure(
-                    "Delegations not authorized".into(),
-                ));
-            };
-
-            let trusted_delegation_description = match trusted_snapshot.meta().get(role) {
-                Some(d) => d,
-                None => {
-                    return Err(Error::VerificationFailure(format!(
-                        "The degated role {:?} was not present in the snapshot metadata.",
-                        role
-                    )));
-                }
-            };
-
-            let trusted_delegation_version = self.trusted_delegation_version(role);
-
-            if trusted_delegation_description.version() < trusted_delegation_version {
-                return Err(Error::VerificationFailure(format!(
-                    "Snapshot metadata did listed delegation {:?} version as {} but current\
-                     version is {}",
-                    role,
-                    trusted_delegation_description.version(),
-                    trusted_delegation_version
-                )));
-            }
-
-            // FIXME(#279) update_delegation trusts tuf::Client to provide too much information,
-            // making this difficult to verify as correct.
-
-            /////////////////////////////////////////
-            // TUF-1.0.5 §5.4.1:
-            //
-            //     Check against snapshot metadata. The hashes and version number of the new
-            //     targets metadata file MUST match the hashes (if any) and version number listed
-            //     in the trusted snapshot metadata. This is done, in part, to prevent a
-            //     mix-and-match attack by man-in-the-middle attackers. If the new targets metadata
-            //     file does not match, discard it, abort the update cycle, and report the failure.
-
-            let (threshold, keys) = self
-                .find_delegation_threshold_and_keys(parent_role, role)
-                .ok_or_else(|| {
-                    Error::VerificationFailure(format!(
-                        "The delegated role {:?} is not known to the base \
-                        targets metadata or any known delegated targets metadata",
-                        role
-                    ))
-                })?;
-
-            let new_delegation = verify::verify_signatures(raw_delegation, threshold, keys)?;
-
-            if trusted_delegation_version == trusted_delegation_description.version() {
-                return Ok(false);
-            }
-
-            if new_delegation.version() != trusted_delegation_description.version() {
-                return Err(Error::VerificationFailure(format!(
-                    "The snapshot metadata reported that the delegation {:?} should be at \
-                     version {} but version {} was found instead.",
-                    role,
-                    trusted_delegation_description.version(),
-                    new_delegation.version(),
-                )));
-            }
-
-            if new_delegation.expires() <= &Utc::now() {
-                // TODO this needs to be chagned to accept a MetadataPath and not Role
-                return Err(Error::ExpiredMetadata(Role::Targets));
-            }
-
-            new_delegation
-        };
-
-        let _ = self.trusted_delegations.insert(role.clone(), verified);
-
-        Ok(true)
+        Ok(None)
     }
 
     /// Get a reference to the description needed to verify the target defined by the given
@@ -848,15 +858,28 @@
     /// metadata. This may mean the target exists somewhere in the metadata, but the chain of trust
     /// to that target may be invalid or incomplete.
     pub fn target_description(&self, target_path: &TargetPath) -> Result<TargetDescription> {
-        let _ = self.trusted_root_unexpired()?;
-        let _ = self.trusted_snapshot_unexpired()?;
-        let targets = self.trusted_targets_unexpired()?;
+        self.target_description_with_start_time(&Utc::now(), target_path)
+    }
+
+    /// Get a reference to the description needed to verify the target defined by the given
+    /// `TargetPath`. Returns an `Error` if the target is not defined in the trusted
+    /// metadata. This may mean the target exists somewhere in the metadata, but the chain of trust
+    /// to that target may be invalid or incomplete.
+    pub fn target_description_with_start_time(
+        &self,
+        start_time: &DateTime<Utc>,
+        target_path: &TargetPath,
+    ) -> Result<TargetDescription> {
+        let _ = self.trusted_root_unexpired(start_time)?;
+        let _ = self.trusted_snapshot_unexpired(start_time)?;
+        let targets = self.trusted_targets_unexpired(start_time)?;
 
         if let Some(d) = targets.targets().get(target_path) {
             return Ok(d.clone());
         }
 
         fn lookup<D: DataInterchange>(
+            start_time: &DateTime<Utc>,
             tuf: &Database<D>,
             default_terminate: bool,
             current_depth: u32,
@@ -883,7 +906,7 @@
                     None => return (delegation.terminating(), None),
                 };
 
-                if trusted_delegation.expires() <= &Utc::now() {
+                if trusted_delegation.expires() <= start_time {
                     return (delegation.terminating(), None);
                 }
 
@@ -895,6 +918,7 @@
                     let mut new_parents = parents.to_vec();
                     new_parents.push(delegation.paths().clone());
                     let (term, res) = lookup(
+                        start_time,
                         tuf,
                         delegation.terminating(),
                         current_depth + 1,
@@ -916,9 +940,18 @@
         match targets.delegations() {
             Some(d) => {
                 let mut visited = HashSet::new();
-                lookup(self, false, 0, target_path, d, &[], &mut visited)
-                    .1
-                    .ok_or(Error::TargetUnavailable)
+                lookup(
+                    start_time,
+                    self,
+                    false,
+                    0,
+                    target_path,
+                    d,
+                    &[],
+                    &mut visited,
+                )
+                .1
+                .ok_or(Error::TargetUnavailable)
             }
             None => Err(Error::TargetUnavailable),
         }
@@ -931,46 +964,50 @@
         self.trusted_delegations.clear();
     }
 
-    fn trusted_root_unexpired(&self) -> Result<&RootMetadata> {
+    fn trusted_root_unexpired(&self, start_time: &DateTime<Utc>) -> Result<&RootMetadata> {
         let trusted_root = &self.trusted_root;
-        if trusted_root.expires() <= &Utc::now() {
-            return Err(Error::ExpiredMetadata(Role::Root));
+        if trusted_root.expires() <= start_time {
+            return Err(Error::ExpiredMetadata(MetadataPath::root()));
         }
         Ok(trusted_root)
     }
 
-    fn trusted_snapshot_unexpired(&self) -> Result<&SnapshotMetadata> {
-        match self.trusted_snapshot {
-            Some(ref trusted_snapshot) => {
-                if trusted_snapshot.expires() <= &Utc::now() {
-                    return Err(Error::ExpiredMetadata(Role::Snapshot));
-                }
-                Ok(trusted_snapshot)
-            }
-            None => Err(Error::MissingMetadata(Role::Snapshot)),
-        }
-    }
-
-    fn trusted_targets_unexpired(&self) -> Result<&TargetsMetadata> {
-        match self.trusted_targets {
-            Some(ref trusted_targets) => {
-                if trusted_targets.expires() <= &Utc::now() {
-                    return Err(Error::ExpiredMetadata(Role::Targets));
-                }
-                Ok(trusted_targets)
-            }
-            None => Err(Error::MissingMetadata(Role::Targets)),
-        }
-    }
-    fn trusted_timestamp_unexpired(&self) -> Result<&TimestampMetadata> {
+    fn trusted_timestamp_unexpired(
+        &self,
+        start_time: &DateTime<Utc>,
+    ) -> Result<&TimestampMetadata> {
         match self.trusted_timestamp {
             Some(ref trusted_timestamp) => {
-                if trusted_timestamp.expires() <= &Utc::now() {
-                    return Err(Error::ExpiredMetadata(Role::Timestamp));
+                if trusted_timestamp.expires() <= start_time {
+                    return Err(Error::ExpiredMetadata(MetadataPath::timestamp()));
                 }
                 Ok(trusted_timestamp)
             }
-            None => Err(Error::MissingMetadata(Role::Timestamp)),
+            None => Err(Error::MissingMetadata(MetadataPath::timestamp())),
+        }
+    }
+
+    fn trusted_snapshot_unexpired(&self, start_time: &DateTime<Utc>) -> Result<&SnapshotMetadata> {
+        match self.trusted_snapshot {
+            Some(ref trusted_snapshot) => {
+                if trusted_snapshot.expires() <= start_time {
+                    return Err(Error::ExpiredMetadata(MetadataPath::snapshot()));
+                }
+                Ok(trusted_snapshot)
+            }
+            None => Err(Error::MissingMetadata(MetadataPath::snapshot())),
+        }
+    }
+
+    fn trusted_targets_unexpired(&self, start_time: &DateTime<Utc>) -> Result<&TargetsMetadata> {
+        match self.trusted_targets {
+            Some(ref trusted_targets) => {
+                if trusted_targets.expires() <= start_time {
+                    return Err(Error::ExpiredMetadata(MetadataPath::targets()));
+                }
+                Ok(trusted_targets)
+            }
+            None => Err(Error::MissingMetadata(MetadataPath::targets())),
         }
     }
 }
@@ -1180,6 +1217,8 @@
 
     #[test]
     fn good_timestamp_update() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1204,16 +1243,18 @@
         let raw_timestamp = timestamp.to_raw().unwrap();
 
         assert_matches!(
-            tuf.update_timestamp(&raw_timestamp),
+            tuf.update_timestamp(&now, &raw_timestamp),
             Ok(Some(_parsed_timestamp))
         );
 
         // second update should do nothing
-        assert_matches!(tuf.update_timestamp(&raw_timestamp), Ok(None))
+        assert_matches!(tuf.update_timestamp(&now, &raw_timestamp), Ok(None))
     }
 
     #[test]
     fn bad_timestamp_update_wrong_key() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1239,11 +1280,13 @@
                 .to_raw()
                 .unwrap();
 
-        assert!(tuf.update_timestamp(&raw_timestamp).is_err())
+        assert!(tuf.update_timestamp(&now, &raw_timestamp).is_err())
     }
 
     #[test]
     fn good_snapshot_update() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1267,16 +1310,18 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
 
-        assert_matches!(tuf.update_snapshot(&raw_snapshot), Ok(true));
+        assert_matches!(tuf.update_snapshot(&now, &raw_snapshot), Ok(true));
 
         // second update should do nothing
-        assert_matches!(tuf.update_snapshot(&raw_snapshot), Ok(false));
+        assert_matches!(tuf.update_snapshot(&now, &raw_snapshot), Ok(false));
     }
 
     #[test]
     fn bad_snapshot_update_wrong_key() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1303,13 +1348,15 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
 
-        assert!(tuf.update_snapshot(&raw_snapshot).is_err());
+        assert!(tuf.update_snapshot(&now, &raw_snapshot).is_err());
     }
 
     #[test]
     fn bad_snapshot_update_wrong_version() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1335,7 +1382,7 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
 
         let raw_snapshot = SnapshotMetadataBuilder::new()
             .version(1)
@@ -1344,11 +1391,13 @@
             .to_raw()
             .unwrap();
 
-        assert!(tuf.update_snapshot(&raw_snapshot).is_err());
+        assert!(tuf.update_snapshot(&now, &raw_snapshot).is_err());
     }
 
     #[test]
     fn good_targets_update() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1381,17 +1430,19 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
-        tuf.update_snapshot(&raw_snapshot).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
+        tuf.update_snapshot(&now, &raw_snapshot).unwrap();
 
-        assert_matches!(tuf.update_targets(&raw_targets), Ok(true));
+        assert_matches!(tuf.update_targets(&now, &raw_targets), Ok(true));
 
         // second update should do nothing
-        assert_matches!(tuf.update_targets(&raw_targets), Ok(false));
+        assert_matches!(tuf.update_targets(&now, &raw_targets), Ok(false));
     }
 
     #[test]
     fn bad_targets_update_wrong_key() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1425,14 +1476,16 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
-        tuf.update_snapshot(&raw_snapshot).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
+        tuf.update_snapshot(&now, &raw_snapshot).unwrap();
 
-        assert!(tuf.update_targets(&raw_targets).is_err());
+        assert!(tuf.update_targets(&now, &raw_targets).is_err());
     }
 
     #[test]
     fn bad_targets_update_wrong_version() {
+        let now = Utc::now();
+
         let raw_root = RootMetadataBuilder::new()
             .root_key(KEYS[0].public().clone())
             .snapshot_key(KEYS[1].public().clone())
@@ -1465,8 +1518,8 @@
                 .to_raw()
                 .unwrap();
 
-        tuf.update_timestamp(&raw_timestamp).unwrap();
-        tuf.update_snapshot(&raw_snapshot).unwrap();
+        tuf.update_timestamp(&now, &raw_timestamp).unwrap();
+        tuf.update_snapshot(&now, &raw_snapshot).unwrap();
 
         let raw_targets = TargetsMetadataBuilder::new()
             .version(1)
@@ -1475,7 +1528,7 @@
             .to_raw()
             .unwrap();
 
-        assert!(tuf.update_targets(&raw_targets).is_err());
+        assert!(tuf.update_targets(&now, &raw_targets).is_err());
     }
 
     #[test]
diff --git a/third_party/rust_crates/vendor/tuf/src/error.rs b/third_party/rust_crates/vendor/tuf/src/error.rs
index d808b7c..1e6b977 100644
--- a/third_party/rust_crates/vendor/tuf/src/error.rs
+++ b/third_party/rust_crates/vendor/tuf/src/error.rs
@@ -9,7 +9,7 @@
 use std::path::Path;
 use thiserror::Error;
 
-use crate::metadata::Role;
+use crate::metadata::MetadataPath;
 
 /// Error type for all TUF related errors.
 #[non_exhaustive]
@@ -25,7 +25,7 @@
 
     /// Metadata was expired.
     #[error("expired {0} metadata")]
-    ExpiredMetadata(Role),
+    ExpiredMetadata(MetadataPath),
 
     /// An illegal argument was passed into a function.
     #[error("illegal argument: {0}")]
@@ -52,7 +52,7 @@
 
     /// The metadata was missing, so an operation could not be completed.
     #[error("missing {0} metadata")]
-    MissingMetadata(Role),
+    MissingMetadata(MetadataPath),
 
     /// There were no available hash algorithms.
     #[error("no supported hash algorithm")]
diff --git a/third_party/rust_crates/vendor/tuf/src/interchange/cjson/shims.rs b/third_party/rust_crates/vendor/tuf/src/interchange/cjson/shims.rs
index d69e00e..a3f10a2 100644
--- a/third_party/rust_crates/vendor/tuf/src/interchange/cjson/shims.rs
+++ b/third_party/rust_crates/vendor/tuf/src/interchange/cjson/shims.rs
@@ -258,7 +258,7 @@
                         )));
                     }
 
-                    let s = p.split_at(p.len() - ".json".len()).0;
+                    let s = p.split_at(p.len() - ".json".len()).0.to_owned();
                     let p = metadata::MetadataPath::new(s)?;
 
                     Ok((p, d))
diff --git a/third_party/rust_crates/vendor/tuf/src/metadata.rs b/third_party/rust_crates/vendor/tuf/src/metadata.rs
index 14ffae0..d9ae3034 100644
--- a/third_party/rust_crates/vendor/tuf/src/metadata.rs
+++ b/third_party/rust_crates/vendor/tuf/src/metadata.rs
@@ -6,7 +6,7 @@
 use serde::de::{Deserialize, DeserializeOwned, Deserializer, Error as DeserializeError};
 use serde::ser::{Error as SerializeError, Serialize, Serializer};
 use serde_derive::{Deserialize, Serialize};
-use std::borrow::Borrow;
+use std::borrow::{Borrow, Cow};
 use std::collections::{HashMap, HashSet};
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
@@ -151,12 +151,15 @@
     /// The root role.
     #[serde(rename = "root")]
     Root,
+
     /// The snapshot role.
     #[serde(rename = "snapshot")]
     Snapshot,
+
     /// The targets role.
     #[serde(rename = "targets")]
     Targets,
+
     /// The timestamp role.
     #[serde(rename = "timestamp")]
     Timestamp,
@@ -168,12 +171,12 @@
     /// ```
     /// use tuf::metadata::{MetadataPath, Role};
     ///
-    /// assert!(Role::Root.fuzzy_matches_path(&MetadataPath::from_role(&Role::Root)));
-    /// assert!(Role::Snapshot.fuzzy_matches_path(&MetadataPath::from_role(&Role::Snapshot)));
-    /// assert!(Role::Targets.fuzzy_matches_path(&MetadataPath::from_role(&Role::Targets)));
-    /// assert!(Role::Timestamp.fuzzy_matches_path(&MetadataPath::from_role(&Role::Timestamp)));
+    /// assert!(Role::Root.fuzzy_matches_path(&MetadataPath::root()));
+    /// assert!(Role::Snapshot.fuzzy_matches_path(&MetadataPath::snapshot()));
+    /// assert!(Role::Targets.fuzzy_matches_path(&MetadataPath::targets()));
+    /// assert!(Role::Timestamp.fuzzy_matches_path(&MetadataPath::timestamp()));
     ///
-    /// assert!(!Role::Root.fuzzy_matches_path(&MetadataPath::from_role(&Role::Snapshot)));
+    /// assert!(!Role::Root.fuzzy_matches_path(&MetadataPath::snapshot()));
     /// assert!(!Role::Root.fuzzy_matches_path(&MetadataPath::new("wat").unwrap()));
     /// ```
     pub fn fuzzy_matches_path(&self, path: &MetadataPath) -> bool {
@@ -182,7 +185,7 @@
             Role::Snapshot if &path.0 == "snapshot" => true,
             Role::Timestamp if &path.0 == "timestamp" => true,
             Role::Targets if &path.0 == "targets" => true,
-            Role::Targets if !&["root", "snapshot", "targets"].contains(&path.0.as_str()) => true,
+            Role::Targets if !&["root", "snapshot", "targets"].contains(&path.0.as_ref()) => true,
             _ => false,
         }
     }
@@ -973,9 +976,29 @@
 /// let _ = MetadataPath::new("root.json");
 /// ```
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
-pub struct MetadataPath(String);
+pub struct MetadataPath(Cow<'static, str>);
 
 impl MetadataPath {
+    /// Create a new `MetadataPath` for the Root role.
+    pub fn root() -> Self {
+        MetadataPath(Role::Root.name().into())
+    }
+
+    /// Create a new `MetadataPath` for the Timestamp role.
+    pub fn timestamp() -> Self {
+        MetadataPath(Role::Timestamp.name().into())
+    }
+
+    /// Create a new `MetadataPath` for the Snapshot role.
+    pub fn snapshot() -> Self {
+        MetadataPath(Role::Snapshot.name().into())
+    }
+
+    /// Create a new `MetadataPath` for the targets role.
+    pub fn targets() -> Self {
+        MetadataPath(Role::Targets.name().into())
+    }
+
     /// Create a new `MetadataPath` from a `String`.
     ///
     /// ```
@@ -989,27 +1012,18 @@
     /// assert!(MetadataPath::new("foo/..bar").is_ok());
     /// assert!(MetadataPath::new("foo/bar..").is_ok());
     /// ```
-    pub fn new<P: Into<String>>(path: P) -> Result<Self> {
+    pub fn new<P: Into<Cow<'static, str>>>(path: P) -> Result<Self> {
         let path = path.into();
-        safe_path(&path)?;
-        Ok(MetadataPath(path))
-    }
-
-    /// Create a metadata path from the given role.
-    ///
-    /// ```
-    /// # use tuf::metadata::{Role, MetadataPath};
-    /// assert_eq!(MetadataPath::from_role(&Role::Root),
-    ///            MetadataPath::new("root").unwrap());
-    /// assert_eq!(MetadataPath::from_role(&Role::Snapshot),
-    ///            MetadataPath::new("snapshot").unwrap());
-    /// assert_eq!(MetadataPath::from_role(&Role::Targets),
-    ///            MetadataPath::new("targets").unwrap());
-    /// assert_eq!(MetadataPath::from_role(&Role::Timestamp),
-    ///            MetadataPath::new("timestamp").unwrap());
-    /// ```
-    pub fn from_role(role: &Role) -> Self {
-        Self::new(format!("{}", role)).unwrap()
+        match path.as_ref() {
+            "root" => Ok(MetadataPath::root()),
+            "timestamp" => Ok(MetadataPath::timestamp()),
+            "snapshot" => Ok(MetadataPath::snapshot()),
+            "targets" => Ok(MetadataPath::targets()),
+            _ => {
+                safe_path(&path)?;
+                Ok(MetadataPath(path))
+            }
+        }
     }
 
     /// Split `MetadataPath` into components that can be joined to create URL paths, Unix paths, or
@@ -1037,6 +1051,17 @@
     }
 }
 
+impl From<Role> for MetadataPath {
+    fn from(role: Role) -> MetadataPath {
+        match role {
+            Role::Root => MetadataPath::root(),
+            Role::Timestamp => MetadataPath::timestamp(),
+            Role::Snapshot => MetadataPath::snapshot(),
+            Role::Targets => MetadataPath::targets(),
+        }
+    }
+}
+
 impl Display for MetadataPath {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&self.0)
@@ -1332,7 +1357,7 @@
         hash_algs: &[HashAlgorithm],
     ) -> Result<Self>
     where
-        P: Into<String>,
+        P: Into<Cow<'static, str>>,
         M: Metadata,
         D: DataInterchange,
     {
diff --git a/third_party/rust_crates/vendor/tuf/src/repo_builder.rs b/third_party/rust_crates/vendor/tuf/src/repo_builder.rs
index 46ce6d0..0079145 100644
--- a/third_party/rust_crates/vendor/tuf/src/repo_builder.rs
+++ b/third_party/rust_crates/vendor/tuf/src/repo_builder.rs
@@ -7,10 +7,10 @@
         interchange::DataInterchange,
         metadata::{
             Metadata, MetadataDescription, MetadataPath, MetadataVersion, RawSignedMetadata,
-            RawSignedMetadataSet, RawSignedMetadataSetBuilder, Role, RootMetadata,
-            RootMetadataBuilder, SignedMetadataBuilder, SnapshotMetadata, SnapshotMetadataBuilder,
-            TargetDescription, TargetPath, TargetsMetadata, TargetsMetadataBuilder,
-            TimestampMetadata, TimestampMetadataBuilder,
+            RawSignedMetadataSet, RawSignedMetadataSetBuilder, RootMetadata, RootMetadataBuilder,
+            SignedMetadataBuilder, SnapshotMetadata, SnapshotMetadataBuilder, TargetDescription,
+            TargetPath, TargetsMetadata, TargetsMetadataBuilder, TimestampMetadata,
+            TimestampMetadataBuilder,
         },
         repository::RepositoryStorage,
         Error, Result,
@@ -707,7 +707,7 @@
         } else if let Some(db) = self.ctx.db {
             db.trusted_root().consistent_snapshot()
         } else {
-            return Err(Error::MissingMetadata(Role::Root));
+            return Err(Error::MissingMetadata(MetadataPath::root()));
         };
 
         let target_description = TargetDescription::from_reader_with_custom(
@@ -929,10 +929,8 @@
 
         // Overwrite the targets entry if specified.
         if let Some(targets_description) = self.state.targets_description()? {
-            snapshot_builder = snapshot_builder.insert_metadata_description(
-                MetadataPath::from_role(&Role::Targets),
-                targets_description,
-            );
+            snapshot_builder = snapshot_builder
+                .insert_metadata_description(MetadataPath::targets(), targets_description);
         };
 
         let snapshot = f(snapshot_builder).build()?;
@@ -1082,7 +1080,7 @@
                 .db
                 .and_then(|db| db.trusted_timestamp())
                 .map(|timestamp| timestamp.snapshot().clone())
-                .ok_or(Error::MissingMetadata(Role::Timestamp))?
+                .ok_or_else(|| Error::MissingMetadata(MetadataPath::timestamp()))?
         };
 
         let timestamp_builder = TimestampMetadataBuilder::from_metadata_description(description)
@@ -1213,19 +1211,21 @@
         } else if let Some(ref root) = self.state.staged_root {
             Database::from_trusted_root(&root.raw)?
         } else {
-            return Err(Error::MissingMetadata(Role::Root));
+            return Err(Error::MissingMetadata(MetadataPath::root()));
         };
 
+        let now = Utc::now();
+
         if let Some(ref timestamp) = self.state.staged_timestamp {
-            db.update_timestamp(&timestamp.raw)?;
+            db.update_timestamp(&now, &timestamp.raw)?;
         }
 
         if let Some(ref snapshot) = self.state.staged_snapshot {
-            db.update_snapshot(&snapshot.raw)?;
+            db.update_snapshot(&now, &snapshot.raw)?;
         }
 
         if let Some(ref targets) = self.state.staged_targets {
-            db.update_targets(&targets.raw)?;
+            db.update_targets(&now, &targets.raw)?;
         }
 
         Ok(())
@@ -1236,7 +1236,7 @@
             self.ctx
                 .repo
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Root),
+                    &MetadataPath::root(),
                     MetadataVersion::Number(root.metadata.version()),
                     &mut root.raw.as_bytes(),
                 )
@@ -1245,7 +1245,7 @@
             self.ctx
                 .repo
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Root),
+                    &MetadataPath::root(),
                     MetadataVersion::None,
                     &mut root.raw.as_bytes(),
                 )
@@ -1255,11 +1255,11 @@
         } else if let Some(db) = self.ctx.db {
             db.trusted_root().consistent_snapshot()
         } else {
-            return Err(Error::MissingMetadata(Role::Root));
+            return Err(Error::MissingMetadata(MetadataPath::root()));
         };
 
         if let Some(ref targets) = self.state.staged_targets {
-            let path = MetadataPath::from_role(&Role::Targets);
+            let path = MetadataPath::targets();
             self.ctx
                 .repo
                 .store_metadata(&path, MetadataVersion::None, &mut targets.raw.as_bytes())
@@ -1278,7 +1278,7 @@
         }
 
         if let Some(ref snapshot) = self.state.staged_snapshot {
-            let path = MetadataPath::from_role(&Role::Snapshot);
+            let path = MetadataPath::snapshot();
             self.ctx
                 .repo
                 .store_metadata(&path, MetadataVersion::None, &mut snapshot.raw.as_bytes())
@@ -1300,7 +1300,7 @@
             self.ctx
                 .repo
                 .store_metadata(
-                    &MetadataPath::from_role(&Role::Timestamp),
+                    &MetadataPath::timestamp(),
                     MetadataVersion::None,
                     &mut timestamp.raw.as_bytes(),
                 )
@@ -1432,7 +1432,7 @@
         };
 
         let snapshot = SnapshotMetadataBuilder::new()
-            .insert_metadata_description(MetadataPath::from_role(&Role::Targets), description)
+            .insert_metadata_description(MetadataPath::targets(), description)
             .version(version)
             .expires(expires)
             .build()
@@ -1598,35 +1598,23 @@
         // Make sure we stored the metadata correctly.
         let mut expected_metadata: BTreeMap<_, _> = vec![
             (
-                (
-                    MetadataPath::from_role(&Role::Root),
-                    MetadataVersion::Number(1),
-                ),
+                (MetadataPath::root(), MetadataVersion::Number(1)),
                 raw_root1.as_bytes(),
             ),
             (
-                (MetadataPath::from_role(&Role::Root), MetadataVersion::None),
+                (MetadataPath::root(), MetadataVersion::None),
                 raw_root1.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Targets),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::targets(), MetadataVersion::None),
                 raw_targets1.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Snapshot),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::snapshot(), MetadataVersion::None),
                 raw_snapshot1.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Timestamp),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::timestamp(), MetadataVersion::None),
                 raw_timestamp1.as_bytes(),
             ),
         ]
@@ -1636,17 +1624,11 @@
         if consistent_snapshot {
             expected_metadata.extend(vec![
                 (
-                    (
-                        MetadataPath::from_role(&Role::Targets),
-                        MetadataVersion::Number(1),
-                    ),
+                    (MetadataPath::targets(), MetadataVersion::Number(1)),
                     raw_targets1.as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Snapshot),
-                        MetadataVersion::Number(1),
-                    ),
+                    (MetadataPath::snapshot(), MetadataVersion::Number(1)),
                     raw_snapshot1.as_bytes(),
                 ),
             ]);
@@ -1726,35 +1708,23 @@
         // Check that the new metadata was written.
         expected_metadata.extend(vec![
             (
-                (
-                    MetadataPath::from_role(&Role::Root),
-                    MetadataVersion::Number(2),
-                ),
+                (MetadataPath::root(), MetadataVersion::Number(2)),
                 raw_root2.as_bytes(),
             ),
             (
-                (MetadataPath::from_role(&Role::Root), MetadataVersion::None),
+                (MetadataPath::root(), MetadataVersion::None),
                 raw_root2.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Targets),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::targets(), MetadataVersion::None),
                 raw_targets2.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Snapshot),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::snapshot(), MetadataVersion::None),
                 raw_snapshot2.as_bytes(),
             ),
             (
-                (
-                    MetadataPath::from_role(&Role::Timestamp),
-                    MetadataVersion::None,
-                ),
+                (MetadataPath::timestamp(), MetadataVersion::None),
                 raw_timestamp2.as_bytes(),
             ),
         ]);
@@ -1762,17 +1732,11 @@
         if consistent_snapshot {
             expected_metadata.extend(vec![
                 (
-                    (
-                        MetadataPath::from_role(&Role::Targets),
-                        MetadataVersion::Number(2),
-                    ),
+                    (MetadataPath::targets(), MetadataVersion::Number(2)),
                     raw_targets2.as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Snapshot),
-                        MetadataVersion::Number(2),
-                    ),
+                    (MetadataPath::snapshot(), MetadataVersion::Number(2)),
                     raw_snapshot2.as_bytes(),
                 ),
             ]);
@@ -2222,49 +2186,31 @@
 
             let mut expected_metadata: BTreeMap<_, _> = vec![
                 (
-                    (
-                        MetadataPath::from_role(&Role::Root),
-                        MetadataVersion::Number(1),
-                    ),
+                    (MetadataPath::root(), MetadataVersion::Number(1)),
                     metadata1.root().unwrap().as_bytes(),
                 ),
                 (
-                    (MetadataPath::from_role(&Role::Root), MetadataVersion::None),
+                    (MetadataPath::root(), MetadataVersion::None),
                     metadata1.root().unwrap().as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Targets),
-                        MetadataVersion::Number(1),
-                    ),
+                    (MetadataPath::targets(), MetadataVersion::Number(1)),
                     metadata1.targets().unwrap().as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Targets),
-                        MetadataVersion::None,
-                    ),
+                    (MetadataPath::targets(), MetadataVersion::None),
                     metadata1.targets().unwrap().as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Snapshot),
-                        MetadataVersion::Number(1),
-                    ),
+                    (MetadataPath::snapshot(), MetadataVersion::Number(1)),
                     metadata1.snapshot().unwrap().as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Snapshot),
-                        MetadataVersion::None,
-                    ),
+                    (MetadataPath::snapshot(), MetadataVersion::None),
                     metadata1.snapshot().unwrap().as_bytes(),
                 ),
                 (
-                    (
-                        MetadataPath::from_role(&Role::Timestamp),
-                        MetadataVersion::None,
-                    ),
+                    (MetadataPath::timestamp(), MetadataVersion::None),
                     metadata1.timestamp().unwrap().as_bytes(),
                 ),
             ]
@@ -2302,38 +2248,23 @@
             expected_metadata.extend(
                 vec![
                     (
-                        (
-                            MetadataPath::from_role(&Role::Targets),
-                            MetadataVersion::Number(2),
-                        ),
+                        (MetadataPath::targets(), MetadataVersion::Number(2)),
                         metadata2.targets().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Targets),
-                            MetadataVersion::None,
-                        ),
+                        (MetadataPath::targets(), MetadataVersion::None),
                         metadata2.targets().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Snapshot),
-                            MetadataVersion::Number(2),
-                        ),
+                        (MetadataPath::snapshot(), MetadataVersion::Number(2)),
                         metadata2.snapshot().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Snapshot),
-                            MetadataVersion::None,
-                        ),
+                        (MetadataPath::snapshot(), MetadataVersion::None),
                         metadata2.snapshot().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Timestamp),
-                            MetadataVersion::None,
-                        ),
+                        (MetadataPath::timestamp(), MetadataVersion::None),
                         metadata2.timestamp().unwrap().as_bytes(),
                     ),
                 ]
@@ -2368,24 +2299,15 @@
             expected_metadata.extend(
                 vec![
                     (
-                        (
-                            MetadataPath::from_role(&Role::Snapshot),
-                            MetadataVersion::Number(3),
-                        ),
+                        (MetadataPath::snapshot(), MetadataVersion::Number(3)),
                         metadata3.snapshot().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Snapshot),
-                            MetadataVersion::None,
-                        ),
+                        (MetadataPath::snapshot(), MetadataVersion::None),
                         metadata3.snapshot().unwrap().as_bytes(),
                     ),
                     (
-                        (
-                            MetadataPath::from_role(&Role::Timestamp),
-                            MetadataVersion::None,
-                        ),
+                        (MetadataPath::timestamp(), MetadataVersion::None),
                         metadata3.timestamp().unwrap().as_bytes(),
                     ),
                 ]
@@ -2417,10 +2339,7 @@
 
             expected_metadata.extend(
                 vec![(
-                    (
-                        MetadataPath::from_role(&Role::Timestamp),
-                        MetadataVersion::None,
-                    ),
+                    (MetadataPath::timestamp(), MetadataVersion::None),
                     metadata4.timestamp().unwrap().as_bytes(),
                 )]
                 .into_iter(),
diff --git a/third_party/rust_crates/vendor/tuf/src/repository.rs b/third_party/rust_crates/vendor/tuf/src/repository.rs
index 6f80c06..861416b 100644
--- a/third_party/rust_crates/vendor/tuf/src/repository.rs
+++ b/third_party/rust_crates/vendor/tuf/src/repository.rs
@@ -514,7 +514,7 @@
 mod test {
     use super::*;
     use crate::interchange::Json;
-    use crate::metadata::{MetadataPath, MetadataVersion, Role, RootMetadata, SnapshotMetadata};
+    use crate::metadata::{MetadataPath, MetadataVersion, RootMetadata, SnapshotMetadata};
     use crate::repository::EphemeralRepository;
     use assert_matches::assert_matches;
     use futures_executor::block_on;
@@ -526,7 +526,7 @@
 
             assert_matches!(
                 repo.fetch_metadata::<RootMetadata>(
-                    &MetadataPath::from_role(&Role::Root),
+                    &MetadataPath::root(),
                     MetadataVersion::None,
                     None,
                     vec![],
@@ -543,17 +543,13 @@
             let mut repo = Repository::<_, Json>::new(EphemeralRepository::new());
             let fake_metadata = RawSignedMetadata::<Json, RootMetadata>::new(vec![]);
 
-            repo.store_metadata(
-                &MetadataPath::from_role(&Role::Root),
-                MetadataVersion::None,
-                &fake_metadata,
-            )
-            .await
-            .unwrap();
+            repo.store_metadata(&MetadataPath::root(), MetadataVersion::None, &fake_metadata)
+                .await
+                .unwrap();
 
             assert_matches!(
                 repo.store_metadata(
-                    &MetadataPath::from_role(&Role::Snapshot),
+                    &MetadataPath::snapshot(),
                     MetadataVersion::None,
                     &fake_metadata,
                 )
@@ -563,7 +559,7 @@
 
             assert_matches!(
                 repo.fetch_metadata::<SnapshotMetadata>(
-                    &MetadataPath::from_role(&Role::Root),
+                    &MetadataPath::root(),
                     MetadataVersion::None,
                     None,
                     vec![],
@@ -577,7 +573,7 @@
     #[test]
     fn repository_verifies_metadata_hash() {
         block_on(async {
-            let path = MetadataPath::from_role(&Role::Root);
+            let path = MetadataPath::root();
             let version = MetadataVersion::None;
             let data: &[u8] = b"valid metadata";
             let _metadata = RawSignedMetadata::<Json, RootMetadata>::new(data.to_vec());
@@ -607,7 +603,7 @@
     #[test]
     fn repository_rejects_corrupt_metadata() {
         block_on(async {
-            let path = MetadataPath::from_role(&Role::Root);
+            let path = MetadataPath::root();
             let version = MetadataVersion::None;
             let data: &[u8] = b"corrupt metadata";
 
@@ -635,7 +631,7 @@
     #[test]
     fn repository_verifies_metadata_size() {
         block_on(async {
-            let path = MetadataPath::from_role(&Role::Root);
+            let path = MetadataPath::root();
             let version = MetadataVersion::None;
             let data: &[u8] = b"reasonably sized metadata";
             let _metadata = RawSignedMetadata::<Json, RootMetadata>::new(data.to_vec());
@@ -659,7 +655,7 @@
     #[test]
     fn repository_rejects_oversized_metadata() {
         block_on(async {
-            let path = MetadataPath::from_role(&Role::Root);
+            let path = MetadataPath::root();
             let version = MetadataVersion::None;
             let data: &[u8] = b"very big metadata";
 
diff --git a/third_party/rust_crates/vendor/tuf/src/repository/file_system.rs b/third_party/rust_crates/vendor/tuf/src/repository/file_system.rs
index bea4ed3..80c7651 100644
--- a/third_party/rust_crates/vendor/tuf/src/repository/file_system.rs
+++ b/third_party/rust_crates/vendor/tuf/src/repository/file_system.rs
@@ -347,7 +347,7 @@
     use super::*;
     use crate::error::Error;
     use crate::interchange::Json;
-    use crate::metadata::{Role, RootMetadata};
+    use crate::metadata::RootMetadata;
     use crate::repository::{fetch_metadata_to_string, fetch_target_to_string, Repository};
     use assert_matches::assert_matches;
     use futures_executor::block_on;
@@ -368,7 +368,7 @@
             assert_matches!(
                 Repository::<_, Json>::new(repo)
                     .fetch_metadata::<RootMetadata>(
-                        &MetadataPath::from_role(&Role::Root),
+                        &MetadataPath::root(),
                         MetadataVersion::None,
                         None,
                         vec![],
diff --git a/third_party/rust_crates/vendor/tuf/src/repository/track_repo.rs b/third_party/rust_crates/vendor/tuf/src/repository/track_repo.rs
index 6149e48..c7d0762 100644
--- a/third_party/rust_crates/vendor/tuf/src/repository/track_repo.rs
+++ b/third_party/rust_crates/vendor/tuf/src/repository/track_repo.rs
@@ -48,11 +48,7 @@
         M: Metadata,
         D: DataInterchange,
     {
-        Self::store(
-            &MetadataPath::from_role(&M::ROLE),
-            version,
-            metadata.as_bytes(),
-        )
+        Self::store(&M::ROLE.into(), version, metadata.as_bytes())
     }
 
     pub(crate) fn fetch_found<T>(
@@ -78,11 +74,7 @@
         M: Metadata,
         D: DataInterchange,
     {
-        Track::fetch_found(
-            &MetadataPath::from_role(&M::ROLE),
-            version,
-            metadata.as_bytes(),
-        )
+        Track::fetch_found(&M::ROLE.into(), version, metadata.as_bytes())
     }
 }
 
diff --git a/third_party/rust_crates/vendor/tuf/tests/integration.rs b/third_party/rust_crates/vendor/tuf/tests/integration.rs
index 0edf478..c633c7d 100644
--- a/third_party/rust_crates/vendor/tuf/tests/integration.rs
+++ b/third_party/rust_crates/vendor/tuf/tests/integration.rs
@@ -1,11 +1,11 @@
 use assert_matches::assert_matches;
+use chrono::offset::Utc;
 use futures_executor::block_on;
 use maplit::hashmap;
 use tuf::crypto::{Ed25519PrivateKey, HashAlgorithm, PrivateKey};
 use tuf::interchange::Json;
 use tuf::metadata::{
-    Delegation, Delegations, MetadataDescription, MetadataPath, Role, TargetPath,
-    TargetsMetadataBuilder,
+    Delegation, Delegations, MetadataDescription, MetadataPath, TargetPath, TargetsMetadataBuilder,
 };
 use tuf::repo_builder::RepoBuilder;
 use tuf::repository::EphemeralRepository;
@@ -22,6 +22,8 @@
 #[test]
 fn simple_delegation() {
     block_on(async {
+        let now = Utc::now();
+
         let root_key = Ed25519PrivateKey::from_pkcs8(ED25519_1_PK8).unwrap();
         let snapshot_key = Ed25519PrivateKey::from_pkcs8(ED25519_2_PK8).unwrap();
         let targets_key = Ed25519PrivateKey::from_pkcs8(ED25519_3_PK8).unwrap();
@@ -84,8 +86,9 @@
             .unwrap();
         let raw_delegation = delegation.to_raw().unwrap();
 
-        tuf.update_delegation(
-            &MetadataPath::from_role(&Role::Targets),
+        tuf.update_delegated_targets(
+            &now,
+            &MetadataPath::targets(),
             &MetadataPath::new("delegation").unwrap(),
             &raw_delegation,
         )
@@ -100,6 +103,8 @@
 #[test]
 fn nested_delegation() {
     block_on(async {
+        let now = Utc::now();
+
         let root_key = Ed25519PrivateKey::from_pkcs8(ED25519_1_PK8).unwrap();
         let snapshot_key = Ed25519PrivateKey::from_pkcs8(ED25519_2_PK8).unwrap();
         let targets_key = Ed25519PrivateKey::from_pkcs8(ED25519_3_PK8).unwrap();
@@ -179,8 +184,9 @@
             .unwrap();
         let raw_delegation = delegation.to_raw().unwrap();
 
-        tuf.update_delegation(
-            &MetadataPath::from_role(&Role::Targets),
+        tuf.update_delegated_targets(
+            &now,
+            &MetadataPath::targets(),
             &MetadataPath::new("delegation-a").unwrap(),
             &raw_delegation,
         )
@@ -201,7 +207,8 @@
             .unwrap();
         let raw_delegation = delegation.to_raw().unwrap();
 
-        tuf.update_delegation(
+        tuf.update_delegated_targets(
+            &now,
             &MetadataPath::new("delegation-a").unwrap(),
             &MetadataPath::new("delegation-b").unwrap(),
             &raw_delegation,
@@ -217,6 +224,8 @@
 #[test]
 fn rejects_bad_delegation_signatures() {
     block_on(async {
+        let now = Utc::now();
+
         let root_key = Ed25519PrivateKey::from_pkcs8(ED25519_1_PK8).unwrap();
         let snapshot_key = Ed25519PrivateKey::from_pkcs8(ED25519_2_PK8).unwrap();
         let targets_key = Ed25519PrivateKey::from_pkcs8(ED25519_3_PK8).unwrap();
@@ -280,8 +289,9 @@
         let raw_delegation = delegation.to_raw().unwrap();
 
         assert_matches!(
-            tuf.update_delegation(
-                &MetadataPath::from_role(&Role::Targets),
+            tuf.update_delegated_targets(
+                &now,
+                &MetadataPath::targets(),
                 &MetadataPath::new("delegation").unwrap(),
                 &raw_delegation
             ),
@@ -298,6 +308,8 @@
 #[test]
 fn diamond_delegation() {
     block_on(async {
+        let now = Utc::now();
+
         let etc_key = Ed25519PrivateKey::from_pkcs8(ED25519_1_PK8).unwrap();
         let targets_key = Ed25519PrivateKey::from_pkcs8(ED25519_2_PK8).unwrap();
         let delegation_a_key = Ed25519PrivateKey::from_pkcs8(ED25519_3_PK8).unwrap();
@@ -320,6 +332,73 @@
         //
         // Verify tuf::Database handles this situation correctly.
 
+        //// build delegation A ////
+
+        let delegation_a_delegations = Delegations::new(
+            hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
+            vec![Delegation::new(
+                MetadataPath::new("delegation-c").unwrap(),
+                false,
+                1,
+                vec![delegation_c_key.public().key_id().clone()].iter().cloned().collect(),
+                vec![TargetPath::new("foo").unwrap()].iter().cloned().collect(),
+            )
+            .unwrap()],
+        )
+        .unwrap();
+
+        let delegation_a = TargetsMetadataBuilder::new()
+            .delegations(delegation_a_delegations)
+            .signed::<Json>(&delegation_a_key)
+            .unwrap();
+        let raw_delegation_a = delegation_a.to_raw().unwrap();
+
+        //// build delegation B ////
+
+        let delegations_b = Delegations::new(
+            hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
+            vec![Delegation::new(
+                MetadataPath::new("delegation-c").unwrap(),
+                false,
+                1,
+                // oops, wrong key.
+                vec![delegation_b_key.public().key_id().clone()].iter().cloned().collect(),
+                vec![TargetPath::new("bar").unwrap()].iter().cloned().collect(),
+            )
+            .unwrap()],
+        )
+        .unwrap();
+
+        let delegation_b = TargetsMetadataBuilder::new()
+            .delegations(delegations_b)
+            .signed::<Json>(&delegation_b_key)
+            .unwrap();
+        let raw_delegation_b = delegation_b.to_raw().unwrap();
+
+        //// build delegation C ////
+
+        let foo_target_file: &[u8] = b"foo contents";
+        let bar_target_file: &[u8] = b"bar contents";
+
+        let delegation_c = TargetsMetadataBuilder::new()
+            .insert_target_from_slice(
+                TargetPath::new("foo").unwrap(),
+                foo_target_file,
+                &[HashAlgorithm::Sha256],
+            )
+            .unwrap()
+            .insert_target_from_slice(
+                TargetPath::new("bar").unwrap(),
+                bar_target_file,
+                &[HashAlgorithm::Sha256],
+            )
+            .unwrap()
+            .signed::<Json>(&delegation_c_key)
+            .unwrap();
+        let raw_delegation_c = delegation_c.to_raw().unwrap();
+
+        //// construct the database ////
+
         let delegations = Delegations::new(
             hashmap! {
                 delegation_a_key.public().key_id().clone() => delegation_a_key.public().clone(),
@@ -372,18 +451,30 @@
                 builder
                     .insert_metadata_description(
                         MetadataPath::new("delegation-a").unwrap(),
-                        MetadataDescription::from_slice(&[0u8], 1, &[HashAlgorithm::Sha256])
-                            .unwrap(),
+                        MetadataDescription::from_slice(
+                            raw_delegation_a.as_bytes(),
+                            1,
+                            &[HashAlgorithm::Sha256],
+                        )
+                        .unwrap(),
                     )
                     .insert_metadata_description(
                         MetadataPath::new("delegation-b").unwrap(),
-                        MetadataDescription::from_slice(&[0u8], 1, &[HashAlgorithm::Sha256])
-                            .unwrap(),
+                        MetadataDescription::from_slice(
+                            raw_delegation_b.as_bytes(),
+                            1,
+                            &[HashAlgorithm::Sha256],
+                        )
+                        .unwrap(),
                     )
                     .insert_metadata_description(
                         MetadataPath::new("delegation-c").unwrap(),
-                        MetadataDescription::from_slice(&[0u8], 1, &[HashAlgorithm::Sha256])
-                            .unwrap(),
+                        MetadataDescription::from_slice(
+                            raw_delegation_c.as_bytes(),
+                            1,
+                            &[HashAlgorithm::Sha256],
+                        )
+                        .unwrap(),
                     )
             })
             .unwrap()
@@ -393,103 +484,44 @@
 
         let mut tuf = Database::<Json>::from_trusted_metadata(&metadata).unwrap();
 
-        //// build delegation A ////
+        //// Verify we can trust delegation-a and delegation-b..
 
-        let delegations = Delegations::new(
-        hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
-        vec![Delegation::new(
-            MetadataPath::new("delegation-c").unwrap(),
-            false,
-            1,
-            vec![delegation_c_key.public().key_id().clone()].iter().cloned().collect(),
-            vec![TargetPath::new("foo").unwrap()].iter().cloned().collect(),
-        )
-        .unwrap()],
-    )
-    .unwrap();
-
-        let delegation = TargetsMetadataBuilder::new()
-            .delegations(delegations)
-            .signed::<Json>(&delegation_a_key)
-            .unwrap();
-        let raw_delegation = delegation.to_raw().unwrap();
-
-        tuf.update_delegation(
-            &MetadataPath::from_role(&Role::Targets),
+        tuf.update_delegated_targets(
+            &now,
+            &MetadataPath::targets(),
             &MetadataPath::new("delegation-a").unwrap(),
-            &raw_delegation,
+            &raw_delegation_a,
         )
         .unwrap();
 
-        //// build delegation B ////
-
-        let delegations = Delegations::new(
-        hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
-        vec![Delegation::new(
-            MetadataPath::new("delegation-c").unwrap(),
-            false,
-            1,
-            // oops, wrong key.
-            vec![delegation_b_key.public().key_id().clone()].iter().cloned().collect(),
-            vec![TargetPath::new("bar").unwrap()].iter().cloned().collect(),
-        )
-        .unwrap()],
-    )
-    .unwrap();
-
-        let delegation = TargetsMetadataBuilder::new()
-            .delegations(delegations)
-            .signed::<Json>(&delegation_b_key)
-            .unwrap();
-        let raw_delegation = delegation.to_raw().unwrap();
-
-        tuf.update_delegation(
-            &MetadataPath::from_role(&Role::Targets),
+        tuf.update_delegated_targets(
+            &now,
+            &MetadataPath::targets(),
             &MetadataPath::new("delegation-b").unwrap(),
-            &raw_delegation,
+            &raw_delegation_b,
         )
         .unwrap();
 
-        //// build delegation C ////
-
-        let foo_target_file: &[u8] = b"foo contents";
-        let bar_target_file: &[u8] = b"bar contents";
-
-        let delegation = TargetsMetadataBuilder::new()
-            .insert_target_from_slice(
-                TargetPath::new("foo").unwrap(),
-                foo_target_file,
-                &[HashAlgorithm::Sha256],
-            )
-            .unwrap()
-            .insert_target_from_slice(
-                TargetPath::new("bar").unwrap(),
-                bar_target_file,
-                &[HashAlgorithm::Sha256],
-            )
-            .unwrap()
-            .signed::<Json>(&delegation_c_key)
-            .unwrap();
-        let raw_delegation = delegation.to_raw().unwrap();
-
         //// Verify delegation-c is valid, but only when updated through delegation-a.
 
-        tuf.update_delegation(
-            &MetadataPath::new("delegation-a").unwrap(),
-            &MetadataPath::new("delegation-c").unwrap(),
-            &raw_delegation,
-        )
-        .unwrap();
-
         assert_matches!(
-            tuf.update_delegation(
+            tuf.update_delegated_targets(
+                &now,
                 &MetadataPath::new("delegation-b").unwrap(),
                 &MetadataPath::new("delegation-c").unwrap(),
-                &raw_delegation
+                &raw_delegation_c
             ),
             Err(Error::VerificationFailure(_))
         );
 
+        tuf.update_delegated_targets(
+            &now,
+            &MetadataPath::new("delegation-a").unwrap(),
+            &MetadataPath::new("delegation-c").unwrap(),
+            &raw_delegation_c,
+        )
+        .unwrap();
+
         assert!(tuf
             .target_description(&TargetPath::new("foo").unwrap())
             .is_ok());