learning_ai_common_plat/docs/devops/USER_ISSUE_REPORTING_ROADMAP.md
saravanakumardb1 1b11db3f6f feat(broadcasts,surveys): Phase 1 complete - backend modules
- broadcasts/types.ts: Broadcast, BroadcastTarget, BroadcastMetrics, InAppMessage
- broadcasts/repository.ts: CRUD + delivery tracking + read receipts
- broadcasts/targeting.ts: evaluateTarget(), semver, FNV-1a hash
- broadcasts/routes.ts: Admin CRUD + public endpoints (14 routes)
- surveys/types.ts: Survey, Question, SurveyResponse, conditional logic
- surveys/repository.ts: CRUD + analytics + CSV export
- surveys/routes.ts: Admin CRUD + public endpoints (13 routes)
- cosmos-init.ts: 7 new containers with TTL policies
- server.ts: Register broadcastRoutes + surveyRoutes

Implements Phase 1 of platform_BROADCAST_SURVEY_ROADMAP.md
2026-03-02 23:51:23 -08:00

10 KiB

User-Initiated Issue Reporting with Screenshots — Implementation Roadmap

Location: docs/devops/USER_ISSUE_REPORTING_ROADMAP.md
Status: Draft
Created: 2026-03-02


Overview

Enable users to self-report issues with automatic/manual screenshots and comments. This extends the existing feedback module to support rich media attachments, leveraging the blob module for Azure Blob storage.

Use Cases

  1. Bug Report with Screenshot — User encounters error → taps "Report Issue" → screenshot captured → typed description submitted
  2. Feature Request with Mockup — User uploads annotated screenshot showing desired UI change
  3. Crash Auto-Report — App crashes → on restart, user prompted to "Send crash report with screenshot"
  4. Support Chat Attachment — Screenshots attached to existing feedback for back-and-forth with support team

Current State

Existing Feedback Module

Component Status
POST /api/feedback Creates feedback (type, title, body, screen)
GET /api/feedback Admin list/query
PUT /api/feedback/:id Admin triage (status, adminNotes)
Screenshot support Only text screen field
Multiple attachments Not supported
Threaded comments Not supported

Existing Blob Module (Reusable)

Component Status
POST /api/blob/sas Generate SAS URL for direct upload
Azure Blob integration Storage + lifecycle
Container management Per-product isolation

Target Architecture

User Flow:
1. User taps "Report Issue" in app
2. Client captures screenshot (optional annotation)
3. Client requests SAS URL: POST /api/feedback/sas
4. Client uploads image directly to Azure Blob
5. Client submits feedback: POST /api/feedback (with screenshotBlobPath)
6. Admin views feedback in dashboard with image preview

Data Model Changes

Option A: Inline Screenshot (Simple)

// feedback/types.ts — Add to existing FeedbackDoc
interface FeedbackDoc {
  // ... existing fields ...
  
  // Screenshot attachment (single)
  screenshotBlobPath?: string;        // "feedback/{productId}/{feedbackId}/{screenshotId}.png"
  screenshotUrl?: string;             // Time-limited SAS URL for viewing
  screenshotUrlExpiresAt?: string;   // When SAS URL expires
  
  // Device context for debugging
  deviceContext?: {
    osVersion: string;
    appVersion: string;
    deviceModel: string;
    screenResolution: string;
    locale: string;
  };
}

// Add to CreateFeedbackSchema
screenshotBlobPath: z.string().optional(),
deviceContext: z.object({
  osVersion: z.string(),
  appVersion: z.string(),
  deviceModel: z.string(),
  screenResolution: z.string(),
  locale: z.string(),
}).optional(),

Option B: Separate FeedbackAttachments Container (Extensible)

// feedback/types.ts — New attachment model
interface FeedbackAttachmentDoc {
  id: string;                         // att_<uuid>
  feedbackId: string;                 // Parent feedback (partition key)
  productId: string;
  
  // Blob storage
  blobPath: string;                   // "feedback/{productId}/{feedbackId}/{id}.png"
  blobUrl: string;                    // SAS URL (refreshed on fetch)
  containerName: string;              // e.g., "user-feedback"
  
  // Metadata
  fileName: string;
  contentType: 'image/png' | 'image/jpeg' | 'image/webp';
  sizeBytes: number;
  width: number;
  height: number;
  
  // Capture context
  capturedAt: string;
  trigger: 'manual' | 'auto_crash' | 'auto_error';
  screenName?: string;
  
  createdAt: string;
}

interface FeedbackDoc {
  // ... existing fields ...
  
  // Reference to attachments
  attachmentCount: number;            // Denormalized counter
  hasScreenshot: boolean;            // Quick check for UI
}

// API changes
POST /api/feedback/:id/attachments      // Add attachment to existing feedback
GET  /api/feedback/:id/attachments      // List attachments
DELETE /api/feedback/:id/attachments/:attId  // Remove attachment (admin)

Recommendation: Start with Option A (single screenshot), migrate to Option B if multi-attachment demand arises.


API Specification

New Endpoints

Method Endpoint Auth Description
POST /api/feedback/sas User Get SAS URL for screenshot upload
POST /api/feedback User Submit feedback (with optional screenshotBlobPath)
GET /api/feedback/:id/screenshot Admin Get fresh SAS URL for viewing screenshot
DELETE /api/feedback/:id/screenshot Admin Delete screenshot (GDPR/privacy)

SAS Generation Endpoint

// POST /api/feedback/sas
// Request
{
  "contentType": "image/png",
  "sizeHint": 1024000  // Optional: 1MB hint for validation
}

// Response (201)
{
  "blobPath": "feedback/lysnrai/feedback_abc123/screenshot_xyz.png",
  "uploadUrl": "https://bytelyst.blob.core.windows.net/...?sv=...",
  "expiresIn": 300,  // 5 minutes
  "maxSizeBytes": 5242880  // 5MB limit
}

Submit Feedback with Screenshot

// POST /api/feedback
// Request
{
  "type": "bug",
  "title": "App crashes when tapping record",
  "body": "Steps: 1. Open app 2. Tap red button 3. Crash",
  "screen": "RecordingScreen",
  "screenshotBlobPath": "feedback/lysnrai/feedback_abc123/screenshot_xyz.png",
  "deviceContext": {
    "osVersion": "iOS 17.4",
    "appVersion": "2.3.1",
    "deviceModel": "iPhone15,2",
    "screenResolution": "393x852",
    "locale": "en-US"
  }
}

Implementation Phases

Phase 1: Server Foundation (2-3 days)

1.1 Data Model Extension

  • Add screenshotBlobPath to FeedbackDoc interface
  • Add deviceContext to FeedbackDoc interface
  • Update CreateFeedbackSchema with new fields
  • Add feedback_screenshots container to cosmos-init.ts (if Option B)

1.2 Repository Layer

  • Extend createFeedback() to handle screenshot metadata
  • Add generateScreenshotSas() function (wrapper around blob module)
  • Add getFeedbackWithScreenshot() with fresh SAS URL generation
  • Add deleteFeedbackScreenshot() for GDPR compliance

1.3 API Routes

  • POST /api/feedback/sas — Generate upload URL
    • Rate limit: 5 requests per 10 minutes per user
    • Validate content type (image/* only)
    • Return blob path + SAS URL
  • Update POST /api/feedback — Accept screenshot metadata
  • GET /api/feedback/:id/screenshot — Get fresh view URL
  • DELETE /api/feedback/:id/screenshot — Admin delete

1.4 Integration

  • Wire new routes into server.ts
  • Add blob container user-feedback to blob module config
  • Set lifecycle policy: 90-day TTL for user screenshots

1.5 Testing

  • Unit tests for SAS generation
  • Unit tests for feedback with screenshot submission
  • Integration test: full flow (SAS → upload → submit → view)
  • GDPR deletion test

Phase 2: Client SDK Updates (3-4 days)

2.1 TypeScript SDK (@bytelyst/feedback-client)

  • FeedbackClient.submitWithScreenshot(params)
    • Internal flow: get SAS → upload blob → submit feedback
    • Progress callbacks for upload
  • FeedbackClient.captureAndSubmit() — Auto-capture current screen

2.2 Swift SDK (iOS)

  • FeedbackManager.submit(title:body:screenshot:)
  • FeedbackManager.captureScreenshot() — UIImage → blob upload
  • Annotation overlay (optional drawing on screenshot)

2.3 Kotlin SDK (Android)

  • FeedbackManager.submitWithScreenshot()
  • MediaProjection integration for screenshot capture
  • Composable for in-app feedback sheet with screenshot preview

Phase 3: Admin Dashboard UI (2-3 days)

3.1 Feedback List Enhancements

  • Thumbnail preview of screenshot in list view
  • Filter: "Has screenshot" / "No screenshot"

3.2 Feedback Detail View

  • Full-size screenshot display (lightbox)
  • Device context panel (OS version, app version, screen resolution)
  • "Download screenshot" button
  • "Delete screenshot" (GDPR compliance)

3.3 Client Library

  • lib/feedback-client.ts — Add getScreenshotUrl(feedbackId)

Privacy & Security Considerations

PII Handling

  • Screenshots may contain sensitive user data
  • Blur regions API (client-side before upload)
  • Auto-redact: Detect and blur common PII areas (email fields, phone numbers)
  • User consent: "This screenshot may include your data. Continue?"

Retention

  • Screenshot TTL: 90 days (match feedback lifecycle)
  • On feedback deletion → cascade delete screenshot blob
  • User-initiated deletion: "Delete my feedback and screenshot"

Access Control

  • Users can only view their own screenshots
  • Admins can view all screenshots for their product
  • Fresh SAS URLs generated per view (time-limited, 15 minutes)

Open Questions

# Question Impact Suggested Answer
1 Max screenshot size? Storage cost 5MB limit, WebP compression recommended
2 Multiple screenshots per feedback? Complexity Start with 1, add array support later
3 Screenshot annotation/drawing? Client complexity Phase 2.2 for iOS, others skip
4 Auto-capture on crash? Privacy risk Opt-in only, show preview before submit
5 Video screen recording? Storage cost Future Phase 4, not now
6 Anonymous feedback allowed? Auth complexity No — require auth for accountability

Success Metrics

  • Adoption: 30% of bug reports include screenshot within 3 months
  • Resolution time: -20% time-to-resolution for reports with screenshots
  • Storage: <100GB/month for screenshots (at 1000 reports/day, 100KB avg)

Appendix: File Changes

New Files

services/platform-service/src/modules/feedback/
  ├── sas.ts                    # SAS generation helpers
  └── attachment.types.ts       # (if Option B)

Modified Files

services/platform-service/src/modules/feedback/
  ├── types.ts                  # Add screenshot fields
  ├── repository.ts             # Add SAS functions
  └── routes.ts                 # Add SAS endpoint

services/platform-service/src/lib/cosmos-init.ts
  └── Add feedback_attachments container (if Option B)

services/platform-service/src/server.ts
  └── Register feedback SAS routes

Last Updated: 2026-03-02