---
phase: 13-file-upload-infrastructure
plan: 01
type: tdd
wave: 1
depends_on: []
files_modified:
  - jam-ui/src/services/attachmentValidation.js
  - jam-ui/src/services/__tests__/attachmentValidation.test.js
autonomous: true

must_haves:
  truths:
    - "User selecting a file over 10 MB sees immediate error message before upload starts"
    - "User selecting unsupported file type (.exe, .zip) sees immediate error listing allowed types"
    - "User selecting valid file (.pdf, .png, .mp3) passes validation and proceeds to upload"
    - "User sees human-readable file sizes (e.g., '5.0 MB' not '5242880 bytes')"
  artifacts:
    - path: "jam-ui/src/services/attachmentValidation.js"
      provides: "File validation utilities"
      exports: ["validateFileSize", "validateFileType", "getAttachmentType", "validateFile", "formatFileSize", "MAX_FILE_SIZE", "ALLOWED_EXTENSIONS"]
      min_lines: 60
    - path: "jam-ui/src/services/__tests__/attachmentValidation.test.js"
      provides: "Unit tests for validation service"
      min_lines: 80
  key_links:
    - from: "jam-ui/src/services/attachmentValidation.js"
      to: "Phase 13 Plan 03"
      via: "Import in JKSessionScreen for validation before upload"
      pattern: "validateFile"
---

<objective>
Create file validation service with TDD methodology for client-side attachment validation

Purpose: Validate file size (10 MB limit) and type (extension whitelist) before upload attempt, preventing wasted uploads and providing immediate user feedback. This is a foundational service used by the upload flow in Plan 03.

Output: `attachmentValidation.js` service with exported validation functions and comprehensive test suite
</objective>

<execution_context>
@/Users/nuwan/.claude/get-shit-done/workflows/execute-plan.md
@/Users/nuwan/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/12-attachment-research-&-backend-validation/docs/REACT_INTEGRATION_DESIGN.md

# Validation requirements from research
# - 10 MB max file size (matches legacy AttachmentStore)
# - Extension whitelist: .pdf, .xml, .mxl, .txt, .png, .jpg, .jpeg, .gif, .mp3, .wav
# - Attachment type: 'audio' for .mp3, .wav, .flac, .ogg, .aiff, .aifc, .au; 'notation' for others
# - Backend-supported extensions differ slightly (no .mp3 yet) - validation should warn
</context>

<feature>
  <name>Attachment Validation Service</name>
  <files>
    jam-ui/src/services/attachmentValidation.js
    jam-ui/src/services/__tests__/attachmentValidation.test.js
  </files>
  <behavior>
    ## validateFileSize(file, maxSizeBytes?)
    - Input: File object, optional max size (default 10 MB)
    - Output: { valid: boolean, error: string|null }
    - Cases:
      - 5 MB file -> { valid: true, error: null }
      - 15 MB file -> { valid: false, error: "File exceeds 10 MB limit" }
      - Exactly 10 MB -> { valid: true, error: null }

    ## validateFileType(file, allowedTypes?)
    - Input: File object, optional allowed extensions array
    - Output: { valid: boolean, error: string|null }
    - Cases:
      - "document.pdf" -> { valid: true, error: null }
      - "music.mp3" -> { valid: true, error: null }
      - "virus.exe" -> { valid: false, error: "File type not allowed..." }
      - "DOCUMENT.PDF" (uppercase) -> { valid: true, error: null }

    ## getAttachmentType(filename)
    - Input: filename string
    - Output: 'audio' | 'notation'
    - Cases:
      - "song.mp3" -> 'audio'
      - "track.wav" -> 'audio'
      - "sheet.pdf" -> 'notation'
      - "image.png" -> 'notation'

    ## validateFile(file)
    - Input: File object
    - Output: { valid: boolean, error: string|null, warnings: string[] }
    - Combines size + type validation
    - Adds warning if extension not in backend-supported list (e.g., .mp3)

    ## formatFileSize(bytes)
    - Input: number (bytes)
    - Output: string
    - Cases:
      - 500 -> "500 B"
      - 2048 -> "2.0 KB"
      - 5242880 -> "5.0 MB"
  </behavior>
  <implementation>
    Follow REACT_INTEGRATION_DESIGN.md Section 7 "File Validation Service" exactly.

    Constants to export:
    - MAX_FILE_SIZE = 10 * 1024 * 1024 (10 MB in bytes)
    - ALLOWED_EXTENSIONS = ['.pdf', '.xml', '.mxl', '.txt', '.png', '.jpg', '.jpeg', '.gif', '.mp3', '.wav']
    - BACKEND_SUPPORTED_EXTENSIONS = ['.pdf', '.xml', '.mxl', '.txt', '.png', '.jpg', '.jpeg', '.gif', '.wav', '.flac', '.ogg', '.aiff', '.aifc', '.au']
    - AUDIO_EXTENSIONS = ['.mp3', '.wav', '.flac', '.ogg', '.aiff', '.aifc', '.au']

    TDD Cycle:
    1. RED: Write test for validateFileSize -> test fails
    2. GREEN: Implement validateFileSize -> test passes
    3. RED: Write test for validateFileType -> test fails
    4. GREEN: Implement validateFileType -> test passes
    5. (continue for each function)
    6. REFACTOR: Clean up if needed
  </implementation>
</feature>

<verification>
```bash
# Run validation service tests
cd /Users/nuwan/Code/jam-cloud/jam-ui && npm run test:unit -- attachmentValidation

# Expected: All tests pass (15+ test cases)
# Coverage: 100% for attachmentValidation.js
```
</verification>

<success_criteria>
1. All 5 exported functions implemented and tested
2. Test file has 15+ test cases covering edge cases
3. All tests pass with `npm run test:unit -- attachmentValidation`
4. No console errors or warnings
5. File matches structure from REACT_INTEGRATION_DESIGN.md Section 7
</success_criteria>

<output>
After completion, create `.planning/phases/13-file-upload-infrastructure/13-01-SUMMARY.md`
</output>
