Commit Graph
21 Commits
Author SHA1 Message Date
Dario Gabriel Lipicar c70b5beeda refactor(nix): rely on module-builder dependency graph 2026-08-25 15:30:59 -03:00
Dario Gabriel Lipicar 4be5880099 chore(deps): relock caller-aware module builder 2026-08-25 15:21:29 -03:00
Dario LipicarandCursor 1cae2932f2 Identify requestModule caller from the RPC token (#26)
* Identify requestModule caller from the RPC token, not fromModuleName.

fromModuleName is leftover ABI: any loaded allowlisted name could be
written there. Use logos::currentCaller() (host → core) for policy and
the token push instead.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(deps): follow logos-cpp-sdk master for logos_caller.h

module-builder's lock still had cpp-sdk 95d7b3, which does not ship
the caller header requestModule now includes. Follow cpp-sdk master
(937f17, #151).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(identity): fall back when mocks/old hosts omit the caller

Direct impl tests and logoscore doctests do not always run under
logos_module_set_call_caller. Use fromModuleName only in that case;
a named currentCaller still wins, so spoofing the leftover ABI stays
denied.

Also follow qt-sdk, plugin-qt, protocol, and lidl master so
qt-generator sees lidl/identity.hpp and the generated glue actually
pushes the caller document.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Revert fromModuleName fallback; simulate identity with CallCaller.

requestModule identity is only logos::currentCaller(). Tests (and every
other C++ module) open that stack with logos::CallCaller, the same push
generated RPC glue performs. Pin cpp-sdk feat/call-caller-raii for that
type until #152 lands.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Take CallCaller from logos-test-framework, not cpp-sdk.

The production SDK has no CallCaller; unit tests get the RAII stand-in
via logos_test.h. Pin the test-framework branch until that lands on master.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Track logos-test-framework master now that CallCaller landed (#7).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Point the composition doctest at a host that actually injects the caller.

logoscore-cli's lock still predates CallerScope and currentCallerJson, so
requestModule saw Unknown and returned empty. Override protocol, plugin-qt,
and the SDKs onto master for that build — the same dispatch path, not a
fallback in capability.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Rebuild logos_host via liblogos #186; root plugin-qt overrides never reached it.

logoscore-cli does not follows plugin-qt into liblogos, so logos_host kept
shipping without currentCallerJson. Pin liblogos to the protocol-0.8 branch
and keep dumping the daemon log if this still fails.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 08:58:35 -03:00
Dario Lipicar 973f71badd fix(nix): cut the logos-standalone-app cycle out of the lock (#25)
logos-capability-module sits inside a dependency cycle:

  logos-capability-module -> logos-module-builder -> logos-standalone-app
    -> logos-liblogos -> logos-capability-module -> ...

flake.lock cannot express a cycle, so Nix unrolls it until the refs reach a
fixed point -- 5 repetitions, 23 levels deep -- duplicating the whole subtree
at every level. This is the reason lock files across the org are enormous.

Dropping the builder's logos-standalone-app input here breaks the loop at its
origin. Measured:

  logos-capability-module   3,391 -> 130 nodes  (2.42 MB -> 0.07 MB)
  logos-liblogos            3,472 -> 211        (re-locked against this branch)
  logos-basecamp           22,575 -> ~2,300
  workspace-wide                              -79.5%

The module still builds and its output is unchanged -- no input was repinned,
the removed nodes were pure duplication.
2026-08-20 23:38:44 -03:00
Dario LipicarandClaude Opus 5 c670f7f2cf feat: capability_module as a universal module, over a host-granted trust root (#24)
* feat: capability_module as a universal module (C4)

Rewrites the trust root as a plain Qt-free C++ class over the host-services
veneer, replacing the hand-written Qt plugin that reached into TokenManager
directly. The RPC surface is preserved EXACTLY — lm reports
requestModule(QString,QString) and registerRestriction(QString,QString,
QStringList) identically before and after; only initLogos(LogosAPI*) is gone,
which is the legacy Qt init hook no universal module has.

  * getTokenKeys()      -> logos::host::tokenKeys()        [token_registry]
  * getToken(name)      -> logos::host::tokenFor(name)
  * informModuleToken_module -> logos::host::informModuleTokenTo [token_delivery]
  * QHash/QSet          -> std::map/std::set, mutex-guarded (the Qt original
                           was implicitly serialised by the event loop, which
                           is not a property to inherit silently)
  * constantTimeEquals  -> the std::string one in logos_host_services.h

Token minting uses boost::uuids::random_generator — deliberately the SAME
generator the host uses for each module's token (liblogos module_manager.cpp),
not a hand-rolled std::random_device formatter: boost seeds from the platform
CSPRNG, while std::random_device is permitted to be deterministic and
historically was on MinGW, which is a live target. This value IS the auth token.

The argument order of the delivery call is spelled out at the call site because
it is the trap: authenticate with the TARGET's token, origin_module is the
TARGET, module_name is the REQUESTER. Swapping the last two compiles and
returns an ok-shaped status while telling the wrong module about the wrong
token.

PROVEN AT RUNTIME: logos-test-modules ipc-tests FAIL -> PASS with this module in
place — a universal trust root minting tokens under a host-granted privilege.

Getting there needed a fix outside this repo. The grant was delivered to the
module's process and then dropped, because module-builder emitted the cdylib
glue with logos-qt-sdk's STALE copy of the generator instead of the maintained
one in logos-plugin-qt (both compile, so nothing failed). The explicit refusal
message this impl logs is what made that findable at all:

  [capability_module] REFUSING 'core_service': this module was not granted the
                      token_registry host service, so it cannot verify any caller

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

* chore(deps): rev-pin logos-module-builder at the builder this module needs

Second lock pass of the capability-module <-> module-builder <-> standalone-app
cycle. Pass 1 pushed the C4 universal rewrite against a builder that predates
it; this closes the loop.

  logos-module-builder  9d3b7cc -> c60d4a9  feat/sdk-codegen-b4-qt-host-repoint

The rev goes in the URL, not just the lock. c60d4a9 is a BRANCH tip, so the
plain `github:logos-co/logos-module-builder` url this repo had would let
`nix flake update` relock onto master (9ac3a15) and silently undo the bump.
Two commits that only exist past master are load-bearing here:

  85dfb34  parse and validate metadata.json#host_services (C2) — this module
           declares host_services [token_registry, token_delivery], and without
           the parser the veneer header is never wired in
  ed50731  emit cdylib glue with logos-qt-host-generator, not qt-sdk's stale
           copy — the out-of-repo fix this repo's own C4 commit names as its
           prerequisite

MEASURED, not assumed. Same tree (fc39b1b), old pin vs new pin:

  packages.default   9d3b7cc: EXIT=1  fatal error: 'logos_host_services.h'
                                      file not found (capability_module_impl.cpp:7)
                     c60d4a9: EXIT=0  /nix/store/fhshfnr5p5icb7bs3ybk0dlj9f7zqxdc-...

lib, generate, include, install and lgx are green at the new pin too (6/7).
The bump is a fast-forward: 9ac3a15 (master) is an ancestor of c60d4a9, and
9d3b7cc is an ancestor of 9ac3a15, so nothing on master is given up. Drop the
rev once the branch merges.

Every transitive rev this drags in was verified to be a live remote branch tip
before it was written here: logos-protocol c8bab12, logos-cpp-sdk a04b278,
logos-qt-sdk 8a06b87, logos-plugin-qt AND logos-plugin-core cc24fa1 (both, per
the type:core / ui split), logos-view-module-runtime 5510acd,
logos-standalone-app 39f4f2b, logos-test-framework c382ab1.

NOT fixed here, and pre-existing: checks.unit-tests fails at both pins with
"Cannot find source file: ../src/capability_module_plugin.cpp". fc39b1b deleted
the hand-written Qt plugin, and tests/ still compiles it and drives
initLogos()/TokenManager. That is a C4 follow-up, not a lock question — see the
level report.

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

* docs: describe the module this repo actually builds

docs.md still described the `interface: "provider"` shape this module was
migrated off. Every claim below was checked against the tree or the build
output, not against the commit history:

  * "Implemented as a LogosProviderBase subclass" — it derives
    LogosModuleContext, and the impl is Qt-FREE: zero Qt types in either of its
    translation units.
  * "exposes a single primary method via the LOGOS_METHOD marker" — there is no
    marker; the public methods ARE the API and the generator derives the
    contract from the header. There are also TWO of them: registerRestriction
    was missing from the table entirely.
  * `requestModule → QString` — it returns std::string.
  * "LogosAPI* is delivered via LogosProviderBase::onInit" — it reaches the
    token store and delivery path through logos_host_services.h, the veneer over
    lp_token_keys / lp_inform_module_token_to, gated by the host-services grant.
  * A `src/capability_module_loader.h` in the file tree — that file does not
    exist; the plugin entry point is generated.
  * "generated_code/logos_provider_dispatch.cpp … produced by
    logos-cpp-generator --provider-header" — neither the file nor the flag
    exists. Confirmed by building
    `.#logos-capability-module--capability_module-generate`: what lands is
    capability_module.lidl, capability_module_cdylib_glue.{h,cpp},
    capability_module_module_impl.cpp and capability_module_types.h.
  * `interface: provider` in the metadata section — it is `universal`.

The three-step build pipeline is now spelled out with what each step produces,
since "which file comes from where" was the thing the old text got wrong in
every particular.

The removed path is named as history rather than deleted outright: "there used
to be a LOGOS_METHOD dispatch" is the question a reader arrives with, and
leaving no trace of it invites the same confusion in reverse.

Found while sweeping for stale references to the deleted generator paths after
the same class of rot turned up in logos-cpp-sdk's docs.

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

* docs: correct the capability_module docs for the universal migration

docs.md and the README still described this module as a handcrafted Qt plugin
and, worse, claimed the request path "always grants requests". It does not:
requestModule gates on a known caller (logos::host::tokenKeys()), a known
target (tokenFor()), and the registerRestriction access policy, minting the
token only after those pass. The token-flow section had the ordering backwards
and routed the push through LogosAPIClient, a Qt type this now Qt-free impl
cannot use — it goes through logos::host::informModuleTokenTo() over an
lp_client.

src/capability_module.lidl is marked DEAD: the module publishes a derived
`lidl` output now, so headerContractLidl prefers that over the committed file,
and the hand-kept method list is the pre-migration surface (it still lists
initLogos, which universal modules do not have).

Also records, in the README, that `nix build .#unit-tests` does not configure:
fc39b1b deleted src/capability_module_plugin.{h,cpp} without migrating tests/,
which still compiles them and drives CapabilityModulePlugin. That is this
repo's ONLY check, so it needs porting before this branch merges.

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

* test: port the unit tests to the universal shape, and fix the only check

fc39b1b moved this module to `interface: "universal"` and deleted
src/capability_module_plugin.{h,cpp}, but left tests/ compiling them. CMake
failed at generate, and since unit-tests is this repo's ONLY check, the whole
suite has been dark since.

Ported to drive CapabilityModuleImpl directly. No seam was added to the impl
and no production call site changed, which the "grant is per-image, not
per-instance" argument in logos_host_services.h asks for.

The push at the end of requestModule needs no fake: LogosMockSetup (which the
old suite already used) puts the process in LogosMode::Mock, where
MockTransportConnection::requestObject vends a MockLogosObject for any name and
its informModuleToken returns true. Everything else runs for real — the token
registry via lp_token_save, the token_registry gate via lp_token_keys,
lp_client_create, and logos::host::informModuleTokenTo. The only new
requirement is lp_grant_host_services, public C ABI.

Qt types are gone from the test's own surface (std::regex for the UUID shape,
std::set, std::string/std::vector); Qt survives only transitively through the
mock guard.

15 tests ported, 3 added — the grant now has fail-closed coverage the Qt shape
could not express (token_registry ungranted, token_delivery ungranted, an
unreachable target). 18 passed in 2ms.

Mutation-tested, 6 gates, one real build each. Four are load-bearing:
known-caller, known-target, access-policy, and registerRestriction's
trusted-token gate each fail the suite when disabled. Two are NOT, and are
labelled in-file as contract assertions rather than left to look like coverage:
the explicit ungranted() check and the empty-name gate are both shadowed by the
known-caller gate. The empty-TARGET half is shadowed more deeply still — it
survives with three gates removed, only because lp_client_create("") returns
nullptr, which nothing in this repo pins.

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

* chore(deps): retire the logos-module-builder rev pin, track master

07dba1f pinned logos-module-builder at c60d4a9 (tip of
feat/sdk-codegen-b4-qt-host-repoint) because two things this module cannot
build without were only on that branch. Both are now on module-builder master
(8cd62c7), so the pin is dead weight and the plain url is correct again:

  * parsing and validating metadata.json#host_services — lib/parseMetadata.nix,
    whose trust-root allowlist names capability_module as the ONLY module
    permitted to ask for token_registry/token_delivery; covered by
    tests/test-parse-metadata.nix, which uses this module's exact declaration
  * emitting the cdylib glue with logos-plugin-qt's logos-qt-host-generator
    instead of logos-qt-sdk's stale copy — lib/modulePreConfigure.nix and
    lib/buildCppPlugin.nix; asserted by tests/test-module-pre-configure.nix

Checked as FILES on master, not by ancestry: the PRs behind them
(logos-module-builder#203, logos-plugin-qt#19, logos-cpp-sdk#138,
logos-qt-sdk#33, logos-protocol#59) were SQUASH-merged, so
`merge-base --is-ancestor c60d4a9 master` is correctly false and proves nothing.

Relocked with an explicit `nix flake lock --update-input logos-module-builder`
rather than a bare `nix flake lock`, which does not re-resolve an input that is
already locked even once its url stops carrying a rev. Verified the revs moved:

  logos-module-builder  c60d4a9 -> 8cd62c7  (master)
  logos-cpp-sdk         a04b278 -> 95d7b3a  (master, #138)
  logos-qt-sdk          8a06b87 -> 19c844f  (master, #33)
  logos-plugin-qt       cc24fa1 -> 9b2c64e  (master, #19)
  logos-plugin-core     cc24fa1 -> 9b2c64e  (same repo, the type:core path this
                                             module actually resolves through)
  logos-protocol        c8bab12 -> f4407ff  (master, #59)

flake.lock shrinks by ~82k lines as the duplicated closures collapse onto one
revision each. No rev-pinned github:logos-co input remains that this repo owns.

VERIFIED on the relocked tree, aarch64-darwin, real builds:

  nix build .#default                        EXIT=0
  nix build .#checks.<sys>.unit-tests        EXIT=0, 18 passed
  lib generate include lidl headers-qt headers-lp
  install install-portable lgx               all EXIT=0 with an out path

and the two properties the pin existed to guarantee, checked in the OUTPUT:

  * generated_code/capability_module_module_impl.cpp exports
    logos_module_grant_host_services() -> lp_grant_host_services(), and
    capability_module_cdylib_glue.cpp calls it from the host's `hostServices`
    property. Both sit behind `LOGOS_PROTOCOL_VERSION_MINOR >= 3`; the closure
    links logos-protocol 0.4.0, so the grant path is compiled IN, not out.
  * the shipped share/logos/capability_module.lidl is byte-identical to the
    DERIVED contract, not to the stale committed src/capability_module.lidl —
    confirming the derived contract wins, as docs/ claims.

README's file-tree line said flake.nix "rev-pins logos-module-builder"; updated.

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

* chore(deps): relock onto module-builder master after the C3 grant landed

logos-module-loader-qt#8 merged (acd07cf), so the host-services grant path this
module depends on is on master: module_initializer.cpp stamps the hostServices
property the generated glue reads, and qt_plugin_format_loader's hostServicesFor
supplies it for capability_module.

unit-tests: 18 passed against the relocked closure.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 10:49:18 -03:00
Dario LipicarandCursor 0cb33fb21c feat(windows): commit a hand-written LIDL contract (#23)
* feat(windows): commit a hand-written LIDL contract

capability_module is interface: "legacy" -- a handcrafted Qt plugin -- so no
contract is derived from its sources the way a universal module's is, and it
publishes no LIDL sidecar or `lidl` flake output.

That is fine natively, where the typed consumer API is recovered by loading and
introspecting the built plugin. It is fatal under cross: the builder cannot
dlopen the Windows PE it just produced. This file is the contract that
logos-plugin-qt's buildHeaders.nix uses instead on that path.

Deliberately hand-written rather than produced by `--header-to-lidl` on the Qt
plugin header: that exits 0 but emits a contract with the constructor as a
method, initLogos exposed, and every QString/bool degraded to `any`.

Verified: the headers generated from this contract for x86_64-w64-mingw32 are
BYTE-IDENTICAL (md5) to the ones native darwin produces by introspecting the
.dylib.

* chore(deps): re-pin logos-module-builder to its merged rev

L6 (logos-module-builder) is on master now, so the lock can name the merged rev
instead of the pre-merge branch tip it was resolving against while that PR was
open. That rev is what carries mkLogosModule's x86_64-windows target, which is
what makes the contract in this repo reachable under cross.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 20:30:31 -03:00
Dario LipicarandClaude Opus 5 f18b9b1568 fix(startup): bound the token push so one unreachable module cannot stall startup (#22)
* fix(startup): bound the token push so one unreachable module cannot stall startup

A grant can only be delivered to a target whose source is published. A module
that calls out from its own initializer has not published yet on older SDKs,
so that one grant could burn the default 20s wait — long past the 10s the
standalone app gives a ui-host to report ready, turning one slow module into
a dead UI. Wait 3s instead and fail fast with a clear reason.

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

* chore: bump logos-module-builder to e9c8da45 (handshake surface)

Unblocks this PR. module-builder is this module's only flake input, so the
merged handshake work reaches it transitively:

  logos-module-builder  e9c8da45
    logos-protocol      c1b0a0f5   (#42)
    logos-qt-sdk        60d7a083   (#28)

The 3000 ms bound this PR adds needs the 5-argument informModuleToken_module
that landed in protocol #42; before this bump the signature did not exist here.

15/15 unit tests against the merged builder with no overrides.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 09:25:58 -03:00
Dario LipicarandClaude Opus 4.8 390486e225 chore: bump logos-module-builder to master (multi-user socket + token validator) (#21)
Pulls the new protocol (#20) + qt-sdk (#11) transitively via module-builder
(#155), so capability_module is built against the same protocol as the rest of
the runtime — closing the core_service<->capability_module protocol skew that
would otherwise break inter-module auth. Default module + unit-tests build green.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 00:53:14 -03:00
Khushboo Mehta 49791be583 chore: bump logos-module-builder 2026-06-26 18:03:33 +00:00
Dario LipicarandClaude Opus 4.8 62be3aaeb2 chore: bump logos-module-builder (logos-protocol json-convert fix) (#18)
Bumps logos-module-builder to master, pulling logos-protocol c6234940
(fix/json-convert-nested-to-qvariant). Pre-bump the glue linked a
protocol where nlohmannToQVariant made JSON arrays QJsonArray, breaking
QStringList returns (getValidVariants -> package manager "NOT AVAILABLE")
and QStringList args (registerRestriction). Lock-only.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 13:16:51 -03:00
Khushboo Mehta 4630b41df8 chore: bump nix-bundle-lgx
Transitive override of logos-module-builder/nix-bundle-lgx so the LGX
bundler copies display_name from metadata.json into the embedded
manifest.json
2026-06-22 21:25:11 +02:00
Iuri Matias 22e54ffc79 refactor capability module to work as an internal module proper instead of cosplaying as a app layer module
refactor capability module to work as an internal module proper instead of cosplaying as a app layer module

refactor capability module to work as an internal module proper instead of cosplaying as a app layer module

update flake

update flake
2026-06-11 16:31:00 -04:00
Dario Lipicar e675e9e3a9 migrate to logos-module-builder (#10)
* migrate to logos-module-builder

* add CI job
2026-05-07 16:36:38 -03:00
Iuri Matias bfae9f51c4 use moved interface and update flake 2026-03-19 19:37:45 -04:00
Iuri Matias c50e80c94c follow logos-nix for nix packages 2026-03-19 19:17:19 -04:00
Iuri Matias 29448227dc follow logos-nix for nix packages 2026-03-19 18:12:11 -04:00
Iuri Matias 0909d8f2dd update logos-cpp-sdk 2026-03-16 18:04:10 -04:00
Iuri Matias a2f9422245 update flake 2026-03-16 17:28:01 -04:00
Iuri Matias 47836a3965 update liblogos reference 2025-10-30 14:02:33 -04:00
Iuri Matias aa58ac9735 update nix dependencies 2025-10-23 14:04:13 -04:00
Iuri Matias 04617c132d feat: add nix flake 2025-10-09 09:22:24 -04:00