Maahir.io · Internal QA · v0.1

jobinterview.maahir.io — QA report

A walk-through of the candidate-facing surface, the public API, and the marketing copy. Staff-side findings are flagged for Munaf & the team to grade on their own accounts.

Target · jobinterview.maahir.io Date · 15 Oct 2026 Method · Browser + curl + JS inspection Candidates run · 1 (Bushra) + endpoint probes Status · 3 critical, 5 significant, 7 minor observed
Critical — fix before any external use Significant — fix this sprint Working — don't break it

01.Scope honesty

What this report covers and what it deliberately does not.

This QA was requested with a 10-candidate plan and logins for the admin, bushra (HR, ABC Trading Co.) and faizan (Manager, reviewer) accounts. Neither was available at run time, so the report is split into two halves:

  • Candidate side (covered): home, /interview-info, /start, /privacy, /register, /auth/login, full apply → welcome → profile → 8-question interview → /done. One full candidate run (Bushra) with strong answers.
  • Staff side (not covered): admin/HR dashboards, candidate reports, grading rationale, export, override flows. See section 5 — the staff QA gate — for what to check before launch.
  • Data pollution guard: only 1 published position exists (Server4Sale Accountant Internship, limit 200) with 3 real applicants. A 10-fake-candidate run would have polluted the live HR pipeline. Recommendation: 1 strong + 1 weak test candidate is enough to surface product bugs, then staff-side QA with seeded fixtures.

02.Critical findings Fix before launch

Each finding below was reproduced in-browser and would visibly embarrass a real candidate or HR reviewer.

#1Only 2 distinct questions in an 8-question interview

The interview promised "8 questions" but the engine cycled between exactly two questions four times each: a "Trade Debtors Ageing" MCQ and a "Section 153 Freight WHT" freeform number. The candidate sees the same numbers and same wording verbatim. The "adaptive AI" engine is not adaptive.

  • Reproduction: applied as Bushra, answered Q1 (B) and Q2 (3,017,240) correctly, then received Q1 again as Q3, Q4, Q6, Q8 and Q2 again as Q5, Q7.
  • Home-page promise: "Skips what you proved. No re-asking what you have already demonstrated" and "Changes the subject. Two weak answers in a topic and it moves on". Both broken.

Why it matters: the moment HR opens the report they will see "candidate answered Q1 four times" and the product's core differentiator collapses. The 8-question cap also means topic coverage is fixed; the engine cannot branch by difficulty or skip proven areas.

#2"Submit & finish" does not auto-redirect to /done

After the final question the URL stays on /interview, inputs disable, and the candidate is left on a static screen with no Save indicator and no next step. The /done route is fully built (warm closing, feedback box, 1-tap rating) but the redirect from the interview page never fires.

  • Reproduction: clicked "Submit & finish" on Q8, page rendered disabled, URL still /interview, candidate has to know to navigate manually to /done to see "Thank you".
  • Home-page promise: "A warm closing page. No score, no pass/fail". The closing page exists, candidates never see it.

Why it matters: on Pakistan mobile networks a 5-second delay or a no-action screen is read as "the form didn't work". Candidates will hit back, retake, and pollute reports with duplicates.

#3Welcome page leaks internal taxonomy to candidates

The "What we will cover" list on /welcome shows raw enum keys, not topic names:

core_accounting · manual_khata · payroll_statutory · taxation_pk · excel_tools · financial_statements · judgment_ethics · personality_retention

Meanwhile /interview-info lists the same eight topics with proper human-readable names: Core accounting, Manual khata, Payroll & EOBI / SESSI, Pakistani taxation, Excel, Salary → tax, Ethics & judgment, You, personally. The candidate-facing surface should use the second set.

Why it matters: it reads like a build artefact, kills trust, and is a one-line fix once the labels are pulled from the same source as /interview-info.

03.Significant findings This sprint

Marketing copy that misrepresents the experience, and UX gaps that will cost trust in the first 100 candidates.

#4Home page advertises a "chat" — interview is MCQ + number input

The hero, the "How it works" section, and the live demo transcript all describe a free-form conversation in English or Roman Urdu. In reality Q1 is a four-option radio group and Q2 is a single number textbox. No free-text answer field, no chat, no image of the promised "balance sheet / khata page / voucher / cheque" attached to the question.

Why it matters: candidates expect a conversation and get a quiz. Either rebuild as a chat (large lift) or rewrite the marketing to honestly say "10 quick technical questions with real accounting scenarios".

#5Time estimate is inconsistent across pages

Four different numbers on the same property:

  • Home page position card: ~25 min
  • Home page intro: 25–35 minutes
  • /interview-info: ~35 min average length
  • Welcome page (live, after start): about 41 minutes

Why it matters: a card saying ~25 turning into a 41-minute session is a trust-killer on WhatsApp. Pick one and propagate it.

#6No per-question feedback to the candidate

After every submit the screen jumps to the next question with no "correct / partial / wrong" signal and no hint of what they got right. The home page promises "Ladders up. Answer well and the next question gets harder" but the candidate has no way to tell whether the next question is harder because of a good answer or random.

Why it matters: candidates finish with zero learning signal and HR has no per-question trail to point to in a rejection call.

#7Question magnitudes are enterprise-scale on an SME job

The "Trade Debtors Ageing" question shows 0-30d = 9.88 crore, 31-60d = 12.1 crore, total debtors ~31.57 crore. The Section 153 freight line shows a single 30.17 crore payment. The job is "Gulshan Iqbal, near Disco Bakery, Karachi" — small/medium business. /interview-info also promises "real kacha khata page" which implies small-business scale.

Why it matters: an SME intern candidate has not seen a 30 crore debtor ledger. The question is technically correct and emotionally wrong for the role. Either scale the numbers down or scale the company profile up.

#8Profile form asks a content-marketing question on an accountant role

Step 2 (profile) includes a text field "Have you written articles or content?" with example hint "Two blog posts on accounting, or none". This is the wrong question for an Accountant (Internship). Likely a shared form template leaking across roles.

Why it matters: every accountant candidate wastes 20 seconds wondering why they're being asked about blog posts. The right field would be years of accounting experience, FBR return familiarity, or QuickBooks/Tally exposure.

04.Marketing copy vs. reality

A side-by-side of what the public site promises and what the candidate actually experiences. Use this as a copy-edit checklist.

Claimed
Observed
"A chat in English or Roman Urdu."
Four radio buttons, then a single number textbox. No chat.
→
"Real balance sheets, khata pages, vouchers and cheques."
Two questions; both as plain data tables. No image, no khata page, no voucher.
→
"AI notices when you are struggling and moves to a different area."
Same two questions looped four times each.
→
"Ladders up. Answer well and the next question gets harder."
Identical question on Q3, Q4, Q6, Q8 regardless of answer quality.
→
"A warm closing page."
/done exists, but is not auto-reached after Submit & finish.
→
"Skips what you proved."
Q1 was answered correctly, then served again four more times.
→
"~25 min" on the open position card.
"about 41 minutes" once the interview starts.
→
"Voice mode" teased on every question card.
Button disabled, says "coming soon". Visible on every question.
→
No login, no app, no OTP, no password.
True. The candidate flow is genuinely frictionless.
✓
"100% provably fair — every candidate gets different numbers."
Confirmed: debtors buckets (98,803,500 / 121,049,000 / 53,672,500 / 42,222,000) and freight figure (301,724,000) appear fresh per session.
✓

05.Staff-side QA gate Needs Munaf

Things only verifiable on admin / bushra / faizan accounts. Provide one of the three and this section becomes a 2-hour deep-dive instead of a stub.

What I could not test, and what to check first

All admin, HR, manager, dashboard, reports and override routes return 307 → /auth/login as expected (auth gate is working). To grade the actual report quality I need one of the following:

  1. Reset and paste passwords for admin, bushra, faizan. I'll run them in read-only mode and screenshot the dashboards.
  2. Create a test-only HR account with read-only role that does not see real PII (a seeded "Demo Trading Co." tenant with synthetic candidates).
  3. Send screenshots of (a) HR dashboard, (b) one full candidate report, (c) admin overview. I'll write findings against them.

Once I have access, the following is the priority checklist for the staff side:

  1. Does HR see the "Q1 served four times" anomaly? Is there a duplicate-question warning or does it just look like the candidate looped?
  2. What is the actual score on Bushra's run (4× correct Q1, 4× correct Q2)? Is the per-question rationale visible or just a number?
  3. Did my apply (#100) get associated with Server4Sale or with a different tenant? Is the application counter correct (3 + 1 = 4)?
  4. Can HR view each answer + grading rationale, or do they only see a score? Privacy page promises "evidence, not verdicts" — verify the evidence is actually there.
  5. Bushra is listed as HR for ABC Trading Co., but the only published job is Server4Sale's. What does she see in her account?
  6. Can admin override a recommendation? The privacy page promises candidates may "ask the company to override any outcome" — is that UI built?
  7. Is there a CSV / PDF export? Bulk actions on candidate lists? Audit log visible to admin (privacy promises every staff action is logged)?
  8. Does the report surface the per-question timing, paste events, tab switches that the welcome page promised are recorded?

06.What is working Don't break

These passed. Keep them healthy; regression-test on every deploy.

W1No-login candidate flow

Name + phone → instant link → instant interview. The single most differentiating piece of the product. End-to-end the candidate never sees a password, an OTP or an app store prompt. This is what the market needs.

W2Rate limiting on /api/public/apply

Returned 429 after a few rapid-fire applies from the same IP. Without this the system is one curl loop away from 200 fake applicants.

W3Auth gates on all staff surfaces

/admin, /admin/dashboard, /admin/jobs, /hr, /hr/dashboard, /dashboard, /reports, /results, /api/admin/*, /api/staff, /api/hr all 307 → /auth/login. No staff endpoint is exposed unauthenticated.

W4Privacy page is solid

Specific retention periods (12 months candidates, 6 months debug screenshots, 24 months analytics), named AI processing, audit-log mention, contact email, GDPR-style rights. This will survive a regulator conversation.

W5Bilingual copy is consistent and warm

English + Roman Urdu flows are parallel across home, /interview-info, /start, /welcome, /done, /privacy. Tone is warm without being patronising.

W6Security headers + SEO meta

CSP, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy all present. OG / Twitter cards, theme-color, robots directives clean. /robots implicitly noindex via meta on the public surface.

W7404 page for invalid interview codes is helpful

/i/demo shows a bilingual "this link is not valid" page rather than a generic 404. Reduces support load when WhatsApp truncates a link.

07.Methodology

What was tested, how, and the raw artefacts left behind.

  • Browser walk-through. Full candidate flow from / → /start → /api/public/apply → /i/{token}/welcome → /profile → /interview (all 8 questions) → /done. All 4 sliders on the profile set to "Strong" (4/5). Both question formats (MCQ + freeform number) exercised.
  • Static / JS inspection. Fetched and decoded the Next.js Turbopack chunks that wire the "Take Interview" button (chunk 0-ui3g2601wl8.js) to confirm the inline form behaviour and the 5-field application shape.
  • Endpoint probing. curl against 20 candidate, public, admin, HR and API routes to verify status codes, redirects, and the rate limit on /api/public/apply. All admin surfaces correctly 307 to /auth/login.
  • Security headers + meta. curl -I on the home page; confirmed CSP, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, frame-ancestors, base-uri, form-action. SEO meta (OG, Twitter, theme-color, keywords, robots) present.
  • Math verification on questions. Verified the "correct" answer (B) on the MCQ matches the published 0% / 5% / 10% / 50% provision math. Submitted the calculated 2%-vs-1% WHT under-deduction on Q2.
  • Test candidate left in production. Bushra Khan, applicant #100, URL /i/0RJ6y8_RFQ868WiOhND_My9Lp0TC715b-2DHng64ANk/done. Feedback left on /done with this bug list. Delete via admin or leave as a real test record.
Reproduction commands (raw)
# Public jobs endpoint
curl -s https://jobinterview.maahir.io/api/public/jobs

# Apply endpoint (valid)
curl -s -X POST https://jobinterview.maahir.io/api/public/apply \
  -H 'Content-Type: application/json' \
  -d '{"jobId":19,"firstName":"Test","lastName":"Candidate","phone":"03001234567","email":"test@example.com","city":"Karachi"}'

# Auth-gate probe (admin surfaces should 307 → /auth/login)
for p in /admin /admin/dashboard /hr /dashboard /reports /api/admin/jobs; do
  curl -sI -o /dev/null -w "%{http_code} %{redirect_url}\n" https://jobinterview.maahir.io$p
done

# Rate-limit verification
for i in 1 2 3 4 5; do
  curl -s -o /dev/null -w "%{http_code} " -X POST https://jobinterview.maahir.io/api/public/apply \
    -H 'Content-Type: application/json' \
    -d "{\"jobId\":19,\"firstName\":\"Spam$i\",\"phone\":\"0300123456$i\",\"email\":\"spam$i@x.com\"}"
done; echo