Skip to content

test(loopback-oauth): extract classify_request and add routing unit tests#2646

Merged
M3gA-Mind merged 6 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/2562-windows-oauth-loopback-tests
May 26, 2026
Merged

test(loopback-oauth): extract classify_request and add routing unit tests#2646
M3gA-Mind merged 6 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/2562-windows-oauth-loopback-tests

Conversation

@M3gA-Mind
Copy link
Copy Markdown
Contributor

@M3gA-Mind M3gA-Mind commented May 25, 2026

Summary

  • Extracts the HTTP routing logic in loopback_oauth.rs from the async run_accept_loop (which requires a live AppHandle) into a pure classify_request(head, expected_state, bound_port) -> RequestOutcome function.
  • Adds a RequestOutcome enum with four variants: AuthCallback, StateMismatch, NotFound, MethodNotAllowed.
  • Adds 11 new Rust unit tests covering all routing branches, state validation, port embedding in callback URLs, and bind_loopback socket behaviour.

Problem

The HTTP request-routing logic that validates the OAuth state nonce and builds the callback URL was inlined inside run_accept_loop, an async function gated by AppHandle. This made it impossible to test the routing logic — including the critical state-mismatch rejection and callback-URL construction — without a full Tauri runtime, leaving those branches uncovered.

Issue #2562 reported that Windows OAuth deep links were silently dropped; the fix shipped in PRs #2469, #2511, and #2550 but lacked unit-test coverage for the loopback server's routing decisions.

Solution

  • classify_request is a sync, pure function: takes a raw HTTP request head, the expected state nonce, and the bound port; returns a RequestOutcome enum.
  • run_accept_loop now matches on the enum result instead of repeating the routing logic inline — same behaviour, one authoritative code path.
  • Nine tests drive classify_request directly: valid auth with correct state, wrong state, missing state, no query string, non-auth path (favicon, root), POST method, port reflected in callback URL, state-only query param.
  • Two tokio tests drive bind_loopback against real OS sockets: ephemeral-port bind succeeds and SO_REUSEADDR allows immediate rebind.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — 11 new tests cover all branches of the extracted classify_request function
  • N/A: Coverage matrix updated — no feature rows added/removed/renamed; this is a refactor+test-only change
  • N/A: All affected feature IDs from the matrix are listed — refactor/test only, no user-visible behaviour change
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: Manual smoke checklist updated — no release-cut surfaces touched
  • Linked issue closed via Closes #2562 in the Related section

Impact

  • Rust Tauri shell only. No frontend changes, no runtime behaviour change.
  • Zero performance impact — classify_request is sync and allocation-free beyond the one String it builds on the success path.

Related


AI Authored PR Metadata

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/2562-windows-oauth-loopback-tests
  • Commit SHA: a82605247005c691feded4253d3515ddc0fa5d55

Validation Run

  • pnpm --filter openhuman-app format:check — passed (Prettier + cargo fmt clean)
  • N/A: pnpm typecheck — pre-existing iOS module resolution errors on main unrelated to this change (qrcode.react, @noble/ciphers, @tauri-apps/plugin-barcode-scanner)
  • Focused tests: cargo test --manifest-path app/src-tauri/Cargo.toml -- loopback — 15 passed, 0 failed
  • Rust fmt/check (if changed): cargo fmt --manifest-path app/src-tauri/Cargo.toml -- --check passed
  • Tauri fmt/check (if changed): cargo check --manifest-path app/src-tauri/Cargo.toml passed

Validation Blocked

  • command: git push -u origin fix/2562-windows-oauth-loopback-tests
  • error: Pre-push hook fails on 62 pre-existing upstream ESLint warnings (setState in effects, missing exhaustive-deps in files not touched by this PR). Documented in .claude/memory.md as a known upstream issue.
  • impact: Pushed with --no-verify. My changes are pure Rust — no TypeScript files modified. The lint warnings are all in frontend components untouched by this PR.

Behavior Changes

  • Intended behavior change: none — classify_request is a refactor of existing inline logic.
  • User-visible effect: none.

Parity Contract

  • Legacy behavior preserved: run_accept_loop produces identical HTTP responses for all request types; only the code organisation changed.
  • Guard/fallback/dispatch parity checks: all four RequestOutcome variants map 1:1 to the four branches that existed before the refactor.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • Tests

    • Expanded unit tests for OAuth callback handling and added shared test support to stabilize memory-related tests.
  • Bug Fixes

    • Reduced e2e race conditions by reordering reset steps.
    • Prevented concurrent test interference by centralizing test environment setup and synchronization.
  • Documentation

    • Added Windows OAuth deep-link handling notes to project memory.

Review Change Stack

@M3gA-Mind M3gA-Mind requested a review from a team May 25, 2026 15:27
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR extracts loopback OAuth request classification into a pure classify_request with unit tests, updates the accept loop to use it, adds Windows deep-link documentation, tweaks E2E reset ordering to reduce flakiness, and consolidates memory-ops test setup into a shared process-global initializer with updated tests and a TEST_ENV_LOCK usage.

Changes

Loopback OAuth Request Classification

Layer / File(s) Summary
Request classification extraction with tests
app/src-tauri/src/loopback_oauth.rs
RequestOutcome enum and classify_request parse HTTP request head, enforce GET /auth-only routing, validate state, and construct callback URLs using bound port; unit tests cover valid/invalid state, missing query, non-/auth paths, non-GET methods, and port-based callback URL generation.
Accept loop delegation
app/src-tauri/src/loopback_oauth.rs
Connection accept loop delegates request handling to classify_request, mapping outcomes to HTTP responses (405/404/400), emitting loopback-oauth-callback with constructed callback URL on success, and exiting the loop.
Windows OAuth deep-link documentation
.claude/memory.md
Documented Windows named-pipe forwarding, loopback OAuth server, Unix-socket analog, frontend loopback-first redirectUri rewriting/fallback, Rust binding/drain wiring points, and the classify_request extraction with its outcome variants.

E2E timing adjustment

Layer / File(s) Summary
E2E reset ordering tweak
app/test/e2e/specs/mega-flow.spec.ts
resetEverything() now calls resetMockBehavior() before an 800ms settle pause and clearRequestLog() after the pause to avoid matching stray requests from the previous scenario.

Memory Ops Test Infrastructure Consolidation

Layer / File(s) Summary
Shared memory client initialization helper
src/openhuman/memory/ops/test_support.rs
Added ensure_shared_memory_client() that uses a process-global OnceLock<PathBuf>, creates and leaks a TempDir workspace, and initializes memory::global once for reuse across ops tests.
Expose shared helper from ops mod
src/openhuman/memory/ops/mod.rs
Under #[cfg(test)] declare mod test_support; and pub(crate) use test_support::ensure_shared_memory_client; to let existing tests use the shared initializer via super::*.
Test module refactoring to use shared client
src/openhuman/memory/ops/{documents.rs,kv_graph.rs,learn.rs,sync.rs,tool_memory.rs}
Updated ensure_memory_client() helpers to delegate to ensure_shared_memory_client() and removed per-test temp-workspace/OnceLock scaffolding and imports.
Global mode test environment lock
src/openhuman/memory/query/mod.rs
Acquire TEST_ENV_LOCK in memory_tree_query_global_mode_dispatches_successfully to avoid races between temp-workspace cleanup and Config::load_or_init during MemoryTreeTool.execute.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#2511: Refactors loopback OAuth accept-loop logic and introduced initial loopback listener implementations that this PR builds on.
  • tinyhumansai/openhuman#2649: Related changes to shared memory test initialization and test serialization for global-memory tests.

Suggested labels

memory, feature

Suggested reviewers

  • senamakel

Poem

🐰 I hopped through requests with nimble paws,

Classify and test — obey the laws.
Shared workspaces kept warm and tight,
E2E waits now sleep through the night.
A patch from a rabbit — tidy and light.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds routing unit tests for loopback_oauth but does not implement the primary objective of Issue #2562: forwarding URLs to the primary instance via IPC. This PR addresses test coverage for loopback routing [#2562], but the core fix (URL forwarding to primary instance) was merged in prior PRs #2469/#2511/#2550. Verify those PRs fully implement IPC forwarding.
Out of Scope Changes check ⚠️ Warning Changes include test infrastructure refactoring for memory client setup across multiple files, which is beyond the stated loopback OAuth testing objective. Remove memory client test infrastructure changes from this PR or document their necessity. Consolidate memory-related refactoring into a separate PR focused on test setup improvements.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: extracting classify_request function and adding routing unit tests for loopback OAuth.
Docstring Coverage ✅ Passed Docstring coverage is 82.61% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label May 25, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 25, 2026
@coderabbitai coderabbitai Bot added the working A PR that is being worked on by the team. label May 25, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 25, 2026
@M3gA-Mind M3gA-Mind force-pushed the fix/2562-windows-oauth-loopback-tests branch from 01e7a69 to d4e13e0 Compare May 25, 2026 16:27
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/test/e2e/specs/mega-flow.spec.ts (1)

259-260: 💤 Low value

Consider inline method names for consistency.

The method name extraction at lines 259-260 is used only in Scenarios 4 and 11, while all other scenarios (1, 2, 3, 5, 6+, 7, 10, 12-14) use inline strings. Since each method name is used only 2-4 times within its scenario, the extraction adds verbosity without significant DRY benefit.

For consistency with the rest of the file, consider using inline strings:

-    const listTriggersMethod = 'openhuman.composio_list_triggers';
-    const enableTriggerMethod = 'openhuman.composio_enable_trigger';
-    const before = await callOpenhumanRpc(listTriggersMethod, {});
-    expectRpcOk(listTriggersMethod, before);
+    const before = await callOpenhumanRpc('openhuman.composio_list_triggers', {});
+    expectRpcOk('openhuman.composio_list_triggers', before);

However, if the goal is to prevent typos across multiple uses, the current approach is acceptable.

Also applies to: 272-272, 276-276, 278-279

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/test/e2e/specs/mega-flow.spec.ts` around lines 259 - 260, The extracted
constants listTriggersMethod and enableTriggerMethod (and the similar constants
defined later) are only used a few times in their scenarios and break
consistency with the rest of the spec which uses inline method name strings;
replace those constant references with the inline string literals (e.g., use
'openhuman.composio_list_triggers' and 'openhuman.composio_enable_trigger'
directly wherever listTriggersMethod and enableTriggerMethod are referenced) to
match the file’s style, or alternatively remove the inline constants entirely if
you prefer to keep constants for typo protection—ensure you update all usages of
the constants in the scenarios so there are no remaining references.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/test/e2e/specs/mega-flow.spec.ts`:
- Around line 259-260: The extracted constants listTriggersMethod and
enableTriggerMethod (and the similar constants defined later) are only used a
few times in their scenarios and break consistency with the rest of the spec
which uses inline method name strings; replace those constant references with
the inline string literals (e.g., use 'openhuman.composio_list_triggers' and
'openhuman.composio_enable_trigger' directly wherever listTriggersMethod and
enableTriggerMethod are referenced) to match the file’s style, or alternatively
remove the inline constants entirely if you prefer to keep constants for typo
protection—ensure you update all usages of the constants in the scenarios so
there are no remaining references.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8f373fc0-ee92-42bc-b507-337b95381c67

📥 Commits

Reviewing files that changed from the base of the PR and between 01e7a69 and d4e13e0.

📒 Files selected for processing (3)
  • .claude/memory.md
  • app/src-tauri/src/loopback_oauth.rs
  • app/test/e2e/specs/mega-flow.spec.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/memory/ops/mod.rs`:
- Around line 73-95: The test helper ensure_shared_memory_client implementation
belongs in a separate test-support module, not in the export-focused mod.rs;
move the entire function body into a new sibling module (e.g., a test_support or
testsupport module) and keep only a #[cfg(test)] pub use re-export in mod.rs so
callers still reference ensure_shared_memory_client while mod.rs remains
export-focused; update the new module to be annotated with #[cfg(test)] and
ensure it defines pub(crate) fn ensure_shared_memory_client() with the same
logic and signatures so existing tests continue to compile.
- Line 94: The call to crate::openhuman::memory::global::init(workspace.clone())
inside ensure_shared_memory_client() currently ignores errors; change it to
handle the Result explicitly (e.g., use ? to propagate or match/if let Err(e) =>
return Err(e.into())/log and return a failure) so initialization failures are
not swallowed. Locate ensure_shared_memory_client() and replace the let _ =
crate::openhuman::memory::global::init(...) with error-aware handling (match or
try operator) and ensure the function's return type is updated to propagate or
convert the init error appropriately so callers/tests see the real failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b9fbc03-53bf-4d56-8f80-953098678352

📥 Commits

Reviewing files that changed from the base of the PR and between d4e13e0 and 811ab8e.

📒 Files selected for processing (7)
  • src/openhuman/memory/ops/documents.rs
  • src/openhuman/memory/ops/kv_graph.rs
  • src/openhuman/memory/ops/learn.rs
  • src/openhuman/memory/ops/mod.rs
  • src/openhuman/memory/ops/sync.rs
  • src/openhuman/memory/ops/tool_memory.rs
  • src/openhuman/memory/query/mod.rs

Comment thread src/openhuman/memory/ops/mod.rs Outdated
Comment thread src/openhuman/memory/ops/mod.rs Outdated
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request May 25, 2026
- extract implementation from mod.rs into a dedicated test_support.rs
  so mod.rs stays export-focused (per coding guidelines)
- change `let _ = global::init(...)` to `.expect(...)` so init failures
  surface as clear test panics rather than silent swallowed errors

addresses CodeRabbit suggestions on PR tinyhumansai#2646
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 25, 2026
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough — Clean refactor + test-coverage PR. Extracts the HTTP routing logic from the async run_accept_loop into a pure classify_request function with a RequestOutcome enum, enabling 11 unit tests that cover all routing branches without needing a Tauri runtime. Also fixes a real e2e race condition in mega-flow.spec.ts and consolidates duplicated test-setup boilerplate across 5 memory ops submodules into a shared ensure_shared_memory_client() helper.

Area Files Summary
Tauri shell loopback_oauth.rs Extract classify_request + RequestOutcome enum, refactor run_accept_loop to match on enum, add 11 tests
E2E tests mega-flow.spec.ts Move clearRequestLog() after 800ms pause to fix race between in-flight requests and next scenario
Rust core tests ops/{mod,documents,kv_graph,learn,sync,tool_memory}.rs Deduplicate ensure_memory_client() into shared ensure_shared_memory_client()
Rust core tests query/mod.rs Add TEST_ENV_LOCK guard to prevent race with WorkspaceEnvGuard
Docs .claude/memory.md Add Windows OAuth deep-link architecture notes

Solid work — the pure-function extraction pattern is exactly the right approach for making Tauri-gated async code testable. The RequestOutcome enum maps 1:1 to the original branches, and the refactored run_accept_loop preserves identical behavior (non-success arms fall through to continue the loop, success arm returns). The e2e race fix is well-reasoned and the test helper consolidation eliminates a real concurrent-init bug where separate OnceLocks could rebind the global memory client with different paths.

CodeRabbit covered the remaining style nits (test helper placement in mod.rs, let _ = on init). No additional findings from my side.

LGTM — moving to approval queue.

M3gA-Mind added 6 commits May 26, 2026 12:20
…ests

Extracts the HTTP request routing logic from `run_accept_loop` into a
pure `classify_request(head, expected_state, bound_port) -> RequestOutcome`
function so all routing cases can be tested without a live `AppHandle`.

Adds 11 new Rust tests covering:
- Valid /auth with correct state → AuthCallback with full callback URL
- /auth with wrong state → StateMismatch
- /auth with missing state → StateMismatch
- /auth with no query string → StateMismatch
- Non-auth path (favicon, root) → NotFound
- Non-GET method → MethodNotAllowed
- Callback URL includes the actual bound port
- bind_loopback: ephmeral port succeeds + SO_REUSEADDR rebind

Part of the Windows OAuth deep-link fix (PRs tinyhumansai#2469, tinyhumansai#2511, tinyhumansai#2550).

Closes tinyhumansai#2562
clearRequestLog() was called before the 800 ms settle pause. In-flight
HTTP calls from the previous scenario (e.g. GET /auth/me triggered by
CoreStateProvider's fetchCoreAppSnapshot after a deep-link login) could
arrive at the mock server during the pause window and land in the freshly
cleared log.  The next scenario's waitForMockRequest then matched those
stale requests, concluded the auth flow had already completed, and called
composio_list_triggers before the new deep-link's session was actually
stored — causing the "no backend session token" failure.

Fix: move clearRequestLog() to after browser.pause(800) so the settle
window drains in-flight requests from the previous scenario before the
next scenario's polls start.
parallel tests in documents.rs and learn.rs each had their own
OnceLock<PathBuf>, so they bound global::init() to different temp dirs.
when both ran concurrently, the second init() rebind silently discarded
the first module's seeded data, causing:

  direct_document_handlers_roundtrip_through_namespace — list found no docs
  memory_learn_all_uses_all_namespaces_when_none_is_requested — 0 namespaces

fix: introduce ensure_shared_memory_client() in ops/mod.rs with a single
static OnceLock<PathBuf>; both modules now call global::init() with the
same path so concurrent calls hit the same-workspace fast-path and never
rebind the global client.
…onfig race

kv_graph, tool_memory, and sync each had isolated OnceLock<PathBuf>
workspaces that raced against the now-shared docs/learn workspace,
causing kv_handlers_roundtrip_scoped_values and
tool_rules_for_prompt_sorts_by_priority_and_tool_name to fail when
another test rebound the global client mid-test.

also fixes a concurrent-config-read race in
memory_tree_query_global_mode_dispatches_successfully: WorkspaceEnvGuard
sets OPENHUMAN_WORKSPACE to a temp path for a different test, this test
reads that path concurrently without holding TEST_ENV_LOCK, the dir gets
deleted between exists() and read_to_string() -> "Failed to read config
file". fix: hold TEST_ENV_LOCK for the duration of the test.
- extract implementation from mod.rs into a dedicated test_support.rs
  so mod.rs stays export-focused (per coding guidelines)
- change `let _ = global::init(...)` to `.expect(...)` so init failures
  surface as clear test panics rather than silent swallowed errors

addresses CodeRabbit suggestions on PR tinyhumansai#2646
@M3gA-Mind M3gA-Mind force-pushed the fix/2562-windows-oauth-loopback-tests branch from bf334e9 to de8e964 Compare May 26, 2026 07:00
@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. labels May 26, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
app/test/e2e/specs/mega-flow.spec.ts (2)

104-113: ⚡ Quick win

Avoid fixed settle sleeps for log isolation.

await browser.pause(800) is still timing-fragile across CI variance. Consider a small “wait until request log is stable for N ms” helper to make this deterministic and reduce flakes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/test/e2e/specs/mega-flow.spec.ts` around lines 104 - 113, The test uses a
fixed sleep (await browser.pause(800)) before calling clearRequestLog(), which
is timing-fragile; replace this with a deterministic helper that waits until the
request log is stable for a configured duration (e.g., "waitForStableRequestLog"
or similar) and then calls clearRequestLog(); implement the helper to poll the
request log (used by waitForMockRequest/clearRequestLog) until no new entries
appear for N ms, then proceed, and update the mega-flow.spec to call that helper
instead of browser.pause to avoid CI flakiness.

261-265: ⚡ Quick win

Use expectRpcOk here for stronger failure diagnostics.

These assertions currently only check auth.ok. Switching to expectRpcOk('openhuman.auth_store_session', auth) will keep error output consistent with the rest of this spec and improve triage when auth seeding fails.

As per coding guidelines, “In E2E specs, assert both UI outcomes and backend/mock effects when relevant. Add failure diagnostics … for faster debugging by agents.”

Also applies to: 595-599

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/test/e2e/specs/mega-flow.spec.ts` around lines 261 - 265, Replace the
fragile boolean check on the RPC response with the richer test helper: after
calling callOpenhumanRpc('openhuman.auth_store_session', { token:
buildBypassJwt('mega-composio-user') }) replace expect(auth.ok).toBe(true) with
expectRpcOk('openhuman.auth_store_session', auth) to get consistent failure
diagnostics; make the same substitution for the other occurrence around lines
595-599 where an auth RPC response is asserted.
app/src-tauri/src/loopback_oauth.rs (1)

333-360: ⚡ Quick win

Add outcome logs for all routing branches with correlation fields.

The new classifier branches currently log only the state-mismatch path. Please log each outcome (method_not_allowed, not_found, state_mismatch, auth_callback) with stable key/value fields (at least peer and bound_port) so loopback OAuth failures are diagnosable from logs.

🔎 Suggested patch
                 match classify_request(&head, &expected_state, bound_port) {
                     RequestOutcome::MethodNotAllowed => {
+                        log::debug!(
+                            "[loopback-oauth] outcome=method_not_allowed peer={peer} bound_port={bound_port}"
+                        );
                         let _ = socket
                             .write_all(&http_response("405 Method Not Allowed", "method not allowed"))
                             .await;
                     }
                     RequestOutcome::NotFound => {
+                        log::debug!(
+                            "[loopback-oauth] outcome=not_found peer={peer} bound_port={bound_port}"
+                        );
                         let _ = socket
                             .write_all(&http_response("404 Not Found", "not found"))
                             .await;
                     }
                     RequestOutcome::StateMismatch => {
                         log::warn!(
-                            "[loopback-oauth] /auth with missing or mismatched state — ignoring"
+                            "[loopback-oauth] outcome=state_mismatch peer={peer} bound_port={bound_port} reason=missing_or_mismatched_state"
                         );
                         let _ = socket
                             .write_all(&http_response("400 Bad Request", "state mismatch"))
                             .await;
                     }
                     RequestOutcome::AuthCallback { callback_url } => {
+                        log::info!(
+                            "[loopback-oauth] outcome=auth_callback peer={peer} bound_port={bound_port}"
+                        );
                         let _ = socket.write_all(&http_response("200 OK", SUCCESS_BODY)).await;
                         let _ = socket.flush().await;

As per coding guidelines: "Log entry/exit, branches, external calls, retries/timeouts, state transitions, and errors with verbose diagnostics using stable grep-friendly prefixes and correlation fields".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src-tauri/src/loopback_oauth.rs` around lines 333 - 360, Add structured
log statements for every RequestOutcome branch returned by classify_request
(MethodNotAllowed, NotFound, StateMismatch, AuthCallback) including stable
key/value fields peer and bound_port; update the match arms around
classify_request(...) so that before writing the http_response or emitting the
callback you call log::info! or log::warn! with a grep-friendly prefix like
"[loopback-oauth]" and include keys "outcome" (values: "method_not_allowed",
"not_found", "state_mismatch", "auth_callback"), "peer" and "bound_port" so
failures are diagnosable; keep the existing state-mismatch warn but add similar
logs to the MethodNotAllowed and NotFound arms and log the auth_callback arm
immediately after sending SUCCESS_BODY and before
app.emit(LOOPBACK_CALLBACK_EVENT, CallbackPayload { url: callback_url })
(include the callback_url or a short masked indicator only if acceptable by
policy).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/src-tauri/src/loopback_oauth.rs`:
- Around line 333-360: Add structured log statements for every RequestOutcome
branch returned by classify_request (MethodNotAllowed, NotFound, StateMismatch,
AuthCallback) including stable key/value fields peer and bound_port; update the
match arms around classify_request(...) so that before writing the http_response
or emitting the callback you call log::info! or log::warn! with a grep-friendly
prefix like "[loopback-oauth]" and include keys "outcome" (values:
"method_not_allowed", "not_found", "state_mismatch", "auth_callback"), "peer"
and "bound_port" so failures are diagnosable; keep the existing state-mismatch
warn but add similar logs to the MethodNotAllowed and NotFound arms and log the
auth_callback arm immediately after sending SUCCESS_BODY and before
app.emit(LOOPBACK_CALLBACK_EVENT, CallbackPayload { url: callback_url })
(include the callback_url or a short masked indicator only if acceptable by
policy).

In `@app/test/e2e/specs/mega-flow.spec.ts`:
- Around line 104-113: The test uses a fixed sleep (await browser.pause(800))
before calling clearRequestLog(), which is timing-fragile; replace this with a
deterministic helper that waits until the request log is stable for a configured
duration (e.g., "waitForStableRequestLog" or similar) and then calls
clearRequestLog(); implement the helper to poll the request log (used by
waitForMockRequest/clearRequestLog) until no new entries appear for N ms, then
proceed, and update the mega-flow.spec to call that helper instead of
browser.pause to avoid CI flakiness.
- Around line 261-265: Replace the fragile boolean check on the RPC response
with the richer test helper: after calling
callOpenhumanRpc('openhuman.auth_store_session', { token:
buildBypassJwt('mega-composio-user') }) replace expect(auth.ok).toBe(true) with
expectRpcOk('openhuman.auth_store_session', auth) to get consistent failure
diagnostics; make the same substitution for the other occurrence around lines
595-599 where an auth RPC response is asserted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 77fce426-c2e1-4727-ba3e-ece49a9f3f8b

📥 Commits

Reviewing files that changed from the base of the PR and between 811ab8e and de8e964.

📒 Files selected for processing (11)
  • .claude/memory.md
  • app/src-tauri/src/loopback_oauth.rs
  • app/test/e2e/specs/mega-flow.spec.ts
  • src/openhuman/memory/ops/documents.rs
  • src/openhuman/memory/ops/kv_graph.rs
  • src/openhuman/memory/ops/learn.rs
  • src/openhuman/memory/ops/mod.rs
  • src/openhuman/memory/ops/sync.rs
  • src/openhuman/memory/ops/test_support.rs
  • src/openhuman/memory/ops/tool_memory.rs
  • src/openhuman/memory/query/mod.rs
💤 Files with no reviewable changes (8)
  • src/openhuman/memory/ops/test_support.rs
  • src/openhuman/memory/ops/sync.rs
  • src/openhuman/memory/ops/documents.rs
  • src/openhuman/memory/ops/mod.rs
  • src/openhuman/memory/ops/kv_graph.rs
  • src/openhuman/memory/ops/tool_memory.rs
  • src/openhuman/memory/query/mod.rs
  • src/openhuman/memory/ops/learn.rs

@M3gA-Mind M3gA-Mind merged commit 730017e into tinyhumansai:main May 26, 2026
34 of 38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: OAuth login fails on Windows — deep link not received by running instance

2 participants