๐ฃ๏ธ User Feedback¶
๐ Overview¶
Covers the architecture of the Give Feedback feature.
The system collects written, audio, and video feedback with optional screen snips or recordings, preserving runtime context for debugging, product analysis, and traceability.
๐ฌ Supported Modes¶
โ๏ธ Text¶
- Plain text input
- Optional attachments
- ๐ผ๏ธ Image snip
- ๐ฅ๏ธ Screen recording (tab or region)
๐๏ธ Audio¶
- Microphone recording
- Optional attachment
- ๐ฅ๏ธ Screen recording (tab or region)
๐ Meet Us¶
- Schedule a session with the team
- Separate entry point
- Outside the feedback pipeline
๐ How It Works¶
The flow has two stages:
Stage 1 โ ๐ค Upload¶
Frontend requests a presigned S3 URL from the backend, then uploads the binary directly to S3 via HTTP PUT. Uploads begin immediately after capture, not at submit time.
Stage 2 โ ๐จ Submit¶
After uploads complete, the frontend sends a compact JSON metadata payload to the backend. The backend validates it and writes a manifest JSON to S3 as the durable record.
โ ๏ธ Submit is blocked until all required uploads finish.
๐๏ธ Responsibilities¶
Frontend - Renders feedback modal and capture flows - Records audio, screen video, region recordings, and screen snips - Uploads binaries directly to S3 (background, post-capture) - Submits final metadata payload - Cleans up streams, tracks, object URLs, and animation frames aggressively
Backend - Issues presigned upload URLs with category + MIME validation - Validates and sanitizes incoming metadata (text stripping, key format checks, correlation ID validation) - Writes feedback manifest to S3
โ๏ธ Key Design Decisions¶
1. ๐ค Presigned Uploads Instead Of Server-Side Multipart¶
Why: Keeps large binaries off the Node server, isolates upload failures from submission failures, and delegates scalability to S3.
2. ๐๏ธ Manifest-Based Storage¶
Why: The backend stores a manifest JSON referencing uploaded media rather than one combined blob. Text and media are validated independently; the record stays inspectable and easy to process downstream.
3. ๐ Correlation ID As Feedback ID¶
Why: Format: userId-sessionId-uuid. One identifier links frontend activity, backend logs, and stored artifacts. If not supplied, the backend generates a safe fallback.
4. โก Background Uploads After Capture¶
Why: Uploads start as soon as media is captured, making the final submit step lightweight and reducing perceived wait time.
5. ๐ช Capture Logic In Focused Hooks¶
Why: Recording, screen capture, and upload lifecycle are encapsulated in reusable hooks, keeping modal components readable and making cleanup explicit.
๐ฆ Manifest Shape¶
{
"feedbackId": "userId-sessionId-uuid",
"type": "text | audio | video",
"text": "...",
"currentUrl": "...",
"userAgent": "...",
"timestamp": "...",
"userId": "...",
"files": { "mediaKey": "...", "imageKey": "..." },
"createdAt": "..."
}
๐ Security¶
| Concern | Mitigation |
|---|---|
| Unsafe text | HTML/control char stripping, whitespace cleanup, hard length cap |
| Invalid uploads | Category + MIME + compatibility validation before issuing presigned URL |
| Malformed S3 keys | Key format validated against expected feedback path patterns on submit |
| Untrusted correlation IDs | Validated on receipt; invalid values replaced with a backend-generated fallback |
| S3 redirect attacks | Fetch uses redirect: 'error' โ presigned URLs are host-bound, silent redirects would silently fail PUT requests |