feat: add blob upload service for embed thumbnail management
Implement blob upload service to fetch images from URLs and upload them to
PDS as atproto blobs, enabling proper thumbnail storage for external embeds.
**Service Features:**
- UploadBlobFromURL: Fetch image from URL → validate → upload to PDS
- UploadBlob: Upload raw binary data to PDS with authentication
- Size limit: 1MB per image (atproto recommendation)
- Supported MIME types: image/jpeg, image/png, image/webp
- MIME type normalization (image/jpg → image/jpeg)
- Timeout handling (10s for fetch, 30s for upload)
**Security & Validation:**
- Input validation (empty checks, nil guards)
- Size validation before network calls
- MIME type validation before reading data
- HTTP status code checking with sanitized error logs
- Proper error wrapping for debugging
**Federated Support:**
- Uses community's PDS URL when available
- Fallback to service default PDS
- Community authentication via PDSAccessToken
**Flow:**
1. Client posts external embed with URI (no thumb)
2. Unfurl service fetches metadata from oEmbed/OpenGraph
3. Blob service downloads thumbnail from metadata.thumbnailURL
4. Upload to community's PDS via com.atproto.repo.uploadBlob
5. Return BlobRef with CID for inclusion in post record
**BlobRef Type:**
```go
type BlobRef struct {
Type string `json:"$type"` // "blob"
Ref map[string]string `json:"ref"` // {"$link": "bafyrei..."}
MimeType string `json:"mimeType"` // "image/jpeg"
Size int `json:"size"` // bytes
}
```
This enables automatic thumbnail upload when users post links to
Streamable, YouTube, Reddit, Kagi Kite, or any URL with OpenGraph metadata.