# DocBox Staging Context

Last updated: 2026-05-30

## Purpose

This file is the running context for DocBox staging work. Update it whenever staging code, configuration, upload instructions, or working assumptions change.

## Environment

- Production URL: https://docbox.asia
- Production web root: `/home/docboxasia/public_html`
- Staging URL: https://staging.docbox.asia
- Staging web root: `/home/stagingdocbox/public_html`
- Local staging copy: `/Users/apple/Documents/docbox_staging`
- Staging private storage target: `/home/stagingdocbox/staging_storage`
- Staging app must not use production database, production ABDM credentials, or live SMS/email.

## Application Notes

- DocBox HMIS is PHP/MySQL with many PHP endpoints, not a REST-only API.
- Authentication is OTP-only. Do not add password login.
- Many UI calls expect legacy PHP responses and manually call `JSON.parse`.
- When an endpoint returns `Content-Type: application/json`, jQuery may auto-parse the response before callback code runs.
- Root landing page loads `/js/script.js`; this is not under `/sajid`.
- The speciality dropdown calls `/sajid/getSpecialityDetails.php`.
- Login after OTP is not navigated by a PHP redirect. The root page JavaScript calls `sajid/authOTP.php` and then `sajid/loginDocbox.php`; `js/script.js` decides the final `window.location`.
- The main login landing routes seen in `js/script.js`/inline `index.php` are `dashboard.php`, `home.php`, and `onboarding.php`.
- PHP navigation/config endpoints also exist:
  - `sajid/app_feature_config.php` for shared hospital-level feature visibility.
  - `sajid/patientinfo_navigation_config.php` for doctor-to-patient-info page routing.
  - `sajid/navigation_config.php` was removed after home feature visibility moved into `sajid/app_feature_config.php`.
- `patientInfo_oph_rectify_test_vs.html` loads `js/patientInfo_oph_rectify_test_vs.js?v=39.73`.
- In `js/patientInfo_oph_rectify_test_vs.js`, care-context upsert after visit save is automatic, but ABDM care-context linking is not silent:
  - visit save calls `syncCareContextAfterVisitSave(...)`;
  - `syncCareContextAfterVisitSave` posts to `api/internal_care_context_upsert.php`;
  - if the care context is already linked and changed, it asks before `notify_context_update`;
  - if the patient has a linked ABHA and the saved care context is not linked, it asks: `This patient has a linked ABHA. Do you want to link the saved care context now?`;
  - only after confirmation does it use `check_token` / `generate_token` / `link_care_context` via `api/abdm_care_context_link_flow.php`.
- Link token generation data flow:
  - `js/patientInfo_oph_rectify_test_vs.js::askToGenerateLinkTokenAndMaybeLink()` posts `action=generate_token`, `patientId`, `careContextReference`, `hipId`, and `hipName` to `api/abdm_care_context_link_flow.php`.
  - `api/abdm_care_context_link_flow.php` then loads ABHA mapping from `abdm_patient_abha_map`, derives identity from `profile_json`, verifies the care context exists in `abdm_patient_care_context`, and posts to `http://abdm.docbox.asia/api/abdm_generate_link_token.php`.
  - Outgoing generate-token payload fields are `abhaAddress`, `abhaNumber`, `careContextReference`, `name`, `gender`, `yearOfBirth`, `profile`, `hipId`, and `hipName`.
  - User shared current Lightsail `abdm_generate_link_token.php`: it sends only `abhaNumber`, `abhaAddress`, `name`, `gender`, and `yearOfBirth` to HIECM `/v3/token/generate-token`.
  - Lightsail records the pending request back to staging/main via `/api/internal_link_token_request_record.php` with `requestId`, `abhaAddress`, `careContextReference`, `hipId`, and the ABDM payload.
  - `internal_link_token_request_record.php` derives `patient_id` by matching `abdm_patient_care_context.care_context_reference` + `abha_address`.
- ABDM discovery service production-reference check:
  - `lib/AbdmDiscoveryService.php`, `api/internal_discovery_care_contexts.php`, and `api/abdm_discovery_patient_search_debug.php` were checked for production DB/schema/user/password literals and hardcoded production server URLs.
  - No `docboxas_patientmanager`, production DB user/password, direct `mysqli_connect`/`new PDO`, `docbox.asia`, `docbox.co.in`, `abdm.docbox.asia`, or `/home/docboxasia` references were found in those files.
  - Discovery uses `Db::conn()` from the shared bootstrap/config and unqualified table names, so the active DB is controlled by the staging config.

## Latest Working Context - 2026-05-30

- ABDM M2 flow check:
  - DocBox currently has two M2-related care-context paths in code.
  - Patient/app-initiated discovery path:
    - Lightsail callback `api/abdm_discovery_on_discover.php` receives ABDM discovery input, forwards it to Main VPS `api/internal_discovery_care_contexts.php`, then responds to HIECM `/user-initiated-linking/v3/patient/care-context/on-discover`.
    - Main VPS `lib/AbdmDiscoveryService.php` matches by ABHA Address first, then mobile, then OPD/IPD or patient id, then demographic filters. It syncs existing visits into `abdm_patient_care_context` before returning care contexts.
    - Lightsail callback `api/v3/hip/link/care-context/init.php` handles the ABDM care-context link init callback, records it on Main VPS through `api/internal_care_context_link_init_record.php`, sends DocBox OTP to the patient mobile, and responds to HIECM `/user-initiated-linking/v3/link/care-context/on-init`.
    - Main VPS `api/internal_care_context_link_confirm_record.php` validates the DocBox OTP and marks matching care contexts linked.
  - DocBox-initiated Rectify path:
    - `js/patientInfo_oph_rectify_test_vs.js` saves/updates a care context through `api/internal_care_context_upsert.php`.
    - If the patient has ABHA linked and the care context is not linked, it calls `api/abdm_care_context_link_flow.php`.
    - `generate_token` calls Lightsail `api/abdm_generate_link_token.php`, which calls HIECM `/v3/token/generate-token`.
    - Link-token generation uses one ABDM API: `POST {hiecmBaseUrl}/v3/token/generate-token` from Lightsail `api/abdm_generate_link_token.php`.
    - Link-token generation headers include the normal ABDM bearer headers from `AbdmHeaders::base(true)` plus `X-HIP-ID`.
    - Link-token generation payload contains `abhaNumber`, `abhaAddress`, `name`, `gender`, and `yearOfBirth`.
    - Main VPS `api/internal_link_token_request_record.php` only records the pending request locally in `abdm_link_token`; it is not an ABDM API call.
    - The link-token callback is received by Lightsail `api/abdm_link_token_callback.php` and stored on Main VPS by `api/internal_consent_hip_notify.php` / `lib/AbdmHipConsentNotificationService.php`.
    - `link_care_context` calls Lightsail `api/abdm_link_care_context.php`, which sends the final care-context link request to HIECM `/hip/v3/link/carecontext`.
  - Follow-up/update notification path:
    - If a linked care context changes, Main VPS action `notify_context_update` calls Lightsail `api/abdm_link_context_notify.php`, which posts to HIECM `/hip/v3/link/context/notify`.
  - Upload target for this context-only update: `/Users/apple/Documents/docbox_staging/stagingcontext.md` to Main VPS `/home/stagingdocbox/public_html/stagingcontext.md`.
- ABDM M2 care-context HI type check:
  - New/updated Rectify visit care contexts are stored in `abdm_patient_care_context.care_context_type` as `OPD`.
  - Patient/app-initiated discovery currently exposes that stored `OPD` as `OPCONSULTATION` through `lib/AbdmDiscoveryService.php::discoveryHiType()`.
  - DocBox-initiated final care-context link currently normalizes `OPD` to `OPConsultation` in Lightsail `api/abdm_link_care_context.php`.
  - Linked-care-context update notification currently normalizes `OPD` to `OPConsultation` in Lightsail `api/abdm_link_context_notify.php`.
  - Care-context document/FHIR preparation also maps stored `OPD` to `OPConsultation` in `lib/AbdmCareContextDocumentService.php`.
  - No `Prescription`, `DiagnosticReport`, `DischargeSummary`, or other HI types are currently created by the Rectify OPD care-context preparation flow unless an existing row has a different `care_context_type`.
- ABDM prescription PDF inclusion planning note:
  - Existing ABDM health-information preparation currently builds structured FHIR bundles from `AbdmCareContextDocumentService` and `AbdmPrescriptionFhirBundleService`; it does not attach generated prescription PDFs.
  - Existing prescription print scripts under `sajid/pdfPrescription*.php` are browser/print oriented and should not be reused directly as ABDM transfer outputs without a reusable server-side PDF generation service.
  - Existing prescription print scripts already save generated PDFs to `sajid/{doctorId}/{patientId}/{fileName}` using names like `{visitingDoctorId} prescription_{visitVersionDate}.pdf`.
  - Current prescription PDF names include visit-version date/minute, so different visits for the same patient are unlikely to have the same prescription filename in normal use. The more practical ambiguity is repeat generation of the same visit prescription, which can overwrite the previous file by design.
  - For ABDM, identify prescription PDFs by a metadata row keyed by doctor, patient, visit version, care-context reference, generated timestamp, and file hash. Use a generated document id or include the raw visit version plus a sequence/hash in the stored filename.
  - These existing PDFs can be reused for ABDM if the ABDM path resolves them from trusted patient/visit/care-context data, validates the file exists and is a PDF, and records a stable metadata row instead of trusting browser-supplied filenames.
  - Do not repurpose `documents.DocumentName` or `documents.DocumentPath` to store visit version. `DocumentName` is used as the actual visible/download filename across patient report UIs and delete flows; `DocumentPath` is also used by report save/delete/update code even though it often duplicates `DocumentName`.
  - Safer schema options: add nullable columns to `documents` such as `VisitVersion`, `DocumentType`, `CareContextReference`, `FileHash`, and `GeneratedAt`, or create a separate `abdm_document_care_context_map` table keyed to the existing document row/file identity.
  - To include prescription PDFs, add a private PDF generation/storage step, store metadata keyed to patient/visit/care-context, create or expose a `Prescription` or `HealthDocumentRecord` care context, and branch ABDM document preparation so that the requested HI type returns a bundle containing the PDF attachment metadata/content.
  - Keep PDF files outside public web folders, validate file type/size, use controlled filenames, and only serve/transfer after patient, doctor/facility, consent, and care-context checks pass.

- Current ABDM update: Rectify Test VS now opens an inline Main VPS ABHA link modal before ABDM M3 if the selected patient is not linked internally.
- `patientInfo_oph_rectify_test_vs.html` now includes the `rectifyAbhaLinkModal` iframe modal and cache-busts `js/patientInfo_oph_rectify_test_vs.js` to `v=40.63`.
- `js/patientInfo_oph_rectify_test_vs.js` now checks `api/patient_abha_status.php` before opening `Public/abdm_m3_patient.php`:
  - linked patient: keeps existing behavior and opens the ABDM M3 workspace.
  - unlinked patient: opens `Public/abha_patient_link_modal.php` inside the page.
  - after successful link: refreshes ABHA status and then opens ABDM M3.
- New Main VPS iframe page `Public/abha_patient_link_modal.php` provides ABHA Number/Address, Mobile Number, Aadhaar Number, and Create ABHA flows for linking only. It does not copy demographic details into Rectify fields.
- New JS `js/rectifyAbhaLinkModal.js` reuses the existing Main VPS prefill proxy and link APIs, preserves captcha and OTP cooldown behavior, and calls `api/abha_registration_prefill_link_patient.php` only after verified ABHA details are available.
- Rectify ABHA mobile-search tab now pre-fills the Mobile Number field from the DocBox patient phone number when available. The value is passed to `Public/abha_patient_link_modal.php` as a cleaned 10-digit `patientMobile` parameter and does not overwrite a manually entered mobile number.
- After mobile-number ABHA accounts are fetched, the captcha now appears immediately above the returned account rows before any account OTP button is used. If no account is returned, the captcha is hidden because no OTP action is available.
- Rectify ABHA OTP verification now reads the returned address list from `abhaAddresses` as used by the bridge/Add Patient flow, with `addresses` kept as a fallback. Address selection is shown only for ABHA Number verification. ABHA Address verification goes directly to the verified-details/link step after OTP succeeds.
- `api/abha_registration_prefill_verify_proxy.php` now stores the current OTP request flow in the session. If an ABHA Address OTP verification returns an address-selection flag from the bridge, the proxy normalizes it to the direct verified-profile response and includes `identifierType: abha_address`, so the Rectify modal does not show the extra address selection step.
- Rectify modal OTP verification now sends its local verification flow (`identifierType` and `mode`) to the Main VPS proxy. The modal also gives local `abha_address` state priority over bridge response metadata, so ABHA Address verification cannot fall back into the address chooser.
- Rectify ABHA modal now scopes the shared OTP panel to the tab that requested the OTP. Switching to another verification tab hides the OTP panel so OTP text from one method is not shown under other methods.
- Rectify ABHA modal now uses separate server-side captcha challenges for each OTP area: ABHA Number/Address, Mobile Number, Aadhaar Number, Create ABHA Aadhaar OTP, and Create ABHA communication mobile OTP. The active captcha purpose is sent to the Main VPS proxy for validation, and refreshing one captcha no longer changes the others.
- Rectify ABHA Create ABHA tab now shows the same Aadhaar consent declaration text used in Add Patient, with a required consent checkbox before Aadhaar OTP can be requested.
- Rectify ABHA modal visual order adjusted so every OTP-send button appears after the captcha block for its section.
- Rectify ABHA mobile verification no longer clears the already entered captcha answer when the user clicks the account-level Send OTP button. The captcha answer is preserved only when the same captcha purpose and same question are being shown again.
- Rectify ABHA link modal now includes the optional post-verification ABHA communication mobile update step:
  - the iframe now loads the DocBox patient record on the server side and uses that trusted mobile if the parent page URL does not include a mobile;
  - it is shown after an ABHA profile has been verified when the DocBox patient has a 10-digit mobile; if the mobile already matches the verified ABHA mobile, it shows a non-action status instead of silently hiding;
  - the OTP request uses its own `mobile_update` captcha purpose and the same cooldown / maximum resend tracking used by the other OTP flows;
  - the Main VPS proxy validates the profile is already verified before forwarding the request to the ABDM bridge;
  - the Lightsail bridge uses ABDM V3 `/v3/profile/account/request/otp` and `/v3/profile/account/verify` with `["abha-profile", "mobile-verify"]` scope and the stored verified profile token.
- Rectify ABHA link modal now compares DocBox patient name, age, gender, and phone number against the verified ABHA profile after an ABHA Address is selected/verified:
  - if a mismatch is found, the modal shows a warning listing the DocBox value and the ABHA value;
  - the user can choose `Update DocBox details and link ABHA`, which updates `patient`.`Patient Name`, `patient`.`Age`, `patient`.`Gender`, `patient`.`PhoneNumber`, and `docboxPatientMiscInfo`.`Dob` when available before linking;
  - when the phone number differs, the warning also offers `Update ABHA mobile instead`, which takes the user to the ABHA communication mobile OTP section using the DocBox patient mobile;
  - the user can also choose `Link without updating` to preserve the existing DocBox demographics.
- Existing prefill APIs now allow doctor/helper access type `8` as well as the existing roles:
  - `api/abha_registration_prefill_token_create.php`
  - `api/abha_registration_prefill_verify_proxy.php`
  - `api/abha_registration_prefill_link_patient.php`
- ABHA link API hardening completed for the Rectify/Add Patient prefill endpoints:
  - JSON responses emitted through `sajid/includes/staging_bootstrap.php::docbox_json_response()` now include no-store cache headers and `X-Content-Type-Options: nosniff`.
  - `api/abha_registration_prefill_common.php` now has a session request limiter helper used by the ABHA token/captcha/proxy APIs.
  - `api/abha_registration_prefill_token_create.php` now rate-limits token creation and captcha refresh, and rejects unknown captcha actions.
  - `api/abha_registration_prefill_verify_proxy.php` now validates every action-specific field server-side before forwarding to the ABDM bridge, including mobile, Aadhaar, ABHA Number, ABHA Address, OTP, account selection index, verification mode, and create-address policy.
  - `Public/abha_patient_link_modal.php` now validates optional doctor context parameters and sends a stricter referrer policy header.
- Direct access to `Public/abdm_m3_patient.php` no longer sends unlinked patients to the old Lightsail ABHA public page. It now stops with a clear message to link ABHA from the patient profile first.
- Upload targets for this update are split across Main VPS and Lightsail ABDM bridge:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/staging_bootstrap.php` to `/home/stagingdocbox/public_html/sajid/includes/staging_bootstrap.php`
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
  - `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php`
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to Lightsail `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to Lightsail `/var/www/html/abdm-app/lib/AbhaVerificationService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## Latest Working Context - 2026-05-23

- Current agency recommendation: site-wide HTTP response headers.
- Updated root `.htaccess` with baseline response headers:
  - `Content-Security-Policy`
  - `X-Frame-Options: SAMEORIGIN`
  - `X-Content-Type-Options: nosniff`
  - `Strict-Transport-Security: max-age=31536000`
  - `Referrer-Policy: strict-origin-when-cross-origin`
  - `Permissions-Policy: camera=(), microphone=(), geolocation=()`
- CSP is compatibility-focused for the legacy app:
  - keeps inline/eval script compatibility for current pages
  - allows current HTTP/HTTPS CDN and integration dependencies
  - restricts object embedding and framing with `object-src 'none'` and `frame-ancestors 'self'`
- Staging smoke test after first header sync showed `/` returned `403` because root `DirectoryIndex disabled` prevented `index.php` from loading.
- Root `.htaccess` was adjusted to `DirectoryIndex index.php index.html` while keeping `Options -Indexes`, so `/` can load the application entry page and folders without an index remain non-listable.
- Root `.htaccess` now sets security headers with both `Header set` and `Header always set` for broader coverage across normal and redirect/error responses.
- Staging smoke test after second header sync showed static and directory-denied responses had the headers, but PHP-rendered responses did not consistently inherit all Apache header rules.
- Added PHP-level header bootstrap:
  - `sajid/includes/security_headers.php`
  - root `.user.ini` now prepends `/home/stagingdocbox/public_html/sajid/includes/security_headers.php`
  - `sajid/includes/staging_bootstrap.php` now requires the same header helper for `sajid` PHP responses, because `sajid/.user.ini` already prepends `staging_bootstrap.php`
- Upload targets for this recommendation:
  - `/Users/apple/Documents/docbox_staging/.htaccess` to `/home/stagingdocbox/public_html/.htaccess`
  - `/Users/apple/Documents/docbox_staging/.user.ini` to `/home/stagingdocbox/public_html/.user.ini`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/security_headers.php` to `/home/stagingdocbox/public_html/sajid/includes/security_headers.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/staging_bootstrap.php` to `/home/stagingdocbox/public_html/sajid/includes/staging_bootstrap.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

- Current agency recommendation: directory listing disabled for sensitive public directories.
- Added local Apache directory rules:
  - root `.htaccess`
    - added baseline `Options -Indexes` and `DirectoryIndex disabled` for web-root inheritance into subfolders
    - added nosniff header where supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
  - `api/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - no-store/nosniff response headers when supported by Apache headers module
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
  - `ckeditor/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - nosniff response header when supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
  - `sajid/.htaccess`
    - already had `Options -Indexes`; added `DirectoryIndex disabled`
    - expanded artifact filename denial to include JSONL, old/orig/save/swp backup variants
  - `js/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - nosniff response header when supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
  - `css/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - nosniff response header when supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
  - `fonts/.htaccess`, `images/.htaccess`, `img/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - nosniff response header when supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
    - normal asset files remain directly accessible
  - `lib/.htaccess`, `sql/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - direct web access denied for all files in these internal folders
    - server-side PHP includes are not affected by Apache direct-request rules
  - `server/.htaccess`
    - `Options -Indexes`
    - `DirectoryIndex disabled`
    - nosniff response header when supported
    - direct access denied for hidden, log, JSONL, backup, and editor-swap artifact filenames
    - existing direct upload helper paths are not blocked by this folder-level listing rule
- Upload targets for this recommendation:
  - `/Users/apple/Documents/docbox_staging/.htaccess` to `/home/stagingdocbox/public_html/.htaccess`
  - `/Users/apple/Documents/docbox_staging/api/.htaccess` to `/home/stagingdocbox/public_html/api/.htaccess`
  - `/Users/apple/Documents/docbox_staging/ckeditor/.htaccess` to `/home/stagingdocbox/public_html/ckeditor/.htaccess`
  - `/Users/apple/Documents/docbox_staging/sajid/.htaccess` to `/home/stagingdocbox/public_html/sajid/.htaccess`
  - `/Users/apple/Documents/docbox_staging/js/.htaccess` to `/home/stagingdocbox/public_html/js/.htaccess`
  - `/Users/apple/Documents/docbox_staging/css/.htaccess` to `/home/stagingdocbox/public_html/css/.htaccess`
  - `/Users/apple/Documents/docbox_staging/fonts/.htaccess` to `/home/stagingdocbox/public_html/fonts/.htaccess`
  - `/Users/apple/Documents/docbox_staging/images/.htaccess` to `/home/stagingdocbox/public_html/images/.htaccess`
  - `/Users/apple/Documents/docbox_staging/img/.htaccess` to `/home/stagingdocbox/public_html/img/.htaccess`
  - `/Users/apple/Documents/docbox_staging/lib/.htaccess` to `/home/stagingdocbox/public_html/lib/.htaccess`
  - `/Users/apple/Documents/docbox_staging/sql/.htaccess` to `/home/stagingdocbox/public_html/sql/.htaccess`
  - `/Users/apple/Documents/docbox_staging/server/.htaccess` to `/home/stagingdocbox/public_html/server/.htaccess`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

- Current agency recommendation in progress: dashboard page access guard.
- `dashboard.php` now requires a valid DocBox session before any HTML is rendered:
  - It loads `sajid/includes/api_auth.php`.
  - It calls `docbox_require_page_auth(null, '/index.php', '/dashboard.php')` at the top of the file.
  - Unauthenticated or expired browser sessions are redirected to `/index.php`.
- `sajid/includes/api_auth.php` now includes reusable browser-page guard helpers:
  - `docbox_require_page_auth($requiredHelperTypeIds = null, $loginPath = '/index.php', $expectedPath = null)`
  - `docbox_redirect_to_login_page($loginPath = '/index.php')`
  - `docbox_reject_unexpected_page_path($expectedPath)`
  - Existing API guard behavior remains unchanged; `docbox_require_api_auth()` still returns JSON for API endpoints.
- Dashboard cache-handling update:
  - Authenticated dashboard responses now send `Cache-Control: no-store, no-cache, private, must-revalidate, max-age=0`.
  - Extra path segments such as `/dashboard.php/none.css` are rejected with a no-store 404 response before dashboard HTML renders.
- Follow-up scan for the same URL path/cache pattern:
  - Root browser app pages in batches 1 and 2 now call `docbox_require_page_auth(...)` with exact expected paths.
  - Public entry/login/registration pages and test/rollback pages were not changed in this cleanup.
  - Authenticated report/print endpoints under `sajid/` were handled in batch 3 with exact-path rejection while preserving existing API auth and CSRF behavior.
- Batch 1 root page guard cleanup completed locally:
  - `addPatient.php` now calls `docbox_require_page_auth(null, '/index.php', '/addPatient.php')`.
  - `authenticate.php` now calls `docbox_require_page_auth(null, '/index.php', '/authenticate.php')`.
  - `expenses.php` now calls `docbox_require_page_auth(null, '/index.php', '/expenses.php')`.
  - `financialSummary.php` now calls `docbox_require_page_auth(null, '/index.php', '/financialSummary.php')`.
  - `profile.php` now calls `docbox_require_page_auth(null, '/index.php', '/profile.php')`.
  - Existing helper-type permission checks in these files were left in place.
- Batch 2 live root app page guard cleanup completed locally:
  - Added top-of-file `sajid/includes/api_auth.php` include plus `docbox_require_page_auth(...)` exact-path checks to:
    - `home.php`, `patientInfo.php`, `IPD.php`, `OTScheduling.php`, `OTSchedulingRange.php`, `OTSchedulingRangeCentrallised.php`, `calendar.php`, `counsellorDesk.php`, `counsellorDesk_centrallised.php`, `patientReports.php`, `patientReportsArchived.php`, `patientReportsCentrallisedGdrive.php`, `patientReportsCentrallisedS3.php`, `hrDesk.php`, `hrDeskNew.php`, `attendanceModule.php`, `consentFormEditor.php`, `discharge_card.php`, `editPatient.php`, `reportEditor.php`, and `todaysAppointment.php`.
  - Public entry/login/registration pages and test/rollback pages were not changed in this batch.
- Batch 3 authenticated `sajid/` report/print endpoint path cleanup completed locally:
  - Added `docbox_reject_unexpected_page_path(...)` to:
    - `sajid/biometryReport.php`, `sajid/breakUpBillPrint.php`, `sajid/finalBillPrint.php`, `sajid/diagnosisReport.php`, `sajid/locationReport.php`, `sajid/medicalCerficate.php`, `sajid/printDetailedFindingsDrawing.php`, `sajid/reportPrintingPDF.php`, `sajid/retinoscopyReport.php`, `sajid/spectaclePrescription.php`, and `sajid/spectaclePrescriptionAllVersions.php`.
  - Existing `docbox_require_api_auth()` and `docbox_require_csrf_token()` calls were preserved.
- Remaining same-pattern review candidates after staging smoke test:
  - Patched remaining live/root candidates with exact-path page guards: `patientClinicalNotes.php`, `subscription.php`, `profile_intl.php`, `home_new.php`, `stock_audit_all_items.php`, `wrong_stock_report.php`, `admin_settings.php`, and `success.php`.
  - `admin_settings.php` uses `docbox_require_page_auth(array('6', 'a', 's'), '/index.php', '/admin_settings.php')`; the other remaining pages use default authenticated-session access.
  - `admin_settings.php` existing DB include was moved below the page guard so extra-path URLs are rejected before configuration/database loading.
  - Public entry/login/registration pages and test/rollback pages remain intentionally out of scope unless the user asks for those explicitly.
- Upload targets after this change:
  - `/Users/apple/Documents/docbox_staging/dashboard.php` to `/home/stagingdocbox/public_html/dashboard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/api_auth.php` to `/home/stagingdocbox/public_html/sajid/includes/api_auth.php`
  - Batch 1 root pages to `/home/stagingdocbox/public_html/`: `addPatient.php`, `authenticate.php`, `expenses.php`, `financialSummary.php`, `profile.php`
  - Batch 2 root pages to `/home/stagingdocbox/public_html/`: `home.php`, `patientInfo.php`, `IPD.php`, `OTScheduling.php`, `OTSchedulingRange.php`, `OTSchedulingRangeCentrallised.php`, `calendar.php`, `counsellorDesk.php`, `counsellorDesk_centrallised.php`, `patientReports.php`, `patientReportsArchived.php`, `patientReportsCentrallisedGdrive.php`, `patientReportsCentrallisedS3.php`, `hrDesk.php`, `hrDeskNew.php`, `attendanceModule.php`, `consentFormEditor.php`, `discharge_card.php`, `editPatient.php`, `reportEditor.php`, `todaysAppointment.php`
  - Batch 3 `sajid/` report/print endpoints to `/home/stagingdocbox/public_html/sajid/`: `biometryReport.php`, `breakUpBillPrint.php`, `finalBillPrint.php`, `diagnosisReport.php`, `locationReport.php`, `medicalCerficate.php`, `printDetailedFindingsDrawing.php`, `reportPrintingPDF.php`, `retinoscopyReport.php`, `spectaclePrescription.php`, `spectaclePrescriptionAllVersions.php`
  - Remaining root page cleanup to `/home/stagingdocbox/public_html/`: `patientClinicalNotes.php`, `subscription.php`, `profile_intl.php`, `home_new.php`, `stock_audit_all_items.php`, `wrong_stock_report.php`, `admin_settings.php`, `success.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

- Current workstream: Rectify Test VS page safe rendering and field handling.
- Page links:
  - Local: `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Staging: `https://staging.docbox.asia/patientInfo_oph_rectify_test_vs.html`
- Step 1 was completed and uploaded by the user:
  - `js/patientInfo_oph_rectify_test_vs.js` now has shared safe rendering helpers:
    - `docboxPatientInfoText`
    - `docboxPatientInfoEscapeHtml`
    - `docboxPatientInfoEscapeAttr`
    - `docboxPatientInfoSafeTrim`
    - `docboxPatientInfoAppendSuggestion`
  - Initial rendering cleanup covered helper dropdowns, suggestion lists, patient summary, visit cards, diagnosis labels, VA table values, medication tags, and visit edit textareas.
  - `patientInfo_oph_rectify_test_vs.html` loads `js/patientInfo_oph_rectify_test_vs.js?v=40.43`.
  - Local checks passed before upload:
    - `node --check js/patientInfo_oph_rectify_test_vs.js`
    - `php -l patientInfo_oph_rectify_test_vs.html`
- Latest user-reported behavior after upload:
  - Add Diagnosis UI displays `1` during the add flow.
- Investigation notes for the next chat:
  - Add Diagnosis button handler starts around `js/patientInfo_oph_rectify_test_vs.js` line `19730`.
  - Final Add Diagnosis handler `.addDiag1` starts around line `19898`.
  - Diagnosis reload helper `getDiagnosis()` starts around line `19858`.
  - Diagnosis modal markup is in `patientInfo_oph_rectify_test_vs.html` around lines `2741` to `2842`.
  - Diagnosis card rendering still uses older string-building around:
    - copy diagnosis callback near line `15310`
    - visit-open diagnosis render near line `19100`
    - Add Diagnosis save/reload near lines `19873` and `19950`
- Next recommended task:
  - Fix only the Add Diagnosis modal/card rendering path first.
  - Use DOM text setters or the existing safe rendering helpers for diagnosis date, diagnosis text, comments, version attributes, and delete button data attributes.
  - Bump Rectify JS from `v=40.43` to `v=40.44`.
  - Run:
    - `node --check js/patientInfo_oph_rectify_test_vs.js`
    - `php -l patientInfo_oph_rectify_test_vs.html`
- Preferred wording in the restarted chat:
  - Use neutral terms such as safe rendering, field cleanup, server-side checks, page access rules, and API guards.
- Upload target after this context update:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## Current Config Understanding

- Shared staging config/bootstrap files are under `/sajid/includes`.
- Staging DB constants should come from `/home/stagingdocbox/staging_storage/config/staging_secrets.php` or environment variables.
- The staging secrets file did not exist when checked by the user, causing `DB_UNAVAILABLE`.
- Expected private secrets file:

```php
<?php
define('DB_HOST', 'p:148.66.129.110');
define('DB_NAME', 'docboxasia_staging');
define('DB_USER', 'docboxasia_usr');
define('DB_PASS', 'secure staging DB password');
```

## Changes Made Locally

- Logout staging-safe redirect:
  - `js/logout.js` and `js/logoutNew.js` now redirect to `window.location.origin + '/index.php'`, preserving the current staging host instead of relying on relative/prod links.
  - `logout.php` now destroys the PHP session before output, has no production URL, uses same-site `/index.php`, and loads root-relative local assets.
- Added/updated staging bootstrap/config/auth support:
  - `sajid/includes/staging_config.php`
  - `sajid/includes/staging_bootstrap.php`
  - `sajid/includes/api_auth.php`
- Added global frontend API wrapper:
  - `sajid/assets/js/api.js`
- Added/updated staging Apache/PHP protections:
  - `sajid/.htaccess`
  - `sajid/.user.ini`
  - `sajid/uploads/.htaccess`
- Added VAPT handover docs:
  - `sajid/docs/staging_vapt_handover.md`
  - `sajid/docs/api_inventory.csv`
  - `sajid/docs/internal_validation_checklist.md`
- Removed hardcoded production DB credentials from:
  - `sajid/savePharmacyItemNew.php`
- Reworked speciality endpoint:
  - `sajid/getSpecialityDetails.php`
  - It now uses `staging_bootstrap.php` and `docbox_mysqli()`.
  - It returns `Content-Type: text/plain` for compatibility with old frontend code that manually parses JSON.
- Patched root landing JS:
  - `js/script.js`
  - Speciality response parser now handles both string and already-parsed JSON responses.
  - Speciality option loop starts at index `1`, because index `0` is the metadata row `{ table: "speciality" }`.
- Updated root page script cache version:
  - `index.php`
  - `js/script.js?v=3.27`
- Removed active production DB fallbacks from ABDM shared config:
  - `config/config.php`
  - `api/abdm_m3_patient_profile.php` loads this through `api/_bootstrap.php` and `lib/Db.php`.
  - DB now resolves from `/home/stagingdocbox/staging_storage/config/staging_secrets.php`, env vars, or staging defaults `docboxasia_staging` / `docboxasia_usr`.
  - DB password is no longer hardcoded in this file; use `DB_PASS`, `DOCBOX_DB_PASS`, or `ABDM_DB_PASS`.
  - Hardcoded bridge secret fallback was removed from this file.
  - Keep `http://abdm.docbox.asia:8090/encrypt` for Fidelius unless the user explicitly asks to change it; this is required by the current ABDM setup.
  - 2026-05-03 recheck showed the local file had reverted; it was re-patched and verified with `php -l`.
  - 2026-05-03 PDO host fix: `config/config.php` strips a leading `p:` from `DB_HOST` before building the ABDM PDO config. The private secrets file may use `p:...` for legacy mysqli, but PDO was failing with `getaddrinfo for p`.

## Important Upload Paths

- Root JS file:
  - Local: `/Users/apple/Documents/docbox_staging/js/script.js`
  - Remote: `/home/stagingdocbox/public_html/js/script.js`
- Root index:
  - Local: `/Users/apple/Documents/docbox_staging/index.php`
  - Remote: `/home/stagingdocbox/public_html/index.php`
- Speciality endpoint:
  - Local: `/Users/apple/Documents/docbox_staging/sajid/getSpecialityDetails.php`
  - Remote: `/home/stagingdocbox/public_html/sajid/getSpecialityDetails.php`
- Staging bootstrap:
  - Local: `/Users/apple/Documents/docbox_staging/sajid/includes/staging_bootstrap.php`
  - Remote: `/home/stagingdocbox/public_html/sajid/includes/staging_bootstrap.php`

## Current Debug State

- `https://staging.docbox.asia/sajid/getSpecialityDetails.php` reached DB after the PHP fixes.
- `{"success":false,"error":"DB_UNAVAILABLE"}` meant the DB secret/config was missing or invalid, not a PHP fatal.
- After DB config was created, the endpoint returned valid speciality data.
- Navigation flow finding: user login navigation is controlled mainly in frontend JavaScript, while PHP endpoints provide auth/profile/config data.
- OTP status:
  - `sajid/OTPDocBox.php` has local staging behavior that logs/returns OTP and should avoid live SMS/email when uploaded with the staging bootstrap.
  - `db_functions.php::otpSaveToTable()` uses `docbox_staging_otp_for()` and logs staging OTP.
  - 2026-05-03 invalid-OTP fix: staging now always rewrites `OTPmappings` with the same OTP value it returns. Before this, an old unexpired random OTP row could remain in DB while staging returned the fixed OTP, causing verification to always say invalid.
  - `sajid/authOTP.php` now loads the staging bootstrap, normalizes posted OTP/mobile values, and defaults `pcDate`/`dateValidity` to avoid malformed JSON from notices.
  - `db_functions.php::otpAuth()` checks a 15-minute window and deletes the OTP row after success, so successful OTP is not reusable.
  - Updated 2026-05-23: `sajid/authOTP.php` now has OTP failed-attempt lockout, starts a secure OTP-verification session, and no longer has a `getmeinside` bypass in the active login OTP flow. Staging-only sample/fixed OTP behavior remains guarded by `docbox_is_staging()`.
- Browser error:

```text
Unexpected token 'o', "[object Obj"... is not valid JSON
```

means old frontend JS is trying to `JSON.parse()` an object that jQuery already parsed.

## Upload/Verification Checklist For Speciality Fix

Upload:

- `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
- `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
- `/Users/apple/Documents/docbox_staging/sajid/getSpecialityDetails.php` to `/home/stagingdocbox/public_html/sajid/getSpecialityDetails.php`

Verify:

- `https://staging.docbox.asia/` page source references `js/script.js?v=3.27`.
- `https://staging.docbox.asia/js/script.js?v=3.27` line around `111` contains `var p = response;`.
- `https://staging.docbox.asia/sajid/getSpecialityDetails.php` returns JSON text with speciality rows.

## Open Risks / Follow-Up

- SFTP credentials in `.vscode/sftp.json` were rejected during attempted upload.
- The downloaded copy can overwrite local fixes if files are pulled from the server again.
- There are still legacy hardcoded values in other files, including old passkeys and direct `patientmanager` schema references. Review before VAPT handover.
- PHP CLI is available locally; use `php -l` for changed PHP files before asking the user to sync.
- SSH shell access appears disabled; remote validation is limited to HTTP/SFTP unless credentials/access change.

## 2026-05-14 Rectify Test VS diagnosis/medicine add guard

- User confirmed the advised surgery/investigation doctor/super-admin rule works and asked to extend the same rule to the prescribe medicine section and add diagnosis section.
- Policy applied:
  - Only helper type `8` Doctor and helper type `a` Super Admin can add diagnosis or prescribe/add medicines from Rectify Test VS.
  - Admin `6`, clinical staff `1`, and other helper types are blocked for these add/write actions.
- Local changes:
  - `/Users/apple/Documents/docbox_staging/sajid/insertDiagnosis.php`
    - now loads the Rectify API guard and calls `docbox_rectify_require_doctor_or_super_admin()` after session/CSRF validation.
  - `/Users/apple/Documents/docbox_staging/sajid/insertMedications.php`
    - now loads the Rectify API guard and blocks unsupported helper types before any medication insert work.
  - `/Users/apple/Documents/docbox_staging/sajid/insertMedicationsAutoPharmacy.php`
    - now blocks unsupported helper types before the current prescription-save medication insert/pharmacy automation path runs.
    - the legacy `db_functions.php` helper is loaded only after the session/CSRF/helper-type guard passes.
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - added `docboxRectifyCanAddDiagnosisOrMedicine()` and click-time denial alerts.
    - blocks Add Diagnosis, final diagnosis save, medicine modal open/add, suggested medicine add, Save All medicine staging, legacy add-medicine-to-DB path, and final medication save when the helper type is not `8` or `a`.
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - cache-bumped Rectify Test VS JS from `v=40.28` to `v=40.29`.
- Verification:
  - `php -l` passed for `sajid/insertDiagnosis.php`, `sajid/insertMedications.php`, `sajid/insertMedicationsAutoPharmacy.php`, `js/patientInfo_oph_rectify_test_vs.js`, and `patientInfo_oph_rectify_test_vs.html`.
  - Simulated helper type `6` add-diagnosis request returned `PERMISSION_DENIED`.
  - Simulated helper type `1` add-medication request returned `PERMISSION_DENIED`.
  - Simulated helper type `6` prescription medication/pharmacy path returned `PERMISSION_DENIED` before legacy helper loading.
  - Direct policy probes allowed helper type `8` Doctor and helper type `a` Super Admin.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/insertDiagnosis.php` to `/home/stagingdocbox/public_html/sajid/insertDiagnosis.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertMedications.php` to `/home/stagingdocbox/public_html/sajid/insertMedications.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertMedicationsAutoPharmacy.php` to `/home/stagingdocbox/public_html/sajid/insertMedicationsAutoPharmacy.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## 2026-05-15 Rectify Test VS diagnosis button guard

- User confirmed the previous Rectify Test VS change works and asked to secure the diagnosis button for Doctor, Admin, and Super Admin. Counsellor was initially included, then removed per follow-up instruction.
- Policy update:
  - Diagnosis add/copy actions now allow helper types `8`, `6`, and `a`.
  - Medicine prescribing remains unchanged: helper types `8` and `a` only.
- Local changes:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php`
    - added `docbox_rectify_require_diagnosis_access()` for helper types `8`, `6`, `a`.
  - `/Users/apple/Documents/docbox_staging/sajid/insertDiagnosis.php`
    - now uses the diagnosis-specific access policy instead of doctor/super-admin-only.
  - `/Users/apple/Documents/docbox_staging/sajid/copyVisitDiagnosis.php`
    - now loads the Rectify guard and applies the same diagnosis-specific access policy before copy work.
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - added `docboxRectifyCanUseDiagnosisButton()` for helper types `8`, `6`, `a`.
    - applied it to Add Diagnosis, final diagnosis Add, diagnosis suggestion buttons, and Copy Diagnosis.
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - cache-bumped Rectify Test VS JS from `v=40.30` to `v=40.31` after removing counsellor from diagnosis access.
- Verification:
  - `php -l` passed for `sajid/includes/rectify_api_guard.php`, `sajid/insertDiagnosis.php`, `sajid/copyVisitDiagnosis.php`, `js/patientInfo_oph_rectify_test_vs.js`, and `patientInfo_oph_rectify_test_vs.html`.
  - Simulated helper type `1` add-diagnosis request returned `PERMISSION_DENIED`.
  - Simulated helper type `1` copy-diagnosis request returned `PERMISSION_DENIED`.
  - Direct policy probes allowed helper type `8` Doctor, `6` Admin, and `a` Super Admin.
  - Simulated helper type `7` Counsellor now returns `PERMISSION_DENIED`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertDiagnosis.php` to `/home/stagingdocbox/public_html/sajid/insertDiagnosis.php`
  - `/Users/apple/Documents/docbox_staging/sajid/copyVisitDiagnosis.php` to `/home/stagingdocbox/public_html/sajid/copyVisitDiagnosis.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## 2026-05-15 API guard function documentation

- User asked that API guard files clearly mention which function handles which page section/action.
- Local documentation-only change:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php`
    - added comments mapping Rectify Test VS guard functions to bootstrap, doctor/patient scope, visit create/open, doctor-only clinical actions, diagnosis add/copy, validators, and legacy-token bridge sections.
  - `/Users/apple/Documents/docbox_staging/sajid/includes/finance_api_guard.php`
    - added comments mapping finance/expense guard functions to bootstrap, Financial Summary/expense-list context, expense action policies, ownership checks, and parameter validators.
  - `/Users/apple/Documents/docbox_staging/sajid/includes/dashboard_api_guard.php`
    - added comments mapping dashboard guard functions to bootstrap, customer/hospital scope, DB connection, timezone, and dashboard filters.
- No permission logic was changed in this pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/finance_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/finance_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/dashboard_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/dashboard_api_guard.php`

## 2026-05-15 Rectify Test VS discharge card button guard

- User asked to secure the Rectify Test VS Discharge Card button for Doctor, Admin, Super Admin, and Counsellor only.
- Policy:
  - Allowed helper types: `8` Doctor, `6` Admin, `a` Super Admin, `7` Counsellor.
  - Other helper types get an access-denied alert at the button/page level and `PERMISSION_DENIED` at the shared discharge-card API helper.
- Local changes:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - added `docboxRectifyCanUseDischargeCard()` for helper types `8`, `6`, `a`, `7`.
    - the `.dischargecard` click handler now blocks unsupported helpers before opening the discharge card page.
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
    - added a page-start guard so direct navigation to `discharge_card_oph.html` is also blocked for unsupported helper types.
  - `/Users/apple/Documents/docbox_staging/sajid/includes/discharge_api_helpers.php`
    - added `docbox_discharge_require_access()` for helper types `8`, `6`, `a`, `7`.
    - `docbox_discharge_require_patient_context()` and `docbox_discharge_require_post_session()` now call the access guard after session/CSRF validation.
    - added comments mapping the discharge helper functions to page/API sections.
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - cache-bumped Rectify Test VS JS from `v=40.31` to `v=40.32`.
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
    - cache-bumped discharge card JS from `v=3.27` to `v=3.28`.
- Verification:
  - `php -l` passed for `sajid/includes/discharge_api_helpers.php`, `js/patientInfo_oph_rectify_test_vs.js`, `discharge_card_oph.js`, `patientInfo_oph_rectify_test_vs.html`, and `discharge_card_oph.html`.
  - Simulated helper type `1` request to `sajid/getDiagnosisForDischarge.php` returned `PERMISSION_DENIED`.
  - Direct policy probes allowed helper type `8` Doctor, `6` Admin, `a` Super Admin, and `7` Counsellor.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html` to `/home/stagingdocbox/public_html/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/discharge_api_helpers.php` to `/home/stagingdocbox/public_html/sajid/includes/discharge_api_helpers.php`

## 2026-05-15 Patient Reports page analysis

- User asked to look for `patientReports.php` and analyze it before deciding the next hardening step.
- Page/files:
  - `/Users/apple/Documents/docbox_staging/patientReports.php`
  - `/Users/apple/Documents/docbox_staging/js/patientReportWeb.js`
  - Related variants exist but are not the active page script for `patientReports.php`: `patientReportsArchived.php`, `patientReportsCentrallisedS3.php`, `patientReportsCentrallisedGdrive.php`, `images/patientReport.js`, `js/patientReports.js`, and older rollback/test scripts.
- Active script:
  - `patientReports.php` loads `js/init.js?v=3.6` and `js/patientReportWeb.js?v=1.15`.
- Main active API calls found:
  - `sajid/getPatientArchivedDocumentsWeb.php`
    - document listing; already uses PHP session, CSRF, doctor/hospital scope, patient ownership, and prepared SQL.
  - `sajid/uploadDocumentsNew.php`
    - direct report upload; already uses PHP session, CSRF, doctor/hospital scope, patient ownership, extension/size/content checks, and prepared insert.
  - `sajid/getPatientUploadedFiles.php`
    - uploaded report lookup; already uses PHP session, CSRF, doctor scope, patient ownership when patient id is present, and prepared SQL.
  - `sajid/testDel.php`
    - delete report metadata and local safe-basename file; already uses PHP session, CSRF, doctor/hospital scope, patient ownership, and prepared delete.
  - `sajid/insertDocuments.php`
    - attaches Drive/YouTube links and finalizes temp uploaded files; already uses PHP session, CSRF, doctor/hospital scope, patient ownership, and prepared insert/delete.
  - `sajid/moveFollowup.php`
    - moves Blueimp temp uploads to patient folder; already uses PHP session, CSRF, doctor match, patient existence, filename validation, and controlled FTP move.
  - `sajid/server/sajid/index.php`
    - Blueimp temporary upload endpoint referenced indirectly through `js/main.js`; tracker says it was guarded in Patient Reports Batch 2.
- Existing tracker status:
  - `secured_api_tracking.md` already contains Patient Reports Batch 1 and Batch 2 rows for list/delete/upload/uploaded-file APIs.
  - Remaining open item is helper-type action policy: current tracker rows still mark report upload/delete/view permission as pending.
- Suggested next hardening:
  - Define a Patient Reports helper-type policy for page open, view/list, upload/attach, and delete.
  - Add a shared `patient_reports_api_guard.php` or a small policy helper in existing endpoints, then update `patientReports.php` page-level access and `patientReportWeb.js` button-level alerts.
- No application behavior was changed in this analysis pass.

## Deep Scan Findings - 2026-05-03

Status: staging should not be shared for VAPT until these public artifacts and production references are removed or explicitly accepted as harmless.

Public artifacts found under the downloaded web root:

- `ad_banners.zip`
- `phpmailer/PHPMailer-master.zip`
- `config/error_log`
- `js/Full-featured-Seating-Chart-Plugin-With-jQuery-Seat-Charts.zip`
- `js/error_log`
- `js/patientInfo_oph_new_backup.js`
- `js/home_test_a_backup.js`
- `js/profile_procedure_helper_backup.js`
- `patientInfo_oph_new_rollback.html.zip`
- `server/sajid/error_log`
- `Public/error_log`
- `sajid/info.php`
- `sajid/token.json`
- `sajid/debug_log.txt`
- `sajid/expenses.zip`
- `sajid/phpinfo.php`
- `sajid/server/sajid/error_log`
- `sajid/PHPMailer (1).zip`
- `sajid/log.txt`
- `sajid/error_log`
- `sajid/add_new_photo.png.zip`
- `api/error_log`
- `images (1).zip`

High-risk notes:

- `sajid/token.json` contains Google OAuth token material and must not remain public.
- `sajid/debug_log.txt` and `sajid/error_log` contain production URLs/server paths and likely patient-file references; move/delete public copies before VAPT.
- `sajid/info.php` and `sajid/phpinfo.php` expose server/PHP configuration and must not remain public.
- ZIPs/backups should be moved outside public_html, preferably under `/home/stagingdocbox/staging_storage/backups/public_removed/`, or deleted after confirming they are not needed.

Production DB/credential references still found outside the patched staging `sajid` bootstrap path:

- Root `db_connect.php` connects to `docbox.asia` / `docboxas_patientmanager` with production-style credentials.
- Root `db_functions.php` contains many fully qualified `docboxas_patientmanager` table references and direct `mysqli_connect("docbox.asia", ...)` calls.
- `wrong_stock_report.php` and `stock_audit_all_items.php` contain hardcoded DB host/name/user/password and enable browser error display.
- `config/config.php` is used by ABDM/API libraries and still has unsafe fallback DB credentials, bridge shared secret, and `fidelius_encrypt_url` pointing to `abdm.docbox.asia`.

Active production URL risks:

- `home_new.php` and `home_test_a.php` call `https://www.docbox.asia/sajid/increment_counter.php`.
- `sajid/getFollowupUrl.php` defines `MAIN_SERVER_BASE_URL` as `https://www.docbox.asia/sajid/`, writes to public `debug_log.txt`, and returns main-server URLs.
- Multiple ophthalmology patient JS files call `https://www.docbox.asia/sajid/getFollowupUrl.php` and/or build patient media URLs on `docbox.asia` / `docbox.co.in`. The active likely file `js/patientInfo_oph_new.js` has this pattern; rollback/test variants also contain it.
- `Public/abdm_m3_patient.php`, `Public/abdm_m3_console.php`, and ABDM API files contain hardcoded `https://abdm.docbox.asia/...` data-push/attach URLs. These need sandbox/staging review before ABDM VAPT scope.
- 2026-05-03 user confirmed `abdm.docbox.asia` must be kept for the ABDM handoff. `Public/abdm_m3_patient.php` redirects unlinked ABHA patients to `https://abdm.docbox.asia/public/abdm_abha_single_entry.php` with the existing `contextToken`, staging `callbackUrl`, `hipId`, and `hipName` parameters.
- 2026-05-04 `Public/abdm_m3_patient.php` now has a top-right `Link ABHA` button. It manually starts the same ABHA handoff without showing the missing-ABHA modal first, using the current patient/doctor context and the existing `contextToken`, staging `callbackUrl`, `hipId`, and `hipName` parameters.
- 2026-05-04 linked-patient ABHA flow fix: `Public/abdm_abha_single_entry.php` only skips to step 3 when launched with `launchMode=linked_abha` and `abhaAddress`. `Public/abdm_m3_patient.php` now appends those parameters when the loaded patient profile already has `abha.abhaAddress`, matching the older `patientInfo_oph_rectify_test_vs.js` launcher behavior.
- 2026-05-04 follow-up fix: the manual top-right `Link ABHA` button originally called `currentProfileForAbhaAttach()` without including `state.abha`, so linked patients launched without `abhaAddress` and stayed on step 1. The helper now includes `abha: state.abha || {}`.

Likely low-risk or documentation/display references:

- Privacy, terms, refund, marketing/email-template links pointing to `docbox.asia` or `docbox.co.in`.
- Commented PDF watermark examples.
- `index.php` still references production branding image and legal links; this is not a database/write risk, but should be changed if the VAPT agency requires all outbound production links removed.

## Step 1 Public Artifact Cleanup - Started 2026-05-03

Local changes made:

- Root `.htaccess` now disables directory listing, adds basic security headers, and blocks direct access to public-risk artifact patterns:
  - `.env`, `.sql`, `.zip`, `.bak`, `.backup`, `.log`
  - `error_log`, `debug_log.txt`, `log.txt`, `token.json`
  - `phpinfo.php`, `info.php`
  - filenames containing `backup` or `rollback`
- `sajid/docs/.htaccess` now denies web access to generated VAPT handover/API inventory docs.

Still required on the staging server:

- Upload root `.htaccess` to `/home/stagingdocbox/public_html/.htaccess`.
- Upload `sajid/docs/.htaccess` to `/home/stagingdocbox/public_html/sajid/docs/.htaccess`.
- Move/delete the listed public artifacts from `/home/stagingdocbox/public_html/`; recommended private target is `/home/stagingdocbox/staging_storage/backups/public_removed/`.
- Revoke and replace the Google OAuth material found in `sajid/token.json`; blocking the file is not enough if the token was ever public.
- Verify with browser/curl that `https://staging.docbox.asia/sajid/token.json`, `debug_log.txt`, `error_log`, `.zip`, and `phpinfo.php` return `403` or `404`.

Token tracking note:

- Do not store or quote the exposed OAuth token value in notes.
- Flag any code that reads or writes `sajid/token.json`, `token.json`, Google OAuth refresh/access token fields, or the Google Drive OAuth client from the removed public token file.
- If still required, move the token to private storage outside web root, for example `/home/stagingdocbox/staging_storage/config/token.json`, and update only staging code to read that private path.

## Edit Patient Staging Fix - 2026-05-03

Browser error:

```text
Uncaught TypeError: Cannot read properties of undefined (reading 'Patient Name')
at editPatient.js?v=1.9:253
```

Finding:

- `js/editPatient.js` expected `sajid/getPatientProfileWeb.php` to return a patient row at `p[1]`.
- On staging, the response can be empty/no-patient, or the patient row may not be fixed at index `1`.
- This likely means the selected `localStorage.patientId` is not present for the logged-in doctor in the staging DB, or the endpoint returned only table marker rows.

Local changes:

- `js/editPatient.js` now parses both string and already-parsed responses, searches for the row containing `Patient Name`, and shows a clear message instead of throwing a JS exception when no patient row exists.
- `js/editPatient.js` now handles empty/null `photo` values without crashing.
- `editPatient.php` now loads `js/editPatient.js?v=2.0` to avoid browser cache of the old `v=1.9` file.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/editPatient.js` to `/home/stagingdocbox/public_html/js/editPatient.js`
- `/Users/apple/Documents/docbox_staging/editPatient.php` to `/home/stagingdocbox/public_html/editPatient.php`

## Rectify Test VS Edit Navigation - 2026-05-03

Finding:

- Active top `Edit` button in `patientInfo_oph_rectify_test_vs.html` pointed to production:
  - `https://www.docbox.asia/editPatient.php`
- The older `href="editPatient.php"` button nearby is inside an HTML comment and is not active.
- JS age-update navigation in `js/patientInfo_oph_rectify_test_vs.js` already uses relative `editPatient.php`.

Local change:

- Updated active top `Edit` button to use relative `editPatient.php`.

Upload required:

- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## Edit Patient Submit Navigation Config - 2026-05-03

Finding before change:

- Edit submit success path is in `js/editPatient.js` after `POST sajid/updatePatient.php`.
- It hardcoded doctor-to-patient-profile routing:
  - BRD doctors -> `patientInfo_brd.html`
  - pharmacy doctors -> `patientInfo_pharmacy.html`
  - update doctors -> `patientInfo_update.html`
  - everyone else -> `patientInfo.html`
- This bypassed the existing centralized patient navigation endpoint:
  - `sajid/patientinfo_navigation_config.php`
- That endpoint already maps doctor `1224` to `patientInfo_oph_rectify_test_vs.html`.

Local change:

- `js/editPatient.js` now loads `sajid/patientinfo_navigation_config.php`, resolves the current `CustomerId` through its `routing.rules`, and redirects to the configured route after a successful edit.
- If the config endpoint cannot be loaded, it falls back to `patientInfo.html`.
- `editPatient.php` now loads `js/editPatient.js?v=2.1`.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/editPatient.js` to `/home/stagingdocbox/public_html/js/editPatient.js`
- `/Users/apple/Documents/docbox_staging/editPatient.php` to `/home/stagingdocbox/public_html/editPatient.php`

## Edit Patient Production URL Cleanup - 2026-05-03

Finding:

- `js/editPatient.js` had two active production image URLs:
  - `https://www.docbox.asia/add_new_photo.png`
  - `https://www.docbox.asia/sajid/{CustomerId}/0/{ProfilePic}`

Local change:

- Replaced both with same-origin relative paths:
  - `add_new_photo.png`
  - `sajid/{CustomerId}/0/{ProfilePic}`

Verification:

- Focused scan found no remaining `docbox.asia` or `docbox.co.in` URLs in `js/editPatient.js`.

Important overwrite note:

- The current local `js/editPatient.js` no longer contains the earlier submit navigation-config change or missing-patient guard. It appears this file was overwritten with an older/fresh server copy before this cleanup. Re-apply/verify the submit navigation-config fix before uploading if that behavior is still required.

## Edit Patient Re-Update - 2026-05-03

Finding before change:

- Local `js/editPatient.js` had reverted to older behavior:
  - submit success hardcoded patient routes instead of using `sajid/patientinfo_navigation_config.php`
  - patient profile response assumed the patient row was always `p[1]`
- Local `editPatient.php` loaded `js/editPatient.js?v=1.9`.
- Local `editPatient.php` had production legal links in the footer.

Local changes:

- Re-applied config-driven submit redirect in `js/editPatient.js`.
- Re-applied patient profile response parsing/guard in `js/editPatient.js`.
- Kept profile image URLs relative in `js/editPatient.js`.
- Changed `editPatient.php` footer legal links to relative paths.
- Bumped `editPatient.php` script version to `js/editPatient.js?v=2.2`.

Verification:

- Focused scan found no remaining runtime `docbox.asia` or `docbox.co.in` URLs in `js/editPatient.js` or `editPatient.php`.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/editPatient.js` to `/home/stagingdocbox/public_html/js/editPatient.js`
- `/Users/apple/Documents/docbox_staging/editPatient.php` to `/home/stagingdocbox/public_html/editPatient.php`

## ABDM M3 Patient Auto ABHA Redirect - 2026-05-03

Finding before change:

- `Public/abdm_m3_patient.php` already loaded patient data from `../api/abdm_m3_patient_profile.php`.
- If no linked ABHA was found, `loadPatient()` called `redirectToAbhaAttachFlow(data)`.
- The redirect was not automatic because `redirectToAbhaAttachFlow()` waited for `showAbhaAttachRedirectAlert()` and required the user to click Continue.
- The file also had hardcoded production ABDM host URLs:
  - `https://abdm.docbox.asia/public/abdm_abha_single_entry.php`
  - `https://abdm.docbox.asia/api/abdm_hiu_data_push.php`

Local changes:

- ABHA attach flow URL is now same-origin relative: `./abdm_abha_single_entry.php`.
- HI data push URL is now same-origin relative via `new URL('../api/abdm_hiu_data_push.php', window.location.href).toString()`.
- Missing-ABHA path now redirects immediately after creating the secure context token; it no longer waits for modal confirmation.

Verification:

- Focused scan found no remaining `docbox.asia`, `docbox.co.in`, or `abdm.docbox.asia` URLs in `Public/abdm_m3_patient.php`.

Upload required:

- `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`

Correction:

- User clarified the missing-ABHA path is supposed to show the modal.
- Restored `showAbhaAttachRedirectAlert(profileData)` before redirecting.
- Kept staging-safe relative URLs for ABHA attach flow and data-push endpoints.

## ABDM M3 Modal Not Showing Investigation - 2026-05-03

Finding:

- The modal DOM exists in `Public/abdm_m3_patient.php` as `#abhaRedirectModal`.
- CSS is valid: `.modal-backdrop.open { display: flex; }`.
- `showAbhaAttachRedirectAlert()` adds class `open` and waits for `#continueAbhaRedirectBtn`.
- The M3 launch button in `js/patientInfo_oph_rectify_test_vs.js` opens `Public/abdm_m3_patient.php` with `patientId` and `doctorId`, so the normal launch path is not missing query parameters.
- The modal is only reached when `api/abdm_m3_patient_profile.php` returns success and `data.abha.abhaAddress` is empty.

Most likely causes if the modal does not appear:

- The deployed `Public/abdm_m3_patient.php` is still the auto-redirect version and not the restored modal version.
- `api/abdm_m3_patient_profile.php` is returning a non-empty `abha.abhaAddress`, so `hasLinkedAbha(data)` returns true and the modal is intentionally skipped.
- The profile API is returning an error before `renderProfile(data)`, so the ABHA check is never reached.

Verification needed in browser Network tab:

- Open `Public/abdm_m3_patient.php?patientId=<id>&doctorId=<id>`.
- Check `../api/abdm_m3_patient_profile.php?...` response.
- If `success:false`, fix profile/API first.
- If `success:true` and `abha.abhaAddress` is non-empty, the code thinks ABHA is linked.
- If `success:true` and `abha.abhaAddress` is empty, the modal should show; if it does not, confirm the deployed file contains `await showAbhaAttachRedirectAlert(profileData);`.

## Rectify Test VS Care-Context Link Token Lookup - 2026-05-04

Finding before change:

- In `js/patientInfo_oph_rectify_test_vs.js`, a new visit save calls `linkSavedCareContextWithoutLightsailUi()`.
- That function posts `action: "check_token"` to `api/abdm_care_context_link_flow.php` with the current HMIS patient ID and newly saved care-context reference.
- `api/abdm_care_context_link_flow.php` used one strict token lookup:
  - `abha_address = current linked ABHA`
  - `patient_id = current patient`
  - `care_context_reference = newly saved context`
- `lib/AbdmHipConsentNotificationService.php` persists the real token callback using request ID, ABHA address, status, link token, and payload. It does not always populate `patient_id` or `care_context_reference` on the callback row.
- Therefore a valid received token could exist in `abdm_link_token`, while `check_token` still returned `missing` because the row did not match the strict patient/context filters.

Local change:

- Updated `api/abdm_care_context_link_flow.php` so `flowTokenState()` checks reusable link tokens by ABHA address plus HIP ID.
- It intentionally ignores `patient_id` and `care_context_reference` for the valid-token lookup because those fields can be blank, but it does require the HIP ID.
- If no reusable `received` token exists for the ABHA/HIP pair, it falls back to the latest row for that ABHA/HIP pair so the caller can still see pending/failed/used state.
- The fallback does not use production DB credentials and keeps the existing `abdm.docbox.asia` Lightsail base URL because that host is the intended ABDM service handoff.
- Added explicit handling for `status = "used"` so used link tokens are not treated as reusable.

Verification:

- `php -l api/abdm_care_context_link_flow.php` passed.
- Focused production-reference scan found only `http://abdm.docbox.asia`, which is intentionally retained per current staging ABDM routing.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_care_context_link_flow.php` to `/home/stagingdocbox/public_html/api/abdm_care_context_link_flow.php`

## Lightsail Script Download Review - 2026-05-04

Finding:

- User downloaded Lightsail server scripts into the local staging folder.
- `lightsail_files/` exists but is empty.
- Lightsail-looking ABHA/bootstrap files are present in the main local tree, including:
  - `api/abdm_generate_link_token.php`
  - `api/abdm_link_care_context.php`
  - `api/abdm_link_token_lookup.php`
  - `api/abdm_link_token_callback.php`
  - `api/abdm_bootstrap.php`
  - `lib1/`
- The local `api/abdm_generate_link_token.php` now differs from the earlier pasted Lightsail copy:
  - it requires `abhaAddress` only, not `abhaNumber`;
  - it sends `abhaAddress`, name, gender, and yearOfBirth to `/v3/token/generate-token`;
  - it records pending token requests back to the main/staging bridge at `/api/internal_link_token_request_record.php`;
  - it writes debug entries through `abdmDebugAppend()`.
- `api/abdm_link_care_context.php` still requires `abhaAddress`, `abhaNumber`, `linkToken`, and a care-context reference before posting to `/hip/v3/link/carecontext`.
- `api/abdm_link_token_callback.php` forwards token callback payloads to the bridge endpoint `/api/internal_consent_hip_notify.php`.

Risk found and fixed locally:

- Downloaded config content reintroduced hardcoded DB/bridge secrets in `config/config.php`.
- `config1/config.php` also contained production DB fallback references.
- Both files were changed to resolve secrets only from `/home/stagingdocbox/staging_storage/config/staging_secrets.php` or environment variables.
- Both configs default to `docboxasia_staging` / `docboxasia_usr` and do not contain hardcoded DB passwords or bridge shared secrets.
- `abdm.docbox.asia` Fidelius URL is intentionally retained.
- 2026-05-04 user confirmed `api1/` and `config1/` are obsolete; both folders were deleted from the local staging copy.

Verification:

- `php -l config/config.php` passed.
- `php -l api/abdm_generate_link_token.php` passed.
- `php -l api/abdm_link_care_context.php` passed.
- Verified `api1/` and `config1/` no longer exist locally.
- Focused scan of the examined Lightsail/config files no longer found the hardcoded DB password, production DB name/user, production web root, or production `docbox.asia` URL references. `abdm.docbox.asia` remains intentionally allowed.

Upload required if these local config changes should be deployed:

- `/Users/apple/Documents/docbox_staging/config/config.php` to `/home/stagingdocbox/public_html/config/config.php`
- Delete `/home/stagingdocbox/public_html/api1/` and `/home/stagingdocbox/public_html/config1/` on staging if they exist.

## Lightsail Script Analysis - 2026-05-04

Scope analyzed:

- `config/config.php`
- `api/abdm_bootstrap.php`
- `api/abdm_generate_link_token.php`
- `api/abdm_link_care_context.php`
- `api/abdm_link_token_lookup.php`
- `api/abdm_link_token_callback.php`
- `api/internal_link_token_lookup.php`
- `api/internal_link_token_request_record.php`
- `api/internal_link_token_status_update.php`
- `api/internal_consent_hip_notify.php`
- supporting `lib/AbdmHeaders.php`, `lib/AbdmToken.php`, and `lib/HttpClient.php`
- `Public/abdm_abha_single_entry.php` token lookup call sites

Architecture:

- Lightsail-facing code uses `api/abdm_bootstrap.php`.
- Staging/main-server internal bridge endpoints use `api/_bootstrap.php`.
- Lightsail calls ABDM sandbox through `AbdmHeaders::base(true)` and `AbdmToken`.
- Lightsail calls staging through `bridgeRequest()`, which signs requests with:
  - `X-DocBox-Client`
  - `X-Request-Id`
  - `X-Timestamp`
  - `X-Body-Sha256`
  - `X-Signature`
- Staging verifies those bridge calls with `verifyBridgeRequest()`, checks timestamp drift, checks body hash, checks HMAC signature, and records replay keys in `abdm_txn_log`.

Link token flow:

- `Public/abdm_abha_single_entry.php` calls `../api/abdm_link_token_lookup.php`.
- `api/abdm_link_token_lookup.php` forwards lookup to staging `/api/internal_link_token_lookup.php`.
- `api/abdm_generate_link_token.php` requires `abhaAddress`, name, gender, and yearOfBirth. It no longer requires `abhaNumber`.
- The generate-token outbound payload sent to ABDM contains `abhaAddress`, name, gender, and yearOfBirth.
- If ABDM accepts the generate-token request, Lightsail records the pending request back to staging via `/api/internal_link_token_request_record.php`.
- ABDM link-token callbacks enter `api/abdm_link_token_callback.php`, which forwards the callback to staging `/api/internal_consent_hip_notify.php`.

Important finding:

- `api/internal_link_token_lookup.php` still filters ABHA-address token lookup by `patient_id` when `contextToken` is present.
- This can still return “Link token not found yet” when the valid token callback row has `abha_address` and `hip_id` but blank `patient_id`.
- This is the same class of problem already fixed in `api/abdm_care_context_link_flow.php`.
- Next recommended patch: change `api/internal_link_token_lookup.php` so reusable token lookup is by `abha_address` plus `hip_id`, while still validating the `contextToken` for authorization.

Security/config findings:

- `config/config.php` now has no hardcoded DB password or bridge shared secret.
- Lightsail/staging config now depends on `/home/stagingdocbox/staging_storage/config/staging_secrets.php` or environment variables for `DB_PASS` and `ABDM_BRIDGE_SHARED_SECRET`.
- If `ABDM_BRIDGE_SHARED_SECRET` is missing, `bridgeRequest()` and `verifyBridgeRequest()` fail safely.
- `abdm.docbox.asia` remains intentionally allowed for Fidelius/ABDM bridge routing.
- `api/abdm_callback_debug_log.jsonl`, `api/error_log`, `Public/error_log`, and `config/error_log` are public-path artifacts and should not be deployed or left web-accessible.
- Error logs include production server paths such as `/home/docboxasia/public_html`; remove/move these before VAPT sharing.
- `lib/AbdmPrescriptionFhirBundleService.php` contains `https://www.docbox.asia/...` as FHIR identifier system URIs. These are not outbound calls, but should be reviewed before changing because changing FHIR system identifiers may affect interoperability/history.

No code changes were made in this analysis pass.

## Internal Link Token Lookup Fix - 2026-05-04

Server ownership:

- Staging main server, not Lightsail.

Finding before change:

- `Public/abdm_abha_single_entry.php` on the Lightsail ABHA flow calls `../api/abdm_link_token_lookup.php`.
- That Lightsail endpoint forwards lookup to staging `/api/internal_link_token_lookup.php`.
- `api/internal_link_token_lookup.php` correctly required and validated `contextToken` for ABHA-address lookup, but then used the handoff `patient_id` as an SQL filter.
- Valid `abdm_link_token` callback rows can have `abha_address` and `hip_id` with blank `patient_id`, so the lookup could incorrectly return “Link token not found yet.”

Local change:

- Updated `api/internal_link_token_lookup.php`.
- `contextToken` validation remains in place for authorization.
- Reusable token lookup now checks latest `received` token by `abha_address` plus `hip_id`.
- If no reusable received token exists, it falls back to latest row by `abha_address` plus `hip_id` so pending/failed/used state can still be returned.
- Added explicit `used` handling so used link tokens are not returned as valid.

Verification:

- `php -l api/internal_link_token_lookup.php` passed.
- Focused production-reference scan found no production URLs, production DB references, hardcoded DB password, or bridge secret in this file.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/internal_link_token_lookup.php` to `/home/stagingdocbox/public_html/api/internal_link_token_lookup.php`

## ABHA/HIP Link Token Scope Correction - 2026-05-04

Server ownership:

- `api/internal_link_token_lookup.php`: staging main server.
- `api/abdm_care_context_link_flow.php`: staging main server.
- `js/patientInfo_oph_rectify_test_vs.js`: staging main server frontend.
- `patientInfo_oph_rectify_test_vs.html`: staging main server frontend page.

Finding:

- User clarified a valid ABDM link token must be scoped by ABHA address and HIP ID.
- `Public/abdm_abha_single_entry.php` already sends `hipId: ABDM_HIP_ID` to the Lightsail lookup endpoint.
- `js/patientInfo_oph_rectify_test_vs.js` sent HIP ID during `check_token` and `generate_token`, but its `poll_token` call sent only patient ID and request ID.

Local changes:

- `api/internal_link_token_lookup.php` now requires `hipId` for ABHA-address lookup and filters reusable token rows by `abha_address` plus `hip_id`.
- `api/internal_link_token_lookup.php` also applies `abha_address` and `hip_id` filters when they are provided with a `requestId`.
- `api/abdm_care_context_link_flow.php` now checks reusable token rows by `abha_address` plus `hip_id`, and filters request-ID lookups by both values when available.
- `js/patientInfo_oph_rectify_test_vs.js` now sends `hipId` and `hipName` in `poll_token`.
- `patientInfo_oph_rectify_test_vs.html` script version bumped from `39.72` to `39.73`.
- Since `js/patientInfo_oph_rectify_test_vs.js` and `patientInfo_oph_rectify_test_vs.html` were edited, active hardcoded `www.docbox.asia` / `docbox.asia` asset and endpoint URLs in those files were converted to same-origin relative paths. `abdm.docbox.asia` was intentionally kept.

Verification:

- `php -l api/internal_link_token_lookup.php` passed.
- `php -l api/abdm_care_context_link_flow.php` passed.
- Focused production-reference scan on the four edited files found only intentional `abdm.docbox.asia` references.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/internal_link_token_lookup.php` to `/home/stagingdocbox/public_html/api/internal_link_token_lookup.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_care_context_link_flow.php` to `/home/stagingdocbox/public_html/api/abdm_care_context_link_flow.php`
- `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## Lightsail ABDM Inbound Debug Log Coverage - 2026-05-04

Server ownership:

- All files in this section belong to the Lightsail ABDM server (`abdm.docbox.asia`) local script copy.

Finding:

- The pasted `bridge_outbound_exchange` entries from `api/abdm_internal_care_context_list.php` and `api/abdm_link_token_lookup.php` were correctly marked `OUTBOUND`.
- The missing part was a separate inbound log line from the wrapper API before it forwarded the request to staging through `bridgeRequest()`.
- The shared JSONL writer already adds top-level `direction`, `logType`, `writerApi`, and `writer`; these wrapper files simply were not calling it at request entry.

Local changes:

- Added explicit `*_inbound` `abdmDebugAppend()` calls to Lightsail bridge wrapper APIs that were missing inbound entries.
- New inbound entries avoid raw token values. Boolean fields use names like `contextHandoffPresent` and `linkValuePresent` so the sanitizer does not redact the boolean itself.
- Added outbound `abdmDebugAppendHttpExchange()` entries for direct ABDM calls in discovery, care-context init, and care-context link request flows.

Updated files:

- `api/abdm_internal_care_context_list.php`
- `api/abdm_link_token_lookup.php`
- `api/abdm_internal_care_context_document.php`
- `api/abdm_link_token_callback.php`
- `api/abdm_link_token_status_update.php`
- `api/abdm_link_care_context_callback.php`
- `api/abdm_discovery_on_discover.php`
- `api/v3/hip/link/care-context/init.php`
- `api/abdm_link_care_context.php`
- `api/abdm_test_consent_validate.php`
- `api/abdm_test_health_information_transfer_prepare_encryption.php`
- `api/abdm_test_health_information_request.php`

Expected next log shape:

- A browser/Postman request to a Lightsail wrapper should now create an `INBOUND` entry with that wrapper as `writerApi`.
- If the wrapper forwards to staging, the existing `bridge_outbound_exchange` line should follow as `OUTBOUND`.

Verification:

- `php -l` passed for all 12 updated files.
- Focused production-reference scan on the edited files found no `https://docbox.asia`, `/home/docboxasia/public_html`, production DB references, or obvious credential strings.
- Direct JSONL writes remain centralized in `api/abdm_bootstrap.php`; `api/abdm_reset_callback_debug_log.php` only truncates the log.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_internal_care_context_list.php` to the Lightsail ABDM server `api/abdm_internal_care_context_list.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_token_lookup.php` to the Lightsail ABDM server `api/abdm_link_token_lookup.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_internal_care_context_document.php` to the Lightsail ABDM server `api/abdm_internal_care_context_document.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_token_callback.php` to the Lightsail ABDM server `api/abdm_link_token_callback.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_token_status_update.php` to the Lightsail ABDM server `api/abdm_link_token_status_update.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context_callback.php` to the Lightsail ABDM server `api/abdm_link_care_context_callback.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_discovery_on_discover.php` to the Lightsail ABDM server `api/abdm_discovery_on_discover.php`
- `/Users/apple/Documents/docbox_staging/api/v3/hip/link/care-context/init.php` to the Lightsail ABDM server `api/v3/hip/link/care-context/init.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context.php` to the Lightsail ABDM server `api/abdm_link_care_context.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_test_consent_validate.php` to the Lightsail ABDM server `api/abdm_test_consent_validate.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_transfer_prepare_encryption.php` to the Lightsail ABDM server `api/abdm_test_health_information_transfer_prepare_encryption.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_request.php` to the Lightsail ABDM server `api/abdm_test_health_information_request.php`

## Lightsail ABDM Debug Log Readability Spacing - 2026-05-04

Server ownership:

- `api/abdm_bootstrap.php`: Lightsail ABDM server shared logger.

Finding:

- `abdm_callback_debug_log.jsonl` entries were written back-to-back with only a single newline.
- Since each entry is a long one-line JSON object, the log was difficult to read in plain file viewers.

Local change:

- Updated the centralized `abdmDebugAppend()` writer to append one blank line after each JSON log record.
- This affects every API that writes through `abdmDebugAppend()`.

Verification:

- `php -l api/abdm_bootstrap.php` passed.
- Focused production-reference scan found no production URL or DB reference. Secret-related matches are existing redaction/signature helper code only.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php` to the Lightsail ABDM server `api/abdm_bootstrap.php`

## Care Context Link 502 ABHA Number Mismatch - 2026-05-04

Server ownership:

- `api/abdm_generate_link_token.php`: Lightsail ABDM server.
- `api/abdm_link_care_context.php`: Lightsail ABDM server.
- `Public/abdm_abha_single_entry.php`: Lightsail ABDM server frontend page.

Finding:

- The browser error `Care context linking request failed. (HTTP 502, POST /api/abdm_link_care_context.php)` comes from the Lightsail care-context link wrapper when ABDM `/hip/v3/link/carecontext` returns a non-2xx response.
- Local `api/abdm_callback_debug_log.jsonl` had a matching historical failure where ABDM returned HTTP 400:
  - code: `ABDM-9999`
  - message: `ABHA number mismatch with Link token`
- The exact local source was that `api/abdm_generate_link_token.php` accepted/used `abhaAddress` but ignored `abhaNumber`, while `api/abdm_link_care_context.php` later sent `abhaNumber` in the link-care-context payload.
- The main staging flow already sends `abhaNumber` to the Lightsail generate-token API, but the Lightsail API was not forwarding it to ABDM.

Local changes:

- `api/abdm_generate_link_token.php`
  - Now derives `abhaNumber` from input/profile/existingAccount.
  - Now requires both `abhaAddress` and `abhaNumber`.
  - Now includes `abhaNumber` in the ABDM `/v3/token/generate-token` payload.
  - Inbound debug log records `abhaNumberPresent` without logging the value.
- `Public/abdm_abha_single_entry.php`
  - Now sends `abhaNumber` in both fresh link-token generation calls.
  - Now blocks care-context linking with a clear message if the linked ABHA profile has no stored ABHA number.
- `api/abdm_link_care_context.php`
  - Now returns ABDM's error code/message in `message` and `abdmError` when the external link request fails, instead of only the generic 502 message.

Verification:

- `php -l api/abdm_generate_link_token.php` passed.
- `php -l api/abdm_link_care_context.php` passed.
- `php -l Public/abdm_abha_single_entry.php` passed.
- Focused production-reference scan found no `https://docbox.asia`, production web root, production DB references, or obvious credential strings in the edited files.

Operational note:

- Old received link tokens generated before this fix may still fail once with `ABHA number mismatch with Link token`.
- After deployment, discard/mark that old token failed and generate a fresh link token so the token and link-care-context call use the same ABHA number.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_generate_link_token.php` to the Lightsail ABDM server `api/abdm_generate_link_token.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context.php` to the Lightsail ABDM server `api/abdm_link_care_context.php`
- `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to the Lightsail ABDM server `Public/abdm_abha_single_entry.php`

## Link Token Generate Log Recheck And HY093 Fix - 2026-05-04

Server ownership:

- `api/abdm_generate_link_token.php`: Lightsail ABDM server.
- `api/internal_link_token_request_record.php`: staging main server.

Finding from pasted log:

- The deployed Lightsail `api/abdm_generate_link_token.php` is still not the latest local copy:
  - inbound `inputKeys` did not include `abhaNumber`
  - inbound log did not include `abhaNumberPresent`
  - ABDM `/v3/token/generate-token` outbound payload did not include `abhaNumber`
- Because of that, ABDM accepted token generation but later rejected `/hip/v3/link/carecontext` with `ABHA number mismatch with Link token`.
- The staging bridge call to `/api/internal_link_token_request_record.php` also returned `SQLSTATE[HY093]: Invalid parameter number`.
- The HY093 source was repeated PDO placeholder `:abha_address` in the care-context lookup query.

Local changes:

- `api/abdm_generate_link_token.php`
  - Added fallback derivation of `abhaNumber` from a numeric ABHA address local part, for example `91723813021885@sbx`.
  - This makes the API resilient even if an older browser payload omits `abhaNumber`, as long as the ABHA address itself is the numeric ABHA form.
- `api/internal_link_token_request_record.php`
  - Replaced repeated `:abha_address` placeholders with distinct names `:abha_address_exact` and `:abha_address_order`.
  - This removes the PDO invalid-parameter-number error when recording pending link-token requests.

Verification:

- `php -l api/abdm_generate_link_token.php` passed.
- `php -l api/internal_link_token_request_record.php` passed.
- Focused production-reference scan found no production URL, production web root, production DB references, or obvious credential strings in the edited files.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_generate_link_token.php` to the Lightsail ABDM server `api/abdm_generate_link_token.php`
- `/Users/apple/Documents/docbox_staging/api/internal_link_token_request_record.php` to `/home/stagingdocbox/public_html/api/internal_link_token_request_record.php`

Retest expectation:

- New `link_token_generate_inbound` should include `abhaNumberPresent: true`.
- New `link_token_generate_exchange` payload should include `abhaNumber`.
- New bridge call to `/api/internal_link_token_request_record.php` should return HTTP 200 instead of `SQLSTATE[HY093]`.

## Stale Link Token ABHA Number Guard - 2026-05-04

Server ownership:

- `api/abdm_link_token_lookup.php`: Lightsail ABDM server.
- `Public/abdm_abha_single_entry.php`: Lightsail ABDM server frontend page.
- `api/internal_link_token_lookup.php`: staging main server.
- `lib/AbdmHipConsentNotificationService.php`: staging main server callback persistence service.

Finding:

- The pasted failed response still used the old link request id `cd42834b-0cc7-46be-a2d8-fd77deed8d51`.
- The token used by that request was generated before `abhaNumber` was included in the ABDM `/v3/token/generate-token` payload.
- Staging callback persistence was also overwriting the original pending generate-token request payload with the callback payload, so later lookup could lose proof of which ABHA number was used when the token was generated.

Local changes:

- `api/abdm_link_token_lookup.php`
  - Now accepts `abhaNumber`.
  - Logs only `abhaNumberPresent`.
  - Forwards `abhaNumber` to staging `/api/internal_link_token_lookup.php`.
- `Public/abdm_abha_single_entry.php`
  - Now sends `abhaNumber` during existing-token lookup and request-id polling.
- `api/internal_link_token_lookup.php`
  - Now validates a received link token against the expected ABHA number when one is known.
  - If the stored token payload lacks a matching ABHA number, it returns HTTP 409 with `status: stale_abha_number_mismatch` and tells the caller to generate a fresh token.
  - For numeric ABHA addresses like `91723813021885@sbx`, it can derive the expected ABHA number from the address local part.
- `lib/AbdmHipConsentNotificationService.php`
  - Link-token callbacks now preserve existing pending request payload as `requestPayload`.
  - The callback body is stored as `callbackPayload`, preventing loss of the original generate-token payload.

Verification:

- `php -l api/abdm_link_token_lookup.php` passed.
- `php -l Public/abdm_abha_single_entry.php` passed.
- `php -l api/internal_link_token_lookup.php` passed.
- `php -l lib/AbdmHipConsentNotificationService.php` passed.
- Focused production-reference scan found no production URL, production web root, production DB references, or obvious credential strings in the edited files.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_link_token_lookup.php` to the Lightsail ABDM server `api/abdm_link_token_lookup.php`
- `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to the Lightsail ABDM server `Public/abdm_abha_single_entry.php`
- `/Users/apple/Documents/docbox_staging/api/internal_link_token_lookup.php` to `/home/stagingdocbox/public_html/api/internal_link_token_lookup.php`
- `/Users/apple/Documents/docbox_staging/lib/AbdmHipConsentNotificationService.php` to `/home/stagingdocbox/public_html/lib/AbdmHipConsentNotificationService.php`

## HIP Consent Notify Artefact Persistence Fix - 2026-05-04

Server ownership:

- `lib/AbdmHipConsentNotificationService.php`: staging main server callback persistence service.

Finding from pasted log:

- Discovery, link init, link confirm, and consent notify callbacks succeeded.
- The failure moved to the health-information request callback:
  - Lightsail called staging `/api/internal_health_information_request_prepare.php`.
  - Staging returned HTTP 404 with `Consent artefact was not found.`
- The consent notify callback had full `notification.consentDetail`, including:
  - `consentId`
  - patient ABHA address
  - care context reference
  - HI types
  - permission date range
- `api/internal_consent_hip_notify.php` calls `AbdmHipConsentNotificationService::persist()`.
- That service was logging `hip_consent_notify` into `abdm_txn_log`, but it was not calling `AbdmConsentArtefactService::persistFromCallback()`.
- Therefore `abdm_consent_artefact` did not get the row needed by `/api/internal_health_information_request_prepare.php`.

Local change:

- Updated `lib/AbdmHipConsentNotificationService.php`.
- For payload type `hip_consent_notify`, it now persists the consent artefact through `AbdmConsentArtefactService`.
- The result now includes `consentArtefact`.
- Request ID selection now prefers forwarded `_callbackRequestId` before the internal bridge request ID, so stored callback logs line up with ABDM's callback request ID.

Verification:

- `php -l lib/AbdmHipConsentNotificationService.php` passed.
- Focused production-reference scan found no production URL, production web root, production DB references, or obvious credential strings in the edited file.

Upload required:

- `/Users/apple/Documents/docbox_staging/lib/AbdmHipConsentNotificationService.php` to `/home/stagingdocbox/public_html/lib/AbdmHipConsentNotificationService.php`

Retest expectation:

- The next `/api/internal_consent_hip_notify.php` response for `hip_consent_notify` should include a non-null `result.consentArtefact`.
- The following `/api/internal_health_information_request_prepare.php` call should find the consent by `consentId` instead of returning `Consent artefact was not found.`

## Rectify Test VS Post-Save Care Context HIP ID Source - 2026-05-04

Files inspected:

- `js/patientInfo_oph_rectify_test_vs.js`: staging main frontend.
- `api/abdm_care_context_link_flow.php`: staging main server API.
- `api/patient_abha_status.php`: staging main server API.

Finding:

- When a visit is saved in Rectify Test VS, the post-save flow syncs/creates the care context and then calls `linkSavedCareContextWithoutLightsailUi()`.
- The HIP ID used for token check, token generation, care-context link, and update notification comes from frontend globals:
  - `ABDM_HIP_ID = localStorage.getItem('abdmHipId') || 'IN0910033627'`
  - `ABDM_HIP_NAME = localStorage.getItem('abdmHipName') || 'eye first eye hospital.'`
- The local copy has no code that sets `localStorage.abdmHipId` or `localStorage.abdmHipName`.
- If those localStorage keys are missing, Rectify Test VS sends fallback HIP ID `IN0910033627`.
- `api/abdm_care_context_link_flow.php` also has the same fallback if the frontend omits `hipId`.
- `api/patient_abha_status.php` only returns ABHA mapping/profile data and does not return HIP/facility information.

Implication:

- The post-save care-context linking HIP ID is currently browser localStorage driven, not derived from the logged-in doctor, the patient mapping, the saved visit, or the facility-scoped ABHA mapping.
- For facility `IN0910033762`, Rectify Test VS must have `localStorage.abdmHipId = IN0910033762`; otherwise it will use the old fallback.

No code changes were made for this inspection.

## Rectify Test VS ABHA Linked Status Fix - 2026-05-04

Server ownership:

- `api/patient_abha_status.php`: staging main server.

Finding:

- `js/patientInfo_oph_rectify_test_vs.js` checks the linked ABHA state through `api/patient_abha_status.php`.
- `api/patient_abha_status.php` only returned a linked mapping when both `hmis_patient_id` and `hmis_doctor_id` matched the current browser values.
- A DocBox patient profile can already be linked in `abdm_patient_abha_map` while the mapping row has a blank or different doctor id, so Rectify Test VS could show the patient as not linked even though the patient profile has an ABHA address.

Local change:

- Updated `api/patient_abha_status.php` so patient profile linkage is based on `hmis_patient_id` with a non-empty `abha_address`.
- The query still prefers the current doctor mapping when it exists, then blank doctor mappings, then the latest other-doctor mapping.
- The JSON response now includes `doctorMatched` for debugging without blocking the linked status.

Verification:

- `php -l api/patient_abha_status.php` passed.
- Focused production-reference scan found no production URLs, production DB references, hardcoded DB password, or secret-like config strings in this file.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/patient_abha_status.php` to `/home/stagingdocbox/public_html/api/patient_abha_status.php`

## Rectify Test VS ABDM Button Wiring Fix - 2026-05-04

Server ownership:

- `js/patientInfo_oph_rectify_test_vs.js`: staging main server frontend.
- `patientInfo_oph_rectify_test_vs.html`: staging main server frontend page.

Finding:

- The Rectify Test VS page renders the ABDM button as `id="openAbdmM3ConsoleBtn"`.
- The ABHA link-flow JavaScript was listening only for clicks on `#openAbhaFlowBtn` and `setAbhaFlowButtonStatus()` also searched only for that missing id.
- Because the expected id was not present, the click handler never ran, `setAbhaFlowButtonStatus()` returned early, and the initial exclamation mark remained visible even when `api/patient_abha_status.php` returned `linked:true`.

Local changes:

- Added `getAbhaFlowButton()` in `js/patientInfo_oph_rectify_test_vs.js` to support both `openAbhaFlowBtn` and the actual `openAbdmM3ConsoleBtn`.
- Updated the click handler to bind both ids.
- Updated the status function to set title/dot state on whichever ABDM button exists.
- Changed the status dot default CSS in `patientInfo_oph_rectify_test_vs.html` from visible to hidden so a stale warning is not shown before the status request completes.
- Bumped `patientInfo_oph_rectify_test_vs.js` from `v=39.73` to `v=39.74`.

Verification:

- `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Focused production-reference scan on the two edited frontend files found no active production `docbox.asia` URL references other than the intentional `abdm.docbox.asia` Lightsail handoff URL.
- Local `node --check` could not be run because Node is not installed in this workspace.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## ABDM Debug Log Metadata Visibility Fix - 2026-05-04

Server ownership:

- `api/abdm_bootstrap.php`: Lightsail ABDM server shared bootstrap/logger.
- `api/abdm_consents_hip_notify.php`: Lightsail ABDM callback server.

Finding:

- The previous logger change added top-level `direction`, `logType`, and `writerApi`, but if the server was still showing the old-looking output or if only nested `data` was being inspected, the distinction was not obvious.
- Existing historical lines in `api/abdm_callback_debug_log.jsonl` will not be rewritten; only new log lines after deployment will show the new fields.

Local changes:

- `abdmDebugAppend()` now duplicates `direction`, `logType`, and `writerApi` inside the nested `data` object as well as top-level fields.
- `api/abdm_consents_hip_notify.php` now explicitly passes `direction: inbound`, `logType: INBOUND`, and `writerApi: api/abdm_consents_hip_notify.php` in the main `hip_callback_inbound` log payload.
- This makes the distinction visible even when reading only the nested `data` payload.

Expected new inbound log shape:

- Top-level `direction`: `inbound`
- Top-level `logType`: `INBOUND`
- Top-level `writerApi`: `api/abdm_consents_hip_notify.php`
- Nested `data.direction`: `inbound`
- Nested `data.logType`: `INBOUND`
- Nested `data.writerApi`: `api/abdm_consents_hip_notify.php`

Verification:

- `php -l api/abdm_bootstrap.php` passed.
- `php -l api/abdm_consents_hip_notify.php` passed.
- Local PHP check confirmed path-info callback URI resolves writer API as `api/abdm_consents_hip_notify.php` and direction as `inbound`.
- Focused production-reference scan found no production URL or DB credential in the edited files; secret-related matches are existing redaction/signature helper code only.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php` to the Lightsail ABDM server `api/abdm_bootstrap.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_consents_hip_notify.php` to the Lightsail ABDM server callback path

## ABDM Debug Log Metadata Applied To All Writers - 2026-05-04

Server ownership:

- All files below are Lightsail ABDM server scripts unless otherwise noted.

Inventory:

- `api/abdm_bootstrap.php`: shared logger and bridge outbound logging.
- `api/abdm_consents_hip_notify.php`: HIP callback router.
- `api/abdm_generate_link_token.php`: link-token generate endpoint.
- `api/abdm_health_information_transfer_push.php`: health-information transfer push endpoint.
- `api/abdm_hiu_callback_common.php`: shared HIU callback handler.
- `api/abdm_hiu_consent_fetch.php`: HIU consent fetch endpoint.
- `api/abdm_hiu_consent_status.php`: HIU consent status endpoint.
- `api/abdm_hiu_consent_init.php`: HIU consent init endpoint.
- `api/abdm_hiu_health_information_notify.php`: HIU health-information notify endpoint.
- `api/abdm_hiu_health_information_request.php`: HIU health-information request endpoint.
- `api/abdm_reset_callback_debug_log.php`: reset utility; it truncates the file and does not append a log entry.

Local changes:

- Every direct `abdmDebugAppend()` call in the inventory now explicitly passes:
  - `direction`
  - `logType`
  - `writerApi`
- Inbound entry points use `direction: inbound` and `logType: INBOUND`.
- Outbound request/exception paths use `direction: outbound` and `logType: OUTBOUND`.
- Internal summary/result logs use `direction: internal` and `logType: INTERNAL`.
- `abdmDebugAppend()` in `api/abdm_bootstrap.php` still applies the same metadata as a fallback, both top-level and inside nested `data`.
- `abdmDebugAppendHttpExchange()` continues to mark HTTP exchange logs as outbound.

Verification:

- `php -l` passed for:
  - `api/abdm_bootstrap.php`
  - `api/abdm_consents_hip_notify.php`
  - `api/abdm_generate_link_token.php`
  - `api/abdm_health_information_transfer_push.php`
  - `api/abdm_hiu_callback_common.php`
  - `api/abdm_hiu_consent_fetch.php`
  - `api/abdm_hiu_consent_status.php`
  - `api/abdm_hiu_consent_init.php`
  - `api/abdm_hiu_health_information_notify.php`
  - `api/abdm_hiu_health_information_request.php`
- Final direct-call scan confirmed every `abdmDebugAppend()` call has explicit `direction`, `logType`, and `writerApi`.
- Direct file write scan found only:
  - `api/abdm_bootstrap.php` append writer.
  - `api/abdm_reset_callback_debug_log.php` reset/truncate utility.
- Focused production-reference scan found no production URL or DB credential in the edited files; secret-related matches are existing redaction/signature helper code only.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php` to Lightsail `api/abdm_bootstrap.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_consents_hip_notify.php` to Lightsail `api/abdm_consents_hip_notify.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_generate_link_token.php` to Lightsail `api/abdm_generate_link_token.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_health_information_transfer_push.php` to Lightsail `api/abdm_health_information_transfer_push.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_callback_common.php` to Lightsail `api/abdm_hiu_callback_common.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_consent_fetch.php` to Lightsail `api/abdm_hiu_consent_fetch.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_consent_status.php` to Lightsail `api/abdm_hiu_consent_status.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_consent_init.php` to Lightsail `api/abdm_hiu_consent_init.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_health_information_notify.php` to Lightsail `api/abdm_hiu_health_information_notify.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_hiu_health_information_request.php` to Lightsail `api/abdm_hiu_health_information_request.php`

## ABDM Link Token Callback HIP ID Finding - 2026-05-04

Server ownership:

- `api/abdm_consents_hip_notify.php`: Lightsail ABDM callback server.
- `api/abdm_link_token_callback.php`: Lightsail ABDM callback server.
- `api/internal_consent_hip_notify.php`: staging main server bridge endpoint.
- `api/internal_link_token_request_record.php`: staging main server pending-request recorder.
- `lib/AbdmHipConsentNotificationService.php`: staging main server callback persistence service.

Finding:

- The ABDM link-token callback reaches Lightsail at `api/abdm_consents_hip_notify.php/.../token/on-generate-token`.
- The inbound ABDM callback includes HIP ID in the `X-HIP-ID` header.
- The generic fallback bridge in `api/abdm_consents_hip_notify.php` forwards only the JSON payload to staging `/api/internal_consent_hip_notify.php`; it does not copy `X-HIP-ID` into `_hipId` or `hipId`.
- `api/abdm_link_token_callback.php` also forwards the JSON payload unchanged.
- `api/internal_link_token_request_record.php` does store `hip_id` when the pending generate-token request is recorded before the callback.
- If the callback persistence updates that same pending request row, the existing `hip_id` can be preserved.
- If the callback persistence creates a separate received row, or the pending row is missing/not matched, the received `abdm_link_token` row can have blank `hip_id`.
- Existing callback debug evidence shows a received link-token row returned with blank `hipId`, so HIP ID storage is not reliable today.

Recommended fix:

- On the Lightsail callback bridge, add `X-HIP-ID` from request headers into the forwarded payload as `_hipId` or `hipId` before calling `/api/internal_consent_hip_notify.php`.
- In the staging persistence service, when saving a link-token callback, set `abdm_link_token.hip_id` from callback payload/header metadata, falling back to the existing pending row's `hip_id` for the same `request_id`.
- Ensure `abdm_link_token.request_id` is unique or update logic explicitly updates the latest matching pending row, so callback rows do not split away from pending rows.

No runtime code was changed in this inspection pass.

## Link Token Callback HIP ID Forward/Persist Fix - 2026-05-04

Server ownership:

- `api/abdm_consents_hip_notify.php`: Lightsail ABDM callback server.
- `api/abdm_link_token_callback.php`: Lightsail ABDM callback server.
- `lib/AbdmHipConsentNotificationService.php`: staging main server callback persistence service.

Finding:

- The ABDM `/token/on-generate-token` callback includes HIP ID in the inbound `X-HIP-ID` header on Lightsail.
- The JSON callback body from ABDM does not include HIP ID.
- Lightsail was forwarding only the JSON body to staging `/api/internal_consent_hip_notify.php`, so staging could not reliably write `abdm_link_token.hip_id`.

Local changes:

- `api/abdm_consents_hip_notify.php` now copies inbound `REQUEST-ID` to `_callbackRequestId` and inbound `X-HIP-ID` to `_hipId` before forwarding the generic callback payload to staging.
- `api/abdm_link_token_callback.php` now does the same for the direct link-token callback bridge path.
- `lib/AbdmHipConsentNotificationService.php` now reads HIP ID from `_hipId`, `hipId`, `hip_id`, or `hip.id`.
- `lib/AbdmHipConsentNotificationService.php` now classifies top-level `linkToken` callbacks as `hip_link_token_callback`.
- When a link-token callback is persisted, staging now updates the existing `abdm_link_token` row for the same `request_id` if present; otherwise it inserts a received row.
- The update writes `hip_id = COALESCE(new HIP ID, existing hip_id)`, so the callback header value is stored and pending-row HIP ID is preserved if callback metadata is absent.

Verification:

- `php -l api/abdm_consents_hip_notify.php` passed.
- `php -l api/abdm_link_token_callback.php` passed.
- `php -l lib/AbdmHipConsentNotificationService.php` passed.
- Focused production-reference scan found no production URLs, production DB references, hardcoded DB password, or secret-like config strings in the three edited files.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_consents_hip_notify.php` to the Lightsail ABDM server callback path.
- `/Users/apple/Documents/docbox_staging/api/abdm_link_token_callback.php` to the Lightsail ABDM server callback path.
- `/Users/apple/Documents/docbox_staging/lib/AbdmHipConsentNotificationService.php` to `/home/stagingdocbox/public_html/lib/AbdmHipConsentNotificationService.php`

## ABDM Debug Log Metadata Standardization - 2026-05-04

Server ownership:

- `api/abdm_bootstrap.php`: Lightsail ABDM server shared bootstrap/logger.

Requirement:

- Every write to `api/abdm_callback_debug_log.jsonl` should clearly identify inbound vs outbound/internal logs.
- Each log line should identify which API script wrote it.
- Logs should be filterable by a consistent top-level field, not only by event name or nested data.

Local change:

- Updated `abdmDebugAppend()` in `api/abdm_bootstrap.php`.
- Every JSONL record now gets top-level:
  - `direction`: `inbound`, `outbound`, or `internal`
  - `logType`: uppercase distinction, for example `INBOUND`, `OUTBOUND`, `INTERNAL`
  - `writerApi`: API script that wrote the log, for example `api/abdm_consents_hip_notify.php`
  - `writer`: script metadata with `api`, `scriptName`, and `phpSelf`
  - `host`
- Direction is inferred from explicit `data.direction`/`data.logType`, then event names like `*_inbound`, `*_outbound`, `*_exchange`, then outbound request shape, otherwise `internal`.
- `abdmDebugAppendHttpExchange()` now explicitly sets outbound metadata for HTTP bridge/API exchanges.

Verification:

- `php -l api/abdm_bootstrap.php` passed.
- Local PHP check confirmed a path-info callback request such as `/api/abdm_consents_hip_notify.php/api/v3/hip/token/on-generate-token` resolves `writerApi` as `api/abdm_consents_hip_notify.php`.
- Local PHP check confirmed `hip_callback_inbound` is classified as `inbound` and `bridge_outbound_exchange` is classified as `outbound`.
- Focused production-reference scan found no new hardcoded production URL or DB credential in the edited file; secret-related matches are existing redaction/signature helper code only.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php` to the Lightsail ABDM server `api/abdm_bootstrap.php`

## Link Token Callback HIP ID DB Parse Recheck - 2026-05-04

Verified callback shape:

- Inbound request URI: `/api/abdm_consents_hip_notify.php/api/v3/hip/token/on-generate-token`
- Inbound headers include `X-HIP-ID`.
- Inbound JSON payload includes `abhaAddress`, `linkToken`, and `response.requestId`.

Code-path verification:

- The token callback shape does not match the earlier HIU, care-context confirm, care-context init, discovery, or health-information handlers in `api/abdm_consents_hip_notify.php`.
- Therefore it reaches the generic bridge block.
- The generic bridge block now copies `X-HIP-ID` into forwarded JSON as `_hipId`.
- `api/internal_consent_hip_notify.php` receives and parses that forwarded JSON through `jsonInput()`.
- `lib/AbdmHipConsentNotificationService.php` reads HIP ID from `_hipId`, `hipId`, `hip_id`, or `hip.id`.
- Since the payload has top-level `linkToken`, the service classifies it as `hip_link_token_callback`.
- `persistLinkTokenCallback()` updates the existing `abdm_link_token` row by `request_id`, writing `hip_id = COALESCE(NULLIF(:hip_id, ''), hip_id)`.
- If no row exists for that `request_id`, it inserts a received row with `hip_id = NULLIF(:hip_id, '')`.

Conclusion:

- After the three changed files are deployed to the correct servers, a callback with `X-HIP-ID: IN0910033762` should persist `IN0910033762` into `abdm_link_token.hip_id`.

## Generate Link Token Postman HIP ID Parsing Finding - 2026-05-04

Server ownership:

- `api/abdm_generate_link_token.php`: Lightsail ABDM server in normal flow; local copy inspected.
- `api/abdm_bootstrap.php`: Lightsail ABDM shared bootstrap/parser in normal flow; local copy inspected.

Finding:

- `api/abdm_generate_link_token.php` parses HIP ID only from JSON/form input key `hipId`:
  - `$hipId = trim((string) ($input['hipId'] ?? 'IN0910033627'));`
- It does not read the `X-HIP-ID` request header.
- `jsonInput()` in `api/abdm_bootstrap.php` reads `php://input`; if raw body exists, it tries `json_decode($raw, true)` and returns `[]` on invalid JSON.
- Because of that parser behavior, Postman `form-data` or `x-www-form-urlencoded` can be ignored when raw body is non-empty, even if PHP populated `$_POST`.
- Correct Postman body for current code is raw JSON with exact camelCase key `hipId`, for example `"hipId": "IN0910033762"`.
- Sending `hip_id`, `hipID`, or only header `X-HIP-ID` will fall back to default HIP ID unless code is updated.

Recommended fix:

- Add a helper that reads HIP ID from, in order: JSON/body `hipId`, JSON/body `hip_id`, `X-HIP-ID` header, then default.
- Improve `jsonInput()` fallback so invalid/non-JSON raw bodies can still use `$_POST`.

No runtime code was changed in this inspection pass.

## Rectify Test VS ABDM Button Redirect Correction - 2026-05-04

Server ownership:

- `js/patientInfo_oph_rectify_test_vs.js`: staging main server frontend.
- `patientInfo_oph_rectify_test_vs.html`: staging main server frontend page.

Finding:

- User clarified the main Rectify Test VS `ABDM` button must not redirect to `abdm.docbox.asia/public/abdm_abha_single_entry.php`.
- That Lightsail ABHA entry URL is only for the manual ABHA link flow, not for the main ABDM/M3 patient console button.

Local changes:

- Reverted the main `#openAbdmM3ConsoleBtn` click path away from the Lightsail ABHA URL.
- `#openAbdmM3ConsoleBtn` now opens same-origin `Public/abdm_m3_patient.php` with `patientId` and `doctorId` from local storage.
- The Lightsail URL remains only behind the separate `#openAbhaFlowBtn` handler.
- Bumped `patientInfo_oph_rectify_test_vs.js` from `v=39.74` to `v=39.75`.

Verification:

- `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Focused production-reference scan on the edited frontend files found no active production `docbox.asia` URL references other than the intentional `abdm.docbox.asia` Lightsail handoff URL, which is no longer used by the main ABDM button.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## Rectify Test VS Care-Context HIP Facility Source - 2026-05-04

Server ownership:

- `js/patientInfo_oph_rectify_test_vs.js`: staging main server frontend.
- `patientInfo_oph_rectify_test_vs.html`: staging main server frontend page.
- `api/abdm_care_context_link_flow.php`: staging main server bridge/API.
- `api/abdm_generate_link_token.php`: Lightsail ABDM server API.
- `api/abdm_link_care_context.php`: Lightsail ABDM server API.
- `api/abdm_link_context_notify.php`: Lightsail ABDM server API.
- `api/abdm_m3_console_records.php`: staging main server M3 console API.
- `api/abdm_m3_console_snapshot.php`: staging main server M3 console API.
- `api/abdm_m3_patient_profile.php`: staging main server M3 patient API.
- `api/abdm_m2_api_probe.php`: Lightsail ABDM server diagnostic probe API.
- `Public/abdm_m3_console.php`: staging main server M3 console UI.
- `Public/abdm_m3_patient.php`: staging main server M3 patient UI.

Finding:

- The Rectify Test VS post-save care-context flow was using `localStorage.abdmHipId` with fallback `IN0910033627` and `localStorage.abdmHipName` with fallback `eye first eye hospital.`.
- `api/abdm_care_context_link_flow.php` also accepted hardcoded fallback HIP values when the frontend omitted them.
- The Lightsail generate/link/notify endpoints also had fallback HIP ID `IN0910033627`.
- A broader scan found the same hardcoded HIP fallback in the M3 console records/snapshot APIs, the M2 probe API, and M3 UI input defaults.
- `api/abdm_m3_patient_profile.php` preferred `abdm_hip_facility_map`, but could fall back to `hospitalClinicDetails` without a HIP ID.

Local changes:

- Removed frontend HIP ID/name fallback variables from `js/patientInfo_oph_rectify_test_vs.js`.
- The frontend now sends `doctorId`/HMIS facility id to `api/abdm_care_context_link_flow.php` for token check, token polling, token generation, care-context linking, and linked-context update notification.
- `api/abdm_care_context_link_flow.php` now resolves HIP from `abdm_hip_facility_map` using active `hmis_facility_id = doctorId`.
- If no active mapping exists, the staging bridge returns an error instead of falling back to a hardcoded HIP.
- The Lightsail generate/link/notify endpoints now require `hipId` from the staging bridge and no longer default to `IN0910033627`.
- M3 console records/snapshot defaults now come from `abdm_hip_facility_map` instead of `IN0910033627`.
- M3 patient profile facility context now uses only an active `abdm_hip_facility_map` row and no longer falls back to `hospitalClinicDetails`.
- M3 console/patient UI inputs now start blank/placeholder-only and are populated from API data loaded from the facility map.
- The M2 diagnostic probe now requires `serviceId` or `hipId` input instead of using a hardcoded HIP default.
- Bumped `patientInfo_oph_rectify_test_vs.js` from `v=39.75` to `v=39.76`.

Verification:

- `php -l` passed for all edited PHP files and the HTML page.
- `node --check` could not be run because `node` is not installed in this local environment.
- Focused scan found no remaining `IN0910033627`, `abdmHipId`, `abdmHipName`, or `eye first eye hospital` fallback references in the active local copy, excluding only obsolete `config 1/` and `api 1/` folders.
- Focused scan found no active main production `docbox.asia` URL references in the edited files; the intentional `abdm.docbox.asia` Lightsail URL remains.

Upload required:

- `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
- `/Users/apple/Documents/docbox_staging/api/abdm_care_context_link_flow.php` to `/home/stagingdocbox/public_html/api/abdm_care_context_link_flow.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_generate_link_token.php` to the Lightsail ABDM server `api/abdm_generate_link_token.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context.php` to the Lightsail ABDM server `api/abdm_link_care_context.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_link_context_notify.php` to the Lightsail ABDM server `api/abdm_link_context_notify.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_records.php` to `/home/stagingdocbox/public_html/api/abdm_m3_console_records.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_snapshot.php` to `/home/stagingdocbox/public_html/api/abdm_m3_console_snapshot.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m3_patient_profile.php` to `/home/stagingdocbox/public_html/api/abdm_m3_patient_profile.php`
- `/Users/apple/Documents/docbox_staging/Public/abdm_m3_console.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_console.php`
- `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m2_api_probe.php` to the Lightsail ABDM server `api/abdm_m2_api_probe.php`

Superseding note:

- User objected to changing `Public/abdm_m3_patient.php` as part of the fallback cleanup.
- Reverted the two local changes made directly in `Public/abdm_m3_patient.php`:
  - restored `consentHiuIdInput` value `IN0910033627`
  - restored JS fallback `text(facility.hipId, 'IN0910033627')`
- Do not upload `Public/abdm_m3_patient.php` for this fallback cleanup unless the user explicitly requests it.

## M3 Patient Explicit Doctor Context Restore - 2026-05-04

Server ownership:

- `api/_bootstrap.php`: staging main server shared API bootstrap.
- `api/abdm_m3_patient_profile.php`: staging main server M3 patient API.
- `api/abdm_m3_patient_consents.php`: staging main server M3 patient API.
- `api/abdm_m3_patient_consent_requests.php`: staging main server M3 patient API.
- `api/abdm_m3_console_records.php`: staging main server M3 records API used by the M3 patient page.
- `api/abdm_m3_console_json.php`: staging main server M3 JSON detail API used by the M3 patient page.
- `api/abdm_m3_console_action.php`: staging main server M3 action API used by the M3 patient page.

Finding:

- User confirmed the M3 patient page previously used explicit/hardcoded staging doctor context.
- The deployed response `{"success":false,"message":"Authenticated doctor context is required."}` means the M3 API path was requiring session-authenticated doctor context instead of accepting `doctorId=3` from the page URL.

Local changes:

- Added staging M3 helper functions in `api/_bootstrap.php`:
  - `m3StagingCurrentDoctorId()`
  - `m3StagingAssertDoctorCanAccessPatient()`
  - `m3StagingRequirePatientAccess()`
- The helpers accept explicit `doctorId` from the M3 page/query/payload and validate it against `patient` or `abdm_patient_abha_map`.
- Replaced strict `m3Auth*` calls in the M3 patient API chain with the staging helper.
- Did not change `Public/abdm_m3_patient.php` in this step.

Verification:

- `php -l` passed for all seven edited PHP files.
- Focused scan found no remaining strict `m3Auth*` calls in the edited M3 patient API chain.
- Focused production-reference scan found no main production `docbox.asia` URLs in the edited files.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/_bootstrap.php` to `/home/stagingdocbox/public_html/api/_bootstrap.php`

## M3 Console Hardcoded HIU/HIP Defaults Removed - 2026-05-05

Server ownership:

- `Public/abdm_m3_console.php`: staging main server standalone M3 console page.
- `api/abdm_m3_console_records.php`: staging main server M3 console records API.
- `api/abdm_m3_console_snapshot.php`: staging main server M3 console snapshot API.

Finding:

- Active code still hardcoded old sandbox identity values in the standalone M3 console:
  - `IN0910033627`
  - `DocBox Sandbox Facility`
  - hardcoded requester values `Imran Akhtar`, `49356`, `Ophthalmology`, and `DocBox Eye Hospital`
- `api/abdm_m3_console_snapshot.php` also had a backend fallback to `IN0910033627`.

Local changes:

- Removed the hardcoded console input values and replaced them with placeholders.
- The selected source facility now populates HIU ID and source HIP ID from `abdm_hip_facility_map.hip_id`.
- If no HIU ID is available, consent/status/fetch/health-information actions stop and show an alert:
  - `HIU ID is missing. Configure an active facility in abdm_hip_facility_map or select a mapped source facility before continuing.`
- Consent init now also alerts if source HIP ID, requester name, or requester registration number is missing.
- `api/abdm_m3_console_records.php` and `api/abdm_m3_console_snapshot.php` now derive default HIU/HIP values from `abdm_hip_facility_map` when no stored consent HIU ID is present.
- `api/abdm_m3_console_snapshot.php` now returns mapped facilities and source facility defaults instead of hardcoded HIP defaults.

Verification:

- `php -l Public/abdm_m3_console.php` passed.
- `php -l api/abdm_m3_console_records.php` passed.
- `php -l api/abdm_m3_console_snapshot.php` passed.
- Focused scan found no remaining active references to `IN0910033627`, `DocBox Sandbox Facility`, `eye first eye hospital`, `DEFAULT_ABDM_HIP`, or the hardcoded requester values in `Public/` and `api/`, excluding historical context/backups.

Upload required:

- `/Users/apple/Documents/docbox_staging/Public/abdm_m3_console.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_console.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_records.php` to `/home/stagingdocbox/public_html/api/abdm_m3_console_records.php`
- `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_snapshot.php` to `/home/stagingdocbox/public_html/api/abdm_m3_console_snapshot.php`

## M3 Console Records Empty State - 2026-05-04

Server ownership:

- `api/abdm_m3_console_records.php`: staging main server M3 records API.

Finding:

- The endpoint is used by `Public/abdm_m3_patient.php` to load locally stored M3/HIU records.
- A patient can validly have no stored M3 consent/request/transfer/log rows yet.
- The API response shape should still be successful in that first-run state, with empty `consents`, `requests`, `transfers`, `dataPushEvents`, and `logs` arrays.
- The local API already handled empty result sets after successful queries, but direct table/facility-map queries could still fail before an empty-state response if optional M3 storage tables were missing or not initialized.

Local changes:

- Updated `api/abdm_m3_console_records.php` to check M3 storage table availability before querying optional stored-record tables.
- Missing/empty `abdm_patient_abha_map`, `abdm_consent_artefact`, `abdm_health_information_request`, `abdm_health_information_transfer`, and `abdm_hiu_phase1_log` now produce empty response sections instead of a failure.
- Facility loading now checks `abdm_hip_facility_map` and handles missing `hospitalClinicDetails` without failing.
- Removed hardcoded HIP/facility fallback values from this API; defaults now stay blank unless returned by `abdm_hip_facility_map` or stored consent data.

Verification:

- `php -l api/abdm_m3_console_records.php` passed.
- Focused scan found no main production `docbox.asia` URL references in the edited API.
- Focused scan found no remaining `IN0910033627` or `DocBox Sandbox Facility` fallback in the edited API.
- Separate inspection found hardcoded `IN0910033627` values still in `Public/abdm_m3_patient.php`; that page was not edited in this step because the current change is limited to the failing API.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_records.php` to `/home/stagingdocbox/public_html/api/abdm_m3_console_records.php`

## M3 Patient Requester Doctor Details Source - 2026-05-04

Server ownership:

- `api/abdm_m3_patient_profile.php`: staging main server M3 patient API.
- `Public/abdm_m3_patient.php`: staging main server M3 patient UI.
- `js/patientInfo_oph_rectify_test_vs.js`: staging main server Rectify Test VS launcher.
- `patientInfo_oph_rectify_test_vs.html`: staging main server Rectify Test VS page.

Finding:

- The M3 consent requester fields were hardcoded in `Public/abdm_m3_patient.php` as `Imran Akhtar` and registration number `49356`.
- User clarified requester doctor details must come from `docboxVisitingDoctorDetails`.
- In that table, `DoctorId` is the hospital-level id and `VisitingDoctorId` is the actual doctor id.

Local changes:

- `api/abdm_m3_patient_profile.php` now accepts `visitingDoctorId` and returns `requester` from `docboxVisitingDoctorDetails`.
- Lookup uses `DoctorId = doctorId` and `VisitingDoctorId = visitingDoctorId`.
- If `visitingDoctorId` is not provided and only one row exists for that hospital `DoctorId`, the API uses that single unambiguous row; if multiple rows exist, requester stays blank instead of guessing.
- `Public/abdm_m3_patient.php` now loads requester name/registration from profile API response and uses those input values in the consent payload.
- The hardcoded requester constants and input values were removed.
- `js/patientInfo_oph_rectify_test_vs.js` now appends `visitingDoctorId` when opening `Public/abdm_m3_patient.php`, using selected visiting doctor id when available, otherwise logged-in helper id, otherwise the existing admin-style `doctorId + "-1"` convention.
- Bumped `patientInfo_oph_rectify_test_vs.js` from `v=39.76` to `v=39.77`.

Verification:

- `php -l` passed for `api/abdm_m3_patient_profile.php`, `Public/abdm_m3_patient.php`, and `patientInfo_oph_rectify_test_vs.html`.
- Focused scan found no remaining `TEST_REQUESTER`, `Imran Akhtar`, or `49356` in active M3 patient requester code.
- Focused production-reference scan found no main production `docbox.asia` URLs in the edited files.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/abdm_m3_patient_profile.php` to `/home/stagingdocbox/public_html/api/abdm_m3_patient_profile.php`
- `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`
- `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
- `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

Follow-up fix:

- Staging returned `Call to undefined function m3StagingCurrentDoctorId()` from `api/abdm_m3_patient_profile.php`.
- Cause: profile API depended on new helper functions in `api/_bootstrap.php`, but staging was running a bootstrap without those helpers.
- Updated `api/abdm_m3_patient_profile.php` to be self-contained for this profile request path and not call `m3StagingCurrentDoctorId()` or `m3StagingAssertDoctorCanAccessPatient()`.
- Also normalizes URL values like `visitingDoctorId=null` to blank before querying `docboxVisitingDoctorDetails`.
- Upload only `/Users/apple/Documents/docbox_staging/api/abdm_m3_patient_profile.php` for this specific undefined-function fix.

Second follow-up:

- User clarified `visitingDoctorId` passed to `Public/abdm_m3_patient.php` must come from local storage `HelperID`.
- Updated `js/patientInfo_oph_rectify_test_vs.js` launcher to set `visitingDoctorId` from `localStorage.HelperID` only.
- Removed the launcher preference for `selectedDoctorId` and removed the admin fallback `doctorId + "-1"` from this URL builder.
- The launcher suppresses literal `null` and `undefined` values.
- Bumped `patientInfo_oph_rectify_test_vs.js` from `v=39.77` to `v=39.78`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

Third follow-up:

- User clarified local storage `HelperName` contains the doctor name.
- `Public/abdm_m3_patient.php` now uses `requester.name` from `docboxVisitingDoctorDetails` first, then falls back to local storage `HelperName` for requester name display/payload.
- Registration number still comes from `docboxVisitingDoctorDetails`, because no local-storage registration field was identified.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`

Fourth follow-up:

- Removed active HIP fallback constants from `Public/abdm_m3_patient.php`:
  - `DEFAULT_ABDM_HIP_ID`
  - `DEFAULT_ABDM_HIP_NAME`
- Consent modal fields now load HIU ID, source HIP ID, and source facility name from the profile/facility data only.
- If facility HIP ID or facility name is missing, ABHA attach flow stops and shows a page error instead of redirecting with fallback HIP data.
- If consent request data is missing, the consent modal now shows a specific missing-data alert listing the missing fields.
- Source HIP ID and source facility name are required before posting the consent request to `api/abdm_m3_console_action.php`.
- Superseded on 2026-05-06: Source HIP ID is no longer required for HIU consent-init requests that should cover all patient-linked HIPs. Keep this older bullet only as historical context.
- `php -l Public/abdm_m3_patient.php` passed.
- Focused scan found no remaining `DEFAULT_ABDM_HIP`, `IN0910033627`, `eye first eye hospital`, `Any available facility`, `Dr. Imran Akhtar`, or `49356` references in `Public/abdm_m3_patient.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php` to `/home/stagingdocbox/public_html/Public/abdm_m3_patient.php`

## M3 Bootstrap Staging Helpers - 2026-05-04

Server ownership:

- `api/_bootstrap.php`: staging main server shared API bootstrap.

Finding:

- `_bootstrap.php` had `m3Auth*` helpers but did not define the `m3Staging*` helpers called by the M3 patient/console APIs.
- This caused undefined-function 500 errors from endpoints such as `api/abdm_m3_console_records.php`.

Local changes:

- Added:
  - `m3StagingNormalizeNullableId()`
  - `m3StagingCurrentDoctorId()`
  - `m3StagingAssertDoctorCanAccessPatient()`
  - `m3StagingRequirePatientAccess()`
- The staging helper uses explicit request `doctorId` first, then falls back to session doctor id only if request doctor id is missing.
- Literal `null` and `undefined` ids are normalized to blank.

Verification:

- `php -l api/_bootstrap.php` passed.
- Focused scan confirms the `m3Staging*` functions are now defined in `_bootstrap.php`.
- Focused production-reference scan found no main production `docbox.asia` URL in `_bootstrap.php`.

Upload required:

- `/Users/apple/Documents/docbox_staging/api/_bootstrap.php` to `/home/stagingdocbox/public_html/api/_bootstrap.php`

## M3 HIU Consent Blank-HIP And Same-Day Range Fix - 2026-05-06

Server ownership:

- **Main server / staging UI and bridge proxy**
  - `/Users/apple/Documents/docbox_staging/Public/abdm_m3_patient.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_m3_console_action.php`
- **Lightsail ABDM app**
  - `/Users/apple/Documents/docbox_staging/api/abdm_hiu_consent_init.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_consents_hip_notify.php`

Behavior confirmed from 2026-05-06 consent-init logs:

- Consent init request sent to ABDM had no `consent.hip`.
- `careContexts` was `null`.
- `sourceFacility.hipId` was blank.
- `internal_hiu_consent_request_record.php` stored `hip_id = null`.
- ABDM accepted the consent init with HTTP `202`.

Current intended behavior:

- HIU consent-init should leave HIP blank when the consent is intended to let the patient select/share records across all linked HIPs in PHR.
- ABHA attach/link journeys still require a HIP ID because linking is facility-specific.
- FHIR/health-information preparation later receives the actual HIP from ABDM's `/hip/health-information/request` callback header `X-HIP-ID`; it is then forwarded as `hipId` to `api/internal_health_information_request_prepare.php`.

Same-day date-range fix:

- Problem found: `Public/abdm_m3_patient.php` defaulted consent `To Date` to yesterday via `defaultYesterday()`.
- Result: a health record created today was outside the consent permission range, and PHR showed no available facility within the requested duration.
- Fix: consent form now defaults `To Date` to today via `defaultToday()`.
- If `To Date` is today, `isoDateTime(..., true)` sends current timestamp instead of future end-of-day `23:59:59Z`.
- Validation now allows today but blocks dates after today.

Local verification:

- `php -l Public/abdm_m3_patient.php` passed.
- Previous syntax checks also passed for:
  - `api/abdm_m3_console_action.php`
  - `api/abdm_hiu_consent_init.php`

Upload/deployment reminder:

- Upload `Public/abdm_m3_patient.php` to the main server web root so the same-day consent date fix is live.
- Upload `api/abdm_m3_console_action.php` to the main server if not already deployed.
- Upload `api/abdm_hiu_consent_init.php` to Lightsail if not already deployed.

## ABDM Care Context Link Patient Reference Consistency - 2026-05-06

Server ownership:

- **Main server / staging UI and bridge proxy**
  - `/Users/apple/Documents/docbox_staging/api/abdm_care_context_link_flow.php`
  - `/Users/apple/Documents/docbox_staging/api/internal_care_context_link_confirm_record.php`
  - `/Users/apple/Documents/docbox_staging/api/internal_care_context_link_on_carecontext_record.php`
- **Lightsail ABDM app**
  - `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_link_context_notify.php`

Finding:

- Direct care-context linking sometimes sent ABDM `patient[0].referenceNumber` as the care context id (`CC_...`).
- Other link flows sent DocBox patient identity (`external_patient_id`, `OpdIpdNumber`, or HMIS patient id fallback).
- The inconsistent direct-link behavior came from Lightsail `api/abdm_link_care_context.php`, where `linkPatientReference()` preferred `careContext.reference` before the patient reference already sent by the main server.

Current intended behavior:

- `careContextReference` remains the `CC_...` value.
- `patientReference` should be a DocBox patient reference where available.
- Main server `api/abdm_care_context_link_flow.php` computes patient reference as:
  - `external_patient_id`
  - else `patient.OpdIpdNumber`
  - else HMIS patient id
- Main server `api/internal_care_context_link_confirm_record.php` uses the same identity preference for user-initiated OTP link confirm.

Local fix:

- Updated Lightsail `api/abdm_link_care_context.php`.
- `linkPatientReference()` now prefers:
  - top-level `patientReference`
  - `careContext.patientReference`
  - `careContext.patient_reference`
  - then falls back to the old `careContext.reference` behavior.

Safety:

- Callers that do not send `patientReference` keep the old fallback behavior.
- Consent, FHIR preparation, encrypted transfer, data push, parsing, and fetched-record UI display were not changed.

Verification:

- `php -l api/abdm_link_care_context.php` passed.

Upload/deployment reminder:

- Upload `/Users/apple/Documents/docbox_staging/api/abdm_link_care_context.php` to the Lightsail ABDM app path for `abdm.docbox.asia`.

## OWASP / SANS API Hardening Work - 2026-05-08

Scope and workflow:

- Current development focus has moved from ABDM documentation to whole-DocBox OWASP Top 10 / SANS Top 25 hardening.
- Work is being done page-wise, starting from `home_new.php`.
- Before editing any script, open it in VS Code first.
- Do not edit `sajid/db_functions.php` without explicit user approval. It may be opened/read to assess SQL risk, then ask before changing it.
- PHP version target is PHP 7.2; avoid newer PHP syntax.
- Keep all tracking files in the repo root unless the user says otherwise.

Security framework and tracker:

- **Main server / staging UI**:
  - `/Users/apple/Documents/docbox_staging/api_security_hardening_framework.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- The tracker checklist per API includes:
  - authentication/session required
  - session doctor/hospital binding
  - HelperTypeID authorization where needed
  - SQL injection protection
  - IDOR protection
  - CSRF consideration for cookie-session POST APIs
  - XSS-safe output where applicable
  - file upload/download validation where applicable
  - sensitive error messages removed

Session / CSRF baseline:

- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/api_auth.php`
  - starts secure PHP sessions
  - validates active session
  - validates CSRF via `X-DocBox-CSRF` or `csrfToken`
  - enforces submitted doctor/hospital id against the active session doctor id
  - loads helper-type-based timeout policy with DB override fallback
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/init.js`
  - sends `X-DocBox-CSRF` on jQuery AJAX requests
  - has a global AJAX error handler for `CSRF_TOKEN_INVALID` and `SESSION_EXPIRED`
- User confirmed all pages load `init.js`, and JS version bumps are required when changing JS.

Global app feature configuration:

- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/app_feature_config.php`
  - single server-side source of truth for reusable hospital-level feature flags/options.
  - no separate include file is used for this feature config.
- Current feature keys:
  - `features.appointmentPatientPool.allowedDoctorIds`
    - controls whether Rectify appointment booking shows the `Send to Patient Pool` option.
    - currently enabled for hospital/base doctor ids `2`, `1219`, `1223`, and `6832`.
  - `features.todayPool.allowedDoctorIds`
    - controls whether `home_new.php` shows the `Today's Pool` tab.
    - currently enabled for hospital/base doctor ids `1219`, `1223`, and `6832`.
  - `features.campProfile.allowedDoctorIds`
    - controls whether `home_new.php` shows camp profile UI.
    - currently enabled for hospital/base doctor id `1223`.
  - `features.counsellorDesk.allowedDoctorIds`
  - `features.attendanceModule.allowedDoctorIds`
  - `features.tpaManager.allowedDoctorIds`
  - `features.labManager.allowedDoctorIds`
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - no longer hardcodes the patient-pool hospital allowlist in JS.
  - loads `sajid/app_feature_config.php` and applies the `appointmentPatientPool` feature.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - script version bumped to `v=39.79`.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/home_new.js`
  - no longer uses hardcoded `APP_SETTINGS.customerGroups` for `todayPool` or `campProfile`.
  - no longer loads `sajid/navigation_config.php` for home feature buttons.
  - loads `sajid/app_feature_config.php` for `campProfile`, `todayPool`, `counsellorDesk`, `attendanceModule`, `tpaManager`, and `labManager`.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/home_new.php`
  - `home_new.js` version bumped to `v=1.48`.

HelperTypeID behavior:

- Helper type id can contain more than one role marker.
- Blank HelperTypeID means super admin and should have all rights.
- For multiple helper type ids, the most lenient timeout policy should apply.
- HelperTypeID authorization per action is planned but deferred until after endpoint/session/SQL hardening.

Completed API hardening items so far:

- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getHospitalStationList.php`
  - session auth, CSRF, session doctor binding, numeric doctor validation.
  - User synced and both tests passed.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/get_patient_stages_new_timing.php`
  - session auth, CSRF, session doctor binding, input validation, endpoint SQL cleanup, related DB function cleanup.
  - User confirmed the API works and brings correct data.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllPatientWebListMin.php`
  - session auth, CSRF, session doctor binding, validation, related DB functions updated with user approval.
  - User synced and confirmed correct result.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllPatientsWebListSearch.php`
  - session auth, CSRF, session doctor binding, search column whitelist, related DB function updated with user approval.
  - Search result patient card payment due/no-dues section removed from **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/home_new.js`.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/bookAppointmentStage.php`
  - session auth, CSRF, session doctor binding, patient ownership check, booking validation.
  - Related appointment/stage/pool DB functions updated with user approval.
  - User confirmed appointment booking works.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updatePatientLastVisit.php`
  - session auth, CSRF, session doctor binding, patient ownership check.
  - `db_functions.php::updatePatientLastVisitedDate()` updated with user approval.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientPool.php`
  - migrated from tokenless access to PHP session auth, CSRF, session doctor binding, numeric doctor validation, stable JSON array response.
  - Live unauthenticated staging request returns `401 SESSION_EXPIRED`.
  - `db_functions.php::getPatientPool()` and `db_functions.php::getPatientPoolForStaff()` were updated with user approval to validate ids and use prepared statements.

Current testing pattern:

- After local patch: run `php -l` on changed PHP files.
- Before user sync: live staging may still show old behavior.
- After sync: test unauthenticated access first; expected response is usually `401 SESSION_EXPIRED`.
- Then test from a logged-in browser session and confirm the real workflow still works.
- For mismatch tests, use another doctor id; expected response is `SESSION_DOCTOR_MISMATCH`.

Next likely `home_new.php` patient-pool APIs:

- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteFromPatientPool.php`
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updatePatientToPool.php`

Important current caution:

- `getPatientPool.php` currently reads optional `helperId` from the frontend but the hardened endpoint preserves old behavior by not applying staff filtering yet.
- Staff-specific pool visibility and HelperTypeID authorization should be handled later as part of the per-action authorization pass.

Counsellor Desk batching:

- Batch 1 is read-only/API lookup endpoints.
- Batch 2 is write/update endpoints.
- Batch 1 patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllPatientsCounsellorDesk.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllPatientsCounsellorDeskDate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAdvisedSurgeryForCounsellor.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getCallLogs.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getConsentData.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientProceduresDetail.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllVisionCentersDetails.php`
- Batch 1 uses PHP session auth, CSRF validation, prepared statements, and a mapped-center session scope check for centralised counsellor workflows that use `visionCenterId`.
- **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/api_auth.php` now includes `docbox_require_session_doctor_or_mapped_center()` for endpoints where a main hospital session can access mapped vision centers.

Counsellor Desk Batch 2:

- OT scheduling write flow is intentionally parked until the OT scheduling page review.
- Batch 2 patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAutoCompleteList.php`
    - now requires PHP session auth and CSRF.
    - validates submitted doctor id against active session doctor or mapped vision center.
    - validates autocomplete table/column identifiers before calling the existing DB function.
    - success response shape preserved for shared legacy JS compatibility.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getConsentTemplate.php`
    - now requires PHP session auth and CSRF.
    - validates doctor id and restricts template listing to that hospital/vision-center `ConsentTemplates` folder.
    - filters unsafe filenames from the returned list.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getConsentTextForSurgery.php`
    - now requires PHP session auth and CSRF.
    - validates doctor, patient, and surgery ids.
    - verifies advised-surgery ownership with a prepared query before returning stored consent text.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveSurgeryConsent.php`
    - now requires PHP session auth and CSRF.
    - validates doctor, patient, surgery, template name, and consent text sizes.
    - verifies advised-surgery ownership before saving.
    - replaces raw DB-function delete/insert with prepared statements.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/consentFormEditor.js`
    - handles both legacy text JSON and parsed JSON template responses.
    - saves surgery consent against `visionCenterId || CustomerId` so centralised counsellor ownership checks match the selected center.
    - unnecessary active console logs removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/counsellorDesk_centrallised.php`
    - `consentFormEditor.js` bumped to `v=1.6`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/counsellorDesk_test_a.php`
    - `consentFormEditor.js` bumped to `v=1.6`.
- Local verification:
  - `php -l` passed for all patched PHP files and the two counsellor desk PHP pages.
  - No `checkToken`, `display_errors`, raw SQL echo, or active `console.log(...)` remains in the Batch 2 patched files, except legacy/commented JS compatibility text.

Home New hardening:

- Home Batch 1 production scope covers transfer page-load support flows.
- Geofencing in `home_new.php` is experimental. `home_new.js` now has `APP_SETTINGS.experimentalFeatures.geofencing = false`, so Home New does not call `check_geofence_status.php` or `validateLocation.php` while the feature is parked.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getTransferPatient.php`
    - now requires PHP session auth and CSRF.
    - validates `DoctorId` against the active session.
    - validates `TransferTo` and uses a prepared transfer-list query.
    - non-empty helper sessions can only fetch their own `HELPER_ID`.
    - wildcard CORS and raw DB error leaks removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/transferPatient.php`
    - now requires PHP session auth and CSRF.
    - validates payload ids/text.
    - verifies patient and selected source/destination visiting doctors belong to the active hospital.
    - duplicate check and insert now use prepared statements.
    - display errors, wildcard CORS, and raw DB error leaks removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/get_today_transfer_overlay.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/date and uses a prepared overlay query.
    - display errors and raw DB error leaks removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/home_new.js`
    - geofencing calls are disabled behind `APP_SETTINGS.experimentalFeatures.geofencing = false`.
    - added the missing `docboxCsrfHeaders()` helper used by fetch calls.
    - transfer overlay, transfer-list, and transfer-save fetches now send `X-DocBox-CSRF`.
    - transfer-list fetch now sends `DoctorId` with `TransferTo`.
    - live issue resolved: `/sajid/getTransferPatient.php` was returning `CSRF_TOKEN_INVALID` after login because raw `fetch()` calls were not covered by `js/init.js` jQuery AJAX headers.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/home_new.php`
    - `home_new.js` bumped to `v=1.52`.
- Local verification:
  - `php -l` passed for all patched PHP files and `home_new.php`.
  - Scan showed no `display_errors`, wildcard CORS, raw SQL error leaks, `checkToken`, `Token invalid`, or `if(1)` in Home Batch 1 endpoints.
  - User synced and confirmed the `getTransferPatient.php` CSRF failure is resolved in the logged-in Home New flow.

Home New Batch 2 hardening:

- Batch 2 covers home activity/counter/report support APIs.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getTodayOPD.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - replaces legacy token check and DB-function count calls with prepared count queries directly in the endpoint.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientCredit.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - uses prepared patient-credit lookup directly in endpoint.
    - preserves legacy scalar JSON response used by add-patient navigation.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveHelperActivityLog.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/activity/patient ids and description length.
    - helper name now comes from PHP session instead of client-supplied localStorage.
    - uses prepared insert directly in endpoint.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/changeLogText.php`
    - now requires PHP session auth and CSRF.
    - validates doctor id and flag.
    - user identity now comes from PHP session instead of client-supplied localStorage.
    - uses prepared changelog seen-flag select/delete/insert queries.
    - escapes changelog file lines before returning HTML.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/diagnosisReport.php`
    - now requires PHP session auth and CSRF.
    - validates doctor id, unix date range, and search length.
    - uses prepared diagnosis report query directly in endpoint.
    - escapes returned HTML fields before DataTables rendering.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/locationReport.php`
    - now requires PHP session auth and CSRF.
    - validates doctor id, date range, and search length.
    - uses prepared location report query directly in endpoint.
    - escapes returned HTML fields before DataTables rendering.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/get_advice_report.php`
    - now requires PHP session auth and CSRF.
    - validates doctor id, date range, and search length.
    - uses prepared advice report query directly in endpoint.
    - no longer returns SQL text or raw DB errors.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/home_new.js`
    - Advice Report fetch now sends `X-DocBox-CSRF`.
    - Advice Report debug console output removed.
    - OPD count and patient-credit callbacks now accept both parsed JSON and legacy string responses.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/home_new.php`
    - `home_new.js` bumped to `v=1.50`.
- No `db_functions.php` edits were made for Batch 2; unsafe DB-function paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for all Batch 2 PHP endpoints and `home_new.php`.
  - Marker scan confirms Batch 2 endpoints contain session auth, CSRF, doctor-session binding, and prepared statements.

Add Patient hardening:

- Add Patient Batch 1 covers the registration sequence and patient insert path.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientSequence.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - replaces legacy token check and raw DB-function sequence query with prepared sequence/count queries directly in the endpoint.
    - preserves the existing response fields: `sequence`, `serverPatientId`, and `serverPID`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id, patient fields, mobile format, and image payload size.
    - ignores client-supplied patient id for persistence and generates the saved patient id/server PUID on the server.
    - replaces raw DB-function patient insert path with prepared endpoint queries for:
      - patient insert
      - patient misc info
      - WhatsApp opt-in row
      - auto-fee marker
      - detailed address
      - GST row
      - TPA row
      - patient credit lookup/decrement
      - WhatsApp enabled flag
    - removes raw cURL error output and hardcoded FTP directory creation from the registration response path.
    - creates the local patient storage directory without exposing FTP credentials.
    - preserves frontend response compatibility: `status`, `payPerUse`, and `syncId`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - registration responses now handle parsed JSON directly.
    - `getPatientSequence.php` call no longer sends the legacy token.
    - patient-info redirect after registration now uses central `sajid/patientinfo_navigation_config.php` instead of the old hardcoded doctor-id block.
    - active registration/debug console logs removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/addPatient.php`
    - `addPatient.js` bumped to `v=3.82`.
    - inline camera debug console logs removed.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/patientinfo_navigation_config.php`
    - now includes Add Patient redirect coverage for `1225`, `1204`, and `6831`.
- No `db_functions.php` edits were made for Add Patient Batch 1; unsafe patient-write DB-function paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for `sajid/getPatientSequence.php`, `sajid/insertPatientTest.php`, and `addPatient.php`.
  - `php -l` passed for `sajid/patientinfo_navigation_config.php`; CLI JSON smoke test returned the route config.
  - Local no-session probes against `getPatientSequence.php` and `insertPatientTest.php` returned `401 SESSION_EXPIRED`.

Add Patient Batch 2 hardening:

- Batch 2 covers the remaining Add Patient support lookup and shared secured calls.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/cityData.php`
    - remains a public static lookup because it is shared by Add Patient and kiosk-style registration scripts.
    - now loads staging bootstrap for consistent error handling.
    - restricts allowed methods to GET/POST.
    - sets JSON content type explicitly.
    - trims and filters city/state list values before returning JSON.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - `cityData.php` callback now handles both parsed JSON and legacy string JSON.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/addPatient.php`
    - `addPatient.js` bumped to `v=3.83`.
- Shared Add Patient submit follow-up APIs already secured and tracked:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePatientStage.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveHelperActivityLog.php`
- Local verification:
  - `php -l` passed for `sajid/cityData.php` and `addPatient.php`.
  - CLI JSON smoke test for `cityData.php` returned normalized city/state arrays.
  - Staging HEAD still showed old `text/html` response before sync; retest after sync should show `content-type: application/json; charset=utf-8`.

Rectify Test VS hardening:

- Active page:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
- Batch 1 covers core patient context/profile reads used when the page loads and when visit media is populated.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientProfileWeb.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient ids.
    - uses a prepared patient ownership check before calling legacy profile loaders.
    - legacy shared-token gate removed.
    - uses explicit `__DIR__` include path for `db_functions.php`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientVisitDoctorAllVisits.php`
    - already secured earlier with session auth, CSRF, doctor-session binding, patient ownership check, and prepared visit-doctor query.
    - included in Batch 1 as the dependency used by `getPatientProfileWeb.php` rendering.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getFollowupUrl.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/patient/version ids.
    - validates posted doctor id against the active session.
    - uses prepared patient ownership and media-follow-up queries.
    - removes debug-log writes and raw DB/cURL error leakage.
    - preserves existing main-server/S3 file URL existence checks for compatibility.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - `fetchMediaFollowUp()` now sends `X-DocBox-CSRF` for the raw fetch to `getFollowupUrl.php`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_test_vs.js` bumped from `v=39.86` to `v=39.87`.
- No `db_functions.php` edits were made for Batch 1.
- Remaining DB-function risk:
  - `db_functions.php::getPatientProfile` and `getPatientProfileCentrallised` still contain raw SQL and need a separate approved DB-function hardening pass.
- Local verification:
  - `php -l` passed for `sajid/getPatientProfileWeb.php`, `sajid/getFollowupUrl.php`, and `patientInfo_oph_rectify_test_vs.html`.
  - Local no-session probes returned `SESSION_EXPIRED` for `getPatientProfileWeb.php` and `getFollowupUrl.php`.
  - Local CLI emitted PHPMailer deprecation warnings only under PHP 8.5; staging target is PHP 7.2.
- Live verification:
  - User synced Batch 1.
  - Patient profile opened normally in `patientInfo_oph_rectify_test_vs.html`.
  - User confirmed all data is fetched properly after the patch.

Rectify Test VS Batch 2 hardening:

- Batch 2 covers supporting reads used after the patient profile opens: single-copy follow-up data, prescription print preferences, dilation timing, and shop delivery status.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientDataForSingleCopy.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient ids.
    - uses prepared patient ownership and follow-up field queries directly in the endpoint.
    - preserves the existing success shape: `status: "yes"` with `data.chiefcomplaint`, `data.findings`, and `data.advice`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPrescriptionPrintPreference.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - removes the old `if(1)` token-bypass path.
    - uses a prepared print-preference query directly in the endpoint.
    - preserves the existing `prescriptionPrintPreference` response shape, or JSON `0` when no preference exists.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getDilationTiming.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient ids.
    - removes display-error output.
    - uses prepared patient ownership and dilation timing queries directly in the endpoint.
    - preserves the existing array-or-`0` response shape.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/checkShopDelivery.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates receipt id while allowing existing receipt formats containing `/`, `.`, and `-`.
    - replaces escaped/interpolated SQL with a prepared delivery-status query.
    - removes SQL debug logging and raw MySQL errors from the response.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - adds `docboxPatientInfoCsrfHeaders()` for Rectify raw `fetch()` calls.
    - sends `X-DocBox-CSRF` for shop delivery and follow-up media fetches.
    - handles both parsed JSON and legacy string JSON for the touched jQuery callbacks.
    - removes obvious debug console logs in the touched single-copy, print-preference, dilation, and delivery paths.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_test_vs.js` bumped from `v=39.87` to `v=39.88`.
- No `db_functions.php` edits were made for Batch 2; unsafe helper methods were bypassed with prepared endpoint queries.
- DB-function methods still needing separate approval if we choose to clean the shared layer:
  - `db_functions.php::getPatientDataForSingleCopy`
  - `db_functions.php::getPrescriptionPrintPreference`
  - `db_functions.php::getDilationTiming`
- Local verification:
  - `php -l` passed for `sajid/getPatientDataForSingleCopy.php`, `sajid/getPrescriptionPrintPreference.php`, `sajid/getDilationTiming.php`, `sajid/checkShopDelivery.php`, and `patientInfo_oph_rectify_test_vs.html`.
  - Local no-session probes returned `SESSION_EXPIRED` for all four protected Batch 2 endpoints.

Profile page autocomplete CSRF fix:

- User reported `CSRF_TOKEN_INVALID` from `getAutoCompleteList.php` on the profile page.
- Root cause identified locally:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
    - profile page was still loading `js/init.js?v=2.7`.
    - `getAutoCompleteList.php` calls on profile are jQuery `$.post` calls, so they depend on the global `ajaxSend` handler in `js/init.js` to attach `X-DocBox-CSRF`.
    - the old cache-bust could keep an older `init.js` in the browser cache and cause the protected autocomplete endpoint to reject the request.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
    - bumped `js/init.js` from `v=2.7` to `v=3.4`.
- Local verification:
  - `php -l profile.php` passed.
- After sync, hard refresh profile page and retry the autocomplete field that failed.
- Profile autocomplete follow-up on 2026-05-09:
  - User reported HTTP `400` from `profile_template_helper.js?v=1.4` calling `POST /sajid/getAutoCompleteList.php`.
  - Root cause: the secured endpoint reused the strict table/column whitelist for the third autocomplete label value; profile sends `Remark/Complications`, which legitimately contains `/`.
  - Patch:
    - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAutoCompleteList.php`
    - added `docbox_autocomplete_clean_label()` for the third row value only.
    - table and column identifiers still use the stricter `docbox_autocomplete_clean_identifier()` whitelist.
  - Verification:
    - `php -l sajid/getAutoCompleteList.php` passed.
    - Local regex check accepts `Remark/Complications`.

Rectify Test VS Batch 3 hardening:

- Batch 3 covers support/template calls used by the Rectify clinical page:
  - SMS credit quota before patient message modal.
  - Visit template list.
  - Dynamic autocomplete suggestions.
  - Legacy activity logging for suggestion/template clicks.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSmsCredits.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - replaces the legacy token/DB-function path with a prepared SMS quota query.
    - preserves JSON scalar response shape.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getVisitTemplate.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates optional patient ownership when patient id is supplied.
    - replaces the legacy token/DB-function path with a prepared visit-template query.
    - preserves array-or-`0` response shape.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAutoCompleteListDynamic.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates dynamic table/column identifiers and search length.
    - replaces tokenless/raw interpolated SQL with validated identifiers and prepared search parameters.
    - returns a JSON array.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveActivityLog.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor/activity ids against the active session.
    - replaces legacy token/DB-function path with prepared duplicate-check and insert queries.
    - note: legacy `db_functions.php::saveActivityLog` had the insert commented out; this endpoint now actually writes the activity log.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - adds `docboxPatientInfoParseJson()` so touched callbacks work with either parsed JSON or legacy string JSON.
    - updates touched SMS, visit-template, and dynamic-autocomplete callbacks to use the helper.
    - removes obvious debug logs in the touched callback paths.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_test_vs.js` bumped from `v=39.88` to `v=39.89`.
- No `db_functions.php` edits were made for Batch 3; unsafe helper paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for `sajid/getSmsCredits.php`, `sajid/getVisitTemplate.php`, `sajid/getAutoCompleteListDynamic.php`, `sajid/saveActivityLog.php`, and `patientInfo_oph_rectify_test_vs.html`.
  - Local no-session probes returned `SESSION_EXPIRED` for all four protected Batch 3 endpoints.

Rectify Test VS Batch 4 hardening:

- Batch 4 covers visit-specific clinical read APIs used after opening a visit in `patientInfo_oph_rectify_test_vs.html`.
- Patched locally on 2026-05-08:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientVisitDoctor.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning visit doctor and next-visit data.
    - replaces legacy token/DB-function path with prepared visit-doctor and next-visit queries.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getVisitChangeLog.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning changelog rows.
    - replaces legacy token/DB-function path with prepared changelog query.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientFundusFindings.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning fundus findings.
    - replaces legacy token/DB-function path with prepared fundus query.
    - preserves the existing `[plotRows, dbRows]` response shape.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getVANear.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning VA near values.
    - replaces old `if(1)` token bypass and raw DB-function path with prepared query.
    - preserves the existing `{vaNear: [...]}` response shape.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientSpectacle.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning spectacle rows/version list.
    - replaces legacy token/DB-function path with prepared spectacle and spectacle-version queries.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientMedications.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning medication rows.
    - replaces legacy token/DB-function path with prepared medication queries.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllVisitDiagnosis.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates patient ownership before returning diagnosis rows.
    - replaces raw interpolated SQL with prepared diagnosis query.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - updates touched Batch 4 callbacks to use `docboxPatientInfoParseJson()` so they work with parsed JSON and legacy string JSON.
    - sends `X-DocBox-CSRF` for the raw `fetch()` call to `getAllVisitDiagnosis.php`.
    - removes obvious debug logs in touched Batch 4 read paths.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_test_vs.js` bumped from `v=39.90` to `v=39.91`.
    - Later bumped to `v=39.92` after a logged-in smoke test exposed one duplicate `populateFollowup()` callback still parsing already-decoded JSON as a string.
  - Follow-up frontend fix on 2026-05-08:
    - patched duplicate Batch 4 visit doctor, changelog, fundus, VA near, and spectacle callbacks to use `docboxPatientInfoParseJson(response)`.
    - removed debug logs in those touched duplicate callback paths.
    - bumped to `v=39.93` and patched the duplicate visit medication callback to use `docboxPatientInfoParseJson(response)` with an empty-array fallback for `0`/empty medication responses.
- No `db_functions.php` edits were made for Batch 4; unsafe helper paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for all seven Batch 4 PHP endpoints and `patientInfo_oph_rectify_test_vs.html`.
  - Local no-session probes returned `SESSION_EXPIRED` for all seven protected Batch 4 endpoints.
- Live staging verification after sync:
  - Unauthenticated POST probes returned HTTP `401` with `SESSION_EXPIRED` for all seven Batch 4 APIs:
    - `getPatientVisitDoctor.php`
    - `getVisitChangeLog.php`
    - `getPatientFundusFindings.php`
    - `getVANear.php`
    - `getPatientSpectacle.php`
    - `getPatientMedications.php`
    - `getAllVisitDiagnosis.php`
  - Logged-in Rectify page smoke test still pending from browser.

Rectify Test VS Batch 5A delete-action hardening:

- Batch 5A covers visit/medication delete actions used inside `patientInfo_oph_rectify_test_vs.html`.
- Patched locally on 2026-05-09:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteFollowup.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/version identifiers.
    - replaces legacy token/raw `db_functions.php::deleteFollowup` path with prepared deletes against `followUp`, `mediaFollowUp`, `otherFollowUp`, and `diagnosis`.
    - removes the SQL echo leak from the legacy helper path by bypassing it.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteAllVisitMedication.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version identifiers.
    - checks patient ownership before deleting.
    - replaces legacy token/raw `db_functions.php::deleteAllVisitMedication` path with a prepared delete.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedication.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version/type identifiers and bounds-checks medication name length.
    - checks patient ownership before deleting.
    - replaces legacy token/raw `db_functions.php::deleteMedication` path with prepared deletes.
- No `db_functions.php` edits were made for Batch 5A; unsafe helper paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for all three Batch 5A PHP endpoints.
  - Local no-session probes returned `SESSION_EXPIRED` for all three protected Batch 5A endpoints:
    - `deleteFollowup.php`
    - `deleteAllVisitMedication.php`
    - `deleteMedication.php`
- Live staging verification:
  - After resync, unauthenticated staging probes returned HTTP `401` with `SESSION_EXPIRED` for all three Batch 5A endpoints.
  - User confirmed logged-in UI tests passed for deleting one medicine, deleting all medicines, and deleting a visit.

Rectify Test VS Batch 5B copy-action hardening:

- Batch 5B is being split because some template/copy-all helpers are large legacy DB functions with multiple raw SQL statements.
- Patched locally on 2026-05-09:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/copyVisitDiagnosis.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version identifiers.
    - checks patient ownership before copying.
    - replaces legacy token/raw `db_functions.php::copyVisitDiagnosis` path with prepared previous-version lookup, insert-select, and result-select queries.
    - preserves the existing `status: "what"` and `syncId` rows response shape used by the frontend.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/copyVisitMedicines.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version identifiers.
    - checks patient ownership before copying.
    - replaces legacy token/raw `db_functions.php::copyVisitMedicines` path with prepared previous-version lookup and insert-select queries.
    - preserves the existing `status: "what"` response convention; frontend then reloads medicines through `getPatientMedications.php`.
- No `db_functions.php` edits were made for these two Batch 5B endpoints; unsafe helper paths were bypassed with prepared endpoint queries.
- Local verification:
  - `php -l` passed for both patched Batch 5B endpoints.
  - Local no-session probes returned `SESSION_EXPIRED` for both protected endpoints:
    - `copyVisitDiagnosis.php`
    - `copyVisitMedicines.php`
- Remaining Batch 5B APIs needing deeper handling:
  - `copyMedications.php`
  - `copyLastVisit.php`
  - `addFollowupFromTemplate.php`
  - `updateVisitFromTemplate.php`
  - These call larger legacy helpers (`copyMedications`, `copyLastVisit`, `addFollowupUsingTemplate`, `updateVisitFromTemplate`) that contain multiple interpolated SQL statements and should either be bypassed endpoint-by-endpoint or updated in `db_functions.php` with explicit approval.

Rectify Test VS Batch 5C template/copy-visit wrapper hardening:

- Batch 5C covers the remaining larger copy/template action wrappers.
- Patched locally on 2026-05-09:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/copyMedications.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session, with session doctor fallback for the save-template flow that historically did not post `doctorIdJSON`.
    - validates version/template identifiers before calling the legacy helper.
    - removes legacy token check from the endpoint wrapper.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/copyLastVisit.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/new-version identifiers.
    - checks patient ownership before calling the legacy helper.
    - replaces raw `getPreviousVisitVersion()` helper call with a prepared previous-version lookup in the endpoint.
    - whitelists copy-preference ids before passing them to `copyLastVisit()`.
    - removes old `if(1)` token bypass and display errors from the endpoint wrapper.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addFollowupFromTemplate.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/new-version/template identifiers.
    - checks patient ownership before calling the legacy helper.
    - removes display errors and legacy token check from the endpoint wrapper.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateVisitFromTemplate.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/new-version/template/visiting-doctor identifiers.
    - checks patient ownership before calling the legacy helper.
    - removes display errors and legacy token check from the endpoint wrapper.
- No `db_functions.php` edits were made for Batch 5C.
- Important risk note:
  - SQL injection is mitigated at the endpoint wrapper by strict validation of user-controlled identifiers/template names and by prepared lookup/ownership checks.
  - Full SQLi closure is still marked `Partial` for these four endpoints because the called helpers in `db_functions.php` still contain multiple interpolated SQL statements and should be hardened with explicit approval in a later DB-function pass.
- Local verification:
  - `php -l` passed for all four Batch 5C endpoints.
  - Local no-session probes returned `SESSION_EXPIRED` for all four protected endpoints:
    - `copyMedications.php`
    - `copyLastVisit.php`
    - `addFollowupFromTemplate.php`
    - `updateVisitFromTemplate.php`

Rectify Test VS Batch 6 detailed case sheet, vitals, and media hardening:

- Batch 6 was patched together on 2026-05-09.
- Patched locally:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertDetailedCaseSheet.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version identifiers.
    - checks patient ownership before saving.
    - bypasses raw `insertDetailedCaseSheet()` and `saveDetailedExamSuggestionsLocal()` helper paths with prepared endpoint SQL.
    - removes the legacy helper SQL echo leak from the save path.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllVitalsForGraph.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient identifiers.
    - checks patient ownership before returning the graph table.
    - bypasses raw vitals DB helpers with prepared endpoint queries.
    - escapes dynamic DB values before building the returned HTML table.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getVitalsVersionList.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient identifiers and checks patient ownership.
    - bypasses raw `getVitalsVersionList()` helper with a prepared endpoint query.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getVitalsList.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version/section values and checks patient ownership.
    - bypasses raw `getVitalsList()` / `getVitalsListSection()` helpers with prepared endpoint queries.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveVitals.php`
    - now requires PHP session auth and CSRF.
    - validates the doctor id embedded in the vitals row payload against the active session.
    - validates row shape and stable identifiers.
    - checks patient ownership before saving.
    - bypasses raw `saveVitalsList()` with prepared delete/insert SQL.
    - includes patient id in the delete scope, avoiding same-doctor/version/section cross-patient deletes.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/uploadOtherMedia.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/patient/version values and checks patient ownership.
    - validates actual uploaded file presence, MIME type, size, and path components.
    - generates a safe JPG/PNG filename and stores under validated doctor/patient directory.
    - removes raw FTP/connect error exposure.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/uploadAnteriorPosterior.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/patient/version/segment values and checks patient ownership.
    - validates actual uploaded file presence, MIME type, size, and path components.
    - removes hardcoded FTP credential literals from the endpoint.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/uploadFindingDrawing.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/patient/version/finding field id and checks patient ownership.
    - validates actual uploaded file presence, MIME type, size, and path components.
    - supports JPG/PNG uploads including canvas/snapshot uploads.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/printDetailedFindingsDrawing.php`
    - now requires PHP session auth and CSRF before loading hospital/patient/case-sheet data.
    - validates doctor/patient/version/field id and checks patient ownership.
    - disables display errors.
    - escapes patient/finding values and sanitizes image filenames in generated PDF HTML.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteDetailedFindings.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version/field id and checks patient ownership before reset.
    - returns a controlled JSON success response instead of an unset response.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getOphthaDetailedCaseSheet.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version and checks patient ownership before returning case sheet data.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getOphthaDetailedCaseSheetTemplate.php`
    - now requires PHP session auth and CSRF.
    - validates posted doctor id against the active session.
    - validates doctor/patient/version and checks patient ownership before returning template/version data.
- No `db_functions.php` edits were made for Batch 6.
- Important risk note:
  - Full SQLi closure is `Yes` for `insertDetailedCaseSheet.php`, vitals list/version/graph/save endpoints because they now use prepared endpoint SQL.
  - Full SQLi closure remains `Partial` for upload metadata helpers, print/read case-sheet wrappers, and delete finding wrapper because those still call legacy DB helpers after strict wrapper validation.
- Local verification:
  - `php -l` passed for all 12 Batch 6 PHP endpoints:
    - `insertDetailedCaseSheet.php`
    - `getAllVitalsForGraph.php`
    - `getVitalsVersionList.php`
    - `getVitalsList.php`
    - `saveVitals.php`
    - `uploadOtherMedia.php`
    - `uploadAnteriorPosterior.php`
    - `uploadFindingDrawing.php`
    - `printDetailedFindingsDrawing.php`
    - `deleteDetailedFindings.php`
    - `getOphthaDetailedCaseSheet.php`
    - `getOphthaDetailedCaseSheetTemplate.php`

## 2026-05-09 Rectify Test VS detailed exam follow-up
- Detailed exam crash after Batch 6 was traced to stale/empty browser `localStorage.userDetails["detailedOphthaGlobal"]`, not to `getOphthaDetailedCaseSheet.php` returning malformed case-sheet data.
- Relogin refreshed `fetchDoctorPersonalInfo.php` output and repopulated `detailedOphthaGlobal`; user confirmed relogin solved the issue.
- Current data flow:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getOphthaDetailedCaseSheet.php`
    - returns case-sheet rows in `caseSheet`.
    - currently returns empty arrays for `casesSheetSuggestions` and `casesSheetSuggestionsLocal`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/fetchDoctorPersonalInfo.php`
    - loads detailed exam local/global suggestions during login/session profile refresh.
    - global suggestions come from `DB_Functions::getDetailedExamSuggestions()`.
    - local suggestions come from `DB_Functions::getDetailedExamSuggestionsLocal($doctorId)`.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/init.js`
    - stores `detailedOphthaGlobal` and `detailedOphthaLocal` into localStorage.
- Static/master tables involved:
  - `docboxDetailedSheetAutoSuggestions` for global suggestions.
  - `docboxDetailedSheetAutoSuggestionsLocal` for doctor-specific suggestions.
  - `docboxOphthaCustomFields` for detailed exam field definitions and local suggestion joins.
- User rule reinforced:
  - Never add a fallback without asking first.
  - For detailed exam issues, check static/master tables before changing behavior.

## 2026-05-09 Rectify Test VS Batch 7 follow-up / plan of care
- User requested verifying `saveAdvisedSurgeryNew.php` before starting Batch 7.
- Verification result:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveAdvisedSurgeryNew.php`
    - already has PHP session auth, CSRF validation, doctor/session binding, patient ownership checks, selected visiting doctor/helper ownership checks, prepared writes, and controlled JSON errors.
    - `php -l` passed.
    - no `db_functions.php` update required for this endpoint.
- Batch 7 endpoints patched:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertFollowUp.php`
    - requires PHP session auth and CSRF.
    - validates follow-up row shape and allowed field names.
    - checks doctor/session binding and patient ownership.
    - replaces raw `DB_Functions::insertFollowUp()` with prepared delete/insert/autocomplete update SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertMediaFollowUp.php`
    - requires PHP session auth and CSRF.
    - validates row shape, doctor/session binding, patient ownership, and stored filename/path components.
    - replaces raw `insertNotes(..., mediaFollowUp)` path to remove SQL echo leakage.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/moveFollowup.php`
    - requires PHP session auth and CSRF.
    - validates doctor/patient ids and filenames, checks patient ownership, and preserves the legacy docroot source path via `dirname(__DIR__) . '/server/sajid/files/'`.
    - no fallback was added.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPlanOfCare.php`
    - requires PHP session auth and CSRF.
    - validates doctor/patient/version, checks patient ownership, and uses prepared reads for investigations, advised surgeries, and existing investigation suggestions.
    - preserves the existing hardcoded investigation suggestion list.
    - static/master dependency: `docboxVisitingDoctorDetails` is required for advised surgery visiting doctor names.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveInvestigation.php`
    - requires PHP session auth and CSRF.
    - validates doctor/patient/version/category/name/body part/visiting doctor or helper id.
    - checks patient ownership and selected doctor/helper ownership before prepared duplicate check/insert.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteAdvisedInvestigation.php`
    - requires PHP session auth and CSRF.
    - validates ids and uses prepared delete scoped by doctor, patient, and advised investigation id.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteAdvisedSurgery.php`
    - requires PHP session auth and CSRF.
    - validates ids and uses prepared delete scoped by doctor, patient, and advised surgery id.
    - preserves old behavior of deleting only from `docboxAdvisedSurgeries`; counsellor queue cleanup is not changed.
- No `db_functions.php` edits were made for Batch 7.
- Local verification:
  - `php -l` passed for all Batch 7 endpoints listed above.
  - Live unauthenticated staging POSTs returned `401 SESSION_EXPIRED`.
  - User completed logged-in Batch 7 smoke testing after fixes for parsed Plan of Care JSON, debug-disabled save reload, and skipped empty media follow-up saves.

## 2026-05-09 Rectify Test VS Batch 8A patient history
- User completed Batch 7 testing and requested the next batch.
- Batch 8A covers the Patient History section:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientHistoryNew.php`
    - now requires PHP session auth and CSRF.
    - validates doctor/patient/version ids and checks posted doctor id against the active session.
    - verifies patient ownership before returning any history rows.
    - uses prepared endpoint SQL for all history reads.
    - preserves legacy behavior: current treatment is filtered by version; allergies, medical, birth, surgical, nutritional, family, immunisation, and occular history are filtered by doctor/patient.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveCurrentTreatment.php`
    - now requires PHP session auth and CSRF.
    - validates ids/text/comment/helper name, checks patient ownership, and writes current treatment with prepared SQL.
    - updates `docboxHistoryAutocompleteHelper` with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteCurrentTreatment.php`
    - now requires PHP session auth and CSRF.
    - validates ids/current treatment, checks patient ownership, and deletes with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveBirthHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/history text/period/comment/helper name, checks patient ownership, preserves the legacy `Noted On d-m-Y` comment suffix, inserts with prepared SQL, and updates autocomplete with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteBirthHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/birth history, checks patient ownership, and deletes with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveMedicalHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/history text/period/comment/helper name, checks patient ownership, preserves the legacy `Noted On d-m-Y` comment suffix, inserts with prepared SQL, and updates autocomplete with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedicalHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/medical history, checks patient ownership, and deletes with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveSurgicalHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/surgical history/body part/comment/helper name, checks patient ownership, inserts with prepared SQL, and updates autocomplete with prepared SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteSurgicalHistory.php`
    - now requires PHP session auth and CSRF.
    - validates ids/surgical history/body part, checks patient ownership, and deletes with prepared SQL.
    - avoids `DB_Functions::deletePatientSurgicalHistory()` because the legacy helper echoes raw SQL.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - `getPatientHistory()` and Batch 8A save callbacks now use `docboxPatientInfoParseJson(response)` so JSON object responses do not break old string parsing.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - bumped Rectify Test VS JS version to `40.01`.
- No `db_functions.php` edits were made for Batch 8A.
- Local verification:
  - `php -l` passed for:
    - `getPatientHistoryNew.php`
    - `saveCurrentTreatment.php`
    - `deleteCurrentTreatment.php`
    - `saveBirthHistory.php`
    - `deleteBirthHistory.php`
    - `saveMedicalHistory.php`
    - `deleteMedicalHistory.php`
    - `saveSurgicalHistory.php`
    - `deleteSurgicalHistory.php`
    - `patientInfo_oph_rectify_test_vs.html`
  - `rg` confirmed the patched Batch 8A PHP endpoints no longer contain `checkToken`, `Token invalid`, display-error enabling, legacy raw helper calls, or raw SQL echo paths.
  - Live no-session staging checks returned `401 SESSION_EXPIRED` for all Batch 8A endpoints after re-syncing `saveBirthHistory.php`.
  - User completed logged-in Batch 8A smoke testing: history loaded, and current treatment, birth history, medical history, and surgical history saved and deleted successfully.

## 2026-05-09 Rectify Test VS Batch 8B remaining patient history
- Batch 8B covers the remaining Patient History section:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveNutritionalHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteNutritionalHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveFamilyHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteFamilyHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveImmunisationHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteImmunisationHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveOccularHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteOccularHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveAllergy.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteAllergy.php`
- Batch 8B endpoint changes:
  - now require PHP session auth and CSRF.
  - validate posted doctor id against the active session.
  - validate doctor/patient/version/text fields and check patient ownership before writes/deletes.
  - use prepared endpoint SQL for insert/delete operations and autocomplete helper updates.
  - avoid legacy delete helpers that echo SQL, including `deletePatientFamilyHistory()`.
  - preserve existing table/column spellings, including `OccularHistory`.
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - Batch 8B save callbacks now use `docboxPatientInfoParseJson(response)` so object JSON responses do not break old string parsing.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - bumped Rectify Test VS JS version to `40.02`.
- No `db_functions.php` edits were made for Batch 8B.
- Local verification:
  - `php -l` passed for all 10 Batch 8B PHP endpoints and `patientInfo_oph_rectify_test_vs.html`.
  - `rg` confirmed the patched Batch 8B PHP endpoints no longer contain `checkToken`, `Token invalid`, display-error enabling, legacy raw helper calls, or raw SQL echo paths.
  - Live no-session staging checks returned `401 SESSION_EXPIRED` for all Batch 8B endpoints after sync.
  - User completed logged-in Batch 8B smoke testing: remaining patient history records saved and deleted successfully.

## 2026-05-09 Rectify Test VS Batch 9 procedures, pharmacy, billing, and delivery
- User asked not to divide this batch; patched the full batch together.
- Batch 9 covers:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientProceduresDetail.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientProceduresDetailPharmacy.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getProcedureDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getProcedureDetailsForDoctor.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePatientProcedures.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePatientPharmacyProcedures.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deletePatientProcedure.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deletePatientProcedurePharmacy.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePatientPaymentDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateShopDeliveryStatus.php`
- Batch 9 endpoint changes:
  - now require PHP session auth and CSRF.
  - validate posted doctor id against active session doctor or mapped center.
  - validate doctor/patient/procedure/receipt/date/quantity/payment fields with allow-lists or numeric checks.
  - check patient ownership before procedure/payment reads and writes.
  - use prepared endpoint SQL for procedure list, patient procedure/pharmacy reads, ownership, duplicate, stock, and existence checks.
  - preserve legacy helper behavior for procedure save/delete, stock updates, payment saving, and shop delivery status; no `db_functions.php` edits were made.
  - preserve legacy response contracts including pharmacy delete `status: bilkul`.
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
    - touched procedure/pharmacy/payment callbacks now use `docboxPatientInfoParseJson(response)` where needed.
    - removed noisy console logs in touched billing/procedure paths.
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
    - bumped Rectify Test VS JS version to `40.03`.
- Local verification:
  - `php -l` passed for all 10 Batch 9 PHP endpoints and `patientInfo_oph_rectify_test_vs.html`.
  - `rg` confirmed patched Batch 9 PHP endpoints no longer contain `checkToken`, `Token invalid`, or display-error enabling.
  - After sync, live no-session staging POST checks returned `401 SESSION_EXPIRED` for all 10 Batch 9 PHP endpoints.
  - After sync, live `patientInfo_oph_rectify_test_vs.html` loads `js/patientInfo_oph_rectify_test_vs.js?v=40.03`.
  - Node is not installed in this workspace, so JS syntax parser verification could not be run here.
  - User completed logged-in UI smoke testing after sync; adding bill item and payment save flow worked after receipt/payment validation fixes.

## 2026-05-09 Rectify Test VS Batch 10 inventory master and surgery upload
- Batch 10 covers:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePharmItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveProcedures.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/uploadSurgeryAttachment.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
- Scope notes:
  - `getVitalsList.php` was inspected as a nearby call but was already secured in Batch 6, so it was not repatched here.
  - No `db_functions.php` edits were made.
- Endpoint changes:
  - `savePharmItem.php` now requires PHP session auth and CSRF, validates posted doctor id against the active session doctor or mapped center, validates item/date/numeric/text fields, and uses prepared SQL directly for pharmacy stock insert/update and pharmacy log writes.
  - `saveProcedures.php` now requires PHP session auth and CSRF, validates procedure ids/name/cost/type/attached doctors, validates posted doctor id against the active session doctor or mapped center, and uses prepared SQL directly for procedure and visiting-doctor mapping inserts.
  - `uploadSurgeryAttachment.php` now requires PHP session auth and CSRF, validates doctor/patient/version/tag, verifies patient ownership, restricts uploads to JPG/PNG/PDF up to 5 MB, sanitizes/generates the stored filename, writes under the expected `sajid/{doctor}/{patient}` directory, and uses prepared SQL for `docboxSurgeryUploads` and `documents` rows.
- Frontend changes:
  - upload FormData AJAX explicitly sets `contentType: false`, `processData: false`, and `cache: false`.
  - removed noisy console logs from touched inventory/upload controls.
  - bumped Rectify Test VS JS version to `40.04`.
- Local verification:
  - `php -l` passed for all three Batch 10 PHP endpoints and `patientInfo_oph_rectify_test_vs.html`.
  - Live no-session staging POST checks returned `401 SESSION_EXPIRED` for all three Batch 10 PHP endpoints.
  - User completed logged-in UI smoke testing after sync; Add Inventory particular, Add Inventory medicine, and surgery attachment upload flows passed.

## 2026-05-09 Rectify Test VS combined Batch 11+12 surgery/IPD read and write
- User asked to start combined Batch 11 and 12, covering surgery/IPD read/setup plus write APIs together.
- Files were opened in VS Code before patching, per current process rule.
- Shared helper update:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/api_auth.php`
    - added reusable endpoint helper functions for invalid/server JSON errors, POST value normalization, id/text/decimal validation, prepared statement binding/execution/fetching, patient ownership checks, and row payload validation.
    - `php -l` passed.
- Patched read/setup endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIOLData.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/fetchOTSchedulePatient.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSurgeryNotesTemplate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPreOpMedicine.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIPDDoctorExaminationFields.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIPDNurseExaminationFields.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPreOpMedicineSurgery.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientTPADetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientInsuranceDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPreOperativeVisitDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getWardCheckList.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPainChartSurgery.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSurgicalCheckList.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAnesthesiaPlan.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPreOpSystemicExamination.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSurgeryDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllOtConsumables.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSurgeryUploads.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPatientClaimDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getKeratometryIOLMap.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getConsentTextForSurgery.php` was already secured and rechecked as part of this batch.
- Patched write endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveIPDDoctorExam.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveNurseExamination.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePreOpMedicineSurgery.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deletePreOpMedicineSurgery.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveInsuranceDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveOtConsumableItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteOtConsumable.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertWardCheckList.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertSurgicalCheckList1.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertIntraOpAnesthesiaPlan.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertSurgeryBasicDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertPreOpSystemicExamination.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertKeratometryConsumeIOL.php`
- Security changes:
  - all patched endpoints require PHP session auth and CSRF.
  - all patched endpoints validate posted doctor id against active session doctor or mapped center.
  - patient-bound endpoints verify patient ownership before returning or writing patient/surgery/IPD data.
  - legacy `checkToken()` gates and `if (1)` token bypasses were removed from the patched batch.
  - high-risk write paths now use prepared SQL directly in endpoints for IPD doctor/nurse exams, pre-op medicine add/delete, ward/surgical/anesthesia/surgery/systemic/keratometry row writes, OT consumable stock/mapping writes, TPA/insurance save, pre-op visit mapping, and IOL surgery mapping.
  - read endpoints still call some constrained legacy DB helper reads after strict id validation; deeper DB-function read cleanup can be done later if needed, with user consent for `db_functions.php`.
- No `db_functions.php` edits were made.
- Local verification:
  - `php -l` passed for `api_auth.php` and every patched Batch 11+12 PHP endpoint.
  - `rg` confirmed the patched Batch 11+12 PHP endpoints no longer contain active `checkToken()`, `Token invalid`, or `if( 1)` token bypass paths.
- Pending user sync/testing:
  - open a surgery from Rectify Test VS and confirm the Surgery Notes/IPD modal loads.
  - test IOL search, pre-op medicine add/delete, doctor exam save, nurse exam save.
  - test ward checklist, surgical checklist sections, anesthesia plan, basic/cataract/surgery notes, systemic exam, keratometry/IOL mapping.
  - test OT consumable add/remove and insurance/claim save.

## 2026-05-09 Rectify Test VS combined Batch 13+14 refraction, orthoptic, and billing print
- User asked to start the next combined batch after confirming Batch 11+12 vitals/checklist flows.
- Files were opened in VS Code before patching, per current process rule.
- Patched data read/write endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getRetinoscopy.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getOrthopticEvaluation.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertRetinoscopyTable.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertSpecPres.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertOrthopticEvaluationSheet.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/recalculatePayment.php`
- Patched print/document endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/retinoscopyReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/breakUpBillPrint.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/finalBillPrint.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertDocuments.php`
- Security changes:
  - all patched endpoints require PHP session auth and CSRF.
  - all patched endpoints validate posted doctor id against active session doctor or mapped center.
  - patient-bound endpoints verify patient ownership before returning data, saving data, or generating PDF files.
  - breakup bill print validates receipt ownership before generating the PDF.
  - read endpoints for retinoscopy/orthoptic now use prepared SELECTs directly in endpoint.
  - write endpoints for refraction, spectacle prescription, orthoptic evaluation, document records, and payment recalculation now use prepared SQL directly in endpoint.
  - legacy `checkToken()` gates, active `if (1)` token bypasses, `insertSpecPrescription()` SQL echo path, and `rectifyPaymentDetails()` raw SQL path were removed from this endpoint batch.
  - report/PDF endpoints still use existing legacy report-builder queries after the new auth/ownership gate; deeper report SQL cleanup can be done later if needed with user consent for DB helper work.
- No `db_functions.php` edits were made.
- Local verification:
  - `php -l` passed for all ten patched Batch 13+14 PHP endpoints.
  - `rg` confirmed patched batch endpoints no longer contain active legacy token checks or token-bypass paths, except a commented historical line in `retinoscopyReport.php`.
- Pending user sync/testing:
  - Retinoscopy modal: open and confirm saved refraction data loads.
  - Save retinoscopy table / spectacle prescription: save and reopen to confirm persistence.
  - Orthoptic evaluation: save, reopen, and print locally.
  - Print retinoscopy report: confirm PDF file opens and document row is inserted.
  - Breakup bill print and final bill print: confirm PDF generation/opening and document row insertion.
  - Recalculate payment: confirm totals update without console errors.
- Follow-up frontend fix after sync:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Fixed Add Receipt crash where global `p` could be overwritten by OT schedule data before billing tried to read `p[1].PhoneNumber`.
  - Patient profile row is now cached in `window.docboxCurrentPatientProfile`, and billing header fields use safe defaults when optional patient fields are blank.
  - Rectify Test VS JS version bumped from `40.08` to `40.09`.

## 2026-05-10 Discharge Card Oph remaining API hardening
- User asked to complete the remaining APIs for `discharge_card_oph` together.
- Files were opened in VS Code before patching, per current process rule.
- Shared helper:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/discharge_api_helpers.php`
    - Added reusable discharge helpers for POST/session guard, raw text/id validation, patient context validation, DB connection, and surgery ownership validation.
    - Later updated to accept both `patientId` and legacy `PatientId` because `getDischargeVersion.php` was returning `400` from a casing mismatch in the caller payload.
- Patched remaining read/template/mapping endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getSpecialityDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIPDDatesForBill.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getDischargeTemplate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getDischargeVersion.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/fetchOTSchedulePatient.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getMappedSurgeryFromDischargeCard.php`
- Patched remaining write/PDF endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertMedications.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedication.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/mapDischargecardWithSurgery.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveDischargeTemplate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveDischargeVersion.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/dischargeCardPDF.php`
  - Already-guarded supporting endpoints were rechecked and the frontend callers were fixed: `/Users/apple/Documents/docbox_staging/sajid/pdfgeneratortest.php`, `/Users/apple/Documents/docbox_staging/sajid/saveActivityLog.php`, `/Users/apple/Documents/docbox_staging/sajid/getPatientProfileWeb.php`.
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/prescription.js`
  - `init.js` now loads before prescription/discharge scripts on the discharge page.
  - JS cache versions are `js/init.js?v=3.5`, `js/prescription.js?v=1.2`, and `discharge_card_oph.js?v=3.27`.
  - Touched POST calls now send explicit `csrfToken` where needed and callbacks handle either parsed JSON objects or JSON strings.
  - `getAllVersions()` now uses the shared `dischargePatientPayload()` instead of the older mixed-case payload.
- Security changes:
  - remaining discharge-card endpoints now require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - patient-scoped endpoints verify patient ownership before reading, writing, mapping surgery, or generating PDF.
  - `insertMedications.php` no longer calls the legacy raw `DB_Functions::insertMedications()` path; it validates the payload and uses prepared SQL for medication insert, temporary medication cleanup, and autocomplete updates.
  - `getIPDDatesForBill.php` no longer calls the raw `getAutoIPDDatesForBill()` helper; it uses prepared SQL directly.
  - discharge template/version/mapping endpoints use prepared SQL directly.
  - `dischargeCardPDF.php` validates patient context and bounds text/id fields before legacy PDF rendering.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Discharge Card Oph remaining read/template/mapping, write/PDF, and frontend tracker rows.
- Local verification:
  - `php -l` passed for all touched PHP endpoints and helpers.
  - `node` is not installed locally, so real JS syntax checks could not be run; changed JS blocks were inspected and PHP lint over JS files reported no PHP-token syntax errors.
- User sync/testing:
  - User synced the discharge-card changes.
  - `getDischargeVersion.php` initially returned `400`; fixed by accepting legacy `PatientId` casing and normalizing the caller payload.
  - User tested the fix successfully.

## 2026-05-10 IPD page API hardening
- User moved the page-wise security work to `IPD.php`.
- Files were opened in VS Code before patching, per current process rule.
- Shared helper:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/ipd_api_helpers.php`
    - Added reusable IPD guards for POST/session/CSRF validation, DB connection, doctor binding, date/id validation, bed ownership checks, and HTML escaping.
- Patched IPD endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getModuleSubcription.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/ipdDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllPatientsWebListMain.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/dischargePatientFromBed.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertPatientToBed.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllBedStatus.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getBedHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getBedDetails.php`
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/IPD.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/IPDall.js`
  - `IPD.php` now loads `js/init.js?v=3.5` and `js/IPDall.js?v=1.3`.
  - Touched IPD POST calls send explicit `csrfToken`.
  - Patched IPD callbacks now parse either JSON strings or already parsed JSON objects.
  - Removed active debug `console.log` calls from touched IPD paths.
- Security changes:
  - patched IPD endpoints require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - patient-scoped endpoints verify patient ownership before patient list, bed assignment, discharge, and bed details/history operations.
  - bed-scoped endpoints verify the bed belongs to the validated doctor.
  - newly patched IPD endpoints use prepared SQL directly inside the endpoint and bypass raw legacy DB helper paths.
  - `ipdDetails.php` no longer uses undefined date variables and now escapes server-rendered summary HTML values.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added IPD bed/admission and patient/subscription/summary tracker rows.
- Local verification:
  - `php -l` passed for the IPD helper, all patched PHP endpoints, and `IPD.php`.
  - `node` is not installed locally, so a real JS syntax check for `js/IPDall.js` could not be run.
- Pending user sync/testing:
  - Open `IPD.php` after syncing and confirm bed grid loads.
  - Print IPD summary and confirm the modal/table opens.
  - Open assign-bed patient list and confirm patients load.
  - Assign a patient to a bed, reopen bed details, and confirm the patient appears.
  - Open bed history and confirm it loads.
  - Discharge a patient from a bed and confirm the bed frees and procedure charge path still works.

## 2026-05-10 Profile page Batch 1 core settings hardening
- User moved the page-wise security work to `profile.php`.
- Batch 1 scope selected:
  - core hospital/doctor settings save
  - home-page/misc preferences save
  - visiting doctor add/delete
  - frontend CSRF/cache-bust for touched `profile.js` calls
- Files were opened in VS Code before patching, per current process rule.
- Shared helper:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_api_helpers.php`
    - Added reusable Profile helpers for POST/session/CSRF validation, DB connection, doctor binding, text/id/email/phone/margin/gender validation, payload-row parsing, and visiting-doctor reload.
- Patched endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateHospitalDetail.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateMiscPrefs.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateDoctor.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertVisitingDoctor.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteVisitingDoctor.php`
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile.js`
  - `profile.php` now loads `js/init.js?v=3.5` and `js/profile.js?v=2.15`.
  - Touched Profile POST calls send explicit `csrfToken`.
  - Touched callbacks now parse either JSON strings or parsed JSON objects.
  - Active debug logs were removed from touched Profile settings paths.
- Security changes:
  - patched Profile endpoints require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - core doctor/hospital/preference updates use prepared SQL directly and bypass raw legacy DB helper paths.
  - `insertVisitingDoctor.php` no longer uses the legacy `if(1)` bypass.
  - `deleteVisitingDoctor.php` was missing locally; added as a guarded endpoint that verifies the visiting doctor belongs to the validated doctor before deletion.
  - `updateDoctor.php` now updates the existing active `personalinfo` row instead of deleting/reinserting the full row.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Profile Page Batch 1 core doctor/hospital settings and visiting-doctor settings tracker rows.
- Local verification:
  - `php -l` passed for the Profile helper, patched PHP endpoints, `profile.php`, and `js/profile.js` as a PHP-token sanity check.
  - `node` is not installed locally, so a real JS syntax check for `js/profile.js` could not be run.
- Pending user sync/testing:
  - Open `profile.php` and confirm the page loads without CSRF errors.
  - Save hospital/doctor profile details and confirm “Changes Saved” then reload.
  - Confirm updated hospital/doctor values persist after reload.
  - Add a visiting doctor and confirm it appears in the visiting-doctor list/localStorage.
  - Delete a visiting doctor from the UI path that calls `deleteVisitingDoctor()` and confirm the list refreshes.

## 2026-05-10 Profile page Batch 2 settings hardening
- Batch 2 scope selected:
  - appointment slot settings
  - discharge-card field mapping settings
  - visiting-doctor procedure commission settings
  - discharge instruction settings
- Files were opened in VS Code before patching, per current process rule.
- Shared helper update:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_api_helpers.php`
    - Added scoped doctor-id helpers for visiting-doctor style ids like `2-1`.
    - Added visiting-doctor ownership validation.
    - Added appointment slot-string and language-code validators.
- Patched endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAppointmentSettings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveAppointmentSettings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllDischargeCardFields.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveDischargeCardFieldSetting.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getdoctorProcedureCommissionSettings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savedoctorProcedureCommissionSettings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getDischargeInstructionsHospital.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveDischargeInstructionsHospital.php`
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/appointmentHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/commissionSettingHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/dischargeCardSettingHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/dischargeInstructionsSettings.js`
  - `profile.php` now loads `appointmentHelper.js?v=1.1`, `commissionSettingHelper.js?v=1.1`, `dischargeCardSettingHelper.js?v=1.2`, and `dischargeInstructionsSettings.js?v=1.1`.
  - Touched Profile settings POST calls send explicit `csrfToken`.
  - Touched callbacks now parse either JSON strings or parsed JSON objects.
  - Active debug logs were removed from touched appointment, commission, and discharge-card settings paths.
- Security changes:
  - patched Profile Batch 2 endpoints require PHP session auth and CSRF.
  - doctor ids and visiting-doctor ids are bound to the active session doctor or mapped center.
  - appointment slot settings validate the 144-character binary slot string.
  - discharge-card field settings validate field ids and sequence values before prepared delete/insert.
  - procedure commission settings validate amount/percentage/procedure id and verify the procedure mapping before prepared update/insert.
  - discharge instruction settings validate language/text/sort/active values and remove debug/fatal error leakage.
  - All patched Batch 2 endpoints use prepared SQL directly in the endpoint and bypass the legacy raw DB helper paths.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Profile Page Batch 2 tracker rows.
- Local verification:
  - `php -l` passed for the Profile helper, all patched PHP endpoints, `profile.php`, and touched JS files as a PHP-token sanity check.
  - CLI no-session POST probes returned `SESSION_EXPIRED` for all eight patched endpoints.
  - `node` is not installed locally, so a real JS syntax check could not be run.
- Pending user sync/testing:
  - Open `profile.php` after syncing and confirm no CSRF/session errors on load.
  - Appointment settings: select a visiting doctor, change a few slot checkboxes, save, reload, and confirm the slot state persists.
  - Commission settings: select a visiting doctor, confirm procedures load, add a commission row, and confirm it appears after refresh.
  - Discharge-card fields: select a visiting doctor, move fields between pool/selected, save, reload, and confirm order/selection persists.
  - Discharge instructions: add/edit/delete an instruction and confirm the list persists after refresh.

## 2026-05-10 Profile page Batch 3 staff and doctor management hardening
- Batch 3 scope selected:
  - staff list/create/update
  - staff activity log caller CSRF
  - visiting-doctor profile list/create/update
  - attendance-machine employee link used by configured hospitals
- Files were opened in VS Code before patching, per current process rule.
- Shared helper update:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_api_helpers.php`
    - `docbox_profile_require_post_session()` now accepts optional required helper types.
    - Added username, staff phone, helper-rights, boolean, money, and next-helper-id validators/helpers.
- Patched endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllStaffDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertStaff.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateStaff.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllVisitingDoctorsProfile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertVisitingDoctorProfile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateVisitingDoctorProfile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveEmployeeToMachine.php`
  - Existing **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveHelperActivityLog.php` was already guarded; the caller now sends CSRF.
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/staffManagementHelper.js`
  - `profile.php` now loads `staffManagementHelper.js?v=1.20`.
  - Touched staff/doctor management POST calls send explicit `csrfToken`.
  - Touched callbacks now parse either JSON strings or parsed JSON objects.
  - Active debug logs were removed from touched staff/doctor management paths.
  - Blank helper type display now maps to Super Admin Access in this UI.
- Security changes:
  - patched staff/doctor management endpoints require PHP session auth and CSRF.
  - staff/doctor management endpoints require Admin/Super Admin helper type (`6` or `a`).
  - posted doctor ids and visiting-doctor ids are bound to the active session doctor or mapped center.
  - staff update verifies the staff helper belongs to the validated doctor and is not a visiting-doctor helper.
  - visiting-doctor update verifies the visiting doctor belongs to the validated doctor.
  - staff, visiting-doctor, and attendance-machine writes now use prepared SQL directly in the endpoint and bypass legacy raw DB helper paths.
  - `saveEmployeeToMachine.php` now only accepts configured doctors and no longer echoes raw terminal-command SQL.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Profile Page Batch 3 tracker rows.
- Local verification:
  - `php -l` passed for the Profile helper, all patched PHP endpoints, `profile.php`, and `js/staffManagementHelper.js` as a PHP-token sanity check.
  - CLI no-session POST probes returned `SESSION_EXPIRED` for the patched endpoints.
  - `node` is not installed locally, so a real JS syntax check could not be run.
- Pending user sync/testing:
  - Open `profile.php`, go to User Management, confirm staff list loads.
  - Add a temporary staff user, confirm it appears.
  - Edit that staff user, confirm changes persist after reload.
  - Deactivate that staff user, confirm it disappears from active list.
  - Go to Doctor Management, confirm visiting doctors load.
  - Add a temporary visiting doctor, confirm it appears.
  - Edit/deactivate that visiting doctor, confirm changes persist after reload.
  - If testing hospital `1245`, confirm the attendance-machine prompt/path still returns success for a new staff user.

## 2026-05-10 Profile page Batch 4 procedure/package and IPD ward hardening
- Batch 4 scope selected:
  - profile procedure/particular list and search
  - procedure/package create, edit, and delete
  - IPD ward list, create, edit, and delete
- Files were opened in VS Code before patching, per current process rule.
- Shared helper update:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_api_helpers.php`
    - Added profile label, count, and id-list validators used by procedure/package/ward settings.
- Patched endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getProcedureDetailsProfile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getProcedureDetailsProfileSearch.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveProceduresPackage.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/editProcedure.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteProcedure.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveWards.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIpdDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteWard.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/editWards.php`
  - Existing **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getProcedureDetails.php` and `/Users/apple/Documents/docbox_staging/sajid/saveProcedures.php` were already guarded and included in this batch review.
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile_procedure_helper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profileIPDHelper.js`
  - `profile.php` now loads `profile_procedure_helper.js?v=1.15` and `profileIPDHelper.js?v=1.1`.
  - Touched procedure/IPD list parsers now accept either JSON strings or parsed JSON objects.
  - IPD ward list renderer now tolerates an empty `{status:"no"}` response without throwing.
- Security changes:
  - patched Profile Batch 4 endpoints require PHP session auth and CSRF.
  - posted doctor ids are bound to the active session doctor or mapped center.
  - procedure endpoints validate procedure ids, names, cost, type ids, visiting-doctor id lists, and package mapping id lists.
  - ward endpoints validate ward names, cost, and bed counts.
  - procedure and ward reads/writes/deletes use prepared SQL directly in the endpoint and bypass the legacy raw DB helper paths.
  - old raw SQL echoes from procedure/ward delete paths and bed-count echo from ward insert path are removed from these endpoints.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Profile Page Batch 4 tracker rows.
- Local verification:
  - `php -l` passed for the Profile helper, all patched PHP endpoints, `profile.php`, and already-guarded `saveProcedures.php`.
  - Static grep on patched endpoint set found no remaining `checkToken`, `mysqli_query(`, `Token invalid`, or SQL echo usage.
  - `node` is not installed locally, so a real JS syntax check could not be run.
- Staging verification:
  - No-session staging probes returned `SESSION_EXPIRED` for the patched Batch 4 endpoints.
  - User synced and verified Particulars and IPD/Wards logged-in smoke tests.

## 2026-05-10 Profile page Batch 5 IOL inventory and report hardening
- Batch 5 scope selected from `profilePharmacyHelper.js`:
  - IOL report HTML
  - IOL search/list
  - IOL add
  - IOL delete
- Files were opened in VS Code before patching, per current process rule.
- Patched endpoints:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getIOLData.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/insertIOLData.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteIOLData.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/IOLReport.php`
- Frontend changes:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - `profile.php` now loads `profilePharmacyHelper.js?v=1.34`.
  - IOL search parser now accepts either JSON strings or parsed JSON objects.
- Security changes:
  - patched IOL endpoints require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - IOL search/list, add, delete, and report queries use prepared SQL directly in the endpoint and bypass the legacy raw DB helper paths.
  - `insertIOLData.php` and `deleteIOLData.php` no longer have legacy token/`if(1)` bypasses.
  - `IOLReport.php` now escapes hospital and IOL table fields before HTML output.
- No `db_functions.php` edits were made.
- Tracking:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - Added Profile Page Batch 5 tracker rows.
- Local verification:
  - `php -l` passed for all patched IOL PHP endpoints and `profile.php`.
  - Static grep on patched endpoint set found no remaining `checkToken`, `if(1)`, `mysqli_query(`, `Token invalid`, or SQL echo usage.
- Staging verification:
  - No-session staging probes returned `SESSION_EXPIRED` for the patched Batch 5 endpoints.
  - User synced and verified IOL report/search/add/delete logged-in smoke tests.

## 2026-05-10 Profile page Batch 6 pharmacy inventory hardening
- Batch 6 scope selected from `profilePharmacyHelper.js` and `profileHelper.js`:
  - pharmacy item add/list/search/filter
  - pharmacy stock add/remove
  - pharmacy item edit/delete
  - pharmacy stock history
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_pharmacy_api_helpers.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePharmItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPharmDetailsPagination.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPharmDetailSearch.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addPharmStock.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/editPharm.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deletePharmItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPharmHistory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
- Frontend changes:
  - `profile.php` now loads `profilePharmacyHelper.js?v=1.35` and `profileHelper.js?v=1.17`.
  - Pharmacy list/search/stock callbacks now tolerate parsed JSON objects as well as JSON strings.
- Security changes:
  - patched Profile Batch 6 endpoints require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - pharmacy item/search/date/quantity inputs are validated before SQL.
  - pharmacy list/search no longer includes `newPharmList.php` or `newPharmListSearch.php`.
  - stock/list/search/edit/delete/history operations use prepared SQL directly in endpoints.
  - no `db_functions.php` edit was made.
- Tracker:
  - Added Profile Page Batch 6 tracker row in `secured_api_tracking.md`.
- Local verification:
  - `php -l` passed for `profile_pharmacy_api_helpers.php`, all Batch 6 PHP endpoints, already-guarded `savePharmItem.php`, and `profile.php`.
  - `rg` found no remaining `checkToken`, `mysqli_query`, `newPharmList`, or pharmacy legacy DB helper references in the Batch 6 endpoint set.
- Staging verification:
  - After user synced, no-session staging probes returned HTTP `401` with `SESSION_EXPIRED` for all seven Batch 6 endpoints:
    - `savePharmItem.php`
    - `getPharmDetailsPagination.php`
    - `getPharmDetailSearch.php`
    - `addPharmStock.php`
    - `editPharm.php`
    - `deletePharmItem.php`
    - `getPharmHistory.php`
- Add-item follow-up fix:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePharmItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - Blank optional purchase-cost/GST fields are normalized to `0` server-side, and pharmacy decimals now allow up to four decimal places.
  - Add-item frontend now stops before `saveProcedure()` if `savePharmItem.php` returns a non-yes status.
  - `profile.php` cache-bumped to `profilePharmacyHelper.js?v=1.36`.
  - `php -l` passed for `savePharmItem.php` and `profile.php`.
- Add-item no-reload follow-up:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - Add pharmacy item now clears the add-item panel and refreshes the pharmacy list with `viewAllPharmItem(1)` after the linked procedure save completes, instead of reloading the whole page.
  - `profile.php` cache-bumped to `profilePharmacyHelper.js?v=1.37`.
  - `php -l profile.php` passed; `rg` found no active `window.location.reload()` in `profilePharmacyHelper.js`.
- Linked procedure save follow-up:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveProcedures.php`
  - Replaced the remaining legacy include-based version with the same profile helper/session/CSRF/doctor-binding pattern used by the tested Profile procedure endpoints.
  - Procedure save now updates an existing `DoctorId` + `ProcedureId` row instead of failing on an already-created id.
  - Removed direct dependency on `docboxProcedureDetails.GST` from this endpoint so pharmacy linked-procedure saves only write core procedure columns: `DoctorId`, `ProcedureId`, `ProcedureName`, `ProcedureCost`, and `ProcedureTypeId`.
  - No `db_functions.php` edit was made.
  - `php -l saveProcedures.php` and `php -l profile.php` passed.
- Staging test plan after sync:
  - Open `profile.php`, go to pharmacy inventory.
  - Confirm pharmacy list loads and pagination works.
  - Search by item/company/batch and test low/empty/expiring/expired filters.
  - Add a new pharmacy item.
  - Add stock and remove stock without making stock negative.
  - Edit a pharmacy item and confirm the corresponding procedure row still displays.
  - Delete a pharmacy item and confirm it disappears from active pharmacy list.
  - Open pharmacy history for a date range and confirm logs appear.
- Final staging status:
  - User synced and verified the logged-in Profile Batch 6 pharmacy inventory flows.
  - Pharmacy item add works without full-page reload, linked procedure save works, and the inventory workflows tested successfully.

## 2026-05-10 Profile page Batch 7 shop and pharmacy report hardening
- Batch 7 scope:
  - shop item list/edit
  - supplier purchase report and PDF generation
  - pharmacy stock report
  - shop stock report
  - OT stock summary report
  - procedure summary reuse from already-secured Financial Summary endpoint
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_pharmacy_api_helpers.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getShopDetailsPagination.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/editShopItem.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPharmSupplierReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/supplierReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/newPharmReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/shopReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/OtStockReport.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
- Security changes:
  - shop list/edit/supplier report endpoints now require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - shop item/date/supplier/report inputs are validated before SQL.
  - shop list/edit/supplier report use prepared endpoint/helper SQL instead of legacy token/raw helper paths.
  - `newPharmReport.php`, `shopReport.php`, and `OtStockReport.php` now use the secured finance guard and controlled errors.
  - supplier PDF generation uses modern Composer mPDF autoload instead of legacy `mpdf60` include.
  - report HTML fields touched in this batch are escaped before output.
  - no `db_functions.php` edit was made.
- Frontend changes:
  - supplier report, procedure summary, pharmacy history, and shop list callbacks now accept parsed JSON object responses.
  - noisy debug logs were removed from touched Profile shop/report paths.
  - `profile.php` cache-bumped to `profilePharmacyHelper.js?v=1.38` and `profileHelper.js?v=1.18`.
- Tracker:
  - Added Profile Page Batch 7 tracker row in `secured_api_tracking.md`.
- Local verification:
  - `php -l` passed for `profile_pharmacy_api_helpers.php`, `getShopDetailsPagination.php`, `editShopItem.php`, `getPharmSupplierReport.php`, `supplierReport.php`, `newPharmReport.php`, `shopReport.php`, `OtStockReport.php`, and `profile.php`.
  - Static scan on the Batch 7 endpoint set found no remaining `checkToken`, `Token invalid`, `mysqli_query`, SQL echo, `print_r`, or undefined `$diagnosisJson` paths.
- Staging test plan after sync:
  - Open `profile.php`, go to pharmacy/shop inventory.
  - Click `Get All Shop Items`; confirm shop list loads.
  - Edit one shop item; confirm save succeeds and the linked procedure row remains usable.
  - Select a supplier and confirm supplier summary table loads.
  - Click supplier `Print Report`; confirm a PDF opens under the validated hospital directory.
  - Run `Medicines Summary`, `Pharmacy Stock Report`, `Shop Stock Report`, and `OT Stock Summary`; confirm tables render and DataTables export buttons initialize.
- Staging verification:
  - No-session probes on the patched Batch 7 endpoints returned HTTP `401` with `SESSION_EXPIRED`.
  - User synced and verified the logged-in shop item, supplier report, medicines summary, pharmacy stock, shop stock, and OT stock report smoke tests.

## 2026-05-10 Profile page Batch 8 visit template settings hardening
- Batch 8 scope:
  - level-3 single-field visit templates for Chief Complaint, Examination Findings, and Advice
  - level-2 combined visit templates list/detail/save/delete
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_template_api_helpers.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addTemplatesLvl3.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/updateTemplates.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteTemplates.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteTemplatesLvl2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getTemplatesLvl2Details.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllTemplatesLvl2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addTemplatesLvl2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
- Security changes:
  - patched template endpoints require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - template column is restricted to known visit-template columns.
  - template names/text/category and selected delete values are validated before SQL.
  - level-3 add/update/delete and level-2 list/detail/save/delete use prepared SQL directly in endpoints.
  - removed legacy `checkToken`, `display_errors`, raw DB helper paths, query echoes, and raw `IN (...)` delete SQL from these endpoint paths.
  - no `db_functions.php` edit was made.
- Frontend changes:
  - level-2 template callbacks now accept parsed JSON object responses as well as strings.
  - touched level-2 template list and details rendering escapes dynamic values.
  - `profile.php` cache-bumped to `profile_template_helper.js?v=1.5`.
- Tracker:
  - Added Profile Page Batch 8 tracker row in `secured_api_tracking.md`.
- Local verification:
  - `php -l` passed for `profile_template_api_helpers.php`, all Batch 8 PHP endpoints, and `profile.php`.
  - Static scan on the Batch 8 endpoint set found no remaining `checkToken`, `Token invalid`, `mysqli_query`, `display_errors`, SQL echo, or `print_r` paths.
- Staging test plan after sync:
  - Open `profile.php` and confirm `profile_template_helper.js?v=1.5` loads.
  - Open the visit template settings area.
  - Add one Chief Complaint / Examination Findings / Advice template and confirm it appears.
  - Edit one single-field template and confirm the updated value appears.
  - Delete one single-field template and confirm it is removed.
  - Add a level-2 visit template with complaint, examination, advice, and category.
  - Click the saved level-2 template and confirm preview details load.
  - Delete the level-2 template and confirm it disappears.

## 2026-05-10 Profile page Batch 9 profile template / medicine settings hardening
- Batch 9 scope:
  - diagnosis medicine level-2 templates.
  - detailed examination local suggestions.
  - medicine category settings.
  - medicine group settings.
  - medicine group mapping settings.
  - pre-op medicine settings.
  - obsolete Razorpay profile payment flow removal.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/includes/profile_template_api_helpers.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addDiagnosisMedTemplateLvl2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getAllDiagnosisTemplatesLvl2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/addDetailedExamSuggestions.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getDeytailedExamSuggestionsLocal.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedicineGroupMappings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getMedicineGroupMappings.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedicineGroup.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getMedicineGroups.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deleteMedicineCatagory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getMedicineCatagory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveMedicineGroupMapping.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveMedicineGroupName.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveMedicineCatagory.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPreOpMedicine.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/deletePreOpMedicine.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/savePreOpMedicine.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/subscription.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
- Security changes:
  - all Batch 9 endpoints now require PHP session auth and CSRF.
  - posted doctor id is bound to the active session doctor or mapped center.
  - category/group/template/pre-op medicine ids and text fields are validated before SQL.
  - Batch 9 endpoints use prepared SQL directly in endpoint/helper code.
  - legacy `checkToken`, raw DB helper calls, query echoes, and `display_errors` paths were removed from the patched endpoints.
  - no `db_functions.php` edit was made.
- Razorpay removal:
  - removed the external Razorpay checkout script from `profile.php`.
  - removed active profile-page calls to `paymentCaptureRazorPayWeb.php` and `paymentCaptureRzpPayPerPatient.php`.
  - subscription payment buttons now show a controlled disabled-payment message; activation-code flow remains usable.
- Frontend changes:
  - touched `profile_template_helper.js` callbacks now accept parsed JSON object responses as well as strings.
  - noisy response debug logs were removed from touched profile template paths.
  - `profile.php` cache-bumped to `profile_template_helper.js?v=1.6` and `subscription.js?v=1.5`.
- Tracker:
  - Added Profile Page Batch 9 tracker row in `secured_api_tracking.md`.
- Local verification:
  - `php -l` passed for `profile_template_api_helpers.php`, all Batch 9 PHP endpoints, and `profile.php`.
  - Static scan on the Batch 9 endpoint set found no remaining `checkToken`, `Token invalid`, `mysqli_query`, `display_errors`, SQL echo, or raw query helper usage.
  - Static scan of `profile.php` and `subscription.js` found no active Razorpay checkout/capture references.
  - CLI no-session POST probes against all Batch 9 endpoints returned `SESSION_EXPIRED`.
- Staging test plan after sync:
  - Open `profile.php` and confirm `profile_template_helper.js?v=1.6` and `subscription.js?v=1.5` load.
  - In template settings, add/list/delete a diagnosis medicine level-2 template.
  - Add and reload detailed exam local suggestions.
  - Add/list/delete a medicine category.
  - Add/list/delete a medicine group.
  - Add/list/delete a medicine group mapping.
  - Add/list/delete a pre-op medicine entry.
  - Confirm old Razorpay payment buttons no longer open Razorpay or call local Razorpay capture endpoints, and activation-code subscription still works.

## 2026-05-10 Profile page Batch 10 subscription / helper / watermark upload hardening
- Batch 10 scope:
  - legacy helper registration endpoint still called by `profile.js`.
  - subscription detail lookup.
  - activation-code subscription renewal.
  - clinic watermark/logo upload form.
  - remaining Razorpay checkout references in `subscription.php`.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/registerHelper.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/fetchDoctorSubscriptionDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/saveActivationCodeSubscription.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/uploadFromHTML.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/subscription.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/subscription.php`
- Security changes:
  - `registerHelper.php`, `fetchDoctorSubscriptionDetails.php`, `saveActivationCodeSubscription.php`, and `uploadFromHTML.php` now require PHP session auth and CSRF.
  - helper registration and watermark upload require settings/admin-capable session access.
  - doctor email/id is validated and bound to the active session doctor or mapped center.
  - helper username/phone/name and activation code are validated before SQL.
  - subscription/helper endpoints use prepared SQL directly instead of legacy `db_functions.php` raw SQL paths.
  - watermark upload validates JPG/PNG content with `getimagesize`, limits size to 500 KB, writes only fixed `watermarkLogo.{jpg,png}`, and removes the opposite old extension.
  - active Razorpay checkout script/classes/capture endpoint references were removed from `profile.php`, `subscription.php`, and `subscription.js`.
  - no `db_functions.php` edit was made.
- Frontend changes:
  - `subscription.js` now parses JSON object responses as well as legacy strings.
  - `profile.js` now sends CSRF for legacy helper registration and sets a hidden CSRF field for watermark upload.
  - `profile.php` cache-bumped to `profile.js?v=2.16`.
  - `subscription.php` cache-bumped to `subscription.js?v=1.5`.
- Tracker:
  - Added Profile Page Batch 10 tracker row in `secured_api_tracking.md`.
- Local verification:
  - `php -l` passed for `registerHelper.php`, `fetchDoctorSubscriptionDetails.php`, `saveActivationCodeSubscription.php`, `uploadFromHTML.php`, `profile.php`, and `subscription.php`.
  - Static scan found no `checkToken`, `Token invalid`, `display_errors`, SQL echo, `mysqli_query`, `print_r`, or `db_functions` references in Batch 10 endpoints.
  - Static scan found no active Razorpay checkout/capture references in `profile.php`, `subscription.php`, or `subscription.js`.
  - CLI no-session POST probes against Batch 10 endpoints returned `SESSION_EXPIRED`.
- Staging test plan after sync:
  - Open `profile.php` and confirm `profile.js?v=2.16` and `subscription.js?v=1.5` load.
  - Use Add Helper legacy UI if visible; confirm registration/update returns success and rejects logged-out/CSRF-less calls.
  - Confirm subscription details render on `profile.php`.
  - Open `subscription.php`; confirm no Razorpay checkout script loads and payment button only shows disabled-payment message.
  - Apply a known safe activation code in a test account if available; otherwise verify invalid code returns controlled "Invalid Activation Code".
  - Upload a small JPG/PNG clinic logo from Profile; confirm redirect back to `profile.php` and image appears.
  - Try oversized or non-image upload and confirm it is rejected.

## 2026-05-10 Profile watermark removal
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/profile.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/profile.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/smoke_testing_later.md`
- Changes:
  - removed the active watermark enable checkbox and clinic-logo/watermark upload form from `profile.php`.
  - removed active watermark image lookup, preview, upload trigger, and toggle logic from `profile.js`.
  - `profile.js` now forces `watermarkDisplayFlag` to `false` in local storage and while saving hospital details.
  - cache-bumped `profile.js` to `v=2.17`.
  - updated smoke tests so later Profile testing verifies watermark UI is absent rather than testing upload.
- Verification:
  - `php -l profile.php` passed.
  - Static scan confirms `profile.php` no longer references `uploadFromHTML`, `waterMarkUpload`, `watermarkLogo`, `add_file`, `docIdLogo`, or `waterMarkCsrfToken`.

## 2026-05-11 Index public speciality lookup
- Issue:
  - `index.php` was loading `js/script.js?v=3.28`, which called `/sajid/getSpecialityDetails.php` before login.
  - `/sajid/getSpecialityDetails.php` is now correctly session/CSRF protected for authenticated pages, so the public index page saw `401 Unauthorized`.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/sajid/getPublicSpecialityDetails.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/script.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/smoke_testing_later.md`
- Changes:
  - added `/sajid/getPublicSpecialityDetails.php` as a dedicated public read-only speciality dropdown endpoint.
  - kept `/sajid/getSpecialityDetails.php` protected for authenticated pages.
  - `js/script.js` now calls the public endpoint and appends option text through jQuery `.text()` instead of raw HTML string interpolation.
  - removed active console output from the speciality dropdown path.
  - cache-bumped `index.php` from `script.js?v=3.28` to `script.js?v=3.29`.
- Verification:
  - `php -l sajid/getPublicSpecialityDetails.php` passed.
  - `php -l index.php` passed.
  - Static scan confirms `index.php` now loads `script.js?v=3.29` and `js/script.js` calls `/sajid/getPublicSpecialityDetails.php`.
  - Staging sync/user smoke test pending.

## 2026-05-11 Trial index page redesign
- Scope:
  - Visual trial refresh only for `index.php`; backend login, OTP, registration, and speciality APIs were not changed.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index.php`
- Changes:
  - added a trial page theme using the same blue/orange/soft-panel visual language as the ABDM ABHA flow.
  - refreshed the hero copy, navigation anchors, CTA buttons, feature copy, workflow copy, and contact copy.
  - added a visible registration section using the existing frontend IDs expected by `js/script.js` (`fname`, `lname`, `email1`, `phNo`, `speciality`, `regNum`, `degree`, `hospitalName`, `hospitalAddress`, `fileToUpload`, `doctorParam`, `studentParam`, `docId`, `imageUpload`).
  - removed the stale commented registration block from the hero area to avoid confusion while testing.
  - corrected active section anchors for `top-content`, `features`, `how-it-works`, `register`, `contact`, and `testimonials`.
  - removed duplicate active `id="login"` usage from the navbar toggle/login button.
- Verification:
  - `php -l index.php` passed.
  - Static scan confirms required login/registration element IDs are present once in active markup.
  - `php index.php` still shows existing undefined-variable warnings for legacy PHP variables when run directly from CLI; this was pre-existing behavior and is normally hidden/handled in the web environment.

## 2026-05-11 Index redesign moved to index2
- User direction:
  - revert the changes in `index.php`.
  - put the new complete redesign in `index2.php` for trial testing.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Revert handling:
  - restored `index.php` from the old landing-page reference structure.
  - kept recent safe fixes in `index.php`: staging canonical/OG URL, removed `retina-1.1.0.min.js`, and kept `js/script.js?v=3.29`.
- New trial page:
  - added `index2.php` as a complete redesigned landing page rather than a restyled copy of the old sections.
  - includes a new fixed navbar, hero, operational platform cards, ABDM workflow section, security section, registration panel, client carousel, contact band, footer, OTP modals, loading modal, and the existing frontend hooks required by `js/script.js` / `js/mine.js`.
  - uses existing IDs/classes required for login and registration: `login`, `email`, `phoneNumber`, `fname`, `lname`, `email1`, `phNo`, `speciality`, `regNum`, `degree`, `hospitalName`, `hospitalAddress`, `fileToUpload`, `doctorParam`, `studentParam`, `docId`, `imageUpload`, `otp`, `otp1`, `beforeClick`, `afterClick`, `showLogin`, `otp1`, `checkOTP`, and `checkOTP1`.
- Verification:
  - `php -l index.php` passed.
  - `php -l index2.php` passed.
  - Static scan confirms `index.php` has no active `retina` or `script_test` references.
  - Static scan confirms `index2.php` loads `js/script.js?v=3.29` and has the functional element hooks expected by the existing login/register JavaScript.

## 2026-05-11 Index2 register page removal
- User direction:
  - remove the register page from the trial redesign.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - removed the `#register` section from `index2.php`.
  - removed the registration-only OTP modal `#otpBox1`.
  - changed register/request-access CTAs to doctor login, explore platform, or contact actions.
  - removed registration-only CSS selectors from the trial page.
  - left `index.php` unchanged.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms no `href="#register"`, `id="register"`, `otpBox1`, `checkOTP1`, `resendOTP1`, registration input IDs, or registration upload hooks remain in `index2.php`.

## 2026-05-11 Index2 full landing page refresh
- User direction:
  - create a strong DocBox landing page using the known product modules and keep doctor login like the existing index page.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - rebuilt `index2.php` as the trial DocBox landing page while leaving `index.php` unchanged.
  - added a fixed header, hero section, dashboard-style workflow preview, module grid, care journey section, ABDM section, security section, reports/admin section, client carousel, contact panel, footer, loading modal and login OTP modal.
  - preserved doctor-login hooks used by the existing frontend scripts: `login`, `email`, `phoneNumber`, `otp`, `otpBox`, `checkOTP`, `resendOTP`, `beforeClick`, `afterClick`, and `showLogin`.
  - kept the public page registration-free: no `#register` section, no registration inputs, no registration upload controls and no `otpBox1`.
  - used existing visual assets only: logo, ophthalmology hero background, dark section background and client carousel images.
- Verification:
  - `php -l index2.php` passed.
  - `php index2.php` renders the page markup without CLI warnings.
  - Static scan confirms login hooks are present and registration hooks remain absent.

## 2026-05-11 Index2 security section SEO copy
- User direction:
  - redesign the "Security work aligned with audit expectations" section with text understandable by doctors and hospital management.
  - make it SEO friendly.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - changed the security section heading to "Secure EMR software for patient data and hospital teams".
  - replaced audit-heavy wording with doctor/hospital-management language covering protected login, patient record access control, safer data entry, safe uploads/reports, staff role controls and ABDM data exchange safety.
  - updated the meta description to include "secure ABDM-ready EMR" and "hospital management software".
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 hero workflow diagram
- User direction:
  - replace "DocBox Command Center" with a diagram-style visual because it is not an actual product module.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - replaced the hero dashboard card with a hospital workflow diagram.
  - diagram now shows Front Desk, Doctor, Billing, Pharmacy, IPD/OT and ABDM connected around a central Patient Record.
  - removed the old "DocBox Command Center" label and old timeline/card classes.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms `DocBox Command Center`, old dashboard queue classes and old patient journey text are no longer present.

## 2026-05-11 Index2 scroll-link fix
- Issue:
  - clicking new `index2.php` navigation links raised `scripts.js:10 Uncaught TypeError: Cannot read properties of undefined (reading 'top')`.
  - root cause: legacy `js/scripts.js` converted `#platform` into `.platform-container`, but `index2.php` uses real section IDs such as `id="platform"`.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/scripts.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - updated `scroll_to()` to support direct `#id` targets first, then legacy `.section-container`, then legacy `.section` selectors.
  - added a missing-target guard so invalid scroll links return without throwing.
  - removed the debug `console.log(element_class)`.
  - cache-bumped the `index2.php` include to `js/scripts.js?v=1.1`.
- Verification:
  - `php -l index2.php` passed.
  - `node --check js/scripts.js` could not be run because Node is not installed in the workspace.

## 2026-05-11 Index2 navbar contrast fix
- Issue:
  - the `db-nav` top bar was white and the DocBox logo is also white, so the logo merged into the navbar background.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - changed the navbar background to dark clinical navy.
  - adjusted navbar link, mobile toggle and login input colors for the dark navbar.
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 navbar scroll offset fix
- Issue:
  - navbar links scrolled to section tops without accounting for the fixed top bar, so the target section appeared misaligned/hidden under the navbar.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/js/scripts.js`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - `scroll_to()` now subtracts the fixed navbar height for section links.
  - `#top` remains clamped to page top.
  - updated `index2.php` to load `js/scripts.js?v=1.2`.
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 hero diagram wording update
- User feedback:
  - "How DocBox connects the hospital" was wrong.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - changed the hero diagram heading to "Patient journey inside DocBox".
  - changed the pill to "Shared hospital record".
  - updated the diagram caption to explain registration, consultation, billing, pharmacy, surgery and ABDM as linked steps on the same patient record.
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 db-dashboard replacement
- User direction:
  - remove `db-dashboard` and replace it with something else.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - replaced the hero `db-dashboard` wrapper with `db-record-map`.
  - removed the remaining dashboard/status-pill styling and markup.
  - kept the diagram content as a shared patient record map across front desk, doctor, billing, pharmacy, IPD/OT and ABDM.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms no `db-dashboard` references remain in `index2.php`.

## 2026-05-11 Index2 record-map removal
- User direction:
  - remove the `db-record-map` section.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - removed the entire `db-record-map` hero visual.
  - removed the related `db-flow-*` CSS and responsive rules.
  - changed the hero layout to a single-column text/CTA/summary-card section.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms no `db-record-map` or `db-flow-*` references remain in `index2.php`.

## 2026-05-11 Index2 patient journey animation
- User direction:
  - add a small animation showing a patient walking through: registration -> billing -> appointment -> workup -> doctor -> pharmacy -> exit.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - added a pure CSS hero animation with a patient icon moving across station nodes.
  - station sequence: Registration, Billing, Appointment, Workup, Doctor, Pharmacy, Exit.
  - added responsive vertical animation for mobile screens.
  - kept login hooks unchanged.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms the new animation classes and station sequence are present.

## 2026-05-11 Index2 patient journey animation correction
- User feedback:
  - animation was wrong; needed deep flow analysis and a step-by-step single-row animation.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - corrected the patient journey animation to a single horizontal row.
  - removed the zig-zag/alternating station movement and the mobile vertical animation.
  - patient now moves left-to-right and pauses step by step through Registration, Billing, Appointment, Workup, Doctor, Pharmacy and Exit.
  - each station highlights in sequence as the patient reaches it.
  - kept the row intact on small screens using horizontal overflow rather than changing the flow direction.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms no vertical animation keyframes remain and the exact station sequence is present.

## 2026-05-11 Index2 patient journey full-width row
- Issue:
  - the patient journey animation was inside the narrow right side of the hero, causing the single row to overflow outside the visible card.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - changed the hero layout from a two-column grid to a single-column grid.
  - made the patient journey animation span the full hero container width.
  - removed the fixed minimum route width that forced horizontal clipping.
  - kept the animation in one row with the same sequence: Registration, Billing, Appointment, Workup, Doctor, Pharmacy, Exit.
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 added integration feature cards
- User direction:
  - include WhatsApp integration and medical device integrations as features.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - added a "WhatsApp Integration" card to the platform module grid.
  - added a "Medical Device Integration" card to the platform module grid.
  - used hospital-friendly and SEO-relevant wording for patient communication, appointment updates, prescription links, follow-up reminders and device-connected reports/readings.
- Verification:
  - `php -l index2.php` passed.

## 2026-05-11 Index2 actual care journey image
- User direction:
  - use the provided generated image for the actual care journey section.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/images/patient_journey.png`
- Changes:
  - copied the provided image from `/Users/apple/Downloads/ChatGPT Image May 11, 2026, 01_18_38 PM.png` to `images/patient_journey.png`.
  - replaced the old "Designed around the actual care journey" step cards with the image.
  - added image wrapper styling with horizontal overflow for smaller screens so the detailed journey image remains readable.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms old `db-journey-step` markup is removed and `images/patient_journey.png` is referenced.

## 2026-05-11 Index2 patient journey image rename
- User direction:
  - rename the care journey image to `patient_journey.png`.
- Files updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/images/patient_journey.png`
- Changes:
  - renamed `images/docbox-care-journey.png` to `images/patient_journey.png`.
  - updated the `index2.php` image reference.
- Verification:
  - `php -l index2.php` passed.
  - `images/patient_journey.png` exists and the old `images/docbox-care-journey.png` file is no longer present.

## 2026-05-11 Index2 patient route animation removal
- User direction:
  - remove `db-patient-route`.
- File updated:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/index2.php`
- Changes:
  - removed the entire hero `db-patient-route` animation markup.
  - removed all related `db-route-*` CSS and keyframes.
  - kept the actual care journey image section using `images/patient_journey.png`.
- Verification:
  - `php -l index2.php` passed.
  - Static scan confirms no `db-patient-route`, `db-route-*`, or related keyframe references remain in `index2.php`.

## 2026-05-11 ABDM endpoint security matrix step 1
- User direction:
  - start ABDM-specific security hardening with step 1: identify and classify ABDM endpoints.
- File created:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/abdm_endpoint_security_matrix.md`
- Changes:
  - created a dedicated ABDM endpoint security matrix.
  - classified endpoints by server and security model:
    - Main server / staging UI browser APIs and ABHA UI journey pages.
    - Windows Lightsail ABDM bridge public callback/webhook routes.
    - Main server internal signed bridge endpoints.
    - M3 console/patient data endpoints.
    - debug/test/probe endpoints that should be restricted or disabled before VAPT.
  - documented that browser session/CSRF applies to normal DocBox UI APIs, while ABDM public callbacks need callback-specific validation instead.
- Next step:
  - review and patch the matrix category by category, starting with debug/test exposure and public callback validation.

## 2026-05-11 ABDM debug/test/probe endpoint removal
- User direction:
  - remove all ABDM debug/test/probe endpoints, but keep them in a separate file so they can be restored later if needed.
- Files removed from executable `api/` locations:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_reset_callback_debug_log.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_care_context_document_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_discovery_patient_search_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_prescription_fhir_bundle_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_visit_payload_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_visit_share_object_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_m2_api_probe.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_consent_validate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_request.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_transfer_prepare_encryption.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_callback_debug_log.jsonl`
- Archive created:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/.abdm_debug_test_probe_endpoints_removed_20260511.tar`
- Notes:
  - the PHP debug/test/probe endpoint sources were archived in the tar file.
  - the runtime `.jsonl` callback debug log was removed but not archived because it can contain patient/transaction data and is not needed to restore endpoint code.
  - `abdm_endpoint_security_matrix.md` was updated to mark these endpoints as removed.
- Verification:
  - archive contains the 10 PHP endpoint source files.
  - scan for `abdm_.*(debug|test|probe)` and `abdm_callback_debug_log` under `api/` returns no ABDM debug/test/probe endpoint files.

## 2026-05-11 ABDM debug/test/probe endpoint restoration
- User direction:
  - restore the ABDM debug/test/probe endpoints.
- Files restored to executable `api/` locations:
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_reset_callback_debug_log.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_care_context_document_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_discovery_patient_search_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_prescription_fhir_bundle_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_visit_payload_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_visit_share_object_debug.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_m2_api_probe.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_consent_validate.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_request.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_transfer_prepare_encryption.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/api/abdm_callback_debug_log.jsonl`
- Notes:
  - PHP files were restored from `.abdm_debug_test_probe_endpoints_removed_20260511.tar`.
  - `api/abdm_callback_debug_log.jsonl` was recreated as an empty file because runtime data was not archived.
  - `abdm_endpoint_security_matrix.md` was updated to mark these endpoints as active/restored and still needing restriction before VAPT.

## 2026-05-11 ABDM single-entry Aadhaar prefill removal
- User direction:
  - on Lightsail, `abdm_abha_single_entry.php` has a hardcoded Aadhaar number; remove it.
- File updated:
  - **Windows Lightsail ABDM bridge** `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
- Change:
  - removed the startup call that prefilled Aadhaar inputs with the hardcoded 12-digit test value.
  - the ABDM single-entry page now loads blank Aadhaar fields when there is no restored flow state.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - scan confirms the hardcoded Aadhaar value is no longer present in `Public/abdm_abha_single_entry.php`.

## 2026-05-11 ABDM debug mode flag
- User direction:
  - add a central flag to disable ABDM debug mode safely.
- Files updated:
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/config/config.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/api/_bootstrap.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_reset_callback_debug_log.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_care_context_document_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_discovery_patient_search_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_prescription_fhir_bundle_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_visit_payload_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_visit_share_object_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_m2_api_probe.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_consent_validate.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_request.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_transfer_prepare_encryption.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/abdm_endpoint_security_matrix.md`
- Changes:
  - added config flag `ABDM_DEBUG_ENABLED`, defaulting to `false`.
  - added `abdmDebugEnabled()` and `requireAbdmDebugEnabled()` helpers to both ABDM bootstrap files.
  - made `abdmDebugAppend()` return without writing when debug is disabled.
  - guarded ABDM debug/test/probe endpoints so they return `403 DEBUG_DISABLED` when the flag is false.
  - updated the ABDM endpoint matrix to show debug endpoints as present but guarded by default.
- Verification:
  - `php -l` passed for `config/config.php`, `api/abdm_bootstrap.php`, `api/_bootstrap.php`, and all guarded debug/test/probe endpoints.
  - CLI check confirms `abdmDebugEnabled()` returns `disabled` by default.
  - CLI check confirms one `abdm_bootstrap.php` debug endpoint and one `_bootstrap.php` debug endpoint both return `{"success":false,"error":"DEBUG_DISABLED","message":"Debug endpoint is disabled."}`.

## 2026-05-11 ABDM debug mode flag revert
- User direction:
  - revert the debug mode flag changes.
- Files reverted:
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/config/config.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge shared code** `/Users/apple/Documents/docbox_staging/api/_bootstrap.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_reset_callback_debug_log.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_care_context_document_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_discovery_patient_search_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_prescription_fhir_bundle_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_visit_payload_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_visit_share_object_debug.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_m2_api_probe.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_consent_validate.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_request.php`
  - **Main server / staging UI / Windows Lightsail ABDM bridge debug endpoints** `/Users/apple/Documents/docbox_staging/api/abdm_test_health_information_transfer_prepare_encryption.php`
  - **Main server / staging UI** `/Users/apple/Documents/docbox_staging/abdm_endpoint_security_matrix.md`
- Reverted:
  - removed `ABDM_DEBUG_ENABLED` config flag.
  - removed `abdmDebugEnabled()` and `requireAbdmDebugEnabled()` helpers.
  - restored `abdmDebugAppend()` to write logs as before.
  - removed debug guards from ABDM debug/test/probe endpoints.
  - updated the matrix so endpoints are again marked restored and needing restriction before VAPT.

## 2026-05-13 AI spell-check visit test clone and medicine UI work
- User direction:
  - implement AI spell-check/clinical safety review without changing the current production visit flow.
  - create and work in a cloned test visit page/script first.
  - user can enable/disable the feature later; current test flow uses field-level AI checks instead of save interception.
- Primary files:
  - **Main server / staging UI test clone** `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_ai_test.html`
  - **Main server / staging UI test clone** `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_ai_test.js`
  - **Main server / staging UI secured backend API** `/Users/apple/Documents/docbox_staging/api/ai_spellcheck_visit.php`
  - **Main server / staging UI config** `/Users/apple/Documents/docbox_staging/sajid/includes/staging_config.php`
- Current clone script version:
  - `patientInfo_oph_rectify_ai_test.html` loads `js/patientInfo_oph_rectify_ai_test.js?v=2.2`.
- Backend AI endpoint status:
  - endpoint: `/api/ai_spellcheck_visit.php`
  - accepts JSON POST only.
  - uses existing DocBox secure session/auth helpers.
  - requires CSRF header.
  - checks session doctor binding against request `doctorId`.
  - reads OpenRouter settings from config/env, not frontend.
  - current model default: `nvidia/nemotron-3-nano-30b-a3b:free`.
  - parses only `choices[0].message.content`.
  - ignores `reasoning` and `reasoning_details`.
  - uses JSON schema output where supported.
  - has safe fallback responses for OpenRouter failure, invalid JSON, invalid structure, timeout, and 429 rate limit.
  - logs metadata only by default; full payload logging was used only temporarily for debugging and must remain disabled in normal use because it contains clinical text.
- AI frontend behavior:
  - save flow is not intercepted.
  - AI runs only when the user clicks field-level `AI Check`.
  - safe corrections apply directly into the matching field.
  - critical errors are review-only and are not auto-applied.
  - unknown fields are skipped for auto-apply.
  - each AJAX call uses existing CSRF header helper.
- AI field coverage in the clone:
  - chief complaint: `#complaint`
  - advice/history text: `#history`
  - examination finding: `#examFinding`
  - diagnosis: `#diagName`
  - medicine name inputs: dynamic `#newMedXX`
  - old medication input: `.medicationText`
- Dynamic AI button attach fixes:
  - AI buttons attach after the visit fields are dynamically rendered.
  - AI buttons attach on modal open.
  - each newly added medicine row calls `window.docboxAiVisitAttachMedicineButton("#newMedXX")` immediately after insertion.
  - generic scan remains as backup through `docboxAiVisitScheduleAttachFieldButtons()`.
- Medicine name UI changes in the clone:
  - medicine name field changed from a narrow text input to a custom boxed textarea.
  - field grows vertically, not horizontally.
  - helper exposed as `window.docboxResizeMedicineNameInput()` to avoid scope errors during dynamic row creation.
  - each medicine name row has its own `AI Check` button.
- Medicine row UI refactor in the clone:
  - old red-bordered medicine table was restyled as `docbox-med-row`.
  - key functional IDs/classes were preserved:
    - `#newMedXX`
    - `#newMedTableXX`
    - `.medGreenXX`
    - `.medBlueXX`
    - `.medDescXX`
    - `.savedPreviewXX`
    - `.autoDosagePreview`
    - `.dosageSuggestionButtonsXX`
    - `#pharmDetailXX`
    - `#pharmDetailsErrorXX`
  - medicine name, dosage preview, frequency, duration, instructions, and dosage suggestions are visually separated.
- Dosage preview/tapering behavior documented:
  - `.savedPreviewXX` is the functional finalized dosage/tapering container.
  - `.autoDosagePreview` is the saved dosage unit read by Save All.
  - `.medPreviewTimesXX`, `.medPreviewDaysXX`, `.medPreviewDescXX`, and `.medPreviewCustomDescXX` are the current dosage selection.
  - if no tapering/finalized row is added, the current dosage selection is still treated as final during Save All.
  - if a tapering/finalized row is added, it is appended into `.savedPreviewXX` as `.autoDosagePreview`.
  - tapering date logic chains from previous `data-to-date` / `data-till-date`.
  - first tapering step uses `Till DD-MM-YYYY`.
  - later tapering steps use `From DD-MM-YYYY to DD-MM-YYYY`.
- Dosage preview UI changes:
  - `docbox-med-preview-box` is hidden by default.
  - it becomes visible only after a finalized/tapering preview row is appended.
  - current dosage row remains visible and is labelled as the final dosage when no tapering row exists.
  - finalized tapering rows render as green preview rows.
  - `Clear` now clears only the current dosage selection for that medicine row.
  - `Clear` does not remove the medicine name and does not remove finalized tapering rows.
- Pending smoke tests after upload to main staging:
  - hard refresh `patientInfo_oph_rectify_ai_test.html`.
  - add one medicine manually and verify `AI Check` appears.
  - add multiple medicines and verify every medicine name box gets its own `AI Check`.
  - type a long medicine name and verify the medicine name box grows vertically.
  - run AI Check on a misspelled medicine name and confirm only the medicine name changes.
  - select frequency/days/instruction without adding tapering and Save All; confirm dosage is saved.
  - add tapering rows and Save All; confirm `.autoDosagePreview` rows are saved correctly.
  - use Clear and confirm only current dosage selection clears.
  - verify medicine delete still removes the correct medicine row.

## 2026-05-14 Context file analysis
- Opened and reviewed `/Users/apple/Documents/docbox_staging/stagingcontext.md`.
- Current context confirms the active workstream is DocBox staging security hardening plus the AI spell-check test clone for Rectify Test VS.
- The latest actionable items are the AI test clone upload/smoke tests for `patientInfo_oph_rectify_ai_test.html`, `js/patientInfo_oph_rectify_ai_test.js`, `api/ai_spellcheck_visit.php`, and related staging config, plus continued attention to ABDM debug/test endpoints before VAPT.
- No application code was changed during this analysis pass.

## 2026-05-14 Application context snapshot
- Generated a concise application-context summary from `stagingcontext.md`.
- Context source remains `/Users/apple/Documents/docbox_staging/stagingcontext.md`.
- No application code was changed.

## 2026-05-14 Non-admin login lookup fix
- Issue reported: login worked for admin username but failed when using a non-admin/helper username.
- Finding: `sajid/loginDocbox.php` checked `personalinfo.CustomerEmail` first through `docbox_login_email_exists()`. If the submitted username was a helper/staff email from `helperDoctorMappings.HelperEmail`, that admin-only precheck failed and the code never reached the helper login query.
- Local fix: `sajid/loginDocbox.php` now calls `docbox_login_lookup()` directly so admin and helper credential lookup both run. The later security follow-up made failed-login responses generic instead of doing a separate identifier-exists check.
- Verification: `php -l sajid/loginDocbox.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/loginDocbox.php` to `/home/stagingdocbox/public_html/sajid/loginDocbox.php`

Follow-up security check:

- `sajid/authOTP.php` still had the legacy `getmeinside` OTP bypass, and `sajid/loginDocbox.php` still had matching code that substituted the stored password and sent a backdoor SMS. Both were removed.
- `sajid/loginDocbox.php` no longer echoes the submitted phone/password array in `response["result"]`.
- Failed login now returns a generic `Invalid login credentials.` message instead of disclosing whether the submitted username exists.
- `secured_api_tracking.md` login row was updated.
- Verification:
  - `php -l sajid/loginDocbox.php` passed.
  - `php -l sajid/authOTP.php` passed.
  - Focused scan found no `getmeinside`, `Backdoor opened`, `dataPasswordTemp`, `response["result"]`, username-enumeration failure messages, or backdoor `curl_init()` call in `sajid/loginDocbox.php` / `sajid/authOTP.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/loginDocbox.php` to `/home/stagingdocbox/public_html/sajid/loginDocbox.php`
  - `/Users/apple/Documents/docbox_staging/sajid/authOTP.php` to `/home/stagingdocbox/public_html/sajid/authOTP.php`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md` if the tracker is kept on the server.

Backdoor restoration request:

- User requested restoring the `getmeinside` login/OTP backdoor.
- Decision: do not restore hidden authentication bypasses. This would defeat the API hardening/VAPT objective.
- Safer alternative if emergency access is required: implement an explicit break-glass admin flow with environment-gated enablement, IP allowlist, short expiry, audited usage logs, rate limiting, and normal OTP/session controls.
- No application code was changed for this request.

## 2026-05-14 Emergency access guidance
- User asked what can be done for an easy backdoor.
- Guidance: do not create hidden authentication bypasses. Use a visible, controlled break-glass access flow instead.
- Suggested controls: private config enablement, IP allowlist, short expiry window, OTP/session creation, rate limiting, immutable audit log, and immediate disable switch.
- No application code was changed for this request.

## 2026-05-14 Profile switch backdoor-like path disabled
- User confirmed the backdoor should be removed and pointed out the Switch Profile button in `js/init.js`.
- Local changes:
  - `js/init.js` no longer renders the `Switch Profile` menu item.
  - `js/init.js` no longer defines or binds the `switchProfile()` function.
  - `sajid/loginDocboxSwitch.php` now fails closed with `PROFILE_SWITCH_DISABLED` after active session/CSRF checks.
  - Active pages loading `js/init.js?v=3.5` were cache-bumped to `v=3.6`:
    - `IPD.php`
    - `patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_ai_test.html`
    - `reportEditor.php`
    - `discharge_card_oph.html`
    - `patientReports.php`
    - `profile.php`
    - `calendar.php`
  - `secured_api_tracking.md` Profile switch row was updated to disabled.
- Verification:
  - `php -l` passed for `sajid/loginDocboxSwitch.php`, `IPD.php`, `reportEditor.php`, `patientReports.php`, `profile.php`, `calendar.php`, `patientInfo_oph_rectify_test_vs.html`, `patientInfo_oph_rectify_ai_test.html`, and `discharge_card_oph.html`.
  - Focused scan confirms `Switch Profile`, `switchProfile`, `profileSwitch`, and `loginDocboxSwitch` are no longer present in `js/init.js`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/init.js` to `/home/stagingdocbox/public_html/js/init.js`
  - `/Users/apple/Documents/docbox_staging/sajid/loginDocboxSwitch.php` to `/home/stagingdocbox/public_html/sajid/loginDocboxSwitch.php`
  - Upload the cache-bumped pages listed above to their matching `/home/stagingdocbox/public_html/` paths.
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md` if the tracker is kept on the server.

Follow-up scan:

- User noted there are more pages with `js/init.js`.
- Full workspace scan confirmed additional `init.js` includes beyond the pages bumped to `v=3.6`.
- No further code changes were made in this scan pass.

## 2026-05-14 Expenses page API hardening
- User pointed to `expenses.php` and requested securing the APIs used by that page.
- Page/APIs reviewed:
  - `/Users/apple/Documents/docbox_staging/expenses.php`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/updateExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenseLogs.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenseLog.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadAttachment.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/finance_api_guard.php`
- Local changes:
  - Expense read/write/delete/payment-log APIs now require an authenticated PHP session and CSRF through `finance_api_guard.php`.
  - Submitted doctor id is bound to the active session doctor or mapped center before DB access.
  - Legacy `checkToken`-only gates and raw `db_functions.php` expense helper calls were removed from these endpoint paths.
  - Expense tracker and payment-log SQL now uses prepared statements directly in the endpoints.
  - `uploadAttachment.php` now requires session + CSRF, validates doctor binding, sanitizes filenames, restricts uploads to image types, limits size to 5 MB, and stores under the validated doctor expense directory.
  - `expenses.php` adds CSRF hidden fields to both upload forms and cache-bumps `init.js` to `v=3.6` and `expenses.js` to `v=1.6`.
  - `js/expenses.js` now uses JSON-safe payload construction for expense API calls, adds CSRF to multipart upload forms, sanitizes attachment names, safely parses JSON API responses, and escapes dynamic table/log output.
- Verification:
  - `php -l` passed for `expenses.php`, `sajid/includes/finance_api_guard.php`, and all seven touched PHP endpoints/upload script.
  - No-session CLI POST probes for all seven touched PHP scripts returned `SESSION_EXPIRED`.
  - Focused scan found no legacy `checkToken`, `Token invalid`, raw `mysqli_query`, display-error, or `die()` paths in the touched expense endpoints/upload path.
  - JS syntax check could not be run because `node` is not installed locally.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/expenses.php` to `/home/stagingdocbox/public_html/expenses.php`

## 2026-05-23 Rectify Test VS chat restart handoff

- User is restarting the chat and wants neutral implementation wording.
- Current active page:
  - Local: `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Staging: `https://staging.docbox.asia/patientInfo_oph_rectify_test_vs.html`
- Step 1 completed and uploaded by user:
  - `js/patientInfo_oph_rectify_test_vs.js` added shared safe rendering helpers:
    - `docboxPatientInfoText`
    - `docboxPatientInfoEscapeHtml`
    - `docboxPatientInfoEscapeAttr`
    - `docboxPatientInfoSafeTrim`
    - `docboxPatientInfoAppendSuggestion`
  - Rectify page now loads `js/patientInfo_oph_rectify_test_vs.js?v=40.43`.
  - Local checks passed:
    - `node --check js/patientInfo_oph_rectify_test_vs.js`
    - `php -l patientInfo_oph_rectify_test_vs.html`
- User reported after upload:
  - In Add Diagnosis, the UI prints `1`.
- Investigation notes:
  - Add Diagnosis button handler starts around `js/patientInfo_oph_rectify_test_vs.js` line `19730`.
  - Add button handler `.addDiag1` starts around line `19898`.
  - `getDiagnosis()` reload helper starts around line `19858`.
  - Diagnosis modal markup is in `patientInfo_oph_rectify_test_vs.html` around lines `2741` to `2842`.
  - Diagnosis card rendering still uses old string-building in these areas:
    - copy diagnosis callback near line `15310`
    - visit-open diagnosis render near line `19100`
    - Add Diagnosis save/reload near lines `19873` and `19950`
- Next recommended task:
  - Fix only the Add Diagnosis modal/card rendering path.
  - Use DOM text setters or existing safe rendering helpers for diagnosis date, diagnosis text, comments, version attributes, and delete button data attributes.
  - Bump Rectify JS from `v=40.43` to `v=40.44`.
  - Run:
    - `node --check js/patientInfo_oph_rectify_test_vs.js`
    - `php -l patientInfo_oph_rectify_test_vs.html`
- Upload required for this context update:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS safe rendering step 1

- User asked to break the external finding work into steps and start with step 1, avoiding unnecessary trigger wording.
- Affected page:
  - Local: `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Staging: `https://staging.docbox.asia/patientInfo_oph_rectify_test_vs.html`
- Local editor open requirement:
  - Tried opening `js/patientInfo_oph_rectify_test_vs.js`, `patientInfo_oph_rectify_test_vs.html`, and `stagingcontext.md` in Visual Studio Code before editing.
  - macOS returned LaunchServices error `-10822`, so edits were applied in the workspace after recording the failure.
- Local changes:
  - Added shared frontend text/attribute helpers in `js/patientInfo_oph_rectify_test_vs.js`.
  - Updated helper/staff dropdown rendering to use DOM text/value setters.
  - Updated chief complaint, examination finding, and advice suggestion rendering to use DOM text and safe `data-ver` assignment.
  - Updated patient summary, visit card, diagnosis labels, VA table values, medication tags, and visit edit textareas to render saved text safely.
  - Changed edited note display refresh from `innerHTML` to `textContent`.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.42` to `v=40.43`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS restart handoff

- User wants to restart the chat with cleaner wording.
- Current page:
  - Local: `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Staging: `https://staging.docbox.asia/patientInfo_oph_rectify_test_vs.html`
- Step 1 already completed:
  - `js/patientInfo_oph_rectify_test_vs.js` has shared safe text and attribute rendering helpers:
    - `docboxPatientInfoText`
    - `docboxPatientInfoEscapeHtml`
    - `docboxPatientInfoEscapeAttr`
    - `docboxPatientInfoSafeTrim`
    - `docboxPatientInfoAppendSuggestion`
  - Rectify JS cache is bumped in `patientInfo_oph_rectify_test_vs.html` to `js/patientInfo_oph_rectify_test_vs.js?v=40.43`.
  - Local checks passed:
    - `node --check js/patientInfo_oph_rectify_test_vs.js`
    - `php -l patientInfo_oph_rectify_test_vs.html`
- User uploaded step 1 and reported:
  - In Add Diagnosis, the UI prints `1`.
- Partial investigation before restart:
  - Add Diagnosis click handler is around `js/patientInfo_oph_rectify_test_vs.js` line `19730`.
  - Add Diagnosis save handler `.addDiag1` is around line `19898`.
  - Diagnosis reload helper `getDiagnosis()` is around line `19858`.
  - Diagnosis modal markup is in `patientInfo_oph_rectify_test_vs.html` around lines `2741` to `2842`.
  - Older diagnosis rendering paths still build diagnosis cards with string concatenation around:
    - copy diagnosis callback near line `15310`
    - visit-open diagnosis render near line `19100`
    - Add Diagnosis save/reload near lines `19873` and `19950`
  - Next step should focus only on diagnosis modal/card rendering and the `.addDiag1` flow, then bump Rectify JS to `v=40.44`.
- Suggested wording for next chat:
  - Use "safe rendering", "field cleanup", "server-side checks", "page access rules", and "API guards".
  - Avoid repeating audit terminology unless explicitly needed.
- Upload required after this context update:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Login OTP Hardening Controls

- User requested further securing of the DocBox login OTP flow without using risk/threat wording.
- Pages / endpoints:
  - Login page: `/Users/apple/Documents/docbox_staging/index.php` -> `/home/stagingdocbox/public_html/index.php`
  - Alternate login page: `/Users/apple/Documents/docbox_staging/index2.php` -> `/home/stagingdocbox/public_html/index2.php`
  - Login JavaScript: `/Users/apple/Documents/docbox_staging/js/script.js` -> `/home/stagingdocbox/public_html/js/script.js`
  - OTP delivery API: `/Users/apple/Documents/docbox_staging/sajid/OTPDocBox.php` -> `/home/stagingdocbox/public_html/sajid/OTPDocBox.php`
  - OTP verification API: `/Users/apple/Documents/docbox_staging/sajid/authOTP.php` -> `/home/stagingdocbox/public_html/sajid/authOTP.php`
  - DB helper: `/Users/apple/Documents/docbox_staging/sajid/db_functions.php` -> `/home/stagingdocbox/public_html/sajid/db_functions.php`
  - API tracking: `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` -> local documentation only
- Local changes:
  - Added `docboxOtpLoginControls` tracking table creation in `db_functions.php`.
  - Added short-window OTP delivery throttle: repeated OTP delivery requests within 60 seconds are blocked with `OTP_REQUEST_THROTTLED`.
  - Added one delivered OTP per mobile per calendar day: later requests return `OTP_ALREADY_SENT_TODAY` and do not send/log another OTP.
  - Added OTP verification lockout: after 5 failed OTP attempts, verification is locked for 15 minutes with `OTP_LOCKED`.
  - Updated `otpAuth()` to verify OTP using a prepared query bound to both `PhoneNumber` and `OTP`.
  - Updated `authOTP.php` to check lock status before verification, record failed attempts, and reset attempt count after successful OTP verification.
  - Updated `OTPDocBox.php` to check delivery controls before saving/sending OTP and record successful delivery.
  - Removed the legacy `getmeinside` special-case branch from `OTPDocBox.php` so OTP delivery follows the same path for every valid login mobile.
  - Updated `js/script.js` to parse structured OTP responses and show clear messages for throttled, already-sent, invalid, and locked OTP states.
  - Bumped `js/script.js` version from `3.29` to `3.30` in `index.php` and `index2.php`.
- Runtime table expected:

```sql
CREATE TABLE IF NOT EXISTS docboxOtpLoginControls (
  PhoneNumber varchar(120) NOT NULL,
  Purpose varchar(40) NOT NULL DEFAULT 'login',
  FailedAttempts int NOT NULL DEFAULT 0,
  LockedUntil datetime DEFAULT NULL,
  LastAttemptAt datetime DEFAULT NULL,
  LastDeliveredAt datetime DEFAULT NULL,
  LastRequestAt datetime DEFAULT NULL,
  PRIMARY KEY (PhoneNumber, Purpose)
);
```

- Local editor note: attempted to open all changed files in VS Code before edits, but macOS LaunchServices returned `kLSServerCommunicationErr`; edits were still applied locally with `apply_patch`.

Follow-up runtime fix:

- User reported `POST https://staging.docbox.asia/sajid/OTPDocBox.php` returning HTTP 500 from `script.js?v=3.30`.
- Live curl reproduced an empty HTTP 500 from the staging endpoint.
- Likely staging cause: `OTPDocBox.php` was active with the new OTP-control call while the matching `db_functions.php` helper methods were not active on the server yet.
- Local hardening follow-up:
  - `OTPDocBox.php` now returns controlled JSON `OTP_CONTROL_UNAVAILABLE` if the matching DB helper methods are not present, instead of throwing a fatal method call.
  - `authOTP.php` now returns controlled JSON `OTP_CONTROL_UNAVAILABLE` if the matching OTP lockout helper methods are not present.
  - `js/script.js` now displays OTP service errors from failed OTP delivery requests and unknown OTP-control messages.
  - `index.php` and `index2.php` now load `js/script.js?v=3.31`.
- Required sync remains all matched files together:
  - `/Users/apple/Documents/docbox_staging/sajid/db_functions.php` to `/home/stagingdocbox/public_html/sajid/db_functions.php`
  - `/Users/apple/Documents/docbox_staging/sajid/OTPDocBox.php` to `/home/stagingdocbox/public_html/sajid/OTPDocBox.php`
  - `/Users/apple/Documents/docbox_staging/sajid/authOTP.php` to `/home/stagingdocbox/public_html/sajid/authOTP.php`
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up OTP delivery policy change:

- User requested replacing the one-successful-SMS-per-day OTP delivery policy with a 15-20 minute mark and enabling the Resend OTP button after 2 minutes.
- Local policy chosen: 15-minute server-side OTP delivery cooldown with a 2-minute UI resend-button cooldown.
- Local changes:
  - `db_functions.php::docboxCheckOtpDeliveryAllowed()` now uses `OTP_DELIVERY_COOLDOWN` instead of `OTP_ALREADY_SENT_TODAY`.
  - `OTPDocBox.php` calls the delivery guard with a 120-second short-window throttle and 900-second successful-delivery cooldown.
  - `db_functions.php::getOtpRequestValidity()` now reuses only OTP rows from the last 15 minutes, matching the OTP verification window; this prevents resending an already expired OTP after the delivery cooldown.
  - `js/script.js` now centralizes OTP send/resend through `docboxRequestOtp()`.
  - `.resendOTP` and `.resendOTP1` are disabled for 2 minutes after a successful OTP request and then re-enabled.
  - `index.php` and `index2.php` now load `js/script.js?v=3.32`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/db_functions.php` to `/home/stagingdocbox/public_html/sajid/db_functions.php`
  - `/Users/apple/Documents/docbox_staging/sajid/OTPDocBox.php` to `/home/stagingdocbox/public_html/sajid/OTPDocBox.php`
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up OTP retry-time display:

- User requested showing the time after which OTP reattempt can be made instead of only saying "try again later".
- Local changes:
  - `js/script.js::docboxOtpMessage()` now appends formatted retry time from API `retryAfterSeconds`.
  - Applies to OTP request throttle, OTP delivery cooldown, and OTP verification lockout messages.
  - `js/script.js` now formats wait time as `14 min 20 sec`, `2 min`, or `45 sec`.
  - `index.php` and `index2.php` now load `js/script.js?v=3.33`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

## 2026-05-23 Rectify Test VS Add Diagnosis rendering cleanup

- User confirmed the current task is Add Diagnosis handling on Rectify Test VS.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared diagnosis rendering helpers in `js/patientInfo_oph_rectify_test_vs.js`:
    - `docboxPatientInfoDiagnosisComment`
    - `docboxPatientInfoSafeClassSuffix`
    - `docboxPatientInfoAppendDiagnosisCard`
  - Updated Add Diagnosis reload helper `getDiagnosis()` to render cards through the shared helper instead of string-building.
  - Updated `.addDiag1` immediate add-card path to use the shared helper for diagnosis date, diagnosis text, comment, version, and delete button data attributes.
  - Updated Copy Diagnosis card rendering to use the same helper.
  - Updated visit-open diagnosis card rendering to use the same helper.
  - Normalized diagnosis comments so internal status values `1` and `5` are not displayed as diagnosis comments.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.43` to `v=40.44`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS spectacle dropdown follow-up

- User reported browser error after uploading `patientInfo_oph_rectify_test_vs.js?v=40.44`:
  - `Uncaught ReferenceError: div is not defined`
  - reported line was in the spectacle previous-version dropdown callback.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced the reported spectacle previous-version dropdown string-building block with jQuery option creation using `.val()` and `.text()`.
  - Cleaned the nearby older spectacle previous-version block with the same uninitialized variable pattern.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.44` to `v=40.45`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan found no remaining `var div1 = div1` pattern in the Rectify JS file.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS medicine-name rendering cleanup

- User reported that entering JavaScript-like text in a medicine name caused a browser error while the medicine summary row was appended.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared medicine summary rendering helpers:
    - `docboxPatientInfoDosageSummaryText`
    - `docboxPatientInfoAppendMedicineSummaryCard`
  - Updated new medicine summary rendering in `.saveAll` to write medicine name and dosage summary as text instead of appending raw markup.
  - Updated `addMedicineToDb()` summary rendering to use the shared helper.
  - Updated saved-medication reload renderers to use the shared helper while preserving refresh, edit, and delete buttons.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.45` to `v=40.46`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan found no remaining touched medicine summary pattern that inserts `medArray[i][4]`, `medArray[i][5]`, or `p[i]['Medications']` directly into HTML.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS dosage icon preservation

- User reported the Font Awesome dosage icons disappeared after the medicine summary rendering cleanup.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added dosage display sanitizer helpers:
    - `docboxPatientInfoSafeClassList`
    - `docboxPatientInfoSanitizeDosageHtml`
  - Medicine names remain rendered as text.
  - Dosage summaries now preserve allowed display markup for Font Awesome icons and language paragraphs while dropping other markup/attributes.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.46` to `v=40.47`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Refraction timeline JSON parser cleanup

- User reported browser error:
  - `"[object Object]" is not valid JSON`
  - source: `refractionKeyboardHelper.js?v=1.3` around the spectacle timeline callback.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/refractionKeyboardHelper.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_ai_test.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxRefractionParseJson()` to accept both legacy JSON strings and already-parsed JSON objects.
  - Updated spectacle timeline callback to use the helper and show the existing empty-state row if parsing fails.
  - Updated IOP timeline callback to use the same helper.
  - Bumped `refractionKeyboardHelper.js` from `v=1.3` to `v=1.4` in:
    - `patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_ai_test.html`
- Verification:
  - `node --check js/refractionKeyboardHelper.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - `php -l patientInfo_oph_rectify_ai_test.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/refractionKeyboardHelper.js` to `/home/stagingdocbox/public_html/js/refractionKeyboardHelper.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_ai_test.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_ai_test.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Medicine template JSON parser cleanup

- User reported browser error:
  - `"[object Object]" is not valid JSON`
  - source: `medicineTemplateHelper.js?v=1.2` in `getMedicineCatagory()`.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/medicineTemplateHelper.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_ai_test.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxMedicineTemplateParseJson()` to accept both legacy JSON strings and already-parsed JSON objects.
  - Replaced direct `$.parseJSON(response)` usage in medicine category, medicine group, medicine mapping, auto-add mapping, and dosage suggestion callbacks.
  - Bumped `medicineTemplateHelper.js` from `v=1.2` to `v=1.3` in:
    - `patientInfo_oph_rectify_test_vs.html`
    - `patientInfo_oph_rectify_ai_test.html`
- Verification:
  - `node --check js/medicineTemplateHelper.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - `php -l patientInfo_oph_rectify_ai_test.html` passed.
  - Focused scan found no remaining direct `$.parseJSON(response)` / `JSON.parse(response)` calls in `medicineTemplateHelper.js` except inside the new parser helper.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/medicineTemplateHelper.js` to `/home/stagingdocbox/public_html/js/medicineTemplateHelper.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_ai_test.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_ai_test.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS allergy history rendering cleanup

- User reported that entering JavaScript-like text in Allergy caused a browser error when `getPatientHistory()` refreshed the history UI.
- Files opened in local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared patient-history UI helpers:
    - `docboxPatientInfoRowsFromStorage`
    - `docboxPatientInfoAppendHistoryDropdown`
    - `docboxPatientInfoAppendHistoryHeader`
    - `docboxPatientInfoAppendHistoryRow`
  - Updated patient-history dropdown rendering for allergy, medical, birth, surgical, nutritional, family, immunisation, ocular, and current treatment autocomplete lists to use DOM text setters.
  - Updated allergy table rendering to write Allergy Type, Allergy Name, Comments, Noted By, and delete button data attributes safely.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `js/patientInfo_oph_rectify_test_vs.js?v=40.47` to `v=40.48`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan found no remaining allergy table/dropdown raw append path for saved allergy text.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

Follow-up OTP countdown readability:

- User reported OTP countdown/status text was grey and unreadable.
- Local changes:
  - `index.php` now defines high-contrast `.otpError` styling.
  - `index.php` and `index2.php` now override disabled OTP modal buttons so countdown text remains white and fully opaque.
  - `index2.php` existing `.otpError` style was adjusted to the same high-contrast red and line height.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up OTP delivery respects verification lockout:

- User requested that after page refresh, entering the same username/phone should check OTP verification lock before sending another OTP.
- Local change:
  - `sajid/OTPDocBox.php` now checks `db_functions.php::docboxGetOtpLockStatus()` before delivery throttling or OTP save/send/log.
  - If locked, `OTPDocBox.php` returns JSON `OTP_LOCKED` with `retryAfterSeconds`, so the existing frontend countdown handles it.
  - No OTP is saved, logged, emailed, or SMS-sent while verification is locked.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/OTPDocBox.php` to `/home/stagingdocbox/public_html/sajid/OTPDocBox.php`

Follow-up OTP cooldown persistence after refresh:

- User requested that verification lock and resend lock remain visible after page refresh for the same phone number.
- Local changes:
  - `js/script.js` now stores OTP resend cooldown and OTP verification lock expiry in `localStorage` per phone number.
  - On phone input/change/blur, the UI checks the stored state for that phone and restores the Resend OTP and Submit countdowns.
  - `docboxRequestOtp()` saves resend cooldowns from server `retryAfterSeconds` responses and also stores the normal 2-minute resend cooldown after a successful OTP send.
  - OTP verification lock responses save the lock expiry locally, so refresh + same phone restores the Submit countdown before another verify request is sent.
  - Changing the phone number clears stale button countdowns if the new number has no active stored cooldown.
  - `index.php` and `index2.php` now load `js/script.js?v=3.37`.
- Server remains the source of truth: `OTPDocBox.php` and `authOTP.php` still enforce delivery cooldown and verification lockout in DB.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up resend OTP cooldown from API:

- User requested the same UI limiting behavior for the Resend OTP button.
- Local changes:
  - `js/script.js::docboxRequestOtp()` now reads `retryAfterSeconds` from failed OTP delivery responses.
  - If the server returns `OTP_REQUEST_THROTTLED` or `OTP_DELIVERY_COOLDOWN`, the Resend OTP button stays disabled and counts down for the server-provided wait time.
  - Successful OTP sends still keep the Resend OTP button disabled for the normal 2-minute UI cooldown.
  - `index.php` and `index2.php` now load `js/script.js?v=3.36`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up OTP UI request limiting:

- User requested a UI-side limit so rapid repeated OTP requests do not keep hitting the server from the page.
- Local changes:
  - `js/script.js` now tracks in-flight OTP send/resend requests per OTP modal and ignores duplicate clicks until the current request finishes.
  - OTP send/resend buttons are disabled while their request is running.
  - `js/script.js` now tracks in-flight OTP verification requests separately for login and registration modals and ignores duplicate Submit clicks.
  - OTP Submit buttons show `Checking...` while verification is running.
  - If the server returns OTP lockout with `retryAfterSeconds`, the OTP Submit button stays disabled and counts down until retry is allowed.
  - `index.php` and `index2.php` now load `js/script.js?v=3.35`.
- Note: UI limiting is convenience protection only; server-side OTP delivery cooldown and verification lockout remain the enforcement layer.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

Follow-up live OTP countdown:

- User reported the wait time displays but stays stuck.
- Local changes:
  - `js/script.js` now uses `docboxShowOtpMessage()` for OTP request and verification errors with `retryAfterSeconds`.
  - A per-error-target timer updates the visible "Try again in ..." text every second.
  - Existing countdown is cleared when the OTP action succeeds or when a new OTP message replaces it.
  - `index.php` and `index2.php` now load `js/script.js?v=3.34`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/index2.php` to `/home/stagingdocbox/public_html/index2.php`

## 2026-05-15 Patient Reports helper-type upload/delete policy

- User requested Patient Reports action access:
  - Upload reports / attach Drive-Youtube reports / finalize temporary uploads: Doctor `8`, Clinical Staff `1`, Admin `6`, Super Admin `a`, Counsellor `7`.
  - Delete already uploaded reports: Doctor `8`, Admin `6`, Super Admin `a`.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientReports.php`
  - `/Users/apple/Documents/docbox_staging/js/patientReportWeb.js`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/patient_reports_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadDocumentsNew.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertDocuments.php`
  - `/Users/apple/Documents/docbox_staging/sajid/moveFollowup.php`
  - `/Users/apple/Documents/docbox_staging/sajid/server/sajid/index.php`
  - `/Users/apple/Documents/docbox_staging/sajid/testDel.php`
- Local changes:
  - Added shared `sajid/includes/patient_reports_api_guard.php`.
  - Added clearly named functions:
    - `docbox_patient_reports_require_upload_access()` for direct upload, Blueimp temp upload, temp-file move, and report metadata save/Drive-Youtube attach.
    - `docbox_patient_reports_require_delete_access()` for deleting already uploaded report records/local files.
  - Wired upload policy into `uploadDocumentsNew.php`, `insertDocuments.php`, `moveFollowup.php`, and `server/sajid/index.php`.
  - Wired delete policy into `testDel.php`.
  - Moved `db_connect.php` / `db_functions.php` includes in the touched report upload/delete endpoints so database helpers load only after session, CSRF, and helper-type authorization pass.
  - Updated `js/patientReportWeb.js` to hide upload buttons for unsupported helper types, suppress delete buttons for unsupported helper types, and show an access-denied alert if an unsupported helper manually triggers upload/delete actions.
  - Bumped `patientReports.php` cache for `js/patientReportWeb.js` from `v=1.15` to `v=1.16`.
- Verification:
  - `php -l` passed for `sajid/includes/patient_reports_api_guard.php`, `sajid/uploadDocumentsNew.php`, `sajid/insertDocuments.php`, `sajid/moveFollowup.php`, `sajid/server/sajid/index.php`, `sajid/testDel.php`, and `patientReports.php`.
  - Simulated helper type `2` direct upload call returned `PERMISSION_DENIED`.
  - Simulated helper type `2` report metadata/attach call returned `PERMISSION_DENIED` before loading the legacy DB helper.
  - Simulated counsellor helper type `7` delete call returned `PERMISSION_DENIED`.
  - Direct policy probes allowed upload for helper types `1` and `7`, and delete for helper types `8`, `6`, and `a`.
  - JS syntax check could not be run locally because `node` is unavailable in this environment.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientReports.php` to `/home/stagingdocbox/public_html/patientReports.php`
  - `/Users/apple/Documents/docbox_staging/js/patientReportWeb.js` to `/home/stagingdocbox/public_html/js/patientReportWeb.js`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/patient_reports_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/patient_reports_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadDocumentsNew.php` to `/home/stagingdocbox/public_html/sajid/uploadDocumentsNew.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertDocuments.php` to `/home/stagingdocbox/public_html/sajid/insertDocuments.php`
  - `/Users/apple/Documents/docbox_staging/sajid/moveFollowup.php` to `/home/stagingdocbox/public_html/sajid/moveFollowup.php`
  - `/Users/apple/Documents/docbox_staging/sajid/server/sajid/index.php` to `/home/stagingdocbox/public_html/sajid/server/sajid/index.php`
  - `/Users/apple/Documents/docbox_staging/sajid/testDel.php` to `/home/stagingdocbox/public_html/sajid/testDel.php`

## 2026-05-15 Rectify Test VS dilatation action helper-type policy

- User requested that only Doctor, Clinical Staff, Admin, and Super Admin should be able to start dilatation.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/startDilation.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php`
- Policy:
  - Start/stop dilatation allowed helper types: Doctor `8`, Clinical Staff `1`, Admin `6`, Super Admin `a`.
- Local changes:
  - Added `docbox_rectify_require_dilation_access()` in `sajid/includes/rectify_api_guard.php`.
  - Updated `sajid/startDilation.php` to use the shared Rectify bootstrap and dilatation helper-type guard before loading legacy DB functions.
  - `startDilation.php` now validates doctor id, patient id, medicine text, status `0/1`, staff text, and patient ownership before calling the existing start/stop DB functions.
  - Initial button-level access-denied checks were removed after sync feedback that the Rectify HTML was not loading; the restriction remains enforced on the API endpoint.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `patientInfo_oph_rectify_test_vs.js?v=40.32` to `v=40.34` to restore the startup JS path while keeping the server-side guard.
- Verification:
  - `php -l` passed for `sajid/includes/rectify_api_guard.php`, `sajid/startDilation.php`, and `patientInfo_oph_rectify_test_vs.html`.
  - Simulated helper type `2` POST to `startDilation.php` returned `PERMISSION_DENIED` before DB work.
  - Direct dilatation policy probes allowed helper types `1`, `8`, `6`, and `a`.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference, so no JS syntax error was found locally; `node` is unavailable in this environment.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-15 Rectify Test VS book appointment helper-type policy

- User requested Book Appointment access only for Non Clinical Staff, Doctor, Admin, Super Admin, and Counsellor. Unsupported helpers should see the block immediately on click.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/bookAppointmentStage.php`
  - `/Users/apple/Documents/docbox_staging/sajid/bookAppointmentWithCustomETA.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php`
- Policy:
  - Book Appointment allowed helper types: Non Clinical Staff `2`, Doctor `8`, Admin `6`, Super Admin `a`, Counsellor `7`.
- Local changes:
  - Added `docbox_rectify_require_appointment_booking_access()` in `sajid/includes/rectify_api_guard.php`.
  - Updated `.giveAppointment`, `.finalBook`, and `.finalBookOld` handlers in `js/patientInfo_oph_rectify_test_vs.js` to immediately alert and return before opening the modal or posting APIs for unsupported helper types.
  - Alert text: `You are not authorised to book appointment. Please contact your Administrator`.
  - Added server-side helper-type guard to `sajid/bookAppointmentStage.php`.
  - Added server-side helper-type guard to `sajid/bookAppointmentWithCustomETA.php` and moved legacy `db_functions.php` loading after the guard.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.36`.
- Verification:
  - `php -l` passed for `sajid/includes/rectify_api_guard.php`, `sajid/bookAppointmentStage.php`, `sajid/bookAppointmentWithCustomETA.php`, and `patientInfo_oph_rectify_test_vs.html`.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
  - Simulated helper type `1` POST to `bookAppointmentStage.php` returned `PERMISSION_DENIED`.
  - Simulated helper type `1` POST to `bookAppointmentWithCustomETA.php` returned `PERMISSION_DENIED`.
  - Direct booking policy probes allowed helper types `2`, `7`, `8`, `6`, and `a`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/bookAppointmentStage.php` to `/home/stagingdocbox/public_html/sajid/bookAppointmentStage.php`
  - `/Users/apple/Documents/docbox_staging/sajid/bookAppointmentWithCustomETA.php` to `/home/stagingdocbox/public_html/sajid/bookAppointmentWithCustomETA.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`

## 2026-05-15 Rectify Test VS billing button helper-type policy

- User requested Billing button access only for Non Clinical Staff, Admin, Super Admin, and Counsellor. Unsupported helpers should see an immediate error on click.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
- Policy:
  - Billing button allowed helper types: Non Clinical Staff `2`, Admin `6`, Super Admin `a`, Counsellor `7`.
- Local changes:
  - Added an immediate `.addReceipt` click check using `docboxRectifyHasAnyHelperType(['2', '6', 'a', '7'])`.
  - Alert text: `You are not authorised to access billing. Please contact your Administrator`.
  - The handler returns before stage-save calls or Billing UI setup for unsupported helper types.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.37`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-15 Rectify Test VS Google Feedback and Edit button helper-type policy

- User requested the same helper-type click restriction for Google Feedback and Edit as Billing.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
- Policy:
  - Google Feedback and Edit allowed helper types: Non Clinical Staff `2`, Admin `6`, Super Admin `a`, Counsellor `7`.
- Local changes:
  - Added an immediate `.sendMessage` click check using `docboxRectifyHasAnyHelperType(['2', '6', 'a', '7'])`.
  - Added the same check inside `.sendMessageFinal` so direct modal send is also blocked.
  - Replaced the top Edit button inline `onclick` with class `editPatientButton`.
  - Added `.editPatientButton` click handler that blocks unsupported helpers before navigating to `editPatient.php`.
  - Alert text:
    - `You are not authorised to use Google Feedback. Please contact your Administrator`
    - `You are not authorised to edit patient. Please contact your Administrator`
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.38`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

Follow-up page-load hotfix:

- User reported the page was not loading after the first Google Feedback/Edit click-guard pass.
- Live staging checks showed:
  - `patientInfo_oph_rectify_test_vs.html` returned HTTP 200.
  - `js/patientInfo_oph_rectify_test_vs.js?v=40.38` returned HTTP 200.
- Local hotfix:
  - Removed the Google Feedback/Edit click guards from the large `js/patientInfo_oph_rectify_test_vs.js` file.
  - Restored the Edit button to inline navigation with a small inline guard in `patientInfo_oph_rectify_test_vs.html`.
  - Added small inline helper functions in the HTML header button area:
    - `docboxRectifyHeaderLimitedActionAllowed()`
    - `docboxRectifyBlockHeaderAction(event, actionName)`
  - Added inline guarded click blocks to Google Feedback open, Google Feedback Send, and Edit.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.39`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

Second page-load hotfix:

- User reported the page was still not loading.
- Local change:
  - Removed the inline Google Feedback/Edit guard script from `patientInfo_oph_rectify_test_vs.html`.
  - Restored Google Feedback and Edit buttons to their previous simple markup.
  - Removed the inline guard from `.sendMessageFinal`.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.40`.
- Current status:
  - Google Feedback/Edit helper-type restriction is temporarily removed to restore page load.
  - Billing, Book Appointment, Dilatation, and server-side API guards from previous passes remain in place.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Scan confirms `docboxRectifyBlockHeaderAction` and `docboxRectifyHeaderLimitedActionAllowed` no longer exist in the page.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## 2026-05-15 Rectify Test VS Google Feedback click restriction re-applied safely

- User confirmed the page loads and asked to apply Google Feedback restriction first, carefully.
- Active page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
- Policy:
  - Google Feedback allowed helper types: Non Clinical Staff `2`, Admin `6`, Super Admin `a`, Counsellor `7`.
- Local change:
  - Added only one small guard at the top of the existing `.sendMessage` click handler.
  - Did not touch Edit.
  - Did not add inline HTML scripts.
  - Did not alter `.sendMessageFinal` in this pass.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.41`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
  - Scan confirms the previous inline `docboxRectifyBlockHeaderAction` and `editPatientButton` changes are not present.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/startDilation.php` to `/home/stagingdocbox/public_html/sajid/startDilation.php`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`

## 2026-05-15 Rectify Test VS Edit click restriction added safely

- User requested applying the same header access rule to Edit after Google Feedback was re-applied separately.
- Page:
  - Rectify Test VS: `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Added class `editPatientRestricted` to the active top Edit button and replaced the inline `onclick` navigation with `data-target-page="editPatient.php"`.
  - Added a small existing-handler style click guard in `js/patientInfo_oph_rectify_test_vs.js`.
  - Edit now allows helper types `2`, `6`, `a`, and `7` only.
  - Unsupported helpers immediately see `You are not authorised to edit patient. Please contact your Administrator`.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `js/patientInfo_oph_rectify_test_vs.js?v=40.42`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the Rectify JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
  - Scan confirms the previous inline `docboxRectifyBlockHeaderAction` and `editPatientButton` changes are not present.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-15 Profile page access review started

- User moved the helper-type access-control review to Profile page.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Files opened for analysis:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profile.js`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/profile_api_helpers.php`
- Current findings:
  - `profile.php` currently starts as plain HTML and has no PHP page-level session/helper guard before rendering.
  - `js/profile.js` has an active client-side page guard that allows the main admin/blank helper or helper type `s` Settings Access.
  - Older commented frontend logic allowed helper types `6`, `a`, and blank admin.
  - Many Profile APIs are already hardened for PHP session, CSRF, doctor/center scoping, and prepared SQL, but tracker rows still mark section-level helper-type action policy as pending for multiple Profile settings areas.
- Suggested first Profile pass:
  - Add a PHP page-level guard to `profile.php`.
  - Normalize the UI rule to allow Admin `6`, Super Admin `a`, and Settings Access `s`.
  - Then convert individual Profile settings API batches from generic session-only `docbox_profile_require_post_session()` to explicit helper-type rules section by section.

## 2026-05-15 Profile page level helper-type guard added

- User confirmed that only Admin, Super Admin, and Settings Access users should be able to open Profile page.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profile.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Added PHP page-level guard before any Profile HTML is rendered.
  - Server allowed helper types: Admin `6`, Super Admin `a`, Settings Access `s`.
  - Restricted helper types receive HTTP 403 Permission denied HTML.
  - Updated the existing frontend guard to use the same helper-type rule and clearer Profile Settings alert.
  - Bumped Profile page script from `js/profile.js?v=2.17` to `v=2.18`.
- Verification:
  - `php -l profile.php` passed.
  - `php -l js/profile.js` passed as a PHP-token sanity check.
  - Static scan confirms `profile.php` checks `docbox_session_has_helper_type(array('6', 'a', 's'))`.
  - Static scan confirms `profile.php` loads `js/profile.js?v=2.18`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profile.js` to `/home/stagingdocbox/public_html/js/profile.js`

## 2026-05-15 Profile tab UI restriction inventory

- User asked to list Profile tabs/functions already restricted at UI level so they can be migrated to server-side helper-type policies.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Files reviewed:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profile.js`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_procedure_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/staffManagementHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/profileIPDHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/appointmentHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/commissionSettingHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/dischargeCardSettingHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/dischargeInstructionsSettings.js`
- Existing UI restrictions found:
  - Profile page open: now server and UI allow Admin `6`, Super Admin `a`, Settings Access `s`.
  - User Management tab/open/add/list/save: UI allows only `6` or `a`; matching endpoints `getAllStaffDetails.php`, `insertStaff.php`, `updateStaff.php`, and `registerHelper.php` already use `docbox_profile_require_post_session(array('6', 'a'))`.
  - Doctor Management tab/open/add/list/save: UI allows only `6` or `a`; newer endpoints `getAllVisitingDoctorsProfile.php`, `insertVisitingDoctorProfile.php`, `updateVisitingDoctorProfile.php` already use `docbox_profile_require_post_session(array('6', 'a'))`.
  - Pharmacy stock quantity negative adjustment: UI allows Super Admin `a`, Pharmacy Stock Deletion `pd`, or main admin; server-side equivalent still needs explicit policy on the stock adjustment endpoint.
- Areas not found with specific UI helper-type checks beyond page-level Profile access:
  - Personal Details / Hospital Details save.
  - Particulars add/edit/delete.
  - IPD Ward add/edit/delete.
  - Pharmacy item add/edit/delete/search/report.
  - IOL Register add/delete/report.
  - Appointment settings save.
  - Commission settings save.
  - Templates add/delete/update.
  - Discharge card field settings.
  - Discharge instruction settings.
- Notes:
  - Several Profile endpoints already have session, CSRF, doctor scoping, input validation, and prepared SQL, but their section-level helper-type rules remain marked pending in `secured_api_tracking.md`.
  - Legacy visiting doctor endpoints `insertVisitingDoctor.php` and `deleteVisitingDoctor.php` are still tracked as helper-type pending even though the newer Doctor Management endpoints are already `6`/`a`.

## 2026-05-15 Profile tab server guard clarification

- User asked which Profile tab areas are already server guarded.
- Clarification:
  - Server guarded for session/CSRF/doctor scope: most previously hardened Profile APIs.
  - Server guarded with explicit helper-type policy: currently limited to Profile page open, Staff/User Management, newer Doctor Management, Attendance Machine link, and helper registration/upload paths already carrying required helper arrays.
- Explicit helper-type guards confirmed by scan:
  - `profile.php`: `6`, `a`, `s`.
  - `sajid/getAllStaffDetails.php`: `6`, `a`.
  - `sajid/insertStaff.php`: `6`, `a`.
  - `sajid/updateStaff.php`: `6`, `a`.
  - `sajid/registerHelper.php`: `6`, `a`.
  - `sajid/getAllVisitingDoctorsProfile.php`: `6`, `a`.
  - `sajid/insertVisitingDoctorProfile.php`: `6`, `a`.
  - `sajid/updateVisitingDoctorProfile.php`: `6`, `a`.
  - `sajid/uploadFromHTML.php`: `6`, `a`, `s` but active Profile watermark UI was already removed.
- Explicit helper-type policy still pending for the other listed Profile tabs/functions.

## 2026-05-15 Profile Pharmacy Inventory delete server helper-type guard

- User requested a server-side restriction for deleting any Pharmacy Inventory item.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- API secured:
  - `/Users/apple/Documents/docbox_staging/sajid/deletePharmItem.php`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/sajid/deletePharmItem.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Changed `deletePharmItem.php` from generic session-only `docbox_profile_require_post_session()` to `docbox_profile_require_post_session(array('6', 'a', 'pd'))`.
  - Deleting a pharmacy inventory item is now server-allowed only for Admin `6`, Super Admin `a`, or Pharmacy Stock Deletion Access `pd`.
  - Existing session, CSRF, doctor scoping, item ownership check, and prepared update/log SQL remain in place.
- Verification:
  - `php -l sajid/deletePharmItem.php` passed.
  - Static scan confirms `deletePharmItem.php` uses `docbox_profile_require_post_session(array('6', 'a', 'pd'))`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/deletePharmItem.php` to `/home/stagingdocbox/public_html/sajid/deletePharmItem.php`

## 2026-05-15 Profile Pharmacy Inventory delete UI warning added

- User reported no warning was shown after the server-side delete restriction.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Added `canDeletePharmacyInventoryItem()` in `js/profileHelper.js`.
  - `.deletePharmItem` now shows an immediate alert before confirmation/API call for unsupported helpers.
  - Allowed UI delete helper types match the server policy: Admin `6`, Super Admin `a`, Pharmacy Stock Deletion Access `pd`, plus the main admin/blank-helper session.
  - Hardened the delete API callback/fail path so a server `PERMISSION_DENIED` response shows the server message instead of silently failing.
  - Bumped `profile.php` from `js/profileHelper.js?v=1.18` to `v=1.19`.
- Verification:
  - `php -l profile.php` passed.
  - `php -l js/profileHelper.js` passed as a PHP-token sanity check.
  - JavaScriptCore parsed `js/profileHelper.js` and stopped only at the expected browser-runtime `document` reference.
  - Static scan confirms `profile.php` loads `js/profileHelper.js?v=1.19`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js` to `/home/stagingdocbox/public_html/js/profileHelper.js`

## 2026-05-15 Profile IOL Register helper-type guard

- User requested the Profile IOL Register tab/API access be restricted to Doctor, Admin, Super Admin, and Counsellor only, with unsupported helpers blocked before opening the tab.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - `/Users/apple/Documents/docbox_staging/sajid/getIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/IOLReport.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Added `iolRegisterTab` class to the IOL Register tab link.
  - Added `canAccessIolRegister()` and `showIolRegisterAccessDenied()` in `js/profilePharmacyHelper.js`.
  - IOL Register tab click, search, add, report, and delete actions now immediately block unsupported helpers with an alert.
  - Server helper-type rule added to `getIOLData.php`, `insertIOLData.php`, `deleteIOLData.php`, and `IOLReport.php`: Doctor `8`, Admin `6`, Super Admin `a`, Counsellor `7`.
  - Bumped `profile.php` from `js/profilePharmacyHelper.js?v=1.38` to `v=1.39`.
- Verification:
  - `php -l profile.php` passed.
  - `php -l js/profilePharmacyHelper.js` passed as a PHP-token sanity check.
  - `php -l` passed for `getIOLData.php`, `insertIOLData.php`, `deleteIOLData.php`, and `IOLReport.php`.
  - JavaScriptCore parsed `js/profilePharmacyHelper.js` and stopped only at the expected browser-runtime `document` reference.
  - Static scan confirms all four IOL endpoints use `docbox_profile_require_post_session(array('8', '6', 'a', '7'))`.
  - Static scan confirms `profile.php` loads `js/profilePharmacyHelper.js?v=1.39`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js` to `/home/stagingdocbox/public_html/js/profilePharmacyHelper.js`
  - `/Users/apple/Documents/docbox_staging/sajid/getIOLData.php` to `/home/stagingdocbox/public_html/sajid/getIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertIOLData.php` to `/home/stagingdocbox/public_html/sajid/insertIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteIOLData.php` to `/home/stagingdocbox/public_html/sajid/deleteIOLData.php`
  - `/Users/apple/Documents/docbox_staging/sajid/IOLReport.php` to `/home/stagingdocbox/public_html/sajid/IOLReport.php`

## 2026-05-15 Profile Particulars delete helper-type guard

- User requested delete in the Profile Particular tab OPD/IPD inventory item list be allowed only for Admin and Super Admin.
- Page:
  - Profile Settings: `/Users/apple/Documents/docbox_staging/profile.php`
- Updated files:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteProcedure.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Change made:
  - Added `canDeleteParticularInventoryItem()` in `js/profileHelper.js`.
  - `.deleteprocedure` now immediately blocks unsupported helpers before the confirm/API call.
  - `deleteProcedure.php` now uses `docbox_profile_require_post_session(array('6', 'a'))`.
  - Delete is server-allowed only for Admin `6` or Super Admin `a` (blank main-admin session is still normalized by shared auth).
  - Delete API failure path now surfaces server permission messages.
  - Bumped `profile.php` from `js/profileHelper.js?v=1.19` to `v=1.20`.
- Verification:
  - `php -l profile.php` passed.
  - `php -l js/profileHelper.js` passed as a PHP-token sanity check.
  - `php -l sajid/deleteProcedure.php` passed.
  - JavaScriptCore parsed `js/profileHelper.js` and stopped only at the expected browser-runtime `document` reference.
  - Static scan confirms `deleteProcedure.php` uses `docbox_profile_require_post_session(array('6', 'a'))`.
  - Static scan confirms `profile.php` loads `js/profileHelper.js?v=1.20`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js` to `/home/stagingdocbox/public_html/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteProcedure.php` to `/home/stagingdocbox/public_html/sajid/deleteProcedure.php`

## 2026-05-16 Terminology preference for Profile/API control review

- User clarified again that they are the owner of the code and the staging application.
- Use practical engineering wording for this work:
  - Helper-type access control.
  - Server-side API authorization.
  - Session, CSRF, doctor/hospital scoping.
  - Profile page control review.
  - Remaining API hardening checklist.
- Avoid threat-style wording in responses unless discussing a concrete implementation behavior.
- User asked to analyse whether the Profile page APIs are fully covered according to OWASP/SANS-style control categories; continue that as a control checklist, not as a threat accusation.
- No application code changed in this note.

## 2026-05-16 Remaining Profile API hardening checklist

- User asked which Profile API hardening items are still left.
- Current status summary:
  - Profile page-level access is guarded for Admin `6`, Super Admin `a`, Settings Access `s`.
  - User Management and newer Doctor Management endpoints already have explicit `6`/`a` helper-type guards.
  - IOL Register endpoints now have explicit `8`/`6`/`a`/`7` helper-type guards.
  - Particulars delete now has explicit `6`/`a` helper-type guard.
  - Pharmacy inventory item delete now has explicit `6`/`a`/`pd` helper-type guard.
  - Remaining Profile endpoints below already have session/CSRF/doctor-scope work in most cases, but still need explicit section-level helper-type policy or a final decision that the page-level rule is enough.
- Remaining section-level helper-type API policies:
  - Core Profile/Hospital settings:
    - `sajid/updateHospitalDetail.php`
    - `sajid/updateMiscPrefs.php`
    - `sajid/updateDoctor.php`
  - Legacy visiting-doctor settings path:
    - `sajid/insertVisitingDoctor.php`
    - `sajid/deleteVisitingDoctor.php`
  - Appointment settings:
    - `sajid/getAppointmentSettings.php`
    - `sajid/saveAppointmentSettings.php`
  - Commission settings:
    - `sajid/getdoctorProcedureCommissionSettings.php`
    - `sajid/savedoctorProcedureCommissionSettings.php`
  - Discharge card field settings:
    - `sajid/getAllDischargeCardFields.php`
    - `sajid/saveDischargeCardFieldSetting.php`
  - Discharge instruction settings:
    - `sajid/getDischargeInstructionsHospital.php`
    - `sajid/saveDischargeInstructionsHospital.php`
  - Particulars add/edit/package/read/search:
    - `sajid/getProcedureDetailsProfile.php`
    - `sajid/getProcedureDetailsProfileSearch.php`
    - `sajid/saveProcedures.php`
    - `sajid/editProcedure.php`
    - `sajid/saveProceduresPackage.php`
    - Delete is already guarded by `sajid/deleteProcedure.php`.
  - IPD ward settings:
    - `sajid/getIpdDetails.php`
    - `sajid/saveWards.php`
    - `sajid/editWards.php`
    - `sajid/deleteWard.php`
  - Pharmacy inventory add/edit/stock/read/search/history:
    - `sajid/savePharmItem.php`
    - `sajid/editPharm.php`
    - `sajid/addPharmStock.php`
    - `sajid/getPharmDetailsPagination.php`
    - `sajid/getPharmDetailSearch.php`
    - `sajid/getPharmHistory.php`
    - Delete is already guarded by `sajid/deletePharmItem.php`.
  - Shop/pharmacy reports and shop edit:
    - `sajid/getShopDetailsPagination.php`
    - `sajid/editShopItem.php`
    - `sajid/getPharmSupplierReport.php`
    - `sajid/supplierReport.php`
    - `sajid/newPharmReport.php`
    - `sajid/shopReport.php`
    - `sajid/OtStockReport.php`
  - Template / medicine-template settings:
    - `sajid/addTemplatesLvl3.php`
    - `sajid/updateTemplates.php`
    - `sajid/deleteTemplates.php`
    - `sajid/deleteTemplatesLvl2.php`
    - `sajid/getTemplatesLvl2Details.php`
    - `sajid/getAllTemplatesLvl2.php`
    - `sajid/addTemplatesLvl2.php`
    - `sajid/addDiagnosisMedTemplateLvl2.php`
    - `sajid/getAllDiagnosisTemplatesLvl2.php`
    - `sajid/addDetailedExamSuggestions.php`
    - `sajid/getDeytailedExamSuggestionsLocal.php`
    - `sajid/deleteMedicineGroupMappings.php`
    - `sajid/getMedicineGroupMappings.php`
    - `sajid/deleteMedicineGroup.php`
    - `sajid/getMedicineGroups.php`
    - `sajid/deleteMedicineCatagory.php`
    - `sajid/getMedicineCatagory.php`
    - `sajid/saveMedicineGroupMapping.php`
    - `sajid/saveMedicineGroupName.php`
    - `sajid/saveMedicineCatagory.php`
    - `sajid/getPreOpMedicine.php`
    - `sajid/deletePreOpMedicine.php`
    - `sajid/savePreOpMedicine.php`
  - Subscription/profile account settings:
    - `sajid/fetchDoctorSubscriptionDetails.php`
    - `sajid/saveActivationCodeSubscription.php`
    - `sajid/registerHelper.php` is already `6`/`a`.
    - `sajid/uploadFromHTML.php` is already `6`/`a`/`s`, and the active Profile watermark UI was removed.
- Suggested order:
  - Next batch: Core Profile/Hospital settings plus Appointment/Commission/Discharge settings, likely same allowed helper types as Profile page: `6`, `a`, `s`.
  - Then IPD wards and remaining Particulars add/edit/package.
  - Then Pharmacy/Shop non-delete actions.
  - Then Templates/medicine-template settings.
- No application code changed in this note.

## 2026-05-16 Particulars helper-type policy decision

- User clarified that in the Profile Particulars tab, only delete should be helper-type restricted.
- Policy decision:
  - `sajid/deleteProcedure.php`: restricted to Admin `6` and Super Admin `a`.
  - `sajid/getProcedureDetailsProfile.php`: no extra helper-type restriction required beyond session/CSRF/doctor scope.
  - `sajid/getProcedureDetailsProfileSearch.php`: no extra helper-type restriction required beyond session/CSRF/doctor scope.
  - `sajid/saveProcedures.php`: no extra helper-type restriction required beyond session/CSRF/doctor scope.
  - `sajid/editProcedure.php`: no extra helper-type restriction required beyond session/CSRF/doctor scope.
  - `sajid/saveProceduresPackage.php`: no extra helper-type restriction required beyond session/CSRF/doctor scope.
- Note:
  - Profile page itself still has a page-level guard for Admin `6`, Super Admin `a`, and Settings Access `s`.
  - This means these non-delete Particulars APIs remain generally available to authenticated/session-valid Profile users unless a future policy changes.
- No application code changed in this note.

## 2026-05-16 init.js helper-type access-control analysis

- User asked to check `js/init.js` because it also has helper-type level access control.
- File reviewed:
  - `/Users/apple/Documents/docbox_staging/js/init.js`
- Pages:
  - Shared across many pages that load `js/init.js`, including Profile Settings `/Users/apple/Documents/docbox_staging/profile.php`, Expenses `/Users/apple/Documents/docbox_staging/expenses.php`, Financial Summary `/Users/apple/Documents/docbox_staging/financialSummary.php`, Add Patient `/Users/apple/Documents/docbox_staging/addPatient.php`, IPD `/Users/apple/Documents/docbox_staging/IPD.php`, Patient Reports `/Users/apple/Documents/docbox_staging/patientReports.php`, Rectify Test VS `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`, and related staging/test pages.
- What `init.js` currently controls:
  - Adds global `X-DocBox-CSRF` header to jQuery AJAX calls from `localStorage.csrfToken`.
  - Shows common session/CSRF warning alerts through `docboxShowSessionWarning()`.
  - Builds the sidebar menu from `localStorage.HelperTypeID` and `localStorage.HelperName`.
  - Redirects `.personalInfo` click to `profile.php`.
- Helper-type menu rules found:
  - Main admin / blank helper or `HelperName == vibheeshan`: gets a hard-coded admin-style menu.
  - Clinical Staff `1`: bitmask `361`.
  - Admin `6`: bitmask `511`.
  - Doctor `8`: bitmask `365`.
  - Non Clinical Staff `2`: bitmask `373`.
  - Counsellor `7`: bitmask `365`.
  - Financial Access `9`: bitmask `16`.
  - Default bitmask `97` is OR-ed into all helper menus.
- Important findings:
  - These are UI/sidebar visibility controls only. They do not secure pages or APIs by themselves.
  - No explicit `s` Settings Access menu rule was found, even though `profile.php` page-level guard now allows `s`.
  - No explicit `pd` Pharmacy Stock Deletion Access menu rule was found.
  - Some pages shown/hidden by `init.js` already have server page/API guards from previous work; others should be judged by their own page/API controls, not by sidebar visibility.
  - `HelperTypeID` is read from `localStorage`; if it is missing, some `.includes()` calls can fail unless login always initializes it.
  - There are active `console.log()` calls for helper/menu values in `init.js` that can be cleaned later.
- No application code changed in this note.

Follow-up click-level block:

- User clarified the block should trigger as soon as an unsupported helper clicks the dilatation button.
- Local change:
  - Added a small inline `docboxRectifyHasAnyHelperType(['8', '6', 'a', '1'])` check inside the existing `.startDilation` click handler.
  - Added the same check inside `.startDilationFinal` so direct modal start is also blocked.
  - Alert text: `You are not authorised to start dilatation. Please contact your Administrator`.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to `patientInfo_oph_rectify_test_vs.js?v=40.35`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - JavaScriptCore parsed the JS and stopped only at the expected browser-runtime `document` reference; no syntax error was found before runtime execution.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-14 Rectify Test VS localStorage restriction analysis

- User asked to analyze Rectify Test VS and identify already-existing restrictions based on browser localStorage before the next hardening pass.
- Pages/files reviewed:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md`
- Active page wiring:
  - `patientInfo_oph_rectify_test_vs.html` loads `js/init.js?v=3.6`.
  - `patientInfo_oph_rectify_test_vs.html` loads `js/patientInfo_oph_rectify_test_vs.js?v=40.20`.
- Existing localStorage-based restrictions found in `js/patientInfo_oph_rectify_test_vs.js`:
  - `HelperTypeID` containing `8` shows `.onlineConsult`; other helper types hide it.
  - For selected `CustomerId` values, `.sendToCounsellor` is visible only for helper type `7`, type `6`, or blank/admin helper type.
  - Logged-in non-admin helpers have billing/procedure controls reduced:
    - helper types `2`, `1`, `5`, `4` lose `.removeProcedure`, `.printPaymentReceipt`, `.deleteProfile`, and `#paidAmount` becomes readonly unless explicitly exempted by type `6` or the type `8` plus customer `514` case.
    - other non-admin helper types lose `.deleteProfile` and `#paidAmount` becomes readonly.
  - Re-rendered receipt rows remove `.removeProcedure` for helper types `2` or `1` when not also type `8`, `6`, or `3`.
  - `updatePatientAge()` redirects to `editPatient.php` only for helper types `2`, `6`, or `a`, excluding type `8`.
  - Payment date override UI is hidden unless helper type contains `a`.
  - Template/follow-up open/copy actions alert and stop when helper type does not contain `1`, unless admin/blank.
  - Visit deletion is allowed by UI only for helper type `6`, `8`, `a`, or blank/admin.
  - Payment log delete button is shown for admin/blank, non-doctor helper types, or helper type `a`; doctor type `8` without `a` hides it.
  - Advised investigation/surgery create/delete actions are allowed by UI only for helper type `8` or blank/admin.
- Security conclusion:
  - These are client-side UI restrictions only because they trust `localStorage.HelperTypeID` / `HelperName`.
  - They should be treated as hints for server-side action policies, not as real authorization.
  - Existing tracker rows show many Rectify Test VS APIs already have session, CSRF, and doctor/patient binding, but helper-type action policies remain pending in several areas.
- No application code was changed in this analysis pass.

## 2026-05-14 Rectify Test VS server-side restriction conversion checklist

- User clarified the current request is only to list localStorage rules as server-side conversion targets, not to keep flagging the staging risk.
- Conversion targets from existing UI rules:
  - Online/video consult credentials:
    - Current UI rule: helper type `8` can see online consult.
    - Server target: `sajid/getVideoOPDCredentials.php`.
  - Send to counsellor:
    - Current UI rule: selected customer ids only; helper types `7`, `6`, or blank/admin can see/send.
    - Rectify Test VS hardcoded visible `CustomerId` list: `10001`, `1170`, `683`, `1175`, `1190`.
    - Broader counsellor feature config files also contain longer allowed-doctor lists, but the Rectify Test VS `.sendToCounsellor` button currently uses the five-id hardcoded list above.
    - Server targets: `sajid/sendToCounsellorListManual.php`, plus the existing counsellor/pool/booking endpoints used by the modal flow.
  - Delete patient/profile:
    - Current UI rule: `.deleteProfile` is removed for most non-admin helpers.
    - Server target: `sajid/updatePatient.php` when called from `.deleteProfile`.
  - Procedure removal:
    - Current UI rule: `.removeProcedure` is removed for helper types `2`, `1`, `5`, `4` unless exempted; re-rendered rows also remove it for types `2` or `1` unless also `8`, `6`, or `3`.
    - Server targets: `sajid/deletePatientProcedure.php`, `sajid/deletePatientProcedurePharmacy.php`.
  - Procedure/billing add or update:
    - Current UI rule: `#paidAmount`, procedure controls, and billing controls are reduced for non-admin helpers.
    - Server targets: `sajid/savePatientProcedures.php`, `sajid/savePatientPharmacyProcedures.php`, `sajid/savePatientPaymentDetails.php`, `sajid/insertPatientPaymentLog.php`, `sajid/insertCustomPatientPaymentLog.php`.
  - Payment date override:
    - Current UI rule: payment date picker is hidden unless helper type contains `a`.
    - Server targets: `sajid/insertCustomPatientPaymentLog.php`, and any payment save endpoint accepting a client-supplied timestamp/date.
  - Payment log delete:
    - Current UI rule: delete button is shown for admin/blank, non-doctor helper types, or helper type `a`; doctor type `8` without `a` hides delete.
    - Server target: `sajid/deletePatientPaymentLog.php`.
  - Patient age edit redirect:
    - Current UI rule: only helper types `2`, `6`, or `a`, excluding `8`, can go to `editPatient.php`.
    - Server target: `editPatient.php` page guard plus patient update endpoints used by that page.
  - Template/follow-up open or copy from template:
    - Current UI rule: helper type must contain `1` or be blank/admin.
    - Server targets: `sajid/addFollowupFromTemplate.php`, `sajid/updateVisitFromTemplate.php`.
  - Follow-up/visit delete:
    - Current UI rule: helper types `6`, `8`, `a`, or blank/admin can delete visits.
    - Server target: `sajid/deleteFollowup.php`.
  - Clinical visit open/workup:
    - Current UI rule: helper type must contain `1` or be blank/admin for multiple follow-up/open-workup actions.
    - Server targets: existing visit-read/write APIs touched by Rectify Test VS, especially `sajid/getPatientVisitDoctor.php`, `sajid/getPatientMedications.php`, `sajid/getAllVisitDiagnosis.php`, `sajid/insertFollowUp.php`, `sajid/insertOtherFollowUp.php`.
  - Advised investigation/surgery create/delete:
    - Current UI rule: helper type `8` or blank/admin can create/delete advised investigation/surgery.
    - Server targets: `sajid/saveInvestigation.php`, `sajid/saveAdvisedSurgeryNew.php`, `sajid/deleteAdvisedInvestigation.php`, `sajid/deleteAdvisedSurgery.php`.
  - Investigation attachment upload:
    - Current UI rule is adjacent to doctor-only advised investigation/surgery actions.
    - Server target: `sajid/uploadInvestigationAttachment.php`.
- No application code was changed in this checklist pass.

## 2026-05-14 Rectify Test VS Send to Counsellor server guard

- User asked to secure the Rectify Test VS `Send To Counsellor` action on the server.
- Local change:
  - `sajid/sendToCounsellorListManual.php` now enforces the existing page rule server-side before opening the DB connection.
  - Allowed hospital/customer ids: `10001`, `1170`, `683`, `1175`, `1190`.
  - Allowed helper types: `6`, `7`, or `a`/blank-admin normalization through `docbox_session_has_helper_type()`.
  - Unauthorized hospital/helper combinations return 403 JSON `PERMISSION_DENIED`.
  - Existing session auth, CSRF, doctor-session match, patient ownership, surgery ownership, visiting-doctor validation, and prepared SQL insert paths remain in place.
- Verification:
  - `php -l sajid/sendToCounsellorListManual.php` passed.
  - Simulated helper type `1` for allowed hospital `1170` returned `PERMISSION_DENIED`.
  - Simulated helper type `6` for non-allowed hospital `9999` returned `PERMISSION_DENIED`.
  - Simulated blank/admin-style helper for allowed hospital `1170` passed the new policy and then stopped at local DB connection because DB access is unavailable in the sandbox.
  - Local CLI probes emitted existing PHPMailer deprecation warnings under PHP 8.5 before JSON output; not changed in this pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/sendToCounsellorListManual.php` to `/home/stagingdocbox/public_html/sajid/sendToCounsellorListManual.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

## 2026-05-14 Rectify Test VS remaining helper-access checklist

- User asked for a remaining checklist of Rectify Test VS helper-access rules that still need server-side conversion after `sendToCounsellorListManual.php` was guarded.
- Page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
- Done:
  - `Send To Counsellor` manual action: `sajid/sendToCounsellorListManual.php`.
  - `Online/video consult credentials`: `sajid/getVideoOPDCredentials.php`.
  - `Visit create/open restrictions`: `sajid/insertFollowUp.php`, `sajid/insertOtherFollowUp.php`, `sajid/addFollowupFromTemplate.php`, `sajid/updateVisitFromTemplate.php`, `sajid/getPatientVisitDoctor.php`, `sajid/getPatientMedications.php`, `sajid/getAllVisitDiagnosis.php`.
  - `Advised surgery/investigation actions`: `sajid/saveInvestigation.php`, `sajid/saveAdvisedSurgeryNew.php`, `sajid/deleteAdvisedInvestigation.php`, `sajid/deleteAdvisedSurgery.php`, `sajid/uploadInvestigationAttachment.php`.
- Remaining checklist:
  - Add/update procedures and billing:
    - Rule: billing/procedure controls reduced for non-admin helpers.
    - Endpoints: `sajid/savePatientProcedures.php`, `sajid/savePatientPharmacyProcedures.php`, `sajid/savePatientPaymentDetails.php`, `sajid/insertPatientPaymentLog.php`.
  - Payment date override:
    - Rule: helper type `a`.
    - Endpoint: `sajid/insertCustomPatientPaymentLog.php` and any payment save path accepting a client-supplied timestamp/date.
  - Patient age/edit patient:
    - Rule: helper types `2`, `6`, or `a`, excluding `8`.
    - Targets: `editPatient.php` page guard plus patient update endpoints used by that page.
- No application behavior changed in this checklist update.

## 2026-05-14 Rectify Test VS patient/profile delete guard

- User asked to secure delete so only Admin and Super Admin can delete.
- Scope implemented:
  - Rectify Test VS `.deleteProfile` posts to `sajid/updatePatient.php` with `syncStatus === '3'`.
  - Only this delete/deactivate branch was guarded; normal patient edit/update statuses remain on the existing auth/ownership path.
- Local change:
  - `sajid/updatePatient.php` now checks parsed `usersJSON` before DB connection.
  - If any payload row requests `syncStatus === '3'`, the endpoint requires helper type `6` or `a`.
  - Non-admin helper sessions receive 403 JSON `PERMISSION_DENIED` before DB work.
- Verification:
  - `php -l sajid/updatePatient.php` passed.
  - Simulated helper type `1` delete request returned `PERMISSION_DENIED`.
  - Simulated helper type `6` delete request passed the new helper guard and then stopped at local DB connection, expected in the sandbox.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/updatePatient.php` to `/home/stagingdocbox/public_html/sajid/updatePatient.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

Follow-up delete redirect:

- User asked that after deleting a profile, the flow should redirect to `home_new.php`.
- Local changes:
  - `js/patientInfo_oph_rectify_test_vs.js` now parses the `updatePatient.php` delete response and redirects to `home_new.php` only when `success === true`.
  - Session-expired responses still redirect to `index.php`.
  - Other API failures show the response message and do not redirect.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped the Rectify Test VS script from `v=40.20` to `v=40.21`.
- Verification:
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-14 Rectify Test VS payment-log delete guard

- User asked for payment-log deletion to be usable only by Admin, Super Admin, and users with bill deletion right; everyone else should not be able to access it.
- Local interpretation:
  - Helper type `6`: Admin.
  - Helper type `a`: Super Admin.
  - Helper type `3`: bill deletion right, named `Reception with delete option` in `sajid/includes/api_auth.php`.
- Local changes:
  - `sajid/deletePatientPaymentLog.php` now requires helper type `6`, `a`, or `3` before parsing/deleting payment data.
  - `js/patientInfo_oph_rectify_test_vs.js` now shows `.deletePaymentLog` only for admin/blank UI sessions or helper types `6`, `a`, or `3`.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.21` to `v=40.22`.
- Verification:
  - `php -l sajid/deletePatientPaymentLog.php` passed.
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Simulated helper type `1` delete-payment request returned `PERMISSION_DENIED`.
  - Simulated helper type `3` request passed the new helper guard and then stopped at local DB connection, expected in the sandbox.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/deletePatientPaymentLog.php` to `/home/stagingdocbox/public_html/sajid/deletePatientPaymentLog.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

## 2026-05-14 Rectify Test VS procedure-removal guards

- User approved securing remove-procedure/delete item actions with the same billing delete policy.
- Local policy:
  - Helper type `6`: Admin.
  - Helper type `a`: Super Admin.
  - Helper type `3`: bill deletion right / Reception with delete option.
- Local changes:
  - `sajid/deletePatientProcedure.php` now requires helper type `6`, `a`, or `3` before accepting `procedureJSON`.
  - `sajid/deletePatientProcedurePharmacy.php` now requires helper type `6`, `a`, or `3` before accepting `procedureJSON`.
  - Existing session auth, CSRF, doctor/session binding, patient ownership, procedure/pharmacy-row ownership checks, and legacy response contracts remain in place.
  - Frontend `removeProcedure` visibility already includes helper type `3` in the relevant re-rendered receipt paths, so no JS change was needed in this pass.
- Verification:
  - `php -l sajid/deletePatientProcedure.php` passed.
  - `php -l sajid/deletePatientProcedurePharmacy.php` passed.
  - Simulated helper type `1` requests to both endpoints returned `PERMISSION_DENIED`.
  - Simulated helper type `3` requests to both endpoints passed the new helper guard and then stopped at local DB connection, expected in the sandbox.
  - Local CLI probes emitted existing PHPMailer PHP 8.5 deprecation warnings before JSON output because these endpoints include `db_functions.php`; not changed in this pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/deletePatientProcedure.php` to `/home/stagingdocbox/public_html/sajid/deletePatientProcedure.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deletePatientProcedurePharmacy.php` to `/home/stagingdocbox/public_html/sajid/deletePatientProcedurePharmacy.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

Parked very important follow-up:

- Do not forget: the final billing/procedure delete operations still call legacy `DB_Functions` helpers:
  - `DB_Functions::deleteProcedureForPatient()`
  - `DB_Functions::deleteProcedureForPatientPharmacy()`
  - related refund/stock helpers such as `saveBillingReturnLogs()` and `rectifyStocks()`
- Current access control is secured at the endpoint layer, but full SQL hardening should later rewrite these legacy helper internals with prepared SQL while preserving:
  - partial quantity return behavior
  - full row delete behavior
  - pharmacy stock restoration
  - billing refund logging
  - existing frontend response contracts

## 2026-05-14 Rectify Test VS visit/follow-up delete guard

- User clarified visit/follow-up deletion should only be allowed to Doctor, Admin, and Super Admin.
- Local policy:
  - Helper type `8`: Doctor.
  - Helper type `6`: Admin.
  - Helper type `a`: Super Admin.
- Local change:
  - `sajid/deleteFollowup.php` now requires helper type `8`, `6`, or `a` after session/CSRF validation and before parsing/deleting the visit payload.
  - Existing doctor/session binding and prepared deletes across `followUp`, `mediaFollowUp`, `otherFollowUp`, and `diagnosis` remain in place.
  - The current frontend click guard already matches `6`, `8`, `a`, or blank/admin, so no frontend cache bump was needed in this pass.
- Verification:
  - `php -l sajid/deleteFollowup.php` passed.
  - Simulated helper type `1` delete request returned `PERMISSION_DENIED`.
  - Simulated helper type `8` request passed the helper guard and then stopped at local DB connection, expected in the sandbox.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/deleteFollowup.php` to `/home/stagingdocbox/public_html/sajid/deleteFollowup.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

Follow-up duplicate alert fix:

- User reported the unauthorized delete-visit alert appears twice.
- Local changes:
  - `js/patientInfo_oph_rectify_test_vs.js` now binds the `.delFol` handler with a namespaced `off().on()` pattern: `click.rectifyDeleteFollowup`.
  - The denied localStorage branch no longer reloads the page after showing the alert.
  - If the server returns a JSON failure such as `PERMISSION_DENIED`, the callback shows one message and does not reload.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.22` to `v=40.23`.
- Verification:
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

Review follow-up:

- User asked to check whether a mistake was made in Rectify Test VS after the duplicate alert fix.
- Reviewed:
  - `js/patientInfo_oph_rectify_test_vs.js` `.delFol` handler.
  - `patientInfo_oph_rectify_test_vs.html` script version.
  - `sajid/deleteFollowup.php` helper guard.
- Result:
  - No syntax errors found in the JS, HTML, or PHP files.
  - The frontend visit-delete rule still allows helper types `6`, `8`, `a`, and blank/admin.
  - The server rule allows helper types `8`, `6`, and `a`; blank/admin sessions are normalized by `docbox_normalize_helper_type_id()` and still pass as intended.
  - The namespaced `off().on()` handler is limited to `.delFol`, and no second `.delFol` handler was found in the file.
  - One behavior note: using `stopImmediatePropagation()` is acceptable here because `.delFol` has no other intentional click handlers, but it should be kept scoped to this handler.

Page-load issue follow-up:

- User reported Rectify Test VS was not loading after the duplicate-alert frontend patch.
- Local rollback:
  - Reverted the `.delFol` frontend handler in `js/patientInfo_oph_rectify_test_vs.js` to the previous simple delegated `$(document).on('click', '.delFol', ...)` style.
  - Removed the `event.preventDefault()`, `event.stopImmediatePropagation()`, and server-response alert handling added in `v=40.23`.
  - Kept the server-side `sajid/deleteFollowup.php` helper guard unchanged.
  - Bumped `patientInfo_oph_rectify_test_vs.html` to load `js/patientInfo_oph_rectify_test_vs.js?v=40.24`.
- Verification:
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - `php -l sajid/deleteFollowup.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

Final visit-delete alert/cancel fix:

- User reported the unauthorized visit-delete alert still appears twice and cancel reloads the page.
- Local changes:
  - `js/patientInfo_oph_rectify_test_vs.js` now guards the `.delFol` click binding with `window.docboxRectifyDeleteFollowupHandlerBound`, so repeated execution of this block cannot attach duplicate handlers.
  - The visit-delete confirm cancel branch now returns without reload.
  - The unauthorized localStorage branch now shows the alert once and returns without reload.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.24` to `v=40.25`.
  - Server-side `sajid/deleteFollowup.php` guard remains unchanged.
- Verification:
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`

## 2026-05-14 Rectify Test VS video OPD credentials guard

- User moved to the next remaining Rectify Test VS helper-access item after visit delete was fixed.
- Page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/getVideoOPDCredentials.php`
- Local changes:
  - `sajid/getVideoOPDCredentials.php` now requires helper type `8` after session/CSRF validation and before reading video OPD credentials.
  - The endpoint now loads legacy `db_functions.php` only after the helper-type and doctor-scope checks pass.
  - `js/patientInfo_oph_rectify_test_vs.js` now hides `.videoOPD` and skips the credentials API call unless the active helper type contains `8`.
  - Credentials response parsing now accepts parsed JSON and string JSON and no longer logs the credentials response to the console.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.25` to `v=40.26`.
- Verification:
  - `php -l sajid/getVideoOPDCredentials.php` passed.
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Simulated helper type `1` request returned `PERMISSION_DENIED`.
  - Simulated helper type `8` with mismatched doctor id returned `SESSION_DOCTOR_MISMATCH`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/getVideoOPDCredentials.php` to `/home/stagingdocbox/public_html/sajid/getVideoOPDCredentials.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

## 2026-05-14 Rectify Test VS visit create/open guard

- User requested immediate UI click restriction and server-side API protection for creating visits and opening visits.
- Policy implemented:
  - New visit creation: helper types `8`, `6`, `a`, or `1`.
  - Same-day visit open/save: helper types `8`, `6`, `a`, or `1`.
  - Older visit open/save: helper types `8`, `6`, or `a`; clinical staff `1` is blocked.
- Page/files:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php`
- API files:
  - `/Users/apple/Documents/docbox_staging/sajid/insertFollowUp.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertOtherFollowUp.php`
  - `/Users/apple/Documents/docbox_staging/sajid/addFollowupFromTemplate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/updateVisitFromTemplate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getPatientVisitDoctor.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getPatientMedications.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getAllVisitDiagnosis.php`
- Local changes:
  - Added shared visit-date/helper policy functions in `sajid/includes/rectify_api_guard.php`.
  - `js/patientInfo_oph_rectify_test_vs.js` now shows the access-denied alert immediately when an unauthorized helper clicks Add Visit, opens a visit card, applies a visit template, or saves an inaccessible visit.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.26` to `v=40.27`.
  - Server guards were added to the listed visit read/write APIs.
  - Denied paths in `insertFollowUp.php`, `insertOtherFollowUp.php`, `addFollowupFromTemplate.php`, and `updateVisitFromTemplate.php` now run the helper/date guard before loading legacy DB helpers where feasible.
- Verification:
  - `php -l` passed for all touched PHP files.
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Simulated helper type `1` opening older visit returned `PERMISSION_DENIED`.
  - Simulated helper type `2` opening same-day visit returned `PERMISSION_DENIED`.
  - Simulated helper type `1` saving older visit data returned `PERMISSION_DENIED`.
  - Direct policy probes allowed helper type `1` for same-day visit and helper type `8` for older visit.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertFollowUp.php` to `/home/stagingdocbox/public_html/sajid/insertFollowUp.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertOtherFollowUp.php` to `/home/stagingdocbox/public_html/sajid/insertOtherFollowUp.php`
  - `/Users/apple/Documents/docbox_staging/sajid/addFollowupFromTemplate.php` to `/home/stagingdocbox/public_html/sajid/addFollowupFromTemplate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/updateVisitFromTemplate.php` to `/home/stagingdocbox/public_html/sajid/updateVisitFromTemplate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getPatientVisitDoctor.php` to `/home/stagingdocbox/public_html/sajid/getPatientVisitDoctor.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getPatientMedications.php` to `/home/stagingdocbox/public_html/sajid/getPatientMedications.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getAllVisitDiagnosis.php` to `/home/stagingdocbox/public_html/sajid/getAllVisitDiagnosis.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

Parked enhancement:

- User asked whether Save Changes can refresh only the visit list instead of reloading the whole patient profile.
- Decision: park for later; no application code changed in this pass.
- Preferred future approach:
  - Extract the existing visit-list build logic from `js/patientInfo_oph_rectify_test_vs.js` into a reusable `refreshPatientVisitsOnly()` style function.
  - After Save Changes finishes, refresh only `.followUpInfo`, `followupDetails`, `modalData`, and `diagnosisArray`, then close the follow-up modal and loading modal.
  - Fast first implementation can reuse `sajid/getPatientProfileWeb.php` while rebuilding only the visit area.
  - Cleaner later implementation can add a dedicated `sajid/getPatientVisitsOnly.php` endpoint returning only follow-up, diagnosis, media, other notes, and visit-doctor mapping data.
  - Important: wait for the save API calls to complete before refreshing visits, otherwise the UI may show stale visit data.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

## 2026-05-14 Rectify Test VS advised surgery/investigation guard

- User clarified that inside a visit, only doctor and super admin should be able to advise surgery and investigation.
- Policy implemented:
  - Allowed helper types: `8` doctor and `a` super admin.
  - Admin `6`, clinical staff `1`, and all other helper types are blocked.
- Local changes:
  - Added `docbox_rectify_require_doctor_or_super_admin()` in `sajid/includes/rectify_api_guard.php`.
  - Server guard applied to:
    - `sajid/saveInvestigation.php`
    - `sajid/saveAdvisedSurgeryNew.php`
    - `sajid/deleteAdvisedInvestigation.php`
    - `sajid/deleteAdvisedSurgery.php`
    - `sajid/uploadInvestigationAttachment.php`
  - Guard runs after session/CSRF/doctor-scope validation and before legacy DB helper loading where applicable.
  - `js/patientInfo_oph_rectify_test_vs.js` now uses `docboxRectifyCanAdviseInvestigationOrSurgery()` for advise/delete click checks instead of the old localStorage condition.
  - `patientInfo_oph_rectify_test_vs.html` cache-bumped Rectify Test VS JS from `v=40.27` to `v=40.28`.
- Verification:
  - `php -l` passed for all touched PHP files.
  - `php -l js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Simulated helper type `1` save-investigation request returned `PERMISSION_DENIED`.
  - Simulated helper type `6` save-advised-surgery request returned `PERMISSION_DENIED`.
  - Simulated helper type `1` delete-advised-surgery request returned `PERMISSION_DENIED`.
  - Simulated helper type `2` investigation-upload request returned `PERMISSION_DENIED`.
  - Direct policy probes allowed helper type `8` and helper type `a`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/rectify_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/rectify_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveInvestigation.php` to `/home/stagingdocbox/public_html/sajid/saveInvestigation.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveAdvisedSurgeryNew.php` to `/home/stagingdocbox/public_html/sajid/saveAdvisedSurgeryNew.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteAdvisedInvestigation.php` to `/home/stagingdocbox/public_html/sajid/deleteAdvisedInvestigation.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteAdvisedSurgery.php` to `/home/stagingdocbox/public_html/sajid/deleteAdvisedSurgery.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadInvestigationAttachment.php` to `/home/stagingdocbox/public_html/sajid/uploadInvestigationAttachment.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/secured_api_tracking.md` to `/home/stagingdocbox/public_html/secured_api_tracking.md`

## 2026-05-14 Financial Summary page-level guard
- User asked to apply only page-level restrictions to the Financial Summary page first.
- Local change:
  - `financialSummary.php` now includes `sajid/includes/finance_api_guard.php` before HTML output.
  - Page requires an active authenticated session via `docbox_require_api_auth()`.
  - Page renders only for helper types `6`, `9`, or `a`.
  - Other helper types receive an HTTP 403 permission-denied page before any Financial Summary UI is sent.
- Verification:
  - `php -l financialSummary.php` passed.
  - CLI probe without session returned `SESSION_EXPIRED`.
  - CLI probe with helper type `1` returned the 403 permission-denied HTML.
  - CLI probe with helper type `9` rendered the Financial Summary page HTML.
  - The allowed-render CLI path also exposed an existing local warning for `include_once 'fileVersion.php'` because the local file is under `sajid/fileVersion.php`; this is separate from the page guard and was not changed in this pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php` to `/home/stagingdocbox/public_html/financialSummary.php`

## 2026-05-14 Add Patient page-level guard
- User requested Add Patient page access only for Non Clinical Staff, Admin, and Super admin.
- Local change:
  - `addPatient.php` now includes `sajid/includes/api_auth.php` before any page output.
  - Page requires an active authenticated session via `docbox_require_api_auth()`.
  - Page renders only for helper types `2`, `6`, or `a`.
  - Other helper types receive an HTTP 403 permission-denied page before any Add Patient UI is sent.
- Verification:
  - `php -l addPatient.php` passed.
  - CLI probe without session returned `SESSION_EXPIRED`.
  - CLI probe with helper type `1` returned the 403 permission-denied HTML.
  - CLI probes with helper types `2`, `6`, and `a` rendered the Add Patient page HTML.
  - The allowed-render CLI path also exposed an existing local warning for `include_once 'fileVersion.php'` because the local file is under `sajid/fileVersion.php`; this is separate from the page guard and was not changed in this pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js` to `/home/stagingdocbox/public_html/js/expenses.js`
  - `/Users/apple/Documents/docbox_staging/sajid/includes/finance_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/finance_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenses.php` to `/home/stagingdocbox/public_html/sajid/getExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenses.php` to `/home/stagingdocbox/public_html/sajid/saveExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/updateExpense.php` to `/home/stagingdocbox/public_html/sajid/updateExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteExpense.php` to `/home/stagingdocbox/public_html/sajid/deleteExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenseLogs.php` to `/home/stagingdocbox/public_html/sajid/getExpenseLogs.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenseLog.php` to `/home/stagingdocbox/public_html/sajid/saveExpenseLog.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadAttachment.php` to `/home/stagingdocbox/public_html/sajid/uploadAttachment.php`

Follow-up save fix:

- User reported `saveExpenses.php` was not saving data after sync.
- Likely cause found in local code review: newer shop/pharmacy expense code inserts into `docboxExpenseTracker` without supplying `ExpenseID` and reads the generated insert id. The hardened `saveExpenses.php` was still explicitly posting a legacy timestamp `ExpenseID`, which may not match the current table write contract.
- Local fix:
  - `sajid/saveExpenses.php` now lets `docboxExpenseTracker` generate `ExpenseID`, then uses `mysqli_insert_id()` for the immediate payment-log insert and response.
  - `sajid/getExpenses.php` now uses a `LEFT JOIN` for payment method mapping and displays `Not Paid` if payment method `0` has no mapping row, so unpaid expenses cannot be hidden by the list query.
  - `js/expenses.js` now stops clearing the form if `saveExpenses.php` returns `success:false`.
- Verification:
  - `php -l sajid/saveExpenses.php` passed.
  - `php -l sajid/getExpenses.php` passed.
  - Local no-session POST probes for save/list still return `SESSION_EXPIRED`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenses.php` to `/home/stagingdocbox/public_html/sajid/saveExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenses.php` to `/home/stagingdocbox/public_html/sajid/getExpenses.php`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js` to `/home/stagingdocbox/public_html/js/expenses.js`

Follow-up server-side helper-type policy:

- User requested implementing server-side helper-type permissions on the expense page first.
- Local changes:
  - Added `docbox_expense_require_action()` in `sajid/includes/finance_api_guard.php`.
  - Expense permission policy:
    - `expense_read`: helper types `6`, `9`, `a`
    - `expense_create`: helper types `6`, `9`, `a`
    - `expense_update`: helper types `6`, `9`, `a`
    - `expense_delete`: helper types `6`, `a`
    - `expense_payment_log_read`: helper types `6`, `9`, `a`
    - `expense_payment_log_create`: helper types `6`, `9`, `a`
    - `expense_attachment_upload`: helper types `6`, `9`, `a`
  - Applied the action guard to:
    - `sajid/getExpenses.php`
    - `sajid/saveExpenses.php`
    - `sajid/updateExpense.php`
    - `sajid/deleteExpense.php`
    - `sajid/getExpenseLogs.php`
    - `sajid/saveExpenseLog.php`
    - `sajid/uploadAttachment.php`
  - Updated `js/expenses.js` so edit/delete/payment UI changes only happen after API success; denied actions now leave the UI state intact and show the API message.
- Verification:
  - `php -l` passed for `sajid/includes/finance_api_guard.php` and all seven expense endpoint/upload files.
  - Simulated helper type `1` calling `saveExpenses.php` returned `PERMISSION_DENIED`.
  - Simulated helper type `9` calling `deleteExpense.php` returned `PERMISSION_DENIED`.
  - Direct policy checks allow helper type `6` for delete and helper type `9` for create.
  - No-session probes for save/delete/upload still return `SESSION_EXPIRED`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/includes/finance_api_guard.php` to `/home/stagingdocbox/public_html/sajid/includes/finance_api_guard.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenses.php` to `/home/stagingdocbox/public_html/sajid/getExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenses.php` to `/home/stagingdocbox/public_html/sajid/saveExpenses.php`
  - `/Users/apple/Documents/docbox_staging/sajid/updateExpense.php` to `/home/stagingdocbox/public_html/sajid/updateExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/deleteExpense.php` to `/home/stagingdocbox/public_html/sajid/deleteExpense.php`
  - `/Users/apple/Documents/docbox_staging/sajid/getExpenseLogs.php` to `/home/stagingdocbox/public_html/sajid/getExpenseLogs.php`
  - `/Users/apple/Documents/docbox_staging/sajid/saveExpenseLog.php` to `/home/stagingdocbox/public_html/sajid/saveExpenseLog.php`
  - `/Users/apple/Documents/docbox_staging/sajid/uploadAttachment.php` to `/home/stagingdocbox/public_html/sajid/uploadAttachment.php`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js` to `/home/stagingdocbox/public_html/js/expenses.js`

Follow-up page-level guard:

- User asked to block unauthorized helpers from opening the Expenses page itself, not only the APIs.
- Local change:
  - `expenses.php` now includes `sajid/includes/finance_api_guard.php` before HTML output.
  - Page requires an active authenticated session via `docbox_require_api_auth()`.
  - Page renders only for helper types `6`, `9`, or `a`.
  - Other helper types receive an HTTP 403 permission-denied page before any Expenses UI is sent.
- Verification:
  - `php -l expenses.php` passed.
  - CLI probe without session returned `SESSION_EXPIRED`.
  - CLI probe with helper type `1` returned the 403 permission-denied HTML.
  - CLI probe with helper type `9` rendered the Expenses page HTML.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/expenses.php` to `/home/stagingdocbox/public_html/expenses.php`

## 2026-05-23 Rectify Test VS patient history text rendering cleanup

- User asked to check other patient history fields for the same browser error seen after saving allergy text.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared patient-history rendering helpers in `js/patientInfo_oph_rectify_test_vs.js` that build dropdown items, table headers, table rows, and delete buttons through jQuery DOM/text setters.
  - Updated `getPatientHistory()` rendering for Allergy, Current Treatment, Birth History, Family History, Immunisation History, Nutritional History, Ocular History, Surgical History, and Medical History to use the shared helpers.
  - Kept the existing delete button classes and data fields for the delete handlers.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.48` to `v=40.49`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused search found no remaining raw `.append()` calls for these patient history tables.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS remaining reload UI scan

- User asked to scan remaining `patientInfo_oph_rectify_test_vs.js` save/reload UI sections outside patient history, especially summary cards, dropdowns, and table rows.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared DOM helpers for generic text table rows, action buttons, file links, suggestion buttons, and detailed exam summary rows.
  - Updated visit change-log table reload to render cells through text setters.
  - Updated payment-log reload table rows for receive-payment and print-receipt views to render saved amount/mode/description/time fields through text setters; print/delete buttons are now constructed as buttons with data attributes.
  - Updated detailed eye exam summary rows to render finding names and RE/LE values through text setters while preserving drawing/upload/delete/print button data fields.
  - Updated plan-of-care advised-surgery rows to render category/name/eye/doctor text through text setters while preserving delete and counsellor button data fields.
  - Updated diagnosis/medicine/template/dosage suggestion buttons to build buttons through DOM helpers; dosage display keeps allowed dosage icon markup through the existing dosage sanitizer.
  - Updated patient name heading in the visit modal to use text setters.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.49` to `v=40.50`.
- Remaining scan findings for follow-up:
  - `advisedInvestigationsTable` still builds rows with embedded upload form HTML and should be handled with a dedicated form-builder cleanup.
  - Billing/receipt table rows, OT schedule rows, pre-op medicine rows, OT consumable rows, appointment log rows, and immediate payment-print rows still contain raw table-string rendering patterns.
  - Detailed exam edit-modal markup still builds textareas/dropdowns with saved values in HTML strings; the visible summary table rows were cleaned in this pass.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan shows no raw reload row insertion left for change-log, saved payment-log reload, detailed exam summary table, advised-surgery table, or suggestion button containers; remaining matches are listed above.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS plan-of-care investigation cleanup

- User reported plan-of-care Surgery Description and Investigation Name still showed an alert after entering JS-like text.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added plan-of-care investigation DOM helpers for upload forms and investigation table rows.
  - Updated `getPlanOfCare()` investigation table rendering to use text setters for Investigation Type, Investigation Name, Eye, and Advising Doctor.
  - Preserved investigation attachment upload preview, submit handling, download attachment link, and delete button data fields.
  - Rechecked active advised-surgery row rendering; active rows already use text setters from `v=40.50`. The only remaining surgery raw-row match is a commented old example.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.50` to `v=40.51`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused plan-of-care scan found no active raw investigation/surgery table row rendering; only an old commented surgery example remains.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS additional table rendering cleanup

- User asked to check for any other similar fields that need modification.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added receipt row helpers for building Remove buttons and receipt rows through DOM/text setters.
  - Updated appointment log rows to render date, time slot, and doctor through text setters.
  - Updated pre-op medicine rows to render medicine name and dosage through text setters while preserving delete button data.
  - Updated OT consumables item dropdown and consumed-items table rows to use DOM/text setters while preserving remove button data.
  - Updated OT schedule rows to render surgeon, anesthetist, procedure names, date, status, payment status, and remarks through text setters.
  - Updated receipt/procedure table rows to render procedure name, batch, expiry, HSN, quantities, and totals through text setters while preserving Remove button behavior.
  - Updated the other-surgery heading and receipt dropdown label rendering to avoid raw HTML string insertion for dynamic text.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.51` to `v=40.52`.
- Remaining scan findings for separate follow-up:
  - Immediate payment-print rows still repeat raw row construction in several branches and should be consolidated into a helper.
  - Detailed exam edit-modal controls still build textareas/dropdowns with saved values in large HTML strings; visible summary rows were already cleaned.
  - Follow-up modal shell, media preview modal, and server-returned pre-op visit HTML still append larger HTML fragments and need a separate careful pass to avoid changing layout behavior.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan found no active raw row rendering for OT schedule, appointment log, pre-op medicine table, OT consumables table, or receipt table; only commented receipt examples remain.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Home New patient card text rendering cleanup

- User reported `home_new` patient list data from `sajid/getAllPatientWebListMin.php` rendered diagnosis text as active markup when diagnosis contained JS-like text.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/home_new.js`
  - `/Users/apple/Documents/docbox_staging/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `appendHomePatientCard()` and supporting helpers in `js/home_new.js`.
  - Replaced raw patient-card HTML string construction in `getPatientList()` with DOM-built card rendering.
  - Replaced raw patient-card HTML string construction in `search()` with the same DOM-built card rendering.
  - Patient Name, Last Visited Date, Patient Unique Id, Diagnosis, Gender, Age, Tags, and due labels now render through text setters.
  - Kept the hidden list index and image container class behavior used by the existing card click handler.
  - Bumped `home_new.php` from `js/home_new.js?v=1.52` to `v=1.53`.
- Verification:
  - `node --check js/home_new.js` passed.
  - `php -l home_new.php` passed.
  - Focused scan no longer finds the old diagnosis string-rendering pattern in `home_new.js`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/home_new.js` to `/home/stagingdocbox/public_html/js/home_new.js`
  - `/Users/apple/Documents/docbox_staging/home_new.php` to `/home/stagingdocbox/public_html/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Add Patient plain-text validation cleanup

- User asked to start cleanup for `addPatient.php` so free-text fields do not accept JavaScript-like input.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added client-side normalization and validation helpers in `js/addPatient.js`.
  - Free-text fields now reject markup delimiters and encoded angle brackets before submit.
  - Required name/mobile checks now use the same cleaned values that are submitted.
  - Added client validation for phone, email, age, age unit, blood group, and GSTIN.
  - Submit now handles JSON validation errors from the server and closes the loading modal.
  - Added server-side plain-text validation in `sajid/insertPatientTest.php` for patient name, diagnosis, tag, blood group text, email, postal address, occupation, address parts, TPA, policy number, and GSTIN.
  - Mobile number is now required server-side for this registration handler.
  - Added `maxlength`, input mode, and autocomplete hints to active `addPatient.php` fields.
  - Added an active `.uploaded64` field next to the active photo input and renamed legacy hidden photo input IDs to reduce duplicate active-ID risk.
  - Bumped `addPatient.php` from `js/addPatient.js?v=3.83` to `v=3.84`.
- Verification:
  - `node --check js/addPatient.js` passed.
  - `php -l addPatient.php` passed.
  - `php -l sajid/insertPatientTest.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php` to `/home/stagingdocbox/public_html/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Add Patient exact field validation alerts

- User asked which checks were applied and requested alerts that show the exact field with the error.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `addPatientFieldError()` in `js/addPatient.js` so client validation alerts use `Field Name: exact problem`.
  - Updated required, format, age range, plain-text, GSTIN, and blood-group client messages to include the exact field name.
  - Added `add_patient_field_error()` in `sajid/insertPatientTest.php` so server validation errors return the same field-specific message format.
  - Updated backend field names to match visible labels such as Name, Phone Number, Email Address, Address Line 1, Insurance Policy Number, and GSTIN.
  - Bumped `addPatient.php` from `js/addPatient.js?v=3.84` to `v=3.85`.
- Verification:
  - `node --check js/addPatient.js` passed.
  - `php -l addPatient.php` passed.
  - `php -l sajid/insertPatientTest.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php` to `/home/stagingdocbox/public_html/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Add Patient age required validation

- User asked to add Age to the required field list.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added required marker to the Age label in `addPatient.php`.
  - Updated `js/addPatient.js` so blank Age shows `Age: this field is required.`
  - Updated `sajid/insertPatientTest.php` so backend validation also requires Age before saving.
  - Bumped `addPatient.php` from `js/addPatient.js?v=3.85` to `v=3.86`.
- Verification:
  - `node --check js/addPatient.js` passed.
  - `php -l addPatient.php` passed.
  - `php -l sajid/insertPatientTest.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php` to `/home/stagingdocbox/public_html/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Add Patient phone number digits-only validation

- User asked that Phone Number should be numeric only and should not check length.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed `maxlength="20"` from the active Phone Number field in `addPatient.php`.
  - Changed the active Phone Number field to `inputmode="numeric"` with `pattern="[0-9]*"`.
  - Updated `js/addPatient.js` so Phone Number is required and must contain digits only, with no length validation.
  - Updated `sajid/insertPatientTest.php` so backend Phone Number validation accepts digits only, with no length validation.
  - Bumped `addPatient.php` from `js/addPatient.js?v=3.86` to `v=3.87`.
- Verification:
  - `node --check js/addPatient.js` passed.
  - `php -l addPatient.php` passed.
  - `php -l sajid/insertPatientTest.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientTest.php` to `/home/stagingdocbox/public_html/sajid/insertPatientTest.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS deeper dynamic rendering scan

- User asked to deeply check `patientInfo_oph_rectify_test_vs.js` for any remaining fields that still need cleanup.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added shared option, attribute, quick-note, biometry-card, and next-visit-date helpers.
  - Updated fundus diagram reload labels and fundus finding table rows to use DOM/text setters instead of `innerHTML` for data point labels, eye labels, and fundus findings.
  - Updated saved fundus finding rows to create the visible spans and remove button through DOM methods.
  - Updated visiting-doctor dropdown option loading to append option nodes with `.text()`/`.attr()` instead of raw option strings.
  - Updated most-frequent quick-note buttons to escape dynamic field names before adding them to the button markup.
  - Updated Surgery Notes cards to render Date of Surgery with text setters and store card data with `.attr()`.
  - Updated Vitals cards to render Date of Visit with text setters and store card data with `.attr()`.
  - Updated Biometry cards to build the card/table through DOM helpers and render all biometry values with `.text()`.
  - Updated Next Visit Date display to build text and the change-date link through DOM helpers.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.52` to `v=40.53`.
- Remaining scan findings for separate focused cleanup:
  - Procedure/billing dropdown builders still concatenate Procedure Name, Batch, Cost, and stock labels into option/list HTML strings in multiple repeated blocks.
  - Detailed-exam edit modal builders still concatenate `FieldValueRE`, `FieldValueLE`, `FieldName`, and suggestion text into large textarea/dropdown HTML strings.
  - Immediate-payment print rows still repeat raw table-row construction in several branches.
  - Follow-up modal shell still appends large static HTML fragments with dynamic button-block variables; most-frequent quick-note dynamic names are now escaped, but the shell should eventually be converted to DOM builders.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds the prior raw fundus, visiting-doctor option, most-frequent note button, surgery-card, vitals-card, biometry-card, or next-visit-date patterns.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS payment print row cleanup

- User agreed to handle the remaining `patientInfo_oph_rectify_test_vs.js` cleanup one area at a time.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoAppendCurrentPaymentPrintRow()` for newly accepted payments.
  - Replaced repeated raw print-row construction for Cash, Card, Cheque/dd, Cashless/TPA/Insurance, Payment link, and UPI/WALLET flows.
  - New payment print rows now use `docboxPatientInfoAppendTextHeaderRow()` and `docboxPatientInfoAppendTextTableRow()` so payment amount, payment mode, description, and timestamp render as text.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.53` to `v=40.54`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds the immediate-payment raw print-row append pattern.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS payment description validation

- User reported that entering markup-like text in Receive Payment Description allowed payment totals/calculations to proceed while the payment log was not saved.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientPaymentLog.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertCustomPatientPaymentLog.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoValidatePaymentBeforeSave()` before the `#payFinal` save flow.
  - Payment Description now trims and blocks markup delimiters before any payment details, activity log, payment log, calculations, or print rows are saved.
  - Invalid description now shows `Payment Description: enter plain text only.`
  - Added matching backend description validation in both normal and custom payment-log endpoints.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.54` to `v=40.55`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - `php -l sajid/insertPatientPaymentLog.php` passed.
  - `php -l sajid/insertCustomPatientPaymentLog.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/sajid/insertPatientPaymentLog.php` to `/home/stagingdocbox/public_html/sajid/insertPatientPaymentLog.php`
  - `/Users/apple/Documents/docbox_staging/sajid/insertCustomPatientPaymentLog.php` to `/home/stagingdocbox/public_html/sajid/insertCustomPatientPaymentLog.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS procedure dropdown rendering cleanup

- User asked to handle the Procedure/Billing dropdown builders while making sure functionality is not changed.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added procedure-specific helpers for option labels, `<option>` markup, legacy menu item markup, submenu item markup, and billing dropdown item markup.
  - Updated `getProcedureDetailsForDoctor()` active dropdown builders to encode dynamic Procedure Name, Procedure Cost, Batch Number, Item Count, Procedure Type Id, and visiting doctor names.
  - Updated `getProcedureDetails()` active dropdown builders with the same helper-based rendering.
  - Preserved existing dropdown structure, `.item`, `.dropItem`, `.nostock`, type classes, data attributes, stock labels, and click handlers.
  - Preserved the legacy `data-reg1` branch where it already existed.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.55` to `v=40.56`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan shows active Procedure/Billing dropdown dynamic insertions now route through helper functions; remaining `ProcedureName` raw-string matches in this area are commented examples.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS detailed exam modal rendering cleanup

- User asked to start the next section carefully after confirming the Procedure/Billing dropdown cleanup worked.
- Section handled: Detailed Exam edit modal builders in `patientInfo_oph_rectify_test_vs.js`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added detailed-exam rendering helpers for suggestion links, dropdown textarea blocks, plain textarea rows, and table rows.
  - Replaced active detailed exam modal string builders so field names, right-eye values, left-eye values, and suggestion labels render through text/attribute encoding.
  - Preserved existing field IDs, wrapper IDs, dropdown IDs, class names, table headings, event selectors, and modal flow.
  - Updated saved detailed exam rows and template/version modal rows.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.56` to `v=40.57`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds active raw detailed-exam suggestion, field-name, or field-value table-row builders; remaining matches are old commented examples.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS follow-up modal button rendering cleanup

- User asked to continue cleaning according to the remaining recommendations.
- Section handled: Follow-up modal button fragments in `patientInfo_oph_rectify_test_vs.js`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added Follow-up modal helpers for app-style action buttons, copy action buttons, and Print All Diagrams button markup.
  - Replaced repeated raw action-button string assignments in both new-visit and edit-visit Follow-up modal paths.
  - Encoded dynamic Follow-up section heading and Add Customised Note button label before insertion into the existing modal strings.
  - Preserved existing classes, IDs, labels, button placement, event selectors, and modal flow.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.57` to `v=40.58`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan shows remaining old Follow-up modal raw examples are commented out only.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS previous visit copy rendering cleanup

- User reported that Copy Chief Complaint, Copy Findings, and Copy Advice could show a browser alert when the previous visit text contained markup-like content.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoAppendCopyTimelineItem()` to build the previous-visit copy timeline entries with jQuery text and attribute setters.
  - Updated `.copyChiefComplaintButton`, `.copyFindingsButton`, and `.copyAdviceButton` handlers to use the helper instead of concatenating previous visit `FieldValue` into button HTML.
  - Preserved existing timeline layout, date/time labels, `ccSuggest`, `efSuggest`, and `adSuggest` classes, and copy-to-textarea behavior.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.58` to `v=40.59`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds active raw previous-visit copy button construction; remaining matches are commented examples.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS customised notes card rendering cleanup

- User asked to patch the remaining Customised Notes fields.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoOtherNoteCardHtml()` and `docboxPatientInfoOtherNoteDataValue()` for Customised Notes cards.
  - Updated saved Customised Notes cards for existing visits to render `noteHead` and `noteField` as text.
  - Updated newly added Customised Note preview cards to render field name and value as text.
  - Preserved existing card IDs, `noteField` IDs, box color classes, delete/edit button classes, and underscore-based `data-header`/`data-value` behavior used by current handlers.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.59` to `v=40.60`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds active raw Customised Notes card construction; remaining matches are commented examples.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS readonly customised notes rendering cleanup

- User asked to move to the next remaining field after the Customised Notes card cleanup.
- Section handled: readonly Customised Notes list rebuilt by `viewAllNotes(notesArray)`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoAppendReadonlyNote()` to build readonly note rows with jQuery text/value setters.
  - Updated `viewAllNotes(notesArray)` to render note headings with `.text()` and note values with `.val()` instead of concatenating them into HTML.
  - Preserved the existing `.notesContainer` target, `.addNote` visibility behavior, row classes, readonly input attributes, and input class/name/id.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.60` to `v=40.61`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds active raw `notesArray` readonly note string construction; remaining `viewAllNotes` references are the active helper call and old commented examples.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Rectify Test VS surgery upload card rendering cleanup

- User clarified to fix remaining fields where data is entered, rather than general media/report cards.
- Section handled: Surgery Uploads card display in `getSurgeryFullData()` and `getSurgeryUploads()`, including the entered upload tag and visible file name where that path already showed it.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `docboxPatientInfoSurgeryUploadPath()` and `docboxPatientInfoSurgeryUploadCard()`.
  - Replaced raw Surgery Upload card strings with DOM construction using `.text()` and `.attr()`.
  - Preserved image/PDF branches, card classes, full-image preview data, download link, and existing upload refresh behavior.
  - Preserved the existing difference between the two paths: the modal load path still shows file name plus delete, while the standalone refresh path still shows the tag/download-only card.
  - Bumped `patientInfo_oph_rectify_test_vs.html` from `v=40.61` to `v=40.62`.
- Verification:
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Focused scan no longer finds active raw Surgery Upload card builders; remaining matches are old commented examples and the new helper calls.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Authenticate verification document upload hardening

- User moved to the agency-recommended `/authenticate.php` file-upload finding.
- Affected flow:
  - Page: `/Users/apple/Documents/docbox_staging/authenticate.php`
  - Endpoint: `/Users/apple/Documents/docbox_staging/sajid/upload.php` with `table=authenticate`
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/upload.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added a dedicated `table=authenticate` branch at the top of `sajid/upload.php` so verification document uploads are handled before the legacy shared upload path.
  - Token, doctor id, patient id, registration type, registration number, and registration council/year are validated before any file is saved.
  - Verification documents are limited to JPG, PNG, and PDF with server-side type checks; images are verified with image metadata and PDFs are checked for a PDF header.
  - Upload size is limited to 5 MB for this flow.
  - Stored filenames are generated server-side as `auth_<doctor>_<time>_<random>.<ext>` instead of using the browser-supplied filename.
  - The saved verification path remains in the existing `doctorId/patientId/file` format so the current review workflow is preserved.
  - `authenticate.php` now hints the same allowed file types in the file picker and requires a file before submit.
- Verification:
  - `php -l sajid/upload.php` passed.
  - `php -l authenticate.php` passed.
  - Focused scan confirms `table=authenticate` is handled by the new dedicated branch before the legacy shared upload path.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/authenticate.php` to `/home/stagingdocbox/public_html/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/sajid/upload.php` to `/home/stagingdocbox/public_html/sajid/upload.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Authenticate upload error alert messages

- User asked to show an alert with a suitable message when a verification document upload is rejected.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/sajid/upload.php`
  - `/Users/apple/Documents/docbox_staging/js/authenticate.js`
  - `/Users/apple/Documents/docbox_staging/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Updated the dedicated `table=authenticate` upload branch to redirect back to `authenticate.php` with safe upload error codes.
  - Added `docboxAuthenticateShowUploadError()` in `js/authenticate.js` to show clear alerts for invalid form details, session verification failure, missing file, size limit, unsupported file type, and save failures.
  - The alert URL parameter is removed with `history.replaceState()` after display to prevent repeated alerts on refresh.
  - Bumped `authenticate.php` script include from `js/authenticate.js` to `js/authenticate.js?v=1.1`.
- Verification:
  - `php -l sajid/upload.php` passed.
  - `php -l authenticate.php` passed.
  - `node --check js/authenticate.js` passed.
  - Focused scan confirms upload error redirects, alert mapping, and `authenticate.js?v=1.1` are present.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/sajid/upload.php` to `/home/stagingdocbox/public_html/sajid/upload.php`
  - `/Users/apple/Documents/docbox_staging/js/authenticate.js` to `/home/stagingdocbox/public_html/js/authenticate.js`
  - `/Users/apple/Documents/docbox_staging/authenticate.php` to `/home/stagingdocbox/public_html/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Authenticate page-level session guard

- User asked to prevent `authenticate.php` itself from rendering without a valid session.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `sajid/includes/api_auth.php` at the top of `authenticate.php`.
  - Added `docbox_require_api_auth()` before any HTML output.
  - No helper-type restriction was added; any valid logged-in session can open the existing RegNo verification page.
- Verification:
  - `php -l authenticate.php` passed.
  - Focused scan confirms `authenticate.php` calls `docbox_require_api_auth()` before HTML output.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/authenticate.php` to `/home/stagingdocbox/public_html/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 jQuery library maintenance update

- User moved to the agency-recommended outdated jQuery finding for `/js/jquery.js`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/jquery.js`
  - `/Users/apple/Documents/docbox_staging/js/jquery.min.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local findings:
  - `/Users/apple/Documents/docbox_staging/js/jquery.js` was jQuery `2.1.4`.
  - `/Users/apple/Documents/docbox_staging/js/jquery.min.js` was jQuery `1.6.2`.
  - Several pages load `/js/jquery.js`; the agency-named path is therefore actively used.
- Local changes:
  - Replaced `/Users/apple/Documents/docbox_staging/js/jquery.js` with official jQuery `3.7.1` full build.
  - Replaced `/Users/apple/Documents/docbox_staging/js/jquery.min.js` with official jQuery `3.7.1` minified build so the paired local copy is not left on an older release.
  - Did not move the app to jQuery `4.0.0` in this pass because that major version has breaking changes and should be handled as a separate compatibility project.
- Verification:
  - Local version marker now shows `jQuery JavaScript Library v3.7.1` in `js/jquery.js`.
  - Local version marker now shows `jQuery v3.7.1` in `js/jquery.min.js`.
  - `node --check js/jquery.js` passed.
  - `node --check js/jquery.min.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/jquery.js` to `/home/stagingdocbox/public_html/js/jquery.js`
  - `/Users/apple/Documents/docbox_staging/js/jquery.min.js` to `/home/stagingdocbox/public_html/js/jquery.min.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 secured page console log cleanup

- User asked to check pages that were recently protected for risky console logs and remove them safely.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/attendanceModule.php`
  - `/Users/apple/Documents/docbox_staging/patientInfo.php`
  - `/Users/apple/Documents/docbox_staging/consentFormEditor.php`
  - `/Users/apple/Documents/docbox_staging/js/authenticate.js`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js`
  - `/Users/apple/Documents/docbox_staging/js/init.js`
  - `/Users/apple/Documents/docbox_staging/js/home.js`
  - `/Users/apple/Documents/docbox_staging/js/financialSummary.js`
  - `/Users/apple/Documents/docbox_staging/js/consentFormEditorStandard.js`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/todayAppointment.js`
  - `/Users/apple/Documents/docbox_staging/js/OTSchedulingRangeCentrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/clinicalNotes.js`
  - `/Users/apple/Documents/docbox_staging/js/profileIPDHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/counsellorDesk.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineKeyboard.js`
  - `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_procedure_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/checkboxChecked.js`
  - `/Users/apple/Documents/docbox_staging/js/OTScheduling.js`
  - `/Users/apple/Documents/docbox_staging/js/counsellorDesk_centrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallisedS3.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportsArchived.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallisedGdrive.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportWeb.js`
  - `/Users/apple/Documents/docbox_staging/js/hrDeskNew.js`
  - `/Users/apple/Documents/docbox_staging/js/prescription.js`
  - `/Users/apple/Documents/docbox_staging/js/calendar.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed active standalone `console.log` statements that printed session/localStorage values, server responses, patient/report objects, billing data, biometric data, image data, and form selections.
  - Kept commented historical debug lines unchanged.
  - Kept existing non-log error handling statements unchanged where they preserve application behavior.
  - Removed an empty `else` branch in `js/OTSchedulingRangeCentrallised.js` after its only debug statement was removed.
- Verification:
  - Focused scan confirms no active standalone `console.log(...)` remains in the protected pages and custom page scripts checked in this pass.
  - `php -l attendanceModule.php`, `php -l patientInfo.php`, and `php -l consentFormEditor.php` passed.
  - `node --check` passed for every touched JavaScript file in this cleanup.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/attendanceModule.php` to `/home/stagingdocbox/public_html/attendanceModule.php`
  - `/Users/apple/Documents/docbox_staging/patientInfo.php` to `/home/stagingdocbox/public_html/patientInfo.php`
  - `/Users/apple/Documents/docbox_staging/consentFormEditor.php` to `/home/stagingdocbox/public_html/consentFormEditor.php`
  - `/Users/apple/Documents/docbox_staging/js/authenticate.js` to `/home/stagingdocbox/public_html/js/authenticate.js`
  - `/Users/apple/Documents/docbox_staging/js/expenses.js` to `/home/stagingdocbox/public_html/js/expenses.js`
  - `/Users/apple/Documents/docbox_staging/js/init.js` to `/home/stagingdocbox/public_html/js/init.js`
  - `/Users/apple/Documents/docbox_staging/js/home.js` to `/home/stagingdocbox/public_html/js/home.js`
  - `/Users/apple/Documents/docbox_staging/js/financialSummary.js` to `/home/stagingdocbox/public_html/js/financialSummary.js`
  - `/Users/apple/Documents/docbox_staging/js/consentFormEditorStandard.js` to `/home/stagingdocbox/public_html/js/consentFormEditorStandard.js`
  - `/Users/apple/Documents/docbox_staging/js/profileHelper.js` to `/home/stagingdocbox/public_html/js/profileHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/todayAppointment.js` to `/home/stagingdocbox/public_html/js/todayAppointment.js`
  - `/Users/apple/Documents/docbox_staging/js/OTSchedulingRangeCentrallised.js` to `/home/stagingdocbox/public_html/js/OTSchedulingRangeCentrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/clinicalNotes.js` to `/home/stagingdocbox/public_html/js/clinicalNotes.js`
  - `/Users/apple/Documents/docbox_staging/js/profileIPDHelper.js` to `/home/stagingdocbox/public_html/js/profileIPDHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/counsellorDesk.js` to `/home/stagingdocbox/public_html/js/counsellorDesk.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineKeyboard.js` to `/home/stagingdocbox/public_html/js/medicineKeyboard.js`
  - `/Users/apple/Documents/docbox_staging/js/profilePharmacyHelper.js` to `/home/stagingdocbox/public_html/js/profilePharmacyHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_procedure_helper.js` to `/home/stagingdocbox/public_html/js/profile_procedure_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js` to `/home/stagingdocbox/public_html/js/profile_template_helper.js`
  - `/Users/apple/Documents/docbox_staging/js/checkboxChecked.js` to `/home/stagingdocbox/public_html/js/checkboxChecked.js`
  - `/Users/apple/Documents/docbox_staging/js/OTScheduling.js` to `/home/stagingdocbox/public_html/js/OTScheduling.js`
  - `/Users/apple/Documents/docbox_staging/js/counsellorDesk_centrallised.js` to `/home/stagingdocbox/public_html/js/counsellorDesk_centrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallisedS3.js` to `/home/stagingdocbox/public_html/js/patientReportCentrallisedS3.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportsArchived.js` to `/home/stagingdocbox/public_html/js/patientReportsArchived.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallisedGdrive.js` to `/home/stagingdocbox/public_html/js/patientReportCentrallisedGdrive.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportWeb.js` to `/home/stagingdocbox/public_html/js/patientReportWeb.js`
  - `/Users/apple/Documents/docbox_staging/js/hrDeskNew.js` to `/home/stagingdocbox/public_html/js/hrDeskNew.js`
  - `/Users/apple/Documents/docbox_staging/js/prescription.js` to `/home/stagingdocbox/public_html/js/prescription.js`
  - `/Users/apple/Documents/docbox_staging/js/calendar.js` to `/home/stagingdocbox/public_html/js/calendar.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 rectify test vs console log scan

- User asked whether `patientInfo_oph_rectify_test_vs` was included in the console-log cleanup.
- Findings:
  - It was not included in the previous protected-page console cleanup pass.
  - A follow-up scan found many active `console.log(...)` statements in `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`.
  - One active image-data log was also found in `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`.
  - The active logs include localStorage values, patient/payment objects, server responses, image data, history fields, medicine data, and follow-up details.
- Local changes:
  - No cleanup patch was applied in this scan-only step.
- Next safe step:
  - Open `patientInfo_oph_rectify_test_vs.html`, `js/patientInfo_oph_rectify_test_vs.js`, and `stagingcontext.md` in the editor, remove standalone active `console.log(...)` lines, handle any empty branch left by removed debug-only lines, then run `php -l` and `node --check`.

## 2026-05-23 rectify test vs console log cleanup

- User asked to patch `patientInfo_oph_rectify_test_vs` to safely remove unnecessary console logs.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed active `console.log(...)` debug statements from `js/patientInfo_oph_rectify_test_vs.js`.
  - Removed the active image-data `console.log(...)` from `patientInfo_oph_rectify_test_vs.html`.
  - Removed the two multi-line ABDM visit-change debug logs while preserving the actual visit-change comparison logic and return value.
  - Kept existing commented historical debug lines unchanged.
  - Kept `console.warn`, `console.info`, and `console.error` statements unchanged where they are used for operational error/status handling.
- Verification:
  - Focused scan confirms no active `console.log(...)` remains in `js/patientInfo_oph_rectify_test_vs.js` or `patientInfo_oph_rectify_test_vs.html`.
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 remaining console log scan

- User asked whether logs are still remaining after the protected-page and rectify test VS cleanup.
- Findings:
  - No active `console.log(...)` remains in the files cleaned in the protected-page pass or in `patientInfo_oph_rectify_test_vs.html` / `js/patientInfo_oph_rectify_test_vs.js`.
  - Repository-wide scan still finds active `console.log(...)` in many other legacy/test/rollback/public files.
  - Current broad count is 251 files with active `console.log(...)` matches.
  - Examples of live or notable remaining files include `index.php`, `patientInfo.html`, `consentForms.php`, `discharge_card.js`, `discharge_card_oph.js`, `sw.js`, `Public/abha_single_entry.php`, `Public/abdm_abha_single_entry.php`, `js/patientInfo.js`, `js/patientInfo_oph_rectify.js`, `js/patientInfo_oph_new.js`, `js/patientPayment.js`, `js/hrDesk.js`, `js/profileIntl.js`, `js/formGenerator.js`, `js/medicineTemplateHelper.js`, `js/refractionKeyboardHelper.js`, `js/patientReportCentrallised.js`, `js/dashboard.js`, `js/demo.js`, and `js/script.js`.
- Local changes:
  - Scan-only step; no application code changed.

## 2026-05-23 main JS console log cleanup

- User asked to remove logs from the main JS files.
- Scope used:
  - Live/non-test/non-rollback application JS files that still had active `console.log(...)` entries.
  - Excluded test, rollback, backup, dated archive, minified/vendor, and alternate experimental files.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/discharge_card.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/sw.js`
  - `/Users/apple/Documents/docbox_staging/js/IPD.js`
  - `/Users/apple/Documents/docbox_staging/js/dashboard.js`
  - `/Users/apple/Documents/docbox_staging/js/formGenerator.js`
  - `/Users/apple/Documents/docbox_staging/js/hrDesk.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineTemplateHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPayment.js`
  - `/Users/apple/Documents/docbox_staging/js/refractionKeyboardHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/script.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/profileIntl.js`
  - `/Users/apple/Documents/docbox_staging/js/demo.js`
  - `/Users/apple/Documents/docbox_staging/js/formInitialiser.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReports.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineUi.js`
  - `/Users/apple/Documents/docbox_staging/js/prescriptionCustom.js`
  - `/Users/apple/Documents/docbox_staging/js/shop.js`
  - `/Users/apple/Documents/docbox_staging/js/profileShopHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientOnlineConsultation.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed active `console.log(...)` debug statements from the scoped main JS files.
  - Removed multi-line debug statements in `js/formGenerator.js`, `js/medicineTemplateHelper.js`, and `js/patientInfo_oph_new.js`.
  - Fixed two debug-only branch cleanup cases in `js/profileIntl.js` and `js/prescriptionCustom.js` by restoring the intended `if/else` structure after removing a debug statement.
  - Left `console.warn`, `console.info`, and `console.error` unchanged for operational handling.
- Verification:
  - Baseline `node --check` passed for the selected files before cleanup.
  - Focused scan confirms no active `console.log(...)` remains in the selected main JS files.
  - `node --check` passed for all selected files after cleanup.
  - Repository-wide active `console.log(...)` file count dropped from 251 to 225; remaining matches are outside this scoped main-file pass.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/discharge_card.js` to `/home/stagingdocbox/public_html/discharge_card.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/sw.js` to `/home/stagingdocbox/public_html/sw.js`
  - `/Users/apple/Documents/docbox_staging/js/IPD.js` to `/home/stagingdocbox/public_html/js/IPD.js`
  - `/Users/apple/Documents/docbox_staging/js/dashboard.js` to `/home/stagingdocbox/public_html/js/dashboard.js`
  - `/Users/apple/Documents/docbox_staging/js/formGenerator.js` to `/home/stagingdocbox/public_html/js/formGenerator.js`
  - `/Users/apple/Documents/docbox_staging/js/hrDesk.js` to `/home/stagingdocbox/public_html/js/hrDesk.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineTemplateHelper.js` to `/home/stagingdocbox/public_html/js/medicineTemplateHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo.js` to `/home/stagingdocbox/public_html/js/patientInfo.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_new.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPayment.js` to `/home/stagingdocbox/public_html/js/patientPayment.js`
  - `/Users/apple/Documents/docbox_staging/js/refractionKeyboardHelper.js` to `/home/stagingdocbox/public_html/js/refractionKeyboardHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/script.js` to `/home/stagingdocbox/public_html/js/script.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReportCentrallised.js` to `/home/stagingdocbox/public_html/js/patientReportCentrallised.js`
  - `/Users/apple/Documents/docbox_staging/js/profileIntl.js` to `/home/stagingdocbox/public_html/js/profileIntl.js`
  - `/Users/apple/Documents/docbox_staging/js/demo.js` to `/home/stagingdocbox/public_html/js/demo.js`
  - `/Users/apple/Documents/docbox_staging/js/formInitialiser.js` to `/home/stagingdocbox/public_html/js/formInitialiser.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentHelper.js` to `/home/stagingdocbox/public_html/js/patientPaymentHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientReports.js` to `/home/stagingdocbox/public_html/js/patientReports.js`
  - `/Users/apple/Documents/docbox_staging/js/medicineUi.js` to `/home/stagingdocbox/public_html/js/medicineUi.js`
  - `/Users/apple/Documents/docbox_staging/js/prescriptionCustom.js` to `/home/stagingdocbox/public_html/js/prescriptionCustom.js`
  - `/Users/apple/Documents/docbox_staging/js/shop.js` to `/home/stagingdocbox/public_html/js/shop.js`
  - `/Users/apple/Documents/docbox_staging/js/profileShopHelper.js` to `/home/stagingdocbox/public_html/js/profileShopHelper.js`
  - `/Users/apple/Documents/docbox_staging/js/patientOnlineConsultation.js` to `/home/stagingdocbox/public_html/js/patientOnlineConsultation.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 rectify test VS console re-check

- User asked to check `patientInfo_oph_rectify_test_vs.html` and `js/patientInfo_oph_rectify_test_vs.js` again after the main JS cleanup.
- Findings:
  - Focused scan found no active `console.log(...)` in either file.
  - `js/patientInfo_oph_rectify_test_vs.js` still contains `console.warn`, `console.info`, and `console.error` calls for operational status/error handling.
  - `patientInfo_oph_rectify_test_vs.html` had no active console calls in the re-check.
- Local changes:
  - Scan-only step; no application code changed.

## 2026-05-23 discharge card OPH field rendering cleanup

- User reported that `discharge_card_oph.html` still showed a JavaScript alert when saved field text was opened.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added local text-rendering helpers in `discharge_card_oph.js`.
  - Changed discharge-card display sections to append text nodes instead of appending raw response strings:
    - diagnosis
    - past history
    - family history
    - investigations
    - vitals
    - allergy and birth-history tags
    - surgery notes
    - current treatment / present illness
    - examination notes
  - Changed medication display/edit rows to build DOM nodes with `.text()` and safe attributes instead of raw HTML string interpolation for medicine and dosage.
  - Changed template/version/surgery dropdown options to use `.val()` and `.text()`.
  - Changed readonly note rows to use DOM creation and `.val()` for the note value.
  - Bumped `discharge_card_oph.html` script include from `discharge_card_oph.js?v=3.28` to `discharge_card_oph.js?v=3.29`.
- Verification:
  - `node --check discharge_card_oph.js` passed.
  - `php -l discharge_card_oph.html` passed.
  - Focused scan confirms the changed response-field append paths now use the local safe text helpers.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html` to `/home/stagingdocbox/public_html/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 discharge card OPH medication response parsing fix

- User reported `Unexpected end of JSON input` at `discharge_card_oph.js?v=3.29` while loading medication data.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Updated `parseDischargeResponse()` to return `null` for empty string responses and avoid throwing on malformed JSON.
  - Added `parseDischargeResponseOr()` for endpoints where an empty response should safely behave as an empty list/object.
  - Replaced the old medication parser that concatenated response characters and then called `JSON.parse()`.
  - Switched department, template, version, surgery, and mapped-surgery response parsing to the shared safe parser.
  - Bumped `discharge_card_oph.html` script include from `discharge_card_oph.js?v=3.29` to `discharge_card_oph.js?v=3.30`.
- Verification:
  - `node --check discharge_card_oph.js` passed.
  - `php -l discharge_card_oph.html` passed.
  - Focused scan confirms active `JSON.parse()` calls are removed from `discharge_card_oph.js`; remaining matches are commented legacy lines only.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html` to `/home/stagingdocbox/public_html/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 active console log cleanup

- User asked to remove unnecessary active `console.log(...)` output.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/index.php`
  - `/Users/apple/Documents/docbox_staging/consentForms.php`
  - `/Users/apple/Documents/docbox_staging/patientInfo.html`
  - `/Users/apple/Documents/docbox_staging/Public/abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_ort.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation_newDb.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_multi.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_pharmacy.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_final.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_update.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_release.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_language_compatible.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_livine.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_raj.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_brd.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_eyemax.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_eyemax_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentComet.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentHelper.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed active debug logs from the focused patient/payment files.
  - Restored `patientInfo_release.js`, `patientInfo_raj.js`, `patientInfo_pharmacy.js`, and `patientInfo_eyemax.js` from the staging server after an overly broad cleanup command affected closure lines, then re-applied the cleanup with a syntax-preserving replacement.
  - Left vendor, test, rollback, backup, and archived files untouched for this pass.
- Verification:
  - `php -l` passed for the updated PHP/HTML files.
  - `node --check` passed for the updated JavaScript files.
  - Focused active scan found no remaining active `console.log(...)` calls in the updated patient/payment file set.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/index.php` to `/home/stagingdocbox/public_html/index.php`
  - `/Users/apple/Documents/docbox_staging/consentForms.php` to `/home/stagingdocbox/public_html/consentForms.php`
  - `/Users/apple/Documents/docbox_staging/patientInfo.html` to `/home/stagingdocbox/public_html/patientInfo.html`
  - `/Users/apple/Documents/docbox_staging/Public/abha_single_entry.php` to `/home/stagingdocbox/public_html/Public/abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/home/stagingdocbox/public_html/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_new.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_ort.js` to `/home/stagingdocbox/public_html/js/patientInfo_ort.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo.js` to `/home/stagingdocbox/public_html/js/patientInfo.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation_new.js` to `/home/stagingdocbox/public_html/js/patientInfo_optimisation_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation_newDb.js` to `/home/stagingdocbox/public_html/js/patientInfo_optimisation_newDb.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_optimisation.js` to `/home/stagingdocbox/public_html/js/patientInfo_optimisation.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_multi.js` to `/home/stagingdocbox/public_html/js/patientInfo_multi.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_pharmacy.js` to `/home/stagingdocbox/public_html/js/patientInfo_pharmacy.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_final.js` to `/home/stagingdocbox/public_html/js/patientInfo_final.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_update.js` to `/home/stagingdocbox/public_html/js/patientInfo_update.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_release.js` to `/home/stagingdocbox/public_html/js/patientInfo_release.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_language_compatible.js` to `/home/stagingdocbox/public_html/js/patientInfo_language_compatible.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_livine.js` to `/home/stagingdocbox/public_html/js/patientInfo_livine.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_raj.js` to `/home/stagingdocbox/public_html/js/patientInfo_raj.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_brd.js` to `/home/stagingdocbox/public_html/js/patientInfo_brd.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_eyemax.js` to `/home/stagingdocbox/public_html/js/patientInfo_eyemax.js`
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_eyemax_new.js` to `/home/stagingdocbox/public_html/js/patientInfo_eyemax_new.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentComet.js` to `/home/stagingdocbox/public_html/js/patientPaymentComet.js`
  - `/Users/apple/Documents/docbox_staging/js/patientPaymentHelper.js` to `/home/stagingdocbox/public_html/js/patientPaymentHelper.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 discharge card console log comment cleanup

- User asked to remove useless console log references from the discharge card page.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/discharge_card.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed stale commented `console.log(...)` debug lines from both discharge card JavaScript files.
  - No PHP/HTML behavior changed.
- Verification:
  - `node --check discharge_card.js` passed.
  - `node --check discharge_card_oph.js` passed.
  - Focused scan found no `console.log` references in `discharge_card.js`, `discharge_card_oph.js`, `discharge_card.php`, or `discharge_card_oph.html`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/discharge_card.js` to `/home/stagingdocbox/public_html/discharge_card.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 discharge card included script console cleanup

- User still saw console log references on the discharge card page after the first cleanup.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/init.js`
  - `/Users/apple/Documents/docbox_staging/js/prescription.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card.php`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed stale commented `console.log(...)` references from the discharge page shared includes `js/init.js` and `js/prescription.js`.
  - Bumped discharge page script query versions to avoid cached old sources:
    - `discharge_card.php`: `js/prescription.js?v=1.1`, `discharge_card.js?v=3.30`
    - `discharge_card_oph.html`: `js/init.js?v=3.7`, `js/prescription.js?v=1.3`, `discharge_card_oph.js?v=3.31`
- Verification:
  - `node --check js/init.js` passed.
  - `node --check js/prescription.js` passed.
  - `node --check discharge_card.js` passed.
  - `node --check discharge_card_oph.js` passed.
  - `php -l discharge_card.php` passed.
  - `php -l discharge_card_oph.html` passed.
  - Focused scan found no `console.*` references in the discharge pages and their local script includes.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/init.js` to `/home/stagingdocbox/public_html/js/init.js`
  - `/Users/apple/Documents/docbox_staging/js/prescription.js` to `/home/stagingdocbox/public_html/js/prescription.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card.php` to `/home/stagingdocbox/public_html/discharge_card.php`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html` to `/home/stagingdocbox/public_html/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/discharge_card.js` to `/home/stagingdocbox/public_html/discharge_card.js`
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.js` to `/home/stagingdocbox/public_html/discharge_card_oph.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 financial summary DataTables script order fix

- User reported `buttons.print.min.js:5 Uncaught ReferenceError: jQuery is not defined`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Finding:
  - `financialSummary.php` loaded CDN DataTables Buttons scripts in the page head before jQuery.
  - The same local DataTables Buttons scripts were already loaded later after the page jQuery include.
- Local changes:
  - Removed the early duplicate CDN DataTables Buttons JavaScript includes from the page head.
  - Left the later local includes in place so `jquery-3.3.1.js`, `jquery.dataTables.min.js`, `dataTables.buttons.min.js`, and `buttons.print.min.js` load in dependency order.
- Verification:
  - `php -l financialSummary.php` passed.
  - Include-order scan confirms `buttons.print.min.js` now appears after the jQuery include in `financialSummary.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php` to `/home/stagingdocbox/public_html/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 financial summary console log cleanup

- User asked to remove console log references as well after the financial summary script-order fix.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/financialSummary.js`
  - `/Users/apple/Documents/docbox_staging/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed stale commented `console.log(...)` debug references from `js/financialSummary.js`.
  - Bumped `financialSummary.php` script include from `js/financialSummary.js?v=2.52` to `js/financialSummary.js?v=2.53`.
- Verification:
  - `node --check js/financialSummary.js` passed.
  - `php -l financialSummary.php` passed.
  - Focused scan found no `console.*` references in `financialSummary.php`, `js/financialSummary.js`, `js/init.js`, `js/buttons.print.min.js`, `js/dataTables.buttons.min.js`, or `js/buttons.html5.min.js`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/financialSummary.js` to `/home/stagingdocbox/public_html/js/financialSummary.js`
  - `/Users/apple/Documents/docbox_staging/financialSummary.php` to `/home/stagingdocbox/public_html/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 init.js cache busting rule for updated PHP pages

- User asked to place cache busting for `init.js` in every PHP page that is updated.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/subscription.php`
  - `/Users/apple/Documents/docbox_staging/success.php`
  - `/Users/apple/Documents/docbox_staging/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Updated root PHP pages that still loaded `js/init.js` without a query string.
  - Used `filemtime(__DIR__ . '/js/init.js')` so the cache-busting value changes when the local `init.js` file changes:
    - `subscription.php`
    - `success.php`
    - `authenticate.php`
  - Confirmed recently updated `financialSummary.php` already has cache busting on `js/init.js`.
  - Did not modify `sajid/authenticate.php` in this pass because it is under the `sajid/` path and its relative `js/init.js` include should be handled separately with that page's path expectations.
- Verification:
  - `php -l subscription.php` passed.
  - `php -l success.php` passed.
  - `php -l authenticate.php` passed.
  - Scan confirms the updated root PHP pages now load `js/init.js` with a version query.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/subscription.php` to `/home/stagingdocbox/public_html/subscription.php`
  - `/Users/apple/Documents/docbox_staging/success.php` to `/home/stagingdocbox/public_html/success.php`
  - `/Users/apple/Documents/docbox_staging/authenticate.php` to `/home/stagingdocbox/public_html/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 financial summary init.js filemtime cache busting

- User asked to apply the same `init.js` cache-busting pattern to `financialSummary.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced `js/init.js?v=<?php include_once 'fileVersion.php'; ?>` with `js/init.js?v=<?php echo filemtime(__DIR__ . '/js/init.js'); ?>`.
- Verification:
  - `php -l financialSummary.php` passed.
  - Scan confirms the page now uses `filemtime(__DIR__ . '/js/init.js')` for the `init.js` include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php` to `/home/stagingdocbox/public_html/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 init.js cache busting switched to fileVersion.php

- User clarified to use `fileVersion.php` for cache busting.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/subscription.php`
  - `/Users/apple/Documents/docbox_staging/success.php`
  - `/Users/apple/Documents/docbox_staging/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced the previous `filemtime(__DIR__ . '/js/init.js')` query values with the app's existing `fileVersion.php` include pattern for `js/init.js`:
    - `financialSummary.php`
    - `subscription.php`
    - `success.php`
    - `authenticate.php`
- Verification:
  - `php -l financialSummary.php` passed.
  - `php -l subscription.php` passed.
  - `php -l success.php` passed.
  - `php -l authenticate.php` passed.
  - Scan confirms all four pages now use `js/init.js?v=<?php include_once 'fileVersion.php'; ?>`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/financialSummary.php` to `/home/stagingdocbox/public_html/financialSummary.php`
  - `/Users/apple/Documents/docbox_staging/subscription.php` to `/home/stagingdocbox/public_html/subscription.php`
  - `/Users/apple/Documents/docbox_staging/success.php` to `/home/stagingdocbox/public_html/success.php`
  - `/Users/apple/Documents/docbox_staging/authenticate.php` to `/home/stagingdocbox/public_html/authenticate.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 fileVersion.php bumped to 3.2

- User asked to open `fileVersion.php` and bump the version.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/sajid/fileVersion.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - `/Users/apple/Documents/docbox_staging/` workspace root, before adding the missing root `fileVersion.php`
- Finding:
  - The PHP pages using `include_once 'fileVersion.php'` expect a root-level `fileVersion.php`.
  - The local workspace only had `sajid/fileVersion.php`, and that file contained invalid top-level `public function` syntax.
- Local changes:
  - Added root `fileVersion.php` with version output `3.2`.
  - Updated `sajid/fileVersion.php` to output `3.2` and parse correctly.
- Verification:
  - `php -l fileVersion.php` passed.
  - `php -l sajid/fileVersion.php` passed.
  - `php fileVersion.php` outputs `3.2`.
  - `php sajid/fileVersion.php` outputs `3.2`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/fileVersion.php` to `/home/stagingdocbox/public_html/fileVersion.php`
  - `/Users/apple/Documents/docbox_staging/sajid/fileVersion.php` to `/home/stagingdocbox/public_html/sajid/fileVersion.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 home_new.php init.js fileVersion cache busting

- User asked to use `fileVersion.php` cache busting in `home_new.php` as well.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced fixed `js/init.js?v=3.3` with `js/init.js?v=<?php include_once 'fileVersion.php'; ?>`.
- Verification:
  - `php -l home_new.php` passed.
  - Scan confirms `home_new.php` now uses `fileVersion.php` for the `init.js` include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/home_new.php` to `/home/stagingdocbox/public_html/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 rectify test VS HTML init.js static cache bust

- User noted that the `fileVersion.php` cache-busting method cannot be used in `patientInfo_oph_rectify_test_vs.html`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Kept the HTML-compatible static query-string pattern.
  - Bumped `js/init.js?v=3.6` to `js/init.js?v=3.8`.
  - Did not add any PHP snippet to the `.html` page.
- Verification:
  - Scan confirms the page uses `js/init.js?v=3.8`.
  - Scan confirms no `fileVersion.php` or PHP snippet was added to the HTML page.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 discharge card OPH HTML init.js static cache bust

- User asked for the same HTML-compatible cache-busting handling in `discharge_card_oph.html`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Kept the HTML-compatible static query-string pattern.
  - Bumped `js/init.js?v=3.7` to `js/init.js?v=3.8`.
  - Did not add any PHP snippet to the `.html` page.
- Verification:
  - Scan confirms the page uses `js/init.js?v=3.8`.
  - Scan confirms no `fileVersion.php` or PHP snippet was added to the HTML page.
  - `php -l discharge_card_oph.html` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/discharge_card_oph.html` to `/home/stagingdocbox/public_html/discharge_card_oph.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 calendar.php init.js fileVersion cache busting

- User asked to update `calendar.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/calendar.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced fixed `js/init.js?v=3.6` with `js/init.js?v=<?php include_once 'fileVersion.php'; ?>`.
- Verification:
  - `php -l calendar.php` passed.
  - Scan confirms `calendar.php` now uses `fileVersion.php` for the `init.js` include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/calendar.php` to `/home/stagingdocbox/public_html/calendar.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 OTSchedulingRange UserGuiding 404 cleanup

- User reported a browser 404 from `user-guiding-451655710ID-embedded.js` on `OTSchedulingRange.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/OTSchedulingRange.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Removed the broken UserGuiding loader from `OTSchedulingRange.php`; it used `451655710ID` and caused the browser to request a missing SDK config.
  - Updated `OTSchedulingRange.php` `js/init.js` include from fixed `v=2.1` to `v=<?php include_once 'fileVersion.php'; ?>` because this PHP page was updated.
- Verification:
  - `php -l OTSchedulingRange.php` passed.
  - Focused scan confirms `OTSchedulingRange.php` no longer contains `userGuiding`, `451655710ID`, or `sdk.userguiding`.
  - Scan confirms `OTSchedulingRange.php` now uses `fileVersion.php` for the `init.js` include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/OTSchedulingRange.php` to `/home/stagingdocbox/public_html/OTSchedulingRange.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 profile.php init.js fileVersion cache busting

- User asked to handle the `init.js` include in `profile.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced fixed `js/init.js?v=3.6` with `js/init.js?v=<?php include_once 'fileVersion.php'; ?>`.
- Verification:
  - `php -l profile.php` passed.
  - Scan confirms `profile.php` now uses `fileVersion.php` for the `init.js` include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 profile template diagnosis join fix

- User reported `Uncaught TypeError: diagnosisText.join is not a function` in `profile_template_helper.js?v=1.6`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js`
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added `normalizeProfileTemplateSearchText()` to safely handle array, empty, and string search values.
  - Updated diagnosis template dropdown rendering to use the normalized value before joining.
  - Applied the same normalization to medicine template dropdown rendering because it used the same `.join()` pattern.
  - Used the existing `escapeProfileTemplateHtml()` helper for dropdown labels built from typed or response text.
  - Bumped `profile.php` include from `js/profile_template_helper.js?v=1.6` to `v=1.7`.
- Verification:
  - `node --check js/profile_template_helper.js` passed.
  - `php -l profile.php` passed.
  - Scan confirms raw `diagnosisText.join(...)` and `medicineText.join(...)` calls were removed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/profile_template_helper.js` to `/home/stagingdocbox/public_html/js/profile_template_helper.js`
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-23 Q2 audit report completion review

- User provided `/Users/apple/Downloads/2026-Q2-DocBox-WebApp-SecurityTest-Report-v1.0-unlocked.pdf` and asked what has been completed.
- Local review:
  - Extracted the PDF locally with `pdftotext`.
  - Compared the 10 report findings against this context file.
- Current remediation status from local work log:
  - Q2 2026-001 OTP verification attempt controls: completed in the local log; server retest still needed.
  - Q2 2026-002 OTP request limiting: completed in the local log; server retest still needed.
  - Q2 2026-003 stored script rendering/input handling on `patientInfo_oph_rectify_test_vs.html`: completed for the reported page scope, with additional related field cleanups logged; server retest still needed.
  - Q2 2026-004 `authenticate.php` verification document upload validation: completed in the local log; server retest still needed.
  - Q2 2026-005 dashboard page authentication guard: completed in the local log; server retest still needed.
  - Q2 2026-006 dashboard cache/path handling: completed in the local log, including broader protected-page treatment; server retest still needed.
  - Q2 2026-007 concurrent active session control: business-accepted exception; user confirmed this will not be implemented because some hospitals intentionally use one login across multiple stations.
  - Q2 2026-008 directory listing: completed in the local log; server retest still needed.
  - Q2 2026-009 HTTP response headers: completed in the local log through `.htaccess`, `.user.ini`, and PHP prepended header helper; server retest still needed.
  - Q2 2026-010 jQuery library update: completed in the local log; server retest still needed.
- No application code was changed during this review.

## 2026-05-23 Q2 audit concurrent-session exception

- User confirmed concurrent-login restriction will not be implemented because some hospitals intentionally use one login across multiple stations.
- Status update:
  - Q2 2026-007 is a business-accepted exception, not an engineering-pending remediation item.
  - No application code changed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-24 remediation completion report review

- User provided `/Users/apple/Downloads/DOCBOX_Q2_2026_Remediation_Completion_Report.pdf` for review.
- Local review:
  - Extracted PDF metadata with `pdfinfo`.
  - Extracted report text with `pdftotext`.
- Review result:
  - The report accurately reflects 9 remediated/synced findings and 1 business-accepted exception.
  - The retest scope correctly excludes Q2-007 and includes Q2-001 through Q2-006 plus Q2-008 through Q2-010.
  - Suggested minor cleanup before sending:
    - Fix wrapped filename text `patientInfo_oph_rectify_tes t_vs.html` if visible in the source document.
    - Consider adding a short "Deployment Date" or "Synced Date" field.
    - Consider adding a one-line note that Q2-007 has business approval/risk acceptance owner if available.
    - Keep final PDF formatting checked after export because the table wraps some long titles.
- No application code changed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 Rectify Test VS jQuery include update

- User asked whether `patientInfo_oph_rectify_test_vs.html` used the latest jQuery libraries, then asked to change it.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Replaced the old Google-hosted `jquery/1.11.2/jquery.min.js` include with local `js/jquery.js`.
  - Local `js/jquery.js` is jQuery `3.7.1`.
- Verification:
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Scan confirms the page now loads `js/jquery.js` and no longer loads `jquery/1.11.2/jquery.min.js`.
  - `head -n 3 js/jquery.js` confirms local jQuery `3.7.1`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 Rectify Test VS full page script include review

- User asked to look deeper across the whole `patientInfo_oph_rectify_test_vs.html` page after the jQuery include update.
- Local review:
  - Scanned all active `<script>` includes after stripping HTML comments.
  - Confirmed the active jQuery core include is now local `js/jquery.js`.
  - Confirmed local `js/jquery.js` is jQuery `3.7.1`.
- Findings:
  - No active Google-hosted `jquery/1.11.2/jquery.min.js` include remains.
  - The old Google jQuery `3.3.1` line is commented only, not active.
  - jQuery-dependent scripts load after the active jQuery core include.
  - `html2canvas.js` is loaded twice.
  - Bootstrap JS is loaded twice from external CDNs: Bootstrap `3.3.7` and Bootstrap `3.2.0`.
  - `taggle.js?v=1.1` is loaded twice.
  - jQuery UI is still loaded from external CDN `https://code.jquery.com/ui/1.12.1/jquery-ui.js`; the local `js/jquery-ui.js` is also version `1.12.1`.
- No application code was changed during this deeper review.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 Rectify Test VS jQuery UI update

- User asked whether jQuery UI was latest, then asked to update it.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.js`
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.min.js`
  - `/Users/apple/Documents/docbox_staging/css/jquery-ui.css`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Updated local `js/jquery-ui.js` from jQuery UI `1.12.1` to official jQuery UI `1.14.2`.
  - Updated local `js/jquery-ui.min.js` from jQuery UI `1.12.1` to official jQuery UI `1.14.2`.
  - Updated local `css/jquery-ui.css` from jQuery UI `1.12.1` to official jQuery UI `1.14.2` base theme.
  - Changed `patientInfo_oph_rectify_test_vs.html` from external `https://code.jquery.com/ui/1.12.1/jquery-ui.js` to local `js/jquery-ui.js?v=1.14.2`.
  - Added cache busting to the jQuery UI CSS include: `css/jquery-ui.css?v=1.14.2`.
- Verification:
  - `node --check js/jquery-ui.js` passed.
  - `node --check js/jquery-ui.min.js` passed.
  - `php -l patientInfo_oph_rectify_test_vs.html` passed.
  - Version markers confirm `js/jquery-ui.js`, `js/jquery-ui.min.js`, and `css/jquery-ui.css` are jQuery UI `1.14.2`.
  - Focused scan confirms `patientInfo_oph_rectify_test_vs.html` no longer loads jQuery UI from `code.jquery.com/ui/1.12.1`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.js` to `/home/stagingdocbox/public_html/js/jquery-ui.js`
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.min.js` to `/home/stagingdocbox/public_html/js/jquery-ui.min.js`
  - `/Users/apple/Documents/docbox_staging/css/jquery-ui.css` to `/home/stagingdocbox/public_html/css/jquery-ui.css`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 Rectify Test VS home.php navigation review

- User asked for a deep dive on whether a user may land on `home.php` from `patientInfo_oph_rectify_test_vs.html`.
- Local review:
  - Scanned `patientInfo_oph_rectify_test_vs.html`, `js/patientInfo_oph_rectify_test_vs.js`, `js/init.js`, and page helper scripts for `home.php` and navigation APIs.
  - Checked active markup and active JS separately from commented legacy lines.
- Findings:
  - A user can land on `home.php` by clicking the active page logo in `patientInfo_oph_rectify_test_vs.html`.
  - A user can also land on `home.php` through the shared sidebar/menu generated by `js/init.js`; the menu includes a `My Patients` link to `home.php`.
  - The static sidebar block inside `patientInfo_oph_rectify_test_vs.html` contains a `home.php` link only inside comments.
  - Page-specific `js/patientInfo_oph_rectify_test_vs.js` contains `home.php` navigation only in commented legacy lines; no active automatic redirect to `home.php` was found in that file.
  - Existing `home.php` has a page auth guard in the local workspace, so landing on `home.php` should still require a valid session.
- No application code changed during this review.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 home.php patient list JS-like input guard

- User asked to add the JS-like input guard after confirming users can land on `home.php` from Rectify Test VS.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/home.php`
  - `/Users/apple/Documents/docbox_staging/js/home.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added home page helper functions to treat patient-list display values as text before appending the patient card HTML.
  - Escaped patient list and search result values for patient name, last visited date, patient unique ID, diagnosis, gender, age, and tags.
  - Added a search field plain-text guard. The alert shown is: `Search field contains unsupported characters. Please enter plain text only.`
  - Bumped `home.php` cache version for `js/home.js` from `14.41` to `14.42`.
- Verification:
  - `node --check js/home.js` passed.
  - `php -l home.php` passed.
  - Focused scan confirms active patient-card HTML now uses escaped display variables for the patient fields checked.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/home.js` to `/home/stagingdocbox/public_html/js/home.js`
  - `/Users/apple/Documents/docbox_staging/home.php` to `/home/stagingdocbox/public_html/home.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 home.php early patient navigation

- User asked to put the patient navigation before anything else is loaded on `home.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/home.php`
  - `/Users/apple/Documents/docbox_staging/js/home.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added an early inline routing script as the first active item inside the `home.php` `<head>`.
  - Preserved the existing routing behavior:
    - helper type containing `c` goes to `attendanceModule.php`
    - customer `1000` goes to `home_test_b.php`
    - all other customers go to `home_new.php`
  - Removed the duplicate late routing block from `js/home.js`.
  - Made the remaining `HelperTypeID` visibility check in `js/home.js` null-safe without changing the visibility decision.
  - Bumped `home.php` cache version for `js/home.js` from `14.42` to `14.43`.
- Verification:
  - `node --check js/home.js` passed.
  - `php -l home.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/home.php` to `/home/stagingdocbox/public_html/home.php`
  - `/Users/apple/Documents/docbox_staging/js/home.js` to `/home/stagingdocbox/public_html/js/home.js`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 retest report triage

- User shared the retest summary showing three items still open: stored script handling, concurrent sessions, and older jQuery usage.
- Local triage performed, no application code changed in this pass.
- Findings:
  - Concurrent sessions remain a documented business exception because some hospitals use one login across multiple stations.
  - `js/jquery.js` and `js/jquery.min.js` are both jQuery `3.7.1`.
  - Older jQuery references still exist in other app pages and old/test pages, including `index.php`, `profile.php`, `patientInfo.php`, `discharge_card_oph.html`, `financialSummary.php`, and several patientInfo variants.
  - Old standalone library files also still exist in `/js`, including `jquery-1.8.2.js`, `jquery-1.8.2.min.js`, and `jquery-3.3.1.js`.
- Recommended next work:
  - Decide whether the retest scope requires all reachable pages to use `js/jquery.js` / `js/jquery.min.js` `3.7.1`, or only the pages listed in the original report.
  - Continue stored-script cleanup field-by-field on the retest affected pages once the agency provides exact URLs/fields, or proactively scan reachable pages that still render server values with raw HTML concatenation.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 Rectify Test VS retest jQuery check

- User clarified that the retest jQuery finding was shown on `patientInfo_oph_rectify_test_vs.html`.
- Local and live staging checks:
  - Local `patientInfo_oph_rectify_test_vs.html` active jQuery core include is `js/jquery.js`.
  - Local `js/jquery.js` is jQuery `3.7.1`.
  - Live staging `https://staging.docbox.asia/patientInfo_oph_rectify_test_vs.html` active jQuery core include is also `js/jquery.js`.
  - Live staging `https://staging.docbox.asia/js/jquery.js` is jQuery `3.7.1`.
  - Local `js/jquery-ui.js` is jQuery UI `1.14.2`.
  - Live staging `https://staging.docbox.asia/js/jquery-ui.js` is still jQuery UI `1.12.1`, so the updated local jQuery UI file has not reached staging or is being served from an old copy.
- Local change:
  - Removed an obsolete commented `https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js` line from `patientInfo_oph_rectify_test_vs.html` so source-based checks do not report a commented old include.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.js` to `/home/stagingdocbox/public_html/js/jquery-ui.js`
  - `/Users/apple/Documents/docbox_staging/js/jquery-ui.min.js` to `/home/stagingdocbox/public_html/js/jquery-ui.min.js`
  - `/Users/apple/Documents/docbox_staging/css/jquery-ui.css` to `/home/stagingdocbox/public_html/css/jquery-ui.css`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 home_new.php jQuery retest cleanup

- User asked to do the same jQuery cleanup on `home_new.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local checks:
  - `home_new.php` active jQuery core include is already `js/jquery.js`.
  - Local `js/jquery.js` is jQuery `3.7.1`.
  - No old jQuery CDN references were found in `home_new.php`.
- Local changes:
  - Updated the old comment from `jQuery 2.2.0` to `jQuery 3.7.1`.
  - Added explicit cache version to jQuery UI include: `js/jquery-ui.js?v=1.14.2`.
- Verification:
  - `php -l home_new.php` passed.
  - Focused scan found no old jQuery CDN/core references in `home_new.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/home_new.php` to `/home/stagingdocbox/public_html/home_new.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 home_new.php live sync check

- User confirmed `home_new.php` was synced and asked to verify.
- Live checks:
  - Unauthenticated `https://staging.docbox.asia/home_new.php` returns HTTP `302` to `/index.php` with no response body, due to the page auth guard.
  - Following redirects with `curl -L` shows `/index.php`, so the old jQuery `1.11.2` line seen there belongs to the login page response, not `home_new.php`.
  - Live `https://staging.docbox.asia/js/jquery.js` is jQuery `3.7.1`.
  - Live `https://staging.docbox.asia/js/jquery-ui.js` is jQuery UI `1.14.2`.
- Result:
  - Public unauthenticated source checks cannot inspect the authenticated `home_new.php` body without a valid session.
  - Local `home_new.php` remains clean for active old jQuery references and points to `js/jquery-ui.js?v=1.14.2`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 dashboard.php jQuery retest cleanup

- User asked to update `dashboard.php` also for the jQuery retest item.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/dashboard.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local checks:
  - `dashboard.php` active jQuery core include was already `js/jquery.js`.
  - Local `js/jquery.js` is jQuery `3.7.1`.
  - No old jQuery CDN/core references were found in `dashboard.php`.
- Local change:
  - Added explicit cache/version marker to the jQuery include: `js/jquery.js?v=3.7.1`.
- Verification:
  - `php -l dashboard.php` passed.
  - Focused scan found no old jQuery CDN/core references in `dashboard.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/dashboard.php` to `/home/stagingdocbox/public_html/dashboard.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 profile.php jQuery retest cleanup

- User asked to update the profile page for the jQuery retest item.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local findings:
  - `profile.php` had an active Google jQuery `1.11.2` include in the head.
  - `profile.php` also loaded local `js/jquery.js` near the bottom.
  - `profile.php` had an active external jQuery UI `1.12.1` include near the bottom.
  - Old jQuery/jQuery UI references also existed inside comments.
- Local changes:
  - Replaced the active Google jQuery `1.11.2` include with `js/jquery.js?v=3.7.1`.
  - Added `v=3.7.1` to the existing lower local jQuery include and updated its stale comment.
  - Replaced the external jQuery UI `1.12.1` include with `js/jquery-ui.js?v=1.14.2`.
  - Added `v=1.14.2` to the active jQuery UI CSS includes.
  - Removed obsolete commented old jQuery/jQuery UI references that could be flagged by source checks.
- Verification:
  - `php -l profile.php` passed.
  - Focused scan found no old jQuery core/UI references in `profile.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/profile.php` to `/home/stagingdocbox/public_html/profile.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 profile.php live sync check

- User confirmed `profile.php` was synced and asked to verify.
- Live checks:
  - Unauthenticated `https://staging.docbox.asia/profile.php` returns HTTP `302` to `/index.php` with no response body because of the page auth guard.
  - Following redirects shows `/index.php`; the old jQuery `1.11.2` line seen there belongs to the login page response, not the authenticated profile page.
  - Live `https://staging.docbox.asia/js/jquery.js` is jQuery `3.7.1`.
  - Live `https://staging.docbox.asia/js/jquery-ui.js` is jQuery UI `1.14.2`.
- Result:
  - Public unauthenticated source checks cannot inspect the authenticated `profile.php` body without a valid session.
  - Local `profile.php` remains clean for active old jQuery references and points to `js/jquery.js?v=3.7.1` and `js/jquery-ui.js?v=1.14.2`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 retest stored-script scope: home.php and Rectify Test VS

- User clarified the retest stored-script finding was sent for `patientInfo_oph_rectify_test_vs.html` and `home.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/home.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local review:
  - `home.php` was already routing early in browser JavaScript, but a browser still had to receive the page source.
  - Session values are available server-side after `docbox_require_page_auth()`: `DOCTOR_ID` and `HELPER_TYPE_ID`.
  - `js/home.js` patient-card rendering already escapes patient name, unique ID, diagnosis, gender, age, tags, and last visited date.
  - `patientInfo_oph_rectify_test_vs.js` has broad text-rendering helpers already in place, but the page remains large and still needs field-by-field review for any remaining raw rendering reported by the agency.
- Local change:
  - Converted `home.php` into a server-side router immediately after the auth guard.
  - Authenticated `home.php` requests now return only a `302` redirect and no `home.php` HTML/JS body:
    - helper type containing `c` goes to `/attendanceModule.php`
    - doctor/customer `1000` goes to `/home_test_b.php`
    - all others go to `/home_new.php`
  - Kept no-store/no-cache headers on the redirect response.
- Verification:
  - `php -l home.php` passed.
  - `node --check js/home.js` passed; no `home.js` changes were made in this step.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/home.php` to `/home/stagingdocbox/public_html/home.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 security remediation file inventory

- User asked for a list of files updated during the security remediation exercise before preparing the agency hash package.
- Local work:
  - Reviewed `stagingcontext.md` audit/remediation sections because this workspace is not a Git repository and has no commit history available.
  - Separated application deployment files from the internal context log.
  - No application code was changed in this inventory step.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 MD5_docbox copy folder preparation

- User asked to copy the security remediation files into a separate `MD5_docbox` folder without moving the source files, and to remove log/cache/temp files from that copy.
- Local work:
  - Created `/Users/apple/Documents/docbox_staging/MD5_docbox`.
  - Copied 161 security remediation files into `MD5_docbox` with the same relative paths as production deployment.
  - Source files were not moved or modified.
  - Scanned `MD5_docbox` for log/cache/temp artifacts using patterns such as `*.log`, `*.jsonl`, `.DS_Store`, `*.cache`, `*.tmp`, `*.bak`, `*.old`, `*.orig`, `*.save`, `*.swp`, `*~`, `__pycache__`, `.cache`, and `cache`.
  - No matching log/cache/temp artifacts were present in the copied set.
- Upload/hash package note:
  - The copied folder is local evidence material only and should not be uploaded to `/home/stagingdocbox/public_html/`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-25 ABDM bridge callback URL confirmation

- User confirmed the main ABDM bridge callback URL to keep in context:
  - `http://abdm.docbox.asia/api/abdm_consents_hip_notify.php`
- Treat this as the current main ABDM bridge callback URL unless the user updates it later.
- No application code was changed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-26 index.php redesign prompt preparation

- User plans to redesign the DocBox `index.php` landing/login page and asked for a detailed prompt to give ChatGPT.
- Scope is prompt/planning only; no application code was changed.
- Prompt should preserve existing login/OTP/registration integration hooks while asking for a fresh landing page design.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-27 staging-to-production merge planning

- User confirmed the security audit work is finished and wants to move from staging to production.
- Scope for this step is planning only; no application code was changed.
- Production deployment plan must preserve existing functionality and ensure staging security changes are applied correctly in production.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-28 ABDM M1 change scoping

- User said ABDM flow changes are needed and asked to start with M1.
- Local context review:
  - M1 maps to the ABHA journey: single-entry UI, Aadhaar-based ABHA creation, existing ABHA verification, ABHA address creation, ABHA card download, and patient linking back to DocBox.
  - Core M1 files include `Public/abdm_abha_single_entry.php`, `api/abdm_abha_request_otp.php`, `api/abdm_abha_enrol_by_aadhaar.php`, `api/abdm_verify_abha_by_otp.php`, `api/abdm_abha_unified_journey.php`, `api/abdm_abha_address_suggest.php`, `api/abdm_abha_address_create.php`, `api/abdm_abha_card_download.php`, and the main-server context-token/patient-link endpoints.
- No application code was changed in this scoping step.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-28 ABDM M1 test case review: entry options

- User test case: `https://abdm.docbox.asia/public/abdm_abha_single_entry.php` should show two options: `Create ABHA ID` and `Fetch ABHA Details`.
- Local review:
  - `Public/abdm_abha_single_entry.php` currently opens directly on the Aadhaar-based creation journey with title `Create ABHA Number Using Aadhaar`.
  - The existing/fetch-style ABHA branch exists later in the page as the existing-account verification section, but it is not exposed as a first-screen choice.
  - Linked-patient launches can skip to the existing ABHA verification branch using `launchMode=linked_abha`, but the normal page load does not show the two requested options.
- Result: not implemented as stated.
- No application code was changed in this review step.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-28 ABDM M1 test case review: four verification choices

- User test case: Fetch ABHA details should allow four verification choices:
  - ABHA Number verification using Aadhaar OTP.
  - ABHA Address verification using Aadhaar OTP.
  - ABHA Number verification using mobile OTP on the ABHA-linked mobile number.
  - ABHA Address verification using mobile OTP on the ABHA-linked mobile number.
- Local review:
  - `Public/abdm_abha_single_entry.php` currently has one identifier input, `verifyAbhaAddress`, and one mode selector, `otpMode`, with `mobile` and `aadhaar`.
  - `api/abdm_verify_abha_by_otp.php` accepts only `abhaAddress`; it has no ABHA-number input/branch.
  - `lib/AbhaVerificationService.php::requestOtp()` always uses `loginHint = abha-address` and only switches between `aadhaar-verify` and `mobile-verify`.
  - `lib/AbhaVerificationService.php::verifyOtp()` also always uses `abha-address-login`.
- Result: partial implementation only.
  - Implemented: ABHA Address verification using Aadhaar OTP.
  - Implemented: ABHA Address verification using mobile OTP.
  - Not implemented: ABHA Number verification using Aadhaar OTP.
  - Not implemented: ABHA Number verification using mobile OTP.
- No application code was changed in this review step.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-28 ABDM M1 four verification choices implementation

- User asked to start implementing the four fetch-details verification choices.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Updated the existing ABHA/fetch-details verification block in `Public/abdm_abha_single_entry.php` to show four explicit choices:
    - ABHA Number using Aadhaar OTP.
    - ABHA Address using Aadhaar OTP.
    - ABHA Number using mobile OTP.
    - ABHA Address using mobile OTP.
  - The identifier input now switches label, placeholder, input mode, and length handling based on ABHA Number vs ABHA Address.
  - ABHA Number input is normalized to digits and requires 14 digits before OTP request.
  - Existing linked-ABHA launch mode still opens the address/mobile path by default to preserve current DocBox-linked patient behavior.
  - Updated `api/abdm_verify_abha_by_otp.php` to accept `identifierType`, `identifierValue`, `abhaNumber`, and `abhaAddress` while preserving existing `abhaAddress` compatibility.
  - Updated `lib/AbhaVerificationService.php` so ABHA Number requests use `loginHint = abha-number` and scope `abha-login`, while ABHA Address requests continue using `loginHint = abha-address` and scope `abha-address-login`.
  - Aadhaar OTP continues using `aadhaar-verify` / `otpSystem = aadhaar`; mobile OTP continues using `mobile-verify` / `otpSystem = abdm`.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l lib/AbhaVerificationService.php` passed.
  - Extracted page script with PHP echo placeholders replaced by dummy strings and ran `node --check`; it passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/home/stagingdocbox/public_html/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/home/stagingdocbox/public_html/api/abdm_verify_abha_by_otp.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/home/stagingdocbox/public_html/lib/AbhaVerificationService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-28 ABDM M1 fetch-details verification moved to beginning

- User asked to show the verification/fetch-details part at the beginning of `Public/abdm_abha_single_entry.php`.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Added a beginning `Fetch ABHA Details` panel at the top of the first active stage before the Aadhaar create-flow consent section.
  - The new beginning panel exposes the same four verification choices:
    - ABHA Number using Aadhaar OTP.
    - ABHA Address using Aadhaar OTP.
    - ABHA Number using mobile OTP.
    - ABHA Address using mobile OTP.
  - Added separate beginning-panel controls and handlers so existing later-stage verification remains available for the Aadhaar flow's existing-account branch.
  - Beginning-panel verification can send OTP, verify OTP, show verified profile details, and enable verified ABHA card download.
  - Reset now clears the beginning-panel verification fields and result state.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Extracted page script with PHP echo placeholders replaced by dummy strings and ran `node --check`; it passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main server.

## 2026-05-28 ABDM M1 first-screen two-option selector

- User clarified the first section should have two options: one to directly verify/fetch ABHA details and one to create ABHA.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - Changed step 1 label from `Consent Collection` to `Choose Flow`.
  - Added two first-screen option cards:
    - `Fetch ABHA Details` for direct verification.
    - `Create ABHA ID` for Aadhaar-based ABHA creation.
  - The direct verification form and the create-ABHA consent form are hidden until the user chooses one option.
  - Added state handling so the selected first-screen option is kept in browser session storage during refresh.
  - Reset clears the selected first-screen option and returns to the two-card selector.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Extracted page script with PHP echo placeholders replaced by dummy strings and ran `node --check`; it passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main server.

## 2026-05-28 ABDM M1 ABHA Number OTP request HTTP 400 fix

- User reported after clicking verify using OTP: `OTP request completed. (HTTP 400, POST /api/abdm_verify_abha_by_otp.php)`.
- Local review:
  - The response text was misleading because `api/abdm_verify_abha_by_otp.php` used `OTP request completed.` as the fallback message even when the upstream response was HTTP 400.
  - ABHA Number verification was still being sent through the PHR-address login endpoint path used for ABHA Address verification.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Local changes:
  - `lib/AbhaVerificationService.php` now keeps ABHA Address verification on the existing PHR-address endpoint.
  - ABHA Number verification now uses the ABHA profile login endpoints:
    - `/v3/profile/login/request/otp`
    - `/v3/profile/login/verify`
    - `/v3/profile/account`
    - `/v3/profile/account/abha-card`
  - `api/abdm_verify_abha_by_otp.php` now passes identifier type into profile fetch after OTP verification.
  - Added safer response-message extraction so a failed OTP request no longer falls back to `OTP request completed.`
- Verification:
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l lib/AbhaVerificationService.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main server.

## 2026-05-28 ABDM M1 ABHA Number login identifier format adjustment

- User reported `ABHA Number using Aadhaar OTP` still returned: `Unable to request OTP for the selected verification details. (HTTP 400, POST /api/abdm_verify_abha_by_otp.php)`.
- Local change:
  - Kept the UI ABHA Number input digit-only for clean validation.
  - Added server-side ABHA Number formatting in `lib/AbhaVerificationService.php` before encrypting `loginId` for ABDM profile login.
  - A 14-digit ABHA Number is now sent to ABDM in standard display format: `XX-XXXX-XXXX-XXXX`.
  - Stored/session values remain the normalized 14-digit value used by DocBox.
- Verification:
  - `php -l lib/AbhaVerificationService.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main server.

## 2026-05-28 Add Patient ABHA verification prefill planning

- User asked whether the ABHA verification functionality can be added while registering a patient, so verified ABHA data can auto-populate the patient registration form.
- Local review:
  - `addPatient.php` is a DocBox main-server page and saves through `js/addPatient.js` to `sajid/insertPatientTest.php`.
  - Current add patient fields that can be safely prefilled from a verified ABHA profile include patient name, mobile number, gender, date of birth / age, address line, city / district, state, and email when available.
  - A patient ID is generated only during the existing save call, so ABHA linking should be handled after the patient is saved, or through a short-lived pre-registration token that is consumed after save.
- Recommended implementation:
  - Add a `Verify ABHA & Fill Patient Details` action on `addPatient.php`.
  - Reuse the existing ABDM / Lightsail verification flow rather than duplicating ABDM logic inside the main registration page.
  - Return only a sanitized verified-profile object to the add patient page.
  - Let the user preview the verified details before filling the form, with a default `Fill empty fields` action and an explicit `Replace all fields` action.
  - Preserve the existing add patient validation and backend save behavior.
- No add patient code changes were made in this planning step.

## 2026-05-28 Add Patient ABHA two-server integration plan

- User clarified that ABDM APIs are on the ABDM / Lightsail server while `addPatient.php` is on the DocBox main VPS.
- Local review:
  - Existing ABDM handoff currently supports a main-server patient context token after a patient already exists.
  - Add Patient does not have a patient ID until `sajid/insertPatientTest.php` completes, so this registration flow needs a temporary pre-registration verification token instead of the existing patient handoff token.
- Planned server split:
  - DocBox main VPS owns the add patient UI, browser session, registration save, and final patient ID.
  - ABDM / Lightsail server owns OTP verification and ABHA profile retrieval.
  - A short-lived pre-registration token links the two without sending raw identifiers through URLs or local storage.
- Recommended flow:
  - Main VPS creates a `registrationToken` for the logged-in doctor/helper and opens the Lightsail ABHA verification page with `mode=registration_prefill`.
  - Lightsail completes one of the four verification modes and posts a sanitized profile back to a signed main-VPS callback endpoint.
  - Main VPS stores the sanitized profile against the token for a short TTL.
  - `addPatient.php` polls/reads the profile by token and fills the form only after the user confirms.
  - On final save, `sajid/insertPatientTest.php` creates the patient ID, then stores or links the verified ABHA details for that new patient.
- No add patient code changes were made in this planning step.

## 2026-05-28 Add Patient ABHA OWASP checklist constraint

- User asked to keep OWASP Top 10 checks in mind while performing the Add Patient ABHA verification updates.
- Current reference checked from official OWASP Top 10 project page: the current released version is OWASP Top 10 2025.
- Implementation constraint for this feature:
  - Validate authorization on every main-VPS and ABDM / Lightsail endpoint involved in the pre-registration flow.
  - Use signed server-to-server callbacks for profile transfer.
  - Keep registration tokens short-lived, one-time-use where possible, and bound to the logged-in doctor/helper.
  - Do not store OTPs, Aadhaar values, session cookies, authorization headers, or raw sensitive verification material in logs or browser storage.
  - Validate and encode all profile fields before rendering into `addPatient.php`.
  - Preserve existing add patient server-side validation in `sajid/insertPatientTest.php`.
  - Add clear error handling for expired tokens, incomplete verification, and patient-save failure.
  - Keep upload/deployment split explicit between DocBox main VPS and ABDM / Lightsail bridge server.
- No add patient code changes were made in this planning step.

## 2026-05-28 ABDM ABHA verification test-case spreadsheet review

- User provided `/Users/apple/Downloads/Untitled spreadsheet (3).xlsx` and asked to analyze the test cases and verification steps.
- Workbook structure:
  - One sheet: `Sheet1`.
  - Four mandatory ABHA verification cases:
    - ABHA Number verification using Aadhaar OTP.
    - ABHA Address verification using Aadhaar OTP.
    - ABHA Number verification using mobile OTP on the ABHA-linked mobile number.
    - ABHA Address verification using mobile OTP on the ABHA-linked mobile number.
- Spreadsheet expectations:
  - User shares ABHA Number or ABHA Address.
  - User receives OTP according to the selected verification channel.
  - User enters OTP.
  - Resend OTP may become available after 60 seconds and should be limited to a maximum of 2 resends per attempt.
  - Correct OTP should fetch ABHA profile fields such as name, date of birth, gender, mobile, photo, address, state, district, ABHA Number, and ABHA Address.
  - Incorrect OTP should fail cleanly.
  - Name, date of birth, and gender should be treated as verified/non-editable after verification; address/email/mobile/state/district/city may remain editable as per business rules.
  - Verified details should be saved in HIMS and linked to the HIMS beneficiary/patient ID.
- Local implementation mapping:
  - Existing ABDM / Lightsail ABHA page already exposes the four verification choices.
  - `api/abdm_verify_abha_by_otp.php` supports identifier type, Aadhaar/mobile mode, OTP request, OTP verification, profile fetch, and OTP limiter keys.
  - `lib/AbhaVerificationService.php` routes ABHA Number verification to ABHA profile endpoints and ABHA Address verification to PHR-address endpoints.
  - Add Patient registration does not yet implement the registration prefill/linking behavior described by the spreadsheet.
- No application code changes were made in this review step.

## 2026-05-28 Add Patient ABHA verification prefill implementation

- User asked to patch the code for adding ABHA verification while registering a patient, keeping the two-server split and OWASP checks in mind.
- Files opened in the local editor before edits:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
  - New API file paths under `/Users/apple/Documents/docbox_staging/api/` were also opened before creation; the editor reported they did not exist yet.
- Main VPS changes:
  - Added ABHA verification panel to `addPatient.php`.
  - Added CSRF token exposure for the new Add Patient ABHA APIs.
  - Added `api/abha_registration_prefill_common.php` for token table setup, profile sanitization, and shared helper functions.
  - Added `api/abha_registration_prefill_token_create.php` to create short-lived doctor-bound registration tokens and return the Lightsail verification URL.
  - Added `api/abha_registration_prefill_status.php` so `addPatient.php` can poll for verified profile availability.
  - Added `api/internal_abha_registration_prefill_store.php` as the signed Lightsail-to-main callback that stores sanitized verified profile data against the registration token.
  - Added `api/abha_registration_prefill_link_patient.php` to link the verified ABHA details to the newly created patient after `sajid/insertPatientTest.php` returns the patient ID.
  - The helper creates `abdm_registration_prefill_tokens` if missing and ensures `abdm_patient_abha_map` exists if the target environment does not already have it.
- ABDM / Lightsail changes:
  - Added `api/abdm_registration_prefill_store.php`, which reads the verified profile from the Lightsail verification session, sanitizes it, and posts it to the signed main-VPS callback.
  - This endpoint intentionally avoids the generic `bridgeRequest()` debug logger so verified profile fields are not written into the ABDM JSON debug log.
  - Updated `Public/abdm_abha_single_entry.php` to support `mode=registration_prefill&registrationToken=...`.
  - Registration-prefill mode opens directly into the existing ABHA verification branch and stores verified profile data back to the main VPS after successful OTP verification.
- Add Patient UI behavior:
  - `js/addPatient.js` can start ABHA verification, open the Lightsail verification page, poll for completion, render a verified profile preview, and fill the registration form.
  - Name, date of birth, age, and gender are locked after verified profile fill.
  - Mobile, email, address, area/district, city, and state remain editable as per the test-case expectations.
  - After patient save, the verified ABHA details are linked to the new patient ID before continuing the existing registration redirect flow.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l api/abha_registration_prefill_status.php` passed.
  - `php -l api/abha_registration_prefill_link_patient.php` passed.
  - `php -l api/internal_abha_registration_prefill_store.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered `Public/abdm_abha_single_entry.php` to `/private/tmp/abha_prefill_render.html`, extracted inline script to `/private/tmp/abha_prefill_inline.js`, and `node --check /private/tmp/abha_prefill_inline.js` passed.
- Upload required:
  - Main VPS / DocBox staging server:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_status.php`
    - `/Users/apple/Documents/docbox_staging/api/internal_abha_registration_prefill_store.php` to `/home/stagingdocbox/public_html/api/internal_abha_registration_prefill_store.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - ABDM / Lightsail bridge server:
    - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php`
    - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php`

## 2026-05-28 Add Patient ABHA prefill URL case fix

- User reported `Not Found` after the Add Patient ABHA prefill patch.
- Root cause:
  - `api/abha_registration_prefill_token_create.php` generated the Lightsail verification URL with lowercase `/public/abdm_abha_single_entry.php`.
  - The deployed folder path is uppercase `/Public/abdm_abha_single_entry.php`.
- Local change:
  - Updated the generated verification URL to `/Public/abdm_abha_single_entry.php`.
- Verification:
  - `php -l api/abha_registration_prefill_token_create.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA prefill verification-only mode fix

- User reported `Network or server error while requesting Aadhaar OTP` and that there was no verification option.
- Local change:
  - Updated `Public/abdm_abha_single_entry.php` so `mode=registration_prefill` or `launchMode=registration_prefill` forces the page into the existing-ABHA verification section.
  - In registration-prefill mode, the first-screen create options and Aadhaar-create section are hidden.
  - The Aadhaar-create OTP handler now blocks itself in registration-prefill mode with a clear message and returns to the ABHA verification section.
  - The Aadhaar-create OTP catch block now shows the actual thrown message when available instead of always showing the generic network message.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php` and `node --check /private/tmp/abha_prefill_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Separate add-patient ABHA verification page

- User requested a separate page for ABHA verification from Add Patient, keeping `Public/abdm_abha_single_entry.php` dedicated to the normal patient-profile ABHA flow.
- Added `Public/abdm_add_patient_abha_verify.php` for Add Patient only.
- Page behavior:
  - Requires a 48-character registration token in `registrationToken`.
  - Supports four verification choices:
    - ABHA Number with Aadhaar OTP.
    - ABHA Address with Aadhaar OTP.
    - ABHA Number with linked-mobile OTP.
    - ABHA Address with linked-mobile OTP.
  - Uses existing Lightsail API wrappers:
    - `../api/abdm_verify_abha_by_otp.php` for OTP request and verification.
    - `../api/abdm_abha_address_select.php` when ABHA Number verification returns multiple ABHA Addresses.
    - `../api/abdm_registration_prefill_store.php` to send the verified profile back to the main server token.
  - Uses DOM text APIs for dynamic display instead of raw HTML string insertion.
  - Uses no external scripts or styles on this page.
- Updated Add Patient launch:
  - `js/addPatient.js` now opens `/Public/abdm_add_patient_abha_verify.php`.
  - `api/abha_registration_prefill_token_create.php` now returns the new page URL.
  - `addPatient.php` cache-busts `js/addPatient.js` with version `3.95`.
- Updated `api/abdm_registration_prefill_store.php`:
  - The verified session profile now carries selected/verified ABHA Address and ABHA Number into the stored prefill profile when the returned profile uses alternate field names.
- Verification:
  - `php -l Public/abdm_add_patient_abha_verify.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered inline JavaScript from `Public/abdm_add_patient_abha_verify.php` passed `node --check`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_add_patient_abha_verify.php` to `/var/www/html/abdm-app/Public/abdm_add_patient_abha_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Inline Add Patient ABHA verification through backend bridge

- User requested that Add Patient should not open a new Lightsail window for ABHA verification.
- Implemented inline Add Patient verification:
  - `addPatient.php` now contains the verification method, identifier, OTP, and ABHA Address selection UI inside the existing ABHA panel.
  - `js/addPatient.js` no longer opens a Lightsail browser window.
  - Browser calls stay on the DocBox staging main VPS.
- Added main VPS API:
  - `api/abha_registration_prefill_verify_proxy.php`
  - Requires authenticated Add Patient session and CSRF.
  - Validates the registration token belongs to the logged-in doctor context.
  - Sends signed server-to-server requests to the Lightsail bridge API.
  - Stores the verified profile into `abdm_registration_prefill_tokens` once verification is complete or an ABHA Address is selected.
- Added Lightsail bridge API:
  - `api/internal_abdm_registration_verify.php`
  - Requires signed bridge headers.
  - Stores verification transaction state by registration token hash in `abdm_registration_verify_state`.
  - Supports `request_otp`, `verify_otp`, and `select_address`.
  - Uses existing `AbhaVerificationService` v3 verification APIs.
- Updated token creation:
  - `api/abha_registration_prefill_token_create.php` now returns `verificationMode = inline` instead of a Lightsail page URL.
- Updated cache busting:
  - `addPatient.php` now loads `js/addPatient.js?v=3.96`.
- Verification:
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Inline Add Patient ABHA verification UI simplification

- User requested replacing the four ABHA verification choices with automatic detection of ABHA Number vs ABHA Address.
- Updated `addPatient.php`:
  - The ABHA panel now asks for a single "ABHA Number or ABHA Address" value.
  - It shows two action buttons only:
    - Verify by Aadhaar OTP.
    - Verify by linked-mobile OTP.
  - Updated `js/addPatient.js` cache version to `3.97`.
- Updated `js/addPatient.js`:
  - Detects ABHA Number when the entered value is a 14-digit number, with spaces/hyphens tolerated.
  - Detects ABHA Address when the value contains a valid address suffix format.
  - Shows detected type before requesting OTP.
  - Sends the detected identifier type and selected OTP mode to the existing main VPS proxy API.
  - Removed old four-method button handling.
- Verification:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA copy button restricted by link check

- User clarified that `Copy details` should only be shown if the verified ABHA Address is not already linked to a DocBox profile.
- Updated `api/abha_registration_prefill_verify_proxy.php`:
  - Returns `copyAllowed = false` and `addressConflict = true` when the verified ABHA Address is already linked.
  - Returns `copyAllowed = true` only after the ABHA Address passes the DocBox link check and the profile is stored for this registration token.
- Updated `addPatient.php`:
  - `Copy details` button is hidden by default.
  - Updated `js/addPatient.js` cache version to `4.01`.
- Updated `js/addPatient.js`:
  - Shows `Copy details` only when `copyAllowed === true`.
  - Keeps the button hidden on address-conflict responses.
  - Prevents copying unless the current verified state has `copyAllowed`.
- Verification:
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA custom alerts and OTP resend limits

- User requested custom alert boxes and human-readable messages for the inline Add Patient ABHA flow.
- User also requested resend OTP cooldown and maximum-attempt handling.
- Updated `addPatient.php`:
  - Added `abhaPrefillAlert` custom Bootstrap-style alert box inside the ABHA panel.
  - Added OTP request status text under the Aadhaar/mobile OTP buttons.
  - Updated `js/addPatient.js` cache version to `3.99`.
- Updated `js/addPatient.js`:
  - Shows success, warning, and error messages in the custom alert box instead of relying only on inline text.
  - Uses the same custom alert box for ABHA link success/failure after the patient record is saved.
  - Keeps progress text in `abhaPrefillStatus`.
  - Disables OTP request buttons during cooldown.
  - Shows countdown text while resend is cooling down.
  - Shows OTP request usage count.
  - Disables further OTP requests when the server reports the attempt limit has been reached.
  - Keeps OTP verification and ABHA Address selection behavior unchanged.
- Updated `api/internal_abdm_registration_verify.php`:
  - Replaced the generic OTP limit call in this Add Patient verification path with a flow-specific limit helper.
  - Returns human-readable limit messages.
  - Returns `retryAfterSeconds`, `cooldownSeconds`, `otpRequestsUsed`, `maxOtpRequests`, `remainingOtpRequests`, `attemptWindowSeconds`, and `limitReached`.
  - Uses the existing configured cooldown, max resend count, and attempt window.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA copy details action

- User requested that after OTP verification, when the ABHA Address is not linked to any DocBox profile, the UI should show a `Copy details` button.
- Updated `addPatient.php`:
  - Replaced the older `Fill empty fields` and `Replace all fields` buttons with a single `Copy details` button.
  - Updated `js/addPatient.js` cache version to `4.00`.
- Updated `js/addPatient.js`:
  - `Copy details` copies the verified ABHA profile into the Add Patient form fields.
  - It copies relevant available fields: name, mobile, email, address line, area/district, city, state, DOB/age, and gender.
  - Name, DOB, age, and gender remain locked after copy because those values came from the verified profile.
  - Shows a custom success alert after copying.
  - If the ABHA Address is already linked, the backend still blocks before the preview/copy action is shown.
- Verification:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA create-address button after verification

- User requested a "Create New ABHA Address" button after OTP verification.
- Updated `addPatient.php`:
  - Added `Create New ABHA Address` button under the ABHA Address selection list.
  - Updated `js/addPatient.js` cache version to `3.98`.
- Updated `js/addPatient.js`:
  - Button appears in the ABHA Number verified state where ABHA Addresses are listed.
  - Click currently shows a clear inline notice and status message instead of calling the earlier address-creation path that returned invalid transaction errors.
  - The existing verification and returned-address selection behavior is unchanged.
- Verification:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA prefill two-choice mode restoration

- User clarified that the Add Patient ABHA prefill popup must still have two buttons: one for ABHA verification and another for ABHA creation.
- Local change:
  - Updated `Public/abdm_abha_single_entry.php` so registration-prefill mode again shows the two first-screen choices:
    - Verify ABHA.
    - Create ABHA.
  - Removed the registration-prefill block that prevented Aadhaar-create OTP from running.
  - Registration-prefill mode now starts on the two-choice screen and explains both choices.
  - When a new ABHA address is created successfully, the page stores the created ABHA profile back to Add Patient through the same signed prefill callback.
  - Updated `api/abdm_registration_prefill_store.php` so it can store either an existing verified ABHA profile from `abha_verify` session or a newly created ABHA profile from `abha_create` session.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php` and `node --check /private/tmp/abha_prefill_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA popup URL hardening

- User reported that Add Patient was calling `abdm_abha_single_entry.php?mode=registration_prefill` without the registration token.
- Local change:
  - Updated `addPatient.php` to expose the ABDM base URL to `js/addPatient.js`.
  - Bumped the Add Patient JS cache version from `3.88` to `3.89`.
  - Updated `js/addPatient.js` to build the Lightsail popup URL from the returned `registrationToken`.
  - The popup URL is now forced to `/Public/abdm_abha_single_entry.php?mode=registration_prefill&registrationToken=...` even if the API response contains a stale, lowercase, partial, or missing `verificationUrl`.
- Verification:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA two-button launch mode rename

- User clarified they do not want Add Patient to open a URL that appears to be registration; they want the popup to open the two ABHA choice buttons.
- Local change:
  - Updated Add Patient popup URL generation in `js/addPatient.js` to use `mode=add_patient_abha` instead of `mode=registration_prefill`.
  - Updated `api/abha_registration_prefill_token_create.php` to return `mode=add_patient_abha` in the generated verification URL.
  - Updated `Public/abdm_abha_single_entry.php` so both `mode=add_patient_abha` and the older `mode=registration_prefill` still activate the Add Patient prefill callback behavior.
  - The popup still carries `registrationToken`, but opens on the two-button ABHA choice screen.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered `Public/abdm_abha_single_entry.php` and `node --check /private/tmp/abha_prefill_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA token-driven two-button entry

- User reported that the ABHA page still showed only the registration/create part.
- Local change:
  - Updated `Public/abdm_abha_single_entry.php` so the presence of `registrationToken` is enough to activate Add Patient mode, even if `mode` is stale, missing, or cached.
  - Updated the page title in Add Patient mode from `Create ABHA Number Using Aadhaar` to `ABHA Verification / Creation`.
  - The Add Patient mode continues to start with the two first-screen buttons.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php` and `node --check /private/tmp/abha_prefill_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA cache-bust after two-button URL change

- User still saw only the registration/create part and no two buttons.
- Deep local check:
  - Rendering `Public/abdm_abha_single_entry.php` locally with `registrationToken` shows title `ABHA Verification / Creation`, `registrationPrefillMode = true`, and the `m1EntryOptions` two-button block.
  - Rendering with `mode=add_patient_abha` also shows `registrationPrefillMode = true` and the two-button block.
  - The remaining Add Patient issue was that `js/addPatient.js` had changed after the last cache-bust, but `addPatient.php` still loaded `js/addPatient.js?v=3.89`.
- Local change:
  - Updated `addPatient.php` to load `js/addPatient.js?v=3.90`.
- Verification:
  - `php -l addPatient.php` passed.
  - Local render checks for `registrationToken` and `mode=add_patient_abha` confirmed the two-button ABHA entry block is present.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA forced choice-start patch

- User still saw only the registration/create section and not the two ABHA buttons.
- Deep local review:
  - Local render continued to show the two-button `m1EntryOptions` block when `registrationToken` or Add Patient mode was present.
  - The remaining likely causes were stale popup `sessionStorage`, reused named popup window state, or cached Add Patient JS.
- Local change:
  - Updated `js/addPatient.js` so the generated ABHA popup URL includes `start=choice` and `_ts=Date.now()`.
  - Updated `js/addPatient.js` to open a token-specific popup window name instead of always reusing `docboxAbhaPrefill`.
  - Updated `api/abha_registration_prefill_token_create.php` so its returned URL also includes `start=choice` and a timestamp.
  - Updated `Public/abdm_abha_single_entry.php` so `start=choice` activates Add Patient mode.
  - Strengthened `applyRegistrationPrefillUi()` to reset to step 1, clear selected entry mode, show `m1EntryOptions`, and explicitly hide both the quick-verification form and Aadhaar-create registration form until the user clicks a choice.
  - Bumped `addPatient.php` cache-busting from `js/addPatient.js?v=3.90` to `v=3.91`.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered `Public/abdm_abha_single_entry.php` with `registrationToken` + `start=choice`; output confirmed `ABHA Verification / Creation`, `registrationPrefillMode = true`, `m1EntryOptions`, and both branch forms hidden initially.
  - Extracted rendered inline script and `node --check /private/tmp/abha_choice_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA direct-page launch adjustment

- User confirmed that opening `abdm_abha_single_entry.php` directly shows the two buttons, but Add Patient still showed only the registration/create Aadhaar form.
- Local change:
  - Removed the `mode` parameter from the Add Patient ABHA launch URL in `js/addPatient.js`.
  - Removed the `mode` parameter from the fallback URL returned by `api/abha_registration_prefill_token_create.php`.
  - The Add Patient popup now opens the same direct ABHA page URL with only `registrationToken`, `start=choice`, and `_ts` appended.
  - Removed stale `mode` and `launchMode` params from any API-returned URL before opening the popup.
  - Bumped Add Patient JS cache-busting from `v=3.91` to `v=3.92`.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered `Public/abdm_abha_single_entry.php` with direct-page token params only; output confirmed the two-button block and both branch forms hidden initially.
  - Extracted rendered inline script and `node --check /private/tmp/abha_direct_token_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA bridge-domain fix

- User showed the generated Add Patient ABHA URL was incorrectly using the main VPS domain:
  - `https://staging.docbox.asia/Public/abdm_abha_single_entry.php?...`
- Root cause:
  - `addPatient.php` and `api/abha_registration_prefill_token_create.php` were allowed to derive the ABHA public base URL from the main VPS app config, which can resolve to `https://staging.docbox.asia`.
  - `js/addPatient.js` also accepted the host from the API-returned URL.
- Local change:
  - `addPatient.php` now defaults the ABHA popup base URL to `https://abdm.docbox.asia`, with only an explicit `ABDM_BRIDGE_PUBLIC_BASE_URL` constant allowed to override it.
  - `api/abha_registration_prefill_token_create.php` now returns `https://abdm.docbox.asia/Public/abdm_abha_single_entry.php?...` by default, with the same explicit override option.
  - `js/addPatient.js` now ignores the host in the returned `verificationUrl` and always builds the popup URL from `window.addPatientAbhaConfig.abdmBaseUrl`.
  - Bumped Add Patient JS cache-busting from `v=3.92` to `v=3.93`.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA verification Runtime Error handling

- User reported `Runtime Error (HTTP 400, POST /api/abdm_verify_abha_by_otp.php)`.
- Local review:
  - The quick ABHA Address verification path first calls `action=search` on `api/abdm_verify_abha_by_otp.php`.
  - If that upstream lookup returns a generic `Runtime Error`, the page previously stopped before attempting the actual OTP request.
- Local change:
  - Updated `Public/abdm_abha_single_entry.php` so the ABHA Address lookup is non-blocking; it logs the result and proceeds to the OTP request.
  - Added clearer UI messages when ABDM returns generic `Runtime Error` during OTP request or OTP verification.
- Verification:
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abha_runtime_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA verify OTP failure message fix

- User reported `OTP verification completed. (HTTP 400, POST /api/abdm_verify_abha_by_otp.php)`.
- Root cause:
  - `api/abdm_verify_abha_by_otp.php` returned HTTP 400 for failed OTP verification but still used the fallback message `OTP verification completed.`
- Local change:
  - Added a `$verificationSucceeded` flag in the `verify_otp` branch.
  - OTP profile fetch now runs only after a successful verify response.
  - Failed verify responses now use `abhaVerifyResponseMessage(...)` with fallback `Unable to verify OTP for the selected ABHA details.`
- Verification:
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Add Patient ABHA already-linked address handling

- User clarified that registered mobile OTP is the preferred verification path, and that if an ABHA Address is already linked to another HMIS patient, the flow should offer creation of another ABHA Address for the same ABHA Number.
- Local change:
  - Main VPS callback now checks `abdm_patient_abha_map` during Add Patient prefill storage. If the ABHA Address is already linked for the same doctor context, it stores the token as `address_conflict` and returns `ABHA_ADDRESS_ALREADY_LINKED` with `canCreateNewAddress=true`.
  - Add Patient polling now displays the exact already-linked message while keeping the polling session alive so the popup can continue after a new address is created.
  - Lightsail ABHA page now shows a persistent action to create another ABHA Address when the main server reports an already-linked address.
  - The address suggestion/create endpoints can use the verified ABHA session transaction as a fallback for the new-address path.
  - After a new ABHA Address is created, the verified profile session is updated with that address before the prefill callback is retried.
  - Updated the verification labels from generic mobile OTP wording to registered mobile OTP wording.
  - Bumped Add Patient JS cache-busting from `v=3.93` to `v=3.94`.
- Verification:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/internal_abha_registration_prefill_store.php` passed.
  - `php -l api/abha_registration_prefill_status.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - `node --check js/addPatient.js` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abha_registration_prefill_store.php` to `/home/stagingdocbox/public_html/api/internal_abha_registration_prefill_store.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_status.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA address creation failure message fix

- User reported that ABHA Address creation returned `ABHA address creation completed. (HTTP 400, POST /api/abdm_abha_address_create.php)`.
- Root cause:
  - `api/abdm_abha_address_create.php` used the same fallback message for both successful and failed ABDM responses.
- Local change:
  - Added a response-message helper that reads ABDM error/message fields safely.
  - Failed address-create responses now return `Unable to create the ABHA address. Please choose a different ABHA address and try again.` when ABDM does not provide a clearer message.
  - Successful address-create responses now use `ABHA address created successfully.` as the fallback.
- Verification:
  - `php -l api/abdm_abha_address_create.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Number verification address selection

- User requested that ABHA Number verification must list ABHA Addresses linked to the verified ABHA Number, allow selecting one, and also allow creating a new ABHA Address with suggestions/manual entry before filling Add Patient.
- Local change:
  - Added `api/abdm_abha_address_select.php` on the ABDM / Lightsail bridge side to accept a selected ABHA Address from the verified profile list and update the verification session profile.
  - Updated `api/abdm_verify_abha_by_otp.php` so successful ABHA Number verification returns `identifierType`, `abhaAddresses`, `requiresAddressSelection`, and `canCreateNewAddress`.
  - Updated `Public/abdm_abha_single_entry.php` so ABHA Number verification pauses after OTP verification and shows linked ABHA Address choices plus a `Create New ABHA Address` option.
  - Existing ABHA Address verification still continues directly to patient registration prefill.
  - If the user selects a linked ABHA Address, the selected address is stored in the Lightsail session and then sent to the Add Patient prefill callback.
  - If the user creates a new ABHA Address, the verified profile session is updated with the new address before the Add Patient callback runs.
  - Updated `api/abdm_abha_address_create.php` to return the updated verified profile after a new ABHA Address is created.
  - Updated `api/abdm_registration_prefill_store.php` to require ABHA Address selection/creation before allowing an ABHA Number-only profile to be stored for Add Patient.
  - Updated ABHA profile sanitizers to recognize `ABHANumber` and `preferredAddress` in addition to existing keys.
  - Updated the ABHA page key/value renderer to HTML-encode profile values before display.
- Verification:
  - `php -l api/abdm_abha_address_select.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_select.php` to `/var/www/html/abdm-app/api/abdm_abha_address_select.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Number new-address transaction guard

- User reported `Invalid Transaction Id (HTTP 400, POST /api/abdm_abha_address_create.php)` while creating a new ABHA Address after ABHA Number verification.
- Root cause:
  - The new-address endpoint uses the enrollment ABHA Address API and requires an enrollment transaction.
  - ABHA Number verification returns a login verification transaction, which ABDM does not accept for the enrollment ABHA Address API.
- Local change:
  - `api/abdm_verify_abha_by_otp.php` now stores the ABHA Number verification transaction as `login_txn_id`, not as an address-creation transaction.
  - ABHA Number verification responses now return `canCreateNewAddress=false` with a clear message explaining that the user must select a linked ABHA Address or start the Create ABHA flow to create another address.
  - `api/abdm_abha_address_suggest.php` and `api/abdm_abha_address_create.php` now use only `abha_create.enrol_txn_id` for suggestions/creation, preventing a login transaction from being sent to the enrollment address API.
  - `Public/abdm_abha_single_entry.php` now blocks the `Create New ABHA Address` action when the current session does not have an enrollment transaction and shows a persistent alert instead of making the failing API call.
- Verification:
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Number verified-session new ABHA Address flow

- User reported that after selecting a fetched ABHA Address already linked to another HMIS profile, clicking `Create New ABHA Address` still showed the earlier not-available message.
- Local change:
  - Kept the existing Aadhaar-created ABHA Address path unchanged.
  - Added a separate ABDM PHR registration-by-ABHA-Number path for verified ABHA Number sessions.
  - `config/config.php` now has `abha_phr_registration_base_url` with an `ABHA_PHR_REGISTRATION_BASE_URL` override for the PHR registration endpoint family.
  - `lib/AbhaService.php` now supports ABHA Address availability check, PHR registration init, OTP request, OTP confirmation, and final ABHA Address creation for the verified ABHA Number path.
  - `api/abdm_verify_abha_by_otp.php` now returns `canCreateNewAddress=true` when ABHA Number verification succeeds and the ABHA Number is present in the verified profile.
  - ABHA Number verification now clears any stale enrollment transaction from the same browser session so the new-address button uses the correct PHR registration path.
  - `api/abdm_abha_address_suggest.php` now returns local suggestions from the verified ABHA profile when the session came from ABHA Number verification.
  - `api/abdm_abha_address_create.php` now routes ABHA Number verified sessions through the PHR registration sequence, asks for the creation OTP, then updates the session profile with the newly created ABHA Address before Add Patient prefill storage runs.
  - `Public/abdm_abha_single_entry.php` now shows an OTP confirmation block after `Create New ABHA Address` for this path and then continues the Add Patient prefill flow after the new address is created.
- Verification:
  - `php -l config/config.php` passed.
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/config/config.php` to `/var/www/html/abdm-app/config/config.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Address availability pre-check response handling

- User checked `abdm_txn_log` and found `phr_address_availability` returning `Please make a valid request.`
- Local change:
  - Updated `api/abdm_abha_address_create.php` so the ABHA Address availability pre-check uses the local address part before `@abdm`.
  - The availability pre-check no longer stops the flow when ABDM returns the generic `Please make a valid request.` response. In that case the code continues to the creation start step so the main creation flow can return the next specific response.
  - Added step-specific messages for creation start, OTP request, OTP confirmation, and final address creation so future UI errors show exactly which step returned the response.
  - The confirmation step now sends the local PHR address value to ABDM while DocBox continues storing/displaying the full `@abdm` address.
- Verification:
  - `php -l api/abdm_abha_address_create.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Address PHR init request format adjustment

- User checked `abdm_txn_log` and found:
  - `phr_address_availability` returned `Please make a valid request.`
  - `phr_hid_address_init` also returned `Please make a valid request.`
- Local change:
  - Updated `lib/AbhaService.php` so `registration/hid/init` receives the ABHA Number as 14 digits instead of the hyphenated display format.
  - Updated `api/abdm_abha_address_create.php` so the final PHR address creation request uses the full `name@abdm` address again, while the availability pre-check keeps using the local address part.
- Verification:
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Address creation reset to v3-only APIs

- User confirmed the ABHA work must use v3 APIs only.
- Local change:
  - Removed the temporary non-v3 PHR registration configuration from `config/config.php`.
  - Removed the temporary non-v3 PHR registration wrapper methods from `lib/AbhaService.php`; the service now keeps ABHA enrollment/profile calls on v3 endpoints.
  - `api/abdm_abha_address_create.php` now creates an ABHA Address only when the v3 enrollment transaction exists in `abha_create.enrol_txn_id`.
  - `api/abdm_abha_address_suggest.php` now returns suggestions only during the v3 Create ABHA flow.
  - `api/abdm_verify_abha_by_otp.php` no longer exposes ABHA Number verification as an address-creation session; it returns `canCreateNewAddress=false` and clears any stale address-creation session alias.
  - `api/abdm_abha_address_select.php` now only accepts a linked ABHA Address from the ABDM-returned verified list.
  - `api/abdm_registration_prefill_store.php`, `api/internal_abha_registration_prefill_store.php`, and `api/abha_registration_prefill_status.php` now show wording that sends users to the v3 Create ABHA flow when a new ABHA Address is required.
  - `Public/abdm_abha_single_entry.php` now disables `Create New ABHA Address` for ABHA Number verification sessions that do not have a v3 enrollment transaction, and offers a `Start Create ABHA Flow` action when patient registration sees an already-linked ABHA Address.
- Expected runtime behavior:
  - ABHA Number verification lists the ABHA Addresses returned by ABDM and lets the user select one.
  - New ABHA Address creation is available only from the v3 Create ABHA path.
  - After upload, no new `phr_address_*` or `phr_hid_*` transaction rows should appear from this screen.
- Verification:
  - `php -l config/config.php` passed.
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_select.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l api/internal_abha_registration_prefill_store.php` passed.
  - `php -l api/abha_registration_prefill_status.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/config/config.php` to `/var/www/html/abdm-app/config/config.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_select.php` to `/var/www/html/abdm-app/api/abdm_abha_address_select.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/internal_abha_registration_prefill_store.php` to `/home/stagingdocbox/public_html/api/internal_abha_registration_prefill_store.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_status.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Re-enable new ABHA Address after ABHA Number verification using v3 calls only

- User clarified that after ABHA Number OTP verification, the user should still be able to create a new ABHA Address.
- Local change:
  - Kept the older non-v3 PHR registration path removed.
  - `api/abdm_verify_abha_by_otp.php` now stores the ABHA Number verification transaction as `abha_verify.address_create_txn_id` and returns `canCreateNewAddress=true` when that transaction is present.
  - `api/abdm_abha_address_suggest.php` now uses either the v3 Create ABHA enrollment transaction or the verified ABHA Number transaction for v3 address suggestions, and passes the profile token when available.
  - `api/abdm_abha_address_create.php` now uses either the v3 Create ABHA enrollment transaction or the verified ABHA Number transaction for v3 address creation, validates the entered ABHA Address locally, strips any suffix before sending, and stores the returned/new address in the verified profile session.
  - `lib/AbhaService.php` now allows the v3 address suggestion/create calls to include an `X-token` header when the verified profile token is available.
  - `api/abdm_registration_prefill_store.php` now reports `canCreateNewAddress=true` when the verified ABHA Number session has an address-creation transaction but no selected ABHA Address yet.
  - `Public/abdm_abha_single_entry.php` now enables `Create New ABHA Address` after ABHA Number verification when the API response provides `canCreateNewAddress=true`.
- Expected runtime behavior:
  - ABHA Number verification lists linked ABHA Addresses and enables `Create New ABHA Address`.
  - The new-address button loads suggestions through v3, allows typing a custom address, and posts to the v3 address creation endpoint.
  - If ABDM does not accept the verified transaction for creation, the UI will show the ABDM response without using the removed non-v3 path.
- Verification:
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA verification and registration API map

- User requested an API inventory before changing behavior for this flow:
  - User chooses Verify ABHA.
  - User chooses one of four verification methods.
  - After OTP verification, all returned ABHA Addresses should be listed.
  - ABHA Addresses already linked to an HMIS patient should be identified and disabled.
  - User may type a new ABHA Address, create it, and link it to the patient being registered.
- Current entry points:
  - Main VPS page: `addPatient.php` shows the ABHA verification panel.
  - Main VPS JS: `js/addPatient.js` creates a registration token, opens the ABDM bridge page, polls the token status, fills patient fields, and links verified ABHA details after patient save.
  - ABDM / Lightsail page: `Public/abdm_abha_single_entry.php` renders the Verify ABHA and Create ABHA choices.
- Main VPS registration APIs:
  - `api/abha_registration_prefill_token_create.php`: creates a 30-minute registration token and returns the ABDM / Lightsail verification URL.
  - `api/abha_registration_prefill_status.php`: polled by `js/addPatient.js`; returns pending, verified, expired, or address-conflict status plus the verified profile.
  - `api/abha_registration_prefill_link_patient.php`: called after the patient record is saved; inserts or updates `abdm_patient_abha_map` and marks the token consumed.
  - `api/internal_abha_registration_prefill_store.php`: signed bridge endpoint called by Lightsail to store verified or created ABHA details against the registration token. It currently checks one selected ABHA Address against `abdm_patient_abha_map`.
  - `api/abha_registration_prefill_common.php`: shared helpers and table setup for `abdm_registration_prefill_tokens` and `abdm_patient_abha_map`.
- ABDM / Lightsail wrapper APIs already present:
  - `api/abdm_verify_abha_by_otp.php`: handles search, OTP request, OTP verification, profile fetch, and collection of ABHA Address values returned by ABDM.
  - `api/abdm_abha_address_select.php`: accepts a selected ABHA Address from the verified list and stores it in the ABDM page session.
  - `api/abdm_abha_address_mobile_otp.php`: starts and verifies registered-mobile OTP for creating another ABHA Address after ABHA Number verification.
  - `api/abdm_abha_address_suggest.php`: fetches suggested ABHA Address values after the address-creation transaction is available.
  - `api/abdm_abha_address_create.php`: creates the typed or suggested ABHA Address and updates the ABDM page session.
  - `api/abdm_registration_prefill_store.php`: forwards the selected or created ABHA details to the main VPS signed internal store endpoint.
- External ABDM v3 API usage in the current local code:
  - ABHA Number plus Aadhaar OTP: `POST /abha/api/v3/profile/login/request/otp`, `POST /abha/api/v3/profile/login/verify`, then `GET /abha/api/v3/profile/account`.
  - ABHA Number plus registered mobile OTP: same profile-login request, verify, and profile endpoints, with mobile verification scope.
  - ABHA Address plus Aadhaar OTP: `POST /abha/api/v3/phr/web/login/abha/search`, `POST /abha/api/v3/phr/web/login/abha/request/otp`, `POST /abha/api/v3/phr/web/login/abha/verify`, then `GET /abha/api/v3/phr/web/login/profile/abha-profile`.
  - ABHA Address plus registered mobile OTP: same PHR web login endpoints, with mobile verification scope.
  - New ABHA Address after verified ABHA Number: `POST /abha/api/v3/enrollment/request/otp`, `POST /abha/api/v3/enrollment/auth/byAbdm`, `GET /abha/api/v3/enrollment/enrol/suggestion`, and `POST /abha/api/v3/enrollment/enrol/abha-address`.
- Required missing API for the requested UI behavior:
  - Current code checks whether an ABHA Address is already linked only after one address is selected and stored through `api/internal_abha_registration_prefill_store.php`.
  - To disable linked addresses before selection, add a read-only signed bridge check:
    - ABDM / Lightsail wrapper, proposed: `api/abdm_abha_address_link_status.php`.
    - Main VPS signed internal endpoint, proposed: `api/internal_abha_address_link_status.php`.
    - It should accept the registration token and a list of ABHA Addresses, validate the token on the main VPS, check `abdm_patient_abha_map` for the token's doctor context, and return per-address status without exposing patient identifiers to the ABDM page.
- Step-to-API map for the requested flow:
  - Start from Add Patient: `api/abha_registration_prefill_token_create.php`.
  - Open verification UI: `Public/abdm_abha_single_entry.php`.
  - Choose one of four verification methods and request OTP: `api/abdm_verify_abha_by_otp.php` with `action=request_otp`.
  - Verify OTP and fetch profile: `api/abdm_verify_abha_by_otp.php` with `action=verify_otp`.
  - List returned ABHA Addresses: current UI function in `Public/abdm_abha_single_entry.php` using `abhaAddresses` from the verify response.
  - Identify linked addresses before selection: proposed `api/abdm_abha_address_link_status.php` to proposed `api/internal_abha_address_link_status.php`.
  - Select an unlinked returned address: `api/abdm_abha_address_select.php`, then `api/abdm_registration_prefill_store.php` to `api/internal_abha_registration_prefill_store.php`.
  - Type a new ABHA Address after verified ABHA Number: `api/abdm_abha_address_mobile_otp.php`, optional `api/abdm_abha_address_suggest.php`, then `api/abdm_abha_address_create.php`.
  - Store created ABHA Address for registration: `api/abdm_registration_prefill_store.php` to `api/internal_abha_registration_prefill_store.php`.
  - Fill fields and link after patient save: `api/abha_registration_prefill_status.php` and `api/abha_registration_prefill_link_patient.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Restore patient-profile ABHA single-entry page

- User requested separation of the add-patient ABHA registration-prefill work from the normal patient-profile ABHA link/create page.
- Restored `Public/abdm_abha_single_entry.php` from the saved audit copy at `MD5_docbox/Public/abdm_abha_single_entry.php`.
- Result:
  - `Public/abdm_abha_single_entry.php` is back to the patient-profile flow used for normal ABHA link/create.
  - Registration-prefill mode and add-patient-only controls were removed from this shared page.
  - Calls from this shared page to `../api/abdm_registration_prefill_store.php` and `../api/abdm_abha_address_mobile_otp.php` were removed by the restore.
  - A temporary local reference of the overwritten add-patient version was kept only at `/private/tmp/abdm_abha_single_entry_registration_prefill_current_20260529.php` for future comparison.
- Verification:
  - `Public/abdm_abha_single_entry.php` now matches `MD5_docbox/Public/abdm_abha_single_entry.php`.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered inline JavaScript was extracted and checked with `node --check`.
- Next implementation direction:
  - Build the add-patient ABDM prefill journey as a separate page/entry point instead of sharing `Public/abdm_abha_single_entry.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Number to new ABHA Address via registered mobile verification

- User clarified that creating another ABHA Address for an already verified ABHA Number should not force Aadhaar verification.
- Local review:
  - The M1 collection keeps ABHA Address suggestion/create on `/v3/enrollment/enrol/suggestion` and `/v3/enrollment/enrol/abha-address`.
  - The same collection includes an `abha-enrol` + `mobile-verify` step on `/v3/enrollment/request/otp` and `/v3/enrollment/auth/byAbdm`, which returns the enrollment transaction needed before address suggestion/create.
- Local change:
  - `lib/AbhaService.php` now supports the v3 registered-mobile enrollment OTP request and verify calls for address creation, and redacts token/OTP/photo-like fields in logs for those new calls.
  - Added `api/abdm_abha_address_mobile_otp.php` to request and verify registered mobile OTP after ABHA Number verification, then store `abha_create.enrol_txn_id` for the existing suggestion/create APIs.
  - `api/abdm_verify_abha_by_otp.php` now marks ABHA Number verification as eligible to start new address creation, but does not claim the address-creation transaction is available until registered mobile OTP is verified.
  - `api/abdm_registration_prefill_store.php` now tells the UI that an ABHA Number without a selected address can create another address after registered mobile verification.
  - `Public/abdm_abha_single_entry.php` now opens a registered-mobile OTP step when the user chooses Create New ABHA Address from a verified ABHA Number, then enables suggestions and address creation only after OTP verification.
  - `api/abdm_abha_address_suggest.php` and `api/abdm_abha_address_create.php` now show mobile-verification-specific messages when the enrollment transaction is missing.
- Verification:
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_abha_address_mobile_otp.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_mobile_otp.php` to `/var/www/html/abdm-app/api/abdm_abha_address_mobile_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Sandbox ABHA Address suffix correction

- User reported that newly created ABHA Addresses were being completed as `@abdm`, but the current sandbox environment should use `@sbx`.
- Local change:
  - `Public/abdm_abha_single_entry.php` now derives the visible ABHA Address suffix from the ABDM config. With the current sandbox config it renders `@sbx`.
  - The ABHA Address verification placeholder now uses the same configured suffix.
  - Suggestion clicks now put only the local address part into the input while the suffix badge supplies the environment suffix.
  - `api/abdm_abha_address_create.php` now derives the fallback stored address suffix from the ABDM config, so sandbox fallback addresses become `name@sbx` and production fallback addresses become `name@abdm`.
  - The create-address API response now also returns top-level `abhaAddress` and `abhaNumber` after successful creation so the UI does not fall back to a local-only value.
- Verification:
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`; output contains `@sbx` for the suffix badge and `ABHA_ADDRESS_SUFFIX = "@sbx"`.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Uploaded Postman collection review

- User provided `/Users/apple/Downloads/Milestone_3_16_02_2026_796709b791.postman_collection` and described it as the M1 API collection.
- Local review:
  - The collection metadata name is `Milestone 3 - New`.
  - It contains gateway/bridge registration and HIU consent/data-flow endpoints.
  - It does not contain ABHA Number verification, ABHA Address suggestion, or ABHA Address creation endpoints.
  - Therefore this collection does not identify the correct M1 ABHA Address creation endpoint for the current `Invalid Transaction Id` response.
- Endpoints observed:
  - Gateway session, bridge URL update, bridge service registration, bridge service lookup, certs, openid-configuration.
  - HIU consent request init/status/on-notify/fetch.
  - HIU health-information request and data-flow notification.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 M1 Postman collection review and Invalid Transaction Id correction

- User provided `/Users/apple/Documents/m1_postman.json`.
- Local review:
  - Collection name is `Milestone 1 Postman Collection-18-08-2025`.
  - The ABHA Address suggestion endpoint is `GET /abha/api/v3/enrollment/enrol/suggestion` and uses the `Transaction_Id` header.
  - The ABHA Address creation endpoint is `POST /abha/api/v3/enrollment/enrol/abha-address` and body contains `txnId`, `abhaAddress`, and `preferred`.
  - Both address endpoints are under ABHA enrolment via Aadhaar and require the enrollment transaction returned by the enrollment flow.
  - ABHA Number OTP verification uses `POST /abha/api/v3/profile/login/request/otp` and `POST /abha/api/v3/profile/login/verify`; this transaction is not valid for the enrollment address endpoint.
- Root cause for `Invalid Transaction Id`:
  - The previous local patch was sending an ABHA Number profile-login transaction to the enrollment address endpoint.
- Local correction:
  - `lib/AbhaService.php` address suggestion/create methods were restored to match the M1 collection headers: no profile `X-token` header is sent for those enrollment endpoints.
  - `api/abdm_verify_abha_by_otp.php` no longer stores the ABHA Number verification transaction as an address-creation transaction and returns `canCreateNewAddress=false`.
  - `api/abdm_abha_address_suggest.php` and `api/abdm_abha_address_create.php` now use only `abha_create.enrol_txn_id`.
  - `api/abdm_registration_prefill_store.php` no longer reports address creation as available from an ABHA Number verification session.
  - `Public/abdm_abha_single_entry.php` now shows `Start Create ABHA Flow` instead of sending the invalid profile-login transaction to the address endpoint.
- Verification:
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abdm_verify_abha_by_otp.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
  - `php -l Public/abdm_abha_single_entry.php` passed.
  - Rendered `Public/abdm_abha_single_entry.php`, extracted inline script, and `node --check /private/tmp/abdm_abha_single_entry_inline.js` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_verify_abha_by_otp.php` to `/var/www/html/abdm-app/api/abdm_verify_abha_by_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abdm_abha_single_entry.php` to `/var/www/html/abdm-app/Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 Current ABDM registration flow planning checkpoint

- User requested API identification only before changing behavior for the add-patient verification flow.
- Existing flow pieces confirmed:
  - `addPatient.php` and `js/addPatient.js` on the DocBox staging main VPS start the registration prefill flow, poll status, fill the registration form, and link ABHA details after patient save.
  - `Public/abdm_abha_single_entry.php` on the ABDM / Lightsail bridge server hosts the Verify ABHA and Create ABHA UI.
  - `api/abdm_verify_abha_by_otp.php` supports the four requested OTP verification choices through v3 endpoints.
  - `api/abdm_abha_address_select.php` stores a selected returned ABHA Address in the ABDM page session.
  - `api/abdm_abha_address_mobile_otp.php`, `api/abdm_abha_address_suggest.php`, and `api/abdm_abha_address_create.php` support typed or suggested new ABHA Address creation after ABHA Number verification and registered-mobile verification.
  - `api/abdm_registration_prefill_store.php` forwards the verified or created ABHA details to the main VPS.
  - `api/internal_abha_registration_prefill_store.php` stores the verified profile against the registration token and checks the selected ABHA Address against `abdm_patient_abha_map`.
  - `api/abha_registration_prefill_status.php` returns the verified profile to `js/addPatient.js`.
  - `api/abha_registration_prefill_link_patient.php` links the stored ABHA details to the newly saved patient.
- Missing piece for the requested UX:
  - There is no current read-only API that checks all returned ABHA Addresses before selection and marks which addresses are already linked to a patient.
  - Recommended next change: add a Lightsail wrapper such as `api/abdm_abha_address_link_status.php` and a signed main-VPS endpoint such as `api/internal_abha_address_link_status.php`.
  - The main-VPS endpoint should validate the registration token, check `abdm_patient_abha_map` for the token's doctor context, and return only per-address selectable status to the ABDM page.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABDM callback debug JSONL logging diagnosis

- User asked why `https://abdm.docbox.asia/api/abdm_callback_debug_log.jsonl` was not showing logs for new ABHA Address creation.
- Local review:
  - The JSONL writer is `abdmDebugAppend()` in `api/abdm_bootstrap.php`.
  - It writes to `__DIR__ . '/abdm_callback_debug_log.jsonl'`, meaning the file beside the running PHP endpoint in the live `api` directory.
  - `bridgeRequest()` writes bridge exchanges to this JSONL by calling `abdmDebugAppendHttpExchange()`.
  - Callback endpoints such as `api/abdm_consents_hip_notify.php`, `api/abdm_link_token_callback.php`, and `api/abdm_link_care_context_callback.php` write inbound callback entries to this JSONL.
  - ABHA verification and address creation calls do not write to this JSONL directly. They write ABDM API responses to the database table `abdm_txn_log` through `lib/AbhaVerificationService.php` and `lib/AbhaService.php`.
- Live check:
  - `curl -I https://abdm.docbox.asia/api/abdm_callback_debug_log.jsonl` returned `200 OK`.
  - The live file was not empty and contained recent entries from `api/abdm_internal_care_context_list.php`.
- Conclusion:
  - The JSONL file is working for bridge/callback traffic, but ABHA Address creation errors are expected in `abdm_txn_log`, not in the JSONL, unless explicit JSONL logging is added to `api/abdm_abha_address_create.php` or `lib/AbhaService.php`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-28 ABHA Address creation JSONL debug logging

- User requested using `api/abdm_callback_debug_log.jsonl` for the ABHA Address creation flow also.
- Local change:
  - `api/abdm_bootstrap.php` debug sanitizer now masks ABHA, Aadhaar, mobile, phone, profile, patient, cookie, token, OTP, authorization, signature, and similar sensitive fields before writing JSONL records.
  - `api/abdm_abha_address_mobile_otp.php` now writes safe JSONL events for registered-mobile OTP request/verify state, validation, results, and exceptions.
  - `api/abdm_abha_address_suggest.php` now writes safe JSONL events for suggestion state, results, and exceptions.
  - `api/abdm_abha_address_create.php` now writes safe JSONL events for create request state, validation, results, and exceptions.
  - `api/abdm_registration_prefill_store.php` now writes safe JSONL events for the registration prefill bridge exchange and store result.
- Safety notes:
  - The JSONL records intentionally do not write raw OTPs, mobile numbers, ABHA numbers, ABHA addresses, Aadhaar values, transaction IDs, or profile bodies.
  - The records include diagnostic metadata such as flow name, event name, status code, boolean state flags, response keys, and counts.
- Verification:
  - `php -l api/abdm_bootstrap.php` passed.
  - `php -l api/abdm_abha_address_mobile_otp.php` passed.
  - `php -l api/abdm_abha_address_suggest.php` passed.
  - `php -l api/abdm_abha_address_create.php` passed.
  - `php -l api/abdm_registration_prefill_store.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_bootstrap.php` to `/var/www/html/abdm-app/api/abdm_bootstrap.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_mobile_otp.php` to `/var/www/html/abdm-app/api/abdm_abha_address_mobile_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_suggest.php` to `/var/www/html/abdm-app/api/abdm_abha_address_suggest.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php` to `/var/www/html/abdm-app/api/abdm_abha_address_create.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/api/abdm_registration_prefill_store.php` to `/var/www/html/abdm-app/api/abdm_registration_prefill_store.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 ABHA Address registered-mobile OTP TypeError fix

- User shared JSONL records from the new ABHA Address creation logs.
- Observation:
  - `api/abdm_abha_address_mobile_otp.php` received `action=request`.
  - The outbound registered-mobile OTP request returned HTTP `401` from ABDM and did not return a request transaction.
  - The wrapper then logged `abha_address_mobile_otp_exception` with `exception=TypeError`.
- Root cause:
  - Two calls to `abdmAddressMobileResponseMessage()` passed only the response body and fallback message.
  - The helper requires the response body, success boolean, and fallback message.
  - This masked the actual ABDM `401` response with a wrapper TypeError.
- Local change:
  - Fixed both `abdmAddressMobileResponseMessage()` calls in `api/abdm_abha_address_mobile_otp.php` to pass the success boolean.
  - After upload, the UI/API should return the real ABDM error message for the `401` response instead of the generic wrapper exception path.
- Verification:
  - `php -l api/abdm_abha_address_mobile_otp.php` passed.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_mobile_otp.php` to `/var/www/html/abdm-app/api/abdm_abha_address_mobile_otp.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 M1 collection PHR web login endpoint check

- User asked whether the uploaded M1 Postman collection contains the PHR web login ABHA APIs.
- Checked `/Users/apple/Documents/m1_postman.json`.
- Result:
  - `v3/phr/web/login/abha/search` is present.
  - `v3/phr/web/login/abha/request/otp` is present.
  - `v3/phr/web/login/abha/verify` is present.
  - `v3/phr/web/login/profile/abha-profile` is present.
  - `v3/phr/web/login/profile/abha/phr-card` is present.
- Note:
  - These are ABHA Address verification and profile/card APIs.
  - They are different from the v3 enrollment APIs used for creating a new ABHA Address after ABHA Number verification.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 ABHA Address verification API usage confirmation

- User asked whether DocBox currently uses the PHR web login APIs for ABHA Address verification.
- Local code check:
  - `api/abdm_verify_abha_by_otp.php` is the local wrapper for ABHA verification.
  - For `identifierType = abha_address`, it calls `AbhaVerificationService::searchAuthMethods()`, `requestOtp()`, `verifyOtp()`, and `getProfile()`.
  - `lib/AbhaVerificationService.php` maps those calls to:
    - `/login/abha/search`
    - `/login/abha/request/otp`
    - `/login/abha/verify`
    - `/login/profile/abha-profile`
    - `/login/profile/abha/phr-card`
  - The configured base URL is `abha_phr_web_base_url`, so the effective endpoints are the `v3/phr/web/login/...` APIs from the M1 collection.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 New ABHA Address mobile verification confirmation

- User asked whether mobile verification is required again when creating a new ABHA Address.
- Local confirmation:
  - For selecting an already returned ABHA Address after ABHA Number verification, no additional mobile verification is needed.
  - For creating another ABHA Address under an already verified ABHA Number, the current local flow requires a separate registered-mobile OTP step.
- Evidence:
  - The M1 collection has address creation under enrollment APIs:
    - `/abha/api/v3/enrollment/request/otp`
    - `/abha/api/v3/enrollment/auth/byAbdm`
    - `/abha/api/v3/enrollment/enrol/suggestion`
    - `/abha/api/v3/enrollment/enrol/abha-address`
  - The mobile OTP request body in the collection uses `scope = ["abha-enrol", "mobile-verify"]`.
  - `lib/AbhaService.php` implements the same current flow through `requestAddressEnrollmentMobileOtp()`, `verifyAddressEnrollmentMobileOtp()`, `getAddressSuggestions()`, and `createAddress()`.
  - The ABHA Number login transaction from `/v3/profile/login/verify` is not reused for `/v3/enrollment/enrol/abha-address`.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 M1 collection answer on mobile verification before address creation

- User clarified that the question is about whether mobile verification is necessary according to the API collection, not according to the current DocBox flow.
- Collection review:
  - In `/Users/apple/Documents/m1_postman.json`, the folder `ABHA enrolment via Aadhaar` places these steps in order:
    - `Mobile Update - Send OTP`: `POST /abha/api/v3/enrollment/request/otp` with `scope = ["abha-enrol", "mobile-verify"]`, `loginHint = "mobile"`, and `otpSystem = "abdm"`.
    - `Mobile Update - Verify OTP`: `POST /abha/api/v3/enrollment/auth/byAbdm` with `scope = ["abha-enrol", "mobile-verify"]`.
    - `ABHA Address Suggestion API`: `GET /abha/api/v3/enrollment/enrol/suggestion`, using `Transaction_Id: {{txnId}}`.
    - `ABHA Address`: `POST /abha/api/v3/enrollment/enrol/abha-address`, with body fields `txnId`, `abhaAddress`, and `preferred`.
  - Therefore, according to the collection's address creation sequence, mobile verification is part of the enrollment flow before address suggestion/create.
  - The PHR web login APIs are for verifying an existing ABHA Address, not creating a new one.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 ABHA Address creation OTP 401 diagnosis

- User shared JSONL records showing:
  - `api/abdm_abha_address_mobile_otp.php` received `action=request`.
  - The outbound ABDM call returned HTTP `401`.
  - `requestTxnPresent=false`.
- Local review:
  - The failing call is `POST /abha/api/v3/enrollment/request/otp` with `scope = ["abha-enrol", "mobile-verify"]`.
  - The current local code seeds this with the ABHA Number verification transaction from the profile-login flow.
  - In the M1 collection, the mobile update step belongs to `ABHA enrolment via Aadhaar`, not to ABHA Number verification/profile-login.
  - The collection's address creation sequence is:
    - Aadhaar enrolment flow creates/uses an enrollment transaction.
    - `Mobile Update - Send OTP`
    - `Mobile Update - Verify OTP`
    - `ABHA Address Suggestion API`
    - `ABHA Address`
  - A search of the collection did not show a separate API sequence for adding another ABHA Address directly after ABHA Number verification.
- Conclusion:
  - The HTTP `401` is consistent with sending the wrong type of transaction to the enrollment mobile OTP endpoint.
  - The current "Create New ABHA Address" action after ABHA Number verification should be changed to avoid this invalid route.
  - Safe correction is to only allow:
    - selecting one of the ABHA Addresses returned by ABHA Number verification, or
    - starting the full Create ABHA/enrollment branch when a new ABHA Address is required.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient inline ABHA profile modal and DOB fix

- User reported that DOB copied from verified ABHA details only showed the year, and asked that selecting a returned ABHA Address fetch and show the full verified details in a modal with the ABHA card and a Fill details button.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added the Verified ABHA Details modal with profile fields, ABHA card frame, and Fill details button.
    - Bumped `js/addPatient.js` cache version to `v=4.02`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added DOB parsing for `dayOfBirth`, `monthOfBirth`, and `yearOfBirth` as well as full date strings.
    - Shows the selected verified profile in the modal only when the ABHA Address is not already linked and details are allowed to be copied.
    - Loads the ABHA card through the existing Add Patient bridge proxy and fills the registration form only from the modal Fill details button or the existing Copy details button.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Preserves normalized day/month/year DOB parts in the sanitized verified profile and builds a full DOB when only separate birth parts are returned.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Added a `card` action that forwards the short-lived registration-token request to the ABDM bridge and returns the card response to the Add Patient UI.
    - Guarded card loading so it is only available after the selected ABHA Address has been accepted for this registration.
- ABDM / Lightsail bridge change:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added short-lived storage for the verified bridge token in `abdm_registration_verify_state` so the selected profile's ABHA card can be fetched during the same registration attempt.
    - Added `card` action to download the card from the ABDM profile/card endpoint and return it as base64 with content type.
- Validation run locally:
  - `php -l addPatient.php`
  - `php -l api/abha_registration_prefill_common.php`
  - `php -l api/abha_registration_prefill_verify_proxy.php`
  - `php -l api/internal_abdm_registration_verify.php`
  - `node --check js/addPatient.js`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA card frame content-policy fix

- User reported that the ABHA card area showed: `This content is blocked. Contact the site owner to fix the issue.`
- Cause:
  - The Add Patient modal was putting the card into an iframe using a `data:` URL.
  - The site content policy does not allow `data:` frames, so the browser blocked the embedded card.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php`
    - Added a same-origin authenticated GET endpoint for displaying the ABHA card.
    - It validates the logged-in doctor context, the registration token, expiry, and verified status before requesting the card from the ABDM bridge.
    - It returns the card as inline PDF/image content with `no-store` cache headers and `SAMEORIGIN` frame protection.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Updated the ABHA card modal iframe to load `/api/abha_registration_prefill_card_view.php?registrationToken=...` instead of a blocked inline `data:` document.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.03`.
- Validation run locally:
  - `php -l api/abha_registration_prefill_card_view.php`
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_card_view.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA card bridge streaming fix

- User reported that the ABHA card area still showed `Unable to process ABHA verification at this time.`
- Local correction:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added `card_stream` action so the ABDM bridge can return the card as inline binary content instead of base64 JSON.
    - Added card-specific content-type validation and a non-sensitive exception message in `abdm_callback_debug_log.jsonl`.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
    - Updated `downloadAbhaCard()` to accept an explicit identifier type so the Add Patient bridge flow does not depend on PHP session state.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php`
    - Updated the same-origin main VPS viewer to request `card_stream` from the ABDM bridge and stream the returned card to the iframe.
- Validation run locally:
  - `php -l api/internal_abdm_registration_verify.php`
  - `php -l lib/AbhaVerificationService.php`
  - `php -l api/abha_registration_prefill_card_view.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_card_view.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA card 400 handling and fallback

- User reported browser console showed `GET /api/abha_registration_prefill_card_view.php?... 400 Bad Request`.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php`
    - Added fallback handling: the viewer first tries bridge action `card_stream`; if that does not return card content, it falls back to bridge action `card`, decodes the returned card, and streams it to the iframe.
    - Keeps local token/session/status validation before any bridge call.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - The iframe load handler now reads same-origin text error responses and shows the exact safe message in the modal instead of always saying the card loaded.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.04`.
- Validation run locally:
  - `php -l api/abha_registration_prefill_card_view.php`
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_card_view.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_card_view.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA card Lightsail popup flow

- User asked to open a small Lightsail window for the ABHA card and put a Fill details button inside that window.
- Implemented approach:
  - Add Patient keeps the verified profile details locally on the main VPS.
  - Main VPS requests a short-lived popup token from the ABDM / Lightsail bridge.
  - A small popup opens on `https://abdm.docbox.asia/Public/abha_card_popup.php`.
  - The popup displays the ABHA card directly from Lightsail and sends only a small `postMessage` signal back to Add Patient.
  - Add Patient validates the message origin and popup token before filling the already-verified local profile details.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Replaced the embedded ABHA card iframe with an `Open ABHA card window` button.
    - Added `bridgeOrigin` to `window.addPatientAbhaConfig`.
    - Bumped `js/addPatient.js` cache version to `v=4.05`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added popup launch via `card_popup` action.
    - Opens a small popup immediately on button click, then redirects it to the Lightsail popup URL after the bridge returns the short-lived token.
    - Added `postMessage` receiver that accepts messages only from the configured bridge origin and only when the popup token matches.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Added `card_popup` action forwarding to the ABDM bridge.
    - Requires local registration token status to be `verified` before opening the popup.
- ABDM / Lightsail changes:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added popup-token columns to `abdm_registration_verify_state`.
    - Added `card_popup` action that creates a 5-minute popup token and returns the Lightsail popup URL.
  - `/Users/apple/Documents/docbox_staging/Public/abha_card_popup.php`
    - New small popup page.
    - Validates the short-lived popup token, displays the ABHA card directly from Lightsail, and has a Fill details button that sends a minimal message back to Add Patient.
- Validation run locally:
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
  - `php -l api/abha_registration_prefill_verify_proxy.php`
  - `php -l api/internal_abdm_registration_verify.php`
  - `php -l Public/abha_card_popup.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/Public/abha_card_popup.php` to `/var/www/html/abdm-app/Public/abha_card_popup.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server if the previous card-streaming method update has not already been uploaded.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA popup opens directly instead of modal

- User confirmed the Lightsail popup works and asked to open the small window directly instead of opening the Verified ABHA Details modal first.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Moved `Open ABHA card window` button into the verified preview area as a manual retry/fallback.
    - Bumped `js/addPatient.js` cache version to `v=4.06`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Successful direct ABHA Address verification now opens the Lightsail popup directly.
    - Successful ABHA Number address selection now opens the Lightsail popup directly.
    - The popup is pre-opened from the user's Verify/Select click before the async call finishes, reducing popup-blocker issues.
    - The modal is no longer opened automatically; it remains as fallback UI only.
    - If the popup cannot be opened automatically, the preview area shows `Open ABHA card window` for manual retry.
- Validation run locally:
  - `node --check js/addPatient.js`
  - `php -l addPatient.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA not-found message

- User asked for a proper message when an entered ABHA Number or ABHA Address does not exist.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added `addPatientAbhaMissingIdentifierMessage()`.
    - During OTP request failure, if the ABDM response indicates the entered ABHA Number or ABHA Address was not found or not valid on ABDM, the UI now shows:
      - `This ABHA Number does not exist. Please check the number and try again.`
      - `This ABHA Address does not exist. Please check the address and try again.`
    - OTP cooldown/limit messages are preserved and not overwritten.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.07`.
- Validation run locally:
  - `node --check js/addPatient.js`
  - `php -l addPatient.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA invalid value cooldown fix

- User reported that entering a random ABHA Number showed `Please wait 60 seconds before requesting another OTP` instead of a not-found message.
- Cause:
  - The Add Patient bridge was consuming the local OTP limiter before ABDM accepted the OTP request.
  - A failed/random identifier could therefore create a cooldown row and the next request returned the cooldown message before ABDM was contacted.
- ABDM / Lightsail change:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Updated `internalRegistrationVerifyOtpRateLimitCheck()` to support a non-consuming precheck.
    - OTP limiter is now consumed only after ABDM returns a successful OTP request with a transaction id.
    - Rate limiting is now scoped to the current registration attempt plus identifier, so stale rows from earlier attempts do not mask invalid ABHA Number or ABHA Address messages.
- Validation run locally:
  - `php -l api/internal_abdm_registration_verify.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 ABDM collection review for mobile-only ABHA lookup

- User asked whether the M1 Postman collection contains a flow where the user enters only a mobile number, receives OTP, verifies OTP, and then ABHA details are fetched.
- Reviewed `/Users/apple/Documents/m1_postman.json`.
- Relevant V3 flow found:
  - `ABHA Verification > Verify Via Mobile Number > Send OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/request/otp`
    - Uses `scope: ["abha-login", "mobile-verify"]`, `loginHint: "mobile"`, encrypted mobile in `loginId`, and `otpSystem: "abdm"`.
  - `ABHA Verification > Verify Via Mobile Number > Verify OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/verify`
    - Uses `scope: ["abha-login", "mobile-verify"]`, OTP transaction id, and encrypted OTP value.
  - `ABHA Verification > Verify Via Mobile Number > Verify User`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/verify/user`
    - Used when the returned account context requires choosing or confirming an ABHA Number.
  - `ABHA Verification > Profile Management > Get Profile Details`
    - `GET https://abhasbx.abdm.gov.in/abha/api/v3/profile/account`
    - Fetches full profile details after the verified account session is established.
- Related search-first flow also found:
  - `ABHA Verification > FIND ABHA > Search`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/account/abha/search`
    - Uses encrypted mobile with `scope: ["search-abha"]`.
  - `ABHA Verification > FIND ABHA > Send OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/request/otp`
    - Uses `scope: ["abha-login", "search-abha", "mobile-verify"]`, `loginHint: "index"`, encrypted search index in `loginId`, and search transaction id.
  - `ABHA Verification > FIND ABHA > Verify OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/verify`
    - Verifies the OTP for the search-based mobile flow.
- Conclusion:
  - The collection supports mobile-only OTP based ABHA account lookup as a sequence, not a single API.
  - Best fit for Add Patient mobile-only lookup is the direct `Verify Via Mobile Number` flow, with `verify/user` if multiple ABHA accounts are returned, followed by `GET /profile/account`.
  - The `FIND ABHA` flow is useful when the UI needs to search ABHA accounts linked to a mobile number before choosing one.
- No application code changed for this review.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient mobile search based ABHA lookup

- User asked to implement the `FIND ABHA` flow using mobile search in Add Patient.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Updated the ABHA verification input label and placeholder to accept ABHA Number, ABHA Address, or 10-digit Mobile Number.
    - Added an inline `Select ABHA Account` result area for mobile search results.
    - Bumped `js/addPatient.js` cache version to `v=4.08`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Detects 10-digit numeric input as mobile search and keeps 14-digit numeric input as ABHA Number.
    - Calls a new `search_mobile` proxy action to find ABHA accounts linked with the mobile number.
    - Renders returned ABHA account choices with safe text rendering.
    - Calls `request_mobile_search_otp` for the selected account index.
    - Reuses the existing OTP verification, profile preview, copy details, and ABHA card popup flow after OTP verification.
    - Reuses the existing OTP resend cooldown and max-attempt UI for mobile search OTP requests.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Allows and forwards `search_mobile` and `request_mobile_search_otp` actions to the ABDM bridge.
- ABDM / Lightsail changes:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
    - Added V3 mobile search call to `POST /v3/profile/account/abha/search`.
    - Added V3 mobile search OTP request call to `POST /v3/profile/login/request/otp` using `loginHint: index`.
    - Added V3 mobile search OTP verification call to `POST /v3/profile/login/verify`.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added `search_mobile` action.
    - Added `request_mobile_search_otp` action.
    - Added `accounts_json` state storage for mobile search account choices.
    - Added mobile search OTP verification handling that fetches the ABHA profile using the returned token and stores it for Add Patient prefill.
    - Treats non-success OTP auth results as failed even when the upstream HTTP response is 200.
- Validation run locally:
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
  - `php -l api/abha_registration_prefill_verify_proxy.php`
  - `php -l api/internal_abdm_registration_verify.php`
  - `php -l lib/AbhaVerificationService.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA verification tabs

- User asked to split Add Patient ABHA verification into two tabs:
  - ABHA Number / ABHA Address verification.
  - Mobile Number verification.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added Bootstrap tabs inside the ABHA verification panel.
    - First tab now contains only ABHA Number / ABHA Address input with Aadhaar OTP and linked-mobile OTP buttons.
    - Second tab now contains a dedicated 10-digit Mobile Number input and `Find ABHA accounts` button.
    - Moved OTP limit/cooldown text outside the first tab so the same message works for both tab flows.
    - Bumped `js/addPatient.js` cache version to `v=4.09`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - ABHA Number / Address tab now validates only ABHA Number or ABHA Address.
    - Mobile Number tab now performs the existing mobile search flow.
    - Existing OTP request, OTP verification, account selection, profile preview, copy details, and ABHA card popup behavior remains unchanged.
    - OTP cooldown and max-attempt display now also updates the mobile account `Send OTP` buttons.
    - New verification sessions reset to the ABHA Number / Address tab by default.
- No ABDM / Lightsail bridge changes were required for this tab-only UI split.
- Validation run locally:
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 ABDM collection review for Aadhaar-card verification flow

- User asked to find a flow similar to mobile search but with Aadhaar-card verification.
- Reviewed `/Users/apple/Documents/m1_postman.json`.
- Direct Aadhaar OTP login flow found:
  - `ABHA Verification > Verify via Aadhaar > Send OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/request/otp`
    - Uses `scope: ["abha-login", "aadhaar-verify"]`, `loginHint: "aadhaar"`, encrypted Aadhaar in `loginId`, and `otpSystem: "aadhaar"`.
  - `ABHA Verification > Verify via Aadhaar > Verify OTP`
    - `POST https://abhasbx.abdm.gov.in/abha/api/v3/profile/login/verify`
    - Uses `scope: ["abha-login", "aadhaar-verify"]`, OTP transaction id, and encrypted OTP value.
    - Response shape includes `authResult`, `token`, `refreshToken`, and `accounts`.
- Related duplicate flow found:
  - `Forgot ABHA & Retrieval of Enrollment Number > Forgot ABHA via Aadhaar OTP`
  - It uses the same request/verify endpoints and the same Aadhaar OTP login shape.
- Search-first Aadhaar nuance:
  - `ABHA Verification > FIND ABHA > Search` accepts encrypted mobile with `scope: ["search-abha"]`.
  - The same `FIND ABHA` flow includes an Aadhaar OTP variant after mobile search/account index selection:
    - `scope: ["abha-login", "search-abha", "aadhaar-verify"]`
    - `loginHint: "index"`
    - `otpSystem: "aadhaar"`
  - This is not Aadhaar-number search; it is mobile search first, then selected account verification through Aadhaar OTP.
- Practical Add Patient implementation path:
  - Add a separate Aadhaar Number tab/input if needed.
  - Send Aadhaar OTP using the direct Aadhaar login flow.
  - Verify OTP.
  - Use returned `accounts` to choose the ABHA account if multiple are returned.
  - Fetch full profile with `GET /v3/profile/account` using the returned token.
  - Do not store or log raw Aadhaar; keep only hashed/rate-limit state.
- No application code changed for this review.
- Upload required:
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient direct Aadhaar OTP verification flow

- User approved patching the Add Patient Aadhaar-card verification flow identified from the M1 collection.
- Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added a third `Aadhaar Number` tab inside the Add Patient ABHA verification panel.
    - Added a 12-digit Aadhaar input and `Send Aadhaar OTP` button.
    - Bumped `js/addPatient.js` cache version to `v=4.10`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added Aadhaar input validation, Aadhaar OTP request handling, and shared resend cooldown / max-attempt UI handling.
    - Added support for Aadhaar OTP verification responses that return multiple ABHA accounts.
    - Added ABHA account selection after Aadhaar verification and then the existing preview, card popup, and copy-details flow.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Added proxy actions `request_aadhaar_otp` and `select_aadhaar_account`.
    - Passes account-selection responses through to the browser without storing until the user selects an ABHA account.
- ABDM / Lightsail bridge changes:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
    - Added V3 direct Aadhaar OTP request using `POST /v3/profile/login/request/otp`.
    - Added V3 direct Aadhaar OTP verification using `POST /v3/profile/login/verify`.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added `request_aadhaar_otp` action.
    - Added `select_aadhaar_account` action.
    - Added Aadhaar verification state handling using hashed state only; raw Aadhaar is not stored in the local bridge state or debug logs.
    - Added Aadhaar account normalization and masked ABHA value cleanup before storing a verified profile.
- Validation run locally:
  - `php -l addPatient.php`
  - `node --check js/addPatient.js`
  - `php -l api/abha_registration_prefill_verify_proxy.php`
  - `php -l api/internal_abdm_registration_verify.php`
  - `php -l lib/AbhaVerificationService.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php` on the DocBox staging main VPS.
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php` to `/var/www/html/abdm-app/lib/AbhaVerificationService.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient Aadhaar OTP service-unavailable message

- User reported `Unable to process ABHA verification at this time.` after trying the new Add Patient Aadhaar OTP flow.
- Checked live ABDM bridge debug log and found the bridge was failing while refreshing the ABDM access token; ABDM returned HTTP 500 from its session service.
- ABDM / Lightsail bridge change:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Keeps logging the exception internally.
    - Returns HTTP 503 with a user-readable message when the ABDM session service is temporarily unavailable.
    - Does not expose upstream response details to the browser.
- Validation run locally:
  - `php -l api/internal_abdm_registration_verify.php`
- Upload required:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php` on the ABDM / Lightsail bridge server.
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md` on the DocBox staging main VPS.

## 2026-05-29 Add Patient ABHA creation integration decision

- User asked whether Add Patient can use the existing ABHA creation flow from the Lightsail server when mobile/Aadhaar search does not find an existing profile.
- Existing Lightsail creation pieces found:
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - V3 enrollment OTP request.
    - V3 enrollment by Aadhaar.
    - V3 address suggestions.
    - V3 ABHA address creation.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_unified_journey.php`
    - Session-based public journey for Aadhaar OTP and creation.
  - `/Users/apple/Documents/docbox_staging/api/abdm_abha_address_create.php`
    - Session-based ABHA address creation.
- Decision:
  - Reuse the Lightsail service methods and endpoint logic.
  - Do not embed or open the existing public journey page inside Add Patient for this inline registration workflow.
  - Add Patient should call the main VPS proxy, and the main VPS proxy should call an internal Lightsail bridge action.
  - The internal bridge action should store only hashed/transient state and return a sanitized profile to the existing Add Patient prefill token flow.
- Proposed next patch:
  - Main VPS: add `start_create_abha`, `verify_create_abha_otp`, `suggest_create_abha_address`, and `create_abha_address` actions to `api/abha_registration_prefill_verify_proxy.php`.
  - Lightsail: add corresponding internal actions to `api/internal_abdm_registration_verify.php`, backed by `AbhaService`.
  - UI: show `Create ABHA` only when mobile search returns no account or Aadhaar verification confirms no matching account path.
  - After creation, store the created ABHA profile in `abdm_registration_prefill_tokens` and reuse the current copy-details / link-on-save behavior.

## 2026-05-29 Add Patient common Aadhaar-only ABHA creation design

- User confirmed ABHA creation must always use Aadhaar Number, regardless of how the user reached the create option.
- Implementation design:
  - Keep verification UI paths as-is:
    - ABHA Number / Address verification.
    - Mobile search verification.
    - Aadhaar verification.
  - Add one shared `Create ABHA` panel inside Add Patient.
  - Show the shared panel when:
    - mobile search returns no ABHA account, or
    - Aadhaar creation is chosen directly by the user, or
    - an existing verification path cannot provide an unlinked ABHA address and user chooses to create a fresh ABHA.
  - The shared creation panel collects:
    - Aadhaar Number.
    - consent checkbox/text.
    - OTP input after OTP request.
    - ABHA address choice after creation/enrolment returns a transaction.
  - Main VPS endpoint remains the browser-facing boundary:
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
  - Lightsail bridge remains the ABDM-facing boundary:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
  - Lightsail service reused:
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
  - New internal actions planned:
    - `create_abha_request_aadhaar_otp`
    - `create_abha_verify_aadhaar_otp`
    - `create_abha_suggest_address`
    - `create_abha_create_address`
  - After creation succeeds:
    - Build a sanitized ABHA profile.
    - Store it against the existing Add Patient registration token.
    - Show the existing profile preview/card popup/copy-details UI.
    - Link the created ABHA address to the saved HMIS patient using the current registration prefill link flow.
  - Privacy/state rule:
    - Do not store raw Aadhaar in database or logs.
    - Keep transient Aadhaar flow state on Lightsail using registration token hash and identifier hash.
    - Log only presence/count/status metadata.

## 2026-05-29 Add Patient CAPTCHA design for ABHA OTP flows

- User asked how CAPTCHA can be implemented for the Add Patient ABHA creation/verification flow.
- Recommended implementation:
  - Use a server-verified CAPTCHA provider, preferably Cloudflare Turnstile if Cloudflare is already planned for DocBox.
  - Render CAPTCHA in Add Patient only when the user starts an OTP-producing flow.
  - Validate CAPTCHA on the Main VPS proxy before the request is forwarded to the ABDM / Lightsail bridge.
  - Keep the Lightsail bridge protected by the existing signed internal bridge request and do not expose CAPTCHA secrets to the browser.
- Proposed Main VPS changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Add CAPTCHA widget container and expose only the public site key.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Collect CAPTCHA token before OTP/search/create actions.
    - Reset CAPTCHA after every completed request or failed validation.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Verify CAPTCHA token server-side before forwarding sensitive OTP/search/create actions.
  - Config/env:
    - Add public site key and private secret key.
- Protected actions should include:
  - `search_mobile`
  - `request_mobile_search_otp`
  - `request_otp`
  - `request_aadhaar_otp`
  - planned `create_abha_request_aadhaar_otp`
- Do not require CAPTCHA for OTP verification or final linking, because those depend on prior transaction state and user-entered OTP.
- No code changed for this design note.

## 2026-05-29 Add Patient local CAPTCHA decision

- User clarified they want regular CAPTCHA only, not Cloudflare Turnstile or a third-party CAPTCHA provider.
- Updated implementation direction:
  - Implement local server-generated CAPTCHA on the Main VPS.
  - Store CAPTCHA answer hash in PHP session with a short expiry.
  - Show CAPTCHA only before OTP-producing ABHA actions.
  - Verify CAPTCHA in `api/abha_registration_prefill_verify_proxy.php` before forwarding to Lightsail.
  - Regenerate CAPTCHA after every validation attempt.
- Proposed Main VPS files:
  - `api/captcha_create.php` or `api/captcha_image.php`
    - Generates image and session hash.
  - `api/captcha_verify.php` or inline verification helper in `_bootstrap.php`
    - Verifies submitted text against session hash.
  - `addPatient.php`
    - Adds CAPTCHA image/input near ABHA action buttons.
  - `js/addPatient.js`
    - Sends CAPTCHA answer with protected ABHA actions and refreshes image after request.
  - `api/abha_registration_prefill_verify_proxy.php`
    - Enforces CAPTCHA on protected OTP/search/create actions.
- Protected actions:
  - `search_mobile`
  - `request_mobile_search_otp`
  - `request_otp`
  - `request_aadhaar_otp`
  - planned `create_abha_request_aadhaar_otp`
- No application code changed for this decision note.

## 2026-05-29 Add Patient ABHA creation using Aadhaar

- Implemented the Add Patient ABHA creation flow before CAPTCHA work.
- Main VPS UI changes:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added `Create ABHA` tab to the ABHA verification panel.
    - Added Aadhaar input, consent checkbox, OTP input, ABHA Address suggestions, manual ABHA Address input, and Create ABHA Address button.
    - Bumped `js/addPatient.js` cache version to `v=4.11`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added Create ABHA UI state/reset handling.
    - Added Aadhaar OTP request with existing resend/cooldown/maximum-attempt handling.
    - Added Aadhaar OTP verification for ABHA creation.
    - Added ABHA Address suggestion rendering and manual ABHA Address creation.
    - Reuses existing profile/card popup and fill-details behavior after successful creation.
- Main VPS proxy changes:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Allowed and forwarded create-flow actions:
      - `create_abha_request_aadhaar_otp`
      - `create_abha_verify_aadhaar_otp`
      - `create_abha_suggest_address`
      - `create_abha_create_address`
    - Keeps browser calls behind the existing registration token and signed Lightsail bridge request.
- ABDM / Lightsail bridge changes:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Added create-flow handlers using `AbhaService`.
    - Uses V3 enrollment endpoints through existing service methods:
      - Aadhaar OTP request.
      - Enrollment by Aadhaar OTP.
      - ABHA Address suggestions.
      - ABHA Address creation.
    - Stores only hashed identifiers/state metadata, not raw Aadhaar.
    - Removes Aadhaar fields from saved profile JSON.
    - Saves final verification state with ABHA account card lookup type so the existing ABHA card popup can use the correct card endpoint.
    - Uses `@sbx` suffix automatically when the configured ABDM environment is sandbox.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - ABDM / Lightsail bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-29 Add Patient ABHA creation OTP verify mobile fix

- Issue seen during testing:
  - After Aadhaar OTP verification in the Add Patient `Create ABHA` flow, the UI showed `Unable to create ABHA.`
- Cause identified:
  - The existing standalone ABHA creation page and M1 collection both include a mobile number for ABHA communication in the V3 `enrol/byAadhaar` request.
  - The Add Patient inline creation flow was not collecting or forwarding this mobile number.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added `Mobile Number for ABHA Communication` field in the Create ABHA OTP section.
    - Changed the action button text to `Verify OTP & Create ABHA`.
    - Bumped `js/addPatient.js` cache version to `v=4.12`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Clears the new mobile field on reset.
    - Prefills it from the Add Patient phone field when a valid 10-digit number is already entered.
    - Validates it before Aadhaar OTP verification.
    - Sends it with `create_abha_verify_aadhaar_otp`.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Forwards `mobile` to the Lightsail bridge for `create_abha_verify_aadhaar_otp`.
- Updated ABDM / Lightsail bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Validates the mobile number for the create flow.
    - Passes the mobile number into `AbhaService::enrolByAadhaar($txnId, $otp, $mobile)`.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - ABDM / Lightsail bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-29 Add Patient Create ABHA mobile field visibility fix

- Issue seen during testing:
  - The mobile number field was not visible before Aadhaar OTP request in the Add Patient `Create ABHA` tab.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Moved `Mobile Number for ABHA Communication` into the visible Create ABHA start section.
    - The field now appears with Aadhaar Number before `Send Aadhaar OTP`.
    - The OTP section now only shows Aadhaar OTP and `Verify OTP & Create ABHA`.
    - Bumped `js/addPatient.js` cache version to `v=4.13`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Prefills Create ABHA mobile from Add Patient phone when switching into the Create ABHA tab.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
    - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient optional ABHA profile mobile-update implementation plan

- User asked how to implement the optional test-case item for ABHA profile mobile update in rows 5.1, 5.2, 6.1, and the mobile OTP ABHA verification row.
- Current state:
  - Add Patient verification, profile fetch, copy/fill, verified-field lock, ABHA Number uniqueness, and patient link are implemented.
  - The bridge stores `x_token` server-side in `abdm_registration_verify_state` after successful ABHA verification.
  - The M1 collection contains V3 APIs for ABHA profile mobile update:
    - `POST /v3/profile/account/request/otp` with scope `abha-profile`, `mobile-verify`.
    - `POST /v3/profile/account/verify` with scope `abha-profile`, `mobile-verify`.
- Proposed implementation:
  - After ABHA verification/profile copy, compare verified ABHA mobile with the Add Patient form mobile.
  - If different, show a Yes/No prompt: update mobile in ABHA profile or keep only the DocBox patient mobile.
  - On Yes, request OTP for the new mobile through the Main VPS proxy, then the Lightsail bridge.
  - Verify OTP through the same proxy/bridge path.
  - On success, update the bridge state profile mobile and the Add Patient UI.
  - On No, continue registration without changing the ABHA profile.
- Files expected when patched:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
  - ABDM / Lightsail bridge:
    - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
  - Context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Required safeguards:
  - Keep `x_token` server-side only.
  - Validate mobile server-side as 10 digits.
  - Use existing signed bridge request path and CSRF-protected Main VPS proxy.
  - Reuse existing OTP resend cooldown and maximum attempt logic.
  - Redact OTP, token, mobile, and Authorization values in logs.
  - Do not block patient registration if the user chooses No or if ABHA profile mobile update is skipped.
- No application code was changed in this entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA Sheet 2 case 1.9 communication mobile OTP

- User asked to patch Sheet 2 test case `1.9` for communication mobile verification during ABHA creation.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added a hidden communication-mobile OTP section in the Create ABHA tab.
    - Added a CAPTCHA target before the Send Mobile OTP button.
    - Added Send Mobile OTP and Verify Mobile OTP controls.
    - Bumped `js/addPatient.js` cache version from `v=4.25` to `v=4.26`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - After Aadhaar OTP creates the ABHA number, the UI now pauses for communication-mobile verification.
    - Added communication-mobile OTP request and verification handlers.
    - Reuses the existing OTP cooldown/maximum-attempt UI for the communication-mobile OTP request.
    - Moves CAPTCHA before the Send Mobile OTP button before that request.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Added proxy support for `create_abha_request_mobile_otp` and `create_abha_verify_mobile_otp`.
    - Enforces CAPTCHA for the communication-mobile OTP request action.
    - Passes the intermediate communication-mobile verification state back to the UI.
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - After Aadhaar OTP ABHA creation succeeds, state moves to `create_mobile_pending` instead of showing address creation immediately.
    - Added `create_abha_request_mobile_otp` using V3 enrollment mobile verification request.
    - Added `create_abha_verify_mobile_otp` using V3 enrollment mobile verification verify.
    - After mobile OTP verification, the flow proceeds to existing ABHA Address creation or verified-profile completion.
    - Logs only state/result metadata, not OTP or mobile values.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-30 ABDM collection review: ABHA delete/deactivate APIs

- User asked whether the local ABDM collection has any API for deleting an ABHA Number.
- Reviewed `/Users/apple/Documents/m1_postman.json` and `/Users/apple/Downloads/Milestone_3_16_02_2026_796709b791.postman_collection`.
- Finding:
  - `/Users/apple/Documents/m1_postman.json` contains `ABHA Profile > Delete ABHA`.
  - Delete via Aadhaar OTP:
    - `POST /abha/api/v3/profile/account/request/otp`
    - scope: `["abha-profile", "delete"]`, `loginHint: "abha-number"`, `otpSystem: "aadhaar"`
    - then `POST /abha/api/v3/profile/account/verify`
    - scope: `["abha-profile", "delete"]`, auth method `otp`, with reason list.
  - Delete via ABHA OTP:
    - same endpoints and delete scope, but request OTP uses `otpSystem: "abdm"`.
  - Delete via password:
    - `POST /abha/api/v3/profile/account/verify`
    - scope: `["abha-profile", "delete"]`, auth method `password`, with reason list.
  - The same collection also contains `ABHA Profile > Deactivate ABHA` using scope `["abha-profile", "de-activate"]` through OTP or password.
  - Benefit `linkAndDelink` APIs are present but are for benefit link/de-link, not ABHA account deletion.
- No application code was changed in this review entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA Sheet 2 creation test-case review

- User provided `/Users/apple/Downloads/Untitled spreadsheet (5).xlsx` and said the additional test cases are in Sheet 2.
- Reviewed Sheet 2 rows:
  - `1.1` Create ABHA option.
  - `1.2` Consent collection.
  - `1.4` Aadhaar collection and invalid Aadhaar message.
  - `1.5` Aadhaar OTP collection.
  - `1.6` Resend OTP maximum two times after cooldown.
  - `1.7` Aadhaar OTP verification.
  - `1.9` Communication mobile verification when communication mobile differs from Aadhaar-linked mobile.
  - Suggested ABHA Address row, listed as `1.1` in the spreadsheet but appears to be the ABHA Address creation-policy case.
  - `1.11` Display created ABHA Number.
  - `1.12` and `2.9` View/download ABHA details/card.
- Current Add Patient implementation mapping:
  - Covered: Create ABHA tab, consent text/checkbox, Aadhaar numeric validation, Aadhaar OTP request and input, OTP cooldown/maximum request handling, Aadhaar OTP verification, ABHA Address suggestions, manual ABHA Address entry, created ABHA preview with ABHA Number and ABHA Address, card window/view through the bridge.
  - Needs patch/decision:
    - Communication mobile verification-II: current Add Patient create flow collects communication mobile after Aadhaar OTP and passes it to the bridge, but does not show a separate OTP request/verify step when it differs from the Aadhaar-linked mobile.
    - ABHA Address policy validation: current server validation allows 4-18 characters and requires first character to be a letter; Sheet 2 says 8-18 characters, dot/underscore only in the middle, max one dot and/or one underscore, and alphanumeric values can be only numbers, only letters, or a combination.
    - ABHA card: current flow opens a card window; if the test expects a separate visible Download button, add one beside Open ABHA card window.
- No application code was changed in this review entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient remaining ABHA test-case clarification

- User confirmed the optional ABHA profile mobile update cannot safely run before the patient is added.
- Decision:
  - Do not add ABHA profile mobile update inside the pre-save Add Patient verification flow.
  - Keep Add Patient focused on ABHA verification, profile fetch, patient detail fill, verified-field lock, patient save, and ABHA link.
  - If implemented later, ABHA profile mobile update should run only after patient creation and ABHA link are successful, either as a post-save prompt or from the registered patient profile.
- Remaining items after current patches:
  - Browser retest for `7.2` mobile search success with empty ABHA list: completed by user.
  - Browser retest for `16.0` unique ABHA Number message with OPD/IPD number: completed by user.
  - Captcha for ABHA start/create remains a separate pending enhancement.
  - Optional ABHA profile mobile update is deferred to post-save/patient profile flow.
- No application code was changed in this entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA browser retests completed

- User confirmed both remaining browser retests are completed:
  - `7.2` mobile number with no ABHA now shows the no-account message and Create ABHA using Aadhaar option.
  - `16.0` unique ABHA Number per patient now blocks duplicate linking and shows the existing OPD/IPD number.
- Current remaining ABHA test-case items:
  - Captcha for ABHA start/create remains a separate pending enhancement.
  - Optional ABHA profile mobile update remains deferred to post-save/patient profile flow.
- No application code was changed in this entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA local CAPTCHA before verification start

- User asked to implement CAPTCHA for the ABHA Add Patient flow.
- Implemented as a local DocBox math verification check on Main VPS before the ABHA verification token is created.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Added session-backed CAPTCHA helper functions.
    - CAPTCHA challenge expires after 10 minutes.
    - CAPTCHA answer is stored server-side as a session-bound hash, not sent to the browser.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php`
    - Requires a valid CAPTCHA answer before creating an ABHA registration token.
    - Supports CAPTCHA refresh through the same CSRF-protected endpoint using `captchaAction: refresh`.
    - Returns a fresh challenge after failed or successful validation.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Loads the current CAPTCHA challenge in the ABHA panel.
    - Adds question, answer field, and refresh button above `Verify ABHA & Fill Details`.
    - Adds the challenge to `window.addPatientAbhaConfig`.
    - Bumped `js/addPatient.js` cache version from `v=4.22` to `v=4.23`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Sends CAPTCHA answer when starting ABHA verification.
    - Blocks start locally if the answer field is empty.
    - Refreshes challenge without calling ABDM.
    - Updates challenge after server validation failure or success.
- Behavior:
  - No ABDM request is made until the user answers the local verification check correctly.
  - Existing ABHA verification, mobile search, Aadhaar search, Create ABHA, OTP cooldown, and patient-link behavior remain unchanged after token creation.
- Validation run locally:
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA CAPTCHA moved to OTP requests

- User clarified that CAPTCHA should not appear at the beginning; it should be required just before generating any OTP, and it should refresh when the page is refreshed or reopened.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - CAPTCHA challenge is now generated fresh on each page load.
    - CAPTCHA UI moved out of the ABHA panel header and into the inline ABHA flow near the OTP request controls.
    - Bumped `js/addPatient.js` cache version from `v=4.23` to `v=4.24`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Starting ABHA verification no longer requires CAPTCHA.
    - CAPTCHA is checked locally before OTP request actions.
    - CAPTCHA answer is sent only for OTP request actions.
    - Challenge is refreshed from server responses after OTP request validation.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php`
    - Token creation no longer requires CAPTCHA.
    - Still supports CAPTCHA refresh through `captchaAction: refresh`.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - CAPTCHA is now enforced server-side only for OTP generation actions:
      - `request_otp`
      - `request_mobile_search_otp`
      - `request_aadhaar_otp`
      - `create_abha_request_aadhaar_otp`
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Updated user-facing CAPTCHA message to refer to OTP request, not ABHA start.
- Behavior:
  - Clicking `Verify ABHA & Fill Details` opens the ABHA flow without CAPTCHA.
  - OTP request buttons require the CAPTCHA answer.
  - Refreshing/reopening Add Patient creates a fresh CAPTCHA question.
  - Manual CAPTCHA refresh remains available.
- Validation run locally:
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_token_create.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient Create ABHA communication mobile placement correction

- User clarified placement rule:
  - `Mobile Number for ABHA Communication` should appear only after Aadhaar OTP is successfully sent.
  - Before OTP request, the Create ABHA tab should show Aadhaar Number, consent, and Send Aadhaar OTP only.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Moved `Mobile Number for ABHA Communication` back into the hidden OTP section.
    - It now appears together with Aadhaar OTP only after successful OTP request.
    - Bumped `js/addPatient.js` cache version to `v=4.14`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Removed prefill while switching to the Create ABHA tab.
    - Clears the communication mobile field when starting a new Create ABHA OTP request.
    - Keeps prefill from Add Patient phone only after OTP request succeeds and the OTP section is shown.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA test-case status after CAPTCHA browser check

- User confirmed the OTP CAPTCHA placement works in the browser after the `v=4.25` Add Patient update.
- Current test-case status:
  - Mandatory Add Patient ABHA verification cases tracked from the spreadsheet are patched.
  - Browser-confirmed items include mobile no-ABHA Create ABHA fallback, unique ABHA Number duplicate-link blocking with OPD/IPD number, and OTP CAPTCHA placement.
  - Remaining item is optional/deferred: ABHA profile mobile-number update prompt/API from rows 5.1, 5.2, 6.1, and the mobile OTP row. This was previously deferred because it is not safe to run before the patient is added.
- No application code was changed in this status update.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient Create ABHA Address visible result feedback

- Issue seen during testing:
  - After entering an ABHA Address and clicking `Create ABHA Address`, the Lightsail log showed address creation success, but the Add Patient page did not clearly show progress or the next state.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - `Create ABHA Address` button now changes to `Creating...` while the request is running and restores afterward.
    - Added an explicit visible error message if the create-address response does not include a verified profile.
    - Added success handling that scrolls to the verified details preview after address creation completes.
    - Keeps existing card-window flow unchanged.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.15`.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient Create ABHA Address success display fix

- Issue seen during testing:
  - ABDM / Lightsail log confirmed ABHA Address creation success, but the Add Patient page still did not visibly show the created/verified state.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Create ABHA Address success path no longer depends on ABHA card popup opening.
    - The verified details preview and Copy details button are shown directly on the Add Patient page after address creation.
    - Added a minimal frontend fallback if the response has ABHA identifiers but the nested profile object is missing.
    - Keeps the Open ABHA card button available after the verified details are shown.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.16`.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient Create ABHA Aadhaar consent text

- User provided the required Aadhaar consent declaration text for ABHA creation.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Replaced the short Create ABHA consent line with a scrollable Aadhaar declaration panel.
    - Kept the existing `abhaCreateConsentInput` checkbox ID so current validation remains unchanged.
    - Checkbox label now confirms the patient has read and consented to the declaration above for ABHA creation.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA panel UI polish

- User confirmed the ABHA functionality looks good and requested UI improvement only.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added scoped `docbox-abha-*` styles for the Add Patient ABHA verification panel.
    - Improved panel header, tab spacing, helper text, consent declaration box, mobile layout, and verified-preview area.
    - Kept all existing element IDs and button actions unchanged.
    - No backend, bridge, validation, or JavaScript behavior changed in this UI-only patch.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA panel modern UI pass

- User requested a more modern design after the first UI polish still felt old.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Restyled the Add Patient title and ABHA panel with a flatter, modern card surface.
    - Converted ABHA mode tabs to pill-style segmented tabs.
    - Modernized scoped ABHA buttons, inputs, focus states, helper text, consent box, alerts, and preview actions.
    - Kept all existing IDs, form fields, button actions, and backend flow unchanged.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient full form modern UI pass

- User requested the rest of Add Patient to follow the same modern theme as the ABHA panel.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added scoped `docbox-patient-form-*` styles for the main patient registration form panel.
    - Modernized the main patient form card, labels, inputs, selects, focus states, radio options, file input, webcam button, patient image, and submit button.
    - Added wrapper classes to the main form panel and form only.
    - Kept existing field IDs, submit class, JavaScript hooks, validation behavior, and backend flow unchanged.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient main fields UI restored

- User asked to restore the UI of the regular Add Patient fields and defer that redesign.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Removed the scoped `docbox-patient-form-*` styles added for the main patient registration fields.
    - Removed the `docbox-patient-form-panel` and `docbox-patient-form` wrapper classes.
    - Kept the modern ABHA panel styling and all ABHA functionality unchanged.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA OTP choice button visual fix

- User reported the ABHA Number / Address tab made `Verify by Aadhaar OTP` look enabled and `Verify by linked-mobile OTP` look disabled.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Made both OTP choice buttons use the same neutral visual style by default.
    - Added scoped CSS so the clicked choice gets the selected blue state only after user selection.
    - Bumped `js/addPatient.js` cache version to `v=4.17`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Removed reset logic that forced Aadhaar to primary blue and mobile to default white.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA OTP buttons stronger neutral state

- User clarified both OTP options should visibly look like buttons.
- Updated Main VPS file:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Strengthened the neutral styling for both `Verify by Aadhaar OTP` and `Verify by linked-mobile OTP`.
    - Both now use the same light-blue button treatment before selection.
    - The selected state remains filled blue after the user clicks an option.
- Validation run locally:
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA verification test-case spreadsheet coverage check

- User provided `/Users/apple/Downloads/Untitled spreadsheet (4).xlsx` and asked whether the ABHA verification test cases are implemented.
- Spreadsheet rows reviewed:
  - 7.1, 7.2, 7.3, 7.4, 7.5
  - 8.1, Aadhaar incorrect OTP row, 8.2, 8.3, 8.4
  - 16.0
  - ABHA Number verification using linked-mobile OTP
  - 6.1 ABHA Address verification using linked-mobile OTP
  - 5.1 ABHA Number verification using Aadhaar OTP
  - 5.2 ABHA Address verification using Aadhaar OTP
- Main VPS coverage checked:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - ABHA panel has tabs for ABHA Number / Address, Mobile Number, Aadhaar Number, and Create ABHA.
    - ABHA Number / Address tab supports Aadhaar OTP and linked-mobile OTP.
    - Mobile Number tab supports mobile-based ABHA account search.
    - Aadhaar Number tab supports Aadhaar-based ABHA account search.
    - Create ABHA tab supports Aadhaar consent, Aadhaar OTP, communication mobile entry after OTP is requested, ABHA address choice, and `@sbx` suffix.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Implements local validation for ABHA number, ABHA address, mobile number, Aadhaar number, OTP, consent, communication mobile, and ABHA address local part.
    - Implements human-readable alert/status messages.
    - Implements resend cooldown and max-request UI handling from bridge rate-limit fields.
    - Renders no-account create-ABHA fallback for mobile search and Aadhaar lookup failures.
    - Renders copy-details only when the verified ABHA address is not linked to another DocBox profile.
    - Copies verified profile details into the registration form and locks name, date of birth, age, and gender.
    - Opens ABHA card through the ABDM bridge popup window.
    - Links verified ABHA details to the saved patient after registration succeeds.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Proxies Add Patient ABHA actions to the Lightsail bridge using signed bridge requests.
    - Stores verified profile state only after successful bridge verification.
    - Blocks copy when the selected ABHA address is already linked to another HMIS patient for the same doctor context.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php`
    - Links the verified ABHA profile to the saved patient.
    - Rechecks ABHA address mapping before insert/update.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Provides token storage, mapping storage, profile cleanup, DOB parsing, and ABHA address mapping lookup.
- Lightsail / ABDM bridge coverage checked:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Implements Add Patient actions: `search_mobile`, `request_mobile_search_otp`, `request_aadhaar_otp`, `request_otp`, `verify_otp`, `select_aadhaar_account`, `select_address`, `create_abha_request_aadhaar_otp`, `create_abha_verify_aadhaar_otp`, `create_abha_suggest_address`, `create_abha_create_address`, `card`, `card_popup`, and `card_stream`.
    - Uses `abdm_registration_verify_state` for per-registration verification state.
    - Uses `abdm_otp_rate_limit` with 60-second cooldown, maximum 2 resends, and 30-minute attempt window.
    - Writes Add Patient ABHA flow events through `abdmDebugAppend()` into `api/abdm_callback_debug_log.jsonl`.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaVerificationService.php`
    - Uses V3 profile login APIs for ABHA number, Aadhaar lookup, and mobile-search flows.
    - Uses V3 PHR web APIs for ABHA address verification and ABHA-address card/profile flows.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Uses V3 enrollment APIs for Aadhaar-based ABHA creation, ABHA address suggestions, ABHA address creation, and profile card download.
- Coverage conclusion:
  - Implemented:
    - ABHA Number verification using Aadhaar OTP.
    - ABHA Address verification using Aadhaar OTP.
    - ABHA Number verification using linked-mobile OTP.
    - ABHA Address verification using linked-mobile OTP.
    - Mobile-number based ABHA account search, OTP request, OTP verify, profile fetch, card popup, and copy-to-registration.
    - Aadhaar-number based ABHA account lookup, OTP request, OTP verify, account selection, profile fetch, card popup, and copy-to-registration.
    - Create ABHA using Aadhaar, consent text, communication mobile entry after OTP request, address suggestions/manual address, `@sbx` suffix, and copy-to-registration.
    - Incorrect OTP/error propagation through user-visible alert/status messages.
    - Resend cooldown and maximum resend handling.
    - Verified profile linking after patient save.
  - Partial / needs decision:
    - Spreadsheet mentions CAPTCHA as preferred under mobile authentication; CAPTCHA is not implemented in this Add Patient ABHA flow yet.
    - Spreadsheet asks the mobile search list to show photo and ABHA address. Follow-up patch below now displays ABHA Address and renders photo only when the mobile-search response itself includes a safe image value; full profile/card remain after OTP verification/selection.
    - Spreadsheet row 8.2 describes the "no ABHA exists for Aadhaar" result after Aadhaar OTP verification. Current UI has a create-ABHA fallback for Aadhaar lookup failures; if ABDM returns this no-account state only after OTP verification, that exact response still needs an explicit create-ABHA fallback.
    - Spreadsheet asks already-linked ABHA details to show the HIMS beneficiary ID. Current message blocks copy/link for already-linked ABHA address but does not expose the existing patient ID in the UI.
    - Spreadsheet row 16.0 asks one ABHA Number to map to a unique HIMS patient ID. Current database checks enforce ABHA address uniqueness per doctor, not ABHA number uniqueness. This is the main remaining implementation gap if row 16.0 must be enforced exactly.
    - Optional mobile update in the ABHA profile is not implemented.
- No application code was changed for this review; only this context note was added.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient mobile-search ABHA account list address/photo display

- User asked whether the mobile-search result list can show photo and ABHA Address before OTP, and requested a patch to see if photo comes from ABDM.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Mobile-search account rows now show ABHA Address when the search response includes `abhaAddress` or `preferredAbhaAddress`.
    - Added safe image-source handling for `profilePhoto`, `photo`, `profilePicture`, and `kycPhoto`.
    - Renders a 52px profile image only for data-image or raw base64 image values already present in the mobile-search response.
    - Shows a small `Photo after OTP` placeholder when the pre-OTP search response does not include an image.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version from `v=4.17` to `v=4.18`.
- Updated Lightsail / ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Mobile-search account normalization now passes through a cleaned image value from `profilePhoto`, `photo`, `profilePicture`, or `kycPhoto` when ABDM returns it.
    - Image pass-through is limited to data-image or raw base64-like values and capped to avoid oversized values.
- Behavior intentionally unchanged:
  - No profile/card fetch happens before OTP verification.
  - Existing OTP request, resend limit, verification, copy-details, and patient-link flows are unchanged.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - ABDM / Lightsail bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-29 ABDM mobile-search response shape confirmed

- User shared the ABDM mobile-search response shape for the Add Patient mobile-number search flow.
- Response fields present before OTP:
  - `txnId`
  - `ABHA[].index`
  - `ABHA[].ABHANumber` masked by ABDM
  - `ABHA[].name`
  - `ABHA[].gender`
  - `ABHA[].kycVerified`
  - `ABHA[].authMethods`
- Response fields not present before OTP:
  - ABHA Address
  - Profile photo / KYC photo
  - Full demographic profile
- Conclusion:
  - The patched mobile-search list can show ABHA Address/photo only if a future ABDM response includes those fields.
  - With the current response shape, the UI should show name, masked ABHA Number, gender, and the `Photo after OTP` placeholder.
  - ABHA Address and photo should be expected only after OTP verification/profile fetch.
- No application code was changed for this note.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA verified photo copy into registration photo

- User asked whether the photo fetched after ABHA verification can be placed into the Add Patient photo field.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Added safe profile-photo cleanup for `profilePhoto`, `photo`, `profilePicture`, and `kycPhoto`.
    - Allows only data-image or raw base64-like image values, capped at the same 5 MB limit used by patient registration.
    - Adds cleaned `profilePhoto` and `photo` to the sanitized verified profile returned to Add Patient.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added helper logic to normalize verified ABHA profile photo values into an image preview source.
    - On `Copy details` / `Fill details`, if a verified profile photo exists, the Add Patient photo preview is updated and `.uploaded64` is filled so the existing patient save flow stores it.
    - Existing manually uploaded/webcam photo is only replaced when the user explicitly clicks copy/fill with replace-all behavior.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version from `v=4.18` to `v=4.19`.
- Behavior intentionally unchanged:
  - No extra pre-OTP profile or card call is added.
  - If ABDM does not return a photo after verification, the Add Patient photo field remains unchanged.
  - Existing upload/webcam/save behavior continues to use `.uploaded64`.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient Aadhaar OTP no-ABHA deterministic create fallback

- User clarified that the Add Patient flow should handle the Aadhaar no-ABHA case deterministically, regardless of exact ABDM wording.
- Updated ABDM / Lightsail bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - After Aadhaar OTP verification, if no ABHA account is returned and no usable ABHA number/address is available from profile data, the bridge now returns a structured `requiresAbhaCreation` state.
    - Saves bridge state as `aadhaar_no_abha`.
    - Logs the structured outcome as `add_patient_abha_aadhaar_verify_no_abha`.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - Passes `requiresAbhaCreation` responses through to the browser without trying to store an incomplete verified profile.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Handles `requiresAbhaCreation` from Aadhaar OTP verification.
    - Hides the OTP/address sections, shows the existing `Create ABHA using Aadhaar` option, and pre-fills the Aadhaar number into the Create ABHA tab.
    - Also handles the same structured state if it arrives through a non-200 response.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version from `v=4.19` to `v=4.20`.
- Behavior intentionally unchanged:
  - Existing Aadhaar account selection, ABHA Number/Address verification, mobile search, create ABHA, resend limit, copy/fill, photo copy, and patient-link flows are unchanged.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - ABDM / Lightsail bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-29 Add Patient ABHA already-linked message shows OPD/IPD number

- User asked that when an ABHA address is already linked, the message should show the existing patient's OPD/IPD number.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Added `abha_prefill_patient_opd_ipd_number()` to look up `patient.OpdIpdNumber` by doctor and patient ID.
    - Added `abha_prefill_existing_abha_link_message()` to build consistent already-linked messages.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - During verified-profile storage, if ABHA Address is already linked, resolves the existing OPD/IPD number and returns it in the alert message.
    - Stores `linkedOpdIpdNumber` in the conflict profile state for status polling.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php`
    - During final patient-link recheck, duplicate ABHA Address errors now include the existing OPD/IPD number when available.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php`
    - Address-conflict status responses now use the stored OPD/IPD number in the message.
- Behavior intentionally unchanged:
  - Duplicate ABHA Address remains blocked.
  - If OPD/IPD number cannot be found, the message falls back to the previous generic linked-patient message.
- Validation run locally:
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/abha_registration_prefill_link_patient.php` passed.
  - `php -l api/abha_registration_prefill_status.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_status.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient mobile-search empty result Create ABHA option

- User asked to patch test case 7.2 where mobile search can return success with an empty ABHA account list.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - When mobile search succeeds but returns zero accounts, the UI now shows a clear no-account message.
    - Hides OTP/address sections for that result.
    - Shows the existing `Create ABHA using Aadhaar` option instead of showing an account-selection success message.
    - Existing no-result error handling is unchanged.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version from `v=4.21` to `v=4.22`.
- Validation run locally:
  - `node --check js/addPatient.js` passed.
  - `php -l addPatient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA remaining test-case review

- Reviewed `/Users/apple/Downloads/Untitled spreadsheet (4).xlsx` after completing ABHA Number duplicate-link validation.
- Current remaining or partially covered items:
  - Captcha for ABHA create/verification start is still pending.
  - Mobile-number search no-result handling should show Create ABHA even if the bridge returns success with an empty result list.
  - Optional ABHA profile mobile-number update prompt/API is not implemented; existing Add Patient flow copies verified mobile and allows editable non-core fields.
  - Final browser retest is still needed for the newest ABHA Number duplicate-link message after deployment.
- No application code was changed in this review entry.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-29 Add Patient ABHA Number duplicate-link validation

- User approved the next ABHA verification test-case cleanup: do not allow the same verified ABHA Number to be linked to another DocBox patient under the same doctor.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Added ABHA Number lookup helper using a normalized 14 digit value.
    - Added a non-unique lookup index for `abha_number` and `hmis_doctor_id` if the mapping table does not already have it.
    - Generalized the existing already-linked message helper so it can say either ABHA address or ABHA number while still showing OPD/IPD number when available.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php`
    - During verified-profile storage, after the address-specific duplicate check, validates whether the ABHA Number is already linked to another patient.
    - Returns `ABHA_NUMBER_ALREADY_LINKED`, blocks copy, and includes OPD/IPD number when found.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php`
    - Rechecks ABHA Number duplicate mapping during final patient link/save.
    - Allows the same patient to update its own mapping, but blocks linking the same ABHA Number to a different patient.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php`
    - Added `numberConflict` status handling so polling shows the same already-linked message.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added client-side handling for `numberConflict` so copy/fill stays hidden and the API message is shown.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version from `v=4.20` to `v=4.21`.
- Behavior intentionally preserved:
  - Exact ABHA Address duplicate checks still run first and keep the existing ABHA Address-specific message.
  - If only the ABHA Number is already linked through another address, the new ABHA Number message is shown and copy/link is blocked.
- Validation run locally:
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_verify_proxy.php` passed.
  - `php -l api/abha_registration_prefill_link_patient.php` passed.
  - `php -l api/abha_registration_prefill_status.php` passed.
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_verify_proxy.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_verify_proxy.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_status.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_status.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA CAPTCHA placement before OTP buttons

- User asked to place CAPTCHA immediately before the buttons that generate OTP.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Moved the CAPTCHA markup into the ABHA Number / Address OTP section before the two OTP buttons.
    - Added empty CAPTCHA target slots before the Aadhaar OTP and Create ABHA Aadhaar OTP buttons.
    - Added a mobile-account CAPTCHA slot before the mobile-search account OTP list.
    - Bumped `js/addPatient.js` cache version from `v=4.24` to `v=4.25`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added a helper to move the single CAPTCHA block to the active OTP-request section.
    - Moves CAPTCHA before ABHA Number / Address OTP buttons, Aadhaar OTP button, Create ABHA OTP button, and mobile-search account OTP buttons.
    - Keeps server-side CAPTCHA checks limited to OTP request actions.
    - Changed CAPTCHA Enter-key behavior so it no longer starts the ABHA flow; it only submits sections with one clear OTP action.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `node --check js/addPatient.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Separate ABHA Number deletion page

- User asked for a separate page to delete an ABHA Number using both Aadhaar OTP and ABHA OTP methods.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/abha_delete.php`
    - Added an authenticated page at `/abha_delete.php`.
    - Requires helper type `3`, `6`, or `a`.
    - Shows ABHA Number input, Aadhaar OTP / ABHA OTP method buttons, reason field, confirmation checkbox, CAPTCHA before Send OTP, and OTP verification UI.
    - Uses `init.js` with the shared `fileVersion.php` cache-busting pattern.
  - `/Users/apple/Documents/docbox_staging/js/abhaDelete.js`
    - Added client-side validation, custom Bootstrap alerts, CAPTCHA refresh, OTP request cooldown display, and final OTP verification handling.
    - Uses text-only rendering for messages returned by the server.
  - `/Users/apple/Documents/docbox_staging/api/abha_delete_proxy.php`
    - Added Main VPS authenticated API proxy with CSRF validation.
    - Verifies CAPTCHA before OTP request.
    - Sends only signed server-to-server requests to the Lightsail ABDM bridge.
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Added signed internal endpoint for ABHA Number deletion.
    - Supports `request_otp` and `verify_delete`.
    - Uses OTP resend limiter, stores only hashed local operation state, and writes sanitized metadata to `abdm_callback_debug_log.jsonl`.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Added V3 profile account delete OTP request and OTP verification service methods.
    - Supports Aadhaar OTP with `otpSystem=aadhaar` and ABHA OTP with `otpSystem=abdm`.
- Validation run locally:
  - `php -l abha_delete.php` passed.
  - `php -l api/abha_delete_proxy.php` passed.
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
  - `node --check js/abhaDelete.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/abha_delete.php` to `/home/stagingdocbox/public_html/abha_delete.php`
    - `/Users/apple/Documents/docbox_staging/js/abhaDelete.js` to `/home/stagingdocbox/public_html/js/abhaDelete.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_delete_proxy.php` to `/home/stagingdocbox/public_html/api/abha_delete_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`

## 2026-05-30 ABHA Number deletion X-token correction

- User reported `Invalid X-token` while testing the new ABHA Number deletion page.
- Root cause:
  - The ABDM profile-account delete endpoints require a profile session token.
  - The first implementation called the delete OTP endpoint directly.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/abha_delete.php`
    - Updated the OTP action label so the first OTP is clearly profile verification.
  - `/Users/apple/Documents/docbox_staging/js/abhaDelete.js`
    - Changed the UI flow to two OTP steps:
      1. Send and verify the selected ABHA Number OTP to establish the ABHA profile session.
      2. Automatically request the delete OTP, then verify it to complete deletion.
    - Locks the ABHA Number and OTP method after profile verification so the final OTP is tied to the same request.
  - `/Users/apple/Documents/docbox_staging/api/abha_delete_proxy.php`
    - Added `verify_login` bridge action and sends the ABHA Number again for state matching before delete OTP request.
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - `request_otp` now calls the V3 ABHA profile login OTP flow first.
    - Added `verify_login` to verify the first OTP, extract the profile token, then request the delete OTP with that token.
    - Final `verify_delete` now requires the stored profile token and delete OTP transaction.
    - Added table columns for login transaction, delete transaction, and profile token if missing.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Delete OTP request and verify methods now send the required `X-token` header.
- Validation run locally:
  - `php -l abha_delete.php` passed.
  - `php -l api/abha_delete_proxy.php` passed.
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
  - `node --check js/abhaDelete.js` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/abha_delete.php` to `/home/stagingdocbox/public_html/abha_delete.php`
    - `/Users/apple/Documents/docbox_staging/js/abhaDelete.js` to `/home/stagingdocbox/public_html/js/abhaDelete.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_delete_proxy.php` to `/home/stagingdocbox/public_html/api/abha_delete_proxy.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`

## 2026-05-30 ABHA Number deletion delete-OTP request hardening

- User reported: `ABHA profile was verified, but delete OTP could not be requested. Please send OTP again.`
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - The second ABDM call now posts directly from the bridge endpoint to the V3 profile account delete OTP endpoint.
    - This avoids depending on newly added `AbhaService` methods during deployment sync.
    - The direct call still sends the required `Authorization`, `REQUEST-ID`, `TIMESTAMP`, `X-CM-ID`, and `X-token` headers.
    - Added sanitized exception details to `abdm_callback_debug_log.jsonl` if the delete OTP request fails before ABDM returns JSON.
    - Final delete OTP verification now also uses the same direct V3 call path.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
  - `php -l api/abha_delete_proxy.php` passed.
  - `node --check js/abhaDelete.js` passed.
- Upload target:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion ABDM scope rejection handling

- User shared ABDM bridge logs showing:
  - First ABHA Number OTP request succeeds.
  - Profile OTP verification succeeds and returns a profile token.
  - Delete OTP request returns HTTP 400 with response key `scope`.
- Interpretation:
  - The code path reaches ABDM correctly and the profile token is present.
  - ABDM is rejecting the delete scope for the configured client/environment.
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Added explicit handling for ABDM `scope` rejection.
    - The browser will now receive a clear message: ABHA profile deletion must be enabled for the configured ABDM client/environment.
    - Added `error=ABDM_DELETE_SCOPE_REJECTED` and `abdmStatusCode` in the JSON response for this condition.
    - Added `scopeStatus` to the sanitized bridge debug log for the delete OTP request.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion scope changed to delete-only

- User found the online ABDM delete flow states profile account delete uses scope `delete` only.
- Previous code was sending `["abha-profile", "delete"]`, which matched the earlier collection but ABDM rejected it with `Invalid Scope`.
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Changed delete OTP request scope from `["abha-profile", "delete"]` to `["delete"]`.
    - Changed final delete OTP verification scope from `["abha-profile", "delete"]` to `["delete"]`.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Updated the shared delete request/verify helper methods to the same `["delete"]` scope for consistency.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion scope format fallback

- User retested after changing delete scope to `["delete"]`; ABDM still returned `Invalid Scope`.
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Delete OTP request now tries supported-looking scope formats only when ABDM returns a scope-specific 400:
      - `["delete"]`
      - `"delete"`
      - `["abha-profile", "delete"]`
    - Logs `scopeAttempt` in `abha_delete_delete_otp_request_result` so the accepted/rejected format is visible without logging sensitive values.
    - Stores the accepted scope format in `abdm_abha_delete_state.delete_scope_json`.
    - Final delete OTP verification reuses the same accepted scope format.
    - Adds the `delete_scope_json` column automatically if it is missing.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion full scope-attempt logging

- User shared a log where the delete OTP request stopped on `scopeAttempt=delete_string` with response keys `message` and `code`.
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - The delete OTP request now continues through the remaining scope variants for any HTTP 400 response without a transaction ID.
    - Added per-attempt log event `abha_delete_delete_otp_scope_attempt`.
    - Per-attempt and final logs include safe metadata: `scopeAttempt`, `statusCode`, `txnPresent`, `responseKeys`, `scopeStatus`, `abdmCode`, and `abdmMessage`.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion abha-address-login scope

- User provided the updated ABDM delete payload pattern:
  - Delete OTP request scope: `["abha-address-login"]`
  - Delete OTP request `loginHint`: `abha-number`
  - Delete OTP verify scope: `["abha-address-login", "delete"]`
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Added first scope attempt `abha_address_login_delete`.
    - Request step sends `scope=["abha-address-login"]`, `loginHint=abha-number`, encrypted ABHA Number, and the selected OTP system.
    - Final verify step stores and reuses `scope=["abha-address-login", "delete"]`.
    - Existing fallback attempts are kept after this new first attempt for diagnostics.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Updated shared delete request/verify helper methods to the same scope pattern.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion abha-login delete scope

- User provided the ABDM V3 delete implementation rules:
  - Public certificate is fetched from `/v3/profile/public/certificate` before encrypted fields are sent.
  - Delete OTP request uses scope `["abha-login"]`.
  - Delete OTP verification uses scope `["abha-login", "delete"]`.
  - OTP verification payload includes `authData.otp.timeStamp`.
- Existing utility confirmed:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmCrypto.php` already fetches and caches the ABDM public certificate and encrypts ABHA Number / OTP values with it.
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Changed the active delete OTP request scope to `["abha-login"]`.
    - Changed final delete OTP verification scope to `["abha-login", "delete"]`.
    - Added `timeStamp` inside `authData.otp` for delete OTP verification.
    - Removed earlier fallback scope variants from the active scope list so the delete flow uses the strict spec payload.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Updated shared delete helper methods to the same strict scopes and OTP timestamp.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA Number deletion abha-profile delete scope restored

- User provided the corrected ABDM V3 delete rules:
  - Delete OTP request scope must be `["abha-profile", "delete"]`.
  - Delete OTP verification scope must duplicate the same `["abha-profile", "delete"]` array.
  - OTP verification must include `authData.otp.timeStamp`.
- Updated Lightsail ABDM bridge files:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php`
    - Changed the active delete OTP request scope to `["abha-profile", "delete"]`.
    - Changed the final delete OTP verification scope to `["abha-profile", "delete"]`.
    - Kept `timeStamp` in `authData.otp`.
  - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php`
    - Updated shared delete helper methods to the same scopes and timestamp.
- Validation run locally:
  - `php -l api/internal_abdm_delete_abha.php` passed.
  - `php -l lib/AbhaService.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_delete_abha.php` to `/var/www/html/abdm-app/api/internal_abdm_delete_abha.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbhaService.php` to `/var/www/html/abdm-app/lib/AbhaService.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA card popup download button

- User asked to add a download-card action to the small ABHA card window that already has the Fill details button.
- Updated Lightsail popup page files:
  - `/Users/apple/Documents/docbox_staging/Public/abha_card_popup.php`
  - `/Users/apple/Documents/docbox_staging/public/abha_card_popup.php`
- Changes made:
  - Added a `Download card` button beside `Fill details`.
  - The card iframe still renders inline for review.
  - The new download action calls the same verified card stream with `download=1`, which serves the card with `Content-Disposition: attachment`.
  - Download filename extension is selected from the returned card content type (`.pdf`, `.png`, `.jpg`, `.webp`).
  - Existing popup token validation, no-store headers, and Fill details `postMessage` flow are unchanged.
- Validation run locally:
  - `php -l Public/abha_card_popup.php` passed.
  - `php -l public/abha_card_popup.php` passed.
- Upload targets:
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/Public/abha_card_popup.php` to `/var/www/html/abdm-app/Public/abha_card_popup.php`
    - `/Users/apple/Documents/docbox_staging/public/abha_card_popup.php` to `/var/www/html/abdm-app/public/abha_card_popup.php`
  - Main VPS context:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA captcha first-attempt sync

- User reported that the first captcha answer in Add Patient ABHA verification was rejected, the captcha refreshed, and the second answer worked.
- Root cause handled:
  - The captcha visible in the browser can be stale when the Add Patient page is restored or when the ABHA inline flow is started after an older challenge is already present in the DOM.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php`
    - Normal ABHA verification session creation now returns a fresh captcha challenge.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - When the ABHA verification session starts, the frontend immediately replaces the displayed captcha with the fresh server challenge before any OTP request can be made.
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Bumped `js/addPatient.js` cache version to `v=4.27`.
- Existing OTP request captcha validation remains unchanged.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_token_create.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_token_create.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABHA delete/deactivate removed from active scope

- User confirmed ABHA Number delete/deactivate should be removed from the active test/remediation scope because the current ABDM sandbox access does not allow completing that flow.
- Decision:
  - Do not treat the separate ABHA Number deletion page as a pending Add Patient ABHA test-case item.
  - Keep any already-created local delete/deactivate files as inactive/reference work unless the user later asks to remove them.
  - Active Add Patient ABHA scope remains verification, profile fetch, Create ABHA, ABHA Address creation, card view/download, fill details, and patient linking.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA captcha first-attempt retest completed

- User confirmed the captcha first-attempt retest is completed after the sync.
- Status:
  - The first correct captcha answer is now accepted.
  - This removes the captcha first-attempt item from the pending ABHA test-case list.
- Remaining active ABHA test-case item:
  - Sheet 2 ABHA Address policy validation.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Add Patient ABHA Address policy validation

- User asked to patch the remaining Sheet 2 ABHA Address policy test case and make the check live while entering a new ABHA Address.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/addPatient.php`
    - Added a live policy help line below the Create ABHA Address input.
    - Create button now starts disabled until the input format is valid.
    - Bumped `js/addPatient.js` cache version to `v=4.28`.
  - `/Users/apple/Documents/docbox_staging/js/addPatient.js`
    - Added live ABHA Address policy validation while typing and when selecting a suggested address.
    - Validation allows 8 to 18 characters before `@sbx`/`@abdm`.
    - Allows letters and numbers; one dot and one underscore are optional.
    - Dot/underscore cannot be first, last, repeated, or placed beside another separator.
    - Disables `Create ABHA Address` until the policy is satisfied.
- Updated Lightsail ABDM bridge file:
  - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php`
    - Server-side Create ABHA Address validation now enforces the same policy before calling ABDM.
- Validation run locally:
  - `php -l addPatient.php` passed.
  - `php -l api/internal_abdm_registration_verify.php` passed.
  - `node --check js/addPatient.js` passed.
  - A small Node policy check confirmed valid letters-only, numbers-only, mixed, dot, underscore, and dot+underscore examples pass; short, leading/trailing separator, repeated dot, and adjacent separator examples fail.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/addPatient.php` to `/home/stagingdocbox/public_html/addPatient.php`
    - `/Users/apple/Documents/docbox_staging/js/addPatient.js` to `/home/stagingdocbox/public_html/js/addPatient.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
  - Lightsail ABDM bridge:
    - `/Users/apple/Documents/docbox_staging/api/internal_abdm_registration_verify.php` to `/var/www/html/abdm-app/api/internal_abdm_registration_verify.php`

## 2026-05-30 Add Patient ABHA Address policy browser test completed

- User confirmed the ABHA Address policy patch was tested successfully.
- Status:
  - Live ABHA Address validation is working.
  - Server-side ABHA Address policy validation is in place.
  - The Sheet 2 ABHA Address policy item is closed.
- Current active Add Patient ABHA test-case status:
  - No known active pending item in the locally tracked spreadsheet/test-case scope.
- Upload target:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA link mismatch detection hardening

- User reported that demographic mismatch was not being detected after OTP verification in the Rectify Test VS ABHA link modal.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Made DocBox-vs-ABHA comparison read nested ABDM profile shapes as well as the flattened profile shape.
    - Broadened name, gender, age/DOB, and mobile field matching so stored verified profile variants are compared consistently.
    - For mobile-number verification, the verified mobile used for OTP is retained for comparison when ABDM does not return the mobile in the fetched profile.
    - When ABHA Number OTP verification returns multiple ABHA Addresses, mismatch information can be shown immediately while the user still must select an address before linking.
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.2`.
- Validation run locally:
  - `node --check js/rectifyAbhaLinkModal.js` passed.
  - `php -l Public/abha_patient_link_modal.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA phone mismatch comparison fix

- User reported that phone number mismatch was still not being matched correctly in the Rectify Test VS ABHA link modal.
- Deep check found two causes:
  - The iframe URL mobile could come from Rectify page state and could override the database patient mobile loaded by the modal page.
  - ABDM may return only partial/masked mobile information, while the browser comparison only checked a full 10-digit ABHA mobile.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - The modal now prefers the database patient mobile from `abha_prefill_patient_profile()` and only uses the URL mobile as fallback.
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.3`.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - ABHA profile sanitization now reads additional mobile/phone key variants.
    - Stores a full mobile only when 10 digits are available, and also keeps `mobileLast4` for safe comparison when ABDM returns a masked/partial value.
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - `patientMobileFromConfig()` now prefers the server-loaded patient profile mobile over the URL mobile.
    - Phone comparison now supports full ABHA mobile comparison and last-4 comparison when only masked/partial ABHA mobile is returned.
    - Mobile update helper text now distinguishes exact match, partial last-4 match, and mismatch instead of treating every partial value as different.
    - ABHA mobile display now shows either masked full mobile or `ending ####` without exposing full numbers.
- Validation run locally:
  - `node --check js/rectifyAbhaLinkModal.js` passed.
  - `php -l Public/abha_patient_link_modal.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - Local phone comparison check confirmed:
    - full different mobile is flagged;
    - partial/masked different last 4 is flagged;
    - partial/masked same last 4 is not flagged because the full ABHA mobile is not available for exact comparison.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA verified preview timing fix

- User reported that `verifiedPreview` was appearing immediately after OTP verification.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Removed the intermediate verified preview display when ABHA Number OTP returns multiple ABHA Addresses.
    - The flow now shows only the ABHA Address selection after OTP.
    - `verifiedPreview`, mismatch warning, and link actions are shown only after an ABHA Address is selected, or when ABHA Address verification completes directly.
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.4`.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA mobile update option visibility fix

- User reported that the ABHA mobile update option was still not shown after verification.
- Root cause:
  - The warning action button was shown only when a phone mismatch was positively detected.
  - If ABDM did not return a full mobile, returned only partial mobile, or the visible mismatch was name/age/gender only, the update option was hidden even though DocBox had a valid patient mobile.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Added `canOfferAbhaMobileUpdate()` to show the ABHA mobile update action whenever DocBox has a patient mobile and the ABHA mobile is not confirmed as an exact match.
    - The action now appears for confirmed mismatch, partial/unknown ABHA mobile, and name/age/gender mismatch cases where mobile can still be verified.
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.5`.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA selected-address mobile comparison alert

- User asked to explicitly check whether the DocBox stored mobile and the ABHA mobile fetched by ABHA Address/Number are the same, and to show both values in an alert when a fetched ABHA Address is selected.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - When an ABHA Address from the fetched address list is selected, the verified profile is stored and an alert is shown.
    - The alert shows masked DocBox mobile, masked/partial ABHA mobile, and a status:
      - mobile numbers match;
      - mobile numbers are different;
      - only last 4 digits match because full ABHA mobile was not returned;
      - unable to compare because one side is unavailable.
    - The actual comparison still uses the full values in memory when ABDM returns full mobile values.
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.6`.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA DocBox mobile source diagnostics

- User asked why DocBox mobile was not getting fetched in the selected-address comparison alert.
- Current fetch logic:
  - Main source: `patient.PhoneNumber` loaded server-side by `abha_prefill_patient_profile()`.
  - Fallback source: `patientMobile` sent by Rectify page in the iframe URL.
  - Both are accepted only when they clean down to a valid 10-digit mobile.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Added `patientMobileSource` to the modal config.
    - Source is `DocBox database` when `patient.PhoneNumber` is valid.
    - Source is `Rectify page` when the database value is unavailable but the Rectify page supplied a valid value.
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.7`.
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Mobile comparison alert now shows `DocBox source`.
    - If no valid value is found, it says `No valid 10-digit mobile from DocBox database or Rectify page`.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA update DocBox mobile from ABHA option

- User confirmed DocBox name and DOB/age update from ABHA works, but there was no separate option to update DocBox phone number from the ABHA registered mobile when a mismatch happens.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Added `Update DocBox mobile from ABHA and link` action in the mismatch warning actions.
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.8`.
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Shows the new action only when ABHA returned a full 10-digit mobile and it differs from DocBox mobile, or DocBox mobile is unavailable.
    - Treats missing/invalid DocBox mobile plus full ABHA mobile as a phone mismatch so the update option is visible.
    - The action sends `updateDocboxMobile: true` while linking.
    - If ABHA returned only masked/partial mobile, the action is not shown because DocBox cannot be updated from partial data.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - Added `abha_prefill_update_patient_mobile()` to update only `patient.PhoneNumber` from the verified ABHA profile.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php`
    - Accepts `updateDocboxMobile`.
    - Updates only DocBox mobile before linking when requested.
    - Returns `updatedDocboxMobile` and the refreshed patient profile.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 Rectify ABHA update-before-link enforcement

- User requested:
  - Move `updateAbhaMobileFromWarningBtn` into `mobileUpdateSection`.
  - Updating DocBox profile or phone number must be separate from linking.
  - ABHA must not be linked until the compared details match.
- Updated Main VPS files:
  - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php`
    - Moved `updateAbhaMobileFromWarningBtn` into `mobileUpdateSection`.
    - Removed `Link without updating` from the mismatch warning.
    - Changed update buttons to update-only labels:
      - `Update DocBox details from ABHA`
      - `Update DocBox mobile from ABHA`
    - Bumped `js/rectifyAbhaLinkModal.js` cache version to `v=2.9`.
  - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js`
    - Update buttons now call update-only API behavior and do not link.
    - Link button is hidden while any mismatch remains.
    - Link action checks the mismatch list before submitting.
    - Phone is considered unmatched if DocBox has a mobile and ABHA does not provide a full matching mobile.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php`
    - `abha_prefill_update_patient_demographics()` can update profile details without changing phone.
    - Added server-side mismatch comparison helper for name, gender, age, and phone.
    - Phone match requires the full ABHA mobile to match the full DocBox mobile when DocBox has a valid mobile.
  - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php`
    - Added `updateOnly` mode for DocBox profile/mobile corrections without consuming the ABHA token or linking.
    - Rejects requests that try to update DocBox details and link in the same call.
    - Added optional server-side match enforcement for final link requests.
- Validation run locally:
  - `node --check js/rectifyAbhaLinkModal.js` passed.
  - `php -l Public/abha_patient_link_modal.php` passed.
  - `php -l api/abha_registration_prefill_common.php` passed.
  - `php -l api/abha_registration_prefill_link_patient.php` passed.
- Upload targets:
  - Main VPS:
    - `/Users/apple/Documents/docbox_staging/Public/abha_patient_link_modal.php` to `/home/stagingdocbox/public_html/Public/abha_patient_link_modal.php`
    - `/Users/apple/Documents/docbox_staging/js/rectifyAbhaLinkModal.js` to `/home/stagingdocbox/public_html/js/rectifyAbhaLinkModal.js`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_common.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_common.php`
    - `/Users/apple/Documents/docbox_staging/api/abha_registration_prefill_link_patient.php` to `/home/stagingdocbox/public_html/api/abha_registration_prefill_link_patient.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM prescription PDF documents table schema note

- User asked whether adding a new column to `documents` means all APIs that store or read documents must be changed.
- Decision:
  - Adding a nullable/defaulted column such as `VisitVersion` does not require changing all read APIs.
  - Read APIs using explicit columns can stay as-is unless they need the new value.
  - Read APIs using `SELECT *` generally continue to work, but front-end code should ignore unknown fields.
  - Inserts that use explicit column lists continue to work, but they will not populate `VisitVersion` until intentionally patched.
  - Inserts that use bare `INSERT INTO documents VALUES (...)` must be changed to explicit column lists before/with the schema change, because column-count assumptions will break when a new column is added.
- Code search notes:
  - Explicit column-list inserts found in:
    - `sajid/uploadDocumentsNew.php`
    - `sajid/db_functions.php`
  - Bare insert patterns needing review/patch before adding the column:
    - `sajid/insertDocuments.php`
    - `sajid/db_functions.php`
    - `sajid/db_functionsPatients.php`
    - `sajid/sendSmsDummydata.php` likely legacy/test path; confirm before production relevance.
- Recommended implementation path:
  - Add nullable `VisitVersion` to `documents`.
  - Convert bare `INSERT INTO documents VALUES (...)` statements to explicit column lists.
  - Populate `VisitVersion` only from prescription PDF generation paths first.
  - Keep existing uploads and older document rows working with `VisitVersion = NULL`.
  - ABDM prescription PDF lookup should use `VisitVersion` when present and use existing filename/date lookup as a fallback for older rows.
- No application code changed in this note; context only.

## 2026-05-30 documents.DocumentName and documents.DocumentPath usage map

- User asked where `DocumentName` and `DocumentPath` are used before deciding how to store visit version for prescription PDFs.
- `documents.DocumentName` usage:
  - Main visible/download filename in patient report UIs:
    - `js/patientReportWeb.js`
    - `js/patientReportCentrallisedS3.js`
    - `js/patientReportCentrallised.js`
    - older report/slit-lamp JS variants.
  - Used to resolve actual file URLs by doctor/patient folder in `sajid/getFollowupUrl.php`.
  - Used by delete flow:
    - Frontend sends `documentName` from the rendered card.
    - `sajid/testDel.php` deletes `documents` by `CustomerId`, `PatientId`, and `DocumentName`, then deletes the local file with the same basename when present.
    - Legacy helper `sajid/db_functions.php::deleteReports()` also deletes by `DocumentName`.
  - Used to join archived/drive mappings:
    - `sajid/getPatientArchivedDocumentsWeb.php`
    - `sajid/db_functions.php` archived document helpers.
  - Used in inserts for uploaded/generated documents, usually with the same value also written into `DocumentPath`.
- `documents.DocumentPath` usage:
  - Mostly written with the same filename value as `DocumentName`.
  - Used as a de-dup/delete key before inserting in:
    - `sajid/insertDocuments.php`
    - `sajid/reportPrintingPDF.php`
    - legacy/dynamic helper path in `sajid/db_functions.php`.
  - Used in `js/clinicalNotes.js` only as display/text handling from returned rows.
  - `DocumentPath` also exists in `mediaFollowUp`; those references are separate from the `documents` table and should not drive the `documents` schema decision.
- Conclusion:
  - Do not reuse either `DocumentName` or `DocumentPath` for `VisitVersion`.
  - `DocumentName` is the stronger live filename/display/delete field.
  - `DocumentPath` is less visible but still participates in save/delete behavior, so repurposing it would change existing document lifecycle logic.
  - Add a separate nullable `VisitVersion` column and patch only insert paths that need to populate it.

## 2026-05-30 documents.SyncStatus usage note

- User asked whether `documents.SyncStatus` can be used instead of adding a new visit-version column.
- Findings:
  - `SyncStatus` is written during document creation:
    - `sajid/uploadDocumentsNew.php` writes uploaded documents with `SyncStatus = '5'`.
    - `sajid/reportPrintingPDF.php` writes generated report PDFs with `SyncStatus = '5'`.
    - `sajid/uploadSurgeryAttachment.php` writes surgery attachments with `SyncStatus = '1'`.
    - `sajid/db_functions.php` legacy document insert helpers write `SyncStatus` values such as `1` and `5`.
  - `SyncStatus` is read/filtered by sync-style flows:
    - `sajid/db_functions.php` selects document rows where `documents.syncStatus IN ('0','5','3')`.
  - `SyncStatus` is mass-updated by sync-style flows:
    - `sajid/changeDoctorSyncStatuses.php` calls `DB_Functions::changeSyncStatus()`.
    - `sajid/db_functions.php::changeSyncStatus()` updates `documents.syncStatus` for a doctor.
    - `sajid/db_functions.php::changeSyncStatusOfsinglePatient()` updates `documents.syncStatus` for a patient.
  - `SyncStatus = 3` is treated specially by cleanup logic that deletes rows with that value.
- Conclusion:
  - Do not reuse `documents.SyncStatus` for `VisitVersion`.
  - It is an application workflow/status field, not a document identity field.
  - Reusing it would interfere with sync filtering, mass updates, and cleanup behavior.
  - Keep `SyncStatus` unchanged and add a separate nullable `VisitVersion` column.

## 2026-05-30 ABDM prescription PDF mapping table decision

- User decided not to add a new column to the shared `documents` table because it is also used for non-prescription documents.
- Revised direction:
  - Create a separate mapping table for prescription/ABDM document metadata.
  - Keep `documents` unchanged.
  - Link mapping rows back to `documents` using the document identity fields.
- Important design note:
  - Do not use `DocumentName` alone as the key because the same file name can exist for different doctors/patients.
  - Use a composite link:
    - `CustomerId`
    - `PatientId`
    - `DocumentName`
    - optionally `DocumentPath` if needed for old rows where path/name behavior differs.
- Suggested mapping table fields:
  - `Id` primary key.
  - `CustomerId`
  - `PatientId`
  - `DocumentName`
  - `DocumentPath`
  - `VisitVersion`
  - `CareContextReference`
  - `DocumentType` such as `PrescriptionPDF`
  - `FileHash` optional for file integrity/deduplication.
  - `CreatedAt`
  - `UpdatedAt`
- Implementation direction:
  - Patch only prescription PDF generation paths to insert/update this mapping table.
  - ABDM document lookup should join/read this mapping table to find the PDF for a visit version.
  - Existing document upload/report flows should continue using `documents` as-is.

## 2026-05-30 Legacy prescription PDF fallback resolution rule

- User noted that older prescription PDFs may need to be resolved from the existing file name because the new mapping table will not exist for historical rows.
- User also noted that the visit version is a Unix timestamp, and the generated prescription file timestamp can have different hours/minutes while still being the same visit date.
- Fallback resolver rule:
  - First try the new ABDM prescription document mapping table by `CustomerId`, `PatientId`, and `VisitVersion`.
  - If no mapping exists, resolve from `documents` for the same `CustomerId` and `PatientId`.
  - Convert the visit `VisitVersion` Unix timestamp to the clinic timezone date.
  - Consider only prescription PDF-like document names.
  - Prefer document names whose embedded/generated date is the same calendar date as the visit version.
  - Add a grace window around the visit timestamp for cases where the prescription generation time differs from the visit version time.
  - Suggested default grace window: same calendar date first, then nearest document within 24 hours of the visit timestamp if multiple same-day candidates exist.
  - If more than one candidate remains, prefer the nearest timestamp, then the newest document row by `Date`.
  - After a legacy row is resolved with confidence, backfill the new mapping table so future lookups do not depend on filename inference.
- Safety rule:
  - Never match across different `CustomerId` or `PatientId`.
  - Never use a legacy fallback result if multiple candidates remain equally likely; return a clear "prescription PDF not uniquely resolved" message instead.

## 2026-05-30 ABDM prescription PDF mapping step 1

- User asked to start with step 1 of the ABDM prescription PDF inclusion plan.
- Implemented schema-only migration file:
  - `/Users/apple/Documents/docbox_staging/sql/create_abdm_prescription_documents.sql`
- New table:
  - `abdm_prescription_documents`
- Purpose:
  - Store prescription/ABDM PDF metadata without changing the shared `documents` table.
  - Link to `documents` logically by `CustomerId`, `PatientId`, and `DocumentName`.
  - Store `VisitVersion`, optional `CareContextReference`, optional `FileHash`, and resolution method.
- Important design decision:
  - No hard database foreign key was added to `documents`.
  - Reason: existing `documents` table does not expose a guaranteed unique key on `CustomerId + PatientId + DocumentName`, and adding that constraint now could affect existing document flows.
- Main keys:
  - `uniq_patient_visit_doc_type` on `CustomerId`, `PatientId`, `VisitVersion`, `DocumentType`.
  - `idx_patient_document_name` on `CustomerId`, `PatientId`, `DocumentName`.
  - `idx_care_context_reference`.
  - `idx_file_hash`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/sql/create_abdm_prescription_documents.sql` to `/home/stagingdocbox/public_html/sql/create_abdm_prescription_documents.sql`

## 2026-05-30 ABDM prescription PDF mapping step 2 investigation

- User noted there may already be a save-documents API.
- Confirmed the active generic endpoint is:
  - `/Users/apple/Documents/docbox_staging/sajid/insertDocuments.php`
- Purpose of this endpoint:
  - Receives `documentsJSON`.
  - Saves rows into the shared `documents` table.
  - Is already guarded by API auth, CSRF, upload access, doctor/center mapping, and patient existence checks.
- Current document row format used by the UI:
  - `CustomerId`
  - `PatientId`
  - `Date`
  - `DocumentName`
  - `DocumentPath`
  - `SyncStatus`
  - Token row as the final array entry.
- Limitation:
  - The endpoint does not currently receive `VisitVersion`, so it cannot create `abdm_prescription_documents` mappings by itself without either an optional extra field or filename/date inference.
- Rectify Test VS prescription print/save paths already call this endpoint after PDF generation from `js/patientInfo_oph_rectify_test_vs.js`.
- Safe next implementation direction:
  - Keep `insertDocuments.php` backward-compatible.
  - Allow an optional 7th row value for `VisitVersion` and optional 8th marker for ABDM prescription mapping.
  - Only insert/update `abdm_prescription_documents` when the optional marker is present and the document is a prescription PDF.
  - Patch the Rectify prescription PDF save rows to pass `localStorage.getItem('followVersion')`.
  - Leave generic uploaded reports and other documents unchanged.

## 2026-05-30 ABDM prescription PDF mapping step 2 implementation

- User decided not to extend `sajid/insertDocuments.php`.
- Implemented a separate mapping API that runs alongside the existing document save:
  - `/Users/apple/Documents/docbox_staging/sajid/saveAbdmPrescriptionDocument.php`
- API behavior:
  - Requires authenticated session.
  - Requires CSRF validation.
  - Uses the same patient reports upload role gate as `insertDocuments.php`.
  - Validates hospital/doctor access and patient existence.
  - Accepts `doctorId`, `patientId`, `visitVersion`, `documentName`, optional `documentPath`, and optional `careContextReference`.
  - Only accepts PDF filenames and rejects path-style input.
  - Verifies the generated PDF exists under `sajid/{doctorId}/{patientId}/{documentName}` before mapping.
  - Stores/updates `abdm_prescription_documents` using `CustomerId`, `PatientId`, `VisitVersion`, and `DocumentType = PrescriptionPDF`.
  - Stores a SHA-256 file hash when the file is available.
- Rectify Test VS wiring:
  - Added `docboxRecordAbdmPrescriptionDocument(documentName)` in `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`.
  - Prescription print-save branches now call the new mapping API in parallel with the existing `sajid/insertDocuments.php` save.
  - Existing `insertDocuments.php` behavior remains unchanged.
  - The helper uses `navigator.sendBeacon` when available to tolerate the existing immediate page reload, with AJAX fallback.
- Cache bust:
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - Updated `js/patientInfo_oph_rectify_test_vs.js` from `v=40.64` to `v=40.65`.
- Local checks:
  - `php -l sajid/saveAbdmPrescriptionDocument.php` passed.
  - `node --check js/patientInfo_oph_rectify_test_vs.js` passed after excluding an inactive commented prescription branch from the mechanical helper insertion.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/sajid/saveAbdmPrescriptionDocument.php` to `/home/stagingdocbox/public_html/sajid/saveAbdmPrescriptionDocument.php`
    - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js` to `/home/stagingdocbox/public_html/js/patientInfo_oph_rectify_test_vs.js`
    - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html` to `/home/stagingdocbox/public_html/patientInfo_oph_rectify_test_vs.html`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM prescription PDF mapping step 3

- User confirmed prescription generation still works and `abdm_prescription_documents` is being populated.
- Implemented direct PDF inclusion in the M2 care-context document builder.
- Updated files:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmCareContextDocumentService.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- `AbdmCareContextDocumentService` now:
  - Loads `hmis_doctor_id` with the linked care context.
  - Looks up matching `abdm_prescription_documents` rows by `CustomerId`, `PatientId`, `VisitVersion`, and `DocumentType = PrescriptionPDF`.
  - Verifies the mapped PDF still exists under `sajid/{CustomerId}/{PatientId}/{DocumentPath}`.
  - Rejects path-style document values and only embeds PDF files.
  - Skips missing/oversized files instead of failing the whole care-context response.
  - Adds the current `CareContextReference` to the mapping row when the mapping row does not already have it.
- `AbdmPrescriptionFhirBundleService` now:
  - Accepts `documentReferences` in the share object.
  - Adds a `Binary` resource with the PDF bytes encoded as base64.
  - Adds a `DocumentReference` resource pointing to that `Binary`.
  - Adds a `Prescription PDF` section in the OP consultation `Composition`.
- Local checks:
  - `php -l lib/AbdmCareContextDocumentService.php` passed.
  - `php -l lib/AbdmPrescriptionFhirBundleService.php` passed.
  - Local bundle build smoke test produced `Composition`, `Patient`, `Organization`, `Practitioner`, `Encounter`, `Binary`, and `DocumentReference` resources.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/lib/AbdmCareContextDocumentService.php` to `/home/stagingdocbox/public_html/lib/AbdmCareContextDocumentService.php`
    - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php` to `/home/stagingdocbox/public_html/lib/AbdmPrescriptionFhirBundleService.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
- Test correction:
  - `api/abdm_care_context_document_debug.php` accepts `POST` with JSON, not `GET` query parameters.
  - Browser URL test with `?careContextReference=...` returns `Method not allowed`.
  - Use a POST request with body `{"careContextReference":"..."}`.
- Test result:
  - User tested `CC_01f032f4bd353ac1cea2dca382aa8e23`.
  - Endpoint returned HTTP 500 with message `The requested care context is not currently linked to an ABHA address.`
  - This is expected guard behavior from `AbdmCareContextDocumentService::loadLinkedCareContext()`.
  - The debug test must use a care context row where `abha_address` is present and `link_status` is not delinked/inactive/hidden/cancelled/canceled/deleted.

## 2026-05-30 ABDM prescription PDF mapping step 4

- User clarified:
  - Visit creation happens only in Rectify.
  - The end step of visit save is prescription PDF creation.
  - Therefore the care context should already exist by the time `sajid/saveAbdmPrescriptionDocument.php` records the prescription mapping.
- Updated:
  - `/Users/apple/Documents/docbox_staging/sajid/saveAbdmPrescriptionDocument.php`
- Behavior added:
  - If the client does not pass `careContextReference`, the API resolves it server-side from `abdm_patient_care_context` using:
    - `hmis_doctor_id = doctorId`
    - `hmis_patient_id = patientId`
    - `visit_version = visitVersion`
  - The resolved care-context reference is stored in `abdm_prescription_documents.CareContextReference` during prescription mapping creation/update.
  - If no care context exists yet, the mapping still saves by visit identity and can be resolved later by the M2 builder.
- Local check:
  - `php -l sajid/saveAbdmPrescriptionDocument.php` passed.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/sajid/saveAbdmPrescriptionDocument.php` to `/home/stagingdocbox/public_html/sajid/saveAbdmPrescriptionDocument.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`
- Successful test:
  - User tested `api/abdm_care_context_document_debug.php` with care context `CC_670ba718ef55058f837eeccb36be59da`.
  - Response returned `success: true`.
  - Bundle checks passed:
    - `DocumentReference: true`
    - `Binary: true`
    - `PDF: true`
    - `Prescription section: true`
  - This confirms the new prescription PDF mapping and FHIR inclusion path works for a linked care context.

## 2026-05-30 ABDM prescription PDF mapping step 5

- Implemented the conservative legacy prescription PDF resolver for older visits where `abdm_prescription_documents` does not yet have a valid direct mapping.
- Updated:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmCareContextDocumentService.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Behavior added:
  - If no valid direct mapping is found in `abdm_prescription_documents`, the M2 builder checks the legacy `documents` table for the same:
    - `CustomerId`
    - `PatientId`
  - It only considers rows where:
    - `DocumentName` or `DocumentPath` contains `prescription`.
    - `DocumentName` or `DocumentPath` ends in `.pdf`.
    - `SyncStatus` is not `3`.
    - The local PDF exists under `sajid/{CustomerId}/{PatientId}/{DocumentPath}`.
  - It matches by visit date using:
    - embedded filename timestamp, for example `prescription_YYYY-MM-DD_H_i.pdf` or `prescription_YYYY-MM-DD_H:i.pdf`;
    - then `documents.Date`;
    - then nearest file within 24 hours.
  - It skips legacy fallback if multiple equally likely candidates remain.
  - On a confident match, it backfills `abdm_prescription_documents` with:
    - `VisitVersion`
    - `CareContextReference`
    - `FileHash`
    - `ResolutionMethod` such as `legacy_filename_same_day`, `legacy_document_date_same_day`, or `legacy_nearest_24h`.
  - After backfill, the same `DocumentReference` + `Binary` FHIR inclusion path is used.
- Local check:
  - `php -l lib/AbdmCareContextDocumentService.php` passed.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/lib/AbdmCareContextDocumentService.php` to `/home/stagingdocbox/public_html/lib/AbdmCareContextDocumentService.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM prescription PDF mapping step 6

- Reviewed the real M2 health-information prepare and transfer path after debug bundle validation.
- Files reviewed:
  - `/Users/apple/Documents/docbox_staging/api/internal_health_information_request_prepare.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbdmHealthInformationTransferService.php`
  - `/Users/apple/Documents/docbox_staging/api/internal_health_information_transfer_payloads.php`
  - `/Users/apple/Documents/docbox_staging/api/internal_health_information_transfer_prepare_encryption.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_consents_hip_notify.php`
- Findings:
  - Lightsail receives the M2 callback and calls main VPS `/api/internal_health_information_request_prepare.php`.
  - The prepare endpoint uses `AbdmCareContextDocumentService::buildBundleForCareContextReference()`, so the same PDF-aware FHIR bundle path is used for real M2 requests.
  - The prepared bundle is persisted in `abdm_health_information_transfer.fhir_bundle_json`.
  - `AbdmHealthInformationTransferService` reads `fhir_bundle_json` directly and encrypts that exact content for transfer.
  - The encrypted payload endpoint returns already encrypted payloads only; it does not rebuild or filter the FHIR resources.
- Result:
  - No application-code patch was required for this step.
  - The next validation should be a real M2 request test and DB check that the transfer row contains `DocumentReference`, `Binary`, and `application/pdf` before encryption.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-31 ABDM M2 deep-link notification explanation

- User asked for more detail about the pending deep-link notification case from the mandatory M2 sheet.
- Meaning:
  - This flow applies when DocBox creates a new health record for a patient whose mobile number is available, but whose ABHA address is not yet linked/stored in DocBox.
  - The HIP notifies ABDM/HIE-CM that a new health record exists for that mobile and HIP ID.
  - ABDM sends an SMS to the patient with a deep link.
  - The patient opens a PHR app from the link, the PHR initiates discovery against DocBox, and DocBox returns discoverable care contexts.
  - The patient then links the selected care context through the normal user-initiated linking flow and can pull the record.
- Difference from current implemented flows:
  - Current ABHA verification/linking handles cases where the ABHA address is known or verified inside DocBox.
  - Current `AbdmLinkOtpService` sends link OTPs for the user-initiated linking step; it is not the ABDM deep-link SMS notification.
  - The missing piece is the HIP-to-ABDM mobile notification call for unlinked records.
- Implementation implication:
  - Trigger after new care-context/health-record creation when:
    - patient mobile number is present;
    - care context has no stored ABHA address;
    - record is eligible for ABDM sharing;
    - duplicate notification for the same visit/care context has not already been sent.
  - Store status for audit/retry instead of sending repeatedly on every save.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM PHR display patch

- User checked transfer row `348`.
- Result:
  - `entry_count = 7`
  - `has_composition = 1`
  - `has_patient = 1`
  - `has_encounter = 1`
  - `has_diagnosis_or_history = 0`
  - `has_medicines = 0`
  - `has_allergies = 0`
  - `has_chief_complaint_section = 1`
  - `has_examination_section = 1`
  - `has_medications_section = 0`
  - `has_pdf_section = 1`
- Interpretation:
  - The bundle had chief complaint and examination sections, but those were text-only Composition sections.
  - The bundle did not contain structured `Observation` resources for chief complaint/examination/advice.
  - PHR appeared to render only the document reference.
- Updated:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php`
- Behavior added:
  - Chief complaint, examination findings, and advice are now emitted as `Observation` resources when present.
  - The Composition sections `Chief Complaints`, `Physical Examination`, and `Follow Up` now include `section.entry` references to those `Observation` resources.
  - Existing PDF `DocumentReference` behavior is unchanged.
- Local checks:
  - `php -l lib/AbdmPrescriptionFhirBundleService.php` passed.
  - Local bundle smoke test produced:
    - `Composition: 1`
    - `Patient: 1`
    - `Organization: 1`
    - `Practitioner: 1`
    - `Observation: 3`
    - `Encounter: 1`
    - `Binary: 1`
    - `DocumentReference: 1`
  - Smoke test also confirmed section entries:
    - `Chief Complaints: 1`
    - `Physical Examination: 1`
    - `Follow Up: 1`
    - `Prescription PDF: 1`
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php` to `/home/stagingdocbox/public_html/lib/AbdmPrescriptionFhirBundleService.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-31 ABDM M2 mandatory test-case sheet review

- User provided mandatory M2 test cases from:
  - `/Users/apple/Downloads/m2_mandatory.xlsx`
- Workbook contents:
  - One sheet, `Sheet1`, with 19 populated rows.
  - Covered groups:
    - Health record creation.
    - HIP-initiated health-record linking.
    - User-initiated health-record linking.
    - Deep-link notification workflow.
    - Data transfer and share.
- Implementation mapping:
  - `Health_RECORD_CREATION_101`: implemented for OPConsultation FHIR health records. Fresh visit testing confirms structured clinical details and prescription PDF are visible in PHR.
  - `HIP_INTI_LINK_501` to `HIP_INTI_LINK_506`: implemented through ABHA verification/profile fetch, demographic match/update checks, link-token generation, care-context linking, and PHR pull validation.
  - `USER_INIT_LINK_601` to `USER_INIT_LINK_607`: server-side support exists through discovery matching, on-discover response, link init, OTP handling, link confirm, and PHR pull validation.
  - `HIP_INIT_SHARE_CARECONTEXT`: implemented and end-to-end tested. Fresh transfer row `348` reached `encrypted`, `pushed`, `notified`, `transferred`, with visible clinical details and PDF in PHR.
  - `HIP_INIT_NOTIFY_HIECM`: not yet implemented as described in the sheet. The current code has link OTP SMS support, but no clear gateway deep-link notification flow for a new health record where mobile is present and ABHA address is not yet available.
- Current action item:
  - If this mandatory case applies to DocBox scope, implement the ABDM deep-link notification flow for unlinked patients after new health-record creation.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM PHR PDF open fix

- User reported:
  - The care context appears in PHR.
  - Clicking the PDF shows: `unable to fetch health record the record shared by facility is invalid`.
- Reviewed ABDM/NRCeS DocumentReference profile:
  - `DocumentReference.content.attachment.contentType` is required.
  - `DocumentReference.content.attachment.data` is required.
- Prior behavior:
  - PDF bytes were embedded in a separate `Binary` resource.
  - `DocumentReference.content.attachment` only pointed to `Binary/{id}` through `url`.
  - Some PHR clients do not resolve that relative Binary reference for opening the PDF.
- Updated:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php`
- Behavior added:
  - `DocumentReference.content.attachment.data` now contains the base64 PDF data directly.
  - `DocumentReference.content.attachment.url` is omitted when inline `data` is present.
  - `DocumentReference.content.attachment.hash` is populated from the stored SHA-256 as FHIR base64Binary.
  - `Binary` resource is still included and now has the ABDM Binary profile in `meta.profile`.
- Local checks:
  - `php -l lib/AbdmPrescriptionFhirBundleService.php` passed.
  - Focused bundle smoke test confirmed:
    - PDF attachment has inline `data`.
    - PDF attachment does not use relative `url`.
    - PDF attachment has FHIR `hash`.
    - `contentType = application/pdf`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php` to `/home/stagingdocbox/public_html/lib/AbdmPrescriptionFhirBundleService.php`
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM PHR display follow-up

- User confirmed the fresh M2 care context is visible in PHR, but PHR appears to show only the document reference and not the other clinical fields.
- Code reviewed:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmVisitPayloadService.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbdmVisitFhirMapperService.php`
  - `/Users/apple/Documents/docbox_staging/lib/AbdmPrescriptionFhirBundleService.php`
- Current code behavior:
  - The M2 builder can include structured OPConsultation data for patient/facility/practitioner/encounter, chief complaint, examination findings, advice, diagnoses, medications, allergies, histories, and prescription PDF document reference.
  - The next check is to inspect transfer row `348` and count actual FHIR resource types/Composition sections inside `fhir_bundle_json`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 new-visit end-to-end success

- User created a fresh visit and tested the full M2 flow from the beginning.
- Transfer result:
  - `id = 348`
  - `health_information_request_id = 131`
  - `care_context_reference = CC_cb214f22b27588a7c53d7f8f7f303ace`
  - `hi_type = OPConsultation`
  - `encryption_status = encrypted`
  - `push_status = pushed`
  - `notify_status = notified`
  - `transfer_status = transferred`
  - `error_code = NULL`
  - `error_message = NULL`
  - `has_document_reference = 1`
  - `has_binary = 1`
  - `has_pdf = 1`
  - `has_encrypted_payload = 1`
- Interpretation:
  - Prescription PDF inclusion in the M2 FHIR bundle is confirmed.
  - Encryption, data push, and transfer notify are confirmed working end to end for a fresh visit.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 push/notify failure state

- User checked transfer row `346` after push attempt.
- Current DB state:
  - `health_information_request_id = 129`
  - `encryption_status = encrypted`
  - `push_status = failed`
  - `notify_status = failed`
  - `transfer_status = failed`
  - `error_code = TRANSFER_NOTIFY_FAILED`
  - `error_message = ABDM transfer notify returned HTTP 400`
  - `has_payload = 1`
  - `payload_json_valid = 1`
  - `data_push_url = https://apissbx.abdm.gov.in/abha/api/v3/patient-hiu/app/v0.5/health-information/transfer`
- Interpretation:
  - Encryption is complete and the encrypted payload JSON is valid.
  - The push attempt ran, but the outbound transfer/notify phase did not complete successfully.
  - Because `push_status = failed`, inspect both `hip_transfer_data_push_exchange` and `hip_transfer_notify_exchange` logs for request row `129` / transfer row `346`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 push returned no ready payloads

- User called the transfer push endpoint for request row `129`.
- Response:
  - `success = false`
  - `message = No encrypted transfer payloads are ready for push.`
  - `result.request.id = 129`
  - `result.count = 0`
- Code reviewed:
  - `/Users/apple/Documents/docbox_staging/api/internal_health_information_transfer_payloads.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_health_information_transfer_push.php`
- Finding:
  - The payload loader only returns transfer rows matching:
    - `health_information_request_id = requestRecordId`
    - `encryption_status = encrypted`
    - `transfer_status = encrypted`
  - It also skips rows where `encrypted_payload_json` is not valid JSON.
- Next check:
  - Inspect transfer row `346` to confirm current `transfer_status`, `push_status`, `notify_status`, and JSON validity before retrying push.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 encryption retry success

- User retried encryption after the Fidelius helper became reachable.
- Result for transfer row `346`:
  - `encryption_status = encrypted`
  - `transfer_status = encrypted`
  - `has_encrypted_payload = 1`
- Interpretation:
  - The M2 bundle containing the prescription PDF was encrypted successfully.
  - Next validation is the transfer push and ABDM notify status.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM Fidelius service reachable

- User tested from local machine:
  - `curl -i http://abdm.docbox.asia:8090/encrypt`
- Result:
  - HTTP `405`
  - `Allow: POST`
  - JSON body with `path: /encrypt`
- Interpretation:
  - The Fidelius helper endpoint is now reachable.
  - HTTP `405` is expected for a GET request because the endpoint accepts POST only.
  - Next validation should be run from the main VPS staging server, then retry encryption for request row `129` / transfer row `346`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM Fidelius restart note

- User suspects `http://abdm.docbox.asia:8090/encrypt` is stopped and asked how to restart it.
- Local repo check:
  - No systemd unit, Docker compose file, PM2 config, or local startup script for the Fidelius helper was found in the repository.
  - The configured endpoint still comes from `/Users/apple/Documents/docbox_staging/config/config.php` via `FIDELIUS_ENCRYPT_URL`, defaulting to `http://abdm.docbox.asia:8090/encrypt`.
- Server to check:
  - Lightsail ABDM server for `abdm.docbox.asia`.
- Operational guidance:
  - First identify whether Fidelius is managed by `systemctl`, Docker, PM2, or a manual Java process.
  - After restart, confirm port `8090` is listening locally on Lightsail and reachable from the main VPS.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 encryption failure check

- User checked failed transfer row `346`.
- Error observed:
  - `ENCRYPTION_FAILED`
  - `HTTP request failed: Failed to connect to abdm.docbox.asia port 8090: Connection refused`
- Code/config reviewed:
  - `/Users/apple/Documents/docbox_staging/lib/AbdmFideliusEncryptionService.php`
  - `/Users/apple/Documents/docbox_staging/config/config.php`
- Finding:
  - The PDF FHIR bundle is already present in the real transfer row.
  - The remaining blocker is that the configured Fidelius encryption helper endpoint is not reachable from the main VPS at `http://abdm.docbox.asia:8090/encrypt`.
  - `config/config.php` already supports overriding this with `FIDELIUS_ENCRYPT_URL`.
- Required server action:
  - Ensure the Fidelius helper is running and reachable from the main VPS.
  - Either run it on the main VPS and set `FIDELIUS_ENCRYPT_URL=http://127.0.0.1:8090/encrypt`, or expose a restricted Lightsail-only/main-VPS-allowed endpoint and set `FIDELIUS_ENCRYPT_URL` to that reachable address.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-30 ABDM M2 transfer validation result

- User ran the transfer-row DB check for care context `CC_670ba718ef55058f837eeccb36be59da`.
- Result row:
  - `id = 346`
  - `health_information_request_id = 129`
  - `hi_type = OPConsultation`
  - `encryption_status = failed`
  - `transfer_status = encryption_failed`
  - `has_document_reference = 1`
  - `has_binary = 1`
  - `has_pdf = 1`
- Interpretation:
  - The PDF inclusion path is confirmed in the real M2 transfer row.
  - The remaining issue is limited to the encryption step and should be checked using `abdm_health_information_transfer.error_code`, `abdm_health_information_transfer.error_message`, and the parent request `key_material_json`.
- Upload target:
  - Main VPS staging:
    - `/Users/apple/Documents/docbox_staging/stagingcontext.md` to `/home/stagingdocbox/public_html/stagingcontext.md`

## 2026-05-31 ABDM M2 deep-link SMS opt-in prompt

- Work done:
  - Added an opt-in deep-link notification flow after Rectify Test VS prescription PDF creation.
  - The Rectify JS first records the prescription document mapping as before, then checks whether the visit is eligible for ABDM deep-link SMS.
  - If the patient has a valid mobile number and no ABHA mapping is already linked for the visit/patient, the browser asks the DocBox user whether to send the ABDM deep-link SMS.
  - No ABDM deep-link request is sent when the user cancels the confirmation.
  - Added a Main VPS bridge endpoint to validate the authenticated DocBox session, doctor/patient access, care context, HIP mapping, patient mobile, and previous send state before calling Lightsail.
  - Added a Lightsail ABDM endpoint that accepts only signed bridge requests and calls ABDM `v0.5/patients/sms/notify2`.
  - Prescription mapping now returns `careContextReference` to the browser for follow-up ABDM checks.
  - Rectify Test VS JS cache version bumped from `40.65` to `40.66`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/sajid/saveAbdmPrescriptionDocument.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_deep_link_flow.php`
  - `/Users/apple/Documents/docbox_staging/api/abdm_deep_link_notify.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `sajid/saveAbdmPrescriptionDocument.php`
    - `api/abdm_deep_link_flow.php`
    - `stagingcontext.md`
  - Lightsail ABDM bridge `/var/www/html/abdm-app`:
    - `api/abdm_deep_link_notify.php`
- Validation:
  - `php -l api/abdm_deep_link_flow.php`
  - `php -l api/abdm_deep_link_notify.php`
  - `php -l sajid/saveAbdmPrescriptionDocument.php`
  - `node --check js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-31 ABDM M2 deep-link prompt after print reload

- Issue found:
  - After prescription printing, Rectify Test VS can reload before the deep-link confirmation is displayed.
- Work done:
  - Rectify Test VS now stores a short pending ABDM deep-link check in `sessionStorage` before the prescription print/reload path.
  - On page load, the pending check is processed after a short delay.
  - If the care context is not ready immediately after the print path, the check is retried up to five times.
  - The prompt is still opt-in: ABDM deep-link SMS is sent only after the DocBox user confirms.
  - Rectify Test VS JS cache version bumped from `40.66` to `40.67`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/api/abdm_deep_link_flow.php`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `api/abdm_deep_link_flow.php`
    - `stagingcontext.md`
- Validation:
  - `node --check js/patientInfo_oph_rectify_test_vs.js`
  - `php -l api/abdm_deep_link_flow.php`

## 2026-05-31 ABDM M2 deep-link prompt moved before print confirmation

- Issue found:
  - The deep-link confirmation should happen before the existing "Do you want to print the Prescription ?" confirmation, not after the prescription print/reload path.
- Work done:
  - Removed the post-print `sessionStorage` pending prompt path from Rectify Test VS.
  - `docboxRecordAbdmPrescriptionDocument()` now only records the prescription PDF mapping, preserving the existing print/document behavior.
  - Added a pre-print deep-link check in `askToPrintPrescriptionAfterAbdmFlow()`.
  - New order:
    1. Save visit and care context.
    2. Check whether ABDM deep-link SMS is applicable.
    3. If applicable, ask the DocBox user whether to send it.
    4. Then ask "Do you want to print the Prescription ?"
  - Rectify Test VS JS cache version bumped from `40.67` to `40.68`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `stagingcontext.md`
- Validation:
  - `node --check js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-31 ABDM M2 deep-link prompt wait fix

- Issue found:
  - The deep-link prompt was still not appearing before print in some Rectify Test VS save paths.
- Root cause:
  - One visit-save branch called `syncCareContextAfterVisitSave(...)` without assigning its promise to `abdmPostSaveFlowPromise`, so the print gate could continue before the care context was ready.
  - The pre-print deep-link check did not retry when the backend reported that the care context was still being prepared.
- Work done:
  - Assigned the missing care-context sync promise to `abdmPostSaveFlowPromise`.
  - Added short pre-print retries when `api/abdm_deep_link_flow.php` returns `retryable: true`.
  - The print confirmation now waits for the deep-link check to finish or safely skip.
  - Rectify Test VS JS cache version bumped from `40.68` to `40.69`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `stagingcontext.md`
- Validation:
  - `node --check js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-31 ABDM M2 deep-link prompt moved into care-context save

- Issue found:
  - The deep-link SMS prompt still did not appear before print in the tested Rectify Test VS flow.
- Work done:
  - Stored the exact `careContextReference` returned by `api/internal_care_context_upsert.php`.
  - The pre-print check now uses the saved care-context reference when available.
  - The unlinked-patient branch inside `syncCareContextAfterVisitSave()` now runs the deep-link SMS opt-in check before resolving the ABDM post-save promise.
  - This prevents the print confirmation from continuing until the deep-link decision has completed or safely skipped.
  - Rectify Test VS JS cache version bumped from `40.69` to `40.71`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `stagingcontext.md`
- Validation:
  - `node --check js/patientInfo_oph_rectify_test_vs.js`

## 2026-05-31 ABDM M2 deep-link prompt placed in ABHA link-status check

- User direction:
  - Place the deep-link SMS option where Rectify Test VS checks whether the patient profile is linked with any ABHA ID.
- Work done:
  - Updated `loadPatientAbhaLinkStatus()` to accept an optional deep-link context.
  - Page-load/focus/button status checks remain status-only.
  - During visit save, the `loadPatientAbhaLinkStatus()` call passes the saved care-context reference.
  - If the status check finds that the patient is not linked, it now runs the ABDM deep-link SMS opt-in from that same status check before resolving the save flow.
  - Rectify Test VS JS cache version bumped from `40.71` to `40.72`.
- Files updated:
  - `/Users/apple/Documents/docbox_staging/js/patientInfo_oph_rectify_test_vs.js`
  - `/Users/apple/Documents/docbox_staging/patientInfo_oph_rectify_test_vs.html`
  - `/Users/apple/Documents/docbox_staging/stagingcontext.md`
- Upload targets:
  - Main VPS staging `/home/stagingdocbox/public_html`:
    - `js/patientInfo_oph_rectify_test_vs.js`
    - `patientInfo_oph_rectify_test_vs.html`
    - `stagingcontext.md`
- Validation:
  - `node --check js/patientInfo_oph_rectify_test_vs.js`
