This document provides a summary of the validation system implementation across both frontend and backend, including current test coverage status and architectural decisions.
- Core Regex Patterns: STELLAR_ACCOUNT_REGEX, ASSET_CODE_REGEX, CAMPAIGN_ID_REGEX, TX_HASH_REGEX
- Reusable Schemas: stellarAccountIdSchema, assetCodeSchema, positiveAmountSchema, unixTimestampSchema, httpsOnlyUrlSchema
- Request Payload Schemas:
- createCampaignPayloadSchema
- createPledgePayloadSchema
- reconcilePledgePayloadSchema
- claimCampaignPayloadSchema
- refundPayloadSchema
- Query Parameter Parsers: parseCampaignListPaginationQuery, parseHistoryPaginationQuery, parsePledgeListPaginationQuery
- Stellar Address Validation (
stellarAddress.ts): CRC-16/XModem checksum verification - SSRF Protection (
urlSafety.ts): Two-layer defense with schema validation and DNS resolution
- Express middleware for request body validation
- Returns 400 with ZodIssue[] details on failure
- Replaces req.body with parsed data on success
| Module | Test File | Coverage | Status |
|---|---|---|---|
| validateBody middleware | validateBody.test.ts | ✅ Covered | Complete |
| Stellar address validation | stellarAddress.test.ts | ✅ Covered | Complete |
| URL safety validation | urlSafety.test.ts | ✅ Covered | Complete |
| Zod schemas | schemas.test.ts | Needs expansion |
- Individual validation functions for each field type:
validateStellarAccount()- Validates account format & lengthvalidateTitle()- Checks length constraints (4-80 chars)validateDescription()- Checks length constraints (20-500 chars)validateTargetAmount()- Validates amount is positive and >= 0.01validateDeadlineHours()- Validates hours are 1-8760 (365 days max)validateForm()- Batch validates entire formisFormValid()- Checks if any errors exist
- Real-time Validation: Validates on every field change, not just submit
- Inline Error Display: Error messages appear below invalid fields
- Visual Error Indicators: Red border + background for invalid fields
- Disabled Submit Button: Blocked when form has any errors
- Error States Match UI: Uses consistent red color (#f87171) with dark theme
.input-errorclass for field styling:- Red border (#f87171)
- Dark red background (rgba(127, 29, 29, 0.1))
- Red focus state with matching glow
.field-errorclass for error messages:- Red text color
- Smaller font (0.8125rem)
- Medium weight for emphasis
- 6px margin above for spacing
| Module | Test File | Coverage | Status |
|---|---|---|---|
| Validation utilities | validation.test.ts | ✅ 50+ tests | Complete |
| Form validation UI | CreateCampaignForm.validation.test.tsx | ✅ Covered | Complete |
- validateBody.test.ts: Tests middleware behavior with valid/invalid payloads, coercion, and error responses
- stellarAddress.test.ts: Tests Base32 decoding, CRC-16 checksums, and edge cases
- urlSafety.test.ts: Tests SSRF protection, private IP detection, and DNS resolution
- schemas.test.ts:
⚠️ Partial coverage - needs expansion for all payload schemas
- validation.test.ts: 50+ test cases covering all validation functions with boundary conditions
- CreateCampaignForm.validation.test.tsx: Integration tests for UI validation behavior
| Field | Required | Type | Constraints | Example |
|---|---|---|---|---|
| Creator | ✅ | String | 56 chars, starts with G, A-Z2-7 only | GAA...AAA |
| Title | ✅ | String | 4-80 characters | "Build Solar" |
| Description | ✅ | Text | 20-500 characters | "Fund the development..." |
| Amount | ✅ | Number | > 0, >= 0.01 | 100.50 |
| Deadline | ✅ | Integer | 1-8760 hours | 72 |
| Asset | ✅ | Select | Predefined list | "USDC" |
| Image URL | ❌ | URL | HTTPS only, no private IPs | https://... |
| External Link | ❌ | URL | HTTPS only, no private IPs | https://... |
- Layer 1: Schema-level validation blocks private IP literals and non-HTTPS protocols
- Layer 2: Runtime DNS resolution prevents DNS rebinding attacks
- Blocked Ranges: 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, and IPv6 equivalents
- Format Check: 56 characters, starts with 'G', Base32 alphabet only
- Checksum Verification: CRC-16/XModem validation of payload
- Version Byte Check: Ensures Ed25519 public key (0x30)
See VALIDATION_IMPLEMENTATION.md for detailed step-by-step instructions:
- Define Zod schema in
backend/src/validation/schemas.ts - Apply
validateBodymiddleware in route handler - Add frontend validation if applicable
- Write tests for the new schema
- Update OpenAPI documentation (automatic)
- Backend Validation: < 1ms for typical payloads (simple regex and type checks)
- Frontend Validation: Negligible impact (runs during user input, no API calls)
- No Additional Dependencies: Uses existing Zod library
- Bundle Size: Validation code < 2KB
- ✅ Chrome 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Edge 90+
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
- Expand Schema Tests: Add comprehensive tests for all Zod schemas in schemas.test.ts
- Async Validation: Add frontend async validation for unique campaign titles
- Field Character Counters: Show remaining characters for title/description fields
- Accessibility: Add aria-invalid, aria-describedby attributes to error states
- Debouncing: Debounce real-time validation for performance optimization
- Animation: Smooth transitions for error appearance/disappearance
The validation system provides:
✅ Strong Backend Validation - Zod schemas with SSRF protection
✅ User-Friendly Frontend Errors - Clear, specific error messages
✅ Real-time Feedback - Errors appear/disappear as user types
✅ Visual Consistency - Matches existing design system
✅ Submit Button Prevention - Disabled until form is valid
✅ Comprehensive Tests - 50+ unit tests + integration tests
✅ Security Features - SSRF protection and Stellar address validation
✅ Zero Breaking Changes - Fully backward compatible
All validation documentation is current and reflects the implementation as of the latest update.