// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "assertion/validator.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/no_destructor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "assertion/actions_assertion_validator.h"
#include "assertion/assertion_parser.h"
#include "assertion/hashed_uri_validator.h"
#include "assertion/references_validator.h"
#include "constants/ingredient_relationships.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "google/protobuf/repeated_ptr_field.h"
#include "jumbf/box.h"
#include "jumbf/uri.h"
#include "proto/actions_assertion.pb.h"
#include "proto/assertion.pb.h"
#include "proto/generator_info.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/manifest.pb.h"
#include "validator/tracker.h"

namespace credentio {
namespace {

using ::jumbf::BinaryDataBox;
using ::jumbf::CborBox;
using ::jumbf::EmbeddedFileDescriptionBox;
using ::jumbf::JsonBox;
using ::jumbf::SuperBox;

constexpr absl::string_view kUnknown = "c2pa.unknown";

enum ManifestType {
  kStandardManifest,
  kUpdateManifest,
};

absl::string_view Basename(absl::string_view path) {
  const size_t pos = path.find_last_of('/');
  if (pos == absl::string_view::npos) {
    return path;
  }
  return path.substr(pos + 1);
}

template <typename ActionsT>
bool ValidateActions(const ActionsT& actions, absl::string_view assertion_url,
                     ValidationTracker& validation_tracker) {
  for (const auto& action : actions.actions()) {
    if (action.action() == kUnknown) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kGoogleAssertionActionUnknownAction,
          {.url = assertion_url});
      return false;
    }
  }
  return true;
}

bool HasSuccesses(const ValidationStatusSet& validation) {
  return !validation.successes().empty();
}

bool HasFailures(const ValidationStatusSet& validation) {
  return !validation.failures().empty();
}

bool IsHardBindingSuccessCode(absl::string_view code) {
  static const absl::NoDestructor<absl::flat_hash_set<std::string>>
      kHardBindingSuccessCodes({
          absl::StrCat(SuccessStatusCode::kAssertionBmffHashMatch),
          absl::StrCat(SuccessStatusCode::kAssertionBoxesHashMatch),
          absl::StrCat(SuccessStatusCode::kAssertionCollectionHashMatch),
          absl::StrCat(SuccessStatusCode::kAssertionDataHashMatch),
      });
  return kHardBindingSuccessCodes->contains(code);
}

bool HasHardBindingSuccess(const ValidationStatusSet& validation) {
  return std::any_of(validation.successes().begin(),
                     validation.successes().end(), [](const auto& status) {
                       return IsHardBindingSuccessCode(status.code());
                     });
}

bool ValidateIngredientAssertionValidationResults(
    const IngredientAssertionV3& ingredient, absl::string_view assertion_url,
    ManifestType manifest_type, ValidationTracker& validation_tracker) {
  if (!ingredient.has_active_manifest()) {
    // No validation results expected.
    return true;
  }
  const ValidationStatusSet& ingredient_validation =
      ingredient.validation_results().active_manifest();
  if (!HasFailures(ingredient_validation)) {
    switch (manifest_type) {
      case kStandardManifest:
        if (!HasHardBindingSuccess(ingredient_validation)) {
          validation_tracker.RecordFailure(
              FailureStatusCode::kAssertionIngredientMalformed,
              {.url = assertion_url,
               .explanation = "no hard binding check recorded"});
          return false;
        }
        break;
      case kUpdateManifest:
        if (!HasSuccesses(ingredient_validation)) {
          validation_tracker.RecordFailure(
              FailureStatusCode::kAssertionIngredientMalformed,
              {.url = assertion_url,
               .explanation = "no validation successes or failures recorded"});
          return false;
        }
        break;
    }
  }
  return true;
}

bool IsValidIngredientRelationship(absl::string_view relationship) {
  return relationship == kIngredientRelationshipParentOf ||
         relationship == kIngredientRelationshipComponentOf ||
         relationship == kIngredientRelationshipInputTo;
}

bool ValidateIngredientAssertion(const IngredientAssertionV3& ingredient,
                                 absl::string_view assertion_url,
                                 ManifestType manifest_type,
                                 ValidationTracker& validation_tracker) {
  if (ingredient.has_active_manifest() &&
      !ingredient.digital_source_type().empty()) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionIngredientMalformed,
        {.url = assertion_url,
         .explanation = "Ingredient assertion must not contain both "
                        "activeManifest and digitalSourceType"});
    return false;
  }
  // Note that while
  // https://spec.c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_performing_explicit_validation
  // only calls for relationship validation on v3 ingredient assertions, this
  // was subsequently corrected for C2PA 2.2 in
  // https://github.com/c2pa-org/specs-core/pull/1513.
  if (ingredient.relationship().empty()) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionIngredientMalformed,
        {.url = assertion_url,
         .explanation = "Missing ingredient relationship"});
    return false;
  }
  if (!IsValidIngredientRelationship(ingredient.relationship())) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionIngredientMalformed,
        {.url = assertion_url,
         .explanation = "Unrecognized ingredient relationship"});
    return false;
  }
  return ValidateIngredientAssertionValidationResults(
      ingredient, assertion_url, manifest_type, validation_tracker);
}

bool ActionAllowedInUpdateManifest(absl::string_view action) {
  return action == "c2pa.edited.metadata" || action == "c2pa.opened" ||
         action == "c2pa.published" || action == "c2pa.redacted";
}

struct AssertionCounter {
  uint32_t hard_bindings = 0;
  uint32_t ingredients = 0;
  uint32_t thumbnails = 0;
  std::string action_disallowed_in_update;
  absl::flat_hash_map<std::string, uint32_t> ingredient_relationships;
  bool has_soft_binding = false;
  bool has_watermarked_bound_action = false;

  void RecordAction(absl::string_view action) {
    if (action_disallowed_in_update.empty() &&
        !ActionAllowedInUpdateManifest(action)) {
      action_disallowed_in_update = action;
    }
    if (action == "c2pa.watermarked.bound" || action == "c2pa.watermarked") {
      has_watermarked_bound_action = true;
    }
  }

  void Add(const Assertion& assertion) {
    if (assertion.has_soft_binding()) {
      has_soft_binding = true;
    }
    if (assertion.has_data_hash() || assertion.has_bmff_based_hash() ||
        assertion.has_boxes_hash() || assertion.has_collection_data_hash()) {
      if (!absl::StrContains(assertion.label(), ".part")) {
        // Only count the full asset hard binding.
        ++hard_bindings;
      }
    }
    for (const auto& action : assertion.actions().actions()) {
      RecordAction(action.action());
    }
    for (const auto& action : assertion.actions_v1().actions()) {
      RecordAction(action.action());
    }
    if (assertion.has_ingredient_v3()) {
      ++ingredients;
      ++ingredient_relationships[assertion.ingredient_v3().relationship()];
    }
    if (assertion.has_claim_thumbnail() ||
        assertion.has_ingredient_thumbnail()) {
      ++thumbnails;
    }
  }

  // See:
  // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_validate_the_assertions
  void ValidateStandardManifestCounts(absl::string_view claim_box_url,
                                      ValidationTracker& validation_tracker) {
    if (hard_bindings == 0) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kClaimHardBindingsMissing,
          {.url = claim_box_url,
           .explanation = "Standard manifest must contain one hard binding."});
    } else if (hard_bindings > 1) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionMultipleHardBindings,
          {.url = kAssertionStoreLabel,
           .explanation = "Standard manifest must not contain more than one "
                          "hard binding."});
    }
    if (ingredient_relationships[kIngredientRelationshipParentOf] > 1) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kManifestMultipleParents,
          {.url = claim_box_url,
           .explanation = "Standard manifest must contain at most one "
                          "ingredient with parentOf relationship."});
    }
  }

  // See:
  // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_validate_the_assertions
  void ValidateUpdateManifestCounts(absl::string_view claim_box_url,
                                    ValidationTracker& validation_tracker) {
    if (hard_bindings != 0) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kManifestUpdateInvalid,
          {.url = claim_box_url,
           .explanation = "Update manifest must not contain hard bindings."});
    }
    if (!action_disallowed_in_update.empty()) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kManifestUpdateInvalid,
          {.url = claim_box_url,
           .explanation =
               absl::StrCat("Update manifest contains disallowed action: ",
                            action_disallowed_in_update)});
    }
    if (ingredients != 1) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kManifestUpdateWrongParents,
          {.url = claim_box_url,
           .explanation = absl::StrCat(
               "Update manifest must contain exactly one ingredient; found ",
               ingredients)});
    } else if (ingredient_relationships[kIngredientRelationshipParentOf] != 1) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kManifestUpdateWrongParents,
          {.url = claim_box_url,
           .explanation =
               "Update manifest ingredient relationship must be parentOf."});
    }
  }

  void ValidateSoftBinding(absl::string_view claim_box_url,
                           ValidationTracker& validation_tracker) {
    if (has_watermarked_bound_action && !has_soft_binding) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionActionSoftBindingMissing,
          {.url = claim_box_url,
           .explanation = "c2pa.watermarked.bound action requires a "
                          "c2pa.soft-binding assertion"});
    }
  }
};

void ValidateCborAssertion(
    absl::string_view label, absl::string_view payload,
    ManifestType manifest_type, const AssertionParser& assertion_parser,
    const ReferencesValidator& references_validator,
    google::protobuf::RepeatedPtrField<Assertion>* assertions_out,
    ValidationTracker& validation_tracker,
    AssertionCounter& assertion_counter) {
  std::optional<Assertion> assertion_proto =
      assertion_parser.ParseCbor(label, payload, validation_tracker);
  if (!assertion_proto.has_value()) {
    return;
  }
  assertion_counter.Add(*assertion_proto);
  if (!references_validator.Validate(*assertion_proto)) {
    return;
  }
  const std::string assertion_url = absl::StrCat(
      kAssertionStoreLabel, kManifestLabelDelimiter, assertion_proto->label());
  switch (assertion_proto->assertion_case()) {
    case Assertion::kActionsV1:
      if (!ValidateActions(assertion_proto->actions_v1(), assertion_url,
                           validation_tracker)) {
        return;
      }
      break;
    case Assertion::kActions:
      if (!ValidateActions(assertion_proto->actions(), assertion_url,
                           validation_tracker)) {
        return;
      }
      break;
    case Assertion::kIngredientV3:
      if (!ValidateIngredientAssertion(assertion_proto->ingredient_v3(),
                                       assertion_url, manifest_type,
                                       validation_tracker)) {
        return;
      }
      break;
    default:
      break;
  }
  assertions_out->Add(*std::move(assertion_proto));
}

void ValidateAssertionContents(
    const SuperBox* assertion_box, ManifestType manifest_type,
    const AssertionParser& assertion_parser,
    const ReferencesValidator& references_validator,
    google::protobuf::RepeatedPtrField<Assertion>* assertions_out,
    ValidationTracker& validation_tracker,
    AssertionCounter& assertion_counter) {
  // CBOR assertion.
  if (assertion_box->contents.size() == 1 &&
      assertion_box->contents[0].Holds<CborBox>()) {
    ValidateCborAssertion(assertion_box->description.label.value_or(""),
                          assertion_box->contents[0].Get<CborBox>().payload,
                          manifest_type, assertion_parser, references_validator,
                          assertions_out, validation_tracker,
                          assertion_counter);
    return;
  }
  // Thumbnail assertion (EmbeddedFileDescriptionBox + BinaryDataBox).
  if (assertion_box->contents.size() == 2 &&
      assertion_box->contents[0].Holds<EmbeddedFileDescriptionBox>() &&
      assertion_box->contents[1].Holds<BinaryDataBox>()) {
    std::optional<Assertion> assertion_proto = assertion_parser.ParseThumbnail(
        assertion_box->description.label.value_or(""),
        assertion_box->contents[0].Get<EmbeddedFileDescriptionBox>().media_type,
        assertion_box->contents[1].Get<BinaryDataBox>().payload,
        assertion_box->contents[0].Get<EmbeddedFileDescriptionBox>().file_name,
        validation_tracker);
    if (assertion_proto.has_value()) {
      assertions_out->Add(*std::move(assertion_proto));
    }
    return;
  }
  // JSON-LD assertion (e.g., c2pa.metadata).
  if (assertion_box->contents.size() == 1 &&
      assertion_box->contents[0].Holds<JsonBox>()) {
    std::optional<Assertion> assertion_proto = assertion_parser.ParseMetadata(
        assertion_box->description.label.value_or(""),
        assertion_box->contents[0].Get<JsonBox>().payload, validation_tracker);
    if (assertion_proto.has_value()) {
      assertions_out->Add(*std::move(assertion_proto));
    }
    return;
  }

  // Ignore other types of assertions.
}

bool ContainsAllZeroBytes(absl::string_view data) {
  return std::all_of(data.begin(), data.end(), [](char c) { return c == 0; });
}

bool ContainsAllZeroBytes(const jumbf::ContentBox& content) {
  if (content.Holds<CborBox>()) {
    return ContainsAllZeroBytes(content.Get<CborBox>().payload);
  }
  if (content.Holds<JsonBox>()) {
    return ContainsAllZeroBytes(content.Get<JsonBox>().payload);
  }
  if (content.Holds<BinaryDataBox>()) {
    return ContainsAllZeroBytes(content.Get<BinaryDataBox>().payload);
  }
  if (content.Holds<EmbeddedFileDescriptionBox>()) {
    // We don't (yet) require redaction of the file description.
    return true;
  }
  return false;
}

bool ContainsAllZeroBytes(const jumbf::SuperBox& box) {
  return std::all_of(
      box.contents.begin(), box.contents.end(),
      [](const auto& content) { return ContainsAllZeroBytes(content); });
}

void ValidateRedactionsAllowed(const Claim& claim,
                               ValidationTracker& validation_tracker) {
  // Note that the selfRedacted check is done in ManifestGraph.
  const AssertionTypeMatcher actions_v1_matcher(kActionsAssertionV1Label);
  const AssertionTypeMatcher actions_v2_matcher(kActionsAssertionV2Label);
  for (const auto& redacted_assertion : claim.redacted_assertions()) {
    absl::string_view label = Basename(redacted_assertion);
    if (actions_v1_matcher.Matches(label) ||
        actions_v2_matcher.Matches(label)) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionActionRedacted,
          {.url = absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter,
                               label)});
    }
  }
}

// Returns true if `path` is a child of `parent`.
bool IsChildPath(absl::string_view path, absl::string_view parent) {
  if (!absl::StartsWith(path, parent)) return false;
  if (path.size() <= parent.size()) return false;
  if (path[parent.size()] != '/') return false;
  return path.find('/', parent.size() + 1) == absl::string_view::npos;
}

// Returns true if the validation succeeded.
bool ValidateRedactedAssertion(absl::string_view path,
                               const jumbf::UriResolver& uri_resolver,
                               ValidationTracker& validation_tracker) {
  // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_claim_signature_hash_validation_method
  // "if the referenced assertion is present and its data consists of anything
  // other than zero or more 0x00 bytes, the claim shall be rejected with a
  // failure code of assertion.notRedacted."

  auto box = uri_resolver.ResolvePath(path);
  if (!box.ok()) {
    return true;
  }
  if (!ContainsAllZeroBytes(**box)) {
    validation_tracker.RecordFailure(FailureStatusCode::kAssertionNotRedacted,
                                     {.url = path});
    return false;
  }
  return true;
}

std::optional<HashedUri> ConvertToHashedUri(
    const InternalOrExternalHashedUri& uri, absl::string_view default_algorithm,
    absl::string_view claim_uri, ValidationTracker& validation_tracker) {
  if (!uri.has_url()) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kHashedUriMissing,
        {.url = claim_uri, .explanation = "Icon URI is missing"});
    return std::nullopt;
  }
  if (!absl::StartsWith(uri.url(), "self#jumbf=")) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kGoogleHashedUriUnsupported,
        {.url = claim_uri,
         .explanation = "Icon URI is pointing to an external resource"});
    return std::nullopt;
  }
  HashedUri hashed_uri;
  hashed_uri.set_url(uri.url());
  hashed_uri.set_hash(uri.hash());
  hashed_uri.set_algorithm(uri.has_algorithm() ? uri.algorithm()
                                               : default_algorithm);
  return hashed_uri;
}

void ValidateAssertion(
    const HashedUri& hashed_uri, absl::string_view manifest_path,
    ManifestType manifest_type,
    const absl::flat_hash_set<std::string>& redacted_assertion_paths,
    const HashedUriValidator& assertion_uri_validator,
    const ReferencesValidator& references_validator,
    absl::string_view assertion_store_path, const Claim& claim,
    const jumbf::UriResolver& uri_resolver,
    const AssertionParser& assertion_parser,
    google::protobuf::RepeatedPtrField<Assertion>* assertions_out,
    absl::flat_hash_set<std::string>& assertion_labels,
    ValidationTracker& validation_tracker,
    AssertionCounter& assertion_counter) {
  auto assertion_path = jumbf::UriResolver::GetAbsolutePathFromUri(
      hashed_uri.url(), manifest_path);
  if (!assertion_path.ok()) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionMissing,
        {.explanation = "malformed assertion URI"});
    return;
  }
  if (redacted_assertion_paths.contains(*assertion_path)) {
    if (ValidateRedactedAssertion(*assertion_path, uri_resolver,
                                  validation_tracker)) {
      Assertion* redacted_assertion = assertions_out->Add();
      redacted_assertion->set_label(Basename(*assertion_path));
      redacted_assertion->mutable_redacted_by_generator();
    }
    // Don't treat the redacted assertion as undeclared.
    assertion_labels.insert(std::string(Basename(*assertion_path)));
    return;
  }
  if (!assertion_uri_validator
           .Validate(hashed_uri, absl::StrCat("self#jumbf=", *assertion_path),
                     validation_tracker)
           .has_value()) {
    return;  // Failure has been recorded by Validate().
  }
  validation_tracker.RecordSuccess(
      SuccessStatusCode::kAssertionHashedUriMatch,
      {.url = absl::StrCat("self#jumbf=", *assertion_path)});
  if (!absl::StartsWith(*assertion_path, manifest_path)) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionOutsideManifest,
        {.url = claim.label(),
         .explanation =
             absl::StrCat("Violated claim assertion: ", *assertion_path)});
    return;
  }
  if (!IsChildPath(*assertion_path, assertion_store_path)) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionMissing,
        {.url = claim.label(),
         .explanation =
             absl::StrCat("Violated claim assertion: ", *assertion_path)});
    return;
  }
  auto assertion_box = uri_resolver.ResolvePath(*assertion_path);
  if (!assertion_box.ok()) {
    // Can't happen -- assertion_uri_validator.Validate would have failed.
    DLOG(FATAL) << "unexpected missing assertion: " << assertion_box.status();
    validation_tracker.RecordFailure(
        FailureStatusCode::kGoogleInternalError,
        {.url = claim.label(), .explanation = "unexpected missing assertion"});
    return;
  }
  ValidateAssertionContents(*assertion_box, manifest_type, assertion_parser,
                            references_validator, assertions_out,
                            validation_tracker, assertion_counter);
  assertion_labels.insert(std::string(Basename(*assertion_path)));
}

void ValidateClaimGeneratorIcon(const Claim& claim,
                                absl::string_view manifest_path,
                                const HashedUriValidator& hashed_uri_validator,
                                ValidationTracker& validation_tracker) {
  if (!claim.claim_generator_info().has_icon()) {
    return;
  }
  std::optional<HashedUri> icon_hashed_uri = ConvertToHashedUri(
      claim.claim_generator_info().icon(), claim.default_algorithm(),
      claim.label(), validation_tracker);
  if (icon_hashed_uri.has_value()) {
    auto icon_path = jumbf::UriResolver::GetAbsolutePathFromUri(
        icon_hashed_uri->url(), manifest_path);
    if (!icon_path.ok()) {
      // The only way this can happen is if the icon URI doesn't start with
      // "self#jumbf=". This would have already been caught by
      // ConvertToHashedUri.
      validation_tracker.RecordFailure(
          FailureStatusCode::kHashedUriMissing,
          {.url = claim.label(), .explanation = "Icon URI is malformed"});
    } else if (hashed_uri_validator
                   .Validate(*icon_hashed_uri, claim.label(),
                             validation_tracker)
                   .has_value()) {
      // No success code for icon URI validation. See
      // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_validation_of_references
    }
  }
}

void ValidateUndeclaredAssertions(
    absl::string_view assertion_store_path,
    const absl::flat_hash_set<std::string>& assertion_labels,
    const jumbf::UriResolver& uri_resolver,
    ValidationTracker& validation_tracker) {
  auto assertion_store_box = uri_resolver.ResolvePath(assertion_store_path);
  if (!assertion_store_box.ok()) {
    return;
  }
  for (const auto& content : (*assertion_store_box)->contents) {
    if (!content.Holds<SuperBox>()) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionUndeclared,
          {.explanation =
               "Assertion store contains a box that is not a superbox."});
      continue;
    }
    const SuperBox& assertion_box = content.Get<SuperBox>();
    auto assertion_label = assertion_box.description.label.value_or("");
    if (!assertion_labels.contains(assertion_label)) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionUndeclared,
          {.url = absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter,
                               assertion_label)});
      continue;
    }
  }
}

}  // namespace

void AssertionValidator::ValidateClaimAssertions(
    const jumbf::UriResolver& uri_resolver,
    const absl::flat_hash_set<std::string>& redacted_assertion_paths,
    Manifest& manifest, ValidationTracker& validation_tracker) const {
  std::string manifest_path = absl::StrCat("/c2pa/", manifest.label());
  const Claim& claim = manifest.claim();
  AssertionCounter assertion_counter;
  auto assertion_store_path =
      jumbf::UriResolver::GetAbsolutePath(kAssertionStoreLabel, manifest_path);
  // Validates claim assertion URIs.
  HashedUriValidator assertion_uri_validator(std::string(manifest_path),
                                             uri_resolver);
  assertion_uri_validator.SetErrorCodes(HashedUriValidator::Codes{
      .missing = FailureStatusCode::kAssertionMissing,
      .mismatch = FailureStatusCode::kAssertionHashedUriMismatch});
  assertion_uri_validator.SetDefaultAlgorithm(claim.default_algorithm());
  HashedUriValidator hashed_uri_validator(std::string(manifest_path),
                                          uri_resolver);
  hashed_uri_validator.SetDefaultAlgorithm(claim.default_algorithm());

  ValidateClaimGeneratorIcon(claim, manifest_path, hashed_uri_validator,
                             validation_tracker);

  ManifestType manifest_type = manifest.is_update_manifest()
                                   ? ManifestType::kUpdateManifest
                                   : ManifestType::kStandardManifest;
  ReferencesValidator references_validator(
      &hashed_uri_validator, manifest.label(), &validation_tracker);
  absl::flat_hash_set<std::string> assertion_labels;
  assertion_labels.reserve(claim.created_assertions_size() +
                           claim.gathered_assertions_size());
  for (const auto& assertions :
       {claim.created_assertions(), claim.gathered_assertions()}) {
    for (const HashedUri& hashed_uri : assertions) {
      ValidateAssertion(
          hashed_uri, manifest_path, manifest_type, redacted_assertion_paths,
          assertion_uri_validator, references_validator, assertion_store_path,
          claim, uri_resolver, assertion_parser_, manifest.mutable_assertions(),
          assertion_labels, validation_tracker, assertion_counter);
    }
  }

  // Validate that this claim's redactions are allowed.
  ValidateRedactionsAllowed(claim, validation_tracker);

  switch (manifest_type) {
    case ManifestType::kUpdateManifest:
      assertion_counter.ValidateUpdateManifestCounts(claim.label(),
                                                     validation_tracker);
      break;
    case ManifestType::kStandardManifest:
      assertion_counter.ValidateStandardManifestCounts(claim.label(),
                                                       validation_tracker);
      break;
  }

  assertion_counter.ValidateSoftBinding(claim.label(), validation_tracker);

  // Validates any undeclared assertions.
  ValidateUndeclaredAssertions(assertion_store_path, assertion_labels,
                               uri_resolver, validation_tracker);

  if (!options_.skip_actions_assertion_validation_for_test) {
    ActionsAssertionValidator actions_validator;
    actions_validator.Validate(manifest, validation_tracker);
  }
}

}  // namespace credentio
