Dario Gabriel LipicarandClaude Opus 5 b3675bc9af feat(shared-api): give LOGOS_SHARED_API an export half
Groundwork for making logos_protocol and logos_qt_host proper shared libraries
for the in-process image set, replacing the whole-archive + generated .def +
empty-archive-shim scheme. On its own this changes no behaviour: every current
consumer still resolves the macro to nothing.

WHAT WAS MISSING. The macro had only two states -- __declspec(dllimport) under
_WIN32 && LOGOS_SHARED_USE_DLL, and empty otherwise. There was no export half at
all, because the export side was delegated to a .def generated at
liblogos_core's link (logos-liblogos/cmake/gen-shared-exports.sh). A shared
library cannot use a .def belonging to a different library, so the types need to
be able to mark themselves.

Now three-state, mirroring LP_API's existing shape in logos_protocol.h:
EXPORT while building the shared library that owns the symbol, IMPORT while
consuming it, EMPTY for the static archive.

TWO MACROS, NOT ONE. LOGOS_QT_HOST_API is added alongside for logos-plugin-qt's
LogosAPI, which lives in a DIFFERENT library. It cannot reuse LOGOS_SHARED_API,
because the two are not the same choice in the same translation unit: while
building the Qt host runtime shared library, LogosAPI must be EXPORTED while
TokenManager -- owned by logos-protocol -- must be IMPORTED. One macro cannot
say both, and on PE getting it wrong defines the type twice in the process.

Nothing uses LOGOS_QT_HOST_API yet; it is defined here so the split is stated
where the mechanism lives rather than discovered later, and so the Qt host
change is a mechanical switch. Off Windows the distinction is moot -- both
resolve to default visibility -- which is exactly why it would go unnoticed
until a Windows build.

Also corrects this file's own premise, which is where the false claim
originated: "ELF and Mach-O give this for free. Both formats interpose symbols
across the whole process image set." True of ELF, FALSE of Mach-O, whose
two-level namespace gives no interposition -- measured in logos-basecamp, where
one reference to LogosAPI::forIdentity dragged logos_api.cpp.o into the
executable and produced 31 refused calls against a baseline of 0.

VERIFIED, aarch64-darwin.

  static archive  symbol tables IDENTICAL (14257 lines each), same size, and
                  EXACTLY ONE byte differs in the whole 5.4MB file -- 351 -> 352
                  in __.SYMDEF's ar header, i.e. build-environment metadata, not
                  content. This is the no-behaviour-change claim, measured.
  shared library  748 exported / 78 runtime symbols, unchanged. Expected: no
                  -fvisibility=hidden anywhere in this build, so a Mach-O shared
                  library already exported them by default.
  checks.tests    PASS

NOT VERIFIED LOCALLY: Windows, which is the only platform where this changes
anything -- without dllexport the symbols are simply absent from the PE export
table. packages.x86_64-windows requires an x86_64-linux builder, so it rests on
CI here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 20:21:56 -03:00
2026-06-09 23:33:17 -03:00

logos-protocol

The Logos protocol layer: transports, token exchange, and the language-neutral lp_* C ABI (cpp/logos_protocol.h) that every Logos SDK builds on.

Extracted from logos-cpp-sdk so that non-C++ SDKs (Rust, …) consume the same transports, capability/token flow and wire behavior through one stable, versioned boundary instead of re-wrapping the C++/Qt SDK.

What lives here

  • Public C ABIcpp/logos_protocol.h: consumer surface (lp_client_*, lp_invoke[_async], lp_subscribe, tokens, lp_get_methods), provider groundwork (lp_provider_*), the trust-root surface (lp_grant_host_services and the two functions it gates), per-identity token stores (lp_token_isolate_identity, lp_token_get_for, lp_token_save_for, lp_token_reset_identity, lp_token_identity_is_isolated), and the protocol version (LOGOS_PROTOCOL_VERSION_*, lp_protocol_version(), lp_protocol_abi_major()). JSON-in-strings data model; bytes cross the boundary as {"_bytes":"<base64url>"} (lossless, NUL-safe).
  • Transports — plain TCP / TCP+TLS (Boost.Asio + OpenSSL + nlohmann, Qt-free), qt_local, in-memory mock, and Qt Remote Objects (qt_remote — the only Qt-bearing transport).
  • Consumer coreLogosAPIClient / LogosAPIConsumer including the automatic capability_module.requestModule token-fetch flow (behind the protocol boundary: every language gets it for free).
  • Provider-side plumbingModuleProxy (auth gate the transports publish) and the abstract LogosProviderObject interface (logos_provider_interface.h).
  • Token manager, transport/registry factories, mode config (remote/local/mock), and the canonical QVariant↔JSON conversion used at the QRO boundary.

Per-identity token stores

TokenManager::instance() is the image's store. In a host that loads several modules in one image it is also an ambient ring: the host writes name -> that module's root auth token for every module it loads, and a client presents a cached token before it ever mints one — so any module in that image can reach any other with authority it was never granted, and no requestModule appears in the log. Per-module origin strings do not change that, because origin was never consulted on the path taken.

TokenManager::forIdentity(origin) makes origin select the store instead of merely labelling the caller, and isolateIdentity(origin) is how a host opts a name in (lp_token_isolate_identity and friends from C). Both are additive and inert by default: until a name is isolated, forIdentity() returns the same object instance() returns, so a host that knows nothing about this is unchanged. A private store is seeded with the trust-root bootstrap (core, capability_module) so first-call requestModule still works, and with nothing else.

This is a second axis, not a replacement for the per-image split: a module cdylib links its own copy of this library and therefore has its own instance(), which stays correct as-is.

logos-cpp-sdk layers the typed C++ developer API (LogosAPI, module context, code generator, provider base classes) on top of this repo.

Versioning

This repo carries the logos-protocol semver — the single number that governs Logos load/call compatibility. Two participants (modules, hosts, SDKs in any language) interoperate iff they share the same MAJOR. MINOR is additive/back-compatible; PATCH never affects compatibility. SDKs must re-expose the version of the protocol they linked (never mint their own).

Building

# Via workspace
ws build logos-protocol

# Standalone
nix build

# Tests
nix build .#tests

Layering invariant

logos-protocol depends only on Qt / Boost / OpenSSL / nlohmann_json — it must NEVER depend on logos-cpp-sdk, logos-qt-sdk, logos-rust-sdk, liblogos or logos-lidl. Everything points inward.

S
Description
No description provided
Readme
1.6 MiB
Languages
C++ 91.5%
C 3.9%
CMake 2.7%
Nix 1.1%
Shell 0.8%