System architecture
High-level architecture
Section titled “High-level architecture”Golfer client (web / iOS / Android / watch) | vAzure API Management / App Service-hosted API | +--> Application services and orchestration | +--> Foundry agents / fallback recommendation logic | +--> OpenGolf integration | +--> Speech synthesis | +--> PostgreSQL (system of record) | +--> Blob storage (image/avatar bytes only)Why the architecture is split this way
Section titled “Why the architecture is split this way”- Clients own capture, immediate presentation, and platform-native UX concerns.
- The API owns validation, persistence, orchestration, and integration boundaries.
- PostgreSQL stores structured entities and relationships.
- Blob storage stores binary assets only.
- AI Foundry is treated as an orchestrated pipeline, not a single monolithic step.
Runtime request path
Section titled “Runtime request path”Upload and analyze
Section titled “Upload and analyze”- A client posts
multipart/form-datatoPOST /api/photos/upload. PhotosControllervalidates the request, resolves user ownership, and derives optional location context.PhotoServicesaves the image and metadata.ShotAnalysisPipelineloads swing averages, attempts Foundry lie analysis, loads profile personalization, and requests stance guidance.- If agent calls fail, built-in fallback recommendation logic still returns a usable answer.
- The API updates the photo’s analysis and returns the full photo payload.
Speech playback
Section titled “Speech playback”- The client requests
GET /api/photos/{id}/speech. - The API builds a spoken summary from the shot analysis.
SpeechSynthesisServicerenders MP3 audio.- The client plays the result immediately.
Authentication model
Section titled “Authentication model”- Microsoft Entra External ID is the main golfer identity source.
- Azure API Management validates tokens at the edge.
- The API still configures bearer authentication so application code can resolve the current caller.
- Development auth can impersonate a test user only in development.
Data ownership model
Section titled “Data ownership model”Each golfer’s data is scoped by a canonical user id derived from authentication. Controllers and repositories preserve per-user separation so one golfer cannot read another golfer’s uploads or profile data by id alone.