Skip to content

LastVet iOS Architecture Notes

API client

The veteran app talks to Configuration.apiBaseURL using Bearer JWT session exchange. Networking lives in LastVet/Core/Networking/LastVetAPIClient.swift.

Build LastVetAPIEnvironment API base URL
Debug production https://api.last.vet/api
Release production https://api.last.vet/api

LASTVET_API_ENVIRONMENT is set in checked-in Configuration/Debug.xcconfig and Configuration/Release.xcconfig. Session exchange secrets are per-environment in gitignored Secrets.xcconfig (VETERAN_SESSION_EXCHANGE_SECRET_STAGING / _PRODUCTION).

Imaging storage (envelope encryption)

As of the envelope encryption integration, veteran imaging uploads use Pattern B (API-mediated):

Flow Endpoint Client behavior
Upload POST /veteran/me/documents/imaging/upload Multipart form (file, title, documentType, optional description / documentDate). Plaintext over TLS. Server encrypts with AES-256-GCM + wrapped DEK.
Download GET /veteran/me/documents/:id/download Inline decrypted stream from API (minio_envelope). No client-side object-store URLs.

Implementation:

  • ImagingEnvelopeUpload.swift — multipart temp file + URLSessionUploadTask progress/cancel
  • LastVetAPIClient.uploadImagingDocument — Wi‑Fi guard (>50 MB), envelope POST, error mapping
  • LastVetAPIClient.downloadDocument — inline stream from API (envelope decrypt on server)

Backend requirement

Staging and production API hosts must run with:

IMAGING_STORAGE_MODE=minio_envelope

When envelope mode is active, retired presigned endpoints (/imaging/upload/init, /complete, abandon DELETE) return 410 Gone. The iOS client treats 410 on abandon as success (local dismiss of stale pending-upload banners).

Caddy on lastvet-edge uses 20 minute read/write timeouts to support 512 MiB uploads over slow uplinks.

Limits and UX

  • Server max object size: 512 MiB per imaging study
  • Client Wi‑Fi gate: 50 MiB on cellular (see UploadConnectivity.swift)
  • Upload progress: real percentage via URLSessionUploadTask; user can cancel mid-upload

Further reading

Provider portal (separate repo)

last.vet-provider downloads veteran documents via GET /provider/:id/veteran/:veteranId/documents/:documentId/download and expects an inline Blob. It does not implement the retired veteran presigned multipart upload flow. Envelope streaming downloads should work without provider changes; provider-originated uploads use the standard document POST (non-imaging types only in UI today).

Tests

LastVetTests/NetworkingTests/ImagingEnvelopeUploadTests.swift covers multipart temp-file writing, imaging error mapping, and 410 abandon dismiss behavior.