01Project Health Scorecard
Overall Score
02Product Roadmap
03Session Velocity
04Next Session Planner
Priority-ordered tasks for the next development session. All are P1 critical security fixes.
Active secret exposure — every day they remain is a breach risk
Anonymous users can delete images, tags, and lists right now
Authenticated users can act as any other user
Attacker can forge JWT and log in as any email address
API credentials visible in HTTP responses on public endpoints
05Risk Register
06Audit Recommendations
07Findings History & Patterns
08Tooling & Workflow
09Overall Progress
10P1 — Critical
DB password, mail password, Foursquare client ID/secret, Laravel APP_KEY all exposed in committed file.
Backend uses 'name' column, TypeScript and Kotlin expect 'tag_name'. Tag names deserialize as null/undefined.
Backend stores short_description, all clients expect description. Profile bios fail to save/load.
iOS calls pre-define-search-tags (CategoryController), docs say search-tags (TagController). New clients will call wrong endpoint.
MySQL password, username, all 8 WordPress auth salts exposed on disk.
image-delete, tags-delete, tastemakerlist-delete outside auth:api middleware. Anonymous users can delete data.
FCM server key, hardcoded device token, Google OAuth client ID in plaintext source code.
jwtTokenDcode() only base64-decodes. Signature never verified against Apple JWKS. Attacker can forge any email.
Active echo/print_r statements output full API URL with credentials in HTTP responses.
Unauthenticated GET /clear-cache runs cache:clear, config:clear, config:cache, route:clear, view:clear.
Multiple endpoints accept user_id from request instead of Auth::user()->id. Any user can act as another.
Zero indexes on FK columns in 3 most-queried pivot tables. Every JOIN triggers full table scan.
Loads ALL tastemakers then runs 2+ queries per tastemaker per restaurant. 100 tastemakers = 600+ queries.
Google/Apple login stores raw OAuth token in password field without Hash::make().
env() called 12+ times for Foursquare credentials. Returns null after php artisan config:cache.
P2 — Important
Types define inner data but not envelopes. Backend wraps in { status, ... }. apiFetch<T>() calls will fail.
Empty Hilt DI directory, google-services plugin fails without config file. Project cannot build.
Auth token in localStorage accessible to all JavaScript. Single XSS = full account takeover.
SaveRestaurantRequest includes user_id field sent to backend, masking IDOR vulnerability.
PHP stack traces revealing /home/tastofgc/public_html/ internal paths.
tastemaker, testmaker (228x), testsmaker, testemakers, TasteMaker across codebase.
Google Play Services, Firebase, camera permissions at scaffold stage. Blocks compilation.
Only default 60 req/min throttle. OTP uses rand() not random_int(). OTP never expires.
RestaurantController (2,985 LOC) and UserController (1,623 LOC) handle 9+ domains each.
Raw cURL duplicated 7 times. CURLOPT_TIMEOUT=0 (infinite). limit=500. No caching.
CURLOPT_SSL_VERIFYPEER=false. Vulnerable to MITM intercepting FCM server API key.
VARCHAR columns force string-to-numeric cast in Haversine formula (duplicated 16 times). No spatial index.
role_id, password, forget_code, login_count in $fillable. Any unvalidated create/update = privilege escalation.
8 admin delete operations use Route::get(). Not protected by CSRF middleware.
HomeController and RestaurantController use $_POST/$_FILES directly, bypassing middleware.
All validation inline with empty rules like "password" => "". No app/Http/Requests/ directory.
forget_code has no expiration timestamp. OTP remains valid indefinitely.