feat: phase 3 part 2 - CDN endpoints with live URL caching system
Implement public CDN endpoints for serving images and live URL generation
with intelligent caching based on prompt hashing.
**CDN Routes (Section 8):**
- **GET /cdn/:orgSlug/:projectSlug/img/:filenameOrAlias**
- Public endpoint (no authentication)
- Serve images by filename or project-scoped alias
- Resolves org and project from slugs
- Supports @alias syntax or filename lookup
- Returns image bytes with 1-year cache headers
- Headers: Content-Type, Content-Length, Cache-Control, X-Image-Id
- **GET /cdn/:orgSlug/:projectSlug/live/:scope**
- Public endpoint (no authentication)
- Live URL generation with caching
- Query params: prompt, aspectRatio, autoEnhance, template
- Cache key: SHA-256(projectId + scope + prompt + params)
- Cache HIT: Returns cached image immediately
- Cache MISS: Generates new image, caches, returns
- Scope management: auto-create or check limits
- Image meta tracking: scope, isLiveUrl, cacheKey
- Headers: X-Cache-Status (HIT/MISS), X-Scope, X-Image-Id, X-Generation-Id
**Cache Key Helper:**
- computeLiveUrlCacheKey() - SHA-256 hash for live URL caching
- computePromptHash() - SHA-256 hash for prompt caching
- Normalized parameters for consistent cache keys
**Live URL Flow (Section 8.3):**
1. Validate prompt and scope format (alphanumeric + hyphens + underscores)
2. Resolve org, project from slugs
3. Compute cache key from params
4. Check cache via images.meta.cacheKey
5. If HIT: serve cached image
6. If MISS: check scope limits, generate, cache, serve
7. Lazy scope creation with project defaults
8. Enforce newGenerationsLimit per scope
**Service Exports:**
- Added LiveScopeService to core services index
- Available for dependency injection
**App Routing:**
- Mounted CDN router at /cdn (public, before auth routes)
- CDN endpoints are completely public (no API key required)
**Technical Notes:**
- Images tagged with meta: { scope, isLiveUrl: true, cacheKey }
- Scope statistics computed from images with matching meta
- Cache controlled via Cache-Control: public, max-age=31536000
- System generations use apiKeyId: null
- All code compiles with zero new TypeScript errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>