using System.Security.Cryptography; using Wingoria.Images.Client.V1; using Wingoria.Images.Contracts.V1; // Backend only. A private bootstrap owned by Authentication creates the client. // Never put its endpoint or credential in source control, logs, a browser or Unity. public sealed class ImagesConnectionTemplate(ImagesClient images) { // For ordinary generation, prompt alone is enough. Provider and artistic // options are optional; no generation profile or financial fields are needed. public Task SubmitGeneration(ManagedImageRequest request, string durableAttemptId, CancellationToken cancellationToken) => images.GenerateManagedAsync(request, durableAttemptId, cancellationToken); public Task SubmitEdit(ManagedImageRequest request, string durableAttemptId, CancellationToken cancellationToken) => images.EditManagedAsync(request, durableAttemptId, cancellationToken); public async Task DownloadAndVerify(ImageJob terminalJob, int maximumBytes, CancellationToken cancellationToken) { if (terminalJob.Status != ImageJobStatus.Succeeded || terminalJob.Artifact is null) throw new InvalidOperationException("The job has no completed artifact."); var bytes = await images.DownloadArtifactAsync(terminalJob.Id, cancellationToken); if (bytes.Length == 0 || bytes.Length > maximumBytes) throw new InvalidDataException("The artifact size is outside the configured boundary."); var actual = SHA256.HashData(bytes); var expected = Convert.FromHexString(terminalJob.Artifact.Sha256); if (!CryptographicOperations.FixedTimeEquals(actual, expected)) throw new InvalidDataException("The artifact checksum does not match the job receipt."); return bytes; } } // Run admission before paid work and verify the registered owner and scopes. Persist // the idempotency key and job ID. Poll GetJobAsync with a bounded timeout. On an // unknown submission outcome, reconcile instead of resubmitting.