Weekly report
Frappe and ERPNext changes, 27 Jul to 2 Aug 2026
282 changes merged: 1 breaking, 60 new features, 21 speed-ups, 153 fixes, 47 refactors.
Breaking changes
Read these before you update. They can change how your site or app works.
- feat Builder-like editing experience Print format builder now matches Website Builder's editing feel with unified selection ring, proper layering, and draggable sections.
- feat Print format builder editing UX polish Print format builder now hides per-item toolbars during bulk selection, uses consistent selection ring across all elements, and adds bulk rename/delete.
- feat Layers panel (drag-drop + hover) and builder UX cleanup Print format builder now has a draggable Layers panel for reordering sections/fields, hover field outline, and drop-field overlay inset to page edge.
- feat Add in-app cloud settings embed Desk now includes an in-app Frappe Cloud Settings dialog for billing, marketplace apps, domains, and advanced settings without leaving the app.
- feat Add reload option to user dropdown menus Hard reload option re-added to both sidebar and Desk avatar dropdown menus.
See all 43 changes
- feat Consolidate view switching to single dropdown List, kanban, and report views now use a single dropdown menu to select layout, available on mobile too (previously had separate dropdowns).
- feat Add support for async options in dropdown menu Dropdown menu now supports asynchronously-loaded options.
- feat Better read-only and impersonation banners Improved visual design of read-only and impersonation banners on forms.
- perf Non-submittable docstatus guard in ORM ORM-level docstatus guard reverted from #41280 because v16 still supports internal submissions of non-submittables; guard belongs in Desk.
- perf Redesigned the general tab for DocType Setting DocType Setting dialog's General tab now displays settings grouped by their source groups for better organization.
- perf Speed up orphan doctype check Checking orphans by importing every controller is slow and fragile. Now diffs DB names against create_entity_file_map instead of executing app code, avoiding unrelated import errors and controller cache issues.
- fix Require read access on the prepared report before queuing its CSV export The `enqueue_json_to_csv_conversion` endpoint now checks read permission on the Prepared Report before queuing conversion.
- fix Resolve inline email image paths inside the assets and site files directories Inline image paths in outgoing email now resolve only inside the assets directory and site public/private files directories.
- fix Check permissions before returning a contact number for SMS Contact number lookup now requires read access on both the contact and reference document.
- fix Limit cross-user event lookups to System Manager The `user` parameter of `get_events` now requires System Manager role; callers without it only see their own events.
- fix Limit Prepared Report access to the user who generated it Prepared Report results now limit access to the owner based on user permissions; System Managers and explicitly shared documents unaffected.
- fix Mobile list scrolling, large-list performance, and virtual skeletons Fixed double scroll on mobile, pinned pagination to bottom, removed horizontal scroll on card layout, and improved virtual skeleton rendering.
- fix Keep the selection ring above field content Print format builder selection ring now drawn as inset overlay instead of outline, and permission check falls back to boot.user when doctype meta unavailable.
- fix Clean up tab buttons and calendar UI Refreshed tab button and calendar UI styling for consistency.
- fix Check calendar date fields against the doctype schema `get_events` now rejects field maps naming start/end fields that don't exist, giving clear error instead of database error.
- fix Publish last_query so assertQueryCount works on SQLite SQLite driver now publishes `last_query` so assertQueryCount works on SQLite like it does on MariaDB and Postgres.
- fix Don't assume frappe.app exists when checking session expiry Session expiry checks no longer crash on requests fired before app boot.
- fix Msgprint loses its message when a save response follows Client-side msgprint no longer loses its body when a request completes immediately afterwards.
- fix Run before_print in builder renderer; guest-only 403 login Print builder renderer now runs before_print hooks and sets link titles for beta PDF downloads.
- fix Isolate msgprint cases on a fresh page Msgprint tests now run on isolated pages to prevent CI flakes from dialog state inheritance.
- fix Handle large int serialization Large integers now serialize correctly in JSON responses (reverts orjson regression).
- fix None link handled and fixed except handler Desktop icon with None link no longer crashes with unhandled exception.
- fix Role permissions manager breaks browser back navigation Role Permissions Manager now preserves browser back history correctly when called from list view menu.
- fix Sanitize UTF-16 surrogate codepoints before FTS Full-text search now handles UTF-16 surrogate codepoints without corruption.
- fix Prevent Jump to Field dialog from stacking Jump to Field dialog no longer stacks when opened multiple times.
- fix Restructure restore without a copy and remove unused verbose Database restore is now simpler and more efficient.
- fix Validate HTTP method for document calls Backport enforcing whitelisted methods' declared methods= on document-method routes (/api/v2/document/*/method/* and POST /api/resource/*/method routes), which was previously unenforced despite being enforced on /api/method/* and run_doc_method.
- fix Drop client-side grant-all rights for Administrator Reverts the blanket grant of all rights to Administrator at all permlevels on every doctype. Administrator was getting submit/cancel/amend buttons on non-submittable doctypes like Bin, and malformed update_child API requests.
- fix Get_locale_value() crashes when no language is set get_locale_value() assigned value only when lang was set but always returned it, raising UnboundLocalError when no language was configured (e.g., bench console on sites that never set a language). frappe.sendmail() failed rendering emails because date-format lookup crashed.
- fix Stop build_index looping forever on an unindexable batch SQLiteSearch.build_index advanced its pagination cursor only inside `if documents:`, so batches where all documents were rejected (no text-field content) never advanced the cursor and looped forever. Forward-port of #41249 from version-16-hotfix.
- fix Don't show private custom workspaces on the dock Private custom workspaces were showing on the app dock even though the new information architecture requires workspaces to be scoped under an app.
- fix Grid row selection on touch Touch-based row selection wasn't working on grids due to event handling differences between touch and click.
- fix Add order to desktop menu item Desktop menu items can now have a specified order so logout can be positioned last.
- fix Constrain read-only Text Editor field height with scroll Read-only Text Editor fields now scroll instead of expanding infinitely.
- refactor Release v15 chore: release v15
- refactor Update POT file chore: update POT file
- refactor Update POT file chore: update POT file
- refactor Release v16 chore: release v16
- feat Add four Sales Invoice print formats Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Sales Invoice.
- feat Add four Sales Order print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Sales Order.
- feat Add four Delivery Note print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Delivery Note.
- feat Add four Purchase Invoice print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Purchase Invoice.
- feat Add four POS Invoice print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to POS Invoice.
See all 53 changes
- feat Add four Quotation print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Quotation.
- feat Add four Purchase Order print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Purchase Order.
- feat Taxable-base resolver hook for custom charge types Allows custom taxable value calculation for taxes (e.g., tax on MRP in India, differently-determined taxes in Brazil).
- feat Add four Request for Quotation print formats built with the print format builder Four new print formats (Bordered, Classic, Modern, Modern with Images) added to Request for Quotation.
- feat Book Expenses Added To Stock GL entries Backport to v16 of the develop-branch GL composer for Expenses Added To Stock, enabling proper accounting of costs like freight or insurance bundled into finished goods.
- perf Isolate accounts settings mutation in overdue threshold test Overdue threshold test now restores Accounts Settings mutations in finally block, preventing test leakage.
- perf Narrow legacy serial ledger lookup by item When calculating rates for legacy serial numbers, the Stock Ledger Entry search is now limited to the current item instead of checking all items. Improves performance without changing valuation results.
- perf Rename misleading filter labels in AR/AP reports "Posting Date" → "Report Date" (it acts as an *as-on* date); "Calculate Ageing With" → "Age as on"; option "Today Date" → "Today". Fieldname `calculate_ageing_with` renamed to `age_as_on`.
- perf Configurable date in reverse ERR journals Users can now control when the reverse journal should be posted (e.g., ERR done last year on a closed period → reversal on 1st April).
- perf Recalculate whole bin in Production Plan reservation patch Follow-up to #57399; now calls Bin.recalculate_values() to recompute all quantities instead of just reserved_qty_for_production_plan, so drifted bins stay correct.
- fix Don't require cancel and delete perms to remove items via Update Items Removing rows in Update Items no longer requires Cancel and Delete permissions on the order; only Write is needed.
- fix Don't require cancel and delete perms to remove items via Update Items fix: don't require cancel and delete perms to remove items via Update Items
- fix Let Purchase Receipt cancel defer to Frappe's linked-document check Purchase Receipt cancellation now defers to Frappe's framework check for submitted linked documents instead of duplicating the guard.
- fix Skip e-invoicing for opening invoices fix(italy): skip e-invoicing for opening invoices
- fix Stop swallowing exceptions silently in six places Converted silent `except Exception: pass` handlers to proper logging or intentional raises across Pricing Rule conditions, Payment Request validation, Supplier Quotation, and others.
- fix Sum semi-FG qty across split job cards Fixes second job card overwriting the first's quantity instead of accumulating; work order now correctly totals produced_qty across all split cards.
- fix Scope BOM Creator tree children to the parent row When the same item is reused as a sub-assembly in multiple places, each occurrence now shows only its own raw materials instead of the union of all occurrences.
- fix Stop storing "{supplier_name}" / "{customer_name}" as the document title Purchase Order, Sales Order, and Subcontracting Order now render title templates correctly instead of storing the literal placeholder.
- fix Update operating cost when propagating workstation hour rate to routing Propagates workstation hour rate changes to operating_cost in linked Routing BOM Operation rows.
- fix Guard against None row in get_stock_balance_for Batch-tracked items called via API with no row parameter no longer crash on `row.use_serial_batch_fields`.
- fix Respect child warehouse account override in Stock and Account Value Comparison Child warehouses that override their parent's account are now correctly scoped to their own account, preventing in-transit transfers from cancelling under the same account.
- fix Fall back to UOM Conversion Factor in Production Plan Production Plan now silently falls back to the UOM Conversion Factor doctype instead of throwing when an item lacks a purchase-UOM child row.
- fix Skip stock expense GL entries for non-stock items Service items in Purchase Invoices no longer generate empty GL entries, fixing validation failures on stock expense accounts.
- fix Clear deferred revenue/expense fields on uncheck Service Start and End Date fields now clear when Deferred Revenue is unchecked on a Sales Invoice.
- fix Replace incorrect usage of `frappe.in_test` with `frappe.flags.in_test` Corrects test flag references in Purchase Price Change Validation.
- fix Add permission check for `get_item_details` Adds user permission validation to prevent unauthorized item detail access via the API.
- fix Correct description on deferred revenue/expense Field descriptions now correctly explain deferred revenue vs. expense behavior.
- fix Scope manufacturing warehouse filters to company Default WIP, Finished Goods and Scrap Warehouse fields now list only warehouses from the current company.
- fix Recover failed POS closings POS Closing Entry can now be cancelled and resubmitted when its status is Failed.
- fix Stop the Subcontracting Receipt title from going stale Subcontracting Receipt title now updates when the supplier changes instead of staying stale.
- fix Stop storing raw title template on subcontracting orders Subcontracting Order and Inward Order titles now render templates correctly instead of storing literal `{supplier_name}` / `{customer_name}`.
- fix Update cost of BOMs created via BOM Creator BOMs created via BOM Creator can now have their costs updated via the Update Cost button or BOM Update Tool.
- fix Fall back to UOM Conversion Factor in Production Plan Backport of UOM Conversion Factor fallback for v15-hotfix.
- fix Keep manufactured item rate at zero when inputs are free When a finished item was manufactured from raw materials consumed at zero valuation, _set_incoming_item_rate treated zero cost as missing and fell back to the item's own valuation rate, inflating the finished good's value on every production run.
- fix Value batched packed-item returns from the original bundle Return Delivery Notes / Sales Invoices built via the use_serial_batch_fields path had incorrect bundle valuations because the return bundle's voucher_detail_no stayed the Packed Item instead of remapping to the parent DN/SI Item. Valuation lookup now resolves via the parent_detail_docname when the direct lookup fails.
- fix Release raw-material reservation when closing a subcontracting order Bin.update_reserved_qty_for_sub_contracting() skipped closed Purchase Orders but not closed Subcontracting Orders, so closing a partially-received SCO kept the raw-material reservation for the unreceived qty. Applied the same status != "Closed" filter to both paths.
- fix Carry forward communications from opportunity Quotations created from opportunities now inherit the opportunity's communications (emails, comments).
- fix Pool batch slot values on every run, not only when negative Batch slots' value differences were only spread across age slots when consumption had already driven one negative, leaving skewed splits (e.g., 10 units at 0 and 10 at 10 showing 0 and 100 instead of 50 each). Now pools slot values on every run.
- fix Align Opportunity status checks with Quotation statuses Opportunity status checks looked for the obsolete Quotation `Closed` status instead of `Cancelled` and `Expired`, and didn't recognize `Partially Ordered` quotations as ordered. Now treats the right statuses and marks Opportunities Converted as soon as a Sales Order is created against part of a Quotation.
- fix Flaky test in exchange rate revaluation Exchange rate revaluation test was non-deterministic due to time-based ordering; stabilized by using fixed timestamps.
- fix Incorrect creation time at cancellation Creation time was being incorrectly set when cancelling an entry with the same posting datetime, causing data issues.
- refactor Reuse shared date range validation across reports refactor: reuse shared date range validation across reports
- refactor Reuse shared date range validation across reports refactor: reuse shared date range validation across reports
- refactor Port point_of_sale get_items to the query builder POS get_items query now uses the Frappe query builder for better performance and consistency.
- refactor Repost accounting ledger Repost Accounting Ledger now provides status feedback, tracks per-voucher outcomes, and supports resuming partial failures.
- refactor Move warehouse defaults from Stock Settings to Company Default Warehouse and Sample Retention Warehouse moved from global Stock Settings to Company in a new Warehouse Defaults section; company check consolidated in Company.validate_warehouses.
- refactor Release v15 chore: release v15
- refactor Release v16 chore: release v16
- fix Filter employees by company in Employee Leave Balance report The Employee filter in the report now displays only employees belonging to the selected Company, preventing silent no-results when users pick employees from a different company.
- fix Resolve AttributeError in update_job_applicant_status exception handling Fixed variable shadowing bug where the Document instance was overriding the string parameter job_applicant, and replaced job_applicant.log_error() with frappe.log_error() in the except block to handle empty/invalid strings.
- fix Format earned leave schedule dates Earned Leave Schedule dates in Leave Allocation now respect the System Settings date format instead of showing raw ISO dates.
- refactor Release v16 chore: release v16
- refactor Release v15 chore: release v15
- feat Capture new feature adoption daily Daily feature adoption tracking captured when telemetry enabled.
- feat Lucide icon picker for views View modal now uses frappe-ui's searchable lucide icon picker with ~1000 icons instead of emoji-only picker.
- feat Migrate to frappe-ui sidebar CRM now uses frappe-ui sidebar component and updated to frappe-ui v1.0.0-beta.24.
- feat Migrate Autocomplete to Combobox 16 pickers migrated from old Autocomplete API to new Combobox with updated slot and event signatures.
- perf Migrate Editor to CommentBox and EmailEditor component Editor components in contact panels now use the unified CommentBox and EmailEditor for consistency.
See all 24 changes
- perf Remove sales hierarchy permissions banner from sidebar Deleted SalesHierarchyBanner.vue and dropped the show_sales_hierarchy_banner boot flag (which ran a CRM Lead count on every page load). Sales Hierarchy settings already links to docs.
- fix Support ERPNext v15's price list in deal view fix: support ERPNext v15's price list in deal view
- fix Render saved-view lucide icons in the view dropdown fix(views): render saved-view lucide icons in the view dropdown
- fix Like button fix: like button
- fix App sidebar background in dark mode fix: app sidebar background in dark mode
- fix Misc frappe-ui fixes Multiple UI fixes including full-name column headers, ID icon in filter dropdown, full-width Field Combobox, and Combobox in filters.
- fix Make button direct child so trigger values are capturable fix: make button direct child so trigger values are capturable
- fix Misc frappe-ui fixes Fixed massive Combobox width due to field description.
- fix Play call recordings reliably Call recordings now play with correct duration and seek support by streaming provider responses and forwarding HTTP Range headers.
- fix Quick filters not working Fixes TypeError when applying quick filters due to null reference in ViewControls.
- fix Require a name to create/save a view Save button is now disabled until the view label is non-empty (trimmed).
- fix Search and selector/dropdown widths Search and dropdown components now render at correct widths.
- fix Improve `PrimaryDropdown` ux and new `IndicatorIcon` PrimaryDropdown migrated to ItemListRow with inline actions and a new Indicator icon.
- fix Validate contact email/mobile and rework the primary dropdown Draft states caused failures in contact email/mobile autosave. Consolidated duplicated contact panel logic from Contact.vue and MobileContact.vue into a shared util and reworked the primary dropdown.
- fix Keep the Unpublished badge visible on row hover The Unpublished badge's light-gray variant blended into the row's hover background. Switched to outline variant so it keeps a visible border.
- refactor Bump frappe-ui to v1.0.0-beta.29 Resolves editor mention visibility issue.
- refactor Rename 'annual_revenue' to 'deal_value' in Org and contact page Organization and contact pages now display Deal value instead of annual revenue.
- refactor Move FileUploader & EmailTemplate button to start of Editor Editor layout improved by moving FileUploader and EmailTemplate button to the start.
- refactor Minor Release v1.80.0 chore: Minor Release v1.80.0
- breaking Stop razorpay from breaking Razorpay <2 imports pkg_resources at module level; setuptools 82 dropped it. LMS imported razorpay at module level in a hook that runs on every session, so any bench with setuptools ≥82 returned HTTP 500 for all requests including login and Desk. Bumped razorpay past the broken range and moved the import inside the get_client() call.
- feat Give every list page one declarative layout List pages now use unified declarative layout components (ListPage, ListPageHeader, etc.) instead of hand-rebuilt duplicates, fixing mobile view.
- feat Make student view a real route instead of editor mode Student view moved from CourseEditor second surface to a real route at /courses/:course/learn/:ch-:lesson, eliminating embedded preview surface.
- fix Accept any casing of an Indian state at checkout Indian state field now uses a Combobox over the canonical list instead of free text validation, and includes all union territories that were missing.
- fix Batch fix_progress_percentage so migrate survives large sites Migration patch that walked every LMS Enrollment and issued one set_value per row now batches counts into two queries, preventing TooManyWritesError on large sites.
See all 14 changes
- fix Open link in new tab to avoid context Links in lesson content now open in new tab via DOM sanitization on render.
- fix Lesson editor formatting, profile permissions, and Razorpay order creation Bold formatting now works in all editor blocks, headings are single-line, profile IDOR closed, and Razorpay order ID extraction fixed.
- fix Broken access control Added server-side authorization checks to get_profile_details (filters privileged roles from students), track_video_watch_duration (requires lesson access), and submit_quiz (requires quiz access).
- fix Seed Google Meet account form on mount GoogleMeetSettings edit swapped list and form with v-if/v-else, mounting the form fresh on every open with accountID already set. The watcher had no `immediate` option so it never fired; saving also called rename_doc with an empty new_name.
- fix Count a coupon redemption once per payment that was actually paid Coupon redemptions were counted wrong (two concurrent redemptions both read the same count, one was lost), and gateway retries picked the wrong Integration Request. Fixed race condition with atomic update and used the correct request for retry.
- fix Resolve private lesson media whose file_url contains _ or % Uploaded lesson PDFs failed to load (403) for enrolled students when the file name had an underscore or %. The access check escaped _/% in a way the query builder double-escaped, so it matched nothing and denied access. Used bound query to fix escaping.
- fix Drop the razorpay dependency LMS pinned razorpay~=1.4.1 while payments (a required app) pins razorpay~=2.0.0 — disjoint ranges that bench only resolves by luck. Nothing in LMS imports the SDK; payments owns it. Dropped the dependency to stop chasing version ranges.
- refactor Merge `develop` into `main-hotfix` chore: merge `develop` into `main-hotfix`
- refactor Now, mon[dot]school domain is not owned by Frappe Team. chore: Now, mon[dot]school domain is not owned by Frappe Team.
b
Builder
2 fixes
- fix Collapse empty Autocomplete instead of showing a blank sliver Autocomplete now hides the container when search returns no matches instead of showing an empty bordered box.
- fix Regenerate block ids when pasting at root with no selection fix: regenerate block ids when pasting at root with no selection
- feat First Ticket tag and tag charts on the dashboard A "First Ticket" tag is now applied automatically to each requester's first ticket, plus two tag charts on the dashboard to surface patterns.
- perf Keep permission filtering bounded at any ticket count Replaces linear ticket enumeration in search filters (O(n) with 32k+ bound-variable ceiling) with parametrized permission queries that scale to any table size.
- fix Move ticket's feedback to sidepanel Ticket feedback UI now lives in the side panel for better UX.
- fix Show chart-specific empty states All empty charts on the dashboard showed the same generic message; now each chart shows its own message and doesn't render skeleton bars where the chart header should be.
- fix Keep the last recent activity row out of the bottom fade The last row in **My Recent Activity** was always rendered faded because the bottom scroll fade was pinned to the card with no notion of scroll position. Added padding to push content above the fade.
- feat Allow serving the app from a custom path Insights can now serve from custom path via `insights_path` site config for sites that use /insights for something else.
- feat Reference lines, funnel-from-measures, percent measures Charts now support horizontal reference lines, funnels from multiple measures, and percent-formatted measures.
- perf Migrate to frappe-ui v1 APIs + standardize components Migrated src2 (v3) off the deprecated frappe-ui 0.1.x APIs to 1.0.0-beta.24, including design tokens codemo, lucide icons, and flat Dialog props. src/ (legacy v2) left as-is.
- perf Remove v2 code Removed Insights v2 frontend, v2 doctypes, and v2-era query builders. Sites with v2 queries executed in the last 30 days are blocked until `insights_allow_legacy_v2_upgrade` is set in site config.
- fix Restore PNG export for dashboards and charts PNG export now works by replacing unmaintained dom-to-image with html-to-image fork, which properly encodes SVG data URIs.
p
Press
4 new features · 1 speed-ups · 5 fixes
- feat Add public IP for hetzner Hetzner servers now support public IP configuration.
- feat Set docker MTU during Hetzner server creation Docker MTU is now set during Hetzner server creation to match the 1450 MTU of Hetzner's private network.
- feat Prebundle headless Chromium in prod bench image feat(server): Prebundle headless Chromium in prod bench image
- feat Add playbook to set docker MTU to 1450 Hetzner private networks run at MTU 1450; docker defaults to 1500, causing silent packet drops over the private network. Merges `"mtu": 1450` into /etc/docker/daemon.json and reboots if changed.
- perf Avoid redundant Team doc loads and N+1 queries Press Role guards called frappe.get_doc("Team", ...) just to call is_team_owner()/is_admin_user(), loading every row of team_members, discounts, and other children. Extracted these methods to use direct DB queries, cutting cost and eliminating N+1s.
See all 10 changes
- fix Encrypt TLS private keys at rest TLS private keys stored plaintext in the database were encrypted at rest using Password fields, keyed by the site's encryption_key.
- fix Keep one-time passwords out of Account Request One-time passwords now stored in cache instead of Account Request, fixing login failures for teams created outside Team.create_new.
- fix Refresh access token after app (re)installation GitHub app reinstallation no longer leaves stale tokens; the callback now refreshes on `installation_id` even when no `code` is present.
- fix Accept team invite as Administrator so member side effects don't fail Invited team members can now accept invites without permission errors from side effects like Email Group Member creation.
- fix Derive document ownership from a declared table Document ownership rules now live in a declared table instead of field sniffing, covering partner records, SSH keys, firewalls, app plans, and child rows.
o
Other
29 new features · 7 speed-ups · 55 fixes · 28 refactors
- feat Name a thread row after everyone who wrote in it Inbox thread rows now name participants in order they first wrote, with user's own addresses collapsed to `me`.
- feat Installable PWA with iOS launch screens Mail now installable as PWA with iOS launch screens; manifest and iOS metas attached only when on /mail route.
- feat Bootstrap enrollment for Central and Pilot Provisioning now hands benches single-use bootstrap tokens instead of durable credentials; benches mint their own via `bench enroll`.
- feat Run Backup Site on a dedicated queue and worker Backup Site now runs on its own `backup` queue and worker, preventing long backups from stalling other operations.
- feat Add loan reporter role feat: Add loan reporter role
See all 119 changes
- feat Implement staging trial provisioning for teams feat(staging_trial): implement staging trial provisioning for teams
- feat Add audit follow-ups Added background migration notifications, hang-guard records, rollback safety, and parser hardening from product audit.
- feat Add binlog purge dialog and alert for server page feat: add binlog purge dialog and alert for server page
- feat List configured sites in `frappectl guide` `frappectl guide` now prints configured site profiles with URLs, descriptions, and default/read-only tags for agent use.
- feat Add cloud settings embed Pilot now serves a cloud settings embed for Desk to load cross-origin with isolated styles.
- feat TOTP powered 2FA Two-factor authentication now supports time-based one-time passwords (TOTP) with recovery code fallback.
- feat Add option to revert page changes since last publish Added Revert Changes option in the primary button dropdown to restore published state from draft changes.
- feat Send reader's Edit button straight to GitHub for synced spaces On public reader pages of git-synced spaces, the Edit button now opens the page's source file in GitHub's web editor.
- feat Refactor!: move the editor SPA from /wiki to /wiki-app Wiki editor SPA moved from /wiki to /wiki-app so spaces can have pages at /wiki; squat removed from website_route_rules and can_render check.
- feat Build out the Mail Admin Dashboard Mail Admin Dashboard now includes detail pages for directory resources (members, groups, mailing lists, etc.) and Emails, Reports, Observability, and Actions sections.
- feat Configurable advance payment handling on loan product Loan Product now has a "How to Handle Advance Payments" option to choose between reducing tenure (EMI fixed) or reducing EMI (tenure fixed).
- feat Import Tally BOM co-products, by-products, and scrap as secondary items Tally BOM rows classified as Co-Product / By-Product / Scrap are now imported as ERPNext BOM secondary items (previously only Component rows were imported).
- feat Report backend and frontend test coverage in the README and on pull requests Backend (545 tests, 83.7%) and frontend (33 specs / 78 tests, 65.3%) coverage now reported in README and PR comments.
- feat Add draft-security-advisory skill for writing GitHub Security Advisories feat: add draft-security-advisory skill for writing GitHub Security Advisories
- feat Storage cards in server page feat: Storage cards in server page
- feat Add "Published pages only" filter to Broken Links report feat: add "Published pages only" filter to Broken Links report
- feat Admin password reset Added admin password reset and sessions management UI.
- feat Mobile PWA navigation shell and touch UX Mobile-only revamp of Mail's chrome with a bottom tab bar (Mail, Screener, Search, Profile) and Compose FAB; desktop unchanged. Tab and FAB step aside in thread view, selection mode, and search.
- feat Access slot props, pass dynamic slots, add components from context menu Components inside a slot can now access slot scope/props, dynamic slots can be passed, and components can be added from the context menu.
- feat Card-per-question layout for the public form Splits the single form card into one quiet card per question on the public respondent form, following the Google Forms pattern with hairline borders, 10px radius, generous padding.
- feat TDS filing integration Added TDS (Tax Deducted at Source) filing integration.
- feat Surface sheets in Drive as content files Sheets are now a Drive content-app; each new Sheet creates a backing Drive File, so sheets show up in — and open from — Drive just like Writer and Slides.
- feat Sleepy VMs: idle VMs sleep to free RAM and wake on the first inbound TCP connection Puts an idle VM to sleep and resumes it on demand via host reboot recovery or — transparently — the first inbound TCP connection. Sleeping VMs keep their disk but release RAM to the host. Opt-in per VM via `sleep_on_idle`.
- feat Replace centralized host mesh controller with ANCP (Atlas network control protocol) Introduces `atlas-networkd` daemon using a distributed network protocol (ANCP) instead of a centralized controller for private networking.
- perf Refactor!: Consolidate state, db directories and remove dead code Consolidates rootless database state, extracts shared systemd plumbing, moves host-level state to common directory, removes dead code.
- perf Trim outputs, save some tokens! `doctype list` and `doctype show` outputs now remove repeated values and defaults to use fewer tokens.
- perf Rebuild the test suite, and fix the product bugs it found Test suite rebuilt from scratch with GameplanTestCase, persona cast, no pending/skipped tests, no retries; surface product bugs found during rebuild.
- perf Simplified Technical English for writing New technical-writing skill with Simplified Technical English rules for documentation, READMEs, commit messages, PRs, plans, and release notes.
- perf Session management refactor Moved bench-level logging to bench, consolidated token minting to pyjwt and Session class, ensured all tasks and major actions are logged, and added JTI store for token revocation and tracking.
- perf Kill the rating-path N+1s in the monthly run Removed N+1 query shapes on the invoice rating path by spreading per-team work across workers.
- perf Fan the monthly billing run out to per-team worker jobs Turned the monthly billing run from a single monolithic scheduler job into a fan-out orchestrator, handling each team's unit of work independently. At ~2s per collected invoice, this reduces a 50k-team run from ~28h sequentially to parallel distribution.
- fix Address audit findings across calendar, mail, store, suite_core and utils Fixed privilege escalation to site takeover in admin member endpoints that accepted caller-supplied User names without permission checks.
- fix Hang-guard record identity + XML DOCTYPE/entity bypass Fixed record identity lookup that misread Tally keys and added XML DOCTYPE/entity parsing guards to prevent bypass attacks.
- fix Bench creation from a production sibling inherits its TLS choice Bench creation now matches parent's admin.tls setting when unspecified and parent is production.
- fix Keep branch name attached after pinned-commit/tag checkout App repos now land on their configured local branch after pinned-commit/tag checkout instead of detached HEAD.
- fix Show an error page when the mail server is unavailable Mail server connection failures now show an error page instead of rendering a blank page or opaque 500 errors.
- fix Generate DB credentials at bench init, not bench new MariaDB/Postgres root passwords now generated at bench initialization instead of bench creation, fixing the setup wizard's "use existing database" false positive.
- fix Keep the in-cell editor pinned to its cell In-cell editor position now updates continuously instead of only on selection, keeping it pinned to the edited cell through scrolling and zoom.
- fix Skip stale accounts in automation sieve rebuild patch Automation sieve rebuild patch now skips stale account rows from before the account reshape.
- fix Decide the layout tier once, at load Mobile and desktop layout tiers now decided once at load instead of re-swapping on resize, preventing unmounting of open surfaces.
- fix Stop filter/pivot range outline from displacing the grid Filter and pivot range outline now drawn at viewport extent instead of full range extent, preventing grid displacement.
- fix Fix/unicommerce display order and invoice fixes Invoice generation now handles Unicommerce rejections via SQL error handling, and Sync Old Orders backfills Display Order No.
- fix Classify ledgers under a renamed reserved Tally group Ledger classification now uses a renamed reserved Tally group's internal ID instead of display name, preserving account_type.
- fix Allow cancel of security amount Loan Refund Loan Refund cancellation now skips available-amount check and correctly adds refund amount back to security deposit.
- fix Keep attachment blob URLs alive so Safari can download them Attachment blob URLs now revoked on a delay instead of immediately after anchor click, letting Safari fetch before revocation.
- fix Show description on hover of SPF, DKIM and DMARC result Mail MIME view now includes parsed Authentication-Results for each check and shows it as a tooltip.
- fix Focus subject input when its label is clicked Composer subject row now wrapped in label so clicking "Subject" text focuses the input.
- fix Surface JMAP errors from sieve script set calls Sieve script create/update/delete now properly detects and surfaces JMAP method-level errors instead of silently dropping them.
- fix Restore live site (asset-hash mismatch) + cap fieldnames at 64 chars Repointed forms.html to actually-committed asset hashes and capped fieldnames at 64 chars.
- fix Shadow DOM with css tokens Shadow DOM now ships with its own CSS tokens instead of depending on desk's.
- fix Prevent NaN for storage stats for macos fix(ui): Prevent NaN for storage stats for macos
- fix Show the declined-domain provider message to the caller Admin API now shows actual provider error messages instead of one fixed generic string.
- fix Safer db provisioning and port defaults MariaDB/Postgres default ports changed to 3310/5450, fixed stale systemd unit survival, and added timeout error raising.
- fix Map domain-provider exit 2 to a declined conflict, not unavailable Domain provider exit code 2 (declined) now raises DomainConflictError instead of DomainProviderError, mapping to 409 instead of vague unavailability.
- fix Bench address/manager reflect config immediately, not after full setup fix: bench address/manager reflect config immediately, not after full setup
- fix Admin bench create/drop accept install.sh's scoped nginx sudo grant Admin API bench create/drop now check scoped nginx sudo grant instead of bare sudo, fixing bench operations on install.sh-provisioned hosts.
- fix Point default-branch references at develop Default branch updated from main to develop in install.sh and README.
- fix Skip worktrees fix(dev): Skip worktrees
- fix Chat notifications and chat ordering fix(meet): chat notifications and chat ordering
- fix Trim the message content if it's too long in toast fix(meet): trim the message content if it's too long in toast
- fix Add spacing between navlinks and btns in sidebar Sidebar navlink items can now have custom classes for additional customization.
- fix Wire up three unreachable UI affordances Cross-link deletion, text resize via corner drag, and nested element selection now wired to UI.
- fix App install consistency App Install dialog now reused everywhere for consistency.
- fix Don't send empty api_key to Ollama Prevents litellm.APIConnectionError when ollama connector is configured without an API key.
- fix Resumable downloads + async folder-zip build Fixes large folder zips truncating into corrupt archives and large files restarting on dropped connections by serving from storage with HTTP Range support and background job build.
- fix Correct S3 presign region, push download status over socket S3 presigned URLs are now signed in the bucket's real region (detected via `get_bucket_location`) instead of the client's default, fixing PermanentRedirect failures.
- fix Seamless reconnects on network issue or stalls Peer connection recovery now seamlessly reconnects on network stalls without user intervention.
- fix Grant the UI job contents: write so the frontend coverage badge publishes Frontend coverage badge now publishes correctly with proper GitHub Actions permissions.
- fix Published pages honour author blank lines Blank lines and single newlines typed in the editor now render on published pages instead of being stripped.
- fix Keep stock-account openings out of the opening JE under perpetual inventory Stock account opening balances are now excluded from the opening journal entry under perpetual inventory to prevent validation failures.
- fix Paint link hover card with a literal fill Link preview hover card now renders opaque instead of transparent on all browsers.
- fix Let paste/copy target the inline cell editor while editing Copy/paste and cut operations now correctly target the in-cell editor instead of being hijacked to whole-cell operations.
- fix Address Greptile review findings on the recent PRs Addresses review findings on BOM secondary allocation guard and related PRs.
- fix Keep link hover card opaque on browsers without color-mix() Link preview hover card now renders with a literal white fill for browser compatibility instead of relying on color-mix().
- fix Set the target company on company Bank Accounts Company bank accounts imported from Tally now have the target company set instead of relying on ambient default.
- fix Run the Step-1 file preview asynchronously so a large export cannot time out Large Tally export preview now runs in background job instead of inline, preventing request timeouts.
- fix Reload site uptime chart when site name changes SiteUptime component now watches both siteName and window, matching the pattern used by SiteInsights.
- fix Keep a BOM when its Tally secondary allocations exceed 100% BOM secondary allocations exceeding 100% are now capped at 100 to match ERPNext's constraints (Tally allows independent percentages that sum beyond 100).
- fix Misc fixes fix: misc fixes
- fix Use updated loan limit for disbursement A secured term Loan could be submitted without a Maximum Loan Amount; adding it after submission didn't persist correctly and Loan Disbursement calculated available limit as zero, failing disbursement.
- fix Do not refetch loan application values on already submitted loan Loan onload always ran the loan_application autofill, even for submitted loans, overwriting fields like monthly repayment amount with old values and blocking updates.
- fix Use semantic tokens instead of tailwind text classes Replaced old text colors with semantic text-ink tokens in the button component to fix color contrast and accessibility issues.
- fix Preserve caller aria-label; Checkbox: emit model updates once Button was silently discarding caller-provided aria-label and overwriting it, and Checkbox was emitting model updates multiple times per change.
- fix Show all day event as all day event All day events now display as "all day" instead of "12am - 12am".
- fix Run invite account creation as Administrator The invite/request-key endpoint runs as Guest but the setup it triggers (archive mailbox / automation sieve) resolved ownership from the session user, throwing "account does not belong to Guest" and rolling back, then every retry failed with primaryKeyViolation.
- fix Match Tally group names case- and whitespace-insensitively Customer/Supplier classification was keyed on exact, case-sensitive match of Tally group names (e.g., `SUNDRY DEBTORS` vs `Sundry Debtors`), so mismatched groups silently imported parties as plain ledger Accounts instead.
- refactor Drop line-height overrides that fight the type tokens Removed redundant line-height overrides fighting frappe-ui type tokens; Drive storage settings now uses items-center for vertical centering.
- refactor Give duplicated helpers one home Seven byte-identical or trivially-equivalent geometry helpers deduplicated into single home in diagram/geometry.js.
- refactor Unify Sheets into the content-app doc-event sync Sheets title and trash operations now use unified Drive doc-event handlers instead of bespoke ad-hoc helpers.
- refactor Sync translations from crowdin chore: sync translations from crowdin
- refactor Track the raster logos, keep screen recordings out of git Logo PNGs moved to design/assets/logomark/; screen recordings deliberately not committed.
- refactor Spell type-checking ignores with the TCH prefix Ruff.toml type-checking ignores now spell with the updated TCH prefix to match pinned ruff version.
- refactor Ignore B904 and fix format drift so pre-commit passes Fixed pre-commit lint failures and format drift on clean checkout.
- refactor Capture actual S3 response chore: Capture actual S3 response
- refactor Add skip validation step chore: Add skip validation step
- refactor Correct classes for p base and update empty state chore: correct classes for p base and update empty state
- refactor Add frappe dependency in pyproject.toml chore: add frappe dependency in pyproject.toml
- refactor Link the target to its branch instead of a dead autolink Report target links now render as clickable branch links instead of dead autolinks.
- refactor Update filing APIs chore: Update filing APIs
- refactor Rename the command to /rereview Workflow command renamed from /refresh to /rereview with single reaction on success/failure.
- refactor Stamp the report with its run, and clear the eyes reaction Report now stamped with run time and link; cleared eye reaction removed.
- refactor Report app check findings on the PR App check findings now reported on PR with file:line format instead of raw semgrep output.
- refactor Bump pinned pilot commit so validation imports resolve Pinned pilot commit updated to match symbol exports needed by validation.
- refactor Add a /refresh command to re-run the app checks PR authors can now use /refresh command to re-run app checks against current code.
- refactor Add e2e tests for drive and writer test: add e2e tests for drive and writer
- refactor Update README - better installation and setup instructions + feature update docs: update README - better installation and setup instructions + feature update
- refactor Drop superseded API endpoints from draw.api.diagram Removed superseded sharing API endpoints that predate draw/api/share.py and are no longer called.
- refactor Fix CI: pin indexHtmlPath for standalone builds + clear ruff findings Fixed CI build failures and ruff lint issues on standalone checkout.
- refactor Remove frontend dead code (orphaned files, unreachable exports) Removed orphaned files and unreachable exports verified unreferenced from both source and tests (282 lines).
- refactor Introduce common_config.toml - Polish Phase 2 Common config (mariadb, postgres, letsencrypt, admin.jwks) now moved to shared common_config.toml; migration runs automatically on upgrade.
- refactor Polish pilot - Phase 1 Setup Wizard DB setup simplified, admin rebuild issue fixed during setup, and site name made clickable in task detail.
- refactor 2FA rescue command 2FA rescue now revokes TOTP from CLI and uses unique device names as alternate TOTP keys.
- refactor Simpler session API Session API simplified for cleaner authentication flow.
- refactor Merging develop into Version 3 Merging develop into Version 3