Sample Audit-to-Fix Report
What the Audit-to-Fix Package ($697) actually delivers — worked on a composite, fictional "Practice" feature for a kirtan-practice app, in the same Flutter + Node shape as the brief this service is built to answer.
sample-deliverable/ in the project repo.
Scope
A "Practice" feature: a user starts a timer, logs a kirtan practice session (raag, shabad, duration), and sees a day streak and weekly-goal progress. Built once correctly, then re-built the way real audits usually find things, then fixed — so every finding below is demonstrated in actual code and, on the Node side, an actual executed test.
Node backend findings
All 8 proven by one command — npm test runs 18 tests: one confirming each bug is real against the unpatched code, one confirming each fix holds. All 18 pass.
| # | Sev | Finding | Fix |
|---|---|---|---|
| 1 | P1 | Practice-day boundary computed from raw server UTC instead of the user's local timezone — a late-night session gets silently bucketed into the wrong day, breaking streaks for anyone not in UTC. | Computed from a client-supplied timezone offset. |
| 2 | P1 | A second session on the same calendar day incremented the streak again instead of just extending that day. | Same-day sessions no longer re-increment; only a new calendar day does. |
| 3 | P1 | No input validation on duration — a negative or NaN value was accepted and corrupted the user's running total permanently. | Rejected with a clear error before it touches any state. |
| 4 | P0 | Lost-update race condition: two concurrent requests for the same user both read the same "before" snapshot — whichever write lands last silently overwrites the other's update, with no error and no log. | Per-user async lock serializes writes. |
| 5 | P1 | No idempotency check — a client-side retry after a lost response created a fully duplicate session, double-counting minutes. | A client-supplied idempotency key dedupes retries. |
| 6 | P0 · security | IDOR — the "read a user's sessions" endpoint never checked the requester's identity against the target user. | Requester identity checked against the target user; unauthorized reads return 403. |
| 7 | P2 | A weekly goal of 0 produced Infinity/NaN, sent straight to the client where the progress-bar widget would crash or render garbage. | Returns a safe "no goal set" result instead of a non-finite number. |
| 8 | P1 | No error boundary around the async persistence call — a transient failure became an unhandled promise rejection, which under Node's default behavior can crash the entire process for every connected user. | Wrapped in try/catch; clean 400/500 responses, process stays up. |
$ npm test
✔ 18 tests, 18 passed, 0 failed
Flutter client findings
Four classic, audit-worthy findings on the same screen. No Flutter SDK was available in the environment this was written in, so these were verified by careful manual construction plus an independent Dart/Flutter code review rather than a green CI run — stated plainly rather than glossed over.
| # | Sev | Finding | Fix |
|---|---|---|---|
| 1 | P1 | A practice-session Timer was started but never cancelled in dispose() — navigating away mid-session leaves it calling setState on a widget that no longer exists. | _timer?.cancel() added to dispose(). |
| 2 | P1 | No mounted check after an await on the network call before calling setState — leaving the screen mid-request throws the same class of crash. | if (!mounted) return; immediately after the awaited call. |
| 3 | P1 | No try/catch around the network call — any failure left the submit button's spinner stuck forever with an uncaught exception. | Wrapped in try/catch; a visible, recoverable error state with a Retry action. |
| 4 | P2 · perf | A new repository (and its underlying HTTP client) was constructed on every submit instead of reused — a slow, steady resource leak invisible in a quick demo. | Repository injected once and reused for the widget's lifetime. |
What a real engagement looks like
This is the shape of every fix delivered under the Bug-Fix Sprint or Audit-to-Fix Package: a patched branch/PR against the real repo, a written fix log mapped to each audit line item exactly like the tables above, and — wherever the existing codebase has a test setup, as most live Flutter/Node apps do — tests that prove the fix the way npm test proves it here.