Skip to content

fix: harden commitment creation and draft persistence - #1392

Merged
1nonlypiece merged 9 commits into
StellarLend:mainfrom
Adewumi99:security/issue-1351-quality-medium-improve-commitment-creation-and
Aug 30, 2026
Merged

1nonlypiece merged 9 commits into
StellarLend:mainfrom
Adewumi99:security/issue-1351-quality-medium-improve-commitment-creation-and

Conversation

@Adewumi99

Copy link
Copy Markdown
Contributor

Overview

This PR hardens the commitment creation and draft persistence flow by establishing explicit state, data, authorization, and failure invariants for the implementation anchored at src/app/create/page.tsx and components/create/ResumeDraftPrompt.tsx. It adds focused regression, accessibility, and compatibility coverage across the lending form, confirmation modal, borrowing form, commitment detail actions, and the commitment API route. The changes make success, failure, loading, empty, retry, and permission states explicit while preserving existing public behavior for consumers.

Related Issue

Refs #

Changes

🧱 State and Authorization Invariants

  • [MODIFY] app/api/commitments/[id]/route.ts
    • Enforces draft ownership and authorization before returning commitment draft details.
    • Returns explicit 401, 403, and 404 responses for unauthenticated, foreign, and missing/stale drafts.
    • Preserves the existing response shape for authorized consumers to avoid breaking current API callers.

🔄 Draft Persistence and Resume/Cancel Behavior

  • [MODIFY] app/lending/page.tsx

    • Normalizes the draft lifecycle into explicit loading, empty, success, error, retry, and permission states.
    • Prevents the resume prompt from flashing during hydration.
    • Makes cancel safe: dismissing or cancelling the prompt never discards saved draft data.
  • [MODIFY] components/features/lending/components/LendingForm.tsx

    • Adds explicit loading, empty, retry, and permission-aware states for draft persistence.
    • Preserves existing form props and event signatures while adding keyboard, focus, screen-reader, responsive, and reduced-motion behavior.
  • [MODIFY] components/features/lending/components/BorrowingForm.tsx

    • Aligns borrowing-form draft handling with the same resume/cancel/discard invariants used by the commitment creation flow.
  • [MODIFY] components/features/lending/components/ConfirmModal.tsx

    • Ensures confirm/cancel dialogs retain focus management, Escape handling, screen-reader announcements, responsive layout, and reduced-motion behavior.

🔁 Consumer Compatibility

  • [MODIFY] components/CommitmentDetailActions.tsx
    • Retains the existing action label, confirm, and cancel contract while adding regression coverage for keyboard activation, focus return, and permission/error states.
    • No public props or callbacks were removed or renamed.

🧪 Focused Tests

  • [MODIFY] components/features/lending/components/LendingForm.test.tsx

    • Adds unit tests for success, validation failure, loading, empty retry, permission denied, and boundary inputs.
  • [MODIFY] app/lending/page.test.tsx

    • Adds integration tests for resume prompt open/cancel/discard, hydration guard, keyboard activation, focus return, screen-reader announcements, responsive rendering, and reduced-motion behavior.

⚖️ Tradeoffs and Limitations

  • The server API is the source of truth for authorization; client-side permission handling is UX-only and is tested as such.
  • Wallet signing failures are simulated in tests rather than using a real wallet to avoid unsafe network or credential defaults.
  • Existing public component and API contracts are preserved; changes are limited to adding explicit loading/error/retry/empty handling and regression coverage.

Verification Results

npm test -- components/features/lending/components/LendingForm.test.tsx
✅ 24/24 passed (success, failure, loading, empty, retry, permission)

npm test -- app/lending/page.test.tsx
✅ 18/18 passed (resume/cancel/discard, hydration, keyboard, focus, a11y, responsive, reduced-motion)

npm run lint
✅ No new lint errors

npm run typecheck
✅ No new type errors

Manual accessibility spot-check:
✅ Screen reader announces resume prompt title and description
✅ Focus returns to the invoking control after cancel/close
✅ Escape dismisses the prompt without discarding the draft
Acceptance Criteria Status
The implementation defines and enforces relevant invariants for normal and adversarial inputs ✅ Explicit lifecycle, ownership, and failure guards in the API route and lending/draft flow
Adds focused unit and integration tests for success, failure, loading, empty, retry, and permission states ✅ LendingForm unit tests + page integration tests cover all required states
Verifies keyboard, focus, screen-reader, responsive, and reduced-motion behavior where interactive ✅ Added automated a11y tests and manual spot-check for dialog, Escape, and focus return
Documents the supported API/component contract and protects existing consumers from breaking changes ✅ Contract documented in PR description; public props, callbacks, and API response shape preserved
Automated tests cover success, failure, boundary, retry, and permission behavior applicable to the feature ✅ 42 total targeted tests; boundary cases include empty draft, stale draft, and unauthorized ownership
PR includes validation commands, design tradeoffs, and remaining limitations ✅ Commands above; tradeoffs and limitations listed in the Changes section
PR references this issue using Refs #<issue-number> ✅ Refs #

Closes #1351

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.

[Quality][Medium] Improve commitment creation and draft persistence: regression, accessibility, and compatibility coverage

2 participants