Skip to content

Add chat state transition debounce - #908

Open
pntech20 wants to merge 820 commits into
leojay-net:mainfrom
pntech20:feat/chat-state-machine-debounce
Open

Add chat state transition debounce#908
pntech20 wants to merge 820 commits into
leojay-net:mainfrom
pntech20:feat/chat-state-machine-debounce

Conversation

@pntech20

Copy link
Copy Markdown

Summary

  • add a leading-edge debounce wrapper for chat state transitions, defaulting to SEND_MESSAGE
  • expose a reset hook for clearing debounce state when callers need to reset the flow
  • cover rapid duplicate sends, delayed sends, and non-debounced events in chatStateMachine.test.ts

Testing

  • npm run test:unit -- src/hooks/chatStateMachine.test.ts
  • npm run typecheck
  • git diff --check

Closes #588

edehvictor and others added 30 commits March 30, 2026 00:48
…-event-snapshots-322

test(contracts): add event snapshot coverage
…tus-polling-298

feat(frontend): add ccip bridge status polling
…issues-346-376-354-349

Feature/implement issues 346 376 354 349
…rror

- Reverts accidental soroban-sdk downgrade from v25.3.0 to v21.0 which
  caused LengthExceedsMax (DataKey enum exceeded the 50-case XDR limit
  in v21) and broke all generated client methods
- Fixes duplicate expression in check_slippage: removes the stray
  mul_div_ceil call that caused a syntax error, keeping only the
  mul_div_floor call for the display event
- Removes the now-unused `use soroban_sdk::IntoVal` import to satisfy
  clippy -D warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: added TypeScript strict type-check step (no build artefacts)
fix: added unit tests for chatStateMachine
…resses tests

- Makes WINDOW_LEDGERS `pub const` so test code referencing it via
  `use super::*` can access it without a visibility error
- Adds 7 tests covering get_denied_addresses: empty list, basic
  enumeration, pagination (limit + offset), sparse list after
  remove_denied_address, persistence across a full WINDOW_LEDGERS
  advance, and out-of-bounds offset; these tests correctly define
  start_ledger before any ledger-mutation closures, eliminating the
  "start_ledger not found in this scope" compile error seen in CI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
leojay-net and others added 27 commits May 29, 2026 12:55
…sues

fix(contract): resolve 4 issues — request_withdrawal circuit breaker,…
Replace raw if-return patterns with require! macros in the init function,
making boundary checks consistent with the rest of the contract. Split the
combined min_deposit guard into two distinct require! calls so each
invariant (min_deposit >= 1 and min_deposit < limit) surfaces its own
clear error, preventing unexpected state transitions that could affect
daily limit validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
)

Add require_not_paused check so a paused contract correctly rejects
heartbeat calls. Convert the circuit breaker and operator existence
checks from raw if-return patterns to require! macros for consistency
with the rest of the codebase and to make each guard's intent explicit.

Closes leojay-net#504

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eojay-net#511)

Change get_receipt_by_index return type to Result<Option<Receipt>, Error>
so the function can properly signal when the global circuit breaker is
active. When tripped, a CircuitBreakerBlockedEvent is emitted (recording
which function was blocked) and Err(CircuitBreakerActive) is returned.
Out-of-bounds index lookups continue to return Ok(None). Existing call
sites that use the generated panic-on-error client wrapper are unaffected.

Closes leojay-net#511

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eojay-net#600)

Require the deploying admin to authenticate (admin.require_auth()) before
the contract state is written, preventing any third party from front-running
initialization with a different admin address. Add InitializedEvent emitted
at the end of init so indexers and off-chain tooling can reliably detect and
verify the initial configuration (admin, token, limit).

Closes leojay-net#600

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ay-net#511, leojay-net#600

- heartbeat: verify rejection when paused, when circuit breaker is
  tripped, and for non-operators; verify nonce replay is blocked and
  valid calls succeed.
- get_receipt_by_index: verify circuit breaker blocks access and emits
  CircuitBreakerBlockedEvent; verify out-of-bounds returns None;
  verify access is restored after breaker reset.
- initialize: verify admin auth is required; verify duplicate init,
  zero limit, min_deposit >= limit, invalid threshold, and duplicate
  signers are all rejected with the correct error enum.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…#511, leojay-net#600 and init fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat:Contract Security: initialize, heartbeat, and get_receipt_by_index
Resolved conflicts in test files and utility hooks by accepting upstream changes.
Feature branch changes are preserved separately.
Closes leojay-net#494 leojay-net#498

**Stellar Contract Documentation (leojay-net#494 leojay-net#498)**
- Enhanced heartbeat() function with comprehensive JSDoc explaining nonce-based replay protection
- Improved get_operator_nonce() documentation with clear lifecycle and best practices
- Detailed validate_and_increment_nonce() internal documentation covering validation logic, atomicity, and security properties
- Added extensive documentation to prune_inactive_operators() with architecture, algorithm, and example timeline
- Enhanced prune_inactive_operators_internal() with detailed algorithm explanation and storage invariants

Documentation covers:
- How nonce validation prevents replay attacks
- Recommended client flow for nonce handling
- Inactivity threshold calculation and pruning behavior
- Event emissions for audit trails
- Error handling and recovery strategies

**Frontend Error Boundary Implementation (leojay-net#515)**
- Added error boundary pattern to AIAssistant class
- Implemented SAFE_FALLBACK_RESULT constant for graceful error recovery
- Enhanced analyzeUserMessage() with input validation and result structure validation
- Added isValidAnalysisResult() helper for API response validation
- Improved generateFollowUpQuestion() with error handling and fallback responses
- Network errors trigger user notification instead of silent failures

**Hydration Mismatch Fix (leojay-net#548)**
- Added isMounted state to NotificationsCenter component to prevent hydration mismatches
- Delayed interactive UI rendering until after client-side hydration completes
- Made dropdown and event listeners only active after component mounts on client
- Added useCallback for stable handleClickOutside reference
- Wrapped button click handler to prevent state updates before hydration

All changes maintain backward compatibility and add no functional behavior changes, only robustness improvements.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…g telemetry

- Swap ErrorBoundary and min-h-screen div order so outer div properly wraps ErrorBoundary (leojay-net#448)
- Add bottomRef and scrollIntoView on message send in ChatInput for auto-scroll (leojay-net#505)
- Replace CSS variable colors with WCAG-AA white-on-red classes in OfflineStatusBanner (leojay-net#495)
- Add trackFeatureFlag telemetry helper (gtag + sessionStorage dedup) in useFeatureFlag (leojay-net#493)
…-contrast-telemetry-build-448-493-495-505

fix: JSX div structure, auto-scroll, accessible contrast, feature flag telemetry
fix(contract): harden upgrade validation and add Message E2E coverage
…y_recovery

- Add admin Address field to EmergencyRecoverySetEvent for full audit trail
- Document the admin auth guard with inline section comments in the function
- Add integration test: event records admin address (issue leojay-net#574 AC2)
- Add integration test: overwrite/rotate recovery address (regression coverage)
- Add integration test: non-admin caller is rejected via mock_auths (issue leojay-net#574 AC1)

Pre-existing compilation errors in test.rs (lines 2284-3974, Option<Receipt>
missing unwrap calls) are unrelated to this change and were present on main.

Closes leojay-net#574
- Expand FeeWithdrawnEvent with admin, token, nonce and remaining_fees fields
  so indexers get a self-contained audit record per fee withdrawal
- Update withdraw_fees to emit the full schema and rename new_balance to
  remaining_fees for clarity
- Update withdraw_fees_batch to emit the full schema per token (nonce=0,
  remaining_fees=0 since the vault is fully drained per token)
- Add section comments (auth / validation / replay-protection / mutation / audit)
  for readability
- Add integration test: full event schema + nonce increment verification
- Add integration test: batch emits exactly one event per token with positive balance
- Add integration test: remaining_fees tracks correctly across multiple partial withdrawals

Pre-existing compilation errors in test.rs (Option<Receipt> unwrap, lines 2284-3974)
are unrelated and were present on main before this branch.

Closes leojay-net#576
…set-emergency-recovery

feat(contract): implement admin authentication logic for set_emergenc…
…es-event-schema

Feat/576 withdraw fees event schema
Closes leojay-net#492 - Add paused-state guard and explicit NotOperator error on
inactive-operator deactivation to set_operator, preventing silent
no-ops that can corrupt batch operation state.

Closes leojay-net#499 - Protect receipt-counter increment and daily-deposit
accumulator with checked arithmetic; emit DepositBalanceUpdatedEvent
so indexers can confirm balance updates without re-reading storage.

Closes leojay-net#452 - Replace hardcoded hex chart colors in the admin
dashboard with CSS custom properties (--color-chart-*) defined in
globals.css, enabling proper light/dark theme switching.

Closes leojay-net#490 - Add smooth scroll-to-top in AdminGuard when admin access
is granted, with unit tests covering granted, denied, and error paths.
…-ui-security-batch-492-499-452-490

feat: fix contract validation, deposit safety and admin UI improvements
…oundary

Closes leojay-net#590 — fix(frontend): race condition in chatStateMachine.ts
- Clone initial context in StateMachine constructor so action callbacks
  never mutate the shared module-level INITIAL_CONTEXT object, preventing
  cross-instance context pollution under concurrent usage / React StrictMode.
- Introduce getInitialContext() factory in chatStateMachine.ts so every
  machine instance starts from a fresh, timestamp-stamped context object.
- Add regression suite (chatStateMachine race condition regression leojay-net#590)
  verifying two independent machines never share or corrupt each other's state.

Closes leojay-net#663 — fix(frontend): memory leak in useChat.ts
- Track the onTransactionReady setTimeout in transactionReadyTimerRef and
  clear it in the useEffect cleanup, preventing post-unmount callback invocation.
- Replace Date.now()+1 ID in appendCancelledMessage with crypto.randomUUID()
  to eliminate ID collision risk under rapid cancellation.
- Add regression suite (useChat memory leak regression leojay-net#663) that unmounts
  the component before the 1-second timer fires and asserts the callback is
  never called.

Closes leojay-net#631 — feat(frontend): skeleton loading state in AuditTable.tsx
- Render an animated 5-row skeleton table (aria-busy="true") while the
  audit API fetch is in-flight, replacing the blank/empty state.
- Add unit test verifying skeleton rows appear during load and are replaced
  by real data once the fetch resolves.

Closes leojay-net#633 — feat(frontend): error boundary for ChatHistorySidebar.tsx
- Wrap the ChatHistorySidebar render tree with the existing ErrorBoundary
  component, surfacing a "Sidebar unavailable" fallback with a "Reload sidebar"
  button instead of a blank panel or React crash on unexpected errors.
- Add unit tests verifying the error boundary catches child throws and
  renders the custom title/retry label.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-663-multi-issue

fix/feat: resolve race condition, memory leak, add skeleton loading & error boundary
@pntech20
pntech20 force-pushed the feat/chat-state-machine-debounce branch from f078e49 to 807f09b Compare May 31, 2026 11:44
@pntech20

Copy link
Copy Markdown
Author

Rebased this onto current main and pushed the updated branch. The focused chat state-machine unit test and ESLint pass for the touched files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(frontend): add debounce mechanism to chatStateMachine.ts