mirror of
https://github.com/logos-co/logos-protocol.git
synced 2026-08-30 21:41:10 +00:00
* test(token): pin that the caller's budget bounds the handshake, not just the call Written first and on its own commit so the red is on the record: against this parent it fails at ~20s, because the capability handshake ignores the caller's budget entirely. LogosAPIClient::invokeRemoteMethod takes a Timeout, but on an un-tokened target the handshake runs FIRST and LogosAPIConsumer::requestModule hardcodes 20000 twice -- once for the capability_module acquire, once for the requestModule call on it. A caller asking for 1500ms could therefore block on the order of 40s before the part it had actually bounded began. logos-view-module-runtime's callModule advertises a 1500ms bound on precisely this path. capability_module is deliberately NOT published, so the acquire runs its budget out rather than succeeding. Every other test in this file publishes it, which is how a hardcoded 20s survived alongside them: none of them ever entered the wait. The assertion is two-sided on purpose. An upper bound alone would pass if something made the acquire return instantly -- leaving the hardcoded 20s in place and the test green for the wrong reason, which is the exact shape of two earlier tests in this change set that passed in both directions. So: >= budget-200ms proves the timeout path actually ran; < 4x budget proves it was the CALLER's budget and not the 20s default. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: make the caller's timeout bound the token handshake, not just the call requestModule gains a timeoutMs parameter (defaulted to today's 20000, so every existing caller is source-compatible and unchanged), and LogosAPIClient threads its caller's Timeout through mintAndCacheToken into it. The budget bounds the WHOLE handshake -- the capability_module acquire plus the requestModule call on it share one deadline, rather than each getting a fresh copy. Halving it would be arbitrary; giving each the full amount would make the worst case twice what the caller asked for. What is left after the acquire is never allowed to reach 0, because some transports read 0 as "no timeout" and an exhausted budget must not silently become an unbounded wait. Also corrects a comment that argued the handshake-refusal fallthrough was safe because "capability_module passes 3000 ms". It does not: capability_module reaches informModuleToken_module through its FOUR-argument overload (capability_module_plugin.cpp:112), so timeoutMs takes the header's 20 s default. The bound is real, it is just not short -- and the code should say the true thing about why it is safe. Not covered here: the ASYNC first-call path still acquires capability_module through invokeRemoteMethodAsync without threading a budget. It does not block the caller, so it is a different defect with a different fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>