/* * Copyright 2026 Kingsrook, LLC * SPDX-License-Identifier: Apache-2.0 */ using System.Net; using System.Text.Json; using Qqq.PrintAgent.Core.Authentication; namespace Printing.NativeAuth; /// Exercises the real native probe gate against bounded, credential-free HTTP responses. internal static class NativeAuthDiscoveryChecks { /// Accepts compatible printing releases while preserving the exact upstream grant requirement. internal static async Task RunAsync() { (string PrintingVersion, string ApiVersion, bool NativeGrant, bool Accepted)[] cases = [ ("2.0.0", "1.9.0", true, true), ("2.1.0", "1.9.0", true, true), ("2.9.17", "1.9.0", true, true), ("1.9.0", "1.9.0", true, false), ("3.0.0", "1.9.0", true, false), ("2.1", "1.9.0", true, false), ("2.01.0", "1.9.0", true, false), ("2.1.0-rc.1", "1.9.0", true, false), ("not-a-version", "1.9.0", true, false), ("2.1.0", "1.8.0", true, false), ("2.1.0", "1.10.0", true, false), ("2.1.0", "1.9.0", false, false), ]; foreach((string printingVersion, string apiVersion, bool nativeGrant, bool expected) in cases) { using var handler = new DiscoveryHandler(printingVersion, apiVersion, nativeGrant); using var client = new QqqSessionClient(new Uri("https://printing.example.invalid"), handler); bool accepted = false; try { await NativeAuthDiscovery.DiscoverAsync(client, CancellationToken.None); accepted = true; } catch(QqqSessionException error) when(error.Failure == QqqSessionException.FailureKind.ConfigurationRequired) { } catch(InvalidDataException) { } catch(InvalidOperationException) { } if(accepted != expected || handler.Requests != 1) { throw new InvalidDataException($"Native discovery compatibility case {printingVersion}/{apiVersion}/grant={nativeGrant} failed."); } } Console.WriteLine($"Native discovery compatibility checks passed: {cases.Length}."); } /// Supplies discovery only and fails if the probe attempts authenticated traffic. private sealed class DiscoveryHandler(string printingVersion, string apiVersion, bool nativeGrant) : HttpMessageHandler { /// Ensures rejected metadata still traversed the public HTTP discovery boundary. internal int Requests { get; private set; } /// Refuses any credential or request outside the public discovery boundary. protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if(request.Method != HttpMethod.Get || request.RequestUri?.AbsoluteUri != "https://printing.example.invalid/qqq/v1/version" || request.Headers.Contains("Cookie") || request.Headers.Contains("Authorization") || request.Headers.Contains("X-QQQ-Device-Id") || request.Headers.Contains("X-QQQ-Device-Token")) { throw new InvalidOperationException("Native discovery must precede authentication and device proof."); } Requests++; string[] features = nativeGrant ? ["version", "metaData", "processes", "processCancel", "extensions", "widgets", "nativeSessionLogin"] : ["version", "metaData", "processes", "processCancel", "extensions", "widgets"]; string json = JsonSerializer.Serialize(new { apiVersion, features, clientChannels = new[] { "api" }, extensions = new[] { new { name = "printing", version = printingVersion, pathPrefix = "/qbit/printing" } } }); return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(json) }); } } }