Back to portfolio

Chapter 04 - Mobile and backend engineering

Strava AI Insights

Live case study

A Strava companion whose owner audited his own product like an attacker, found a missing auth layer and IDOR chain, then shipped signed sessions, token encryption, controller security tests, and native-image fixes.

Strava AI Insights Android and coaching backend preview
2026-06-10

self-audit material located and source checked

PR #13

native AOT token-encryption key fix merged

Open gates

live OAuth, device QA, migrations, and revocation remain visible

Thesis

The case study is the audit arc, not a perfect product story.

The product combines a Spring Boot backend, native Android, Strava OAuth, AI insight generation, and training surfaces. The stronger engineering signal is that the audit found exploitable trust boundaries, then turned them into token-only sessions, ownership checks, encrypted local/server storage, and regression tests.

Arus L5 ledger ownership lesson

The same lesson appears in Arus: never accept resource ownership from the caller when the server can derive it from the credential boundary.

Strava AI Insights ingestion and auth boundaryStrava OAuth issues a signed mobile session; Android calls authenticated activity APIs; ingestion and AI services persist insights and search documents.token onlydeep linkBearerowned activitypersist insightStrava OAuthstate cookie + callbackSigned sessionHMAC token deep linkAndroid appEncrypted preferencesActivity APIsBearer ownership checkAI pipelineGemini + DeepseekPostgres + searchEncrypted tokensBoundary: Strava tokens stay server-side; Android receives a signed session token, not a trusted athleteId.

Security honesty

Found -> fixed, with the remaining limits left visible.

These rows come from the 2026-06-10 audit material and the source repositories' `origin/main` history. The table only marks an item fixed when a commit, source file, or test file exists.

FindingFoundFixed evidenceStatus
Client-trusted athleteId created an IDOR chainThe audit found activity endpoints and Android flows that trusted client-supplied athlete IDs after OAuth.Backend origin/main includes SessionTokenService, OAuthStateService, ActivityAuthInterceptor, and WebMvcConfig; Android tests require token-only deep links and Authorization headers on backend requests.Source: Backend commit 5af7b0d; android LoginDeepLinkParserTest.kt and ApiServiceTest.kt; evidence SA.Fixed
Plain Strava tokens were stored in database columnsThe project stored Strava access and refresh tokens as normal athlete fields before the hardening slice.EncryptedTokenConverter encrypts non-empty tokens with AES-GCM, permits legacy plaintext reads for migration, and defers key lookup for native AOT processing.Source: Backend merges bd83e9e and b0eff1d; EncryptedTokenConverterTest.java.Fixed
Global mobile search could expose other athletesThe Android client called a global activity search path, and docs described cross-athlete search as a P0 production-readiness risk.Android now calls the athlete-scoped route, backend search fallback receives athleteId, and tests pin the scoped Retrofit route and fallback behavior.Source: Backend merge bd83e9e; android commit 2b1b491; ActivitySearchServiceTest and ApiServiceTest.Fixed
Malformed webhooks and CSV imports had unsafe failure modesWebhook shape assumptions could throw, and unknown CSV dates could silently become current timestamps.Webhook and CSV parsing tests cover safe acknowledgement, deterministic date parsing, and invalid-row skipping.Source: StravaWebhookControllerTest.java and ActivityServiceTest.java on backend origin/main.Fixed

Open item

No full Spring Security migration or session revocation yet

The current boundary is an explicit first-party HMAC session layer. Server-side revocation and a full Spring Security integration remain out of scope.

Source: strava-ai-insights/docs/code_review.md

Open item

Real Strava OAuth and device QA remain release gates

The audit docs record local tests, not a physical-device OAuth walkthrough or live Strava callback proof for this pass.

Source: strava-ai-insights/docs/test_analysis.md

Open item

Hibernate-managed schema still needs migration discipline

Feature docs repeatedly call out Flyway or Liquibase adoption as a follow-up before stronger production rollout claims.

Source: strava-ai-insights/docs/system_analysis.md

Open item

Diagnostic search remains behind bearer auth

Mobile no longer uses global search, but backend origin/main still contains a debug search path. Do not claim every diagnostic search surface was deleted.

Source: family-finance/docs/docs/system-analysis/2026-06-11-v01-strava-telegram-case-study-evidence-sa.md

Feature evidence

Product claims stay bound to repository artifacts.

OAuth onboarding

The Android flow uses the Strava callback to receive a signed session token and stores it in encrypted preferences for API calls.

Source: strava-ai-insights/docs/walkthrough.md

AI insight pipeline

The backend fetches Strava activities, persists activity rows, creates Gemini quick insight text, and supports Deepseek weekly reasoning reports.

Source: strava-ai-insights/docs/system_analysis.md

Training surfaces

Repository docs and tests cover physiology profile, push tokens, daily readiness, workload summary, training plan, weekly digest, and coach chat contracts.

Source: strava-ai-insights/docs/PRD.md

Evidence trail

No fake screenshots, transcripts, or unproven metrics.

  • 2026-06-10 Auth Foundation Security Fix
    strava-ai-insights/docs/PRD.md
  • Auth foundation implementation plan
    strava-ai-insights/docs/superpowers/plans/2026-06-10-auth-foundation.md
  • Auth foundation architecture update
    strava-ai-insights/docs/system_analysis.md
  • Auth foundation code review
    strava-ai-insights/docs/code_review.md
  • Auth and native-image verification plan
    strava-ai-insights/docs/test_analysis.md
  • Backend session and activity interceptor source
    strava-ai-insights/backend/src/main/java/com/portfolio/stravainsights/security/ActivityAuthInterceptor.java
  • Backend token encryption regression tests
    strava-ai-insights/backend/src/test/java/com/portfolio/stravainsights/security/EncryptedTokenConverterTest.java
  • Android bearer contract and deep-link tests
    strava-ai-insights/android/app/src/test/java/com/portfolio/stravainsights/data/ApiServiceTest.kt
  • Portfolio evidence inventory
    family-finance/docs/docs/system-analysis/2026-06-11-v01-strava-telegram-case-study-evidence-sa.md