mirror of
https://github.com/logos-co/logos-protocol.git
synced 2026-08-31 14:01:14 +00:00
fix(protocol): re-exchange token on provider rejection (#26)
When a provider rejects a call for a stale/unrecognized token it now returns a structured "unauthorized" sentinel (logos_rpc_status.h) instead of a bare QVariant(). LogosAPIClient detects it below the typed wrapper, drops the cached token, re-runs capability_module.requestModule and retries the call once — closing the gap where a stale token was reused forever (the consumer-latched-dead failure mode) and lazily recovering the common provider-reload case. The return VALUE is the only provider->consumer channel available on every transport (qt_local/qt_remote/plain) without an ABI break, since the QtRO dispatch slot returns a single QVariant — hence a value sentinel. Backward compatible: - OLD consumers convert the sentinel identically to QVariant() for every scalar/string/LogosResult return, so they keep seeing today's empty/failed result. - OLD providers return bare QVariant(); a NEW consumer never matches the sentinel and so never re-exchanges against them. The retry is bounded to one attempt and fires ONLY on the explicit sentinel (never a legitimately-empty result), so no loops and no misfire. Downstream note: logos-qt-sdk's test_auth_token_enforcement.cpp asserts !isValid() on unauthorized calls; those become isUnauthorizedSentinel() when it re-pins (the security property — no provider dispatch — is unchanged). Tests: tests/protocol/test_token_reexchange.cpp covers provider-side emission, sync/async re-exchange+retry, bounded retry (no loop), the false-positive guard (a legit empty return must not re-exchange), and old-consumer decode. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
664b43f18a
commit
ef24bd70d9
@@ -1,6 +1,7 @@
|
||||
#include "module_proxy.h"
|
||||
#include "logos_provider_interface.h"
|
||||
#include "token_manager.h"
|
||||
#include "logos_rpc_status.h"
|
||||
#include <QDebug>
|
||||
#include <QByteArray>
|
||||
#include <QJsonObject>
|
||||
@@ -96,7 +97,12 @@ QVariant ModuleProxy::callRemoteMethod(const QString& authToken, const QString&
|
||||
if (!isAuthorized(authToken)) {
|
||||
qWarning() << "ModuleProxy: rejecting unauthorized call to" << methodName
|
||||
<< "- auth token not recognized";
|
||||
return QVariant();
|
||||
// Structured rejection instead of a bare QVariant() so a NEW consumer can
|
||||
// drop its stale token and re-exchange (see logos_rpc_status.h /
|
||||
// LogosAPIClient::invokeRemoteMethod). OLD consumers convert this to the
|
||||
// same empty/default they already got from QVariant(), so it's backward
|
||||
// compatible.
|
||||
return logos::makeUnauthorizedSentinel();
|
||||
}
|
||||
|
||||
// SECURITY: never log call arguments — they routinely carry secrets
|
||||
|
||||
Reference in New Issue
Block a user