Releases: Tusharp21/scan_me
Release list
Version-2.3.1
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.3.1
Chromium system-library dependencies declared for Frappe Cloud + clearer failure handling.
🛠 Fixes
- PDF generation failed on servers missing Chromium's system libraries. The bundled
chrome-headless-shellbinary launches but exits immediately (code 127) when host libraries such aslibatk-1.0.so.0,libcups,libgbm, orlibnss3are absent. Playwright surfaced this only as an opaqueTargetClosedError.generator.pynow wraps the launch in_launch_chromium(), detects the shared-library failure, writes the full diagnostic to the Error Log, and raises a cleanfrappe.ValidationError. The outer handler re-raises that message instead of masking it with the generic "PDF generation failed."
📦 Deployment
[deploy.dependencies.apt]added topyproject.toml. Declares the Chromium runtime libraries (libatk1.0-0,libatk-bridge2.0-0,libcups2,libgbm1,libnss3, etc.). Frappe Cloud (Press) reads this table when it builds the deploy image and installs the packages automatically — so a fresh deploy provisions the libraries before the app runs. It is not consumed bybench migrateorbench build(asset build); it is an image-build step. Self-hosted hosts still install the equivalent libraries at the OS level.
🔐 Audit
- The user-facing failure message contains no shell/install commands — it reads "PDF generation is temporarily unavailable. Please contact your administrator." The actionable detail lives in the Error Log, keeping the Frappe Cloud "install instructions" audit clean.
🔁 No behaviour changes
- No schema migrations, no settings changes. Existing print flows are unaffected on hosts that already have the libraries.
v2.3.0
Page orientation in Advanced Print + Frappe Cloud audit follow-ups.
✨ New
- Portrait / Landscape orientation in the Advanced Print page. A new Orientation selector under Print Setup rotates the rendered A4 page; the live preview re-renders on change like every other option. Plumbed end-to-end:
orientationis whitelisted in the options schema (api/pdf/options.py), resolved to Playwright'slandscapeflag ingenerator.py, and applied to everypage.pdf()render path inassembly.py(all-pages, none, reference, and per-segment renders use the same value so page counts and breaks stay consistent). - Wider landscape preview. The preview iframe widens from
900pxto1240px(≈ the 1.41× A4 aspect ratio) when Landscape is selected, with a smoothmax-widthtransition, so the rotated page fills the main column instead of staying boxed at portrait width. The mobile breakpoint still wins on narrow screens.
🛠 Fixes
- Deprecated
cur_frmremoved.scan_me_settings.jscalledrender_cert_status(cur_frm)from inside the cert-install callback (which had nofrmin scope). The form reference is now carried on the dialog (d._frm) and used directly — clears the Semgrepfrappe-cur-frm-usagecorrectness finding.
🔐 Security
- Semgrep file-traversal findings resolved (false positives). The two new cert-read sites in
api/admin.py(_read_pfx_bytes,cert_status_info) read paths that are alreadyrealpath-validated against the site's private-files root by_resolve_uploaded_file()/_safe_pfx_path(). Annotated both with# nosemgrep: frappe-security-file-traversalplus rationale, matching the existing directive on the cert-write path.
📦 Marketplace
- Long Description. The "long description contains install instructions" audit finding is cleared in the listing copy (no
bench setup/bench installtext). Canonical marketplace copy is now version-controlled inMARKETPLACE_LONG_DESCRIPTION.md— paste it into the Frappe Cloud listing; do not pasteDOCUMENTATION.md/RELEASE_NOTES.md(they containbenchinstall commands by design and would re-trip the check).
🔁 No behaviour changes for existing options
Additive feature only. No schema migrations; orientation defaults to Portrait, preserving current output for every existing print flow.
v2.2.0
Cert management UI + invisible PAdES signatures + audit follow-ups.
✨ New
- Signing & Certificates tab in Scan Me Settings with:
- Status panel showing the active signing cert at a glance: 🔴 self-signed (recipients see yellow ⚠), 🟡 CA-issued expiring within 30 days, 🟢 CA-issued healthy, ⚪ no cert installed. Surfaces subject CN, issuer, validity window, days-to-expiry, SHA-256 fingerprint, and a recognised-CA hint for AATL-listed issuers (Sectigo, GlobalSign, eMudhra, DigiCert, etc.).
- Upload Production Certificate button — Frappe Attach-based dialog with a validate-then-install flow. Server-side preview shows cert metadata plus warnings (expired, expiring soon, missing
digital_signaturekey usage, self-signed) before the admin commits. - Regenerate Self-Signed Certificate button — confirms before wiping the auto-generated PFX so a fresh self-signed cert is created on the next PAdES-signed PDF.
- Signing Certificate Display Name setting — overrides the Subject CN/O baked into auto-generated self-signed certificates. Falls back to Global Defaults → Default Company, then to the site name when blank.
- In-print signed-PDF indicator — the Advanced Print page shows a blue 🔒 "Final PDF will be cryptographically signed (PAdES). Adobe Reader will show the signature panel — no visual stamp is drawn on the page." hint whenever Apply Signature is on, signature_type involves PAdES, and the master switch is enabled.
🛠 Fixes
- Invisible PAdES signatures.
sign_pdf()previously stamped a PyHankoTextStampStyleat the bottom-right of the last page, which collided with the HTML signature card rendered bysignature.py. Now the PAdES signature field has no visual appearance — Adobe Reader, Foxit, and Chrome PDF viewer continue to surface the signature in their Signature Panel UI, and the on-page signature card stands alone. Matches enterprise PAdES practice (DocuSign, Adobe Sign). PLAYWRIGHT_BROWSERS_PATHresolved one directory too high.generator.py:_ensure_browsers_path()computed<bench>/apps/playwright-browsersfrom a 4-level relative climb out ofapi/pdf/, butinstall.pywrites Chromium to<bench>/playwright-browsers/. PDFs failed atsync_playwright()with an "executable doesn't exist"–style error. Switched tofrappe.utils.get_bench_path()so installer and generator can never drift apart again.- Semgrep nosemgrep directive now actually suppresses. The
# nosemgrep: frappe-subprocess-execcomment ininstall.pywas followed by a rationale-continuation line, so the immediate preceding line ofsubprocess.run(was no longer the directive. Reordered. - Long-description install-instruction audit finding. The Playwright-missing log at
install.py:54referencedbench setup requirements, which tripped the Frappe Cloud "long description contains install instructions" check (regexbench\s+setup). Rephrased to "Playwright module is missing — reinstall scan_me to refresh dependencies."
🔐 Security
- New
scan_me/api/admin.py— five hardened endpoints, all System Manager only, all POST-only with rate limits (validate 10/hr, install 5/hr, regenerate 5/hr, cancel 20/hr) and audit logging. - Realpath-based path validation against
sites/<site>/private/files/for every cert read/write; symlinks pointing outside are refused withValidationError. - Atomic install with rollback — writes to
.tmp+fsync+os.replace; backs up old PFX before overwriting; restores backup ifupdate_site_configfails afterwards. - Strict input handling — 100 KB binary cap on uploaded PFX, base64 decoded with
validate=True, password bytes zeroed after PKCS#12 parse. - Audit log — every install / regenerate writes an Error Log row with user, timestamp, fingerprint prefix (first 16 hex chars). Passwords are never logged.
- Backup retention — keeps the most recent 3 timestamped
signing.pfx.*.bakfiles; older backups are deleted (each contains a private key). - Mandatory cleanup of temporary uploads —
install_cert_uploaddeletes the temp Frappe File doc in afinallyblock. The dialog'shidden.bs.modalhandler callscancel_cert_uploadif the admin closes without installing, and a swap-attachment handler cleans up the previous URL before accepting a new one.
🧱 Internal
_company_name()inscan_me/utils/pades.pyreads the newsigning_cert_display_namesetting first, falling back toGlobal Defaults.default_company, then to the site name.get_dialog_settings()inscan_me_settings.pynow also returnsenable_pades_signingso the print page can decide whether to render the signed-PDF indicator.
📚 Docs
DSC_DESKTOP_APP_DESIGN.md(new) — solution design for an optional future desktop signer that integrates Indian Class 3 DSC USB tokens (ePass2003, ProxKey, mToken) with Scan Me. Covers architecture, technology stack rationale, cryptographic flow, server-side changes, security architecture, 4-phase delivery plan, cost summary, alternatives (Aadhaar eSign, emSigner Cloud SDK, organisational Document Signer Certificate).
🧹 Migration
- Run
bench migrateto pick up the new tab andsigning_cert_display_namefield. Existing settings are preserved — the new field defaults to blank, which keeps current behaviour (Default Company is used in self-signed cert subjects). - No data migrations. No backwards-incompatible changes.
v2.1.1
Patch release — public verify page rendered unstyled.
🛠 Fixes
- Verify page CSS/JS 404.
scan_me/www/verify_document/index.htmlreferencedverify_document.cssandverify_document.jswith relative paths. Frappe serves the page at ...
Version-2.3.0
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.3.0
Page orientation in Advanced Print + Frappe Cloud audit follow-ups.
✨ New
- Portrait / Landscape orientation in the Advanced Print page. A new Orientation selector under Print Setup rotates the rendered A4 page; the live preview re-renders on change like every other option. Plumbed end-to-end:
orientationis whitelisted in the options schema (api/pdf/options.py), resolved to Playwright'slandscapeflag ingenerator.py, and applied to everypage.pdf()render path inassembly.py(all-pages, none, reference, and per-segment renders use the same value so page counts and breaks stay consistent). - Wider landscape preview. The preview iframe widens from
900pxto1240px(≈ the 1.41× A4 aspect ratio) when Landscape is selected, with a smoothmax-widthtransition, so the rotated page fills the main column instead of staying boxed at portrait width. The mobile breakpoint still wins on narrow screens.
🛠 Fixes
- Deprecated
cur_frmremoved.scan_me_settings.jscalledrender_cert_status(cur_frm)from inside the cert-install callback (which had nofrmin scope). The form reference is now carried on the dialog (d._frm) and used directly — clears the Semgrepfrappe-cur-frm-usagecorrectness finding.
🔐 Security
- Semgrep file-traversal findings resolved (false positives). The two new cert-read sites in
api/admin.py(_read_pfx_bytes,cert_status_info) read paths that are alreadyrealpath-validated against the site's private-files root by_resolve_uploaded_file()/_safe_pfx_path(). Annotated both with# nosemgrep: frappe-security-file-traversalplus rationale, matching the existing directive on the cert-write path.
📦 Marketplace
- Long Description. The "long description contains install instructions" audit finding is cleared in the listing copy (no
bench setup/bench installtext). Canonical marketplace copy is now version-controlled inMARKETPLACE_LONG_DESCRIPTION.md— paste it into the Frappe Cloud listing; do not pasteDOCUMENTATION.md/RELEASE_NOTES.md(they containbenchinstall commands by design and would re-trip the check).
🔁 No behaviour changes for existing options
Additive feature only. No schema migrations; orientation defaults to Portrait, preserving current output for every existing print flow.
v2.2.0
Cert management UI + invisible PAdES signatures + audit follow-ups.
✨ New
- Signing & Certificates tab in Scan Me Settings with:
- Status panel showing the active signing cert at a glance: 🔴 self-signed (recipients see yellow ⚠), 🟡 CA-issued expiring within 30 days, 🟢 CA-issued healthy, ⚪ no cert installed. Surfaces subject CN, issuer, validity window, days-to-expiry, SHA-256 fingerprint, and a recognised-CA hint for AATL-listed issuers (Sectigo, GlobalSign, eMudhra, DigiCert, etc.).
- Upload Production Certificate button — Frappe Attach-based dialog with a validate-then-install flow. Server-side preview shows cert metadata plus warnings (expired, expiring soon, missing
digital_signaturekey usage, self-signed) before the admin commits. - Regenerate Self-Signed Certificate button — confirms before wiping the auto-generated PFX so a fresh self-signed cert is created on the next PAdES-signed PDF.
- Signing Certificate Display Name setting — overrides the Subject CN/O baked into auto-generated self-signed certificates. Falls back to Global Defaults → Default Company, then to the site name when blank.
- In-print signed-PDF indicator — the Advanced Print page shows a blue 🔒 "Final PDF will be cryptographically signed (PAdES). Adobe Reader will show the signature panel — no visual stamp is drawn on the page." hint whenever Apply Signature is on, signature_type involves PAdES, and the master switch is enabled.
🛠 Fixes
- Invisible PAdES signatures.
sign_pdf()previously stamped a PyHankoTextStampStyleat the bottom-right of the last page, which collided with the HTML signature card rendered bysignature.py. Now the PAdES signature field has no visual appearance — Adobe Reader, Foxit, and Chrome PDF viewer continue to surface the signature in their Signature Panel UI, and the on-page signature card stands alone. Matches enterprise PAdES practice (DocuSign, Adobe Sign). PLAYWRIGHT_BROWSERS_PATHresolved one directory too high.generator.py:_ensure_browsers_path()computed<bench>/apps/playwright-browsersfrom a 4-level relative climb out ofapi/pdf/, butinstall.pywrites Chromium to<bench>/playwright-browsers/. PDFs failed atsync_playwright()with an "executable doesn't exist"–style error. Switched tofrappe.utils.get_bench_path()so installer and generator can never drift apart again.- Semgrep nosemgrep directive now actually suppresses. The
# nosemgrep: frappe-subprocess-execcomment ininstall.pywas followed by a rationale-continuation line, so the immediate preceding line ofsubprocess.run(was no longer the directive. Reordered. - Long-description install-instruction audit finding. The Playwright-missing log at
install.py:54referencedbench setup requirements, which tripped the Frappe Cloud "long description contains install instructions" check (regexbench\s+setup). Rephrased to "Playwright module is missing — reinstall scan_me to refresh dependencies."
🔐 Security
- New
scan_me/api/admin.py— five hardened endpoints, all System Manager only, all POST-only with rate limits (validate 10/hr, install 5/hr, regenerate 5/hr, cancel 20/hr) and audit logging. - Realpath-based path validation against
sites/<site>/private/files/for every cert read/write; symlinks pointing outside are refused withValidationError. - Atomic install with rollback — writes to
.tmp+fsync+os.replace; backs up old PFX before overwriting; restores backup ifupdate_site_configfails afterwards. - Strict input handling — 100 KB binary cap on uploaded PFX, base64 decoded with
validate=True, password bytes zeroed after PKCS#12 parse. - Audit log — every install / regenerate writes an Error Log row with user, timestamp, fingerprint prefix (first 16 hex chars). Passwords are never logged.
- Backup retention — keeps the most recent 3 timestamped
signing.pfx.*.bakfiles; older backups are deleted (each contains a private key). - Mandatory cleanup of temporary uploads —
install_cert_uploaddeletes the temp Frappe File doc in afinallyblock. The dialog'shidden.bs.modalhandler callscancel_cert_uploadif the admin closes without installing, and a swap-attachment handler cleans up the previous URL before accepting a new one.
🧱 Internal
_company_name()inscan_me/utils/pades.pyreads the newsigning_cert_display_namesetting first, falling back toGlobal Defaults.default_company, then to the site name.get_dialog_settings()inscan_me_settings.pynow also returnsenable_pades_signingso the print page can decide whether to render the signed-PDF indicator.
📚 Docs
DSC_DESKTOP_APP_DESIGN.md(new) — solution design for an optional future desktop signer that integrates Indian Class 3 DSC USB tokens (ePass2003, ProxKey, mToken) with Scan Me. Covers architecture, technology stack rationale, cryptographic flow, server-side changes, security architecture, 4-phase delivery plan, cost summary, alternatives (Aadhaar eSign, emSigner Cloud SDK, organisational Document Signer Certificate).
🧹 Migration
- Run
bench migrateto pick up the new tab andsigning_cert_display_namefield. Existing settings are preserved — the new field defaults to blank, which keeps current behaviour (Default Company is used in self-signed cert subjects). - No data migrations. No backwards-incompatible changes.
v2.1.1
Patch release — public verify page rendered unstyled.
🛠 Fixes
- Verify page CSS/JS 404.
scan_me/www/verify_document/index.htmlreferencedverify_document.cssandverify_document.jswith relative paths. Frappe serves the page at/verify_document(no trailing slash), so the browser resolved them to/verify_document.cssand/verify_document.js— both 404. Switched to absolute paths (/verify_document/verify_document.css,/verify_document/verify_document.js), which Frappe serves correctly. Page now loads with full styling and scanner JS as intended. CSP (style-src 'self'/script-src 'self') unchanged — same-origin so no policy update needed.
🔁 No behaviour changes
HTML-only fix. No schema changes, no migrations, no dependency bumps.
v2.1.0
Reliability + print-format author tooling.
🛠 Fixes
- Chromium install pipeline rewrite — root-causes the "Executable doesn't exist" launch failure that hit benches after a Playwright pip upgrade left a stale
chromium_headless_shell-*cache dir behind. Five mechanical changes:- Cache moved to
{bench_path}/playwright-browsers/(was user-global~/.cache/ms-playwright/). Survives Playwright pip upgrades, one cache per bench, no~/.cachepollution. - Cache validity now requires Playwright's
INSTALLATION_COMPLETEmarker file — not just directory existence. Stale and partially-downloaded dirs now trigger a fresh install instead of being silently reused. _cleanup_partial()wipes marker-less Chromium dirs before retry so the next install starts clean.- New
scan_me/__init__.pyexportsPLAYWRIGHT_BROWSERS_PATHso every web/worker process picks up the bench-local cache at import time. - Switched from
chromiumtochromium-headless-shell(Playwright's PDF-focused build — ~110 MB vs ~170 MB, same rendering engine).
- Cache moved to
Scan Me Settingsallowlist now actually rejects Single + child-table doctypes. The previous row-level...
Version-2.2.0
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.2.0
Cert management UI + invisible PAdES signatures + audit follow-ups.
✨ New
- Signing & Certificates tab in Scan Me Settings with:
- Status panel showing the active signing cert at a glance: 🔴 self-signed (recipients see yellow ⚠), 🟡 CA-issued expiring within 30 days, 🟢 CA-issued healthy, ⚪ no cert installed. Surfaces subject CN, issuer, validity window, days-to-expiry, SHA-256 fingerprint, and a recognised-CA hint for AATL-listed issuers (Sectigo, GlobalSign, eMudhra, DigiCert, etc.).
- Upload Production Certificate button — Frappe Attach-based dialog with a validate-then-install flow. Server-side preview shows cert metadata plus warnings (expired, expiring soon, missing
digital_signaturekey usage, self-signed) before the admin commits. - Regenerate Self-Signed Certificate button — confirms before wiping the auto-generated PFX so a fresh self-signed cert is created on the next PAdES-signed PDF.
- Signing Certificate Display Name setting — overrides the Subject CN/O baked into auto-generated self-signed certificates. Falls back to Global Defaults → Default Company, then to the site name when blank.
- In-print signed-PDF indicator — the Advanced Print page shows a blue 🔒 "Final PDF will be cryptographically signed (PAdES). Adobe Reader will show the signature panel — no visual stamp is drawn on the page." hint whenever Apply Signature is on, signature_type involves PAdES, and the master switch is enabled.
🛠 Fixes
- Invisible PAdES signatures.
sign_pdf()previously stamped a PyHankoTextStampStyleat the bottom-right of the last page, which collided with the HTML signature card rendered bysignature.py. Now the PAdES signature field has no visual appearance — Adobe Reader, Foxit, and Chrome PDF viewer continue to surface the signature in their Signature Panel UI, and the on-page signature card stands alone. Matches enterprise PAdES practice (DocuSign, Adobe Sign). PLAYWRIGHT_BROWSERS_PATHresolved one directory too high.generator.py:_ensure_browsers_path()computed<bench>/apps/playwright-browsersfrom a 4-level relative climb out ofapi/pdf/, butinstall.pywrites Chromium to<bench>/playwright-browsers/. PDFs failed atsync_playwright()with an "executable doesn't exist"–style error. Switched tofrappe.utils.get_bench_path()so installer and generator can never drift apart again.- Semgrep nosemgrep directive now actually suppresses. The
# nosemgrep: frappe-subprocess-execcomment ininstall.pywas followed by a rationale-continuation line, so the immediate preceding line ofsubprocess.run(was no longer the directive. Reordered. - Long-description install-instruction audit finding. The Playwright-missing log at
install.py:54referencedbench setup requirements, which tripped the Frappe Cloud "long description contains install instructions" check (regexbench\s+setup). Rephrased to "Playwright module is missing — reinstall scan_me to refresh dependencies."
🔐 Security
- New
scan_me/api/admin.py— five hardened endpoints, all System Manager only, all POST-only with rate limits (validate 10/hr, install 5/hr, regenerate 5/hr, cancel 20/hr) and audit logging. - Realpath-based path validation against
sites/<site>/private/files/for every cert read/write; symlinks pointing outside are refused withValidationError. - Atomic install with rollback — writes to
.tmp+fsync+os.replace; backs up old PFX before overwriting; restores backup ifupdate_site_configfails afterwards. - Strict input handling — 100 KB binary cap on uploaded PFX, base64 decoded with
validate=True, password bytes zeroed after PKCS#12 parse. - Audit log — every install / regenerate writes an Error Log row with user, timestamp, fingerprint prefix (first 16 hex chars). Passwords are never logged.
- Backup retention — keeps the most recent 3 timestamped
signing.pfx.*.bakfiles; older backups are deleted (each contains a private key). - Mandatory cleanup of temporary uploads —
install_cert_uploaddeletes the temp Frappe File doc in afinallyblock. The dialog'shidden.bs.modalhandler callscancel_cert_uploadif the admin closes without installing, and a swap-attachment handler cleans up the previous URL before accepting a new one.
🧱 Internal
_company_name()inscan_me/utils/pades.pyreads the newsigning_cert_display_namesetting first, falling back toGlobal Defaults.default_company, then to the site name.get_dialog_settings()inscan_me_settings.pynow also returnsenable_pades_signingso the print page can decide whether to render the signed-PDF indicator.
📚 Docs
DSC_DESKTOP_APP_DESIGN.md(new) — solution design for an optional future desktop signer that integrates Indian Class 3 DSC USB tokens (ePass2003, ProxKey, mToken) with Scan Me. Covers architecture, technology stack rationale, cryptographic flow, server-side changes, security architecture, 4-phase delivery plan, cost summary, alternatives (Aadhaar eSign, emSigner Cloud SDK, organisational Document Signer Certificate).
🧹 Migration
- Run
bench migrateto pick up the new tab andsigning_cert_display_namefield. Existing settings are preserved — the new field defaults to blank, which keeps current behaviour (Default Company is used in self-signed cert subjects). - No data migrations. No backwards-incompatible changes.
v2.1.1
Patch release — public verify page rendered unstyled.
🛠 Fixes
- Verify page CSS/JS 404.
scan_me/www/verify_document/index.htmlreferencedverify_document.cssandverify_document.jswith relative paths. Frappe serves the page at/verify_document(no trailing slash), so the browser resolved them to/verify_document.cssand/verify_document.js— both 404. Switched to absolute paths (/verify_document/verify_document.css,/verify_document/verify_document.js), which Frappe serves correctly. Page now loads with full styling and scanner JS as intended. CSP (style-src 'self'/script-src 'self') unchanged — same-origin so no policy update needed.
🔁 No behaviour changes
HTML-only fix. No schema changes, no migrations, no dependency bumps.
v2.1.0
Reliability + print-format author tooling.
🛠 Fixes
- Chromium install pipeline rewrite — root-causes the "Executable doesn't exist" launch failure that hit benches after a Playwright pip upgrade left a stale
chromium_headless_shell-*cache dir behind. Five mechanical changes:- Cache moved to
{bench_path}/playwright-browsers/(was user-global~/.cache/ms-playwright/). Survives Playwright pip upgrades, one cache per bench, no~/.cachepollution. - Cache validity now requires Playwright's
INSTALLATION_COMPLETEmarker file — not just directory existence. Stale and partially-downloaded dirs now trigger a fresh install instead of being silently reused. _cleanup_partial()wipes marker-less Chromium dirs before retry so the next install starts clean.- New
scan_me/__init__.pyexportsPLAYWRIGHT_BROWSERS_PATHso every web/worker process picks up the bench-local cache at import time. - Switched from
chromiumtochromium-headless-shell(Playwright's PDF-focused build — ~110 MB vs ~170 MB, same rendering engine).
- Cache moved to
Scan Me Settingsallowlist now actually rejects Single + child-table doctypes. The previous row-levelvalidate()was dead code (Frappe doesn't call children'svalidate()during the parent save flow) — moved the check toScanMeSettings.validate()so it fires at the real entry point.
✨ New
PRINT_FORMAT_GUIDE.md— complete authoring guide for print formats: body-header/footer extraction (id="header-html"/id="footer-html"), utility classes (.page-break,.new-page,.no-split,.no-print,.screen-only,.breakable), edge-case CSS rules already in place, Jinja helpers, worked examples, common pitfalls.- Print CSS extended with seven edge-case rules (image overflow protection, orphans/widows on paragraphs and rows, list-item keep-whole, preformatted-block wrapping, caption-stays-with-table, long-string break-anywhere) and six opt-in utility classes — all backwards-compatible additions.
🧱 Internal
api/pdf.pyrefactored intoapi/pdf/package (one file per feature: generator / assembly / attach / css / images / letterhead / options / pades / qr / signature / watermark). Public API pathscan_me.api.pdf.generate_chrome_pdfpreserved via package re-export.- Body-defined header/footer (
id="header-html"/id="footer-html") now auto-promoted to repeating page header/footer with dynamic height measurement so Chromium reserves the right margin without manual tuning.
v2.0.2
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Replaced raw
frappe.cache.get/setex/incrbycalls in the per-UUID rate limiter (api/verify_document_qr.py) with multitenancy-safeget_value/set_value. Resolves the Semgrepfrappe-cache-breaks-multitenancyfinding from the Frappe Cloud audit. Behaviour preserved — UUIDs over 60 hits / hour still get blocked, with the cache entry now correctly site-prefixed on multi-tenant benches. - Removed remaining external links from the Marketplace long description per audit guidance.
🔁 No behaviour changes
This release is audit / fix only. No feature additions, no schema changes, no migrations.
v2.0.1
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Added
[tool.bench.frappe-dependencies]section topyproject.tomldeclaring supported Frappe range (>=14.0.0,<=17.0.0-dev). - Removed external links from the long description (
README.md) per Frappe Cloud audit guidance. - Tightened the ...
Version-2.1.1
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.1.1
Patch release — public verify page rendered unstyled.
🛠 Fixes
- Verify page CSS/JS 404.
scan_me/www/verify_document/index.htmlreferencedverify_document.cssandverify_document.jswith relative paths. Frappe serves the page at/verify_document(no trailing slash), so the browser resolved them to/verify_document.cssand/verify_document.js— both 404. Switched to absolute paths (/verify_document/verify_document.css,/verify_document/verify_document.js), which Frappe serves correctly. Page now loads with full styling and scanner JS as intended. CSP (style-src 'self'/script-src 'self') unchanged — same-origin so no policy update needed.
🔁 No behaviour changes
HTML-only fix. No schema changes, no migrations, no dependency bumps.
v2.1.0
Reliability + print-format author tooling.
🛠 Fixes
- Chromium install pipeline rewrite — root-causes the "Executable doesn't exist" launch failure that hit benches after a Playwright pip upgrade left a stale
chromium_headless_shell-*cache dir behind. Five mechanical changes:- Cache moved to
{bench_path}/playwright-browsers/(was user-global~/.cache/ms-playwright/). Survives Playwright pip upgrades, one cache per bench, no~/.cachepollution. - Cache validity now requires Playwright's
INSTALLATION_COMPLETEmarker file — not just directory existence. Stale and partially-downloaded dirs now trigger a fresh install instead of being silently reused. _cleanup_partial()wipes marker-less Chromium dirs before retry so the next install starts clean.- New
scan_me/__init__.pyexportsPLAYWRIGHT_BROWSERS_PATHso every web/worker process picks up the bench-local cache at import time. - Switched from
chromiumtochromium-headless-shell(Playwright's PDF-focused build — ~110 MB vs ~170 MB, same rendering engine).
- Cache moved to
Scan Me Settingsallowlist now actually rejects Single + child-table doctypes. The previous row-levelvalidate()was dead code (Frappe doesn't call children'svalidate()during the parent save flow) — moved the check toScanMeSettings.validate()so it fires at the real entry point.
✨ New
PRINT_FORMAT_GUIDE.md— complete authoring guide for print formats: body-header/footer extraction (id="header-html"/id="footer-html"), utility classes (.page-break,.new-page,.no-split,.no-print,.screen-only,.breakable), edge-case CSS rules already in place, Jinja helpers, worked examples, common pitfalls.- Print CSS extended with seven edge-case rules (image overflow protection, orphans/widows on paragraphs and rows, list-item keep-whole, preformatted-block wrapping, caption-stays-with-table, long-string break-anywhere) and six opt-in utility classes — all backwards-compatible additions.
🧱 Internal
api/pdf.pyrefactored intoapi/pdf/package (one file per feature: generator / assembly / attach / css / images / letterhead / options / pades / qr / signature / watermark). Public API pathscan_me.api.pdf.generate_chrome_pdfpreserved via package re-export.- Body-defined header/footer (
id="header-html"/id="footer-html") now auto-promoted to repeating page header/footer with dynamic height measurement so Chromium reserves the right margin without manual tuning.
v2.0.2
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Replaced raw
frappe.cache.get/setex/incrbycalls in the per-UUID rate limiter (api/verify_document_qr.py) with multitenancy-safeget_value/set_value. Resolves the Semgrepfrappe-cache-breaks-multitenancyfinding from the Frappe Cloud audit. Behaviour preserved — UUIDs over 60 hits / hour still get blocked, with the cache entry now correctly site-prefixed on multi-tenant benches. - Removed remaining external links from the Marketplace long description per audit guidance.
🔁 No behaviour changes
This release is audit / fix only. No feature additions, no schema changes, no migrations.
v2.0.1
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Added
[tool.bench.frappe-dependencies]section topyproject.tomldeclaring supported Frappe range (>=14.0.0,<=17.0.0-dev). - Removed external links from the long description (
README.md) per Frappe Cloud audit guidance. - Tightened the Advanced Print page role from
AlltoSystem User, blocking Guest / Website User access while keeping all desk users (Sales User, Accountant, Stock User, etc.) functional. - Annotated the two intentional file-system call sites (
api/pdf.py,utils/pades.py) with inline# nosemgrep: frappe-security-file-traversalmarkers — both are already gated by allow-list containment / fixed internal paths.
🔁 No behaviour changes
This release is audit / metadata only. No feature additions, no schema changes, no migrations.
v2.0.0
Major release — Chromium PDF pipeline, PAdES digital signatures, Advanced Print page, and a hardened Verified QR with tamper detection.
🚀 New features
🔐 Signing & Verification
- Multi-signer support — same document can be signed by multiple users, each with their own Verified QR
- Content hash (SHA-256) recorded at sign time — edits auto-invalidate the signature in PDFs and on the verify page
- Permanent signature lock — Verified QR records can be locked so no one, including Administrator, can modify or delete
- Stored-signature mode — server reads the user's saved signature instead of accepting client-supplied images
- Signature Type selector — one setting controls Visual Block / Cryptographic (PAdES) / Both
🖨️ Advanced Print Page (/app/scan-me-print/{DocType}/{DocName})
- Live PDF preview pane that re-renders on every option change (debounced)
- Auto-fills Print Format + Letter Head defaults per doctype
- Multi-copy (1–5) with optional comma-separated labels (Original / Duplicate / Triplicate / custom)
- Header & footer repeat modes — All pages / First only / Last only / First + Last / None
- QR / Barcode insertion at any corner of the PDF
- Acrobat-style signature card with green VERIFIED / red INVALIDATED states
- Watermark system — Document Status (auto DRAFT / CANCELLED / status) or Custom Text
- Attach-to-Document option — saves the PDF as a private attachment on download
- Breadcrumbs: DocType → DocName → Advanced Print
🧠 PAdES Digital Signatures (PyHanko)
- Optional Adobe-compatible cryptographic PDF signatures
- Self-signed certificate auto-generated on first use
- Replace the PKCS#12 bundle with a CA-issued one for Adobe's green "Signed and all signatures are valid" badge
🌐 Public Verify Page (/verify_document/)
- Redesigned mobile-first UI with dark-mode support
- Three distinct result states — Verified, Signature Invalidated (tampered), Not Recognised
- Admin-configurable detail level — Minimal / Standard (default) / Full — controls what guests see
- Rate-limited to 30 requests per 60 seconds per IP
⚙️ Settings & Form Integration
- Scan Me Settings is now a tabbed form — Allowed Documents / Verification & Signing / Public Verification / Print Dialog Features
- New "Advanced Print" icon on document forms, placed immediately right of Frappe's native Print icon
- Admin toggle to show/hide the Advanced Print icon
📄 Bundled print formats
Sales Invoice Scan Me— full-featured invoice with QR footerSO— sample Sales Order formatBasic HTML Template by Scan Me— starter skeleton users can duplicate for any doctype
📝 Bundled Letter Head
Letter Head By Scan Meships as a fixture for reference — admin can mark it default or customize as needed
🧰 Jinja helpers (for print format authors)
qr_img,qr_link_img,verify_qr,verify_qr_img— added alongside existingqr,barcode,qr_link
🧱 Dependencies added
playwright~=1.47— Chromium PDF renderingpypdf~=6.1.3— multi-copy PDF mergingpyHanko~=0.25— PAdES signingcryptography>=41— self-signed cert generation
📦 Installation
bench get-app https://github.com/Tusharp21/scan_me
bench install-app scan_meChromium for PDF rendering (~200 MB) downloads automatically via the
after_install hook. On restricted hosts where auto-download fails,
run ./env/bin/python -m playwright install chromium manually — the app will show
a clear message pointing to this fallback.
Existing installs: bench migrate runs 5 patches that backfill sensible
defaults for new settings fields and will download Chromium if it isn't
already cached.
⚠️ Known limitations
- Self-signed PAdES cert shows as "signer unknown" in Adobe until replaced with a CA-issued PFX
- Test suite is skeleton-only — real test coverage planned for 2.1
📚 Documentation
- Full wiki: https://github.com/Tusharp21/scan_me/wiki
- Functional + Technical guide shipped in the repo as
DOCUMENTATION.md
v1.0.2 — 06 Jan 2026
- System-verified QR code generation with unique document IDs
- Logo integration in QR codes
- Signature requirement for QR generation
- Doctype-based configuration via Scan Me Settings
- Public verification support with
ROOT_URL/verify_document/
Generate a unique system ID linked to a specific document, with verification URL and embedded logo.
v1.0.1 — 18 Nov 2025
- Fixed line-level issue in
jinja_functions.py - Updated function logic for accurate output rendering
- Minor code cleanup for readability
This update focuses on improving reliability in template utilities without introducing any breaking changes.
v1.0.0 — 15 Nov 2025
- Jinja functions for print formats:
qr(),barcode(),qr_link() - Global JavaScript function
add_qr_to_description() - QR/barcode ge...
Version-2.1.0
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.1.0
Reliability + print-format author tooling.
🛠 Fixes
- Chromium install pipeline rewrite — root-causes the "Executable doesn't exist" launch failure that hit benches after a Playwright pip upgrade left a stale
chromium_headless_shell-*cache dir behind. Five mechanical changes:- Cache moved to
{bench_path}/playwright-browsers/(was user-global~/.cache/ms-playwright/). Survives Playwright pip upgrades, one cache per bench, no~/.cachepollution. - Cache validity now requires Playwright's
INSTALLATION_COMPLETEmarker file — not just directory existence. Stale and partially-downloaded dirs now trigger a fresh install instead of being silently reused. _cleanup_partial()wipes marker-less Chromium dirs before retry so the next install starts clean.- New
scan_me/__init__.pyexportsPLAYWRIGHT_BROWSERS_PATHso every web/worker process picks up the bench-local cache at import time. - Switched from
chromiumtochromium-headless-shell(Playwright's PDF-focused build — ~110 MB vs ~170 MB, same rendering engine).
- Cache moved to
Scan Me Settingsallowlist now actually rejects Single + child-table doctypes. The previous row-levelvalidate()was dead code (Frappe doesn't call children'svalidate()during the parent save flow) — moved the check toScanMeSettings.validate()so it fires at the real entry point.
✨ New
PRINT_FORMAT_GUIDE.md— complete authoring guide for print formats: body-header/footer extraction (id="header-html"/id="footer-html"), utility classes (.page-break,.new-page,.no-split,.no-print,.screen-only,.breakable), edge-case CSS rules already in place, Jinja helpers, worked examples, common pitfalls.- Print CSS extended with seven edge-case rules (image overflow protection, orphans/widows on paragraphs and rows, list-item keep-whole, preformatted-block wrapping, caption-stays-with-table, long-string break-anywhere) and six opt-in utility classes — all backwards-compatible additions.
🧱 Internal
api/pdf.pyrefactored intoapi/pdf/package (one file per feature: generator / assembly / attach / css / images / letterhead / options / pades / qr / signature / watermark). Public API pathscan_me.api.pdf.generate_chrome_pdfpreserved via package re-export.- Body-defined header/footer (
id="header-html"/id="footer-html") now auto-promoted to repeating page header/footer with dynamic height measurement so Chromium reserves the right margin without manual tuning.
v2.0.2
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Replaced raw
frappe.cache.get/setex/incrbycalls in the per-UUID rate limiter (api/verify_document_qr.py) with multitenancy-safeget_value/set_value. Resolves the Semgrepfrappe-cache-breaks-multitenancyfinding from the Frappe Cloud audit. Behaviour preserved — UUIDs over 60 hits / hour still get blocked, with the cache entry now correctly site-prefixed on multi-tenant benches. - Removed remaining external links from the Marketplace long description per audit guidance.
🔁 No behaviour changes
This release is audit / fix only. No feature additions, no schema changes, no migrations.
v2.0.1
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Added
[tool.bench.frappe-dependencies]section topyproject.tomldeclaring supported Frappe range (>=14.0.0,<=17.0.0-dev). - Removed external links from the long description (
README.md) per Frappe Cloud audit guidance. - Tightened the Advanced Print page role from
AlltoSystem User, blocking Guest / Website User access while keeping all desk users (Sales User, Accountant, Stock User, etc.) functional. - Annotated the two intentional file-system call sites (
api/pdf.py,utils/pades.py) with inline# nosemgrep: frappe-security-file-traversalmarkers — both are already gated by allow-list containment / fixed internal paths.
🔁 No behaviour changes
This release is audit / metadata only. No feature additions, no schema changes, no migrations.
v2.0.0
Major release — Chromium PDF pipeline, PAdES digital signatures, Advanced Print page, and a hardened Verified QR with tamper detection.
🚀 New features
🔐 Signing & Verification
- Multi-signer support — same document can be signed by multiple users, each with their own Verified QR
- Content hash (SHA-256) recorded at sign time — edits auto-invalidate the signature in PDFs and on the verify page
- Permanent signature lock — Verified QR records can be locked so no one, including Administrator, can modify or delete
- Stored-signature mode — server reads the user's saved signature instead of accepting client-supplied images
- Signature Type selector — one setting controls Visual Block / Cryptographic (PAdES) / Both
🖨️ Advanced Print Page (/app/scan-me-print/{DocType}/{DocName})
- Live PDF preview pane that re-renders on every option change (debounced)
- Auto-fills Print Format + Letter Head defaults per doctype
- Multi-copy (1–5) with optional comma-separated labels (Original / Duplicate / Triplicate / custom)
- Header & footer repeat modes — All pages / First only / Last only / First + Last / None
- QR / Barcode insertion at any corner of the PDF
- Acrobat-style signature card with green VERIFIED / red INVALIDATED states
- Watermark system — Document Status (auto DRAFT / CANCELLED / status) or Custom Text
- Attach-to-Document option — saves the PDF as a private attachment on download
- Breadcrumbs: DocType → DocName → Advanced Print
🧠 PAdES Digital Signatures (PyHanko)
- Optional Adobe-compatible cryptographic PDF signatures
- Self-signed certificate auto-generated on first use
- Replace the PKCS#12 bundle with a CA-issued one for Adobe's green "Signed and all signatures are valid" badge
🌐 Public Verify Page (/verify_document/)
- Redesigned mobile-first UI with dark-mode support
- Three distinct result states — Verified, Signature Invalidated (tampered), Not Recognised
- Admin-configurable detail level — Minimal / Standard (default) / Full — controls what guests see
- Rate-limited to 30 requests per 60 seconds per IP
⚙️ Settings & Form Integration
- Scan Me Settings is now a tabbed form — Allowed Documents / Verification & Signing / Public Verification / Print Dialog Features
- New "Advanced Print" icon on document forms, placed immediately right of Frappe's native Print icon
- Admin toggle to show/hide the Advanced Print icon
📄 Bundled print formats
Sales Invoice Scan Me— full-featured invoice with QR footerSO— sample Sales Order formatBasic HTML Template by Scan Me— starter skeleton users can duplicate for any doctype
📝 Bundled Letter Head
Letter Head By Scan Meships as a fixture for reference — admin can mark it default or customize as needed
🧰 Jinja helpers (for print format authors)
qr_img,qr_link_img,verify_qr,verify_qr_img— added alongside existingqr,barcode,qr_link
🧱 Dependencies added
playwright~=1.47— Chromium PDF renderingpypdf~=6.1.3— multi-copy PDF mergingpyHanko~=0.25— PAdES signingcryptography>=41— self-signed cert generation
📦 Installation
bench get-app https://github.com/Tusharp21/scan_me
bench install-app scan_meChromium for PDF rendering (~200 MB) downloads automatically via the
after_install hook. On restricted hosts where auto-download fails,
run ./env/bin/python -m playwright install chromium manually — the app will show
a clear message pointing to this fallback.
Existing installs: bench migrate runs 5 patches that backfill sensible
defaults for new settings fields and will download Chromium if it isn't
already cached.
⚠️ Known limitations
- Self-signed PAdES cert shows as "signer unknown" in Adobe until replaced with a CA-issued PFX
- Test suite is skeleton-only — real test coverage planned for 2.1
📚 Documentation
- Full wiki: https://github.com/Tusharp21/scan_me/wiki
- Functional + Technical guide shipped in the repo as
DOCUMENTATION.md
v1.0.2 — 06 Jan 2026
- System-verified QR code generation with unique document IDs
- Logo integration in QR codes
- Signature requirement for QR generation
- Doctype-based configuration via Scan Me Settings
- Public verification support with
ROOT_URL/verify_document/
Generate a unique system ID linked to a specific document, with verification URL and embedded logo.
v1.0.1 — 18 Nov 2025
- Fixed line-level issue in
jinja_functions.py - Updated function logic for accurate output rendering
- Minor code cleanup for readability
This update focuses on improving reliability in template utilities without introducing any breaking changes.
v1.0.0 — 15 Nov 2025
- Jinja functions for print formats:
qr(),barcode(),qr_link() - Global JavaScript function
add_qr_to_description() - QR/barcode generation in desk forms and print formats
- Auto-loading via
hooks.pyconfiguration
Version-2.0.2
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.0.2
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Replaced raw
frappe.cache.get/setex/incrbycalls in the per-UUID rate limiter (api/verify_document_qr.py) with multitenancy-safeget_value/set_value. Resolves the Semgrepfrappe-cache-breaks-multitenancyfinding from the Frappe Cloud audit. Behaviour preserved — UUIDs over 60 hits / hour still get blocked, with the cache entry now correctly site-prefixed on multi-tenant benches.
🔁 No behaviour changes
This release is audit / fix only. No feature additions, no schema changes, no migrations.
v2.0.1
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Added
[tool.bench.frappe-dependencies]section topyproject.tomldeclaring supported Frappe range (>=14.0.0,<=17.0.0-dev). - Removed external links from the long description (
README.md) per Frappe Cloud audit guidance. - Tightened the Advanced Print page role from
AlltoSystem User, blocking Guest / Website User access while keeping all desk users (Sales User, Accountant, Stock User, etc.) functional. - Annotated the two intentional file-system call sites (
api/pdf.py,utils/pades.py) with inline# nosemgrep: frappe-security-file-traversalmarkers — both are already gated by allow-list containment / fixed internal paths.
🔁 No behaviour changes
This release is audit / metadata only. No feature additions, no schema changes, no migrations.
v2.0.0
Major release — Chromium PDF pipeline, PAdES digital signatures, Advanced Print page, and a hardened Verified QR with tamper detection.
🚀 New features
🔐 Signing & Verification
- Multi-signer support — same document can be signed by multiple users, each with their own Verified QR
- Content hash (SHA-256) recorded at sign time — edits auto-invalidate the signature in PDFs and on the verify page
- Permanent signature lock — Verified QR records can be locked so no one, including Administrator, can modify or delete
- Stored-signature mode — server reads the user's saved signature instead of accepting client-supplied images
- Signature Type selector — one setting controls Visual Block / Cryptographic (PAdES) / Both
🖨️ Advanced Print Page (/app/scan-me-print/{DocType}/{DocName})
- Live PDF preview pane that re-renders on every option change (debounced)
- Auto-fills Print Format + Letter Head defaults per doctype
- Multi-copy (1–5) with optional comma-separated labels (Original / Duplicate / Triplicate / custom)
- Header & footer repeat modes — All pages / First only / Last only / First + Last / None
- QR / Barcode insertion at any corner of the PDF
- Acrobat-style signature card with green VERIFIED / red INVALIDATED states
- Watermark system — Document Status (auto DRAFT / CANCELLED / status) or Custom Text
- Attach-to-Document option — saves the PDF as a private attachment on download
- Breadcrumbs: DocType → DocName → Advanced Print
🧠 PAdES Digital Signatures (PyHanko)
- Optional Adobe-compatible cryptographic PDF signatures
- Self-signed certificate auto-generated on first use
- Replace the PKCS#12 bundle with a CA-issued one for Adobe's green "Signed and all signatures are valid" badge
🌐 Public Verify Page (/verify_document/)
- Redesigned mobile-first UI with dark-mode support
- Three distinct result states — Verified, Signature Invalidated (tampered), Not Recognised
- Admin-configurable detail level — Minimal / Standard (default) / Full — controls what guests see
- Rate-limited to 30 requests per 60 seconds per IP
⚙️ Settings & Form Integration
- Scan Me Settings is now a tabbed form — Allowed Documents / Verification & Signing / Public Verification / Print Dialog Features
- New "Advanced Print" icon on document forms, placed immediately right of Frappe's native Print icon
- Admin toggle to show/hide the Advanced Print icon
📄 Bundled print formats
Sales Invoice Scan Me— full-featured invoice with QR footerSO— sample Sales Order formatBasic HTML Template by Scan Me— starter skeleton users can duplicate for any doctype
📝 Bundled Letter Head
Letter Head By Scan Meships as a fixture for reference — admin can mark it default or customize as needed
🧰 Jinja helpers (for print format authors)
qr_img,qr_link_img,verify_qr,verify_qr_img— added alongside existingqr,barcode,qr_link
🧱 Dependencies added
playwright~=1.47— Chromium PDF renderingpypdf~=6.1.3— multi-copy PDF mergingpyHanko~=0.25— PAdES signingcryptography>=41— self-signed cert generation
📦 Installation
bench get-app https://github.com/Tusharp21/scan_me
bench install-app scan_meChromium for PDF rendering (~200 MB) downloads automatically via the
after_install hook. On restricted hosts where auto-download fails,
run ./env/bin/python -m playwright install chromium manually — the app will show
a clear message pointing to this fallback.
Existing installs: bench migrate runs 5 patches that backfill sensible
defaults for new settings fields and will download Chromium if it isn't
already cached.
⚠️ Known limitations
- Self-signed PAdES cert shows as "signer unknown" in Adobe until replaced with a CA-issued PFX
- Test suite is skeleton-only — real test coverage planned for 2.1
📚 Documentation
- Full wiki: https://github.com/Tusharp21/scan_me/wiki
- Functional + Technical guide shipped in the repo as
DOCUMENTATION.md
v1.0.2 — 06 Jan 2026
- System-verified QR code generation with unique document IDs
- Logo integration in QR codes
- Signature requirement for QR generation
- Doctype-based configuration via Scan Me Settings
- Public verification support with
ROOT_URL/verify_document/
Generate a unique system ID linked to a specific document, with verification URL and embedded logo.
v1.0.1 — 18 Nov 2025
- Fixed line-level issue in
jinja_functions.py - Updated function logic for accurate output rendering
- Minor code cleanup for readability
This update focuses on improving reliability in template utilities without introducing any breaking changes.
v1.0.0 — 15 Nov 2025
- Jinja functions for print formats:
qr(),barcode(),qr_link() - Global JavaScript function
add_qr_to_description() - QR/barcode generation in desk forms and print formats
- Auto-loading via
hooks.pyconfiguration
Version-2.0.1
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.0.1
Patch release — Frappe Cloud audit compliance.
🛠 Fixes
- Added
[tool.bench.frappe-dependencies]section topyproject.tomldeclaring supported Frappe range (>=14.0.0,<=17.0.0-dev). - Removed external links from the long description (
README.md) per Frappe Cloud audit guidance. - Tightened the Advanced Print page role from
AlltoSystem User, blocking Guest / Website User access while keeping all desk users (Sales User, Accountant, Stock User, etc.) functional. - Annotated the two intentional file-system call sites (
api/pdf.py,utils/pades.py) with inline# nosemgrep: frappe-security-file-traversalmarkers — both are already gated by allow-list containment / fixed internal paths.
🔁 No behaviour changes
This release is audit / metadata only. No feature additions, no schema changes, no migrations.
v2.0.0
Major release — Chromium PDF pipeline, PAdES digital signatures, Advanced Print page, and a hardened Verified QR with tamper detection.
🚀 New features
🔐 Signing & Verification
- Multi-signer support — same document can be signed by multiple users, each with their own Verified QR
- Content hash (SHA-256) recorded at sign time — edits auto-invalidate the signature in PDFs and on the verify page
- Permanent signature lock — Verified QR records can be locked so no one, including Administrator, can modify or delete
- Stored-signature mode — server reads the user's saved signature instead of accepting client-supplied images
- Signature Type selector — one setting controls Visual Block / Cryptographic (PAdES) / Both
🖨️ Advanced Print Page (/app/scan-me-print/{DocType}/{DocName})
- Live PDF preview pane that re-renders on every option change (debounced)
- Auto-fills Print Format + Letter Head defaults per doctype
- Multi-copy (1–5) with optional comma-separated labels (Original / Duplicate / Triplicate / custom)
- Header & footer repeat modes — All pages / First only / Last only / First + Last / None
- QR / Barcode insertion at any corner of the PDF
- Acrobat-style signature card with green VERIFIED / red INVALIDATED states
- Watermark system — Document Status (auto DRAFT / CANCELLED / status) or Custom Text
- Attach-to-Document option — saves the PDF as a private attachment on download
- Breadcrumbs: DocType → DocName → Advanced Print
🧠 PAdES Digital Signatures (PyHanko)
- Optional Adobe-compatible cryptographic PDF signatures
- Self-signed certificate auto-generated on first use
- Replace the PKCS#12 bundle with a CA-issued one for Adobe's green "Signed and all signatures are valid" badge
🌐 Public Verify Page (/verify_document/)
- Redesigned mobile-first UI with dark-mode support
- Three distinct result states — Verified, Signature Invalidated (tampered), Not Recognised
- Admin-configurable detail level — Minimal / Standard (default) / Full — controls what guests see
- Rate-limited to 30 requests per 60 seconds per IP
⚙️ Settings & Form Integration
- Scan Me Settings is now a tabbed form — Allowed Documents / Verification & Signing / Public Verification / Print Dialog Features
- New "Advanced Print" icon on document forms, placed immediately right of Frappe's native Print icon
- Admin toggle to show/hide the Advanced Print icon
📄 Bundled print formats
Sales Invoice Scan Me— full-featured invoice with QR footerSO— sample Sales Order formatBasic HTML Template by Scan Me— starter skeleton users can duplicate for any doctype
📝 Bundled Letter Head
Letter Head By Scan Meships as a fixture for reference — admin can mark it default or customize as needed
🧰 Jinja helpers (for print format authors)
qr_img,qr_link_img,verify_qr,verify_qr_img— added alongside existingqr,barcode,qr_link
🧱 Dependencies added
playwright~=1.47— Chromium PDF renderingpypdf~=6.1.3— multi-copy PDF mergingpyHanko~=0.25— PAdES signingcryptography>=41— self-signed cert generation
📦 Installation
bench get-app https://github.com/Tusharp21/scan_me
bench install-app scan_meChromium for PDF rendering (~200 MB) downloads automatically via the
after_install hook. On restricted hosts where auto-download fails,
run ./env/bin/python -m playwright install chromium manually — the app will show
a clear message pointing to this fallback.
Existing installs: bench migrate runs 5 patches that backfill sensible
defaults for new settings fields and will download Chromium if it isn't
already cached.
⚠️ Known limitations
- Self-signed PAdES cert shows as "signer unknown" in Adobe until replaced with a CA-issued PFX
- Test suite is skeleton-only — real test coverage planned for 2.1
📚 Documentation
- Full wiki: https://github.com/Tusharp21/scan_me/wiki
- Functional + Technical guide shipped in the repo as
DOCUMENTATION.md
v1.0.2 — 06 Jan 2026
- System-verified QR code generation with unique document IDs
- Logo integration in QR codes
- Signature requirement for QR generation
- Doctype-based configuration via Scan Me Settings
- Public verification support with
ROOT_URL/verify_document/
Generate a unique system ID linked to a specific document, with verification URL and embedded logo.
v1.0.1 — 18 Nov 2025
- Fixed line-level issue in
jinja_functions.py - Updated function logic for accurate output rendering
- Minor code cleanup for readability
This update focuses on improving reliability in template utilities without introducing any breaking changes.
v1.0.0 — 15 Nov 2025
- Jinja functions for print formats:
qr(),barcode(),qr_link() - Global JavaScript function
add_qr_to_description() - QR/barcode generation in desk forms and print formats
- Auto-loading via
hooks.pyconfiguration
Version-2.0.0
Scan Me — Release Notes
All previous releases are on GitHub: https://github.com/Tusharp21/scan_me/releases
v2.0.0
Major release — Chromium PDF pipeline, PAdES digital signatures, Advanced Print page, and a hardened Verified QR with tamper detection.
🚀 New features
🔐 Signing & Verification
- Multi-signer support — same document can be signed by multiple users, each with their own Verified QR
- Content hash (SHA-256) recorded at sign time — edits auto-invalidate the signature in PDFs and on the verify page
- Permanent signature lock — Verified QR records can be locked so no one, including Administrator, can modify or delete
- Stored-signature mode — server reads the user's saved signature instead of accepting client-supplied images
- Signature Type selector — one setting controls Visual Block / Cryptographic (PAdES) / Both
🖨️ Advanced Print Page (/app/scan-me-print/{DocType}/{DocName})
- Live PDF preview pane that re-renders on every option change (debounced)
- Auto-fills Print Format + Letter Head defaults per doctype
- Multi-copy (1–5) with optional comma-separated labels (Original / Duplicate / Triplicate / custom)
- Header & footer repeat modes — All pages / First only / Last only / First + Last / None
- QR / Barcode insertion at any corner of the PDF
- Acrobat-style signature card with green VERIFIED / red INVALIDATED states
- Watermark system — Document Status (auto DRAFT / CANCELLED / status) or Custom Text
- Attach-to-Document option — saves the PDF as a private attachment on download
- Breadcrumbs: DocType → DocName → Advanced Print
🧠 PAdES Digital Signatures (PyHanko)
- Optional Adobe-compatible cryptographic PDF signatures
- Self-signed certificate auto-generated on first use
- Replace the PKCS#12 bundle with a CA-issued one for Adobe's green "Signed and all signatures are valid" badge
🌐 Public Verify Page (/verify_document/)
- Redesigned mobile-first UI with dark-mode support
- Three distinct result states — Verified, Signature Invalidated (tampered), Not Recognised
- Admin-configurable detail level — Minimal / Standard (default) / Full — controls what guests see
- Rate-limited to 30 requests per 60 seconds per IP
⚙️ Settings & Form Integration
- Scan Me Settings is now a tabbed form — Allowed Documents / Verification & Signing / Public Verification / Print Dialog Features
- New "Advanced Print" icon on document forms, placed immediately right of Frappe's native Print icon
- Admin toggle to show/hide the Advanced Print icon
📄 Bundled print formats
Sales Invoice Scan Me— full-featured invoice with QR footerSO— sample Sales Order formatBasic HTML Template by Scan Me— starter skeleton users can duplicate for any doctype
📝 Bundled Letter Head
Letter Head By Scan Meships as a fixture — customize and use
🧰 Jinja helpers (for print format authors)
qr_img,qr_link_img,verify_qr,verify_qr_img— added alongside existingqr,barcode,qr_link
🧱 Dependencies added
playwright~=1.47— Chromium PDF renderingpypdf~=6.1.3— multi-copy PDF mergingpyHanko~=0.25— PAdES signingcryptography>=41— self-signed cert generation
📦 Installation
bench get-app https://github.com/Tusharp21/scan_me
bench install-app scan_meChromium for PDF rendering (~200 MB) downloads automatically via the
after_install hook. On restricted hosts where auto-download fails,
run ./env/bin/python -m playwright install chromium manually — the app will show
a clear message pointing to this fallback.
Existing installs: bench migrate runs 5 patches that backfill sensible
defaults for new settings fields and will download Chromium if it isn't
already cached.
⚠️ Known limitations
- Self-signed PAdES cert shows as "signer unknown" in Adobe until replaced with a CA-issued PFX
- Test suite is skeleton-only — real test coverage planned for 2.1
📚 Documentation
- Full wiki: https://github.com/Tusharp21/scan_me/wiki
- Functional + Technical guide shipped in the repo as
DOCUMENTATION.md
v1.0.2 — 06 Jan 2026
- System-verified QR code generation with unique document IDs
- Logo integration in QR codes
- Signature requirement for QR generation
- Doctype-based configuration via Scan Me Settings
- Public verification support with
ROOT_URL/verify_document/
Generate a unique system ID linked to a specific document, with verification URL and embedded logo.
v1.0.1 — 18 Nov 2025
- Fixed line-level issue in
jinja_functions.py - Updated function logic for accurate output rendering
- Minor code cleanup for readability
This update focuses on improving reliability in template utilities without introducing any breaking changes.
v1.0.0 — 15 Nov 2025
- Jinja functions for print formats:
qr(),barcode(),qr_link() - Global JavaScript function
add_qr_to_description() - QR/barcode generation in desk forms and print formats
- Auto-loading via
hooks.pyconfiguration
Version-1.0.2
Full Changelog: v1.0.1...v1.0.2
Scan Me – Release Notes
Version: v1.0.2
App Name: Scan Me
Category: Frappe Utility App (QR Code and Barcode Generator)
Overview
Scan Me is a utility app for Frappe that provides Jinja helper methods for generating QR codes and barcodes inside Print Formats and documents.
Previous versions supported only QR and barcode generation using Jinja methods.
This release introduces system-verified QR code generation with logo integration and public verification support.
What’s New in This Release
System Verified QR Code Generation
- Generate a unique system ID linked to a specific document.
- QR code includes a verification URL and embedded logo.
- Ensures document authenticity and prevents duplicate or fake QR usage.
Signature Required for QR Generation
- QR code generation now requires a signature from the user.
- The signature is stored and validated during verification.
- Improves security, traceability, and accountability.
Doctype-Based Configuration
- Scan Me Settings child table to configure which doctypes can generate verified QR codes.
- Only selected doctypes show the Generate QR action button.
Print Format Integration
- Generate QR code in Print Formats using Jinja methods.
- Example usage:
<h4>QR for ID</h4> <img src="{{ qr(doc.name, clarity=10, fill_color='black', include_logo=True) }}" width="120">
Existing Features
- QR code and barcode generation using Jinja methods.
- Easy integration in Print Formats.
- Lightweight and developer-friendly.
Verification Flow
- Configure allowed doctypes in Scan Me Settings.
- Open a configured document.
- Click Generate QR from the Action menu.
- System generates a unique ID and QR code with logo.
- QR appears in the Print Format and PDF.
- External users scan the QR and verify the document using the public URL. ROOT_URL/verify_document/
Installation / Upgrade
Available on Frappe Cloud Marketplace:
https://cloud.frappe.io/marketplace/apps/scan_me
Upgrade the app using standard Frappe update process.
Feedback
Issues, feature requests, and contributions are welcome via GitHub.
Version-1.0.1
Release Notes
Fixes
- Corrected a line-level issue in
jinja_functions.pythat affected Jinja template processing. - Updated the function logic to ensure accurate output rendering.
- Performed minor code cleanup for improved readability and consistency.
Notes
This update focuses on improving reliability in template utilities without introducing any breaking changes.