Repository navigation
ApiToken issuance: confirm node readable before returning (fix MCP reconnect reject) - #624
1 commit merged into
Conversation
…reconnect reject) After the OAuth code-exchange fix (#620) the /token exchange now succeeds and issues an mw_ API token — but the client's immediate reconnect was rejected ("Got new credentials, but memex rejected them on reconnect"). Same create→ routable lag, one layer up: ValidateToken reads the just-created token/index nodes via the one-shot hub.GetMeshNode, which hits [ROUTE] NotFound during the window before the node is routable on the validating replica. Fix at issuance, not on the hot validation path: after creating the token node and its global index, ApiTokenService.CreateToken now reads BOTH back through the resilient GetMeshNodeStream poll (self-paced Concat, swallows the transient "No node found", 10s bound, best-effort) BEFORE returning the raw token. This activates each node's owning per-node hub from Postgres, so by the time /token returns the token is validatable on any replica — while ValidateToken keeps the fast one-shot read (only issuance, a one-time login, pays the read-back). Verified: MeshWeaver.Auth.Test ApiToken suite 50/50 (real run, Release). The monolith tests confirm no regression; the multi-silo reconnect is verified live. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Ensures newly issued API tokens are immediately readable across replicas in a multi-silo portal by confirming both the per-user token node and the global ApiToken/{hashPrefix} index node are readable (via GetMeshNodeStream polling) before returning the raw token, reducing [ROUTE] NotFound rejections on the MCP client’s immediate reconnect.
Changes:
- Added a best-effort
ConfirmReadable(path)helper that pollsGetMeshNodeStream(path)with a bounded retry loop under System identity. - Updated
CreateTokento confirm readability of both the index node and token node before returningTokenCreationResult.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// than failing issuance — the token IS created; worst case validation resolves it a | ||
| /// beat later. System identity: the ApiToken/index nodes are System-owned. |
| .Where(n => n is not null && n.Content is not null) | ||
| .Select(n => (MeshNode?)n) | ||
| .Catch<MeshNode?, Exception>(_ => Observable.Empty<MeshNode?>()) | ||
| .Concat(Observable.Defer(Attempt).DelaySubscription(TimeSpan.FromMilliseconds(50))); |
Test Results (shard 3) 11 files - 1 11 suites - 1 3m 9s ⏱️ - 1m 27s Results for commit 9354353. ± Comparison against base commit 10b2d13. This pull request removes 59 tests. |
Test Results (shard 1)1 165 tests ±0 1 163 ✅ - 1 7m 2s ⏱️ +29s For more details on these failures, see this check. Results for commit 9354353. ± Comparison against base commit 10b2d13. |
Test Results 60 files - 1 60 suites - 1 31m 21s ⏱️ -27s For more details on these failures, see this check. Results for commit 9354353. ± Comparison against base commit 10b2d13. This pull request removes 59 tests. |
Problem (the next layer of the MCP-connect failure, observed live)
After #620 fixed the OAuth code exchange, the
/tokenflow now succeeds and issues anmw_API token (live logs:Node created at rbuergi/ApiToken/...+ global index). But the MCP client's immediate reconnect was rejected — user report: "Got new credentials, but memex rejected them on reconnect."Same
create→routablelag, one layer up:ApiTokenService.ValidateTokenreads the just-created token/index nodes via the one-shothub.GetMeshNode(path), which hits[ROUTE] NotFoundduring the window before the node is routable on the validating replica (issuance and reconnect often land on different replicas).Fix
Confirm-readable at issuance, not on the hot validation path. After creating the token node + global index,
CreateTokenreads BOTH back through the resilientGetMeshNodeStreampoll (self-pacedConcat, swallows the transient "No node found", 10s bound, best-effort → returns the token anyway on timeout) BEFORE returning the raw token. This activates each node's owning per-node hub from Postgres, so the token is validatable on any replica by the time/tokenreturns.ValidateTokenkeeps the fast one-shot read — only the one-time login pays the read-back.Verification
MeshWeaver.Auth.TestApiToken suite: 50/50 (real run, Release). Monolith tests confirm no regression (they can't reproduce the multi-silo lag — in-process routing is authoritative).No What's New entry — completes the MCP-connect fix chain; user-facing effect covered by #609's entry.
🤖 Generated with Claude Code