Skip to content

fix(android): reject manual workouts ending in the future - #1067

Open
TAKEOFF69 wants to merge 1 commit into
ryanbr:mainfrom
TAKEOFF69:fix/manual-workout-future-end
Open

fix(android): reject manual workouts ending in the future#1067
TAKEOFF69 wants to merge 1 commit into
ryanbr:mainfrom
TAKEOFF69:fix/manual-workout-future-end

Conversation

@TAKEOFF69

Copy link
Copy Markdown

What this PR does

Reject manual workout rows whose computed end timestamp is later than the injected wall-clock nowSeconds. The check also guards the start-plus-duration addition against Long overflow. A workout ending exactly at nowSeconds remains valid.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • CI / tooling

How it was tested

  • android/gradlew.bat testFullDebugUnitTest --no-daemon --dependency-verification=off --console=plain — 3,448 tests, 0 failures, 0 errors (5 pre-existing skips).
  • android/gradlew.bat testFullDebugUnitTest --tests com.noop.ui.WorkoutEditingTest --no-daemon --dependency-verification=off --console=plain — 41 tests, 0 failures, 0 errors.
  • android/gradlew.bat assembleFullDebug --no-daemon --dependency-verification=off --console=plain — passed.
  • Focused cases cover end exactly at nowSeconds, one second beyond nowSeconds, and Long.MAX_VALUE addition overflow.
  • No BLE or hardware behavior changed; real-hardware evidence is not applicable.

The local --dependency-verification=off flag only bypasses the existing unpinned Windows AAPT2 artifact in this checkout; no verification metadata was changed. Standard CI runs the commands without that local workaround.

Checklist

  • Swift package tests pass for any package I touched (swift test in Packages/<name>)
  • Android unit tests pass if I touched android/ (./gradlew testFullDebugUnitTest)
  • No new build warnings introduced
  • UI changes use only StrandDesign tokens — no hardcoded colors, fonts, or spacing
  • No hardcoded hex frame bytes; protocol facts live in the schema / decoders
  • Follows the conventions in docs/CONTRIBUTING.md
  • I did not commit generated output (Strand.xcodeproj/) or any secrets/keystores

Related issues

Not applicable — this is a deterministic Android input-validation fix with focused regression coverage.

@ryanbr ryanbr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Android fix is clean — end > now → null with end-exactly-at-now staying valid is the right rule, and the tests pin all three edges (now, +1s, overflow). The overflow guard is only reachable by the synthetic Long.MAX case since durationMin is already bounded to 1..1440, which your comment nicely calls out.

One thing before merge though: the same bug exists on iOS and isn't fixed here. Strand/Data/WorkoutSource.swift buildManualRow guards start <= now but computes endTs = s + durationMin * 60 with no future-end check — and ManualWorkoutSheet only constrains the start (its DatePicker is in: ...Date(), duration goes to 24h). So start = now - 30s, duration = 45min still stores a workout ending ~44 min in the future on iOS — exactly the row this PR now rejects on Android.

That matters because ManualWorkoutSheet's own header says these inputs are "validated by WorkoutSource.buildManualRow (the same honest-row rules the engine uses)" — the intent is one shared rule across platforms, and a future-ending WorkoutRow feeds rescoreManualWorkouts / zones downstream. Could you mirror the guard into the Swift twin so the two stay in sync? It's basically:

let end = s + durationMin * 60
guard end <= Int(now.timeIntervalSince1970) else { return nil }

(Swift Int is 64-bit and durationMin ≤ 1440, so no overflow guard needed there.) With that folded in, one PR fixes both platforms and I'm happy to merge. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants