# Implementation notes

No framework build step. `public/` is the only web root. `private/` contains server code, config, private uploaded PDFs and PHP sessions. PDO supports MySQL/MariaDB for cPanel and SQLite for disposable local tests. Browser code never receives provider credentials.

## Data flow

1. The browser opens a PDF using the bundled PDF.js 5.4.624, records every page separately, and groups text items by their PDF coordinates.
2. The original PDF is stored privately. Page text is sent in batches of at most five, with its page number and extraction method. Completion requires all page records, including explicitly unreadable pages.
3. Optional Gemini OCR transcribes a selected page image. OCR output remains marked as OCR, not verified printed text.
4. Question generation selects a lowest-use readable page with random tie-breaking, then a random window of lines. The server includes prior stems to discourage reuse and calls the configured Gemini generateContent model.
5. Structured model output is validated for four distinct options, an answer index, per-option explanations, page and line bounds, and a literal quotation present in those source lines. Invalid or duplicate candidates are dropped. This verifies citation matching, not scientific correctness.
6. AI questions remain personal study drafts until admin review. Public PYQs enter through import and must be explicitly verified before student access. A public question can have a separate modern-textbook citation.
7. Exam creation locks the user's row on MySQL, resumes an existing active exam when present, prefers unseen stems across sessions and years, shuffles questions and answer options, and persists an immutable question snapshot. The API returns no answer key or source until submission.
8. Each answer is saved separately. The server deadline, not the browser counter, determines when answers stop. Submission is idempotent. Topic-level feedback distinguishes wrong and unanswered items.
9. Chat uses only a finished exam's question snapshot, its source, and that user's question thread. It does not use unrelated users' conversations. Provider failures produce visible errors, never canned fake AI answers.

## Security and operating boundaries

- Password hashing, strict PHP sessions, HttpOnly/SameSite cookies, CSRF tokens for writes, prepared SQL, per-user ownership checks and role checks.
- HTTPS redirect is configured at cPanel; secure cookies depend on the server correctly setting HTTPS.
- Browser rendering escapes text and restricts source links to HTTP(S).
- Login, registration, reports and AI requests have server-side limits. AI limits are requests per fixed UTC-aligned period, not token or billing limits.
- Original PDFs are behind the authenticated API. The public root must never contain private code/config/upload storage.
- Untrusted documents are passed as data to the AI. Prompt instructions and schema/citation validation reduce, but do not eliminate, model mistakes.
- A cited external URL is not fetched or automatically certified by the app. Admin verification is an accountable human assertion with an audit record.
- Near-duplicate detection is a character-trigram heuristic. It catches many paraphrases, not every semantic duplicate. Mathematical signs and decimal points are preserved.
- The 1990 onward year matrix displays counts and never claims a full year is complete without a separate corpus audit.
- Shared hosting is suited to modest use. Generation/scan OCR is synchronous per small request; high concurrent traffic or very large corpora should use a job queue and indexed retrieval in a future deployment.

## Third-party components

PDF.js 5.4.624 is bundled in `public/vendor/` with Apache-2.0 license. Noto Sans Bengali fonts are bundled with their SIL Open Font License. The rest of this package is newly authored application code. No API key or historical question corpus is bundled.

References: [PDF.js API](https://mozilla.github.io/pdf.js/api/), [Gemini REST generateContent](https://ai.google.dev/api/generate-content).
