[
    {
        "version": "LM.0.0.2",
        "date": "2026-06-02",
        "notes": [
            "Added Post button in Payroll Processing",
            "Only Admins are permitted to revert posted payroll entries",
            "Department data is now properly connected and functional",
            "SSS Contribution Table updated to include employer's share and additional fields",
            "Payroll Processing filters for Department and Status are now fully functional"
        ]
    },
    {
        "version": "LM.0.0.3",
        "date": "2026-06-05",
        "notes": [
            "Reports module is now live — Payroll Summary, Payslip Report, Employee Masterlist, Loan Ledger, 13th Month Computation, Contributions (SSS / PhilHealth / Pag-Ibig), and BIR Report tabs added",
            "Reports › Payroll Summary lists all posted payroll periods with a Reprint action per period",
            "Reports › Payslip Report lists all employees for a selected posted period with per-employee and batch Print actions",
            "Reports › Contributions combines SSS, PhilHealth, and Pag-Ibig into a single page with inner tabs (same pattern as System Config › Contributions)",
            "Reports › Employee Masterlist is now live with Active/Inactive filter and CSV export",
            "Reports › Loan Ledger is now live with Type and Status filters and CSV export",
            "Reports › 13th Month Computation is now live with year filter and CSV export",
            "Export Summary button removed from Payroll Processing — payroll summary reports are now accessed exclusively from the Reports module",
            "Payroll Processing posted badge moved to the left side of the card header, next to the title",
            "All Payroll Processing action buttons (Process Payroll, Generate Payslips) are now disabled when the period is posted; Unpost button remains available for Admins only",
            "Pay frequency is now available as a PHP page-scope variable and as JS globals (SESSION_PAY_FREQUENCY, SESSION_IS_WEEKLY) for use across views",
            "Fixed: Payslip Report spinner was stuck on initial page load when no period was selected",
            "Fixed: Print All button animation in Payslip Report now properly resets after the file is downloaded",
            "Fixed: payslips_pdf.php now sets the download cookie so button state feedback works correctly for both batch and individual payslip prints",
            "Timecard Manager period filter (date range) is now fully functional — changing the start or end date reloads the table with the correct filtered records",
            "Employee list panel: removed h-100 stretch from LOA, Deductions, OT Approval, DTR, and Employee 201 File views",
            "DTR, OTA, LOA, and Loan/CA: employee list and detail card are now always inline (flex-nowrap) — columns no longer wrap on narrow screens",
            "DTR, OTA, LOA, and Loan/CA: detail card now clips overflow correctly and scrolls horizontally instead of bleeding outside the card",
            "Timesheet Manager, Shift and Schedule, Timecard Manager, and Payroll Processing: tables now scroll horizontally inside the card instead of overflowing it",
            "DataTables page length defaults updated — no-paging tables show all rows, Employee 201 File defaults to 30 rows, all other tables default to 15 rows with matching length-menu options",
            "Fixed: DataTables length menu dropdown no longer shows blank when page length is not a multiple of 5",
            "Fixed: Timecard Manager (and all other DT tables) no longer show phantom whitespace at the far-right end of the horizontal scroll — root cause was Bootstrap .row negative side-margins (margin-inline: -12px) extending the table row beyond its wrapper; fixed by adding .g-0 to all DT-injected rows",
            "Fixed: Employee Masterlist table was wiped on load due to DataTables search teleport targeting the table element itself instead of the filter bar placeholder",
            "Fixed: Loan Ledger, Employee Masterlist, and 13th Month report tables threw DataTables TN/4 error when switching filters — old DataTable instance was orphaned on HTML replace; resolved by explicitly destroying the existing instance before reloading",
            "Fixed: DataTables TN/4 error on empty filter results — single-cell colspan placeholder rows (PHP empty-state rows) are now stripped by sanitizeBody before DataTables initialises, falling back to the built-in empty table message",
            "Renamed rpt.js to rpt_payroll_summary.js for naming consistency across report JS files",
            "Mobile-friendly interface added — sidebar collapses into a hamburger drawer on small screens, tab bar scrolls horizontally, and all tables scroll horizontally on mobile instead of overflowing",
            "Fixed: User Management new user rows were silently dropped on Save — DataTables strips custom data attributes from <tr> elements when rendering; attributes are now restored after row.add()",
            "User Management: duplicate username validation added — real-time check on blur flags usernames already in use with Bootstrap is-invalid styling and a tooltip message; server-side pre-validation blocks save and returns the conflicting usernames",
            "Fixed: Company Profile page showed empty fields for Payroll Officer accounts — fetch endpoint was restricted to Admin only; now accessible to all non-employee roles",
            "Sidebar profile: users without an employee photo now show a role abbreviation badge (ADM, PO, TK, SV) instead of the generic account icon"
        ]
    },
    {
        "version": "LM.0.0.4",
        "date": "2026-06-06",
        "notes": [
            "Mobile UI improvements — login page no longer overlaps on input focus; inputs use font-size 16px to prevent iOS auto-zoom",
            "Mobile UI: page scrolling restored on all pages — overflow-y was previously hidden on wrappers causing content to be clipped",
            "Mobile UI: filter bar layout optimised — search box moves to its own full-width row, Last Refreshed aligns with the Filter label, selects are 100% width",
            "Mobile UI: DataTables whitespace removed — overrode Bootstrap's injected --bs-gutter-y on DT rows at mobile breakpoint",
            "Mobile UI: Employee Applications (LOA, OTA, Deductions) two-panel layout now stacks vertically on mobile with full-width panels",
            "Mobile UI: Employee 201 File two-panel layout now stacks vertically on mobile (added flex-nowrap to row, consistent with other two-panel pages)",
            "Mobile UI: DTR two-panel layout — gap added between stacked employee list and detail card",
            "Mobile UI: Timesheet Manager modal — reduced g-5 gutter to 0.75rem on mobile; ATT Records table wrapped in scroll container",
            "Mobile UI: Shift & Schedule table — added missing .ss-grid-responsive scroll wrapper around #tblSs; table now scrolls horizontally instead of overflowing",
            "Mobile UI: Biometrics modal and Payroll Processing modal — reset hardcoded pixel widths to auto on mobile",
            "Mobile UI: Payroll Summary modal — panels stack vertically on mobile; input-group checkbox spans no longer wrap to a new line; header title truncates with ellipsis",
            "Mobile UI: Pending Deduction and Biometrics modal tables wrapped in table-responsive for horizontal scroll",
            "Mobile UI: Employee 201 File — Pre-employment Docs and Employment Docs tables wrapped in table-responsive",
            "Mobile UI: System Config Contributions current active table wrapped in table-responsive",
            "Mobile UI: Timecard Manager filter bar — PERIOD and Abnormal Only controls reordered below search on mobile; Last Refreshed pinned to Filter label row",
            "CSS: removed 3 redundant rules from app.css — duplicate early .modal-header block (overridden by the correct block 840 lines later), duplicate .main-content padding inside the mobile breakpoint, and a no-op .erp-filter-bar align-items repeat inside the mobile breakpoint",
            "Payroll Processing: filter bar reordered — All Departments and All Status selects now appear above the Search box on both desktop and mobile; mobile layout pins Last Refreshed to the Filter label row, selects stack full-width below it, search appears last",
            "System Config › User Management: Role Permissions matrix added — administrators can now define access levels per role (EMP, SV, TK, PO, ADM) across all system modules directly from the User Management tab",
            "Role Permissions: access levels are granular — each cell is a dropdown with three options: No Access (—), View (read-only), and Edit (full access); defaults match the previous hardcoded role behaviour and take effect after the first Save Matrix",
            "Role Permissions: matrix is backed by a new role_permissions DB table; saving upserts all 125 role × action cells in a single operation",
            "Role Permissions: role column headers show a tooltip icon (ⓘ) — hovering reveals the full role name (Employee, Supervisor, Timekeeper, Payroll Officer, Administrator)",
            "Role Permissions: legend added to the filter bar showing — No Access, View, and Edit badge indicators",
            "Role Permissions: matrix table wrapped in table-responsive for horizontal scroll on mobile devices",
            "Sidebar navigation is now driven by the Role Permissions matrix — menu items (Org Set-up, Timekeeping, Payroll Processing, Reports, System Config) show or hide based on the saved DB permissions, with hardcoded role defaults as fallback when the table is empty",
            "Org Set-up tabs (Company Profile, Employee 201 File, Department, Site, Resignation) are now individually gated by the Role Permissions matrix — users see only the tabs their role has access to",
            "View-only mode: when a role has View (level 1) but not Edit (level 2) access to a page, all write controls (buttons, inputs, selects, textareas) are automatically disabled on load and for any AJAX-injected content via MutationObserver",
            "View-only mode: a yellow banner is displayed at the top of the page reading 'View-only — you do not have permission to make changes on this page'",
            "Fixed: Timekeeping sidebar group label was hidden for roles without Timekeeping access, leaving Employee Apps with no group heading — label is now always rendered since Employee Apps is always visible beneath it"
        ]
    },
    {
        "version": "LM.0.0.5",
        "date": "2026-06-07",
        "notes": [
            "OT, LOA, and Loan/CA: period filter (date range) added inline in the card header beside the employee name and ID — defaults to the current pay period selected in Payroll Schedule, reloads the employee's records when changed",
            "Pending OT, Pending LOA, and Pending Loan/CA modals: period filter added in the modal header (far right, beside the close button) — defaults to the current pay period on open, re-fetches the pending list when changed",
            "Pending OT/LOA/Loan/CA fetch endpoints now accept date_from and date_to parameters to scope results to the selected period",
            "Pending OT, LOA, Loan/CA, and Biometrics modal bodies: removed default Bootstrap padding (p-0) so tables render flush to the modal edges",
            "Fixed: System Config (Payroll Schedule, Contributions, Rules) was not visible in the sidebar for roles with Setup & Configuration access — sidebar now shows System Config for any role that has access to at least one SC module, not just roles with User Management access",
            "Fixed: System Config sidebar link now lands on the first SC page the role actually has access to (User Management → Payroll Schedule → Contributions → Rules) instead of always linking to User Management",
            "Fixed: System Config tabs (User Management, Payroll Schedule, Contributions, Rules) are now individually gated — roles only see the tabs they have permission to access",
            "Fixed: Role Permissions edit access was not being applied correctly — the role_permissions table was missing a UNIQUE KEY on (rp_module, rp_action, rp_role), causing every Save Matrix to INSERT a new row instead of updating the existing one; duplicate rows resulted in non-deterministic permission lookups where the old value could silently override the new one",
            "Fixed: permissions SELECT query now uses MAX(rp_allowed) with GROUP BY to always resolve to the highest granted access level per cell, eliminating the race condition caused by duplicate rows",
            "Added migration: migrations/2026_06_07_role_permissions_unique_key.sql — deduplicates existing rows and adds the UNIQUE KEY so future saves correctly use ON DUPLICATE KEY UPDATE",
            "DTR table inputs now fill their entire cell — td padding removed on non-date columns, inputs are borderless and transparent at rest, and display a focused inset ring on active edit; eliminates the small fixed-width dead zones that made cells hard to click",
            "System Config › System Logs tab added (Admin only) — Admins can now view payroll-errors.log and the server PHP error log directly in the browser; source toggle switches between Payroll Errors and PHP Errors; shows timestamp, type, severity badge, context (file:line for PHP errors, context tag for payroll), and message columns; severity filter options change per source (HTTP codes for payroll, Fatal / Warning / Notice / Deprecated for PHP); line-count selector (50–1000) and Refresh button; PHP log path resolved dynamically via ini_get; log files are never served raw",
            "Code audit — button and table consistency: btn-recalc in payroll summary modal migrated from raw $.ajax() click handler to wireAjaxFormButton; hol-delete migrated from raw $.ajax() click handler to wireAjaxFormButton; contrib-parse-btn and contrib-save-btn documented as intentional exceptions (no <form> element to serialize); btn-calc-payroll pre-check interceptor documented as intentional two-handler pattern; Pre-employment Docs and Employment Docs tables in Employee 201 File patched with table-bordered and data-dt-ignore; Contribution Deduction reference table in Payroll Schedule patched with table-bordered and data-dt-ignore"
        ]
    },
    {
        "version": "LM.0.0.6",
        "date": "2026-06-07",
        "notes": [
            "Fixed: active pay period now persists across logout — the selected cutoff start and end dates are saved to payroll_sys_config (last_cutoff_start / last_cutoff_end) whenever the Payroll Schedule settings are saved",
            "Fixed: on fresh login or session expiry, the active pay period is now restored from the last DB-saved period instead of defaulting to the current calendar week; the calendar-week fallback is now only used on first-time setup when no saved period exists",
            "Fixed: Payroll Processing RECALC confirmation dialog now shows the exact pay period dates (start → end) so users can verify they are recalculating the correct period before confirming",
            "Safety check added: Process Payroll and RECALC both now detect when the selected pay period has not ended yet (cutoff end date is in the future) and show a prominent warning before allowing the operation to proceed — prevents accidental payroll runs on incomplete or wrong periods",
            "Loan/CA: Delete is now available for all statuses (Active, Pending, Paused, Closed, Rejected, Cancelled) — PO and Admin roles can remove erroneous deduction records at any stage; for Closed deductions the server automatically reverses all ledger entries and adjusts the affected payslip CA/Loan totals and net pay; deletion is blocked if the payroll period containing the deduction is already posted",
            "Payroll Summary modal: paused deduction indicator added — when an employee has a CA or Loan in Paused status with a remaining balance, a blue info banner appears inside the Deduction card showing each paused item's type, remaining balance, and per-period amount; makes it immediately visible that the deduction was skipped for the current period",
            "Payroll Summary modal: RECALC button is now disabled when the payroll period is already posted; a lock notice ('Period is already posted — updating is not allowed.') is displayed in the modal footer to make the read-only state explicit"
        ]
    },
    {
        "version": "LM.0.0.7",
        "date": "2026-06-11",
        "notes": [
            "Quick period change shortcut added — Payroll Officers and Admins now see the active pay period badge in the topbar as a clickable button (pencil icon); clicking it opens an inline panel with Start and End date pickers and Save / Cancel actions, so the pay period can be changed without navigating to System Config › Payroll Schedule",
            "Quick period panel: Save button follows the standard btn-icon-mode structure and behavior — spinner while saving, green checkmark on success, resets to idle after 1.5 s; panel stays open after a successful save so the updated badge can be confirmed before closing",
            "Quick period panel: topbar badge text updates in-place immediately after a successful save without a page reload; the panel pre-fills with the newly saved start date on next open",
            "Quick period panel: topbar badge is hidden on mobile (screen width ≤ 767 px) — the full Payroll Schedule settings remain available in System Config on all screen sizes",
            "Payroll Processing: Post button is now gated — it only appears after payroll has been generated for the period; periods with no payroll rows show neither Post nor Unpost, preventing accidental posts on empty periods",
            "System Config › User Management: developer accounts (pu_dev_flag = 1) are now hidden from the user table — dev entries no longer appear in the list and cannot be edited or deleted through the UI",
            "Security: ded_counter.php, loa_counter.php, and ot_counter.php now call bootApiSession() — unauthenticated requests are rejected with HTTP 401 instead of silently serving data",
            "ot_counter.php: wrapped in try/catch so executeQuery failures return a safe fallback instead of a fatal error",
            "Fixed: loa_save.php leave-balance deduction was returning a false 409 on every approval — SELECT ROW_COUNT() after a prepared statement always returns -1; replaced with the affected-rows return value from executeQuery()",
            "Fixed: payroll_process.php deduction ledger INSERT and employee_deductions UPDATE used throwOnError=false — silent write failures inside a transaction now throw and trigger a proper rollback",
            "Fixed: timesheet_save.php delete path issued a redundant inner mysqli_begin_transaction(), which implicitly committed the outer transaction before the delete executed; redundant call removed",
            "Security: ded_approval.php and loa_approval.php no longer expose raw exception messages to the client in error responses",
            "Fixed: deduction_save.php UPDATE bind-type string had 'i' (integer) for employee_id which is a string column — corrected to 's'",
            "Security: ded_status_update.php now requires employee_id to be present — previously a missing employee_id allowed a ded_id-only lookup, enabling cross-employee status changes",
            "Fixed: pay_period.js bi-monthly cutoff end-date calculation used day <= cutoff_day_1, producing a zero-length period when the user picked exactly cutoff_day_1; corrected to day < cutoff_day_1",
            "Fixed: sc_users.js scroll-to-row animation computed NaN due to wrong operator precedence ($row.offset()?.top - 100 ?? 0); corrected to ($row.offset()?.top ?? 0) - 100",
            "Deduction status buttons (Pause/Resume/Close/Reject/Cancel) migrated from raw $.ajax() handler to wireAjaxFormButton() — gains standard spinner, success feedback, and error handling",
            "sc_logs.js: removed local esc() duplicating global escapeHtml(); all 5 call sites updated; added complete: callback so showCompleted() always fires after loadLogs() AJAX to prevent stuck processing state; renamed shadow variable const p → const parsed inside renderRows forEach",
            "Removed duplicate formatEmployeeDisplayName() from ota.js, loa.js, and deduction.js; consolidated into app.js as a single global",
            "sc_users.js renderUmDeleteBtn() replaced with a call to renderBtn() — eliminates inline button HTML duplication",
            "payroll_process.php: removed local diffMinutes(), normalizeDateTime(), addMinutes(), and fetchTimecardPunchWindow() — all were identical to attDiffMinutesBetweenTimestamps(), attNormalizeDateTimeForWorkDate(), attAddMinutesToTimestamp(), and attFetchTimecardPunchWindow() in functions.php; all call sites updated to use the global helpers",
            "functions.php: added normalizeCheckboxToInt() and mapLoaTypeToBalanceCol() as shared helpers; removed duplicate definitions from loa_save.php, ota_save.php, and loa_approval.php",
            "Shift & Schedule: schedule plotting is now locked when the active pay period is posted — all day-cell dropdowns are disabled, the Save Week, Reset View, and Plot Range buttons are disabled, and a lock banner replaces the info notice; the lock lifts automatically when the period is unposted",
            "Shift & Schedule: server-side guard added — both the Save Week (bulk grid) and single-assignment save paths reject writes with HTTP 409 if the pay period is already posted, preventing bypasses via direct POST",
            "Shift & Schedule: Department filter added to the filter bar alongside the existing search — selecting a department shows only employees in that designation; the daily headcount row updates to reflect visible employees only; selecting All Departments restores all rows",
            "Payroll Processing: Post Payroll now runs four pre-checks before allowing a post — blocks if no schedules have been plotted in Shift & Schedule, no timecards calculated, no DTR records processed, or no payslips generated; all failing checks are shown together in a dismissing warning notice above the filter bar",
            "Timecard Manager: Timesheet filter added to the filter bar — selecting a timesheet limits the table and CSV export to records assigned to that timesheet; defaults to All Timesheets",
            "System Config › Leave Balances: new page for configuring annual leave allocations per leave type (SL, VL, SIL, PL, ML) — each type has an Annual Days amount, a Carry Over toggle (when on: remaining balance carries forward and annual days are added on top; when off: balance resets to the annual amount), and an Enable Refresh toggle; an Auto-Refresh Date (month + day) is configurable and stored in system settings; the refresh fires automatically on the first page load on or after the configured date each year using an atomic DB claim so it runs exactly once even under concurrent requests; a Run Refresh Now button is also available for manual runs; leave_balance_config table is created and seeded with defaults on first access",
            "Unsaved-changes guard extended system-wide — the browser confirm prompt that previously protected only the DTR form now covers Employee Information, Payroll & HR Records, Pre-employment Documents, Employment Documents, Company Profile, Payroll Rules, Payroll Period Settings, Government Contributions, Holiday Configuration, and Shift & Schedule; alert fires on tab switch, employee row click, year-filter change (holidays), and page close/navigation; each form clears its dirty flag automatically after a successful save",
            "System Config › Leave Balances: annual leave amounts now split into Probationary and Regular tiers — each leave type has separate day allocations for probationary and regular employees; the refresh applies the correct amount per employment status; leave_balance_config table migrated with annual_amount_prob and annual_amount_reg columns; existing installs are upgraded and seeded automatically on first access",
            "System Config › Leave Balances: Leave Balance Configuration added to the Role & Permissions matrix under Setup & Configuration so access can be granted per role",
            "System Config › Leave Balances: page title now correctly resolves to System Configuration > Leave Balances via renderTitle() & setPageTitle()",
            "Fixed: Employee 201 File — Add New Employee button was accidentally removed from the employee list card header; restored and gated to Admin and Payroll Officer roles only",
            "Employee 201 File › Payroll & HR: tab overhaul — Allowances card replaced the single lump-sum input with a Philippine-standard breakdown (Transportation, Meal / Food, Communication / Internet, Housing, COLA, Clothing / Uniform, Medical), each wired into payroll processing as other earnings, stored in individual columns, defaulting to 0.00, and the card is now constrained to col-lg-6 to match the other cards; a Salary History button was added that opens a modal showing Period, Net Pay, Posting Date, and Bank Reference (placeholder); Leave Balance labels (SL, VL, SIL, PL, ML) now show a tooltip icon with the full leave type name on hover; and the Payroll Details coming-soon tiles were restyled to match the Salary History button shape and size",
            "Biometric Logs modal: employee badge now shows First Name and Last Name only (middle name and suffix removed)",
            "Salary History modal: employee badge follows the same Name [ID] format as Biometric Logs",
            "System Config › User Management: Role Permissions column headers (EMP, SV, TK, PO, ADM) now show a tooltip icon with the full role name on hover",
            "Code cleanup: normalized table markup system-wide — removed table-light / bg-light, text-end, text-center, text-start, text-nowrap, and small classes plus all inline styles from table elements (table, thead, tbody, tr, th, td, tfoot)",
            "Payroll Processing: Process Payroll button now runs the same pre-checks as Post Payroll before executing — warns if no schedules have been plotted in Shift & Schedule, no timecards have been calculated, or no DTR records are found for the period; user can still proceed after confirming each warning",
            "Code cleanup: replaced all custom row-top-margin-x and row-bottom-margin-x classes with Bootstrap utility classes (mt-x / mb-x) across all views, modals, and JS files; custom CSS definitions removed from app.css",
            "System Config: User Management tab is now restricted to Admin role only — Payroll Officer accounts no longer see User Management in the System Config tab bar",
            "Security: server-side page-access enforcement added — restricted pages (Organization Setup, Timekeeping, Payroll Processing, Reports, System Config) can no longer be opened by typing the URL directly; the page router now checks the same Role Permissions matrix used to render the sidebar and redirects unauthorized roles to the Dashboard (previously the sidebar only hid the links while the page still rendered)",
            "Security: all API endpoints now enforce the Role Permissions matrix server-side — fetch/save endpoints across Organization Setup, Timekeeping, Employee Applications, Payroll, Setup & Configuration, and Users & Reports were migrated from static role checks to a new requirePermission() helper (reads require View, saves / approvals / deletes require Edit), so access configured in System Config is honored at the endpoint instead of being cosmetic; editing the permission matrix itself remains hard-locked to Admin to prevent privilege escalation",
            "Security: the holiday-delete path (holidays_fetch.php) was missing both a permission check and CSRF validation — any logged-in user could delete holidays via a crafted request; deletion now requires CSRF and Edit-level Holidays permission",
            "Fixed: removed a dead permission mapping (sc_logs referenced a non-existent setup_config.system_logs action); System Logs remains Admin-only",
            "Dashboard: new landing page with at-a-glance KPI cards (pending Overtime/WDO, Leave, and Loan/CA approvals, plus active headcount), a current pay-period summary (status, payslip count, gross/net totals), and a \"Needs Your Attention\" list that links into the relevant modules; data is role-aware — Employees see their own pending items and payslip totals while approvers and Admins see organization-wide figures. The page shows the current date and is access-controlled via a new Dashboard row in the Role Permissions matrix",
            "Role Permissions matrix consolidated for clarity: Payroll Schedule is now its own action separate from Rules; Company Profile collapsed from two rows (View Company Profile / Edit Company Profile) into a single action that uses the per-cell View/Edit dropdown; Rules and Holidays merged into one action; View / Manage Users and User Access Control merged into one action; and the old \"Export Summary / Generate Payslips\" label was shortened to \"Generate Payslips\" (Export Summary now lives under Reports). Existing permissions were migrated automatically, obsolete rows cleaned up, and the matrix now always loads its current definition instead of a cached copy",
            "Timekeeping permissions are now enforced per tab — Biometric Upload, Timesheet Manager, Shift & Schedule, Timecard Manager, and Daily Time Record each honor their own matrix action for sidebar visibility, tab buttons, and page access (previously all five rode on the single Timesheet Manager permission); roles without Dashboard access now land on their first permitted page instead of a blocked Dashboard",
            "System Config › Rules: Holiday Management now has a holiday-type filter (Regular / Special Non-Working) alongside the existing year filter",
            "UI: the signed-in user now appears as a top-right account menu — showing name and Employee ID / role — with Logout moved into it; the sidebar footer now displays the application version. The pay-period badge is hidden on Biometric Upload and Timesheet Manager, and its quick-edit shortcut (Payroll Officer / Admin only) no longer shows a hover tooltip"
        ]
    },
    {
        "version": "LM.0.0.8",
        "date": "2026-06-13",
        "notes": [
            "Security: login brute-force protection added — after 3 failed sign-ins an account is temporarily locked for 5 minutes, and after 6 failed sign-ins it is locked until an administrator unlocks it. System Config › User Management now shows a Locked / Timed-out badge and an Unlock button per account, and every sign-in attempt is recorded for auditing",
            "Login: the username is now kept after a failed sign-in so it no longer has to be retyped, and the page shows a clear message when an account is temporarily timed out or has been locked",
            "Security hardening: removed the one-time contribution seed script from the server, blocked direct web access to the uploads and migrations folders, and stopped internal error details from being shown in the browser when Timecard Manager or Departments fail to load",
            "Account menu: the top-right dropdown now shows your avatar, and avatar badges are color-coded by role (Admin, Payroll Officer, Timekeeper, Supervisor, Employee)",
            "Tables: column headers now stay pinned to the top while scrolling long tables — applied across the data tables, the Role Permissions matrix, Government Contributions, and System Logs",
            "Mobile: the Overtime/WDO, Leave, and Loan/CA tables now scroll horizontally within their card instead of overflowing on small screens",
            "Maintenance: database schema setup was moved out of runtime code into versioned migration files, and a case where a database error while saving the weekly schedule was silently ignored has been fixed",
            "Pay period: changing the active pay period from the topbar now refreshes the current page so all period-dependent content updates immediately — the Shift & Schedule, Daily Time Record, and Payroll Processing tables, plus the posted/locked banner — instead of continuing to show the previous period",
            "Timecard Manager: the topbar pay-period selector is now hidden on this page, which has its own Period date-range filter — removing the confusion of two competing period controls"
        ]
    }
]
