Spike: retry/resilience policy, session lifecycle, and multisig state coordination - #85
Conversation
…-protocol#79 Audits the retry, session, and multisig state gaps described in trustflow-protocol#79, finds most of the retry gap already closed by the tx-pipeline and axios-retry work, and proposes/prototypes the rest: - Retry: remove src/stellar/rpc.ts, dead and unretried code fully superseded by TransactionPipeline. Document an idempotency policy per call type (simulate/prepare safe to retry, submit is not). - Session: make storage pluggable via a SessionStorageAdapter, add a Node-safe in-memory default instead of the previous silent no-op, and add expiry metadata plus isSessionExpired(). - Multisig: define the target MultiSigStateStore abstraction for cross-process coordination, and add exportState/importState to MultiSigEscrowClient as a non-breaking stopgap ahead of a native backend-backed store. Full writeup, idempotency table, and blocking unknowns in docs/spikes/issue-79-retry-session-multisig.md. Closes trustflow-protocol#79
Summary
Here's what I reviewed
What I like
Blocking / high-priority items (please address before merge)
Non-blocking but recommended changes
Optional / future improvements
Tone / wording suggestions for the PR description
Merge readiness checklist
Final assessment
Thanks — great spike and great tests; the follow-up issues give a clear path to finish the remaining integration work. |
…docs Addresses meshackyaro's review on the retry/session/multisig spike PR: Blocking: - Add an explicit best-effort compatibility note (JSDoc on Session/ saveSession, README, spike doc) for the client-side expiresAt default, since the backend doesn't return a token TTL yet (trustflow-protocol#82). - Re-verify and document that removing src/stellar/rpc.ts has no public API or documentation footprint (never re-exported, never mentioned in README/API.md, no tests). Also: - Fix isSessionExpired() treating a malformed stored expiresAt as non-expiring forever; it's now treated as already-expired. - Make importState() validate the snapshot shape and return an SDKResult instead of throwing, matching the rest of the class's error-handling convention (no thrown exceptions in public APIs). - Add tests for adapter failures, malformed expiresAt, malformed multisig snapshots, and explicit Node/browser environment-detection switching within a single test. - Document session storage environment detection (incl. SSR/bundler caveats) and multisig exportState/importState usage + conflict semantics in the README; add a CHANGELOG entry.
|
Thanks for the thorough review! Pushed a follow-up commit addressing both blockers and most of the recommended items: Blocking
Also addressed
All still green: 134/134 tests, lint clean, build succeeds. Left as follow-up (not blocking, per your note): the example-app / mock server-backed store idea, and a version field on exported multisig state — happy to fold either into #83 if you'd like them scoped there instead of a new issue. |
Thanks — nice follow-up and good cleanup across the spike. What I looked for
Ship-it with a couple of small follow-ups before I merge:
None of these are blockers for the approach — tests + build passing and the follow-up issues filed are exactly the right pattern. If you want I can push a tiny follow-up commit that adds the exported-state version field and the missing-session-expires test; otherwise please add the two small changes above and I’ll approve/merge. |
…ompat Addresses meshackyaro's follow-up review on the retry/session/multisig spike PR (trustflow-protocol#82, trustflow-protocol#83, trustflow-protocol#84): - Add a version field (MULTISIG_SNAPSHOT_VERSION) to exported multisig snapshots. importState() now rejects a missing or mismatched version outright instead of silently misinterpreting an unfamiliar shape, giving future schema changes an explicit negotiation point. - Document and explicitly test the backward-compatible path in loadSession(): a session with no stored expiresAt key at all (written before expiry tracking existed) is treated as not-yet-expired, distinct from a malformed value (already treated as expired). - Add a "Compatibility & migration" note to the top of the spike doc and the CHANGELOG confirming no breaking changes, and cross-reference the follow-up issues (trustflow-protocol#82-trustflow-protocol#84) more explicitly throughout both. - Re-confirmed (repo-wide search) that removing src/stellar/rpc.ts still has no lingering references.
|
Pushed both requested changes:
136/136 tests passing, lint clean, build succeeds. |
Thanks — this is an excellent, thorough spike and implementation. A few highlights I appreciated:
Non-blocking suggestions:
Overall: Looks good to me — this is ready to approve/merge from my side once you’re happy with the small docs/changelog follow-ups. |
|
Thanks for the kind words and the careful re-review through all three rounds! Both non-blocking suggestions are actually already in place from the earlier rounds:
One gap I do see, though: the spike doc itself ( |
Small follow-up to meshackyaro's third review round: the spike doc described the Node-default session storage recommendation in prose but didn't point readers at the README's concrete configureSessionStorage() adapter-injection example.
|
Pushed the cross-reference: 136/136 tests passing, lint clean, build succeeds. This is a docs-only change, so no behavioral risk. Let me know if there's anything else — otherwise this should be ready from my side. |
meshackyaro
left a comment
There was a problem hiding this comment.
Thank you — this is an excellent follow-up and a solid, well-constructed and well-tested implementation of the spike. I’m happy to approve this for merge. Great Job!
Summary
Resolves the spike in #79: define a retry/resilience policy, a Node-vs-browser-aware session
storage + token lifecycle strategy, and a multisig operation-state coordination strategy, with
a prototype of each and any blocking unknowns flagged.
Full writeup (idempotency table, options considered, decisions, unknowns):
docs/spikes/issue-79-retry-session-multisig.md.What changed
TransactionPipelineandcreateApiHttpClient(axios-retry) already cover most of the gap described in the issue. What was left was dead code:
removed
src/stellar/rpc.ts(simulateAndAssemble) — unreferenced anywhere, not retried, nottimed out, fully superseded by
TransactionPipeline.prepare.src/utils/retry.tsis kept as-is(it's a tested public utility, not dead).
auth/session.tsnow supports a pluggableSessionStorageAdapter(
configureSessionStorage/resetSessionStorage), defaults to an in-memory adapter under Nodeinstead of silently no-op'ing, and persists an
expiresAtalongside the token with a newisSessionExpired()helper. Backward compatible — existingsaveSession(token, address)callsstill work.
MultiSigStateStoreinterface (src/types/multisig.ts) as theabstraction a future backend-backed store should satisfy, plus
exportState/importStateonMultiSigEscrowClientas a non-breaking stopgap that lets an operation's state be round-trippedthrough an external store today, ahead of native async storage support.
Follow-up implementation issues filed
/auth/verifyMultiSigStateStoreTransactionPipeline's retry loop ontoutils/retry.tsCloses #79
Test plan
npm test— 129/129 passing (added coverage for session expiry, pluggable storage, Nodein-memory default, and multisig
exportState/importState)npm run lint— 0 errors (pre-existingno-explicit-anywarnings elsewhere untouched)npm run build— CJS/ESM/DTS artifacts build cleanly