mirror of
https://github.com/logos-co/logos-logoscore-cli.git
synced 2026-08-31 04:41:06 +00:00
* feat(access-policy): --access-policy enforce, and prove it on a real daemon
`--access-policy` already reached the runtime; what was missing was a way to
ask for deny-by-default without hand-writing JSON, and any evidence that it
works. The README actively said the opposite ("enforcement is not yet
implemented ... a no-op for now") — it has been enforced for a while.
resolveAccessPolicyArg moves out of main.cpp into daemon/access_policy_arg.
so it can be unit-tested, and gains one spelling: the literal `enforce`
expands to {"version":1,"mode":"enforce","restrictions":{}}. That is not a
second switch — `mode` is still the runtime's only switch — it is the bare
document that arms it. Checked before the file branch, so arming enforcement
can't depend on the daemon's working directory.
The integration tests are the point: same binaries, same modules, same call,
policy the only variable. test_ipc_module declares test_basic_module and
test_extlib_module; test_basic_module declares nothing.
no flag -> requestModule(test_basic_module, test_extlib_module) mints
enforce -> the same call is refused, and both names appear in the log
enforce -> requestModule(test_ipc_module, test_basic_module) still mints
The third is the one that matters; a change that refused everything would
pass the second on its own. The refusal is matched structurally rather than
by exact text because the two capability_module implementations in this tree
quote the names differently.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(qt-host): link the Qt host runtime from logos-plugin-qt, not logos-qt-sdk
logoscore's daemon and its in-process core service are built on LogosAPI,
LogosAPIProvider and LogosProviderObject. Those moved out of logos-qt-sdk
into logos-plugin-qt, which publishes them as the `logos-qt-host` package
with the CMake target logos-qt-host::logos_qt_host. Point at that target.
Those three headers were the ONLY thing this repo took from logos-qt-sdk —
it emits no Qt consumer wrappers, ships no UI plugin, and never touches
logos_qt_lp_bridge.h or logos_ui_plugin_context.h — so the logos-qt-sdk
input is dropped outright rather than kept alongside. LOGOS_QT_SDK_ROOT
becomes LOGOS_QT_HOST_ROOT in all three derivations (build, tests,
buildPortable), and `--version` now reports the logos-plugin-qt commit.
Both new failure modes are hard errors, never silent skips: an unset
LOGOS_QT_HOST_ROOT is a FATAL_ERROR before find_package runs, and a
find_package that somehow does not define the imported target is a
FATAL_ERROR too.
logos-qt-host needs TokenManager::forIdentity/isolateIdentity, which
logos-protocol only grew on its per-client-token-store commit, so the
lock moves there. logos-plugin-qt is rev-pinned for now because
nix/qt-host.nix does not exist on its default branch yet.
Verified on aarch64-darwin: `nix build .#checks.aarch64-darwin.tests`
passes 21/21 with the committed lock and no overrides (same 21 as the
pre-change baseline), .#cli and .#cli-bundle-dir build, and the set of
LogosAPI/LogosAPIProvider/LogosProviderObject/qtArgDecode symbols in the
logoscore binary is identical to the pre-change build.
* chore(deps): re-pin the SDK stack onto the pushed b4 revs
Rebased onto master, so the inputs have to name the revs the rest of the b4
stack was actually pushed at rather than each input's default branch:
logos-cpp-sdk a04b2788 b3 codegen tip; a strict descendant of
cpp-sdk master, so forward-only
logos-protocol c8bab12 per-client token store — logos-qt-host
calls TokenManager::forIdentity, which
exists nowhere else
logos-plugin-qt cc24fa1 was 8ccb1fc. The superset branch that
logos-liblogos and logos-module-builder
also pin, so exactly ONE logos-qt-host
is in the closure — this CLI links it
directly AND through liblogos_core
logos-liblogos f2a15ef the liblogos built on that same qt-host
logos-capability-module 0cb33fb master, pinned explicitly — see below
All five are rev-pinned in the URL rather than left to the lock: every one is
a branch commit, so an unpinned url lets `nix flake update` silently relock
onto a default branch that does not build here.
capability_module deliberately does NOT move to the universal port (07dba1f).
That port declares metadata.json#host_services and fails closed until a host
calls logos_module_grant_host_services — and nothing in this stack calls it
yet (neither logos-liblogos nor logos-plugin-qt contains a single call site).
Built against it, the daemon's capability gate refuses EVERY requestModule
with "not granted the token_registry host service", so no module can call
another; the new access-policy integration test caught exactly that. 0cb33fb
is what logos-liblogos and logos-standalone-app lock too.
Verified on aarch64-darwin with the committed lock and no overrides:
.#checks.aarch64-darwin.tests-logosctl 191 + 25 + 21 tests, all PASSED
.#checks.aarch64-darwin.tests-logoscore 20 + 24 tests, all PASSED
.#checks.aarch64-darwin.tests built (exit 0)
.#packages.aarch64-darwin.{cli,ctl} built (exit 0)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(deps): rev-pin logos-test-modules at the b4 qt-host tip
The daemon-backed integration checks load these plugins into the daemon
this repo builds, so the two share one host runtime in one process image
-- the same constraint that already rev-pins logos-liblogos. a639b934
links the test modules against logos-qt-host rather than logos-qt-sdk and
carries the matching B4 stack pins; the previous lock sat on master
(f8077fab), which predates that repoint.
The URL had to change, not just the lock. The input was an UNPINNED url,
so it resolved to the default branch -- and f8077fab IS master's tip.
`nix flake update logos-test-modules` was therefore a silent no-op that
would leave the ten b4 commits behind while reporting success.
f8077fab is a strict ancestor of a639b934 (verified on a non-shallow
clone), so this is forward-only, not a lineage switch.
Two behaviour changes ride along and were checked against this repo's
assertions rather than assumed safe:
* test_basic_module and test_extlib_module migrate to
interface "universal". Neither declares metadata.json#host_services,
so the fail-closed gate that keeps logos-capability-module pinned off
its universal port does not apply here.
* stringLength now answers in CHARACTERS, not bytes. Every assertion
here is ASCII ("abcdef" -> 6), so the two agree.
The access-policy fixture still has its pair: test_ipc_module declares
[test_basic_module, test_extlib_module] and test_basic_module declares
none, so basic -> extlib stays undeclared.
Checks built by name, all exit 0: tests-logosctl, tests-logoscore,
tests. 281 tests, 0 failures, 0 skips.
* test: use test_ipc_new_api_module as the transitive-dependency fixture
These integration tests pick a module that DECLARES the other two, so one
load-module has to pull all three, and then request a token across that edge.
test_ipc_module was that fixture; it is being retired as a duplicate. Its
successor declares exactly the same dependency pair, so the fixture role
transfers unchanged.
Worth doing in the same breath as the retirement rather than after: these call
GTEST_SKIP() when the module is missing, so deleting the module out from under
them would not have turned anything red — the dependency-resolution and
token-request coverage would simply have stopped running.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(windows): refuse an unknown target instead of silently skipping it
`logos_use_shared_runtime_from_dll` empties the static archive of each named
IMPORTED target so the symbol resolves to liblogos_core.dll's exported copy
instead. It skipped any name that was not a target, which makes a typo or a
moved target silent — and the failure it hides is the duplicate-statics class:
the image keeps its own static copy of the shared runtime alongside the DLL's,
and PE has no interposition to collapse the two.
That hazard was already WRITTEN DOWN at basecamp's call site ("naming the old
target here would be a silent no-op … Windows would regress to the 29
'rejecting unauthorized call' lines this shim exists to prevent") — documented,
but not enforced. This enforces it.
Taken from feat/sdk-codegen-phase-a, which hardened its logoscore-cli copy and
never fixed basecamp's; feat/sdk-codegen-b3 has neither. It is the one place
where reconciling onto b3 would otherwise lose work, so both copies get it.
Behaviour is unchanged for every current caller: the function early-returns off
Windows, and both call sites pass the same two targets
(logos-qt-host::logos_qt_host, logos-protocol::logos_protocol) that phase-a's
hardened copy already accepts. x86_64-windows still evaluates (386 packages).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ci: use logos-co/setup-nix-cache-action for Nix setup and caching
Replaces the per-repo installer + cachix pair with the shared action, which
installs Nix with the Logos Attic cache (cache.nix.logos.co) preconfigured and
publishes what the job builds — master to the public cache, every other ref to
ci.
Each converted job also gains
environment: ${{ github.ref == 'refs/heads/master' && 'public-cache' || '' }}
because ATTIC_TOKEN_PUBLIC only exists inside that environment. Without it the
secret resolves empty on master and publishing is silently skipped — the job
still passes, so the omission would not show up as a failure.
The action installs Nix itself on every runner, macOS included. That is a
deliberate reversal of the workaround these files carried: the comments here
said cachix/install-nix-action collides with the runner's pre-existing _nixbld
users (eDSRecordAlreadyExists), so DeterminateSystems' installer was used
instead. It no longer reproduces — logos-delivery-module has already been
converted the plain way and its `build-and-test (macos-latest)` leg passes.
Keeping the workaround would have meant a second installer plus a duplicated
substituter/key block in ten files, guarding against something two green runs
say does not happen. If it ever recurs it fails loudly at install, which is
recoverable; the silent-skip above is the failure mode worth engineering
against.
One property is deliberately NOT carried over: the old cachix step ran with
`continue-on-error: true` so a failed cache push could not fail a job whose
tests passed. The action exposes no equivalent, and adding one here would also
swallow genuine setup failures now that the same step installs Nix rather than
only publishing at the end.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: drop references to removed generator flags and interfaces
README and docs described module authoring in terms of LogosProviderBase,
LOGOS_METHOD and --provider-header, none of which exist. Updated to the
universal model, keeping the retired shapes named as history.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(deps): track master for protocol, cpp-sdk and plugin-qt
logos-protocol#59, logos-cpp-sdk#138 and logos-plugin-qt#19 merged, so the three
rev pins bridging to them are retired, each with its rationale rewritten to name
the PR that closed the gap.
Left pinned: logos-liblogos, logos-capability-module and logos-test-modules —
their branches are still in flight and no merged upstream was confirmed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: delete[] the arrays liblogos allocates with new[], and clean up on error
Two defects on the logos_core_* seam, both live.
1. UNDEFINED BEHAVIOUR, 8 sites. logos_core_* hands back memory allocated with
new[], never malloc: module_manager.cpp's toNullTerminatedArray does
`new char*[]` plus a `new char[]` per element, and getModulesInfoCStr and
ProcessStats::getModuleStats each `new char[]`. This freed all of it with
free() — 6 sites in core_service_impl.cpp, 2 in package_ops.cpp. It happened
not to crash, which is the worst way for UB to behave.
logos-basecamp already gets this right and says so in a comment at
CoreModuleManager.cpp:31 ("delete[] is the correct deallocator — do NOT use
free()"). The same note now sits at this repo's first drain site.
2. TWO ERROR PATHS STRANDED THE MODULE SUBPROCESSES. daemon.cpp returns 1 at
what are now :627 and :685 — after logos_core_start() has launched the child
processes and before the logos_core_cleanup() at the end of the function.
Those are the only two returns between start and cleanup; both now clean up
first.
`nix build .#default` passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(deps): track capability_module master, now that the host grants it
This was held at 0cb33fb — the pre-universal Qt module — and the pin said why:
the `interface: "universal"` port declares metadata.json#host_services and fails
closed until a host calls logos_module_grant_host_services, which nothing in the
stack did. Under that build the capability gate refuses EVERY requestModule with
"not granted the token_registry host service", so no module can call another.
The condition it named has been met. logos-module-loader-qt#8 stamps the
hostServices property and calls the grant (module_initializer.cpp), #178 relocked
logos-liblogos onto it, and #94 brought that here — this closure resolves the
loader at acd07cf. capability_module master (c670f7f) is the universal port from
its #24.
Verified rather than inferred, because the failure mode here is SILENT: an
ungranted gate produces {"result":"","status":"ok"}, so a green build and a
running daemon prove nothing. Ran doctests/fullapi-chain.test.yaml, which stands
up a proxy module forwarding every call to another module — exactly the path the
gate controls:
Results: 20 passed, 0 failed, 0 skipped (of 20 run)
with no "not granted" and no empty results anywhere in the output.
This makes logoscore-cli the first consumer running the universal
capability_module outside a doctest fixture: #24's own doctests exercise it, but
through a closure built from this repo's master, which still pinned the old
module.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ci(windows): raise cold-derivation-budget to 60
The Windows cross-build failed the anti-cold-build guard at 32 derivations
against a default budget of 30, with:
32 derivations to build exceeds the budget.
This is what an unprimed mingw Qt closure looks like.
Fix: re-prime the cache, then re-run.
That remedy does not fit the number. The guard's own documentation puts a COLD
Windows CLI in this repo at 100 derivations and a warm incremental in single
digits, so 32 is a warm closure plus one dependency bump — here, the relocks
onto the host-services grant path. Running logos-basecamp's ~1.5 h staged prime
job for that would be treating a warm cache as an empty one.
60 lets an ordinary closure shift through while still catching a genuinely cold
build before it burns four hours.
This is safe to raise now because the repo has an Attic push token and the
reusable workflow forwards attic-token-ci / attic-token-public to
setup-nix-cache-action. The run that builds those derivations therefore PUSHES
them, so the next run drops back to single digits without anyone priming by
hand — the guard was blocking the very build that would have fixed the cache.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>