Commit Graph
144 Commits
Author SHA1 Message Date
Dario Gabriel LipicarandClaude Opus 4.8 272c6b5bc7 fix(host): tie worker lifetime to the daemon (no orphan leak on crash)
Pairs the process-group isolation (setsid) with explicit parent-death cleanup so
a worker never lingers if the daemon dies WITHOUT cleaning it up (a crash).
setsid detaches the worker from the launcher's controlling terminal, which also
removes the incidental SIGHUP that used to reap orphans — so we replace it with
something reliable: PR_SET_PDEATHSIG(SIGKILL) on Linux (kernel-level, immediate),
plus a portable getppid() watchdog (covers macOS and backs up PDEATHSIG) that
exits if our parent changes. Compares against the daemon's actual pid (not pid
1) so a daemon that is itself PID 1 (a container) is handled correctly. Graceful
shutdown is unchanged (daemon still kills workers per-PID).

Verified: workers isolate into their own group; after kill -9 of the daemon,
every worker exits on its own (no leak).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:09:39 -03:00
Dario Gabriel LipicarandClaude Opus 4.8 fd00bcbccb fix(host): isolate each module subprocess into its own process group
logos_host now calls setsid() at startup, so each module subprocess leads its
own session/process group instead of inheriting the daemon's — which is in turn
the launcher's group. Without this, tearing the module tree down on shutdown (or
any process-group signal aimed at the daemon) leaks into the launcher and can
kill the shell driving the daemon (a script's teardown step dies with exit -15
on Linux). The daemon itself deliberately stays in the foreground / its
launcher's group so process managers (systemd, Docker) and shells keep managing
it normally — only its workers detach. Verified: daemon stays in the launcher
group; module subprocesses become own-group leaders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:43:44 -03:00
Dario LipicarandClaude Opus 4.8 050f2d3628 Qt-split retarget + logos_protocol_version load gate (#142)
* Qt-split retarget + protocol-version load gate

- Link the split SDK stack: logos-qt-sdk (LogosAPI/provider glue; the
  logos_sdk alias now points at logos-qt-sdk::logos_qt_sdk, chaining
  logos-protocol) + Qt-free logos-cpp-sdk headers.
- Protocol-version load gate (the first real consumer of module
  metadata pre-load): ModuleManager reads the module's embedded
  logos_protocol_version before runtime.load() and applies the one
  compatibility rule — equal protocol MAJOR loads, different MAJOR is
  refused with a diagnostic naming both versions, missing/unparseable
  stamp (pre-protocol modules) loads permissively with a warning. The
  decision logic is std-only (logos_core/protocol_gate.h) and unit
  tested (refuse bumped major / warn-load legacy / silent minor skew).
- ModuleDescriptor.rawMetadata is now actually populated for runtimes.

* lock: pin extraction-chain branch revs for standalone CI

Temporary — drop when the chain PRs merge (re-lock against masters).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: pin logoscore-cli to its qt-split branch head

The doc-test builds logoscore-cli at latest master with only liblogos
overridden to the commit under test; master logoscore-cli cannot build
against qt-split liblogos. Pin the runtime to the chain branch
(logos-co/logos-logoscore-cli#43) so the doc-test exercises the
coherent stack. Temporary — revert to the unpinned URL when the chain
merges.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* host: surface the spawn auth token as a LogosAPI property

cdylib-authored modules run their own statically-linked protocol stack
whose TokenManager is a separate copy of the singleton; the generated Qt
glue reads this property (cross-image-safe, like modulePath) and seeds
the cdylib's stack via logos_module_accept_token so the module's
outbound calls authenticate.

* host: set the authToken property before registerObject

registerObject runs the provider object's init() — where the cdylib glue
reads the property. Setting it afterwards meant cdylib modules always saw
an empty token.

* lock: protocol+cpp-sdk merged to master — pins advance (protocol 9de4165, cpp-sdk f0fe8cb, qt-sdk 722e590)

* lock: qt-sdk#1 merged — pin advances to qt-sdk master

* gate: drop QJson from the Qt-free core — parse rawMetadataJson with nlohmann

The protocol-version load gate had pulled QJsonDocument/QJsonObject into
src/logos_core (Qt-free territory). logos-module now exposes the embedded
metadata as a compact JSON string, so the gate reads it via nlohmann and
the std::string extractMetadata overload.

* lock: logos-module b42805d (result-lm untracked)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:45:49 -03:00
Iuri Matias 66256b54ef update logos-capability-module and logos-cpp-sdk (#147) 2026-06-11 16:53:59 -04:00
Iuri Matias 2bb5b89f3c enforce access policy based on dependencies (#146) 2026-06-11 16:33:03 -04:00
Iuri Matias 76416d32fc fix: f_014: prevent unbounded accumulation of child module stdou (#144) 2026-06-10 18:18:14 -04:00
Iuri Matias 098fed4527 support setting access policy (#145) 2026-06-10 18:17:54 -04:00
Iuri Matias 68e408a5de add api for access policy (#143) 2026-06-10 11:08:24 -04:00
Dario LipicarandClaude Opus 4.8 b396b36b5e test: assert auto-resolution leaves transitive dep closure loaded (#141)
LoadWithDeps_LoadsInTopologicalOrder pins the load *call sequence* when
loading a module with_dependencies=true. Add a complementary test that
pins the *observable end state* via the public logos_core_is_module_loaded
query: requesting a single top-level module must leave its entire
transitive dependency closure loaded.

Uses a diamond (app -> ui, core; ui -> core) so it also proves a
dependency reachable by two paths is loaded exactly once, not skipped or
double-loaded. This is the guarantee callers actually depend on ("load
app, get everything it needs").

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 22:22:12 -03:00
Iuri Matias eb0d30095d fix: f-030: sanitize malicious names used in sockets (#138) 2026-06-08 15:11:15 -04:00
Iuri Matias fedb496720 fix: F-022: add blocklist for certain module names (#139) 2026-06-08 14:43:19 -04:00
Iuri Matias 949fec18bc fix: authenticate token-handoff socket peer by uid and restrict it to 0600 (#136)
fix: authenticate token-handoff socket peer by uid and restrict it to 0600

fix

update doctests
2026-06-08 14:30:33 -04:00
Iuri Matias 6715b59326 fix: F-011: sanitize module names used for sockets (#137) 2026-06-08 14:06:25 -04:00
Iuri Matias f1debca480 fix: F-010: authenticate token-socket peer before sending auth token (#140) 2026-06-08 13:52:44 -04:00
Iuri Matias 51313eb58f add doctest (#134) tutorial-v3 2026-06-01 10:33:03 -04:00
Igor Sirotin be7c8fd8e8 chore: bump logos-cpp-sdk (provider event threading fix) (#133)
Picks up logos-co/logos-cpp-sdk#68 — marshals provider event emission onto the
remoting source thread. Host-runtime step toward fixing the start hang.
2026-05-25 11:53:24 -04:00
Dario Lipicar d4289c65ea fix returned value on load when modules already loaded (#132)
* fix returned value on load when modules already loaded

* make dependency resolution errors fail a load with dependencies
2026-05-20 12:51:05 -03:00
Dario Lipicar 738a578dca Module crash handling (#131)
* properly handle module subprocess crash

* print backtrace on subprocess crash

* add test

* pr comments
2026-05-20 11:10:56 -03:00
Corey Petty 666737597b Add disclaimer about experimental development environment (#60)
Added a disclaimer regarding the experimental nature of the repository and its intended use.
2026-05-19 17:27:18 -04:00
Iuri Matias 6b7e66da80 simplify c api by merging redudant functions; deprecate more functions no longer in use (#130)
* simplify c api by merging redudant functions; deprecate more functions no longer in use

simplify c api by merging redudant functions; deprecate more functions no longer in use

update docs

* remove deprecated methods
2026-05-19 16:20:32 -04:00
Dario Lipicar 2321de0365 fix: ensure consistent token socket path on the sender and receiver end (#129)
* fix: ensure consistent token socket path on the sender and receiver end

* address PR #129 review comments

- unix_socket_path.h: replace fixed-size PATH_MAX buffer with a
  two-step confstr probe (nullptr/0 to learn the size, then a
  std::vector<char>). Apple's per-user temp dir can exceed PATH_MAX
  on some configurations; the truncated fallback to /tmp would
  reintroduce the exact parent/child path mismatch this helper is
  meant to prevent.

- token_receiver.cpp: stack-allocate QLocalServer instead of new +
  deleteLater. The Qt event loop is not guaranteed to be running on
  the receiver thread, so deleteLater would leak; RAII makes every
  exit path (including listen() failure) clean up.

- tests/test_token_exchange.cpp: add a regression test that pins the
  TMPDIR-unset behaviour. The new test
  RoundTrip_SucceedsWithTmpdirUnset unsets TMPDIR (and
  LOGOS_INSTANCE_ID, which earlier tests may have left set via
  LogosInstance::id) and asserts both sender and receiver agree on
  the helper-resolved socket path. Also re-route the existing
  tmpDir() helper through ::logos::qtCompatibleTempDir() so the
  instance-id tests stay correct under the same conditions.
2026-05-08 15:00:23 -03:00
Iuri Matias 8acb280ba7 refactor: separate runtime from container (#126)
refactor: separate runtime from container

update docs
2026-05-08 10:35:05 -04:00
Dario LipicarandClaude Opus 4.7 03ffaa379e fix(subprocess-manager): clear processes in ~IoRuntime to avoid shutdown UAF (#128)
`s_processes` is a namespace-scope static (constructed before main),
while `IoRuntime` is a function-local static (constructed lazily on
first use, from main). C++ destroys statics in reverse construction
order, so at exit `~IoRuntime` fires first — tearing down the
asio::io_context and its epoll_reactor — and then `~s_processes`
runs, dropping `shared_ptr<ProcessEntry>`s whose dtors close asio
handles tied to the already-freed reactor. The resulting
use-after-free corrupts the heap and aborts logoscore on shutdown
(SIGABRT 134 / sometimes SIGSEGV 139, glibc reports
"corrupted size vs. prev_size"). Caught by valgrind:

    Invalid read of size 1
       at boost::asio::detail::epoll_reactor::deregister_descriptor
       by io_object_impl::~io_object_impl
       by std::_Hashtable<..., shared_ptr<ProcessEntry>, ...>::~_Hashtable
       by __cxa_finalize
     Address ... free'd
       by boost::asio::detail::epoll_reactor::~epoll_reactor
       by IoRuntime::~IoRuntime

Move ~IoRuntime out-of-line so it can reach s_processes, and have it
clear the map after stopping the worker thread but before ctx itself
is torn down by the field destructors. Each ProcessEntry's asio
handles are now released against a live reactor; the later
~s_processes then runs against an empty map.

Surfaced by logos-test-modules: 149/158 tests failed in CI
(intermittently 9–149 across machines, depending on malloc layout).
With this fix: 158 passed, 0 failed.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tutorial-v2
2026-05-07 18:22:38 -03:00
Dario Lipicar 54abc701fd bump capability module (#127) 2026-05-07 16:44:09 -03:00
Dario Lipicar 94af58c819 support non-local remote transports (#123)
* support non-local remote transports

* fix tests

* avoid masking crashes

* allow transport set configuration on any module

* pr comments

* add docs

* pr comments

* fixes

* fix flake.nix
2026-05-07 12:41:12 -03:00
Dario Lipicar 87b5c2e337 sendTokenToProcess: deadline-driven retry + sun_path length check (#124)
Two related fixes to the parent-side token handoff to a child module
process, both motivated by races / silent failures observed in the
docker smoke matrix.

1. Replace the hard-coded 10×100ms retry loop with a deadline-driven
   loop, default budget 5000ms (configurable via a new max_wait_ms
   parameter). The previous 900ms cap was tight enough that on a cold
   child — dynamic loader + Qt platform bring-up + CLI11 parse +
   plugin loadFromPath — the parent would give up before the child
   bound its QtTokenReceiver socket, leaving a half-loaded module
   with a misleading "Failed to connect to token socket" error. New
   tests pin both ends of the contract:
       SendToken_FailsFast_WhenSocketNeverAppears  — bails within budget
       SendToken_SucceedsAfterDelay                — accepts late binders

   test_token_exchange's WrongName_FailsCleanlyWithinTimeout bound
   loosened from <5000ms to <5500ms because the deadline check can
   overshoot by ~one poll interval (50ms) plus syscall slack.

2. Validate the computed Unix socket path against
   sockaddr_un::sun_path (~104 bytes on macOS, ~108 on Linux) before
   strncpy. Long TMPDIR + module name + LOGOS_INSTANCE_ID combos
   would otherwise silently truncate, leaving the parent connecting
   to the wrong socket while the child binds the full path. Fail
   loudly instead.
2026-05-01 17:05:17 -03:00
Iuri Matias b82145ce9a rename plugins to modules (#122) 2026-04-23 09:20:45 -04:00
Dario Lipicar d2d6ec7695 add instance id to token exchange socket name (#121)
* add instance id to token exchange socket name

* pr comments
2026-04-22 11:35:21 -03:00
Iuri MatiasandCopilot e86db998c4 refactor: move logost_host to become one of the possible runtimes (#119)
* refactor: move logost_host to become one of the possible runtimes

refactor: move logost_host to become one of the possible runtimes

remove shim

revert some unnecessary changes

update docs

update docs

revert unnecessary changes

simplify

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-21 15:15:46 -04:00
Dario LipicarandClaude Opus 4.7 5c01d968ce fix stdout and stderr redirection (#117)
* fix stdout and stderr redirection

* address PR review: strip trailing CR on pipe flush + add split-stream test

- handleRead: when flushing a partial line on pipe close, apply the same
  trailing-CR trim that the newline loop does.
- tests: add StartProcess_OnOutput_SplitsStdoutAndStderr to assert that
  both pipes drain and onOutput fires with the correct isStderr flag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 16:27:20 -03:00
Iuri Matias e96b05b657 use lm version that doesn't need qt arguments (#115) 2026-04-16 18:46:39 -04:00
Dario Lipicar a392301701 bump logos-package-manager (#116) 2026-04-16 18:26:08 -03:00
7a054c223f add unload with dependents method (#112)
* add unload with dependents method

* address second-round PR review comments

- plugin_registry.cpp: registerPlugin always writes dependencies and
  recomputes reverse edges (previously gated on !empty, which kept
  dependents stale when a plugin was registered with {} after another
  had already declared a dep on it, and also left callers with no way
  to clear forward edges).
- plugin_manager.cpp: getDependencies filters to known modules so the
  output matches the "among known modules" contract the header
  documents. pluginDependencies can return raw manifest names that
  aren't installed; filter at this boundary.
- README.md: thread-safety section no longer claims logos_core_refresh_plugins
  is serialised by the load/unload mutex — it isn't; it goes through the
  registry's reader-writer lock.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update src/logos_core/plugin_registry.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-16 15:11:44 -03:00
Iuri Matias ed5924ef1c use logos-cpp-sdk apis without qt types (#114) 2026-04-16 13:22:41 -04:00
Iuri Matias b92848b629 Remove (most) qt types (#113)
* replace usage of QDir and QFile

* replace usage of QString and QStringList

* replace QUuid

* update docs to reflect latest changes
2026-04-16 11:06:01 -04:00
Iuri Matias 732ab9e3c1 remove qt app context from logos_core (#111) 2026-04-15 16:52:32 -04:00
Iuri Matias 9cb8c09dbc replace qt logs (#110)
replace qt logs

fix spdlog in the tests

fix spdlog in the tests
2026-04-15 15:46:19 -04:00
Iuri Matias b035c965a0 replace qt process manager (#109)
* replace qt process manager

* fix boost rpath issue for the CI

* update docs
2026-04-15 14:38:13 -04:00
Khushboo-dev-cpp b293e9d70a fix: failing ci test (#108) 2026-04-13 08:55:38 -04:00
Dario Lipicar 522c56b4fa introduce instance persistence path for modules (#106) 2026-04-09 16:59:03 -03:00
Iuri Matias 198c261b5a add more tests to catch potential regressions (#107)
* add more tests to catch potential regressions

* remove qt from the tests

remove qt from the tests

revert changes made to src; update tests
2026-04-09 15:38:57 -04:00
Iuri Matias 608a11394f Replace process stats + fix existing issue with process stats + add regression test (#105)
* update process stats

* fix issue with module state disapearing on discovery refresh

* update flake
2026-04-09 10:30:33 -04:00
Dario Lipicar 87fbb87c9c incorporate thread-safe plugin management (#103)
* incorporate thread-safe plugin management

* copilot comments

* docs
2026-04-06 08:57:47 -03:00
Khushboo-dev-cpp da6ba7210e chore: bump logos-cpp-sdk to latest master (#95) 2026-03-31 16:27:01 +02:00
Iuri Matias 1ae87bafd5 update docs (#94) 2026-03-27 17:47:41 -04:00
Iuri Matias d2d04bef76 abstract qt components frmo logos_host; refactor (#93) 2026-03-27 17:08:43 -04:00
Iuri Matias 3af618e529 remove excessive logs; use a Plugin registry and move plugin launcher as separate concern (#92)
* remove excessive logs

* use a PluginInfo registry instead of various variables

* simplify: plugin_loader is no longer needed

* move plugin launcher as a separate concern
2026-03-27 16:17:59 -04:00
Dario Lipicar 4af6ae839b fix support for more than 2 module dirs (#91) 2026-03-27 15:28:47 -03:00
Iuri Matias 0d1e47f123 use new logos module methods to simplify getting name and dependencies (#90) 2026-03-27 14:22:00 -04:00
Iuri Matias c45417b6e3 Reorganize plugin manager into clearer files with defined responsibility; move (mostly) from qt json to nlohmann_json (#89)
* remove unused methods

* separate plugin manaager into separatge files with better defined responsibility

* move from Qt JSON to nlohmann_json
2026-03-27 12:33:38 -04:00