Files
logos-app/app/InstallRegistry.cpp
Dario Gabriel Lipicar 7851bf9f46 feat(host): per-plugin identities, an opt-in access policy, and the source split
Each loaded plugin -- including pure-QML ones -- gets its own LogosAPI identity
rather than sharing the host's, so a plugin's calls are attributable and can be
refused independently. The host-services grant is wired through to
capability_module, and its trust root is guarded on an OUTCOME rather than a
log line.

Inter-module access policy stays OFF by default: enforce mode's derived
deny-by-default gates every ui_qml app's calls to its own backend module,
because UI plugins load out-of-process and are not tracked as dependents in the
core ModuleRegistry. Operators opt in per launch with --access-policy enforce
or LOGOS_ACCESS_POLICY.

Takes the Qt host runtime from logos-plugin-qt rather than logos-qt-sdk, which
keeps only the Qt<->lp seam headers, and moves logos-protocol onto the rev that
split host needs. On Windows logos_core must come LAST on the link line: GNU ld
resolves an archive left to right, so the view runtime's references have to be
undefined already when it reaches the import library.

Separates the two source trees -- app/ is the host, src/ is the UI shell -- and
brings the CI onto setup-nix-cache-action. Merges master.
2026-08-22 16:42:13 -03:00

126 lines
3.8 KiB
C++

#include "InstallRegistry.h"
InstallRegistry::InstallRegistry(QObject* parent) : QObject(parent) {}
int InstallRegistry::stage(const QString& name) const
{
const auto it = m_ops.constFind(name);
return it == m_ops.cend() ? InstallStage::None
: static_cast<int>(it->stage);
}
bool InstallRegistry::isInFlight(const QString& name) const
{
const auto it = m_ops.constFind(name);
if (it == m_ops.cend()) return false;
switch (it->stage) {
case InstallStage::Downloading:
case InstallStage::Queued:
case InstallStage::Installing:
return true;
default:
return false;
}
}
QString InstallRegistry::error(const QString& name) const
{
const auto it = m_ops.constFind(name);
return it == m_ops.cend() ? QString() : it->error;
}
QString InstallRegistry::targetVersion(const QString& name) const
{
const auto it = m_ops.constFind(name);
return it == m_ops.cend() ? QString() : it->targetVersion;
}
QString InstallRegistry::targetHash(const QString& name) const
{
const auto it = m_ops.constFind(name);
return it == m_ops.cend() ? QString() : it->targetHash;
}
void InstallRegistry::begin(const QString& name,
const QString& targetVersion,
const QString& targetHash,
const QString& startedByTopLevel)
{
if (name.isEmpty()) return;
const bool added = !m_ops.contains(name);
Entry& e = m_ops[name];
e.name = name;
e.targetVersion = targetVersion;
e.targetHash = targetHash;
e.stage = InstallStage::Downloading;
e.error.clear();
e.startedByTopLevel = startedByTopLevel;
emit stageChanged(name, e.stage);
if (added) emit activeNamesChanged();
}
void InstallRegistry::setStage(const QString& name, InstallStage::Value stage)
{
auto it = m_ops.find(name);
if (it == m_ops.end()) return;
if (it->stage == stage) return;
it->stage = stage;
emit stageChanged(name, stage);
}
void InstallRegistry::fail(const QString& name, const QString& error)
{
auto it = m_ops.find(name);
if (it == m_ops.end()) return;
const bool stageChanged_ = it->stage != InstallStage::Failed;
it->stage = InstallStage::Failed;
it->error = error;
if (stageChanged_) emit stageChanged(name, InstallStage::Failed);
emit errorChanged(name, error);
}
void InstallRegistry::finish(const QString& name)
{
setStage(name, InstallStage::Installed);
}
void InstallRegistry::clear(const QString& name)
{
if (!m_ops.contains(name)) return;
m_ops.remove(name);
emit stageChanged(name, InstallStage::None);
emit errorChanged(name, QString());
emit activeNamesChanged();
}
void InstallRegistry::clearByTopLevel(const QString& topLevelName)
{
if (topLevelName.isEmpty()) return;
QStringList toRemove;
for (auto it = m_ops.cbegin(); it != m_ops.cend(); ++it) {
if (it->startedByTopLevel == topLevelName) toRemove.append(it.key());
}
if (toRemove.isEmpty()) return;
for (const QString& name : toRemove) m_ops.remove(name);
for (const QString& name : toRemove) {
emit stageChanged(name, InstallStage::None);
emit errorChanged(name, QString());
}
emit activeNamesChanged();
}
void InstallRegistry::beginOrTrack(const QString& name,
const QString& targetVersion,
const QString& targetHash,
const QString& startedByTopLevel)
{
if (name.isEmpty()) return;
if (!m_ops.contains(name)) {
begin(name, targetVersion, targetHash, startedByTopLevel);
return;
}
Entry& e = m_ops[name];
if (!targetVersion.isEmpty()) e.targetVersion = targetVersion;
if (!targetHash.isEmpty()) e.targetHash = targetHash;
}