mirror of
https://github.com/logos-co/logos-liblogos.git
synced 2026-08-27 12:51:10 +00:00
fix(doctests): unpin logoscore-cli, and retire the archived accounts module
The macOS doc-test job has been red since 2026-08-21: every module call came
back {"__logos_rpc_status__":"unauthorized"}, preceded in the daemon log by
capability_module rejecting the CLI's own requestModule handshake. Linux was
green throughout.
NOT MODULE ROT. A freshly-built test_basic_module failed identically to
accounts_module. Bisected on one macOS box, one variable, same CLI, same module:
liblogos 3893c833 (parent) -> "result":42
liblogos b2a9a0ba (#182) -> unauthorized
MECHANISM, from `nm -mu` on the logoscore binary:
pre-#182: TokenManager::instance() (from liblogos_core)
at-#182: TokenManager::instance() (from liblogos_module_client)
#182 made liblogos_core export ZERO TokenManager symbols -- they moved to
liblogos_protocol. macOS two-level namespace then rebound the CLI's imports to
the next image still statically absorbing a copy, so the CLI wrote its token
into one singleton while the runtime authorized against another. ELF cannot
show this: flat namespace collapses every definition onto the first-loaded
image, so Linux held the invariant by accident.
THE PIN IS THE BUG, not the linkage. The shared-runtime split landed as one pin
SET -- logos-protocol 2e3344a, logos-plugin-qt 1aa3e31, logos-liblogos b2a9a0b
(#182), logoscore-cli 2312a3a. This spec pinned the CLI at b92ade06
(2026-06-10) and overrode only logos-liblogos, manufacturing exactly the
half-migrated pairing the set exists to prevent. That pin's own commit (050f2d3)
called it "Temporary -- drop when the chain PRs merge"; nobody did. Dropping the
rev is the fix. logoscore master had already shed the deprecated
logos-module-client in its #48, so nothing there needs changing.
WHY THIS READ AS ONE FLAKY STEP rather than a total auth outage: "Call a method"
asserted on the bare string '"result"', which the unauthorized envelope also
contains. Both calls now assert values -- '"result":"hello"' and '"result":42'.
ALSO RETIRED: logos-accounts-module was archived on 2026-07-22. Both specs now
drive test_basic_module from logos-test-modules, via the
`#modules.$SYSTEM.<name>.lgx` attribute path the logoscore-cli doc-tests already
use. The module-runtime spec no longer clones a repo at all, so it loses its git
prerequisite and one step.
VERIFIED on aarch64-darwin against 959d11d9 -- the exact commit CI failed on:
34 passed, 0 failed (was 34 passed, 1 failed of 35), and zero "rejecting
unauthorized call" lines in the daemon log.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Dario Lipicar
co-authored by
Claude Opus 5
parent
2ac002b410
commit
f05ed5a899
@@ -3,11 +3,11 @@ name: liblogos Doc-Tests
|
||||
# Runs the executable liblogos doc-tests end-to-end via the shared doctest CLI,
|
||||
# both pinned to the commit of logos-liblogos under test (via --release-for):
|
||||
# - doctests/liblogos-module-runtime.test.yaml — drives liblogos through the
|
||||
# logoscore CLI frontend (build logoscore against this commit, install the
|
||||
# accounts module, start the daemon, load + call methods).
|
||||
# logoscore CLI frontend (build logoscore against this commit, install
|
||||
# test_basic_module, start the daemon, load + call methods).
|
||||
# - doctests/liblogos-as-a-library.test.yaml — embeds liblogos directly:
|
||||
# builds liblogos_core from this commit, compiles a C++ program that links
|
||||
# it, installs modules with lgpm, and loads the accounts module via the C API.
|
||||
# it, installs modules with lgpm, and loads test_basic_module via the C API.
|
||||
# Both specs run in one invocation, producing a single combined report.
|
||||
#
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
const body =
|
||||
`${marker}\n` +
|
||||
`### 📊 liblogos doc-test report\n\n` +
|
||||
`The real accounts module, run through a logoscore daemon built against ` +
|
||||
`A real module, run through a logoscore daemon built against ` +
|
||||
`this commit of liblogos — rendered alongside the commands actually run ` +
|
||||
`and their output (updated each run, commit \`${context.sha.slice(0,7)}\`):\n\n` +
|
||||
`${links}\n\n` +
|
||||
|
||||
@@ -18,10 +18,10 @@ intro: |
|
||||
under test.
|
||||
2. Build the `lgpm` package manager and install two real modules
|
||||
([`capability_module`](https://github.com/logos-co/logos-capability-module)
|
||||
and [`accounts_module`](https://github.com/logos-co/logos-accounts-module))
|
||||
and [`test_basic_module`](https://github.com/logos-co/logos-test-modules))
|
||||
into a local modules directory.
|
||||
3. Write a ~50-line C++ program that links `liblogos_core`, then calls the C
|
||||
API to start the runtime and load `accounts_module`.
|
||||
API to start the runtime and load `test_basic_module`.
|
||||
4. Build that program against this liblogos and run it — watching the module
|
||||
come up over liblogos' own IPC.
|
||||
|
||||
@@ -36,7 +36,7 @@ intro: |
|
||||
> as `logoscore` and basecamp do. You do **not** need to run Qt's event loop;
|
||||
> the load calls are synchronous.
|
||||
|
||||
what_you_build: "A standalone C++ program that links `liblogos_core` from this commit and loads the real `accounts_module` through the C API."
|
||||
what_you_build: "A standalone C++ program that links `liblogos_core` from this commit and loads a real module — `test_basic_module` — through the C API."
|
||||
|
||||
what_you_learn:
|
||||
- How to build `liblogos_core`, `logos_host`, and `logos_core.h` from a specific liblogos commit
|
||||
@@ -100,8 +100,8 @@ sections:
|
||||
text: |
|
||||
The runtime discovers modules from a directory of installed packages. We
|
||||
build the `lgpm` package manager and two real modules' `.lgx` packages,
|
||||
then install them in the next step. `accounts_module` is loaded through the
|
||||
host's capability layer, so we install `capability_module` alongside it.
|
||||
then install them in the next step. `test_basic_module` is loaded through
|
||||
the host's capability layer, so we install `capability_module` alongside it.
|
||||
steps:
|
||||
- title: "Build lgpm"
|
||||
run: "nix build 'github:logos-co/logos-package-manager#cli' -o lgpm"
|
||||
@@ -114,15 +114,17 @@ sections:
|
||||
extra_run:
|
||||
run: "ls cap-lgx/*.lgx"
|
||||
|
||||
- title: "Build the accounts module's .lgx"
|
||||
- title: "Build the test module's .lgx"
|
||||
text: |
|
||||
This compiles the module and its SDK dependencies through Nix (the
|
||||
accounts module wraps the go-wallet-sdk C library), so the first build
|
||||
is slow.
|
||||
run: "nix build 'github:logos-co/logos-accounts-module#lgx' -o accounts-lgx"
|
||||
post_text: "The `.lgx` package is under `./accounts-lgx/`:"
|
||||
`logos-test-modules` publishes each of its modules under
|
||||
`modules.<system>.<name>`, so the attribute path carries the Nix system
|
||||
double — `builtins.currentSystem` supplies it.
|
||||
run: |
|
||||
SYSTEM=$(nix eval --impure --raw --expr 'builtins.currentSystem')
|
||||
nix build "github:logos-co/logos-test-modules#modules.$SYSTEM.test_basic_module.lgx" -o module-lgx
|
||||
post_text: "The `.lgx` package is under `./module-lgx/`:"
|
||||
extra_run:
|
||||
run: "ls accounts-lgx/*.lgx"
|
||||
run: "ls module-lgx/*.lgx"
|
||||
|
||||
- title: "Install the modules with lgpm"
|
||||
step: true
|
||||
@@ -137,18 +139,18 @@ sections:
|
||||
expect_contains:
|
||||
- "Installed to:"
|
||||
|
||||
- title: "Install accounts_module"
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file accounts-lgx/*.lgx"
|
||||
- title: "Install test_basic_module"
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file module-lgx/*.lgx"
|
||||
expect_contains:
|
||||
- "Installed to:"
|
||||
|
||||
- title: "Confirm both modules are installed"
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules list"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
- "test_basic_module"
|
||||
- "capability_module"
|
||||
- "core"
|
||||
check_file: "modules/accounts_module/manifest.json"
|
||||
check_file: "modules/test_basic_module/manifest.json"
|
||||
post_text: |
|
||||
Both modules now report type `core`, so `logos_core_start()` will
|
||||
discover them.
|
||||
@@ -203,7 +205,7 @@ sections:
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
||||
const char* modulesArg = (argc > 1) ? argv[1] : "./modules";
|
||||
const char* moduleName = (argc > 2) ? argv[2] : "accounts_module";
|
||||
const char* moduleName = (argc > 2) ? argv[2] : "test_basic_module";
|
||||
|
||||
// logos_core needs an absolute modules directory: it cannot read
|
||||
// plugin metadata from a relative path. Resolve it up front.
|
||||
@@ -300,24 +302,24 @@ sections:
|
||||
module (here, the one from the library we built).
|
||||
- `QT_QPA_PLATFORM=offscreen` — so Qt needs no display.
|
||||
|
||||
We point it at `./modules` and ask it to load `accounts_module`.
|
||||
We point it at `./modules` and ask it to load `test_basic_module`.
|
||||
steps:
|
||||
- title: "Load accounts_module through the C API"
|
||||
- title: "Load test_basic_module through the C API"
|
||||
run: |
|
||||
LOGOS_HOST_PATH="$PWD/liblogos/bin/logos_host" \
|
||||
QT_QPA_PLATFORM=offscreen \
|
||||
./embed-app/build/logos_embed_app ./modules accounts_module
|
||||
./embed-app/build/logos_embed_app ./modules test_basic_module
|
||||
code_block: |
|
||||
export LOGOS_HOST_PATH="$PWD/liblogos/bin/logos_host"
|
||||
export QT_QPA_PLATFORM=offscreen
|
||||
./embed-app/build/logos_embed_app ./modules accounts_module
|
||||
./embed-app/build/logos_embed_app ./modules test_basic_module
|
||||
expect_contains:
|
||||
- "Module loaded: capability_module"
|
||||
- "Module loaded: accounts_module"
|
||||
- "Module loaded: test_basic_module"
|
||||
- "Load OK"
|
||||
post_text: |
|
||||
The output shows the runtime starting, discovering both modules,
|
||||
bringing up `capability_module`, then loading `accounts_module` (a real
|
||||
bringing up `capability_module`, then loading `test_basic_module` (a real
|
||||
subprocess launched via `logos_host` and wired up over liblogos' IPC):
|
||||
|
||||
```
|
||||
@@ -326,13 +328,13 @@ sections:
|
||||
Module loaded: capability_module
|
||||
Discovered modules:
|
||||
- capability_module
|
||||
- accounts_module
|
||||
Loading 'accounts_module' (with dependencies)...
|
||||
Module loaded: accounts_module
|
||||
- test_basic_module
|
||||
Loading 'test_basic_module' (with dependencies)...
|
||||
Module loaded: test_basic_module
|
||||
Load OK
|
||||
Loaded modules:
|
||||
- capability_module
|
||||
- accounts_module
|
||||
- test_basic_module
|
||||
```
|
||||
|
||||
That is your own program — not the `logoscore` CLI — running a real
|
||||
@@ -343,7 +345,7 @@ sections:
|
||||
text: |
|
||||
The C API loads and manages modules; it does not call their methods (that
|
||||
goes over the typed IPC bridge, which the frontends wrap). To see what
|
||||
`accounts_module` exposes, introspect the installed plugin with `lm`, the
|
||||
`test_basic_module` exposes, introspect the installed plugin with `lm`, the
|
||||
module inspector from [`logos-module`](https://github.com/logos-co/logos-module).
|
||||
steps:
|
||||
- title: "Build lm"
|
||||
@@ -351,10 +353,10 @@ sections:
|
||||
check_file: "lm/bin/lm"
|
||||
|
||||
- title: "List the module's invokable methods"
|
||||
run: "./lm/bin/lm methods ./modules/accounts_module/accounts_module_plugin.{ext}"
|
||||
code_block: "lm methods ./modules/accounts_module/accounts_module_plugin.{ext}"
|
||||
run: "./lm/bin/lm methods ./modules/test_basic_module/test_basic_module_plugin.{ext}"
|
||||
code_block: "lm methods ./modules/test_basic_module/test_basic_module_plugin.{ext}"
|
||||
expect_contains:
|
||||
- "createRandomMnemonic"
|
||||
- "addInts"
|
||||
post_text: |
|
||||
These are the `Q_INVOKABLE` methods the module you just loaded exposes —
|
||||
the entry points a frontend would call over the IPC bridge once the
|
||||
|
||||
@@ -12,18 +12,18 @@ intro: |
|
||||
commit under test** — so the runtime you exercise is built against the code
|
||||
in this repository, not the latest published release.
|
||||
2. Build the `lgpm` local package manager.
|
||||
3. Build the real [`accounts_module`](https://github.com/logos-co/logos-accounts-module)
|
||||
3. Build [`test_basic_module`](https://github.com/logos-co/logos-test-modules)
|
||||
as an `.lgx` package straight from its own flake, and install it into a
|
||||
`./modules` directory with `lgpm`.
|
||||
4. Start `logoscore` in daemon mode (`-D`), load `accounts_module`, introspect
|
||||
it, and call one of its methods — verifying the module actually runs on top
|
||||
4. Start `logoscore` in daemon mode (`-D`), load `test_basic_module`, introspect
|
||||
it, and call two of its methods — verifying the module actually runs on top
|
||||
of this liblogos.
|
||||
|
||||
Because every layer (host, module loader, IPC) comes from the liblogos commit
|
||||
under test, a green run is real evidence that this change keeps the module
|
||||
runtime working.
|
||||
|
||||
what_you_build: "The real `accounts_module`, installed with `lgpm` and called through a `logoscore` daemon running on this liblogos commit."
|
||||
what_you_build: "A real module — `test_basic_module` — installed with `lgpm` and called through a `logoscore` daemon running on this liblogos commit."
|
||||
|
||||
what_you_learn:
|
||||
- How to build `logoscore` against a specific `logos-liblogos` commit via `--override-input`
|
||||
@@ -41,7 +41,6 @@ prerequisites:
|
||||
```
|
||||
|
||||
Verify: `nix flake --help >/dev/null 2>&1 && echo "Flakes enabled"`
|
||||
- "**git** — to clone the module repository."
|
||||
- "A Linux or macOS machine."
|
||||
|
||||
sections:
|
||||
@@ -56,11 +55,18 @@ sections:
|
||||
> runner expands a release placeholder on it to a concrete ref. Locally that
|
||||
> is this checkout's `HEAD` (see `run.sh`); in CI it is the commit being
|
||||
> tested. With no pin it falls back to latest `master`.
|
||||
|
||||
> The CLI itself tracks `master`, deliberately. Only `logos-liblogos` is
|
||||
> overridden, so everything else in the closure must be a revision that
|
||||
> liblogos' current runtime pairs with — the shared-runtime split landed as
|
||||
> one pin set across logos-protocol, logos-plugin-qt, logos-liblogos and
|
||||
> this CLI, and an older CLI rev pinned here silently reintroduces a second
|
||||
> copy of the runtime in the process.
|
||||
steps:
|
||||
- title: "Build the CLI with the liblogos override"
|
||||
run: "nix build 'github:logos-co/logos-logoscore-cli/b92ade06cdbd3cdf48c8de5b8375cbcc3a6088cf' --override-input logos-liblogos 'github:logos-co/logos-liblogos{release}' --out-link ./logos"
|
||||
run: "nix build 'github:logos-co/logos-logoscore-cli' --override-input logos-liblogos 'github:logos-co/logos-liblogos{release}' --out-link ./logos"
|
||||
code_block: |
|
||||
nix build 'github:logos-co/logos-logoscore-cli/b92ade06cdbd3cdf48c8de5b8375cbcc3a6088cf' \
|
||||
nix build 'github:logos-co/logos-logoscore-cli' \
|
||||
--override-input logos-liblogos 'github:logos-co/logos-liblogos' \
|
||||
--out-link ./logos
|
||||
check_file: "logos/bin/logoscore"
|
||||
@@ -84,39 +90,36 @@ sections:
|
||||
check_file: "lgpm/bin/lgpm"
|
||||
post_text: "The executable is at `./lgpm/bin/lgpm`."
|
||||
|
||||
- title: "Build and install the accounts module"
|
||||
- title: "Build and install a module"
|
||||
step: true
|
||||
text: |
|
||||
Clone [`logos-accounts-module`](https://github.com/logos-co/logos-accounts-module),
|
||||
build its `.lgx` straight from its flake's `#lgx` output, and install it
|
||||
into a local `./modules` directory with `lgpm`. Every module built with
|
||||
Build [`test_basic_module`](https://github.com/logos-co/logos-test-modules)'s
|
||||
`.lgx` straight from its flake and install it into a local `./modules`
|
||||
directory with `lgpm`. Every module built with
|
||||
[`logos-module-builder`](https://github.com/logos-co/logos-module-builder)
|
||||
exposes a ready-to-install `#lgx`.
|
||||
exposes a ready-to-install `lgx` output.
|
||||
steps:
|
||||
- title: "Clone the module"
|
||||
text: |
|
||||
We clone over HTTPS so the step works in CI; over SSH the URL is
|
||||
`git@github.com:logos-co/logos-accounts-module.git`.
|
||||
run: "git clone --depth 1 https://github.com/logos-co/logos-accounts-module.git"
|
||||
check_file: "logos-accounts-module/flake.nix"
|
||||
|
||||
- title: "Build the module's .lgx"
|
||||
text: |
|
||||
Build the `#lgx` output and link it as `./accounts-lgx`. (This compiles
|
||||
the module and its SDK dependencies through Nix, so the first build is
|
||||
slow.)
|
||||
run: "nix build 'path:./logos-accounts-module#lgx' -o accounts-lgx"
|
||||
`logos-test-modules` publishes each of its modules under
|
||||
`modules.<system>.<name>`, so the attribute path carries the Nix system
|
||||
double — `builtins.currentSystem` supplies it. Link the result as
|
||||
`./module-lgx`.
|
||||
run: |
|
||||
SYSTEM=$(nix eval --impure --raw --expr 'builtins.currentSystem')
|
||||
nix build "github:logos-co/logos-test-modules#modules.$SYSTEM.test_basic_module.lgx" -o module-lgx
|
||||
code_block: |
|
||||
# From inside the clone this is simply: nix build '.#lgx'
|
||||
nix build 'path:./logos-accounts-module#lgx' -o accounts-lgx
|
||||
post_text: "The `.lgx` package is now under `./accounts-lgx/`:"
|
||||
# From inside a single-module repo this is simply: nix build '.#lgx'
|
||||
SYSTEM=$(nix eval --impure --raw --expr 'builtins.currentSystem')
|
||||
nix build "github:logos-co/logos-test-modules#modules.$SYSTEM.test_basic_module.lgx" -o module-lgx
|
||||
post_text: "The `.lgx` package is now under `./module-lgx/`:"
|
||||
extra_run:
|
||||
run: "ls accounts-lgx/*.lgx"
|
||||
run: "ls module-lgx/*.lgx"
|
||||
|
||||
- title: "Seed the modules directory with the bundled capability module"
|
||||
text: |
|
||||
`accounts_module` is loaded through the host's capability layer, so the
|
||||
modules directory also needs the `capability_module` that ships with
|
||||
Modules are loaded through the host's capability layer, so the modules
|
||||
directory also needs the `capability_module` that ships with
|
||||
`logoscore`. Copy it across first.
|
||||
run: |
|
||||
mkdir -p modules
|
||||
@@ -125,10 +128,10 @@ sections:
|
||||
|
||||
- title: "Install the .lgx with lgpm"
|
||||
text: |
|
||||
Install the freshly-built package into `./modules`. `accounts_module` is
|
||||
a `core` module, so it goes to `--modules-dir`. The package is unsigned
|
||||
(a local dev build), so we pass `--allow-unsigned`.
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file accounts-lgx/*.lgx"
|
||||
Install the freshly-built package into `./modules`. `test_basic_module`
|
||||
is a `core` module, so it goes to `--modules-dir`. The package is
|
||||
unsigned (a local dev build), so we pass `--allow-unsigned`.
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file module-lgx/*.lgx"
|
||||
expect_contains:
|
||||
- "Installed to:"
|
||||
|
||||
@@ -136,14 +139,14 @@ sections:
|
||||
text: "Scan the directory and confirm the module landed:"
|
||||
run: "./lgpm/bin/lgpm --modules-dir ./modules list"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
check_file: "modules/accounts_module/manifest.json"
|
||||
- "test_basic_module"
|
||||
check_file: "modules/test_basic_module/manifest.json"
|
||||
|
||||
- title: "Run the daemon and call the module"
|
||||
step: true
|
||||
text: |
|
||||
Start `logoscore` in daemon mode pointed at `./modules`, then use the client
|
||||
subcommands to load `accounts_module`, introspect it, and call one of its
|
||||
subcommands to load `test_basic_module`, introspect it, and call two of its
|
||||
methods. Daemon output is captured in `logs.txt`.
|
||||
steps:
|
||||
- title: "Start the daemon"
|
||||
@@ -168,18 +171,18 @@ sections:
|
||||
code_block: "logoscore status"
|
||||
|
||||
- title: "List discovered modules"
|
||||
text: "`accounts_module` should be visible in the scan directory:"
|
||||
text: "`test_basic_module` should be visible in the scan directory:"
|
||||
run: "./logos/bin/logoscore list-modules"
|
||||
code_block: "logoscore list-modules"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
- "test_basic_module"
|
||||
|
||||
- title: "Load the module"
|
||||
text: "Load `accounts_module` into the running daemon:"
|
||||
run: "./logos/bin/logoscore load-module accounts_module"
|
||||
code_block: "logoscore load-module accounts_module"
|
||||
text: "Load `test_basic_module` into the running daemon:"
|
||||
run: "./logos/bin/logoscore load-module test_basic_module"
|
||||
code_block: "logoscore load-module test_basic_module"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
- "test_basic_module"
|
||||
|
||||
- title: "Confirm the module is loaded"
|
||||
text: |
|
||||
@@ -188,39 +191,36 @@ sections:
|
||||
run: "./logos/bin/logoscore status"
|
||||
code_block: "logoscore status"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
- "test_basic_module"
|
||||
- '"status":"loaded"'
|
||||
|
||||
- title: "Introspect the module with module-info"
|
||||
text: |
|
||||
`module-info` lists the `Q_INVOKABLE` methods the module exposes — the
|
||||
`module-info` lists the methods and events the module exposes — the
|
||||
same methods you can `call`:
|
||||
run: "./logos/bin/logoscore module-info accounts_module"
|
||||
code_block: "logoscore module-info accounts_module"
|
||||
run: "./logos/bin/logoscore module-info test_basic_module"
|
||||
code_block: "logoscore module-info test_basic_module"
|
||||
expect_contains:
|
||||
- "accounts_module"
|
||||
- "createRandomMnemonic"
|
||||
- "addInts"
|
||||
- "echo"
|
||||
|
||||
- title: "Call a method"
|
||||
text: |
|
||||
Generate a fresh 12-word BIP-39 mnemonic. `createRandomMnemonic` takes
|
||||
the word count and returns the phrase — a real round-trip through the
|
||||
go-wallet-sdk C library wrapped by the module, dispatched over liblogos'
|
||||
IPC:
|
||||
run: "./logos/bin/logoscore call accounts_module createRandomMnemonic 12"
|
||||
code_block: "logoscore call accounts_module createRandomMnemonic 12"
|
||||
`echo` returns its argument unchanged — a string round-trip out to the
|
||||
module subprocess and back over liblogos' IPC:
|
||||
run: "./logos/bin/logoscore call test_basic_module echo hello"
|
||||
code_block: "logoscore call test_basic_module echo hello"
|
||||
expect_contains:
|
||||
- '"result"'
|
||||
- '"result":"hello"'
|
||||
|
||||
- title: "Call a second method"
|
||||
text: |
|
||||
`lengthToEntropyStrength` maps a mnemonic word count to its entropy
|
||||
strength in bits — 12 words is 128 bits. This exercises an `int`
|
||||
round-trip:
|
||||
run: "./logos/bin/logoscore call accounts_module lengthToEntropyStrength 12"
|
||||
code_block: "logoscore call accounts_module lengthToEntropyStrength 12"
|
||||
`addInts` adds its two arguments. This exercises an `int` round-trip,
|
||||
where `echo` exercised a string:
|
||||
run: "./logos/bin/logoscore call test_basic_module addInts 40 2"
|
||||
code_block: "logoscore call test_basic_module addInts 40 2"
|
||||
expect_contains:
|
||||
- '"result":128'
|
||||
- '"result":42'
|
||||
|
||||
- title: "Stop the daemon"
|
||||
text: "Shut the daemon down cleanly:"
|
||||
|
||||
@@ -15,10 +15,10 @@ program**, built against **this** liblogos commit:
|
||||
under test.
|
||||
2. Build the `lgpm` package manager and install two real modules
|
||||
([`capability_module`](https://github.com/logos-co/logos-capability-module)
|
||||
and [`accounts_module`](https://github.com/logos-co/logos-accounts-module))
|
||||
and [`test_basic_module`](https://github.com/logos-co/logos-test-modules))
|
||||
into a local modules directory.
|
||||
3. Write a ~50-line C++ program that links `liblogos_core`, then calls the C
|
||||
API to start the runtime and load `accounts_module`.
|
||||
API to start the runtime and load `test_basic_module`.
|
||||
4. Build that program against this liblogos and run it — watching the module
|
||||
come up over liblogos' own IPC.
|
||||
|
||||
@@ -33,7 +33,7 @@ an embeddable library, not just through the `logoscore` frontend.
|
||||
> as `logoscore` and basecamp do. You do **not** need to run Qt's event loop;
|
||||
> the load calls are synchronous.
|
||||
|
||||
**What you'll build:** A standalone C++ program that links `liblogos_core` from this commit and loads the real `accounts_module` through the C API.
|
||||
**What you'll build:** A standalone C++ program that links `liblogos_core` from this commit and loads a real module — `test_basic_module` — through the C API.
|
||||
|
||||
**What you'll learn:**
|
||||
|
||||
@@ -82,7 +82,7 @@ header, and the `logos_host` binary.
|
||||
### 1.1 Build the library
|
||||
|
||||
```bash
|
||||
nix build 'github:logos-co/logos-liblogos/5f8139723702a8fff7eee6ae20c042be1c72159f' -o ./liblogos
|
||||
nix build 'github:logos-co/logos-liblogos' -o ./liblogos
|
||||
```
|
||||
|
||||
The result has three things your program depends on:
|
||||
@@ -104,8 +104,8 @@ ls liblogos/include/logos_core.h liblogos/lib/liblogos_core.dylib liblogos/bin/l
|
||||
|
||||
The runtime discovers modules from a directory of installed packages. We
|
||||
build the `lgpm` package manager and two real modules' `.lgx` packages,
|
||||
then install them in the next step. `accounts_module` is loaded through the
|
||||
host's capability layer, so we install `capability_module` alongside it.
|
||||
then install them in the next step. `test_basic_module` is loaded through
|
||||
the host's capability layer, so we install `capability_module` alongside it.
|
||||
|
||||
### 2.1 Build lgpm
|
||||
|
||||
@@ -127,20 +127,22 @@ The `.lgx` package is under `./cap-lgx/`:
|
||||
ls cap-lgx/*.lgx
|
||||
```
|
||||
|
||||
### 2.3 Build the accounts module's .lgx
|
||||
### 2.3 Build the test module's .lgx
|
||||
|
||||
This compiles the module and its SDK dependencies through Nix (the
|
||||
accounts module wraps the go-wallet-sdk C library), so the first build
|
||||
is slow.
|
||||
`logos-test-modules` publishes each of its modules under
|
||||
`modules.<system>.<name>`, so the attribute path carries the Nix system
|
||||
double — `builtins.currentSystem` supplies it.
|
||||
|
||||
```bash
|
||||
nix build 'github:logos-co/logos-accounts-module#lgx' -o accounts-lgx
|
||||
SYSTEM=$(nix eval --impure --raw --expr 'builtins.currentSystem')
|
||||
nix build "github:logos-co/logos-test-modules#modules.$SYSTEM.test_basic_module.lgx" -o module-lgx
|
||||
|
||||
```
|
||||
|
||||
The `.lgx` package is under `./accounts-lgx/`:
|
||||
The `.lgx` package is under `./module-lgx/`:
|
||||
|
||||
```bash
|
||||
ls accounts-lgx/*.lgx
|
||||
ls module-lgx/*.lgx
|
||||
```
|
||||
|
||||
---
|
||||
@@ -158,10 +160,10 @@ builds, so we pass `--allow-unsigned`.
|
||||
./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file cap-lgx/*.lgx
|
||||
```
|
||||
|
||||
### 3.2 Install accounts_module
|
||||
### 3.2 Install test_basic_module
|
||||
|
||||
```bash
|
||||
./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file accounts-lgx/*.lgx
|
||||
./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file module-lgx/*.lgx
|
||||
```
|
||||
|
||||
### 3.3 Confirm both modules are installed
|
||||
@@ -222,7 +224,7 @@ int main(int argc, char** argv) {
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
||||
const char* modulesArg = (argc > 1) ? argv[1] : "./modules";
|
||||
const char* moduleName = (argc > 2) ? argv[2] : "accounts_module";
|
||||
const char* moduleName = (argc > 2) ? argv[2] : "test_basic_module";
|
||||
|
||||
// logos_core needs an absolute modules directory: it cannot read
|
||||
// plugin metadata from a relative path. Resolve it up front.
|
||||
@@ -321,18 +323,18 @@ Run the program. It needs two things in the environment:
|
||||
module (here, the one from the library we built).
|
||||
- `QT_QPA_PLATFORM=offscreen` — so Qt needs no display.
|
||||
|
||||
We point it at `./modules` and ask it to load `accounts_module`.
|
||||
We point it at `./modules` and ask it to load `test_basic_module`.
|
||||
|
||||
### 6.1 Load accounts_module through the C API
|
||||
### 6.1 Load test_basic_module through the C API
|
||||
|
||||
```bash
|
||||
export LOGOS_HOST_PATH="$PWD/liblogos/bin/logos_host"
|
||||
export QT_QPA_PLATFORM=offscreen
|
||||
./embed-app/build/logos_embed_app ./modules accounts_module
|
||||
./embed-app/build/logos_embed_app ./modules test_basic_module
|
||||
```
|
||||
|
||||
The output shows the runtime starting, discovering both modules,
|
||||
bringing up `capability_module`, then loading `accounts_module` (a real
|
||||
bringing up `capability_module`, then loading `test_basic_module` (a real
|
||||
subprocess launched via `logos_host` and wired up over liblogos' IPC):
|
||||
|
||||
```
|
||||
@@ -341,13 +343,13 @@ Starting (modules dir: .../modules)
|
||||
Module loaded: capability_module
|
||||
Discovered modules:
|
||||
- capability_module
|
||||
- accounts_module
|
||||
Loading 'accounts_module' (with dependencies)...
|
||||
Module loaded: accounts_module
|
||||
- test_basic_module
|
||||
Loading 'test_basic_module' (with dependencies)...
|
||||
Module loaded: test_basic_module
|
||||
Load OK
|
||||
Loaded modules:
|
||||
- capability_module
|
||||
- accounts_module
|
||||
- test_basic_module
|
||||
```
|
||||
|
||||
That is your own program — not the `logoscore` CLI — running a real
|
||||
@@ -359,7 +361,7 @@ module on top of this liblogos.
|
||||
|
||||
The C API loads and manages modules; it does not call their methods (that
|
||||
goes over the typed IPC bridge, which the frontends wrap). To see what
|
||||
`accounts_module` exposes, introspect the installed plugin with `lm`, the
|
||||
`test_basic_module` exposes, introspect the installed plugin with `lm`, the
|
||||
module inspector from [`logos-module`](https://github.com/logos-co/logos-module).
|
||||
|
||||
### 7.1 Build lm
|
||||
@@ -371,7 +373,7 @@ nix build 'github:logos-co/logos-module#lm' -o lm
|
||||
### 7.2 List the module's invokable methods
|
||||
|
||||
```bash
|
||||
lm methods ./modules/accounts_module/accounts_module_plugin.dylib
|
||||
lm methods ./modules/test_basic_module/test_basic_module_plugin.dylib
|
||||
```
|
||||
|
||||
These are the `Q_INVOKABLE` methods the module you just loaded exposes —
|
||||
|
||||
@@ -9,18 +9,18 @@ end-to-end through the headless `logoscore` runtime:
|
||||
commit under test** — so the runtime you exercise is built against the code
|
||||
in this repository, not the latest published release.
|
||||
2. Build the `lgpm` local package manager.
|
||||
3. Build the real [`accounts_module`](https://github.com/logos-co/logos-accounts-module)
|
||||
3. Build [`test_basic_module`](https://github.com/logos-co/logos-test-modules)
|
||||
as an `.lgx` package straight from its own flake, and install it into a
|
||||
`./modules` directory with `lgpm`.
|
||||
4. Start `logoscore` in daemon mode (`-D`), load `accounts_module`, introspect
|
||||
it, and call one of its methods — verifying the module actually runs on top
|
||||
4. Start `logoscore` in daemon mode (`-D`), load `test_basic_module`, introspect
|
||||
it, and call two of its methods — verifying the module actually runs on top
|
||||
of this liblogos.
|
||||
|
||||
Because every layer (host, module loader, IPC) comes from the liblogos commit
|
||||
under test, a green run is real evidence that this change keeps the module
|
||||
runtime working.
|
||||
|
||||
**What you'll build:** The real `accounts_module`, installed with `lgpm` and called through a `logoscore` daemon running on this liblogos commit.
|
||||
**What you'll build:** A real module — `test_basic_module` — installed with `lgpm` and called through a `logoscore` daemon running on this liblogos commit.
|
||||
|
||||
**What you'll learn:**
|
||||
|
||||
@@ -40,7 +40,6 @@ echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf
|
||||
|
||||
Verify: `nix flake --help >/dev/null 2>&1 && echo "Flakes enabled"`
|
||||
|
||||
- **git** — to clone the module repository.
|
||||
- A Linux or macOS machine.
|
||||
|
||||
---
|
||||
@@ -56,10 +55,17 @@ than the latest release. The result is symlinked to `./logos/`.
|
||||
> is this checkout's `HEAD` (see `run.sh`); in CI it is the commit being
|
||||
> tested. With no pin it falls back to latest `master`.
|
||||
|
||||
> The CLI itself tracks `master`, deliberately. Only `logos-liblogos` is
|
||||
> overridden, so everything else in the closure must be a revision that
|
||||
> liblogos' current runtime pairs with — the shared-runtime split landed as
|
||||
> one pin set across logos-protocol, logos-plugin-qt, logos-liblogos and
|
||||
> this CLI, and an older CLI rev pinned here silently reintroduces a second
|
||||
> copy of the runtime in the process.
|
||||
|
||||
### 1.1 Build the CLI with the liblogos override
|
||||
|
||||
```bash
|
||||
nix build 'github:logos-co/logos-logoscore-cli/b92ade06cdbd3cdf48c8de5b8375cbcc3a6088cf' \
|
||||
nix build 'github:logos-co/logos-logoscore-cli' \
|
||||
--override-input logos-liblogos 'github:logos-co/logos-liblogos' \
|
||||
--out-link ./logos
|
||||
```
|
||||
@@ -89,44 +95,37 @@ The executable is at `./lgpm/bin/lgpm`.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Build and install the accounts module
|
||||
## Step 3: Build and install a module
|
||||
|
||||
Clone [`logos-accounts-module`](https://github.com/logos-co/logos-accounts-module),
|
||||
build its `.lgx` straight from its flake's `#lgx` output, and install it
|
||||
into a local `./modules` directory with `lgpm`. Every module built with
|
||||
Build [`test_basic_module`](https://github.com/logos-co/logos-test-modules)'s
|
||||
`.lgx` straight from its flake and install it into a local `./modules`
|
||||
directory with `lgpm`. Every module built with
|
||||
[`logos-module-builder`](https://github.com/logos-co/logos-module-builder)
|
||||
exposes a ready-to-install `#lgx`.
|
||||
exposes a ready-to-install `lgx` output.
|
||||
|
||||
### 3.1 Clone the module
|
||||
### 3.1 Build the module's .lgx
|
||||
|
||||
We clone over HTTPS so the step works in CI; over SSH the URL is
|
||||
`git@github.com:logos-co/logos-accounts-module.git`.
|
||||
`logos-test-modules` publishes each of its modules under
|
||||
`modules.<system>.<name>`, so the attribute path carries the Nix system
|
||||
double — `builtins.currentSystem` supplies it. Link the result as
|
||||
`./module-lgx`.
|
||||
|
||||
```bash
|
||||
git clone --depth 1 https://github.com/logos-co/logos-accounts-module.git
|
||||
# From inside a single-module repo this is simply: nix build '.#lgx'
|
||||
SYSTEM=$(nix eval --impure --raw --expr 'builtins.currentSystem')
|
||||
nix build "github:logos-co/logos-test-modules#modules.$SYSTEM.test_basic_module.lgx" -o module-lgx
|
||||
```
|
||||
|
||||
### 3.2 Build the module's .lgx
|
||||
|
||||
Build the `#lgx` output and link it as `./accounts-lgx`. (This compiles
|
||||
the module and its SDK dependencies through Nix, so the first build is
|
||||
slow.)
|
||||
The `.lgx` package is now under `./module-lgx/`:
|
||||
|
||||
```bash
|
||||
# From inside the clone this is simply: nix build '.#lgx'
|
||||
nix build 'path:./logos-accounts-module#lgx' -o accounts-lgx
|
||||
ls module-lgx/*.lgx
|
||||
```
|
||||
|
||||
The `.lgx` package is now under `./accounts-lgx/`:
|
||||
### 3.2 Seed the modules directory with the bundled capability module
|
||||
|
||||
```bash
|
||||
ls accounts-lgx/*.lgx
|
||||
```
|
||||
|
||||
### 3.3 Seed the modules directory with the bundled capability module
|
||||
|
||||
`accounts_module` is loaded through the host's capability layer, so the
|
||||
modules directory also needs the `capability_module` that ships with
|
||||
Modules are loaded through the host's capability layer, so the modules
|
||||
directory also needs the `capability_module` that ships with
|
||||
`logoscore`. Copy it across first.
|
||||
|
||||
```bash
|
||||
@@ -135,17 +134,17 @@ cp -RL ./logos/modules/. ./modules/
|
||||
|
||||
```
|
||||
|
||||
### 3.4 Install the .lgx with lgpm
|
||||
### 3.3 Install the .lgx with lgpm
|
||||
|
||||
Install the freshly-built package into `./modules`. `accounts_module` is
|
||||
a `core` module, so it goes to `--modules-dir`. The package is unsigned
|
||||
(a local dev build), so we pass `--allow-unsigned`.
|
||||
Install the freshly-built package into `./modules`. `test_basic_module`
|
||||
is a `core` module, so it goes to `--modules-dir`. The package is
|
||||
unsigned (a local dev build), so we pass `--allow-unsigned`.
|
||||
|
||||
```bash
|
||||
./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file accounts-lgx/*.lgx
|
||||
./lgpm/bin/lgpm --modules-dir ./modules --allow-unsigned install --file module-lgx/*.lgx
|
||||
```
|
||||
|
||||
### 3.5 Confirm the install
|
||||
### 3.4 Confirm the install
|
||||
|
||||
Scan the directory and confirm the module landed:
|
||||
|
||||
@@ -158,7 +157,7 @@ Scan the directory and confirm the module landed:
|
||||
## Step 4: Run the daemon and call the module
|
||||
|
||||
Start `logoscore` in daemon mode pointed at `./modules`, then use the client
|
||||
subcommands to load `accounts_module`, introspect it, and call one of its
|
||||
subcommands to load `test_basic_module`, introspect it, and call two of its
|
||||
methods. Daemon output is captured in `logs.txt`.
|
||||
|
||||
### 4.1 Start the daemon
|
||||
@@ -195,7 +194,7 @@ logoscore status
|
||||
|
||||
### 4.4 List discovered modules
|
||||
|
||||
`accounts_module` should be visible in the scan directory:
|
||||
`test_basic_module` should be visible in the scan directory:
|
||||
|
||||
```bash
|
||||
logoscore list-modules
|
||||
@@ -203,10 +202,10 @@ logoscore list-modules
|
||||
|
||||
### 4.5 Load the module
|
||||
|
||||
Load `accounts_module` into the running daemon:
|
||||
Load `test_basic_module` into the running daemon:
|
||||
|
||||
```bash
|
||||
logoscore load-module accounts_module
|
||||
logoscore load-module test_basic_module
|
||||
```
|
||||
|
||||
### 4.6 Confirm the module is loaded
|
||||
@@ -220,32 +219,29 @@ logoscore status
|
||||
|
||||
### 4.7 Introspect the module with module-info
|
||||
|
||||
`module-info` lists the `Q_INVOKABLE` methods the module exposes — the
|
||||
`module-info` lists the methods and events the module exposes — the
|
||||
same methods you can `call`:
|
||||
|
||||
```bash
|
||||
logoscore module-info accounts_module
|
||||
logoscore module-info test_basic_module
|
||||
```
|
||||
|
||||
### 4.8 Call a method
|
||||
|
||||
Generate a fresh 12-word BIP-39 mnemonic. `createRandomMnemonic` takes
|
||||
the word count and returns the phrase — a real round-trip through the
|
||||
go-wallet-sdk C library wrapped by the module, dispatched over liblogos'
|
||||
IPC:
|
||||
`echo` returns its argument unchanged — a string round-trip out to the
|
||||
module subprocess and back over liblogos' IPC:
|
||||
|
||||
```bash
|
||||
logoscore call accounts_module createRandomMnemonic 12
|
||||
logoscore call test_basic_module echo hello
|
||||
```
|
||||
|
||||
### 4.9 Call a second method
|
||||
|
||||
`lengthToEntropyStrength` maps a mnemonic word count to its entropy
|
||||
strength in bits — 12 words is 128 bits. This exercises an `int`
|
||||
round-trip:
|
||||
`addInts` adds its two arguments. This exercises an `int` round-trip,
|
||||
where `echo` exercised a string:
|
||||
|
||||
```bash
|
||||
logoscore call accounts_module lengthToEntropyStrength 12
|
||||
logoscore call test_basic_module addInts 40 2
|
||||
```
|
||||
|
||||
### 4.10 Stop the daemon
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@
|
||||
# Two specs run, each exercising THIS liblogos commit a different way:
|
||||
# - liblogos-module-runtime.test.yaml — drives liblogos through the headless
|
||||
# `logoscore` CLI frontend (build logoscore against this liblogos, install
|
||||
# the accounts module, start the daemon, call methods).
|
||||
# test_basic_module, start the daemon, call methods).
|
||||
# - liblogos-as-a-library.test.yaml — embeds liblogos directly: builds
|
||||
# liblogos_core from this commit, compiles a small C++ program that links it,
|
||||
# installs modules with lgpm, and loads the accounts module through the C API.
|
||||
# installs modules with lgpm, and loads test_basic_module through the C API.
|
||||
#
|
||||
# The runner is the shared `doctest` CLI
|
||||
# (https://github.com/logos-co/logos-doctest), invoked directly via its flake.
|
||||
|
||||
Reference in New Issue
Block a user