From dcc032cccf752f686f246754c6e9ce6ccdd487fc Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Mon, 10 Feb 2025 21:38:53 -0800
Subject: [PATCH 1/7] rest client 1.10 parsing

---
 src/AppInstallerCLITests/RestClient.cpp       |  2 +-
 .../AppInstallerRepositoryCore.vcxproj        |  4 +++
 ...AppInstallerRepositoryCore.vcxproj.filters | 18 +++++++++++
 .../ManifestJSONParser.cpp                    |  7 ++++-
 .../Rest/RestClient.cpp                       |  7 ++++-
 .../Rest/Schema/1_10/Interface.h              | 21 +++++++++++++
 .../Schema/1_10/Json/ManifestDeserializer.h   | 17 +++++++++++
 .../1_10/Json/ManifestDeserializer_1_10.cpp   | 30 +++++++++++++++++++
 .../Rest/Schema/1_10/RestInterface_1_10.cpp   | 26 ++++++++++++++++
 .../Rest/Schema/CommonRestConstants.h         |  1 +
 10 files changed, 130 insertions(+), 3 deletions(-)
 create mode 100644 src/AppInstallerRepositoryCore/Rest/Schema/1_10/Interface.h
 create mode 100644 src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer.h
 create mode 100644 src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer_1_10.cpp
 create mode 100644 src/AppInstallerRepositoryCore/Rest/Schema/1_10/RestInterface_1_10.cpp

diff --git a/src/AppInstallerCLITests/RestClient.cpp b/src/AppInstallerCLITests/RestClient.cpp
index 7713d791d5..4bd534794b 100644
--- a/src/AppInstallerCLITests/RestClient.cpp
+++ b/src/AppInstallerCLITests/RestClient.cpp
@@ -61,7 +61,7 @@ TEST_CASE("GetSupportedInterface", "[RestSource]")
     REQUIRE(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, version, {})->GetVersion() == version);
 
     // Update this test to next version so that we don't forget to add to supported versions before rest e2e tests are available.
-    Version invalid{ "1.10.0" };
+    Version invalid{ "1.11.0" };
     REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, invalid, {}), APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION);
 
     Authentication::AuthenticationArguments authArgs;
diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
index d70fb30e56..8ffaf09a66 100644
--- a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
+++ b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
@@ -439,6 +439,8 @@
     <ClInclude Include="Rest\Schema\1_0\Json\ManifestDeserializer.h" />
     <ClInclude Include="Rest\Schema\1_0\Json\SearchRequestSerializer.h" />
     <ClInclude Include="Rest\Schema\1_0\Json\SearchResponseDeserializer.h" />
+    <ClInclude Include="Rest\Schema\1_10\Interface.h" />
+    <ClInclude Include="Rest\Schema\1_10\Json\ManifestDeserializer.h" />
     <ClInclude Include="Rest\Schema\1_1\Interface.h" />
     <ClInclude Include="Rest\Schema\1_1\Json\ManifestDeserializer.h" />
     <ClInclude Include="Rest\Schema\1_1\Json\SearchRequestSerializer.h" />
@@ -534,6 +536,8 @@
     <ClCompile Include="Rest\Schema\1_0\Json\ManifestDeserializer_1_0.cpp" />
     <ClCompile Include="Rest\Schema\1_0\Json\SearchRequestSerializer_1_0.cpp" />
     <ClCompile Include="Rest\Schema\1_0\Json\SearchResponseDeserializer_1_0.cpp" />
+    <ClCompile Include="Rest\Schema\1_10\Json\ManifestDeserializer_1_10.cpp" />
+    <ClCompile Include="Rest\Schema\1_10\RestInterface_1_10.cpp" />
     <ClCompile Include="Rest\Schema\1_1\Json\ManifestDeserializer_1_1.cpp" />
     <ClCompile Include="Rest\Schema\1_1\Json\SearchRequestSerializer_1_1.cpp" />
     <ClCompile Include="Rest\Schema\1_1\RestInterface_1_1.cpp" />
diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters
index 1b91d82bcf..60b6b9b6c3 100644
--- a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters
+++ b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters
@@ -109,6 +109,12 @@
     <Filter Include="Rest\Schema\1_9\Json">
       <UniqueIdentifier>{7464e3ff-7a60-4bb6-8806-70562382043b}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Rest\Schema\1_10">
+      <UniqueIdentifier>{da801426-6d3b-40ca-b204-152e7e18067b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Rest\Schema\1_10\Json">
+      <UniqueIdentifier>{1a1efb9f-7332-4094-bb98-a4c51ea68b24}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="pch.h">
@@ -474,6 +480,12 @@
     <ClInclude Include="Rest\Schema\1_9\Interface.h">
       <Filter>Rest\Schema\1_9</Filter>
     </ClInclude>
+    <ClInclude Include="Rest\Schema\1_10\Interface.h">
+      <Filter>Rest\Schema\1_10</Filter>
+    </ClInclude>
+    <ClInclude Include="Rest\Schema\1_10\Json\ManifestDeserializer.h">
+      <Filter>Rest\Schema\1_10\Json</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="pch.cpp">
@@ -740,6 +752,12 @@
     <ClCompile Include="Rest\Schema\1_9\RestInterface_1_9.cpp">
       <Filter>Rest\Schema\1_9</Filter>
     </ClCompile>
+    <ClCompile Include="Rest\Schema\1_10\RestInterface_1_10.cpp">
+      <Filter>Rest\Schema\1_10</Filter>
+    </ClCompile>
+    <ClCompile Include="Rest\Schema\1_10\Json\ManifestDeserializer_1_10.cpp">
+      <Filter>Rest\Schema\1_10\Json</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="PropertySheet.props" />
diff --git a/src/AppInstallerRepositoryCore/ManifestJSONParser.cpp b/src/AppInstallerRepositoryCore/ManifestJSONParser.cpp
index d30a871cdf..b9a6eac39c 100644
--- a/src/AppInstallerRepositoryCore/ManifestJSONParser.cpp
+++ b/src/AppInstallerRepositoryCore/ManifestJSONParser.cpp
@@ -9,6 +9,7 @@
 #include "Rest/Schema/1_6/Json/ManifestDeserializer.h"
 #include "Rest/Schema/1_7/Json/ManifestDeserializer.h"
 #include "Rest/Schema/1_9/Json/ManifestDeserializer.h"
+#include "Rest/Schema/1_10/Json/ManifestDeserializer.h"
 
 namespace AppInstaller::Repository::JSON
 {
@@ -51,10 +52,14 @@ namespace AppInstaller::Repository::JSON
             {
                 m_pImpl->m_deserializer = std::make_unique<Rest::Schema::V1_7::Json::ManifestDeserializer>();
             }
-            else
+            else if (parts.size() > 1 && parts[1].Integer < 10)
             {
                 m_pImpl->m_deserializer = std::make_unique<Rest::Schema::V1_9::Json::ManifestDeserializer>();
             }
+            else
+            {
+                m_pImpl->m_deserializer = std::make_unique<Rest::Schema::V1_10::Json::ManifestDeserializer>();
+            }
         }
         else
         {
diff --git a/src/AppInstallerRepositoryCore/Rest/RestClient.cpp b/src/AppInstallerRepositoryCore/Rest/RestClient.cpp
index c7f0bfd79c..e4442df051 100644
--- a/src/AppInstallerRepositoryCore/Rest/RestClient.cpp
+++ b/src/AppInstallerRepositoryCore/Rest/RestClient.cpp
@@ -9,6 +9,7 @@
 #include "Rest/Schema/1_6/Interface.h"
 #include "Rest/Schema/1_7/Interface.h"
 #include "Rest/Schema/1_9/Interface.h"
+#include "Rest/Schema/1_10/Interface.h"
 #include "Rest/Schema/InformationResponseDeserializer.h"
 #include "Rest/Schema/CommonRestConstants.h"
 #include <winget/HttpClientHelper.h>
@@ -23,7 +24,7 @@ using namespace AppInstaller::Http;
 namespace AppInstaller::Repository::Rest
 {
     // Supported versions
-    std::set<Version> WingetSupportedContracts = { Version_1_0_0, Version_1_1_0, Version_1_4_0, Version_1_5_0, Version_1_6_0, Version_1_7_0, Version_1_9_0 };
+    std::set<Version> WingetSupportedContracts = { Version_1_0_0, Version_1_1_0, Version_1_4_0, Version_1_5_0, Version_1_6_0, Version_1_7_0, Version_1_9_0, Version_1_10_0 };
 
     constexpr std::string_view WindowsPackageManagerHeader = "Windows-Package-Manager"sv;
     constexpr size_t WindowsPackageManagerHeaderMaxLength = 1024;
@@ -181,6 +182,10 @@ namespace AppInstaller::Repository::Rest
         {
             return std::make_unique<Schema::V1_9::Interface>(api, helper, information, additionalHeaders, authArgs);
         }
+        else if (version == Version_1_10_0)
+        {
+            return std::make_unique<Schema::V1_10::Interface>(api, helper, information, additionalHeaders, authArgs);
+        }
 
         THROW_HR(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION);
     }
diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Interface.h
new file mode 100644
index 0000000000..7ff88a28e3
--- /dev/null
+++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Interface.h
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#pragma once
+#include "Rest/Schema/1_9/Interface.h"
+
+namespace AppInstaller::Repository::Rest::Schema::V1_10
+{
+    // Interface to this schema version exposed through IRestClient.
+    struct Interface : public V1_9::Interface
+    {
+        Interface(const std::string& restApi, const Http::HttpClientHelper& helper, IRestClient::Information information, const Http::HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, Authentication::AuthenticationArguments authArgs = {});
+
+        Interface(const Interface&) = delete;
+        Interface& operator=(const Interface&) = delete;
+
+        Interface(Interface&&) = default;
+        Interface& operator=(Interface&&) = default;
+
+        Utility::Version GetVersion() const override;
+    };
+}
diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer.h
new file mode 100644
index 0000000000..202440543f
--- /dev/null
+++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer.h
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#pragma once
+#include "Rest/Schema/1_9/Json/ManifestDeserializer.h"
+
+namespace AppInstaller::Repository::Rest::Schema::V1_10::Json
+{
+    // Manifest Deserializer.
+    struct ManifestDeserializer : public V1_9::Json::ManifestDeserializer
+    {
+    protected:
+
+        std::optional<Manifest::ManifestInstaller> DeserializeInstaller(const web::json::value& installerJsonObject) const override;
+
+        Manifest::ManifestVer GetManifestVersion() const override;
+    };
+}
diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer_1_10.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer_1_10.cpp
new file mode 100644
index 0000000000..d4d5ce643c
--- /dev/null
+++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/Json/ManifestDeserializer_1_10.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#include "pch.h"
+#include "ManifestDeserializer.h"
+#include "Rest/Schema/AuthenticationInfoParser.h"
+#include <winget/JsonUtil.h>
+
+using namespace AppInstaller::Manifest;
+
+namespace AppInstaller::Repository::Rest::Schema::V1_10::Json
+{
+    std::optional<Manifest::ManifestInstaller> ManifestDeserializer::DeserializeInstaller(const web::json::value& installerJsonObject) const
+    {
+        auto result = V1_9::Json::ManifestDeserializer::DeserializeInstaller(installerJsonObject);
+
+        if (result)
+        {
+            auto& installer = result.value();
+
+            installer.AuthInfo = ParseAuthenticationInfo(installerJsonObject, ParseAuthenticationInfoType::Installer, GetManifestVersion());
+        }
+
+        return result;
+    }
+
+    Manifest::ManifestVer ManifestDeserializer::GetManifestVersion() const
+    {
+        return Manifest::s_ManifestVersionV1_10;
+    }
+}
diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_10/RestInterface_1_10.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/RestInterface_1_10.cpp
new file mode 100644
index 0000000000..c53f1387d2
--- /dev/null
+++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_10/RestInterface_1_10.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#include "pch.h"
+#include "Rest/Schema/1_10/Interface.h"
+#include "Rest/Schema/CommonRestConstants.h"
+#include "Rest/Schema/IRestClient.h"
+#include <winget/HttpClientHelper.h>
+#include <winget/JsonUtil.h>
+
+namespace AppInstaller::Repository::Rest::Schema::V1_10
+{
+    Interface::Interface(
+        const std::string& restApi,
+        const Http::HttpClientHelper& httpClientHelper,
+        IRestClient::Information information,
+        const Http::HttpClientHelper::HttpRequestHeaders& additionalHeaders,
+        Authentication::AuthenticationArguments authArgs) : V1_9::Interface(restApi, httpClientHelper, std::move(information), additionalHeaders, std::move(authArgs))
+    {
+        m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_10_0.ToString());
+    }
+
+    Utility::Version Interface::GetVersion() const
+    {
+        return Version_1_10_0;
+    }
+}
diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/CommonRestConstants.h b/src/AppInstallerRepositoryCore/Rest/Schema/CommonRestConstants.h
index 6ee979b7aa..6f02692843 100644
--- a/src/AppInstallerRepositoryCore/Rest/Schema/CommonRestConstants.h
+++ b/src/AppInstallerRepositoryCore/Rest/Schema/CommonRestConstants.h
@@ -13,6 +13,7 @@ namespace AppInstaller::Repository::Rest::Schema
     const Utility::Version Version_1_6_0{ "1.6.0" };
     const Utility::Version Version_1_7_0{ "1.7.0" };
     const Utility::Version Version_1_9_0{ "1.9.0" };
+    const Utility::Version Version_1_10_0{ "1.10.0" };
 
     // General API response constants
     constexpr std::string_view Data = "Data"sv;

From d44b7434948c948be3d284bcef5ac7b4abe15e21 Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 15:24:59 -0800
Subject: [PATCH 2/7] rest 110 test

---
 .../AppInstallerCLITests.vcxproj              |   1 +
 .../AppInstallerCLITests.vcxproj.filters      |   3 +
 .../RestInterface_1_10.cpp                    | 411 ++++++++++++++++++
 3 files changed, 415 insertions(+)
 create mode 100644 src/AppInstallerCLITests/RestInterface_1_10.cpp

diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
index 538c2f6367..ddacac2ee2 100644
--- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
+++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
@@ -319,6 +319,7 @@
     <ClCompile Include="RestClient.cpp" />
     <ClCompile Include="RestInterface_1_0.cpp" />
     <ClCompile Include="RestInterface_1_1.cpp" />
+    <ClCompile Include="RestInterface_1_10.cpp" />
     <ClCompile Include="RestInterface_1_4.cpp" />
     <ClCompile Include="RestInterface_1_5.cpp" />
     <ClCompile Include="RestInterface_1_6.cpp" />
diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters
index 5da81fec15..bd0da2c2dc 100644
--- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters
+++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters
@@ -374,6 +374,9 @@
     <ClCompile Include="Fonts.cpp">
       <Filter>Source Files\Common</Filter>
     </ClCompile>
+    <ClCompile Include="RestInterface_1_10.cpp">
+      <Filter>Source Files\Repository</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="PropertySheet.props" />
diff --git a/src/AppInstallerCLITests/RestInterface_1_10.cpp b/src/AppInstallerCLITests/RestInterface_1_10.cpp
new file mode 100644
index 0000000000..87130fd366
--- /dev/null
+++ b/src/AppInstallerCLITests/RestInterface_1_10.cpp
@@ -0,0 +1,411 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#include "pch.h"
+#include "TestCommon.h"
+#include "TestRestRequestHandler.h"
+#include <Rest/Schema/1_10/Interface.h>
+#include <Rest/Schema/IRestClient.h>
+#include <AppInstallerVersions.h>
+#include <AppInstallerErrors.h>
+
+using namespace TestCommon;
+using namespace AppInstaller::Http;
+using namespace AppInstaller::Utility;
+using namespace AppInstaller::Manifest;
+using namespace AppInstaller::Repository;
+using namespace AppInstaller::Repository::Rest;
+using namespace AppInstaller::Repository::Rest::Schema;
+using namespace AppInstaller::Repository::Rest::Schema::V1_10;
+
+namespace
+{
+    const std::string TestRestUriString = "http://restsource.com/api";
+
+    struct GoodManifest_AllFields
+    {
+        utility::string_t GetSampleManifest_AllFields()
+        {
+            return _XPLATSTR(
+                R"delimiter(
+        {
+          "Data": {
+            "PackageIdentifier": "Foo.Bar",
+            "Versions": [
+              {
+                "PackageVersion": "3.0.0abc",
+                "DefaultLocale": {
+                  "PackageLocale": "en-US",
+                  "Publisher": "Foo",
+                  "PublisherUrl": "http://publisher.net",
+                  "PublisherSupportUrl": "http://publisherSupport.net",
+                  "PrivacyUrl": "http://packagePrivacyUrl.net",
+                  "Author": "FooBar",
+                  "PackageName": "Bar",
+                  "PackageUrl": "http://packageUrl.net",
+                  "License": "Foo Bar License",
+                  "LicenseUrl": "http://licenseUrl.net",
+                  "Copyright": "Foo Bar Copyright",
+                  "CopyrightUrl": "http://copyrightUrl.net",
+                  "ShortDescription": "Foo bar is a foo bar.",
+                  "Description": "Foo bar is a placeholder.",
+                  "Tags": [
+                    "FooBar",
+                    "Foo",
+                    "Bar"
+                  ],
+                  "Moniker": "FooBarMoniker",
+                  "ReleaseNotes": "Default release notes",
+                  "ReleaseNotesUrl": "https://DefaultReleaseNotes.net",
+                  "Agreements": [{
+                    "AgreementLabel": "DefaultLabel",
+                    "Agreement": "DefaultText",
+                    "AgreementUrl": "https://DefaultAgreementUrl.net"
+                  }],
+                  "PurchaseUrl": "http://DefaultPurchaseUrl.net",
+                  "InstallationNotes": "Default Installation Notes",
+                  "Documentations": [{
+                    "DocumentLabel": "Default Document Label",
+                    "DocumentUrl": "http://DefaultDocumentUrl.net"
+                  }],
+                  "Icons": [{
+                    "IconUrl": "https://DefaultTestIcon",
+                    "IconFileType": "ico",
+                    "IconResolution": "custom",
+                    "IconTheme": "default",
+                    "IconSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8123"
+                  }]
+                },
+                "Channel": "",
+                "Locales": [
+                  {
+                    "PackageLocale": "fr-Fr",
+                    "Publisher": "Foo French",
+                    "PublisherUrl": "http://publisher-fr.net",
+                    "PublisherSupportUrl": "http://publisherSupport-fr.net",
+                    "PrivacyUrl": "http://packagePrivacyUrl-fr.net",
+                    "Author": "FooBar French",
+                    "PackageName": "Bar",
+                    "PackageUrl": "http://packageUrl-fr.net",
+                    "License": "Foo Bar License",
+                    "LicenseUrl": "http://licenseUrl-fr.net",
+                    "Copyright": "Foo Bar Copyright",
+                    "CopyrightUrl": "http://copyrightUrl-fr.net",
+                    "ShortDescription": "Foo bar is a foo bar French.",
+                    "Description": "Foo bar is a placeholder French.",
+                    "Tags": [
+                      "FooBarFr",
+                      "FooFr",
+                      "BarFr"
+                    ],
+                    "ReleaseNotes": "Release notes",
+                    "ReleaseNotesUrl": "https://ReleaseNotes.net",
+                    "Agreements": [{
+                      "AgreementLabel": "Label",
+                      "Agreement": "Text",
+                      "AgreementUrl": "https://AgreementUrl.net"
+                    }],
+                    "PurchaseUrl": "http://purchaseUrl.net",
+                    "InstallationNotes": "Installation Notes",
+                    "Documentations": [{
+                      "DocumentLabel": "Document Label",
+                      "DocumentUrl": "http://documentUrl.net"
+                    }],
+                    "Icons": [{
+                      "IconUrl": "https://testIcon",
+                      "IconFileType": "png",
+                      "IconResolution": "32x32",
+                      "IconTheme": "light",
+                      "IconSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321"
+                    }]
+                  }
+                ],)delimiter") _XPLATSTR(R"delimiter(
+                "Installers": [
+                  {
+                    "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
+                    "InstallerUrl": "http://foobar.zip",
+                    "Architecture": "x86",
+                    "InstallerLocale": "en-US",
+                    "Platform": [
+                      "Windows.Desktop"
+                    ],
+                    "MinimumOSVersion": "1078",
+                    "InstallerType": "zip",
+                    "Scope": "user",
+                    "InstallModes": [
+                      "interactive"
+                    ],
+                    "InstallerSwitches": {
+                      "Silent": "/s",
+                      "SilentWithProgress": "/s",
+                      "Interactive": "/i",
+                      "InstallLocation": "C:\\Users\\User1",
+                      "Log": "/l",
+                      "Upgrade": "/u",
+                      "Custom": "/custom",
+                      "Repair": "/repair"
+                    },
+                    "InstallerSuccessCodes": [
+                      0
+                    ],
+                    "UpgradeBehavior": "deny",
+                    "Commands": [
+                      "command1"
+                    ],
+                    "Protocols": [
+                       "protocol1"
+                    ],
+                    "FileExtensions": [
+                      ".file-extension"
+                    ],
+                    "Dependencies": {
+                      "WindowsFeatures": [
+                        "feature1"
+                      ],
+                      "WindowsLibraries": [
+                        "library1"
+                      ],
+                      "PackageDependencies": [
+                        {
+                          "PackageIdentifier": "Foo.Baz",
+                          "MinimumVersion": "2.0.0"
+                        }
+                      ],
+                      "ExternalDependencies": [
+                        "FooBarBaz"
+                      ]
+                    },
+                    "ProductCode": "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d",
+                    "ReleaseDate": "2021-01-01",
+                    "InstallerAbortsTerminal": true,
+                    "InstallLocationRequired": true,
+                    "RequireExplicitUpgrade": true,
+                    "UnsupportedOSArchitectures": [ "arm" ],
+                    "ElevationRequirement": "elevatesSelf",
+                    "AppsAndFeaturesEntries": [{
+                      "DisplayName": "DisplayName",
+                      "DisplayVersion": "DisplayVersion",
+                      "Publisher": "Publisher",
+                      "ProductCode": "ProductCode",
+                      "UpgradeCode": "UpgradeCode",
+                      "InstallerType": "exe"
+                    }],
+                    "Markets" : {
+                      "AllowedMarkets": [ "US" ]
+                    },
+                    "ExpectedReturnCodes": [{
+                      "InstallerReturnCode": 3,
+                      "ReturnResponse": "custom",
+                      "ReturnResponseUrl": "http://returnResponseUrl.net"
+                    }],
+                    "NestedInstallerType": "portable",
+                    "DisplayInstallWarnings": true,
+                    "UnsupportedArguments": [ "log" ],
+                    "NestedInstallerFiles": [{
+                      "RelativeFilePath": "test\\app.exe",
+                      "PortableCommandAlias": "test.exe"
+                    }],
+                    "InstallationMetadata": {
+                      "DefaultInstallLocation": "%TEMP%\\DefaultInstallLocation",
+                      "Files": [{
+                        "RelativeFilePath": "test\\app.exe",
+                        "FileSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
+                        "FileType": "launch",
+                        "InvocationParameter": "/parameter",
+                        "DisplayName": "test"
+                      }]
+                    },
+                    "DownloadCommandProhibited": true,
+                    "RepairBehavior": "uninstaller",
+                    "ArchiveBinariesDependOnPath": true,
+                    "Authentication": {
+                      "AuthenticationType": "microsoftEntraId",
+                      "MicrosoftEntraIdAuthenticationInfo" : {
+                        "Resource": "TestResource",
+                        "Scope" : "TestScope"
+                      }
+                    }
+                  }
+                ]
+              }
+            ]
+          },
+          "ContinuationToken": "abcd"
+        })delimiter");
+        }
+
+        void VerifyLocalizations_AllFields(const AppInstaller::Manifest::Manifest& manifest)
+        {
+            REQUIRE(manifest.DefaultLocalization.Locale == "en-US");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Publisher>() == "Foo");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherUrl>() == "http://publisher.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Author>() == "FooBar");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageName>() == "Bar");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageUrl>() == "http://packageUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::License>() == "Foo Bar License");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar.");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Description>() == "Foo bar is a placeholder.");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().size() == 3);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(0) == "FooBar");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(1) == "Foo");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(2) == "Bar");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotes>() == "Default release notes");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotesUrl>() == "https://DefaultReleaseNotes.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().size() == 1);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).Label == "DefaultLabel");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementText == "DefaultText");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://DefaultAgreementUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::PurchaseUrl>() == "http://DefaultPurchaseUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::InstallationNotes>() == "Default Installation Notes");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().size() == 1);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Default Document Label");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://DefaultDocumentUrl.net");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().size() == 1);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Url == "https://DefaultTestIcon");
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).FileType == IconFileTypeEnum::Ico);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Resolution == IconResolutionEnum::Custom);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Theme == IconThemeEnum::Default);
+            REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8123"));
+
+            REQUIRE(manifest.Localizations.size() == 1);
+            ManifestLocalization frenchLocalization = manifest.Localizations.at(0);
+            REQUIRE(frenchLocalization.Locale == "fr-Fr");
+            REQUIRE(frenchLocalization.Get<Localization::Publisher>() == "Foo French");
+            REQUIRE(frenchLocalization.Get<Localization::PublisherUrl>() == "http://publisher-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::Author>() == "FooBar French");
+            REQUIRE(frenchLocalization.Get<Localization::PackageName>() == "Bar");
+            REQUIRE(frenchLocalization.Get<Localization::PackageUrl>() == "http://packageUrl-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::License>() == "Foo Bar License");
+            REQUIRE(frenchLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
+            REQUIRE(frenchLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl-fr.net");
+            REQUIRE(frenchLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar French.");
+            REQUIRE(frenchLocalization.Get<Localization::Description>() == "Foo bar is a placeholder French.");
+            REQUIRE(frenchLocalization.Get<Localization::Tags>().size() == 3);
+            REQUIRE(frenchLocalization.Get<Localization::Tags>().at(0) == "FooBarFr");
+            REQUIRE(frenchLocalization.Get<Localization::Tags>().at(1) == "FooFr");
+            REQUIRE(frenchLocalization.Get<Localization::Tags>().at(2) == "BarFr");
+            REQUIRE(frenchLocalization.Get<Localization::ReleaseNotes>() == "Release notes");
+            REQUIRE(frenchLocalization.Get<Localization::ReleaseNotesUrl>() == "https://ReleaseNotes.net");
+            REQUIRE(frenchLocalization.Get<Localization::Agreements>().size() == 1);
+            REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).Label == "Label");
+            REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementText == "Text");
+            REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://AgreementUrl.net");
+            REQUIRE(frenchLocalization.Get<Localization::PurchaseUrl>() == "http://purchaseUrl.net");
+            REQUIRE(frenchLocalization.Get<Localization::InstallationNotes>() == "Installation Notes");
+            REQUIRE(frenchLocalization.Get<Localization::Documentations>().size() == 1);
+            REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Document Label");
+            REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://documentUrl.net");
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().size() == 1);
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Url == "https://testIcon");
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).FileType == IconFileTypeEnum::Png);
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Resolution == IconResolutionEnum::Square32);
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Theme == IconThemeEnum::Light);
+            REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321"));
+        }
+
+        void VerifyInstallers_AllFields(const AppInstaller::Manifest::Manifest& manifest)
+        {
+            REQUIRE(manifest.Installers.size() == 1);
+
+            ManifestInstaller actualInstaller = manifest.Installers.at(0);
+            REQUIRE(actualInstaller.Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
+            REQUIRE(actualInstaller.Url == "http://foobar.zip");
+            REQUIRE(actualInstaller.Arch == Architecture::X86);
+            REQUIRE(actualInstaller.Locale == "en-US");
+            REQUIRE(actualInstaller.Platform.size() == 1);
+            REQUIRE(actualInstaller.Platform[0] == PlatformEnum::Desktop);
+            REQUIRE(actualInstaller.MinOSVersion == "1078");
+            REQUIRE(actualInstaller.BaseInstallerType == InstallerTypeEnum::Zip);
+            REQUIRE(actualInstaller.Scope == ScopeEnum::User);
+            REQUIRE(actualInstaller.InstallModes.size() == 1);
+            REQUIRE(actualInstaller.InstallModes.at(0) == InstallModeEnum::Interactive);
+            REQUIRE(actualInstaller.Switches.size() == 8);
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Silent) == "/s");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::SilentWithProgress) == "/s");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Interactive) == "/i");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::InstallLocation) == "C:\\Users\\User1");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Log) == "/l");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Update) == "/u");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Custom) == "/custom");
+            REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Repair) == "/repair");
+            REQUIRE(actualInstaller.InstallerSuccessCodes.size() == 1);
+            REQUIRE(actualInstaller.InstallerSuccessCodes.at(0) == 0);
+            REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Deny);
+            REQUIRE(actualInstaller.Commands.at(0) == "command1");
+            REQUIRE(actualInstaller.Protocols.at(0) == "protocol1");
+            REQUIRE(actualInstaller.FileExtensions.at(0) == ".file-extension");
+            REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsFeature, "feature1"));
+            REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsLibrary, "library1"));
+            REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::Package, "Foo.Baz", "2.0.0"));
+            REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::External, "FooBarBaz"));
+            REQUIRE(actualInstaller.PackageFamilyName == "");
+            REQUIRE(actualInstaller.ProductCode == "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d");
+            REQUIRE(actualInstaller.ReleaseDate == "2021-01-01");
+            REQUIRE(actualInstaller.InstallerAbortsTerminal);
+            REQUIRE(actualInstaller.InstallLocationRequired);
+            REQUIRE(actualInstaller.RequireExplicitUpgrade);
+            REQUIRE(actualInstaller.ElevationRequirement == ElevationRequirementEnum::ElevatesSelf);
+            REQUIRE(actualInstaller.UnsupportedOSArchitectures.size() == 1);
+            REQUIRE(actualInstaller.UnsupportedOSArchitectures.at(0) == Architecture::Arm);
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.size() == 1);
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayName == "DisplayName");
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayVersion == "DisplayVersion");
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).Publisher == "Publisher");
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).ProductCode == "ProductCode");
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).UpgradeCode == "UpgradeCode");
+            REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).InstallerType == InstallerTypeEnum::Exe);
+            REQUIRE(actualInstaller.Markets.AllowedMarkets.size() == 1);
+            REQUIRE(actualInstaller.Markets.AllowedMarkets.at(0) == "US");
+            REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseEnum == ExpectedReturnCodeEnum::Custom);
+            REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseUrl == "http://returnResponseUrl.net");
+            REQUIRE(actualInstaller.NestedInstallerType == InstallerTypeEnum::Portable);
+            REQUIRE(actualInstaller.DisplayInstallWarnings);
+            REQUIRE(actualInstaller.UnsupportedArguments.size() == 1);
+            REQUIRE(actualInstaller.UnsupportedArguments.at(0) == UnsupportedArgumentEnum::Log);
+            REQUIRE(actualInstaller.NestedInstallerFiles.size() == 1);
+            REQUIRE(actualInstaller.NestedInstallerFiles.at(0).RelativeFilePath == "test\\app.exe");
+            REQUIRE(actualInstaller.NestedInstallerFiles.at(0).PortableCommandAlias == "test.exe");
+            REQUIRE(actualInstaller.InstallationMetadata.DefaultInstallLocation == "%TEMP%\\DefaultInstallLocation");
+            REQUIRE(actualInstaller.InstallationMetadata.Files.size() == 1);
+            REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).RelativeFilePath == "test\\app.exe");
+            REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileType == InstalledFileTypeEnum::Launch);
+            REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileSha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
+            REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).InvocationParameter == "/parameter");
+            REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).DisplayName == "test");
+            REQUIRE(actualInstaller.DownloadCommandProhibited);
+            REQUIRE(actualInstaller.RepairBehavior == RepairBehaviorEnum::Uninstaller);
+            REQUIRE(actualInstaller.ArchiveBinariesDependOnPath);
+            REQUIRE(actualInstaller.AuthInfo.Type == AppInstaller::Authentication::AuthenticationType::MicrosoftEntraId);
+            REQUIRE(actualInstaller.AuthInfo.MicrosoftEntraIdInfo.has_value());
+            REQUIRE(actualInstaller.AuthInfo.MicrosoftEntraIdInfo->Resource == "TestResource");
+            REQUIRE(actualInstaller.AuthInfo.MicrosoftEntraIdInfo->Scope == "TestScope");
+        }
+    };
+}
+
+TEST_CASE("GetManifests_GoodResponse_V1_10", "[RestSource][Interface_1_10]")
+{
+    GoodManifest_AllFields sampleManifest;
+    utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
+    HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
+    Interface v1_10{ TestRestUriString, std::move(helper), {} };
+    std::vector<Manifest> manifests = v1_10.GetManifests("Foo.Bar");
+    REQUIRE(manifests.size() == 1);
+
+    // Verify manifest is populated
+    Manifest& manifest = manifests[0];
+    REQUIRE(manifest.Id == "Foo.Bar");
+    REQUIRE(manifest.Version == "3.0.0abc");
+    REQUIRE(manifest.Moniker == "FooBarMoniker");
+    REQUIRE(manifest.Channel == "");
+    REQUIRE(manifest.ManifestVersion == AppInstaller::Manifest::ManifestVer{ "1.10.0" });
+    sampleManifest.VerifyLocalizations_AllFields(manifest);
+    sampleManifest.VerifyInstallers_AllFields(manifest);
+}

From 5d4883d5dbe478aa8f979ca5419c1b47898305f4 Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 16:03:54 -0800
Subject: [PATCH 3/7] utilinterop update

---
 .../Manifest/V1/InstallerAuthentication.cs    | 24 +++++++++++++++++++
 ...allerMicrosoftEntraIdAuthenticationInfo.cs | 24 +++++++++++++++++++
 src/WinGetUtilInterop/Manifest/V1/Manifest.cs |  7 +++++-
 .../Manifest/V1/ManifestInstaller.cs          |  7 +++++-
 4 files changed, 60 insertions(+), 2 deletions(-)
 create mode 100644 src/WinGetUtilInterop/Manifest/V1/InstallerAuthentication.cs
 create mode 100644 src/WinGetUtilInterop/Manifest/V1/InstallerMicrosoftEntraIdAuthenticationInfo.cs

diff --git a/src/WinGetUtilInterop/Manifest/V1/InstallerAuthentication.cs b/src/WinGetUtilInterop/Manifest/V1/InstallerAuthentication.cs
new file mode 100644
index 0000000000..163ac6d2dd
--- /dev/null
+++ b/src/WinGetUtilInterop/Manifest/V1/InstallerAuthentication.cs
@@ -0,0 +1,24 @@
+// -----------------------------------------------------------------------------
+// <copyright file="InstallerAuthentication.cs" company="Microsoft Corporation">
+//     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+// </copyright>
+// -----------------------------------------------------------------------------
+
+namespace Microsoft.WinGetUtil.Models.V1
+{
+    /// <summary>
+    /// Installer authentication info.
+    /// </summary>
+    public class InstallerAuthentication
+    {
+        /// <summary>
+        /// Gets or sets the authentication type.
+        /// </summary>
+        public string AuthenticationType { get; set; }
+
+        /// <summary>
+        /// Gets or sets the Microsoft Entra Id authentication info.
+        /// </summary>
+        public InstallerMicrosoftEntraIdAuthenticationInfo MicrosoftEntraIdAuthenticationInfo { get; set; }
+    }
+}
diff --git a/src/WinGetUtilInterop/Manifest/V1/InstallerMicrosoftEntraIdAuthenticationInfo.cs b/src/WinGetUtilInterop/Manifest/V1/InstallerMicrosoftEntraIdAuthenticationInfo.cs
new file mode 100644
index 0000000000..2c06220a02
--- /dev/null
+++ b/src/WinGetUtilInterop/Manifest/V1/InstallerMicrosoftEntraIdAuthenticationInfo.cs
@@ -0,0 +1,24 @@
+// -----------------------------------------------------------------------------
+// <copyright file="InstallerMicrosoftEntraIdAuthenticationInfo.cs" company="Microsoft Corporation">
+//     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+// </copyright>
+// -----------------------------------------------------------------------------
+
+namespace Microsoft.WinGetUtil.Models.V1
+{
+    /// <summary>
+    /// Microsoft Entra Id authentication info.
+    /// </summary>
+    public class InstallerMicrosoftEntraIdAuthenticationInfo
+    {
+        /// <summary>
+        /// Gets or sets the authentication resource.
+        /// </summary>
+        public string Resource { get; set; }
+
+        /// <summary>
+        /// Gets or sets the authentication scope.
+        /// </summary>
+        public string Scope { get; set; }
+    }
+}
diff --git a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
index 811081064c..8b80fa4940 100644
--- a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
+++ b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
@@ -333,7 +333,12 @@ public class Manifest
         /// <summary>
         /// Gets or sets the default repair behavior.
         /// </summary>
-        public string RepairBehavior { get; set; }
+        public string RepairBehavior { get; set; }
+
+        /// <summary>
+        /// Gets or sets the default installer authentication info.
+        /// </summary>
+        public InstallerAuthentication Authentication { get; set; }
 
         /// <summary>
         /// Gets or sets collection of ManifestInstaller. At least one is required.
diff --git a/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs b/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
index c6e326e3e3..172bb0de58 100644
--- a/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
+++ b/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
@@ -214,7 +214,12 @@ public class ManifestInstaller
         /// <summary>
         /// Gets or sets the repair behavior.
         /// </summary>
-        public string RepairBehavior { get; set; }
+        public string RepairBehavior { get; set; }
+
+        /// <summary>
+        /// Gets or sets the installer authentication info.
+        /// </summary>
+        public InstallerAuthentication Authentication { get; set; }
 
         /// <summary>
         /// Returns a List of strings containing the URIs contained within this installer.

From 181667b24539219d9ddd56140bd4c66eb7b7299e Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 16:17:57 -0800
Subject: [PATCH 4/7] utilinterop tests

---
 .../ManifestUnitTest/V1ManifestReadTest.cs    |  25 ++
 .../TestCollateral/V1_10ManifestMerged.yaml   | 263 ++++++++++++++++++
 .../WinGetUtilInterop.UnitTests.csproj        |   3 +
 3 files changed, 291 insertions(+)
 create mode 100644 src/WinGetUtilInterop.UnitTests/TestCollateral/V1_10ManifestMerged.yaml

diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
index 72f24a5272..0ce596eec0 100644
--- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
+++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
@@ -36,6 +36,7 @@ private enum TestManifestVersion
             V160,
             V170,
             V190,
+            V1100,
         }
 
         /// <summary>
@@ -69,6 +70,11 @@ public void ReadV1ManifestsAndVerifyContents()
                 Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V190ManifestMerged));
 
             this.ValidateManifestFields(v190manifest, TestManifestVersion.V190);
+
+            Manifest v1100manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1100ManifestMerged));
+
+            this.ValidateManifestFields(v1100manifest, TestManifestVersion.V1100);
         }
 
         /// <summary>
@@ -279,6 +285,13 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.True(manifest.ArchiveBinariesDependOnPath);
             }
 
+            if (manifestVersion >= TestManifestVersion.V1100)
+            {
+                Assert.Equal("microsoftEntraId", manifest.Authentication.AuthenticationType);
+                Assert.Equal("DefaultResource", manifest.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
+                Assert.Equal("DefaultScope", manifest.Authentication.MicrosoftEntraIdAuthenticationInfo.Scope);
+            }
+
             // Individual installers
             Assert.Equal(2, manifest.Installers.Count);
             ManifestInstaller installer1 = manifest.Installers[0];
@@ -391,6 +404,13 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("fakeIdentifier", installer2.ProductId);
             }
 
+            if (manifestVersion >= TestManifestVersion.V1100)
+            {
+                Assert.Equal("microsoftEntraId", installer1.Authentication.AuthenticationType);
+                Assert.Equal("DefaultResource", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
+                Assert.Equal("DefaultScope", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Scope);
+            }
+
             // Additional Localizations
             Assert.Single(manifest.Localization);
             ManifestLocalization localization1 = manifest.Localization[0];
@@ -474,6 +494,11 @@ internal class ManifestStrings
             /// </summary>
             public const string V190ManifestMerged = "V1_9ManifestMerged.yaml";
 
+            /// <summary>
+            /// Merged v1.10 manifest.
+            /// </summary>
+            public const string V1100ManifestMerged = "V1_10ManifestMerged.yaml";
+
             /// <summary>
             /// Merged v1 manifest without localization.
             /// </summary>
diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_10ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_10ManifestMerged.yaml
new file mode 100644
index 0000000000..7c06202ddf
--- /dev/null
+++ b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_10ManifestMerged.yaml
@@ -0,0 +1,263 @@
+PackageIdentifier: microsoft.msixsdk
+PackageVersion: 1.7.32
+PackageLocale: en-US
+Publisher: Microsoft
+PublisherUrl: https://www.microsoft.com
+PublisherSupportUrl: https://www.microsoft.com/support
+PrivacyUrl: https://www.microsoft.com/privacy
+Author: Microsoft
+PackageName: MSIX SDK
+PackageUrl: https://www.microsoft.com/msixsdk/home
+License: MIT License
+LicenseUrl: https://www.microsoft.com/msixsdk/license
+Copyright: Copyright Microsoft Corporation
+CopyrightUrl: https://www.microsoft.com/msixsdk/copyright
+ShortDescription: This is MSIX SDK
+Description: The MSIX SDK project is an effort to enable developers
+Moniker: msixsdk
+Tags:
+  - "appxsdk"
+  - "msixsdk"
+ReleaseNotes: Default release notes
+ReleaseNotesUrl: https://DefaultReleaseNotes.net
+PurchaseUrl: https://DefaultPurchaseUrl.com
+InstallationNotes: Default installation notes
+Documentations:
+  - DocumentLabel: Default document label
+    DocumentUrl: https://DefaultDocumentUrl.com
+Icons:
+  - IconUrl: https://testIcon
+    IconFileType: ico
+    IconResolution: custom
+    IconTheme: default
+    IconSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8123
+Agreements:
+  - AgreementLabel: DefaultLabel
+    Agreement: DefaultText
+    AgreementUrl: https://DefaultAgreementUrl.net
+InstallerLocale: en-US
+Platform:
+  - Windows.Desktop
+  - Windows.Universal
+MinimumOSVersion: 10.0.0.0
+InstallerType: zip
+Scope: machine
+InstallModes:
+  - interactive
+  - silent
+  - silentWithProgress
+InstallerSwitches:
+  Custom: /custom
+  SilentWithProgress: /silentwithprogress
+  Silent: /silence
+  Interactive: /interactive
+  Log: /log=<LOGPATH>
+  InstallLocation: /dir=<INSTALLPATH>
+  Upgrade: /upgrade
+  Repair: /repair
+InstallerSuccessCodes:
+  - 1
+  - 0x80070005
+UpgradeBehavior: uninstallPrevious
+Commands:
+  - makemsix
+  - makeappx
+Protocols:
+  - protocol1
+  - protocol2
+FileExtensions:
+  - appx
+  - msix
+  - appxbundle
+  - msixbundle
+Dependencies:
+  WindowsFeatures:
+    - IIS
+  WindowsLibraries:
+    - VC Runtime
+  PackageDependencies:
+    - PackageIdentifier: Microsoft.MsixSdkDep
+      MinimumVersion: 1.0.0
+  ExternalDependencies:
+    - Outside dependencies
+Capabilities:
+  - internetClient
+RestrictedCapabilities:
+  - runFullTrust
+PackageFamilyName: Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
+ProductCode: "{Foo}"
+ReleaseDate: 2021-01-01
+InstallerAbortsTerminal: true
+InstallLocationRequired: true
+RequireExplicitUpgrade: true
+DisplayInstallWarnings: true
+ElevationRequirement: elevatesSelf
+UnsupportedOSArchitectures:
+  - arm
+AppsAndFeaturesEntries:
+  - DisplayName: DisplayName
+    DisplayVersion: DisplayVersion
+    Publisher: Publisher
+    ProductCode: ProductCode
+    UpgradeCode: UpgradeCode
+    InstallerType: exe
+Markets:
+  AllowedMarkets:
+    - US
+ExpectedReturnCodes:
+    - InstallerReturnCode: 2
+      ReturnResponse: contactSupport
+      ReturnResponseUrl: https://defaultReturnResponseUrl.com
+    - InstallerReturnCode: 3
+      ReturnResponse: custom
+UnsupportedArguments:
+  - log
+NestedInstallerType: msi
+NestedInstallerFiles:
+  - RelativeFilePath: RelativeFilePath
+    PortableCommandAlias: PortableCommandAlias
+InstallationMetadata:
+  DefaultInstallLocation: "%ProgramFiles%\\TestApp"
+  Files:
+    - RelativeFilePath: "main.exe"
+      FileSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82
+      FileType: launch
+      InvocationParameter: "/arg"
+      DisplayName: "DisplayName"
+DownloadCommandProhibited: true
+ArchiveBinariesDependOnPath: true
+RepairBehavior: uninstaller
+Authentication:
+  AuthenticationType: microsoftEntraId
+  MicrosoftEntraIdAuthenticationInfo:
+    Resource: DefaultResource
+    Scope: DefaultScope
+Localization:
+- Agreements:
+  - Agreement: Text
+    AgreementLabel: Label
+    AgreementUrl: https://AgreementUrl.net
+  Author: Microsoft UK
+  Copyright: Copyright Microsoft Corporation UK
+  CopyrightUrl: https://www.microsoft.com/msixsdk/copyright/UK
+  Description: The MSIX SDK project is an effort to enable developers UK
+  License: MIT License UK
+  LicenseUrl: https://www.microsoft.com/msixsdk/license/UK
+  PackageLocale: en-GB
+  PackageName: MSIX SDK UK
+  PackageUrl: https://www.microsoft.com/msixsdk/home/UK
+  PrivacyUrl: https://www.microsoft.com/privacy/UK
+  Publisher: Microsoft UK
+  PublisherSupportUrl: https://www.microsoft.com/support/UK
+  PublisherUrl: https://www.microsoft.com/UK
+  ReleaseNotes: Release notes
+  ReleaseNotesUrl: https://ReleaseNotes.net
+  ShortDescription: This is MSIX SDK UK
+  Tags:
+  - appxsdkUK
+  - msixsdkUK
+  PurchaseUrl: https://PurchaseUrl.com
+  InstallationNotes: Installation notes
+  Documentations:
+  - DocumentLabel: Document label
+    DocumentUrl: https://DocumentUrl.com
+  Icons:
+  - IconUrl: https://testIcon2
+    IconFileType: png
+    IconResolution: 32x32
+    IconTheme: dark
+    IconSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321
+Installers:
+  - Architecture: x86
+    InstallerLocale: en-GB
+    Platform:
+      - Windows.Desktop
+    MinimumOSVersion: 10.0.1.0
+    InstallerType: msix
+    InstallerUrl: https://www.microsoft.com/msixsdk/msixsdkx86.msix
+    InstallerSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82
+    SignatureSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82
+    Scope: user
+    InstallModes:
+      - interactive
+    InstallerSwitches:
+      Custom: /c
+      SilentWithProgress: /sp
+      Silent: /s
+      Interactive: /i
+      Log: /l=<LOGPATH>
+      InstallLocation: /d=<INSTALLPATH>
+      Upgrade: /u
+      Repair: /r
+    UpgradeBehavior: install
+    Commands:
+      - makemsixPreview
+      - makeappxPreview
+    Protocols:
+      - protocol1preview
+      - protocol2preview
+    FileExtensions:
+      - appxbundle
+      - msixbundle
+      - appx
+      - msix
+    Dependencies:
+      WindowsFeatures:
+        - PreviewIIS
+      WindowsLibraries:
+        - Preview VC Runtime
+      PackageDependencies:
+        - PackageIdentifier: Microsoft.MsixSdkDepPreview
+          MinimumVersion: 1.0.0
+      ExternalDependencies:
+        - Preview Outside dependencies
+    PackageFamilyName: Microsoft.DesktopAppInstallerPreview_8wekyb3d8bbwe
+    Capabilities:
+      - internetClientPreview
+    RestrictedCapabilities:
+      - runFullTrustPreview
+    ReleaseDate: 2021-02-02
+    InstallerAbortsTerminal: false
+    InstallLocationRequired: false
+    NestedInstallerFiles:
+      - RelativeFilePath: RelativeFilePath2
+        PortableCommandAlias: PortableCommandAlias2
+    RequireExplicitUpgrade: false
+    DisplayInstallWarnings: true
+    ElevationRequirement: elevationRequired
+    NestedInstallerType: msi
+    UnsupportedArguments:
+      - location
+    UnsupportedOSArchitectures:
+      - arm64
+    Markets:
+      ExcludedMarkets:
+        - "US"
+    ExpectedReturnCodes:
+      - InstallerReturnCode: 2
+        ReturnResponse: contactSupport
+        ReturnResponseUrl: https://returnResponseUrl.com
+    DownloadCommandProhibited: true
+    ArchiveBinariesDependOnPath: false
+    RepairBehavior: modify
+    InstallationMetadata:
+      DefaultInstallLocation: "%ProgramFiles%\\TestApp"
+      Files:
+        - RelativeFilePath: "main2.exe"
+          FileSha256: 79D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82
+          FileType: launch2
+          InvocationParameter: "/arg2"
+          DisplayName: "DisplayName2"
+    Authentication:
+      AuthenticationType: microsoftEntraId
+      MicrosoftEntraIdAuthenticationInfo:
+        Resource: Resource
+        Scope: Scope
+  - Architecture: x64
+    InstallerSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82
+    InstallerUrl: https://www.microsoft.com/msixsdk/msixsdkx64.exe
+    InstallerType: exe
+    ProductCode: '{Bar}'
+    MSStoreProductIdentifier: fakeIdentifier
+ManifestType: merged
+ManifestVersion: 1.7.0
diff --git a/src/WinGetUtilInterop.UnitTests/WinGetUtilInterop.UnitTests.csproj b/src/WinGetUtilInterop.UnitTests/WinGetUtilInterop.UnitTests.csproj
index 5b8e0d0784..595b6231c5 100644
--- a/src/WinGetUtilInterop.UnitTests/WinGetUtilInterop.UnitTests.csproj
+++ b/src/WinGetUtilInterop.UnitTests/WinGetUtilInterop.UnitTests.csproj
@@ -99,6 +99,9 @@
     <None Update="TestCollateral\V1_9ManifestMerged.yaml">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="TestCollateral\V1_10ManifestMerged.yaml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
     <None Update="xunit.runner.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>

From 56dd3c1485c4b97aa8b15119edf13d6009c59834 Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 16:19:50 -0800
Subject: [PATCH 5/7] Fix tests

---
 .../ManifestUnitTest/V1ManifestReadTest.cs                    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
index 0ce596eec0..54c039d4cb 100644
--- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
+++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
@@ -407,8 +407,8 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             if (manifestVersion >= TestManifestVersion.V1100)
             {
                 Assert.Equal("microsoftEntraId", installer1.Authentication.AuthenticationType);
-                Assert.Equal("DefaultResource", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
-                Assert.Equal("DefaultScope", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Scope);
+                Assert.Equal("Resource", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
+                Assert.Equal("Scope", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Scope);
             }
 
             // Additional Localizations

From 684fa35d88cc1365da462c760e7a87354e7afe09 Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 16:30:47 -0800
Subject: [PATCH 6/7] Enum name change

---
 .../ManifestUnitTest/V1ManifestReadTest.cs    | 88 +++++++++----------
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
index 54c039d4cb..986c03fe4a 100644
--- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
+++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
@@ -31,12 +31,12 @@ public V1ManifestReadTest(ITestOutputHelper log)
 
         private enum TestManifestVersion
         {
-            V100,
-            V110,
-            V160,
-            V170,
-            V190,
-            V1100,
+            V1_0_0,
+            V1_1_0,
+            V1_6_0,
+            V1_7_0,
+            V1_9_0,
+            V1_10_0,
         }
 
         /// <summary>
@@ -46,35 +46,35 @@ private enum TestManifestVersion
         [DisplayTestMethodName]
         public void ReadV1ManifestsAndVerifyContents()
         {
-            Manifest v100manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V100ManifestMerged));
+            Manifest v1_0_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_0_0ManifestMerged));
 
-            this.ValidateManifestFields(v100manifest, TestManifestVersion.V100);
+            this.ValidateManifestFields(v1_0_0manifest, TestManifestVersion.V1_0_0);
 
-            Manifest v110manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V110ManifestMerged));
+            Manifest v1_1_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_1_0ManifestMerged));
 
-            this.ValidateManifestFields(v110manifest, TestManifestVersion.V110);
+            this.ValidateManifestFields(v1_1_0manifest, TestManifestVersion.V1_1_0);
 
-            Manifest v160manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V160ManifestMerged));
+            Manifest v1_6_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_6_0ManifestMerged));
 
-            this.ValidateManifestFields(v160manifest, TestManifestVersion.V160);
+            this.ValidateManifestFields(v1_6_0manifest, TestManifestVersion.V1_6_0);
 
-            Manifest v170manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V170ManifestMerged));
+            Manifest v1_7_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_7_0ManifestMerged));
 
-            this.ValidateManifestFields(v170manifest, TestManifestVersion.V170);
+            this.ValidateManifestFields(v1_7_0manifest, TestManifestVersion.V1_7_0);
 
-            Manifest v190manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V190ManifestMerged));
+            Manifest v1_9_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_9_0ManifestMerged));
 
-            this.ValidateManifestFields(v190manifest, TestManifestVersion.V190);
+            this.ValidateManifestFields(v1_9_0manifest, TestManifestVersion.V1_9_0);
 
-            Manifest v1100manifest = Manifest.CreateManifestFromPath(
-                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1100ManifestMerged));
+            Manifest v1_10_0manifest = Manifest.CreateManifestFromPath(
+                Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestCollateral", ManifestStrings.V1_10_0ManifestMerged));
 
-            this.ValidateManifestFields(v1100manifest, TestManifestVersion.V1100);
+            this.ValidateManifestFields(v1_10_0manifest, TestManifestVersion.V1_10_0);
         }
 
         /// <summary>
@@ -134,7 +134,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             Assert.Equal("appxsdk", manifest.Tags[0]);
             Assert.Equal("msixsdk", manifest.Tags[1]);
 
-            if (manifestVersion >= TestManifestVersion.V110)
+            if (manifestVersion >= TestManifestVersion.V1_1_0)
             {
                 Assert.Equal("Default release notes", manifest.ReleaseNotes);
                 Assert.Equal("https://DefaultReleaseNotes.net", manifest.ReleaseNotesUrl);
@@ -144,7 +144,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("https://DefaultAgreementUrl.net", manifest.Agreements[0].AgreementUrl);
             }
 
-            if (manifestVersion >= TestManifestVersion.V160)
+            if (manifestVersion >= TestManifestVersion.V1_6_0)
             {
                 Assert.Equal("Default installation notes", manifest.InstallationNotes);
                 Assert.Equal("https://DefaultPurchaseUrl.com", manifest.PurchaseUrl);
@@ -221,7 +221,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             Assert.Equal("Microsoft.DesktopAppInstaller_8wekyb3d8bbwe", manifest.PackageFamilyName);
             Assert.Equal("{Foo}", manifest.ProductCode);
 
-            if (manifestVersion >= TestManifestVersion.V110)
+            if (manifestVersion >= TestManifestVersion.V1_1_0)
             {
                 Assert.Equal("2021-01-01", manifest.ReleaseDate);
                 Assert.True(manifest.InstallerAbortsTerminal);
@@ -244,7 +244,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("contactSupport", manifest.ExpectedReturnCodes[0].ReturnResponse);
             }
 
-            if (manifestVersion >= TestManifestVersion.V160)
+            if (manifestVersion >= TestManifestVersion.V1_6_0)
             {
                 Assert.Equal("msi", manifest.NestedInstallerType);
                 Assert.Single(manifest.NestedInstallerFiles);
@@ -274,18 +274,18 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("https://defaultReturnResponseUrl.com", manifest.ExpectedReturnCodes[0].ReturnResponseUrl);
             }
 
-            if (manifestVersion >= TestManifestVersion.V170)
+            if (manifestVersion >= TestManifestVersion.V1_7_0)
             {
                 Assert.Equal("/repair", defaultSwitches.Repair);
                 Assert.Equal("uninstaller", manifest.RepairBehavior);
             }
 
-            if (manifestVersion >= TestManifestVersion.V190)
+            if (manifestVersion >= TestManifestVersion.V1_9_0)
             {
                 Assert.True(manifest.ArchiveBinariesDependOnPath);
             }
 
-            if (manifestVersion >= TestManifestVersion.V1100)
+            if (manifestVersion >= TestManifestVersion.V1_10_0)
             {
                 Assert.Equal("microsoftEntraId", manifest.Authentication.AuthenticationType);
                 Assert.Equal("DefaultResource", manifest.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
@@ -345,7 +345,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             Assert.Equal("runFullTrustPreview", installer1.RestrictedCapabilities[0]);
             Assert.Equal("Microsoft.DesktopAppInstallerPreview_8wekyb3d8bbwe", installer1.PackageFamilyName);
 
-            if (manifestVersion >= TestManifestVersion.V110)
+            if (manifestVersion >= TestManifestVersion.V1_1_0)
             {
                 Assert.Equal("2021-02-02", installer1.ReleaseDate);
                 Assert.True(!installer1.InstallerAbortsTerminal);
@@ -368,7 +368,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             Assert.Equal("69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82", installer2.Sha256);
             Assert.Equal("{Bar}", installer2.ProductCode);
 
-            if (manifestVersion >= TestManifestVersion.V160)
+            if (manifestVersion >= TestManifestVersion.V1_6_0)
             {
                 Assert.Single(installer1.InstallationMetadata.Files);
                 ManifestInstallerFile installerFile2 = installer1.InstallationMetadata.Files[0];
@@ -392,19 +392,19 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("https://returnResponseUrl.com", installer1.ExpectedReturnCodes[0].ReturnResponseUrl);
             }
 
-            if (manifestVersion >= TestManifestVersion.V170)
+            if (manifestVersion >= TestManifestVersion.V1_7_0)
             {
                 Assert.Equal("/r", installer1Switches.Repair);
                 Assert.Equal("modify", installer1.RepairBehavior);
             }
 
-            if (manifestVersion >= TestManifestVersion.V190)
+            if (manifestVersion >= TestManifestVersion.V1_9_0)
             {
                 Assert.False(installer1.ArchiveBinariesDependOnPath);
                 Assert.Equal("fakeIdentifier", installer2.ProductId);
             }
 
-            if (manifestVersion >= TestManifestVersion.V1100)
+            if (manifestVersion >= TestManifestVersion.V1_10_0)
             {
                 Assert.Equal("microsoftEntraId", installer1.Authentication.AuthenticationType);
                 Assert.Equal("Resource", installer1.Authentication.MicrosoftEntraIdAuthenticationInfo.Resource);
@@ -432,7 +432,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
             Assert.Equal("appxsdkUK", localization1.Tags[0]);
             Assert.Equal("msixsdkUK", localization1.Tags[1]);
 
-            if (manifestVersion >= TestManifestVersion.V110)
+            if (manifestVersion >= TestManifestVersion.V1_1_0)
             {
                 Assert.Equal("Release notes", localization1.ReleaseNotes);
                 Assert.Equal("https://ReleaseNotes.net", localization1.ReleaseNotesUrl);
@@ -442,7 +442,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
                 Assert.Equal("https://AgreementUrl.net", localization1.Agreements[0].AgreementUrl);
             }
 
-            if (manifestVersion >= TestManifestVersion.V160)
+            if (manifestVersion >= TestManifestVersion.V1_6_0)
             {
                 Assert.Equal("Installation notes", localization1.InstallationNotes);
                 Assert.Equal("https://PurchaseUrl.com", localization1.PurchaseUrl);
@@ -472,32 +472,32 @@ internal class ManifestStrings
             /// <summary>
             /// Merged v1 manifest.
             /// </summary>
-            public const string V100ManifestMerged = "V1ManifestMerged.yaml";
+            public const string V1_0_0ManifestMerged = "V1ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1.1 manifest.
             /// </summary>
-            public const string V110ManifestMerged = "V1_1ManifestMerged.yaml";
+            public const string V1_1_0ManifestMerged = "V1_1ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1.6 manifest.
             /// </summary>
-            public const string V160ManifestMerged = "V1_6ManifestMerged.yaml";
+            public const string V1_6_0ManifestMerged = "V1_6ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1.7 manifest.
             /// </summary>
-            public const string V170ManifestMerged = "V1_7ManifestMerged.yaml";
+            public const string V1_7_0ManifestMerged = "V1_7ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1.9 manifest.
             /// </summary>
-            public const string V190ManifestMerged = "V1_9ManifestMerged.yaml";
+            public const string V1_9_0ManifestMerged = "V1_9ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1.10 manifest.
             /// </summary>
-            public const string V1100ManifestMerged = "V1_10ManifestMerged.yaml";
+            public const string V1_10_0ManifestMerged = "V1_10ManifestMerged.yaml";
 
             /// <summary>
             /// Merged v1 manifest without localization.

From 9ad58c46f35c163789d3222e9155cb0ccfb680f1 Mon Sep 17 00:00:00 2001
From: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 11 Feb 2025 19:25:21 -0800
Subject: [PATCH 7/7] Fix build warnings

---
 .../ManifestUnitTest/V1ManifestReadTest.cs                   | 2 ++
 src/WinGetUtilInterop/Api/WinGetManifest.cs                  | 3 +--
 src/WinGetUtilInterop/Manifest/V1/Manifest.cs                | 1 -
 src/WinGetUtilInterop/WinGetUtilInterop.csproj               | 5 +++--
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
index 986c03fe4a..81905518bf 100644
--- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
+++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
@@ -469,6 +469,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
         /// </summary>
         internal class ManifestStrings
         {
+#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
             /// <summary>
             /// Merged v1 manifest.
             /// </summary>
@@ -498,6 +499,7 @@ internal class ManifestStrings
             /// Merged v1.10 manifest.
             /// </summary>
             public const string V1_10_0ManifestMerged = "V1_10ManifestMerged.yaml";
+#pragma warning restore SA1310 // FieldNamesMustNotContainUnderscore
 
             /// <summary>
             /// Merged v1 manifest without localization.
diff --git a/src/WinGetUtilInterop/Api/WinGetManifest.cs b/src/WinGetUtilInterop/Api/WinGetManifest.cs
index 156959eeb8..9d20e67f7a 100644
--- a/src/WinGetUtilInterop/Api/WinGetManifest.cs
+++ b/src/WinGetUtilInterop/Api/WinGetManifest.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
 // <copyright file="WinGetManifest.cs" company="Microsoft Corporation">
 //     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
 // </copyright>
@@ -25,7 +25,6 @@ public sealed class WinGetManifest : IWinGetManifest
         /// Initializes a new instance of the <see cref="WinGetManifest"/> class.
         /// </summary>
         /// <param name="manifestHandle">Handle of the manifest.</param>
-        /// <param name="loggingContext">Logging Context.</param>
         internal WinGetManifest(IntPtr manifestHandle)
         {
             this.manifestHandle = manifestHandle;
diff --git a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
index 8b80fa4940..9df3343f84 100644
--- a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
+++ b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
@@ -228,7 +228,6 @@ public class Manifest
         /// </summary>
         public string ProductCode { get; set; }
 
-        /// <summary>
         /// <summary>
         /// Gets or sets the default list of capabilities. For msix only.
         /// </summary>
diff --git a/src/WinGetUtilInterop/WinGetUtilInterop.csproj b/src/WinGetUtilInterop/WinGetUtilInterop.csproj
index 6b66270457..54f0ba7547 100644
--- a/src/WinGetUtilInterop/WinGetUtilInterop.csproj
+++ b/src/WinGetUtilInterop/WinGetUtilInterop.csproj
@@ -1,8 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>netstandard2.1</TargetFramework>
-    <RootNamespace>Microsoft.WinGetUtil</RootNamespace>
+    <RootNamespace>Microsoft.WinGetUtil</RootNamespace>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>
 
   <ItemGroup>