fix: block direct progress updates on activity-derived goals#1755
Conversation
PATCH /api/goals/[id] previously accepted any client-supplied `current`
value — including values equal to `target` — for goals whose progress is
meant to be derived from verified GitHub activity (unit: "commits" or
"prs"). This allowed goal completion without any real commits or pull
requests being made.
Changes:
- Introduce ACTIVITY_DERIVED_UNITS constant ("commits", "prs")
- Return 422 when a client attempts to set `current` on a goal tracked
by the GitHub sync endpoint; progress for those goals must flow
exclusively through POST /api/goals/sync, which reads from the GitHub
Search API
- Tighten the `current` input check to require a non-negative integer
(rejects floats, strings, and negatives more precisely)
- Add an upper-bound guard so `current` cannot exceed the goal's target
on manually tracked goals
- Add 19 focused tests covering: auth guards, input validation, the 422
block for commits/prs goals, the upper-bound check, legitimate manual
updates, and webhook dispatch on goal completion
Closes Priyanshu-byte-coder#1753
|
@Ridanshi is attempting to deploy a commit to the PRIYANSHU DOSHI's projects Team on Vercel. A member of the Team first needs to authorize it. |
GSSoC Label Checklist 🏷️@Priyanshu-byte-coder — please apply the appropriate labels before merging: Difficulty (pick one):
Quality (optional):
Validation (required to score):
|
There was a problem hiding this comment.
Thanks for your first PR on DevTrack! 🎉
A maintainer will review it within 48 hours. While you wait:
- Make sure CI is passing (type-check + lint)
- Double-check the PR description is filled out and the issue is linked
- Feel free to ask questions in Discussions if you need help
If you find DevTrack useful, a ⭐ star on the repo is always appreciated — it helps the project grow and attract more contributors!
c9d2760
into
Priyanshu-byte-coder:main
|
🎉 Merged! Thanks for contributing to DevTrack. If the project has been useful to you, a ⭐ star on the repo is the easiest way to support it — it helps DevTrack get discovered by more developers. Keep an eye on open issues for your next contribution! |
Closes #1753
Problem
PATCH /api/goals/[id]accepted any client-suppliedcurrentvalue — including one equal totarget— regardless of the goal's unit type. For goals whose progress is meant to come from verified GitHub activity (unit: "commits"orunit: "prs"), this allowed a user to mark a goal complete without a single real commit or pull request:The sync endpoint (
POST /api/goals/sync) queries the GitHub Search API and is the only trusted source for progress on activity-derived goals. Accepting client values in PATCH breaks that trust boundary.Root cause
The PATCH handler performed only
typeof current !== "number" || current < 0, which passes for any non-negative number including floats and values exceeding the goal target. No check existed for the goal's unit type.Fix
src/app/api/goals/[id]/route.tsACTIVITY_DERIVED_UNITS = new Set(["commits", "prs"]).existingGoal.unitis in that set. The error message directs callers to the sync endpoint.currentmust now be a non-negative integer (rejects floats such as5.5).currentcannot exceed the goal'stargeton manually tracked goals.Manually tracked goals (any unit other than
"commits"/"prs", e.g."hours","tasks", or custom strings) continue to accept client-supplied progress exactly as before.The GitHub sync route is unaffected — it calls
supabaseAdmin…update({ current })directly and bypasses the PATCH handler entirely.Tests
test/goals-patch-integrity.test.ts— 19 new tests:commitsgoal → 422,prsgoal → 422, regression for #1753 (settingcurrent = targetoncommits), partial update onprscurrent > target→ 400hours, custom unit, reset to 0, completing at targetAll 19 pass; the single pre-existing failure in
test/dateUtils.test.ts(timezone boundary, unrelated to goals) was already present onmainbefore this branch.