From 352a9b0cc4be3661c32b80064161e767675758e7 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Sep 2026 22:27:40 -0400 Subject: [PATCH] fix(driver): pin polar api version --- docs/windows-driver.md | 6 ++++++ .../windows/broker/libvirtualhid_broker.cpp | 7 +++++-- .../windows_broker_service_test_hooks.hpp | 1 + .../windows_broker_service_test_hooks.cpp | 17 ++++++++++++++--- tests/unit/test_windows_broker_service.cpp | 1 + 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/windows-driver.md b/docs/windows-driver.md index 54a45a9..73afc0b 100644 --- a/docs/windows-driver.md +++ b/docs/windows-driver.md @@ -352,6 +352,12 @@ portal URL changes, then rebuild the Windows package. No Polar access token or webhook secret is compiled into the client: activation, validation, and deactivation use Polar's [public customer license-key API](https://polar.sh/docs/features/benefits/license-keys). +Those requests pin Polar's date-based API contract to `2026-04` with the +`Polar-Version` header. Before Polar removes that version, update +`polar_request_headers` in +`src/platform/windows/broker/libvirtualhid_broker.cpp`, review Polar's +[API versioning guidance](https://polar.sh/docs/api-reference/versioning), and +validate the license response contract before rebuilding the Windows package. The production configuration accepts organization `3db9f05a-44d7-42f1-ba7c-a0f198235fb7` with yearly license-key benefit diff --git a/src/platform/windows/broker/libvirtualhid_broker.cpp b/src/platform/windows/broker/libvirtualhid_broker.cpp index d256c72..916724a 100644 --- a/src/platform/windows/broker/libvirtualhid_broker.cpp +++ b/src/platform/windows/broker/libvirtualhid_broker.cpp @@ -80,6 +80,10 @@ namespace lvh::detail::windows_broker_service { constexpr int polar_connect_timeout = 5000; constexpr int polar_send_timeout = 5000; constexpr int polar_receive_timeout = 10000; + constexpr auto polar_request_headers = + L"Accept: application/json\r\n" + L"Content-Type: application/json\r\n" + L"Polar-Version: 2026-04\r\n"; constexpr auto license_validation_interval = std::chrono::days {1}; constexpr auto license_validation_retry_interval = std::chrono::seconds {60}; constexpr auto license_outage_device_retention = std::chrono::hours {1}; @@ -944,8 +948,7 @@ namespace lvh::detail::windows_broker_service { return result; } - auto body = request_body.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); - if (constexpr auto headers = L"Accept: application/json\r\nContent-Type: application/json\r\n"; ::WinHttpSendRequest(request.get(), headers, static_cast(-1), body.data(), static_cast(body.size()), static_cast(body.size()), 0) == FALSE) { + if (auto body = request_body.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); ::WinHttpSendRequest(request.get(), polar_request_headers, static_cast(-1), body.data(), static_cast(body.size()), static_cast(body.size()), 0) == FALSE) { result.error = "WinHttpSendRequest failed: " + windows_error_message(::GetLastError()); return result; } diff --git a/tests/fixtures/include/fixtures/windows_broker_service_test_hooks.hpp b/tests/fixtures/include/fixtures/windows_broker_service_test_hooks.hpp index 816c487..e75c922 100644 --- a/tests/fixtures/include/fixtures/windows_broker_service_test_hooks.hpp +++ b/tests/fixtures/include/fixtures/windows_broker_service_test_hooks.hpp @@ -48,6 +48,7 @@ namespace lvh::detail::test { int connect_timeout = 0; int send_timeout = 0; int receive_timeout = 0; + std::wstring request_headers; std::string body; std::string error; }; diff --git a/tests/fixtures/windows_broker_service_test_hooks.cpp b/tests/fixtures/windows_broker_service_test_hooks.cpp index 4217b27..9d9947f 100644 --- a/tests/fixtures/windows_broker_service_test_hooks.cpp +++ b/tests/fixtures/windows_broker_service_test_hooks.cpp @@ -48,6 +48,7 @@ namespace { int connect_timeout = 0; int send_timeout = 0; int receive_timeout = 0; + std::wstring request_headers; }; BrokerServiceTestState &broker_service_test_state() { @@ -285,14 +286,22 @@ namespace { BOOL WINAPI broker_test_win_http_send_request( HINTERNET, - LPCWSTR, - DWORD, + LPCWSTR headers, + DWORD headers_length, std::byte *, DWORD, DWORD, DWORD_PTR ) { - if (broker_service_test_state().polar_scenario == BrokerPolarScenario::send_failure) { + auto &state = broker_service_test_state(); + if (headers == nullptr) { + state.request_headers.clear(); + } else if (headers_length == static_cast(-1)) { + state.request_headers = headers; + } else { + state.request_headers.assign(headers, headers_length); + } + if (state.polar_scenario == BrokerPolarScenario::send_failure) { ::SetLastError(ERROR_WINHTTP_CONNECTION_ERROR); return FALSE; } @@ -466,6 +475,7 @@ namespace lvh::detail::test { state.connect_timeout = 0; state.send_timeout = 0; state.receive_timeout = 0; + state.request_headers.clear(); const auto result = lvh::detail::windows_broker_service::post_polar_license_request( L"/test", @@ -480,6 +490,7 @@ namespace lvh::detail::test { .connect_timeout = state.connect_timeout, .send_timeout = state.send_timeout, .receive_timeout = state.receive_timeout, + .request_headers = state.request_headers, .body = result.body, .error = result.error, }; diff --git a/tests/unit/test_windows_broker_service.cpp b/tests/unit/test_windows_broker_service.cpp index 48d6e05..e2b86f7 100644 --- a/tests/unit/test_windows_broker_service.cpp +++ b/tests/unit/test_windows_broker_service.cpp @@ -395,6 +395,7 @@ TEST(WindowsBrokerImplementationTest, ReportsDpapiAndPolarFailures) { EXPECT_EQ(succeeded.connect_timeout, 5000); EXPECT_EQ(succeeded.send_timeout, 5000); EXPECT_EQ(succeeded.receive_timeout, 10000); + EXPECT_NE(succeeded.request_headers.find(L"Polar-Version: 2026-04\r\n"), std::wstring::npos); } TEST(WindowsBrokerImplementationTest, BoundsOfflineSubscriptionValidation) {