Each of these classes wrapped an existing free function with a one-line delegating method and was never instantiated anywhere (verified: no references outside their own translation unit, not even within their own .cpp beyond the definition) — the redundant "wrapper layer" pattern CLAUDE.md warns against: - LiteWalletLifecycleUiExecutionAdapter -> executeLiteWalletLifecycleUiRequest - LiteWalletServerSelectionUiExecutionAdapter -> executeLiteWalletServerSelectionUi - LiteWalletServerLifecycleReadinessPlanner -> evaluateLiteWalletServerLifecycleReadiness - LiteBackendActivationReadinessAdapter -> evaluateLiteBackendActivationReadiness The live free functions (the actual entry points used by the UI/runtime) are unchanged. Both targets build, test suite passes, source-hygiene clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
914 lines
48 KiB
C++
914 lines
48 KiB
C++
#include "wallet/lite_backend_artifact_resolver.h"
|
|
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <system_error>
|
|
#include <utility>
|
|
|
|
namespace dragonx::wallet {
|
|
namespace {
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
struct CandidateInspectionResult {
|
|
bool ok = false;
|
|
LiteBackendArtifactResolverStatus status = LiteBackendArtifactResolverStatus::WaitingForArtifactCandidate;
|
|
LiteBackendArtifactResolverIssue issue = LiteBackendArtifactResolverIssue::ArtifactMissing;
|
|
std::string message;
|
|
LiteBackendResolvedArtifact artifact;
|
|
LiteWalletSdxlArtifactInput syncArtifactInput;
|
|
};
|
|
|
|
void addIssue(LiteBackendArtifactResolverResult& result,
|
|
LiteBackendArtifactResolverIssue issue,
|
|
std::string message)
|
|
{
|
|
result.issues.push_back(LiteBackendArtifactResolverIssueInfo{issue, std::move(message)});
|
|
}
|
|
|
|
void addIssue(LiteBackendActivationReadinessResult& result,
|
|
LiteBackendActivationReadinessIssue issue,
|
|
std::string message)
|
|
{
|
|
result.issues.push_back(LiteBackendActivationReadinessIssueInfo{issue, std::move(message)});
|
|
}
|
|
|
|
LiteBackendArtifactResolverResult stoppedResolverResult(
|
|
LiteBackendArtifactResolverResult result,
|
|
LiteBackendArtifactResolverStatus status,
|
|
LiteBackendArtifactResolverIssue issue,
|
|
std::string message)
|
|
{
|
|
result.status = status;
|
|
addIssue(result, issue, std::move(message));
|
|
result.error = result.issues.back().message;
|
|
return result;
|
|
}
|
|
|
|
LiteBackendActivationReadinessResult stoppedActivationResult(
|
|
LiteBackendActivationReadinessResult result,
|
|
LiteBackendActivationReadinessStatus status,
|
|
LiteBackendActivationReadinessIssue issue,
|
|
std::string message,
|
|
WalletBackendState backendState = WalletBackendState::Unavailable)
|
|
{
|
|
result.status = status;
|
|
addIssue(result, issue, std::move(message));
|
|
result.error = result.issues.back().message;
|
|
result.connectionStatus = WalletBackendStatus{backendState, result.error, {}, {}, 0.0};
|
|
return result;
|
|
}
|
|
|
|
std::string lowerCopy(const std::string& value)
|
|
{
|
|
std::string lowered;
|
|
lowered.reserve(value.size());
|
|
for (const unsigned char character : value) {
|
|
lowered.push_back(static_cast<char>(std::tolower(character)));
|
|
}
|
|
return lowered;
|
|
}
|
|
|
|
std::string trimCopy(const std::string& value)
|
|
{
|
|
auto begin = value.begin();
|
|
while (begin != value.end() && std::isspace(static_cast<unsigned char>(*begin))) ++begin;
|
|
|
|
auto end = value.end();
|
|
while (end != begin && std::isspace(static_cast<unsigned char>(*(end - 1)))) --end;
|
|
|
|
return std::string(begin, end);
|
|
}
|
|
|
|
std::string baseNameLower(const std::string& path)
|
|
{
|
|
const auto slash = path.find_last_of("/\\");
|
|
const std::string name = slash == std::string::npos ? path : path.substr(slash + 1);
|
|
return lowerCopy(name);
|
|
}
|
|
|
|
bool endsWith(const std::string& value, const char* suffix)
|
|
{
|
|
const std::string suffixValue(suffix);
|
|
return value.size() >= suffixValue.size() &&
|
|
value.compare(value.size() - suffixValue.size(), suffixValue.size(), suffixValue) == 0;
|
|
}
|
|
|
|
LiteBackendArtifactPlatform normalizePlatform(LiteBackendArtifactPlatform platform)
|
|
{
|
|
return platform == LiteBackendArtifactPlatform::Current
|
|
? currentLiteBackendArtifactPlatform()
|
|
: platform;
|
|
}
|
|
|
|
LiteBackendArtifactKind inferArtifactKind(const std::string& path)
|
|
{
|
|
const std::string name = baseNameLower(path);
|
|
if (endsWith(name, ".a") || endsWith(name, ".lib")) return LiteBackendArtifactKind::StaticLibrary;
|
|
if (endsWith(name, ".so") || endsWith(name, ".dll") || endsWith(name, ".dylib")) {
|
|
return LiteBackendArtifactKind::SharedLibrary;
|
|
}
|
|
if (endsWith(name, ".exe") || name == "silentdragonxlite" || name == "silentdragonx-lite") {
|
|
return LiteBackendArtifactKind::Executable;
|
|
}
|
|
return LiteBackendArtifactKind::Unknown;
|
|
}
|
|
|
|
bool artifactKindSupported(LiteBackendArtifactKind kind)
|
|
{
|
|
return kind == LiteBackendArtifactKind::StaticLibrary ||
|
|
kind == LiteBackendArtifactKind::SharedLibrary ||
|
|
kind == LiteBackendArtifactKind::Executable;
|
|
}
|
|
|
|
std::vector<std::string> defaultArtifactNames(LiteBackendArtifactPlatform platform,
|
|
LiteBackendArtifactKind kind)
|
|
{
|
|
const auto normalizedPlatform = normalizePlatform(platform);
|
|
std::vector<std::string> names;
|
|
|
|
const auto addNamesForKind = [&](LiteBackendArtifactKind artifactKind) {
|
|
switch (normalizedPlatform) {
|
|
case LiteBackendArtifactPlatform::Windows:
|
|
if (artifactKind == LiteBackendArtifactKind::StaticLibrary) {
|
|
names.push_back("silentdragonxlite.lib");
|
|
names.push_back("libsilentdragonxlite.a");
|
|
} else if (artifactKind == LiteBackendArtifactKind::SharedLibrary) {
|
|
names.push_back("silentdragonxlite.dll");
|
|
} else if (artifactKind == LiteBackendArtifactKind::Executable) {
|
|
names.push_back("silentdragonxlite.exe");
|
|
names.push_back("silentdragonx-lite.exe");
|
|
}
|
|
break;
|
|
case LiteBackendArtifactPlatform::MacOS:
|
|
if (artifactKind == LiteBackendArtifactKind::StaticLibrary) {
|
|
names.push_back("libsilentdragonxlite.a");
|
|
names.push_back("silentdragonxlite.a");
|
|
} else if (artifactKind == LiteBackendArtifactKind::SharedLibrary) {
|
|
names.push_back("libsilentdragonxlite.dylib");
|
|
names.push_back("silentdragonxlite.dylib");
|
|
} else if (artifactKind == LiteBackendArtifactKind::Executable) {
|
|
names.push_back("silentdragonxlite");
|
|
names.push_back("silentdragonx-lite");
|
|
}
|
|
break;
|
|
case LiteBackendArtifactPlatform::Linux:
|
|
case LiteBackendArtifactPlatform::Current:
|
|
case LiteBackendArtifactPlatform::Unknown:
|
|
if (artifactKind == LiteBackendArtifactKind::StaticLibrary) {
|
|
names.push_back("silentdragonxlite.a");
|
|
names.push_back("libsilentdragonxlite.a");
|
|
} else if (artifactKind == LiteBackendArtifactKind::SharedLibrary) {
|
|
names.push_back("libsilentdragonxlite.so");
|
|
names.push_back("silentdragonxlite.so");
|
|
} else if (artifactKind == LiteBackendArtifactKind::Executable) {
|
|
names.push_back("silentdragonxlite");
|
|
names.push_back("silentdragonx-lite");
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
if (kind == LiteBackendArtifactKind::Unknown) {
|
|
addNamesForKind(LiteBackendArtifactKind::StaticLibrary);
|
|
addNamesForKind(LiteBackendArtifactKind::SharedLibrary);
|
|
addNamesForKind(LiteBackendArtifactKind::Executable);
|
|
} else {
|
|
addNamesForKind(kind);
|
|
}
|
|
return names;
|
|
}
|
|
|
|
fs::path resolvePath(const std::string& projectRoot, const std::string& path)
|
|
{
|
|
const fs::path value(path);
|
|
if (value.is_absolute()) return value;
|
|
const fs::path root = projectRoot.empty() ? fs::path(".") : fs::path(projectRoot);
|
|
return root / value;
|
|
}
|
|
|
|
std::vector<LiteBackendArtifactCandidate> expandSearchRoots(
|
|
const LiteBackendArtifactResolverInput& input,
|
|
LiteBackendArtifactResolverResult& result,
|
|
LiteBackendArtifactResolverOptions options)
|
|
{
|
|
std::vector<LiteBackendArtifactCandidate> candidates;
|
|
result.searchRootCount = input.searchRoots.size();
|
|
|
|
for (const auto& root : input.searchRoots) {
|
|
if (options.requireArtifactCandidates && !root.configured) {
|
|
result = stoppedResolverResult(
|
|
std::move(result),
|
|
LiteBackendArtifactResolverStatus::WaitingForArtifactSearchRoot,
|
|
LiteBackendArtifactResolverIssue::ArtifactSearchRootNotConfigured,
|
|
"lite backend artifact search root is not configured");
|
|
return {};
|
|
}
|
|
if (trimCopy(root.rootPath).empty()) {
|
|
result = stoppedResolverResult(
|
|
std::move(result),
|
|
LiteBackendArtifactResolverStatus::WaitingForArtifactSearchRoot,
|
|
LiteBackendArtifactResolverIssue::ArtifactSearchRootMissing,
|
|
"lite backend artifact search root path is missing");
|
|
return {};
|
|
}
|
|
|
|
const fs::path rootPath = resolvePath(input.projectRoot, root.rootPath);
|
|
std::error_code error;
|
|
if (!fs::exists(rootPath, error) || error) {
|
|
result = stoppedResolverResult(
|
|
std::move(result),
|
|
LiteBackendArtifactResolverStatus::WaitingForArtifactSearchRoot,
|
|
LiteBackendArtifactResolverIssue::ArtifactSearchRootMissing,
|
|
"lite backend artifact search root does not exist");
|
|
return {};
|
|
}
|
|
if (!fs::is_directory(rootPath, error) || error) {
|
|
result = stoppedResolverResult(
|
|
std::move(result),
|
|
LiteBackendArtifactResolverStatus::WaitingForArtifactSearchRoot,
|
|
LiteBackendArtifactResolverIssue::ArtifactSearchRootNotDirectory,
|
|
"lite backend artifact search root is not a directory");
|
|
return {};
|
|
}
|
|
|
|
const auto names = root.expectedArtifactNames.empty()
|
|
? defaultArtifactNames(root.platform, root.kind)
|
|
: root.expectedArtifactNames;
|
|
for (const auto& artifactName : names) {
|
|
LiteBackendArtifactCandidate candidate;
|
|
candidate.configured = true;
|
|
candidate.artifactPath = (rootPath / artifactName).string();
|
|
candidate.platform = root.platform;
|
|
candidate.kind = root.kind;
|
|
candidate.versionLabel = root.versionLabel;
|
|
candidate.provenance = root.provenance;
|
|
candidate.signatureVerification = root.signatureVerification;
|
|
candidate.sdxlCompatible = root.sdxlCompatible;
|
|
candidate.symbols = root.symbols;
|
|
candidate.executableMetadataRequired = root.executableMetadataRequired;
|
|
candidates.push_back(std::move(candidate));
|
|
}
|
|
}
|
|
result.artifactSearchRootsAccepted = true;
|
|
return candidates;
|
|
}
|
|
|
|
bool coreSymbolsReady(const LiteWalletSdxlArtifactSymbolsInput& symbols)
|
|
{
|
|
return symbols.walletExists &&
|
|
symbols.initializeNew &&
|
|
symbols.initializeNewFromPhrase &&
|
|
symbols.initializeExisting &&
|
|
symbols.execute &&
|
|
symbols.checkServerOnline;
|
|
}
|
|
|
|
bool fileReadable(const fs::path& path)
|
|
{
|
|
std::ifstream input(path, std::ios::binary);
|
|
return input.good();
|
|
}
|
|
|
|
bool fileExecutable(const fs::path& path, LiteBackendArtifactPlatform platform)
|
|
{
|
|
const std::string name = baseNameLower(path.string());
|
|
if (normalizePlatform(platform) == LiteBackendArtifactPlatform::Windows && endsWith(name, ".exe")) return true;
|
|
|
|
std::error_code error;
|
|
const auto permissions = fs::status(path, error).permissions();
|
|
if (error) return false;
|
|
return (permissions & fs::perms::owner_exec) != fs::perms::none ||
|
|
(permissions & fs::perms::group_exec) != fs::perms::none ||
|
|
(permissions & fs::perms::others_exec) != fs::perms::none;
|
|
}
|
|
|
|
bool provenanceComplete(const LiteBackendArtifactProvenanceMetadata& provenance)
|
|
{
|
|
return provenance.metadataProvided &&
|
|
!trimCopy(provenance.source).empty() &&
|
|
!trimCopy(provenance.builder).empty() &&
|
|
!trimCopy(provenance.sourceRevision).empty() &&
|
|
!trimCopy(provenance.artifactSetId).empty();
|
|
}
|
|
|
|
CandidateInspectionResult inspectCandidate(const LiteBackendArtifactResolverInput& input,
|
|
const LiteBackendArtifactCandidate& candidate,
|
|
LiteBackendArtifactResolverOptions options)
|
|
{
|
|
CandidateInspectionResult inspection;
|
|
if (options.requireArtifactCandidates && !candidate.configured) {
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactCandidateNotConfigured;
|
|
inspection.message = "lite backend artifact candidate is not configured";
|
|
return inspection;
|
|
}
|
|
if (trimCopy(candidate.artifactPath).empty()) {
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactPathMissing;
|
|
inspection.message = "lite backend artifact candidate path is missing";
|
|
return inspection;
|
|
}
|
|
|
|
const fs::path artifactPath = resolvePath(input.projectRoot, candidate.artifactPath);
|
|
std::error_code error;
|
|
if (!fs::exists(artifactPath, error) || error) {
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactMissing;
|
|
inspection.message = "lite backend artifact candidate does not exist";
|
|
return inspection;
|
|
}
|
|
if (!fs::is_regular_file(artifactPath, error) || error) {
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactNotRegularFile;
|
|
inspection.message = "lite backend artifact candidate is not a regular file";
|
|
return inspection;
|
|
}
|
|
if (!fileReadable(artifactPath)) {
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactUnreadable;
|
|
inspection.message = "lite backend artifact candidate is not readable";
|
|
return inspection;
|
|
}
|
|
|
|
const auto candidatePlatform = normalizePlatform(candidate.platform);
|
|
const auto expectedPlatform = normalizePlatform(input.expectedPlatform);
|
|
if (candidatePlatform == LiteBackendArtifactPlatform::Unknown || candidatePlatform != expectedPlatform) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::PlatformMismatch;
|
|
inspection.message = "lite backend artifact platform metadata does not match the expected platform";
|
|
return inspection;
|
|
}
|
|
|
|
const auto kind = candidate.kind == LiteBackendArtifactKind::Unknown
|
|
? inferArtifactKind(candidate.artifactPath)
|
|
: candidate.kind;
|
|
if (!artifactKindSupported(kind)) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::UnsupportedArtifactKind;
|
|
inspection.message = "lite backend artifact kind is unsupported or unknown";
|
|
return inspection;
|
|
}
|
|
|
|
if (options.requireVersionMetadata && trimCopy(candidate.versionLabel).empty()) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::VersionMissing;
|
|
inspection.message = "lite backend artifact version metadata is missing";
|
|
return inspection;
|
|
}
|
|
|
|
if (options.requireProvenanceMetadata) {
|
|
if (!candidate.provenance.ownerReady) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ProvenanceOwnerMissing;
|
|
inspection.message = "lite backend artifact provenance owner is not ready";
|
|
return inspection;
|
|
}
|
|
if (!provenanceComplete(candidate.provenance)) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ProvenanceMetadataMissing;
|
|
inspection.message = "lite backend artifact provenance metadata is incomplete";
|
|
return inspection;
|
|
}
|
|
}
|
|
|
|
if (options.requireSdxlCompatibility && !candidate.sdxlCompatible) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactNotSdxlCompatible;
|
|
inspection.message = "lite backend artifact is not marked SDXL-compatible";
|
|
return inspection;
|
|
}
|
|
|
|
if (options.requireSdxlSymbols) {
|
|
if (!coreSymbolsReady(candidate.symbols)) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactSymbolsMissing;
|
|
inspection.message = "lite backend artifact is missing required SDXL bridge symbol metadata";
|
|
return inspection;
|
|
}
|
|
if (!candidate.symbols.freeString) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactStringOwnershipUnverified;
|
|
inspection.message = "lite backend artifact string cleanup symbol metadata is missing";
|
|
return inspection;
|
|
}
|
|
if (!candidate.symbols.shutdown) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ArtifactShutdownUnavailable;
|
|
inspection.message = "lite backend artifact shutdown symbol metadata is missing";
|
|
return inspection;
|
|
}
|
|
}
|
|
|
|
const bool executable = fileExecutable(artifactPath, candidatePlatform);
|
|
if ((kind == LiteBackendArtifactKind::Executable || candidate.executableMetadataRequired) && !executable) {
|
|
inspection.status = LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata;
|
|
inspection.issue = LiteBackendArtifactResolverIssue::ExecutableMetadataMissing;
|
|
inspection.message = "lite backend executable artifact is not marked executable";
|
|
return inspection;
|
|
}
|
|
|
|
std::size_t artifactSizeBytes = 0;
|
|
const auto fileSize = fs::file_size(artifactPath, error);
|
|
if (!error) artifactSizeBytes = static_cast<std::size_t>(fileSize);
|
|
|
|
inspection.ok = true;
|
|
inspection.artifact.found = true;
|
|
inspection.artifact.artifactPath = artifactPath.string();
|
|
inspection.artifact.platform = candidatePlatform;
|
|
inspection.artifact.kind = kind;
|
|
inspection.artifact.versionLabel = candidate.versionLabel;
|
|
inspection.artifact.provenance = candidate.provenance;
|
|
inspection.artifact.signatureVerification = candidate.signatureVerification;
|
|
inspection.artifact.exists = true;
|
|
inspection.artifact.regularFile = true;
|
|
inspection.artifact.readable = true;
|
|
inspection.artifact.executable = executable;
|
|
inspection.artifact.sdxlCompatible = candidate.sdxlCompatible;
|
|
inspection.artifact.symbols = candidate.symbols;
|
|
inspection.artifact.artifactSizeBytes = artifactSizeBytes;
|
|
|
|
inspection.syncArtifactInput.pathConfigured = true;
|
|
inspection.syncArtifactInput.exists = true;
|
|
inspection.syncArtifactInput.readable = true;
|
|
inspection.syncArtifactInput.sdxlCompatible = candidate.sdxlCompatible;
|
|
inspection.syncArtifactInput.artifactPath = artifactPath.string();
|
|
inspection.syncArtifactInput.versionLabel = candidate.versionLabel;
|
|
inspection.syncArtifactInput.symbols = candidate.symbols;
|
|
return inspection;
|
|
}
|
|
|
|
LiteBackendArtifactResolverResult rejectResolverRuntimeAction(
|
|
LiteBackendArtifactResolverResult result,
|
|
const LiteBackendArtifactResolverInput& input,
|
|
LiteBackendArtifactResolverOptions options)
|
|
{
|
|
if (options.rejectArtifactMutation && input.artifactMutationRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::ArtifactMutationRequested,
|
|
"lite backend artifact mutation is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectSdxlApiCalls && input.sdxlApiRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::SdxlApiRequested,
|
|
"SDXL API calls are disabled for artifact resolution");
|
|
}
|
|
if (options.rejectServerConnectivityChecks && input.serverConnectivityCheckRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::ServerConnectivityCheckRequested,
|
|
"server connectivity checks are disabled for artifact resolution");
|
|
}
|
|
if (options.rejectWalletLifecycle && input.walletLifecycleRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::WalletLifecycleRequested,
|
|
"wallet lifecycle execution is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectSync && input.syncRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::SyncRequested,
|
|
"lite sync execution is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectSyncStatusPolling && input.syncStatusPollingRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::SyncStatusPollingRequested,
|
|
"lite syncstatus polling is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectWorkerQueue && input.workerQueueRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::WorkerQueueRequested,
|
|
"worker queue enqueue is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectWalletStateMutation && input.walletStateMutationRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::WalletStateMutationRequested,
|
|
"WalletState mutation is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectWalletPersistence && input.walletPersistenceRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::WalletPersistenceRequested,
|
|
"wallet persistence is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectUpload && input.uploadRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::UploadRequested,
|
|
"upload is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectSigning && input.signingRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::SigningRequested,
|
|
"signing is disabled for artifact resolution");
|
|
}
|
|
if (options.rejectPublication && input.publicationRequested) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::RuntimeActionDisabled,
|
|
LiteBackendArtifactResolverIssue::PublicationRequested,
|
|
"publication is disabled for artifact resolution");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
LiteBackendActivationReadinessResult rejectActivationRuntimeAction(
|
|
LiteBackendActivationReadinessResult result,
|
|
const LiteBackendActivationReadinessInput& input,
|
|
LiteBackendActivationReadinessOptions options)
|
|
{
|
|
if (options.rejectArtifactMutation && input.artifactMutationRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::ArtifactMutationRequested,
|
|
"lite backend artifact mutation is disabled for activation readiness");
|
|
}
|
|
if (options.rejectSdxlApiCalls && input.sdxlApiRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::SdxlApiRequested,
|
|
"SDXL API calls are disabled for activation readiness");
|
|
}
|
|
if (options.rejectServerConnectivityChecks && input.serverConnectivityCheckRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::ServerConnectivityCheckRequested,
|
|
"server connectivity checks are disabled for activation readiness");
|
|
}
|
|
if (options.rejectWalletLifecycle && input.walletLifecycleRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::WalletLifecycleRequested,
|
|
"wallet lifecycle execution is disabled for activation readiness");
|
|
}
|
|
if (options.rejectSync && input.syncRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::SyncRequested,
|
|
"lite sync execution is disabled for activation readiness");
|
|
}
|
|
if (options.rejectSyncStatusPolling && input.syncStatusPollingRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::SyncStatusPollingRequested,
|
|
"lite syncstatus polling is disabled for activation readiness");
|
|
}
|
|
if (options.rejectWorkerQueue && input.workerQueueRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::WorkerQueueRequested,
|
|
"worker queue enqueue is disabled for activation readiness");
|
|
}
|
|
if (options.rejectWalletStateMutation && input.walletStateMutationRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::WalletStateMutationRequested,
|
|
"WalletState mutation is disabled for activation readiness");
|
|
}
|
|
if (options.rejectWalletPersistence && input.walletPersistenceRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::WalletPersistenceRequested,
|
|
"wallet persistence is disabled for activation readiness");
|
|
}
|
|
if (options.rejectUpload && input.uploadRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::UploadRequested,
|
|
"upload is disabled for activation readiness");
|
|
}
|
|
if (options.rejectSigning && input.signingRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::SigningRequested,
|
|
"signing is disabled for activation readiness");
|
|
}
|
|
if (options.rejectPublication && input.publicationRequested) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::RuntimeActionDisabled,
|
|
LiteBackendActivationReadinessIssue::PublicationRequested,
|
|
"publication is disabled for activation readiness");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
WalletBackendStatus backendStatusOrDefault(const LiteBackendBridgeReadinessInput& backend,
|
|
const std::string& fallback)
|
|
{
|
|
if (!backend.status.message.empty()) return backend.status;
|
|
return WalletBackendStatus{WalletBackendState::Unavailable, fallback, {}, {}, 0.0};
|
|
}
|
|
|
|
WalletBackendStatus readyConnectionStatus(const LiteServerSelectionResult& selectedServer)
|
|
{
|
|
const std::string serverLabel = selectedServer.server.label.empty()
|
|
? selectedServer.server.url
|
|
: selectedServer.server.label;
|
|
return WalletBackendStatus{
|
|
WalletBackendState::Disconnected,
|
|
"lite backend activation readiness accepted for " + serverLabel + "; bridge calls remain disabled here",
|
|
{},
|
|
{},
|
|
0.0
|
|
};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
LiteBackendArtifactPlatform currentLiteBackendArtifactPlatform()
|
|
{
|
|
#if defined(_WIN32)
|
|
return LiteBackendArtifactPlatform::Windows;
|
|
#elif defined(__APPLE__)
|
|
return LiteBackendArtifactPlatform::MacOS;
|
|
#else
|
|
return LiteBackendArtifactPlatform::Linux;
|
|
#endif
|
|
}
|
|
|
|
const char* liteBackendArtifactPlatformName(LiteBackendArtifactPlatform platform)
|
|
{
|
|
switch (platform) {
|
|
case LiteBackendArtifactPlatform::Current: return "Current";
|
|
case LiteBackendArtifactPlatform::Linux: return "Linux";
|
|
case LiteBackendArtifactPlatform::Windows: return "Windows";
|
|
case LiteBackendArtifactPlatform::MacOS: return "MacOS";
|
|
case LiteBackendArtifactPlatform::Unknown: return "Unknown";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
const char* liteBackendArtifactKindName(LiteBackendArtifactKind kind)
|
|
{
|
|
switch (kind) {
|
|
case LiteBackendArtifactKind::Unknown: return "Unknown";
|
|
case LiteBackendArtifactKind::StaticLibrary: return "StaticLibrary";
|
|
case LiteBackendArtifactKind::SharedLibrary: return "SharedLibrary";
|
|
case LiteBackendArtifactKind::Executable: return "Executable";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
const char* liteBackendArtifactResolverStatusName(LiteBackendArtifactResolverStatus status)
|
|
{
|
|
switch (status) {
|
|
case LiteBackendArtifactResolverStatus::ReadyForActivationReadiness: return "ReadyForActivationReadiness";
|
|
case LiteBackendArtifactResolverStatus::WaitingForResolverOwner: return "WaitingForResolverOwner";
|
|
case LiteBackendArtifactResolverStatus::WaitingForReadOnlyGate: return "WaitingForReadOnlyGate";
|
|
case LiteBackendArtifactResolverStatus::WaitingForArtifactSearchRoot: return "WaitingForArtifactSearchRoot";
|
|
case LiteBackendArtifactResolverStatus::WaitingForArtifactCandidate: return "WaitingForArtifactCandidate";
|
|
case LiteBackendArtifactResolverStatus::WaitingForArtifactMetadata: return "WaitingForArtifactMetadata";
|
|
case LiteBackendArtifactResolverStatus::RuntimeActionDisabled: return "RuntimeActionDisabled";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
const char* liteBackendArtifactResolverIssueName(LiteBackendArtifactResolverIssue issue)
|
|
{
|
|
switch (issue) {
|
|
case LiteBackendArtifactResolverIssue::ResolverOwnerMissing: return "ResolverOwnerMissing";
|
|
case LiteBackendArtifactResolverIssue::ReadOnlyGateMissing: return "ReadOnlyGateMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactSearchRootMissing: return "ArtifactSearchRootMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactSearchRootNotConfigured: return "ArtifactSearchRootNotConfigured";
|
|
case LiteBackendArtifactResolverIssue::ArtifactSearchRootNotDirectory: return "ArtifactSearchRootNotDirectory";
|
|
case LiteBackendArtifactResolverIssue::ArtifactCandidateMissing: return "ArtifactCandidateMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactCandidateNotConfigured: return "ArtifactCandidateNotConfigured";
|
|
case LiteBackendArtifactResolverIssue::ArtifactPathMissing: return "ArtifactPathMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactMissing: return "ArtifactMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactNotRegularFile: return "ArtifactNotRegularFile";
|
|
case LiteBackendArtifactResolverIssue::ArtifactUnreadable: return "ArtifactUnreadable";
|
|
case LiteBackendArtifactResolverIssue::UnsupportedArtifactKind: return "UnsupportedArtifactKind";
|
|
case LiteBackendArtifactResolverIssue::PlatformMismatch: return "PlatformMismatch";
|
|
case LiteBackendArtifactResolverIssue::VersionMissing: return "VersionMissing";
|
|
case LiteBackendArtifactResolverIssue::ProvenanceOwnerMissing: return "ProvenanceOwnerMissing";
|
|
case LiteBackendArtifactResolverIssue::ProvenanceMetadataMissing: return "ProvenanceMetadataMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactNotSdxlCompatible: return "ArtifactNotSdxlCompatible";
|
|
case LiteBackendArtifactResolverIssue::ArtifactSymbolsMissing: return "ArtifactSymbolsMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactStringOwnershipUnverified: return "ArtifactStringOwnershipUnverified";
|
|
case LiteBackendArtifactResolverIssue::ArtifactShutdownUnavailable: return "ArtifactShutdownUnavailable";
|
|
case LiteBackendArtifactResolverIssue::ExecutableMetadataMissing: return "ExecutableMetadataMissing";
|
|
case LiteBackendArtifactResolverIssue::ArtifactMutationRequested: return "ArtifactMutationRequested";
|
|
case LiteBackendArtifactResolverIssue::SdxlApiRequested: return "SdxlApiRequested";
|
|
case LiteBackendArtifactResolverIssue::ServerConnectivityCheckRequested: return "ServerConnectivityCheckRequested";
|
|
case LiteBackendArtifactResolverIssue::WalletLifecycleRequested: return "WalletLifecycleRequested";
|
|
case LiteBackendArtifactResolverIssue::SyncRequested: return "SyncRequested";
|
|
case LiteBackendArtifactResolverIssue::SyncStatusPollingRequested: return "SyncStatusPollingRequested";
|
|
case LiteBackendArtifactResolverIssue::WorkerQueueRequested: return "WorkerQueueRequested";
|
|
case LiteBackendArtifactResolverIssue::WalletStateMutationRequested: return "WalletStateMutationRequested";
|
|
case LiteBackendArtifactResolverIssue::WalletPersistenceRequested: return "WalletPersistenceRequested";
|
|
case LiteBackendArtifactResolverIssue::UploadRequested: return "UploadRequested";
|
|
case LiteBackendArtifactResolverIssue::SigningRequested: return "SigningRequested";
|
|
case LiteBackendArtifactResolverIssue::PublicationRequested: return "PublicationRequested";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
const char* liteBackendActivationReadinessStatusName(LiteBackendActivationReadinessStatus status)
|
|
{
|
|
switch (status) {
|
|
case LiteBackendActivationReadinessStatus::ReadyForConnectionReadiness: return "ReadyForConnectionReadiness";
|
|
case LiteBackendActivationReadinessStatus::WaitingForActivationOwner: return "WaitingForActivationOwner";
|
|
case LiteBackendActivationReadinessStatus::WaitingForReadOnlyGate: return "WaitingForReadOnlyGate";
|
|
case LiteBackendActivationReadinessStatus::WaitingForLiteBuild: return "WaitingForLiteBuild";
|
|
case LiteBackendActivationReadinessStatus::WaitingForBackendCapability: return "WaitingForBackendCapability";
|
|
case LiteBackendActivationReadinessStatus::WaitingForArtifactResolver: return "WaitingForArtifactResolver";
|
|
case LiteBackendActivationReadinessStatus::WaitingForBackendLink: return "WaitingForBackendLink";
|
|
case LiteBackendActivationReadinessStatus::WaitingForBridge: return "WaitingForBridge";
|
|
case LiteBackendActivationReadinessStatus::WaitingForConnectionSettings: return "WaitingForConnectionSettings";
|
|
case LiteBackendActivationReadinessStatus::RuntimeActionDisabled: return "RuntimeActionDisabled";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
const char* liteBackendActivationReadinessIssueName(LiteBackendActivationReadinessIssue issue)
|
|
{
|
|
switch (issue) {
|
|
case LiteBackendActivationReadinessIssue::ActivationOwnerMissing: return "ActivationOwnerMissing";
|
|
case LiteBackendActivationReadinessIssue::ReadOnlyGateMissing: return "ReadOnlyGateMissing";
|
|
case LiteBackendActivationReadinessIssue::FullNodeBuild: return "FullNodeBuild";
|
|
case LiteBackendActivationReadinessIssue::LiteBackendCapabilityMissing: return "LiteBackendCapabilityMissing";
|
|
case LiteBackendActivationReadinessIssue::ArtifactResolverRejected: return "ArtifactResolverRejected";
|
|
case LiteBackendActivationReadinessIssue::BackendNotLinked: return "BackendNotLinked";
|
|
case LiteBackendActivationReadinessIssue::BridgeUnavailable: return "BridgeUnavailable";
|
|
case LiteBackendActivationReadinessIssue::ConnectionSettingsRejected: return "ConnectionSettingsRejected";
|
|
case LiteBackendActivationReadinessIssue::ArtifactMutationRequested: return "ArtifactMutationRequested";
|
|
case LiteBackendActivationReadinessIssue::SdxlApiRequested: return "SdxlApiRequested";
|
|
case LiteBackendActivationReadinessIssue::ServerConnectivityCheckRequested: return "ServerConnectivityCheckRequested";
|
|
case LiteBackendActivationReadinessIssue::WalletLifecycleRequested: return "WalletLifecycleRequested";
|
|
case LiteBackendActivationReadinessIssue::SyncRequested: return "SyncRequested";
|
|
case LiteBackendActivationReadinessIssue::SyncStatusPollingRequested: return "SyncStatusPollingRequested";
|
|
case LiteBackendActivationReadinessIssue::WorkerQueueRequested: return "WorkerQueueRequested";
|
|
case LiteBackendActivationReadinessIssue::WalletStateMutationRequested: return "WalletStateMutationRequested";
|
|
case LiteBackendActivationReadinessIssue::WalletPersistenceRequested: return "WalletPersistenceRequested";
|
|
case LiteBackendActivationReadinessIssue::UploadRequested: return "UploadRequested";
|
|
case LiteBackendActivationReadinessIssue::SigningRequested: return "SigningRequested";
|
|
case LiteBackendActivationReadinessIssue::PublicationRequested: return "PublicationRequested";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
LiteBackendArtifactResolverResult evaluateLiteBackendArtifactResolver(
|
|
const LiteBackendArtifactResolverInput& input,
|
|
LiteBackendArtifactResolverOptions options)
|
|
{
|
|
LiteBackendArtifactResolverResult result;
|
|
|
|
result = rejectResolverRuntimeAction(std::move(result), input, options);
|
|
if (!result.issues.empty()) return result;
|
|
|
|
if (options.requireResolverOwner && !input.resolverOwnerReady) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::WaitingForResolverOwner,
|
|
LiteBackendArtifactResolverIssue::ResolverOwnerMissing,
|
|
"lite backend artifact resolver owner is not ready");
|
|
}
|
|
result.resolverOwnerAccepted = true;
|
|
|
|
if (options.requireReadOnlyGate && !input.readOnlyGateReady) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::WaitingForReadOnlyGate,
|
|
LiteBackendArtifactResolverIssue::ReadOnlyGateMissing,
|
|
"lite backend artifact resolver read-only gate is not ready");
|
|
}
|
|
result.readOnlyGateAccepted = true;
|
|
|
|
auto candidates = expandSearchRoots(input, result, options);
|
|
if (!result.issues.empty()) return result;
|
|
for (const auto& candidate : input.candidates) candidates.push_back(candidate);
|
|
|
|
result.candidateCount = candidates.size();
|
|
if (options.requireArtifactCandidates && candidates.empty()) {
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::WaitingForArtifactCandidate,
|
|
LiteBackendArtifactResolverIssue::ArtifactCandidateMissing,
|
|
"lite backend artifact resolver has no configured candidates");
|
|
}
|
|
result.artifactCandidatesAccepted = true;
|
|
|
|
CandidateInspectionResult firstRejected;
|
|
bool haveRejectedCandidate = false;
|
|
for (const auto& candidate : candidates) {
|
|
++result.checkedCandidateCount;
|
|
auto inspection = inspectCandidate(input, candidate, options);
|
|
if (!inspection.ok) {
|
|
++result.rejectedCandidateCount;
|
|
if (!haveRejectedCandidate) {
|
|
firstRejected = std::move(inspection);
|
|
haveRejectedCandidate = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
result.ok = true;
|
|
result.status = LiteBackendArtifactResolverStatus::ReadyForActivationReadiness;
|
|
result.artifact = std::move(inspection.artifact);
|
|
result.syncArtifactInput = std::move(inspection.syncArtifactInput);
|
|
result.artifactDiscovered = true;
|
|
result.artifactMetadataAccepted = true;
|
|
result.platformAccepted = true;
|
|
result.versionAccepted = !options.requireVersionMetadata || !result.artifact.versionLabel.empty();
|
|
result.provenanceAccepted = !options.requireProvenanceMetadata || provenanceComplete(result.artifact.provenance);
|
|
result.sdxlCompatibilityAccepted = !options.requireSdxlCompatibility || result.artifact.sdxlCompatible;
|
|
result.symbolMetadataAccepted = !options.requireSdxlSymbols ||
|
|
(coreSymbolsReady(result.artifact.symbols) && result.artifact.symbols.freeString && result.artifact.symbols.shutdown);
|
|
result.executableMetadataAccepted = true;
|
|
result.syncArtifactInputProduced = true;
|
|
return result;
|
|
}
|
|
|
|
if (haveRejectedCandidate) {
|
|
return stoppedResolverResult(std::move(result), firstRejected.status, firstRejected.issue, firstRejected.message);
|
|
}
|
|
return stoppedResolverResult(std::move(result), LiteBackendArtifactResolverStatus::WaitingForArtifactCandidate,
|
|
LiteBackendArtifactResolverIssue::ArtifactCandidateMissing,
|
|
"lite backend artifact resolver did not find any artifact candidates");
|
|
}
|
|
|
|
LiteBackendActivationReadinessResult evaluateLiteBackendActivationReadiness(
|
|
const LiteBackendActivationReadinessInput& input,
|
|
LiteBackendActivationReadinessOptions options)
|
|
{
|
|
LiteBackendActivationReadinessResult result;
|
|
result.connectionAvailability = LiteConnectionAvailability::BackendUnavailable;
|
|
|
|
result = rejectActivationRuntimeAction(std::move(result), input, options);
|
|
if (!result.issues.empty()) return result;
|
|
|
|
if (options.requireActivationOwner && !input.activationOwnerReady) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForActivationOwner,
|
|
LiteBackendActivationReadinessIssue::ActivationOwnerMissing,
|
|
"lite backend activation readiness owner is not ready");
|
|
}
|
|
result.activationOwnerAccepted = true;
|
|
|
|
if (options.requireReadOnlyGate && !input.readOnlyGateReady) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForReadOnlyGate,
|
|
LiteBackendActivationReadinessIssue::ReadOnlyGateMissing,
|
|
"lite backend activation readiness read-only gate is not ready");
|
|
}
|
|
result.readOnlyGateAccepted = true;
|
|
|
|
if (options.requireLiteBuild && !isLiteBuild(input.capabilities)) {
|
|
result.connectionAvailability = LiteConnectionAvailability::UnsupportedBuild;
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForLiteBuild,
|
|
LiteBackendActivationReadinessIssue::FullNodeBuild,
|
|
"lite backend activation readiness requires a lite build");
|
|
}
|
|
result.liteBuildAccepted = true;
|
|
|
|
if (options.requireLiteBackendCapability && !supportsLiteBackend(input.capabilities)) {
|
|
result.connectionAvailability = LiteConnectionAvailability::BackendUnavailable;
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForBackendCapability,
|
|
LiteBackendActivationReadinessIssue::LiteBackendCapabilityMissing,
|
|
"lite backend capability is not available for activation readiness");
|
|
}
|
|
result.backendCapabilityAccepted = true;
|
|
|
|
result.artifactResolverResult = evaluateLiteBackendArtifactResolver(input.artifactResolver, options.resolverOptions);
|
|
if (options.requireResolvedArtifact && !result.artifactResolverResult.ok) {
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForArtifactResolver,
|
|
LiteBackendActivationReadinessIssue::ArtifactResolverRejected,
|
|
result.artifactResolverResult.error.empty()
|
|
? "lite backend artifact resolver did not produce a usable artifact"
|
|
: result.artifactResolverResult.error);
|
|
}
|
|
result.artifactResolverAccepted = true;
|
|
result.syncArtifactInput = result.artifactResolverResult.syncArtifactInput;
|
|
|
|
if (options.requireLinkedBackend && !input.backend.linked) {
|
|
result.connectionAvailability = LiteConnectionAvailability::BackendUnavailable;
|
|
const auto status = backendStatusOrDefault(input.backend, "lite backend is not linked");
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForBackendLink,
|
|
LiteBackendActivationReadinessIssue::BackendNotLinked,
|
|
status.message);
|
|
}
|
|
result.backendLinkedAccepted = true;
|
|
|
|
if (options.requireBridgeAvailable && !input.backend.bridgeAvailable) {
|
|
result.connectionAvailability = LiteConnectionAvailability::BridgeUnavailable;
|
|
const std::string message = !input.backend.bridgeUnavailableReason.empty()
|
|
? input.backend.bridgeUnavailableReason
|
|
: backendStatusOrDefault(input.backend, "lite client bridge is unavailable").message;
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForBridge,
|
|
LiteBackendActivationReadinessIssue::BridgeUnavailable,
|
|
message);
|
|
}
|
|
result.bridgeAccepted = true;
|
|
|
|
result.selectedServer = selectLiteServer(input.connectionSettings);
|
|
if (options.requireUsableServer && !result.selectedServer.ok) {
|
|
result.connectionAvailability = LiteConnectionAvailability::NoUsableServer;
|
|
return stoppedActivationResult(std::move(result), LiteBackendActivationReadinessStatus::WaitingForConnectionSettings,
|
|
LiteBackendActivationReadinessIssue::ConnectionSettingsRejected,
|
|
result.selectedServer.error.empty()
|
|
? "no usable lite server is configured for activation readiness"
|
|
: result.selectedServer.error,
|
|
WalletBackendState::Error);
|
|
}
|
|
result.connectionSettingsAccepted = true;
|
|
|
|
result.syncBackendInput.linked = input.backend.linked;
|
|
result.syncBackendInput.bridgeAvailable = input.backend.bridgeAvailable;
|
|
result.syncBackendInput.status = input.backend.status.message.empty()
|
|
? WalletBackendStatus{WalletBackendState::Disconnected, "lite backend bridge readiness accepted", {}, {}, 0.0}
|
|
: input.backend.status;
|
|
result.syncBackendInput.bridgeUnavailableReason = input.backend.bridgeUnavailableReason;
|
|
result.syncReadinessInputsProduced = true;
|
|
|
|
result.ok = true;
|
|
result.status = LiteBackendActivationReadinessStatus::ReadyForConnectionReadiness;
|
|
result.connectionAvailability = LiteConnectionAvailability::Ready;
|
|
result.connectionStatus = readyConnectionStatus(result.selectedServer);
|
|
result.connectionServiceBoundaryAccepted = true;
|
|
return result;
|
|
}
|
|
|
|
LiteBackendArtifactResolver::LiteBackendArtifactResolver(LiteBackendArtifactResolverOptions options)
|
|
: options_(options)
|
|
{
|
|
}
|
|
|
|
LiteBackendArtifactResolverResult LiteBackendArtifactResolver::resolve(
|
|
const LiteBackendArtifactResolverInput& input) const
|
|
{
|
|
return evaluateLiteBackendArtifactResolver(input, options_);
|
|
}
|
|
|
|
} // namespace dragonx::wallet
|