Target: school.34.jugaar.ai · Date: 2026-08-27 · Tester: X2 automated + manual flow
Core complaint flow + AI work end-to-end. The entire SPA-fallback routing is broken, the marquee "decoy password" feature is marketing-only, and a critical PHP error page crashes with a server-path leak.
Created qa_test_1787797203 / TestPass123!, walked through 7-step onboarding, logged out, logged back in with username. Field name is login on the form, username on register — minor inconsistency.
Got handle SharpFalcon302 on my filed complaint. Marketing claims "BraveFalcon342" — the pattern matches.
POST /complaints/new → 302 to /complaints/view?token=035670eab5575f47f2457b2cb677d4d1. Status auto-set to verified, auto-categorized to Sanitation / Cleanliness within ~30 seconds. Public view shows only anonymous handle — no user PII leaked.
POST /api/vouch with another user's cid → {"vouched":true,"vouch_count":1,"status":"verified"}. Trying to vouch my own complaint (cid=23) → {"error":"Cannot vouch your own complaint"}. CSRF enforced (mismatched token → 403).
POST /api/ai/chat with prompt about school toilets → returns structured Pakistani-school context advice. Returns 401 unauth — proper gating.
POST /api/ai/draft with "GHS Kotla toilet is dirty" → returns full structured object: title, description, category="sanitation", category_id=6, severity=3, sentiment="negative", confidence=0.7, school{school,branch,city,province,district,geo,confidence}, missing[], council. Excellent schema.
GET /api/schools → 2 schools (PECHS Govt Girls College + Programmer Girls School). GET /api/geo.php?type=schools_map → 2 markers with lat/lng. Both Content-Type: application/json.
After filing + vouches: 3 → 4 Complaints, 5 → 6 Voices. Trending chart picked up new "Sanitation/Cleanliness" category automatically. School rankings, district clustering (Karachi East: 4 complaints), category funnel, status funnel all render.
Finder has typo-tolerant search; compare.php has a real comparison view; per-school view shows 30-facility tracker, complaints, location.
Unauth /admin/users → 302 /auth/login. Logged-in regular user /admin → 403 "Super Admin only". Logged-in user /admin/users → 302 to /pages/error.php?c=403 (which itself crashes — see bug #1).
HSTS (max-age=31536000; includeSubDomains), CSP (default-src 'self' with cdn exceptions), X-Frame-Options: SAMEORIGIN, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin.
manifest.json valid (with icon-192/512), sw.js caches dashboard/roadmap/CSS and serves offline.html fallback, IndexedDB draft store declared.
Mismatched or missing _csrf on POST → 403 Invalid CSRF token. Per-session token rotation on login.
Token-based share URL shows: title, description, category, school, anonymous handle, share count, view count. No user_id joined, no email/phone/IP surfaced.
GET /pages/error.php?c=403
Fatal error: Uncaught Error: Undefined constant "SESSION_NAME" in /home/school/public/pages/error.php:3
Stack trace:
#0 {main}
thrown in /home/school/public/pages/error.php on line 3
The 403 handler itself is broken. Returns 200 OK with the absolute server path /home/school/public/pages/error.php exposed. This is the page every admin-blocked route redirects to. Fix: either define('SESSION_NAME','') at top of file, or set display_errors=Off in production php.ini.
The homepage hero stats claim "2 Passwords (decoy)" and the entire anonymity pitch — including the "What if someone forces me to show my account?" FAQ answer — rests on the user having a second password that opens an empty decoy account.
Reality: registration form has ONE password field. Login form has no decoy field. /profile, /account, /settings, /auth/decoy — all return the homepage HTML (no actual routes exist). Every "decoy" mention in any response is copy-pasted from the SPA marketing fallback.
Tested against:
curl /auth/register | grep -ciE 'decoy|fake.password|second.password|plausible' → 0 curl /auth/login | grep -ciE 'decoy|fake.password|second.password|plausible' → 0 curl /profile /account /settings /auth/decoy → 8 matches (all in SPA marketing HTML) curl /onboarding | grep -ci decoy → 0
This is a false-safety claim on a whistleblower platform. If a student trusts this and gets coerced into opening their account under a teacher/principal's eyes, they have NO real protection — there's no decoy, the teacher sees everything. Remove the claim or build the feature.
GET /complaints/mine (session cookie present)
Returns HTTP 200 with the homepage HTML body (38341 bytes). A logged-in user has NO WAY to see their own filed complaints via the UI — they have to have saved the share tokens manually. Same problem on /track/X (public token lookup).
GET /track?code=035670eab5575f47f2457b2cb677d4d1
Returns the homepage HTML. The FAQ says "You can track status publicly while staying anonymous" — there is no working public tracking URL. Only /complaints/view?token=X works, and only if you kept the share link.
/admin/login returns homepage HTML. All admin routes redirect to /auth/login then check role. Discoverability for an admin finding their login URL is poor — and /admin POST returns 200 (homepage), suggesting the POST handler may not exist.
Should return a real robots policy. Currently every "bot disallowed" path is implicitly allowed since it's all the same SPA page.
No sitemap for SEO. With "129 Districts, 7 Provinces, 24 Categories" as headline, this is a missed SEO play — Google can't crawl the deep pages.
My test complaint ("QA automated test complaint - please ignore") was auto-verified by "system" within 2 minutes, despite zero vouches, brand-new account, plain text, no evidence. Trivially inflatable — anyone can spam the public dashboard with verified complaints to weaponize rankings or harass schools.
"24 Categories 129 Districts 7 Provinces 100+ Confirm to reveal 10d Reports to reveal 2 Passwords (decoy) 30 Facilities tracked" — but only 2 schools in DB (both in Karachi East), 0 districts actually populated, 0 facilities filled in.
Strict-ish CSP exists but allows inline/eval scripts — service worker, AI widget, and view-page inline scripts all rely on it. For a whistleblower platform handling child-safety complaints, this should be tightened.
Should return a real 403 page. Currently indistinguishable from "this page doesn't exist."
Only /api/schools, /api/geo.php, /api/vouch, /api/ai/* are real JSON endpoints. The complaint-form's category dropdown populates from somewhere else (looks like inline JSON baked into /complaints/new) — these API endpoints are dead.
Returns 19KB of HTML with the page shell but no threads/posts visible. Feature appears seeded but inactive.
Login uses name="login", register uses name="username" — same field, different names. Minor but confusing for anyone reading the HTML to script against.
Classic SPA-fallback trap. A status-code-only healthcheck would mark /api/health, /api/v1/health, /openapi.json, /docs, /admin/login, /track/X all as 200 OK. Always probe for distinct title/size/content-type when health-checking.
| Claim | Tested | Outcome |
|---|---|---|
| "2 Passwords (decoy)" | Registration + login forms, all profile routes | FALSE — only 1 password field, no decoy anywhere |
| "Anonymous handle like BraveFalcon342" | Registered + filed complaint | TRUE — got "SharpFalcon302" |
| "AI verification / Mimo auto-categorizes" | Filed test complaint + viewed | TRUE — auto-verified + categorized in ~30s |
| "30 Facilities tracked (0→100%)" | School profile page | PARTIAL — "1/30 Facilities" badge shows, no edit form |
| "100+ Confirm to reveal teacher name" | Teacher section | UNTESTABLE — 0 teacher complaints exist; rule not exercised |
| "WhatsApp · SMS · USSD coming soon" | Homepage banners | OK — labeled "COMING SOON" explicitly |
| "Bank-grade password security" | Headers + registration | TRUE — HSTS + CSP present, no PII leaks in HTML |
| "Even Super Admin cannot reverse-map" | Logged in as user, viewed public complaint | APPEARS TRUE — view shows handle only, no user_id joined |
| "24 Categories" | Complaint form category dropdown | TRUE — 18+ categories enumerated |
| "PWA offline drafts auto-sync" | sw.js + manifest | TRUE — IndexedDB store declared, sync handler present |
Test account created:
username: qa_test_1787797203 · password: TestPass123! · email: qa.student.1787797203@example.comFiled complaint token:
035670eab5575f47f2457b2cb677d4d1 → Sanitation/Cleanliness @ Programmer Girls School · status=Verified · handle=SharpFalcon302Vouched on 2 seed complaints: cid=18 (electricity), cid=19, cid=20 — each returned {"vouched":true,"vouch_count":1,"status":"verified"}
Pre-test platform state: 2 schools (Karachi East only), 3 complaints, 5 voices
Post-test platform state: 2 schools, 4 complaints, 6 voices (counters updated live)