A desktop PDF viewer and editor, built on permissive open-source libraries. Windows verified; macOS + Linux configured but unverified — see Platform support.
**Status — Phase 7.5 Acrobat Parity Close (v0.8.0, June 2026). The Acrobat parity gap from Riley's
docs/acrobat-parity-audit.mdis closed: page operations (extract / split / replace / crop / combine / insert from file / rotate), watermarks / headers & footers / backgrounds, stamps + a stamp library, hyperlinks, area measure, page-content cut/copy/paste, font swap, compress, sanitize, password encryption (bundled qpdf, Apache-2.0), Document Properties dialog, auto-bookmarks from headings, Action Wizard, Spell Check (en-US — see honesty disclosure), Find / Search, Compare Files (text + visual diff), Read Aloud (TTS), Preflight (PDF/X + PDF/A subset), the full accessibility-authoring suite (Tag PDF tree editor, Reading Order overlay, Alt Text inspector, Accessibility Checker), Page Display modes, view-only rotation, and chromeless Read Mode all ship in v0.8.0. The Bucket A tooltip / wiring / shortcut cleanups land alongside the tool registry foundation (R1 + R2 + R3) and the new L-007 ratchet (every user-facing tool surface MUST appear insrc/client/tools/registry.ts). Read What's new in v0.8.0 before relying on a subset claim or a deferred surface. The prior 7-phase roadmap (Phases 1–7 + 7.1–7.4) is preserved unchanged below and continues to ship.
Status (carried from prior cuts) — Phase 7 Polish & Cross-Platform (0.7.6). The app opens PDFs, renders them at HiDPI crisply (Ctrl+scroll zoom is fluid, cursor-anchored so the page stays put under the cursor across the gesture, and the zoom dropdown stays synced), edits pages and forms, ships visual + PAdES cryptographic signatures, runs local OCR via Tesseract.js (all nine downloadable language packs work), scans from a connected WIA scanner on Windows via a custom Node-API COM addon (Phase 5.1 — LIVE on Windows; degrades to
scanner_unavailableon macOS/Linux), combines two or more PDFs end-to-end via a real pdf-lib engine (H-30.1 — the Phase-1 stub is gone), exports to Word / Excel / PowerPoint / image formats (all six formats fully functional, including standard-font text in image exports), and adds the polish layer: an auto-update client wired to a real GitHub release feed (SuperiorAg/PDF_Viewer_Editor; the in-app "Check for updates" contacts the live feed and returns honest results), an opt-in / default-OFF telemetry framework (anonymous feature-usage counts only, nothing leaves your machine), WCAG 2.1 AA accessibility for the critical paths (keyboard navigation + Windows Narrator), an i18next localization framework (English baseline + a Spanish translation sample), macOS + Linux build configuration, a new app icon (white PDF document + folded corner + bold red "PDF" ribbon — embedded in the binary, no more "default Electron icon" warning), and a comprehensive 13-section in-app Help modal (F1) covering Getting started, Navigation, Editing pages, Annotations, Forms, Signing, OCR, Scanning, Export, Combine, Settings, Troubleshooting, and About. The two genuinely deferred items are real-hardware macOS/Linux verification and a Windows code-signing certificate; both are blocked on resources outside the codebase, not on remaining engineering work. Read Platform support and Roadmap status before relying on auto-update or non-Windows builds.
Phase 7.5 closes the parity gap surfaced in docs/acrobat-parity-audit.md (Riley, 588 lines, 2026-06-15) and the docs/acrobat-comparison.html principal-facing comparison. 35+ feature surfaces ship across 13 waves; full plan in docs/project-plan.md. The headline groupings:
- Extract / Split / Replace pages (B10 / B11) — new pages-modal pages; split by every-N-pages / by bookmark / explicit range; explicit replace-from-source-file flow.
- Insert pages from another PDF (B11) — file picker → range selection → insert at index.
- Crop Pages (B5) — overlay-driven box on the active page; apply-to-range.
- Combine (Phase 1 closure carried) — multi-file picker, dedup-by-absolute-path, de-stub.
- Page Display modes (B15) — single / two-up / scroll / facing.
- View-only rotation + true Read Mode (B16) — non-destructive view rotation; F11 chromeless reader.
- Page-content Cut/Copy/Paste (B12) — region clipboard overlay; cross-page paste; honors L-001 path sanitizer.
- Hyperlinks (B13) — add / edit / remove; targets: page goto, URL, named destination.
- Watermark / Header & Footer / Background (B4) — one modal, three tabs; range-targeted; text + image variants; per-strip token expansion (page#, totalPages, fileName, date).
- Stamps + Stamp library (B7) — built-in catalog + user-authored stamps stored in SQLite; place by drag.
- Compress / Optimize PDF (B6) — bytes-only pass; reports before/after size.
- Sanitize / Remove hidden information (B20) — rebuild-from-scratch (per P7.5-L-12 discipline carried from B1 Redaction); 13 sanitize categories including metadata, JS, embedded files, outline, AcroForm, layers, structure tree.
- Document Properties dialog (B21) — description / fonts / custom-props / Security tab.
- Password protection / Encryption (B8) — AES-128 / AES-256 via bundled qpdf (Apache-2.0); permission flags (print / copy / modify / annotate / fill-forms / accessibility / page-extract / assemble).
- Auto-bookmarks from headings (B19) — heading heuristic → proposed-bookmark tree → user edits → commit.
- Edit text & images — font swap (B18) — swap an embedded font name to a built-in standard font across the whole document. Honest scope: v0.8.0 swaps by font name; finer-grained scope (this run / this page / whole document) is forward-looking and tracked.
- Action Wizard (B9) — record-replay over the existing
replay-engine. Edit on saved actions is rename-only in v0.8.0 (full op editor tracked). Custom destination folder for the runner is deferred to v0.9.0 (runner currently writes next to each source). - Find / Search (B3) — Ctrl+F overlay; F3 / Shift+F3 next/prev; match counter; case + whole-word toggles; cross-page.
- Spell Check (B14) —
nspell(MIT) + Hunspell en-US (MIT scowl). es-ES is NOT shipped — the Hunspell Spanish dictionary is GPL-3 / LGPL-3 / MPL-1.1 (per the npm registry vet 2026-06-18) and does not meet the project policy of MIT / Apache / BSD permissive-only. Thespell:listLocalesIPC channel returns the verbatim user-facing reason; future locales are tracked.
- Compare Files (B2) — open-pair flow; per-page sequential pairing (orphan pages on the longer side are surfaced); text-diff via
diff-match-patch(Apache-2.0); visual-diff viapixelmatch(ISC) +pngjs(MIT) at a fixed 1600 px render width; lazy per-viewport (no eager rasterize). Honest scope: sequential pairing (no content-hash matching in v0.8.0); LRU eviction across long-doc compares is tracked for v0.9.0 (close the session before reopening to free memory on very long compares). - Read Aloud / TTS (C1) — floating bar; sentence highlighting in the text layer. Per OS: SAPI on Windows;
sayon macOS;espeakon Linux. espeak is GPL-3 — subprocess-only call (we shell out, we don't link, we don't bundle). Linux users install espeak via the system package manager; if absent, the bar surfaces an honest "engine_unavailable" fallback with the install hint. - Preflight (C2) — PDF/X-1a + PDF/X-4 + PDF/A-1b + PDF/A-2b. Honest scope: a compliant subset. v0.8.0 ships ~30 rules across four profiles. Acrobat's Preflight ships hundreds. The header subtitle in the panel reads "Subset of PDF/X-1a, PDF/X-4, PDF/A-1b, PDF/A-2b — see Help for the shipped rule set." See
docs/preflight-spec.mdfor the enumerated rule set.
- Tag PDF tree editor (C3) — sidebar panel surfacing the structure tree; drag-and-drop reparenting; add / rename / delete tags; auto-tag-from-content heuristic (font-size cluster + position-on-page → P / H1 / H2 / Figure / Table). Existing tagged docs default to Save-As-copy to protect the original's tags.
- Reading Order overlay (C4) — numbered badges on each content block; drag-to-reorder; "Auto-detect from layout" button. Honest fallback: when the layout text extractor is not wired (v0.8.0 default), the overlay shows tag-tree order and surfaces a permanent banner "Auto-detect unavailable — layout text extractor not wired in this build."
- Alt Text inspector (C5) — list of figures without alt text; per-figure input; pHash-based "set bulk alt text for similar figures".
- Accessibility Checker (C6) — a SUBSET of WCAG 2.1 + PDF/UA-1. v0.8.0 ships 12 rules; the canonical, regression-tested verbatim subtitle is "Subset of WCAG 2.1 + PDF/UA-1 — see Help for the shipped rule set." Four-state outcome model: pass / warn / fail / unevaluated. The color-contrast spot-sample rule is permanently
unevaluatedunder pdf-lib (a raster engine is the future path). Two extractor-dependent rules (a11y.content.non-text-tagged,a11y.content.scanned-searchable) emitunevaluatedhonestly until the layout extractor is wired. The Export Report dialog (HTML default; JSON for tool integration) lands as Wave 5e. Full rule list indocs/accessibility-authoring-spec.md§6.3.
- Stale
phase3()tooltips and "Coming in Phase N" strings are gone (contract-test enforced). - Insert → Blank Page / Page from File menu items wired to real dispatchers.
- Shapes toolbar button surfaces the shape sub-toolbar.
- New shortcut chords:
Alt+B(Bookmarks edit),Alt+O(Run OCR),Alt+C(Combine),Ctrl+1(Fit width),Ctrl+2(Fit page),Ctrl+/("Find a tool…" palette),Ctrl+F(Find / Search),Ctrl+Shift+A(Run Accessibility Check),Ctrl+Shift+C(Compare Files),Shift+Ctrl+R(Read Aloud). - Menu mirrors for 9 toolbar-only items.
- Cursor / Hand-tool button (V) on the toolbar.
- i18n-wrapped shape sub-toolbar (en-US + es-ES partial).
src/client/tools/registry.ts is now the single declarative source of truth for every user-facing tool surface. Each ToolDef carries a seven-dimension well-marked contract: id, nameKey, tooltipKey, ariaLabelKey, icon, shortcutId, menu.top, surfaces, enabledWhen, dispatch, searchKeywords. The four contract tests in src/client/tools/registry.contract.test.ts enforce: (1) every tool is well-marked across all seven dimensions; (2) every tool with a shortcut advertises it in its tooltip; (3) every shortcut maps to a tool (no orphans); (4) no stale "Coming in Phase N" tooltip survives a shipped phase. The L-007 ratchet (scripts/ratchet-tool-registry-coverage.mjs) runs in pre-commit and CI; any new user-facing surface that bypasses the registry fails the build with a file:line + suggested ToolDef shape. See docs/tool-registry-spec.md and Developer guide → Adding a new tool.
Items explicitly deferred — see docs/project-roadmap.md for the tracked list:
- HTML / RTF / XML / EPS export.
- Audio comment recording.
- PDF Portfolio container.
- New Window / Cascade / Tile multi-doc layouts.
- Native TWAIN scanner binding — Windows WIA ships from 0.7.3; macOS/Linux degrade to
scanner_unavailable. TWAIN remains deferred until a permissive-OSS binding surfaces. Workflow: scan in your OS, then File → Open / drag-and-drop into PDF Viewer Editor. - Distribute Form (email aggregation), Adobe Sign / Send-for-E-Signature, cloud-storage pickers (Dropbox / Drive / OneDrive / Box) — all cloud-adjacent and excluded by the standing principal cloud-exclusion policy.
- JavaScript form actions — by-design stripped on save per security policy §14.6.
- es-ES Hunspell dictionary — license non-permissive (see Spell Check above).
- macOS qpdf bundling — upstream qpdf 11.9.1 publishes no macOS prebuilt binary (verified 2026-06-18). The discovery in
encryption-engine.tsfalls through to systemqpdfon macOS (install viabrew install qpdf);engine_unavailableis surfaced honestly when neither is present. Tracked for Phase 7.6. - Linux qpdf bundling — CONFIG-ONLY / UNVERIFIED per the Phase 7 P7-L-1 convention.
Full license trail in docs/license-manifest.md (Diego, Wave 11). Full code-review verdict in docs/code-review.md §11 (Julian — YELLOW with 1 HIGH follow-up + 3 MED + 2 LOW open; closed L-007 sign-off).
PDF_Viewer_Editor is a desktop PDF tool built with Electron, TypeScript, and React. It uses only permissively licensed PDF libraries (pdf.js, pdf-lib, utif, exceljs, node-signpdf, node-forge, pkijs, asn1js, tesseract.js, docx, pptxgenjs, i18next, react-i18next, electron-updater) — no AGPL components, no commercial SDKs, no per-seat licensing.
Phase 7 is the polish phase. It adds no new document-editing capability; instead it makes the feature-complete app updatable, measurable (opt-in), accessible, and translatable, and adds the build configuration for non-Windows platforms. Open Settings (Ctrl+,) → General to switch the interface language, opt into anonymous telemetry, or pick an update channel; open Help → About to check for updates and see acknowledgments. Each of these surfaces is built to tell you the truth about its limits at the point of action — telemetry is OFF by default and stores counts in memory only; auto-update is wired to the real SuperiorAg/PDF_Viewer_Editor release feed (it contacts the feed and returns an honest result); Spanish is a partial translation sample.
Point releases since the 0.7.0 roadmap close (in order): 0.7.1 resolved the image-export blank-text defect, multi-language OCR download, and the deep modal i18n (816 keys) plus the annotation-surface a11y name and Node-20 toolchain guard. 0.7.2 stood up the real GitHub release channel (SuperiorAg/PDF_Viewer_Editor) and release.yml workflow. 0.7.3 re-cut a clean release after a truncated-source incident and shipped the native WIA scanner addon (David's custom Node-API COM addon — pure N-API, single binary works under Node + Electron, validated against a real Xerox WIA device). 0.7.4 shipped three viewer UX fixes — crisp HiDPI text (DPR-aware raster + offscreen double-buffer), fluid Ctrl+scroll zoom (two-tier displayZoom CSS transform + rAF-coalesce + 120ms debounce commit; horizontally centered via transformOrigin: '50% 0'), and a synced zoom dropdown that tracks the committed zoom %. 0.7.5 shipped the new SSI PDF app icon (white document + folded corner + bold red "PDF" ribbon — multi-res ICO incl. 256px for NSIS, wired into win/nsis/mac/fileAssociations; the "default Electron icon is used" build warning is gone). 0.7.6 layered three polish + closure deltas: cursor-anchored Ctrl+wheel zoom (the point under the cursor stays put across the gesture — per-tick transformOriginOverride on the cursor page + a useLayoutEffect scroll-comp that ratios contentX by newZoom / oldZoom on commit), an ample 13-section in-app Help modal (F1 opens a horizontal-tablist reference covering every workflow — 140 new en-US localization keys; structured TS data behind a discriminated-union sub-section shape), and the functional Combine PDFs end-to-end closure (H-30.1: David's real pdf-lib engine + dialog:pickPdfFiles channel + Riley's modal wire-up — the Phase-1 not_implemented stub is gone from every renderer surface). See Roadmap status for the resolved-vs-deferred breakdown.
The full feature surface across all seven phases:
| Phase | Capability | State in 0.7.6 |
|---|---|---|
| 1 | Open / render / navigate (pan, fluid cursor-anchored Ctrl+scroll zoom, synced zoom dropdown, crisp HiDPI raster, thumbnails); page edit (reorder, insert, delete, rotate); combine end-to-end via the real pdf-lib engine (H-30.1, 0.7.6); bookmarks; print; Print-to-PDF | Live |
| 2 | Edit-replay engine; atomic Save that preserves edits; command-pattern undo/redo; image import (page or overlay); replace-only text edit | Live |
| 3 | AcroForm detect / fill / flatten; form designer (create fields); mail-merge from CSV / XLSX | Live |
| 4 | Annotations (highlight, strikethrough, sticky note, freehand, 7 shapes, text box); visual signatures (typed / drawn / image); PAdES cryptographic signing + audit log | Live |
| 5 | Local OCR via Tesseract.js; searchable-PDF authoring; confidence overlay; language-pack manager (English bundled; all nine additional languages download with real SHA-256 verification) | Live |
| 5.1 | Native WIA scanner addon (Windows) — pure Node-API COM addon, enumerates real devices via IWiaDevMgr2, ADF multi-page → single PDF, optional scan→OCR chain |
Live on Windows; degrades to scanner_unavailable elsewhere |
| 6 | Export to Word / Excel / PowerPoint / image (PNG / JPEG / TIFF) — all six formats fully functional, including standard-font text in image exports | Live |
| 7 | Auto-update client wired to a real GitHub release feed; opt-in telemetry; WCAG 2.1 AA a11y; i18next localization; macOS + Linux build config; new app icon | See Platform support + Roadmap status |
| 7.4 B1 | Redaction (R1 rasterize-redact) — Acrobat-parity destructive redaction tool. Mark rectangle, Apply; redacted pages become rasterized images with marked content burned out and 17 categories of hidden information (metadata, XMP, document-level JavaScript, embedded files, outline, AcroForm, layers, structure tree, threads, catalog Additional Actions, PieceInfo / SpiderInfo, per-page annotations) stripped by rebuild-from-scratch. PAdES signatures on the document are invalidated; the signature audit log records the invalidation | NEW in v0.8.0 |
The Phase 2 architecture (replay engine, atomic save, command-pattern undo), Phase 3 surface (forms + mail merge), Phase 4 surface (visual + PAdES signing), Phase 5 surface (OCR + searchable PDFs), and Phase 6 surface (Office + image export) all carry through unchanged. See the project roadmap for the phased plan and Roadmap status for the honest close-out.
Two Windows builds ship with the v0.8.0 milestone (published as a real GitHub Release at SuperiorAg/PDF_Viewer_Editor — both the NSIS installer and the portable .exe are downloadable directly from there). The v0.8.0 installer carries the bundled qpdf binary (Apache-2.0; ~7.5 MB on Windows) for B8 Password Encryption + B21 Document Properties Security tab.
| File | Type | Notes |
|---|---|---|
pdf-viewer-editor-setup-0.8.0.exe |
NSIS installer (~144 MB) | One-click install, file-association checkbox is on by default (you can uncheck it during install). Adds Start Menu + Desktop entries; both carry the SSI PDF document icon. Includes bundled qpdf for encryption flows. |
pdf-viewer-editor-0.8.0.exe |
Portable executable (~143 MB) | Single file, no install. Stores user data under %APPDATA%/PDF Viewer & Editor/. |
pdf-viewer-editor-setup-0.7.6.exe |
(prior cut, NSIS, ~136 MB) | Pre–Phase 7.5 build, no Bucket B / C parity features. |
pdf-viewer-editor-0.7.6.exe |
(prior cut, portable, ~135 MB) | Same. |
The 0.7.x point releases since the 0.7.0 roadmap close are all additive — no Phase 7 dependency churn (electron-updater, i18next, react-i18next, i18next-resources-to-backend, all MIT and pure JS). Each binary carries a verified, packaged-binary visual proof: 0.7.1 = standard-font text renders in image exports (25,688 dark pixels vs 0/blank in 0.6.1); 0.7.2 = the bundled app-update.yml carries the real SuperiorAg/PDF_Viewer_Editor target (no placeholder) and the in-app update check contacts the live feed; 0.7.3 = window.pdfApi exposes 18 namespaces incl. scan (Phase 5.1 WIA addon ships); 0.7.4 = pixel-level proof of the HiDPI raster crispness, the live ctrl+scroll GPU transform, the centered transform-origin, and the 100% → 177% zoom-dropdown sync; 0.7.5 = the new app icon is embedded (titlebar shot + extraction proof) and the "default Electron icon is used" build warning is gone; 0.7.6 = pixel-level proof of cursor-anchored ctrl+wheel zoom (100% → 133% with the point under the cursor staying put across the gesture), the 13-section in-app Help modal (F1) navigated end-to-end, and a real Combine PDFs run that produces a multi-source merged document from File → Combine PDFs… (the Phase-1 not_implemented stub is gone from every renderer surface). The toolchain ratchets (husky pre-commit + lint-staged + tsc-after-autofix safeguard; all MIT, build/test-only — they do NOT ship in the binary) carry through unchanged.
Upgrading from 0.6.x (or earlier) is non-destructive: recents, settings, bookmarks, saved form templates, the Phase 4 signature audit log, the Phase 5 OCR jobs + results + language packs, and the Phase 6 export job history all survive the schema-v7 migration (migrations/0007_phase7_polish.sql) that runs automatically on first launch. Every 0.7.x → 0.7.y upgrade since 0.7.0 touches no database schema — they are all the same schema v7. The Phase 7 migration is the smallest in the project — it seeds four new key-value rows in the existing settings table (telemetry.optIn, i18n.locale, update.channel, update.lastCheckedAt) and adds no new table and no new column on any prior table. There is deliberately no telemetry_events table — the telemetry buffer is in-memory only by privacy design (see user guide → Telemetry). See docs/build-report.md for the wave-by-wave upgrade story.
The 0.7.x binaries are still unsigned (carrying over from Phases 1–6). The first time you launch the installer or portable build, Windows SmartScreen will show a blue "Windows protected your PC" prompt. Click More info → Run anyway. Code-signing certificate acquisition is a real-world manual step deferred to a later point release (it is also a prerequisite for auto-update to apply downloaded bundles — electron-updater correctly refuses to install an unsigned bundle even when the check/download path against the live feed works; see Roadmap status). The binaries you build from this source tree are exactly what you'd expect; the SmartScreen warning is the cost of skipping the cert for now. The new app icon (the white PDF document with the red "PDF" ribbon shipped in 0.7.5) is embedded in the binary regardless of signing — you'll see it in the titlebar, taskbar, file-association handler, and the NSIS installer/uninstaller chrome.
- Windows 10 1809 or Windows 11 (the verified platform — see Platform support)
- 4 GB RAM minimum (8 GB recommended if you OCR large multi-page documents or export image-heavy PDFs at high DPI — image rasterization at 300+ DPI on a 100-page magazine holds substantial transient memory)
- 200 MB disk for the app, plus working space for the documents you open, any language packs you download, and any exported Office / image files you produce
- For PAdES signing (Phase 4): a PFX/P12 certificate file plus its password — the app does NOT bundle a test cert. See user guide → PAdES signing.
- For RFC 3161 timestamps (Phase 4): a TSA URL of your choice. See user guide → Timestamping.
- For OCR (Phase 5): nothing extra. English ships in the installer; nine additional languages (Spanish / French / German / Portuguese / Italian / Russian / Simplified + Traditional Chinese / Japanese) download on demand from the language manager with real SHA-256 verification (all nine work as of 0.7.1).
- For scanning (Phase 5.1, Windows only): a connected WIA scanner. The native addon ships in the Windows binary and is loaded at runtime; on non-Windows the channel returns
scanner_unavailableand the menu item stays disabled. The headline test target was a Xerox WIA-compliant MFP viaIWiaDevMgr2; ADF multi-page scans compose into a single PDF you can then OCR. See user guide → Scanning from a device. - For Export to Office (Phase 6): nothing extra. The Word / Excel / PowerPoint / image writers ship inside the binary.
- For localization (Phase 7): nothing extra. English (en-US) is the default; Spanish (es-ES, a partial translation sample) ships in the binary and switches live from Settings → General.
Honesty first: Windows is the only platform verified to run. macOS and Linux build configuration ships in 0.7.0, but no macOS or Linux binary has been produced and launched on real hardware.
| Platform | Build config | Produced + launched | Status |
|---|---|---|---|
| Windows (x64) | NSIS installer + portable .exe |
YES — the packaged 0.7.6 binary is verified with pixel-level evidence at every point release (0.7.1 image-export glyphs, 0.7.2 real-feed update check, 0.7.3 window.pdfApi end-to-end + Phase 5.1 WIA addon enumerating a real scanner, 0.7.4 HiDPI raster + fluid centered zoom + 177% dropdown sync, 0.7.5 embedded app icon in the titlebar, 0.7.6 cursor-anchored zoom + 13-section Help modal + functional Combine end-to-end). All evidence PNGs in release/wave-*.png |
VERIFIED |
| macOS (universal: x64 + arm64) | dmg + zip (electron-builder.yml, hardenedRuntime: true) |
NO — config-only; not built, not launched | CONFIGURED BUT UNVERIFIED |
| Linux (x64) | AppImage + deb (electron-builder.yml, category: Office) |
NO — config-only; not built, not launched | CONFIGURED BUT UNVERIFIED |
The macOS and Linux configs are produced by CI build configuration and have not been tested on real machines. They are structurally complete and reusable, but the project's locked decision (P7-L-1: configure all, verify Windows only) is deliberate — a green CI package step does not prove a binary runs. The riskiest unverified surface is the native-module rebuild: better-sqlite3 (the database layer) must compile against each target platform's Electron ABI, and @napi-rs/canvas (the raster pipeline behind OCR + image export) must merge both arm64 and x64 prebuilds into the macOS universal binary. If either fails to rebuild on a real host, the app would crash on launch. Verifying macOS + Linux on real hardware (with a launch screenshot, mirroring the Windows verification discipline) is the headline Phase 7.1 work item.
If you want to run on macOS or Linux today, build from source on that host (npm install && npm run dist) and treat the result as unverified — please file an issue with what you observe, since that is exactly the verification Phase 7.1 needs.
For the full walkthrough, see docs/user-guide.md. Headline use cases:
- Open and read a PDF — file dialog, drag-and-drop, or the recents menu.
- Navigate with zoom, pan, and thumbnails — keyboard shortcuts for everything.
- Edit pages in memory — drag-reorder, insert blank, delete, rotate, insert image as page or overlay, edit text on existing pages.
- Combine multiple PDFs — merge two or more files into one.
- Annotate — highlight, sticky note, text box, freehand, and seven shape tools.
- Redact pages — NEW in Phase 7.4 B1 (v0.8.0). Mark rectangular regions on one or more pages and Apply to permanently remove the content. Redaction is destructive — the redacted pages are rebuilt as raster images and the marked content is gone from the file. Document metadata, embedded files, JavaScript, document outline, AcroForm objects, and per-page annotations on redacted pages are stripped at the same time. Any existing PAdES signatures on the document are invalidated and the signature-audit log records the invalidation. Use Save As before you Apply — there is no undo path.
- Capture and place a signature — three modes (typed / drawn / image).
- Sign cryptographically with PAdES — 3-step wizard.
- Review the signature audit log — local "what have I signed and when?" panel.
- Run OCR on a page or document — 4-step wizard; produces a searchable PDF with an invisible text layer aligned to recognized words.
- Manage language packs — English ships bundled; other languages download on demand with SHA-256 verification.
- Toggle the OCR confidence overlay — orange boxes over low-confidence recognized words. Improved in 0.7.18: the overlay now also restores from disk on reopen (so a doc you OCR'd earlier shows its overlay immediately when you reopen it, without re-running OCR), and the boxes position correctly on rotated pages (0 / 90 / 180 / 270 degrees).
- Browse OCR results — 4th sidebar tab with per-page word counts, mean confidence, searchable word list.
- Export to Word / Excel / PowerPoint / image — NEW in 0.6.0. 4-step wizard (Format → Quality + options → Confirm → Background). Output is a new file alongside the source; the source PDF is never mutated.
- Browse the Exports sidebar tab — NEW in 0.6.0. 5th sidebar tab listing in-flight + recent export jobs with Cancel / Open / Show in folder / Re-run actions.
- Working with forms — detect, fill, and save AcroForm fields (text / checkbox / radio / dropdown / date / signature placeholder).
- Designing forms — toggle the designer (Ctrl+Shift+F), click-to-place new fields, edit properties, save reusable templates.
- Mail merge — 4-step wizard (Ctrl+M): template → data source (CSV or XLSX) → column mapping → output (folder or concatenated, optionally flattened).
- Working with bookmarks — create, rename, nest, and reorder a full bookmark tree.
- Save the result — produces a valid PDF with all edits, annotations, form values, signatures, AND any OCR text-behind-image layer preserved. (Export is a separate operation; Save is unchanged.)
- Print to PDF with optional flatten — exports via pdf-lib (default) or Chromium (fallback); flatten-on-output checkbox available.
- Print — dispatches to the system print dialog via Electron
webContents.print(). - Change the interface language — NEW in 0.7.0. Settings → General → language picker. English (default) + Spanish (a partial translation sample — some strings stay English).
- Opt into anonymous telemetry — NEW in 0.7.0. OFF by default. Anonymous feature-usage counts only; nothing leaves your machine; inspect the buffer in the debug panel.
- Check for updates — NEW in 0.7.0. Help → About → Check for updates. The update channel is a placeholder until the project is published — see the honest placeholder state.
- About modal — NEW in 0.7.0. Version, acknowledgments, and the update-status area.
- Keyboard navigation + screen-reader support — NEW in 0.7.0. WCAG 2.1 AA for the critical paths; tested with Windows Narrator. Some pointer-centric gaps documented.
- Undo / Redo — across page, annotation, image, text, bookmark, form-design, Phase-4 shape + visual-signature, and Phase-5 OCR operations. Export is NOT undoable — the exported file lives on disk, separate from the source document's edit history (the source itself is untouched).
The 7-phase roadmap is implementation-complete as of 0.7.0 (Julian's Wave 29 review verdict: GREEN). Six post-roadmap point releases (0.7.1 → 0.7.6) cleared every backlog item that was not blocked on physical hardware: image-export blank-text defect, multi-language OCR download, deep-modal i18n, annotation a11y name, Node-20 toolchain guard, the real GitHub release channel + release.yml workflow, the native WIA scanner addon (Phase 5.1), HiDPI text crispness + fluid centered Ctrl+scroll zoom + synced zoom dropdown, the new app icon, cursor-anchored Ctrl+wheel zoom, the 13-section in-app Help modal, and the H-30.1 Combine-PDFs end-to-end closure (the Phase-1 stub is gone). The resolved backlog lists what each point release closed, and Deferred — requires external resources lists the two items that genuinely cannot be cleared without resources outside the codebase (real Mac/Linux hardware + a Windows code-signing cert).
All seven phases are implemented. Viewing (with crisp HiDPI text, fluid centered Ctrl+scroll zoom as of 0.7.4 and cursor-anchored zoom as of 0.7.6, and a synced zoom dropdown), page editing, combine (now fully functional end-to-end via a real pdf-lib engine — H-30.1 closed in 0.7.6), bookmarks, print, Print-to-PDF, annotations, forms, mail-merge, visual + PAdES signing, OCR (with multi-language download), native WIA scanning on Windows, and Office + image export (all six formats, including standard-font text in image exports) are all live (with the per-feature trust-floor caveats documented in the user guide). Phase 7 adds the auto-update client (now wired to a real release feed), opt-in telemetry, WCAG 2.1 AA accessibility, the i18next localization framework, macOS + Linux build config, and a comprehensive 13-section in-app Help modal (F1) shipped in 0.7.6.
Redaction is the most-cited Acrobat parity gap from Riley's parity audit, and v0.8.0 closes it with an R1 rasterize-redact engine. Open a document, click the Redact toolbar button (or Tools → Redaction → Mark Rectangle…), draw rectangles on any pages you want redacted, then click Apply to commit. The Apply step is irreversible and is gated behind a confirm modal that calls out the trust-floor consequences before any bytes change. See user guide → Redaction for the workflow and the developer guide → Redaction for the engine architecture.
Three honest things about R1 redaction you should know up front:
- It is destructive. Once you Apply, the redacted pages are rebuilt as raster images and the original content is gone from the saved file. The marked content cannot be recovered by copy-paste, "search inside file", or any text-extract path — that is the point. Save As first if you want to keep the original; the editor does NOT add a hidden backup.
- Redacted pages lose searchability. R1 replaces every redacted page's content stream with a single raster image, which means the non-redacted text on those pages is no longer searchable until you re-run OCR. The Apply confirm modal says so; the post-Apply warning list reminds you again. Run Tools → Run OCR… on the redacted output if you need search.
- Applying redaction invalidates any existing PAdES signatures. If the document carries one or more digital signatures, the Apply confirm modal lists the affected signature fields and you must explicitly confirm before the engine runs. The signature audit panel will then show "Invalidated by redaction on YYYY-MM-DD" on each affected row. This mirrors the OCR pattern from Phase 5.
The R2 "content-stream walker" variant — which preserves searchability of non-redacted text by editing the content stream directly — is deferred to a future phase behind a real fixture corpus and a content-stream-parser test surface. Mark Text (selection-based redaction) is also deferred to that future phase; v1 ships Mark Rectangle only.
Keyboard shortcuts: Shift+R arms the Mark Rectangle tool (opens the sub-toolbar if it isn't open); Ctrl+Shift+Y opens the Apply confirm modal when at least one mark is pending. Both shortcuts mirror Acrobat.
These are surfaced at the point of action in the app and explained in full in user guide → Phase 7 trust floor:
- Telemetry is OFF by default. When enabled, it records anonymous feature-usage counts only — never document content, file paths, or personal information. Nothing leaves your machine at all; the transport is an in-memory buffer you can inspect. There is no analytics endpoint, no third-party SDK, no
telemetry_eventstable. - The auto-update channel is real but the build is unsigned. As of 0.7.2 the update client is wired to the real
SuperiorAg/PDF_Viewer_EditorGitHub release feed — "Check for updates" actually contacts the feed and returns an honest result (up-to-date,update-available, or a real feed/network error — never a fake "you're up to date"). However,electron-updatercorrectly refuses to apply an unsigned update bundle until a code-signing certificate is in place; the check + download paths work, the install path does not. - macOS and Linux builds are UNVERIFIED. They are produced by the build config but have not been tested on real hardware — see Platform support.
- Spanish (es-ES) is a translation sample, not a complete localization. It exists to prove the localization framework works (~68% of strings translated, on a denominator that grew to 816 keys in 0.7.1); the rest fall back to English. It is not a complete professional translation.
Two more Phase 7 disclosures: accessibility is audited to WCAG 2.1 AA for the critical paths with documented pointer-centric gaps (freehand annotation drawing, drawn-signature canvas — see user guide → Accessibility); and a code-signing certificate remains the real-world manual step that auto-update requires before it can apply downloaded bundles in production.
The post-roadmap point releases closed these previously-documented follow-ups. They are no longer pending.
| Item | Was | Now |
|---|---|---|
| Image-export standard-font text (Phase 6.2) | Standard-font text (Helvetica / Times / Courier) came out blank in image exports | FIXED in 0.7.1. Image export (PNG / JPEG / TIFF) renders standard-font text. Root cause was a file://-URL-vs-fs.readFile ambiguity in the pdf.js font factory; verified from the packaged 0.7.1 binary (25,688 dark pixels versus 0 blank). All six export formats are now fully functional |
| Word / PowerPoint / image export end-to-end (Phase 6.1) | docx / pptx / image depended on the production pdf.js source-loader wire | FIXED in 0.7.1. All six formats (docx / xlsx / pptx / PNG / JPEG / TIFF) produce valid output end-to-end |
| Non-English OCR language packs (Phase 5.1.x) | Downloads failed with pack_integrity_failed — the catalog shipped TBD-FILL-AT-RELEASE SHA-256 sentinels for the nine non-bundled rows |
FIXED in 0.7.1. All nine downloadable languages (spa / fra / deu / por / ita / rus / chi_sim / chi_tra / jpn) have real SHA-256 hashes; multi-language download works |
| Deep modal-step i18n (28c) | The deep Phase-4..6 modal-step prose was not yet t()-extracted |
FIXED in 0.7.1. i18n extraction completed: 482 → 816 keys; es-ES is ~68% (high-traffic surface translated, the rest falls back to English) |
| Annotation-layer accessibility | The freehand drawing surface was a nameless static <div> with a scoped a11y-lint disable |
FIXED in 0.7.1. The drawing surface now has role="application" + an accessible name + a documented keyboard alternative (highlight / text / sticky / shape annotations via toolbar + Inspector) |
| Auto-update unsaved-work install gate (H-29.1) | quitAndInstall had no dirty-document prompt |
FIXED end-to-end in 0.7.2+ (main-process gate + renderer dirty-state gate, both reachable now that the real publish target exists). See the developer guide |
| Test env-skew (better-sqlite3 Node-24 ABI) | ~350 db tests failed under Node 24 with ERR_DLOPEN_FAILED |
FIXED in 0.7.1. Node 20 is the enforced baseline (L-003) with a check-node.mjs pre-test guard and a non-destructive rebuild escape hatch; the full suite runs green via the documented path. The latent CI Node-ABI bug was also fixed |
| Lint-debt re-accumulation | npm run lint carried pre-existing --max-warnings 0 debt |
ADDRESSED in 0.7.1. A husky pre-commit hook runs lint-staged + a tsc-after-autofix safeguard (the safeguard catches consistent-type-imports autofix breaking type-only imports of pdf-lib runtime values) |
| Real auto-update publish target (Phase 7 obligation #2) | The app-update.yml block carried a PLACEHOLDER owner/repo and the controller short-circuited to update_not_configured |
DONE in 0.7.2. Real publish target is SuperiorAg/PDF_Viewer_Editor (releaseType: draft for publish safety — a human promotes each release). .github/workflows/release.yml triggers on v*.*.* tags. The in-app check now contacts the live feed and returns an honest result (up-to-date, update-available, or a real network/feed error). Auto-update install still needs a code-signing cert — see Deferred |
| Native WIA scanner (Phase 5.1) | No MIT-licensed Node WIA binding existed; the menu item was disabled with a tooltip | DONE in 0.7.3. David built a custom pure-Node-API COM addon (native/wia-scanner/). IWiaDevMgr2::EnumDeviceInfo enumerates devices; CreateDevice + IWiaTransfer::Download acquires pages; ADF multi-page composes into a single PDF via pdf-lib; the output handle chains directly into the OCR pipeline for scan→searchable-PDF. Pure N-API means a single binary works under Node + Electron with no two-ABI dance (unlike better-sqlite3). Validated end-to-end against a real Xerox WIA scanner. On macOS / Linux the loader degrades to scanner_unavailable (the menu item stays disabled, the rest of the app is unaffected) |
| Viewer UX — blocky HiDPI text + jerky ctrl+scroll zoom + zoom dropdown didn't track | Page raster was 1× backing store regardless of devicePixelRatio; ctrl+scroll triggered per-tick re-rasters with a snap-back jump; the status-bar zoom % went stale during a gesture |
DONE in 0.7.4. DPR-aware raster + offscreen double-buffer for crisp HiDPI text; two-tier displayZoom CSS transform driving an instant live zoom while pdf.js re-rasters ONCE on the 120ms debounce commit; transformOrigin: '50% 0' keeps the page horizontally centered during the gesture (no off-center drift / snap-back); the zoom dropdown flips to the committed % on gesture end. Pixel-level proof captured from the packaged 0.7.4 binary at 177% zoom |
| App icon — "default Electron icon" build warning + default Electron-atom in title/taskbar | The build/ icon assets existed but were UNTRACKED and not wired into electron-builder.yml |
DONE in 0.7.5. New SSI brand icon committed (build/{icon.ico,icon.png,icon.icns,icon.svg,ICON-README.md}) and wired into electron-builder.yml (win.icon, nsis.installerIcon/uninstallerIcon, win.fileAssociations[0].icon, mac.icon). The 7-layer multi-res ICO carries 256px (NSIS hard requirement). The "default Electron icon is used" warning is gone from the build log; embedded-icon extraction from the binary returns the new red-ribbon PDF document, not the Electron atom |
Combine PDFs — Phase-1 not_implemented stub (H-30.1) |
pdf:combine returned a Phase-1 not_implemented stub even though the walking-skeleton milestone, the Combine modal, the help modal, and the user guide all claimed it worked; the renderer surfaced a "Combine failed" toast in production |
DONE in 0.7.6. David shipped a real pdf-lib combine engine (src/main/pdf-ops/combine.ts) + a path-only file picker channel (dialog:pickPdfFiles, multi: true) + 24 new tests. Riley wired the modal end-to-end against the new contracts: Combine PDFs… now opens a multi-file picker, de-dups by absolute path, and concatenates the requested page ranges into a fresh "Combined Document.pdf" the user can Save As. JS / open-action / outline strip is automatic-by-construction via pdf-lib's copyPages (page-tree only — the source catalog's document-level entries never come along). The "Phase 1 stub" string is gone from every renderer surface |
| Viewer UX — cursor-anchored Ctrl+wheel zoom | Ctrl+wheel zoom (made fluid in 0.7.4) still expanded the page around the horizontal midline, not the cursor — the point under the cursor drifted as the user zoomed in past 110% | DONE in 0.7.6. Cursor anchoring layered on top of the 0.7.4 two-tier zoom: every wheel tick captures a CursorAnchorRef (clientX/Y, scroller scrollLeft/Top, contentX/Y at base zoom, page index + page-local pixels); during the gesture a per-frame transformOriginOverride rewrites the cursor page's transform-origin to the anchor point (other pages keep '50% 0' = no per-frame style churn); on the 120ms debounce commit a useLayoutEffect ratios the scroller's scrollLeft/scrollTop by newZoom / oldZoom so the anchor stays put. Three new pdf-viewer tests pin zoom-in commits + scrolls, zoom-out commits + scrolls, and plain wheel no-op. Verified at the packaged binary at 100% → 133% — the anchor point stayed under the cursor across six wheel ticks |
| In-app help — single-screen modal | The Help modal was a single short screen; users hit F1 expecting a thorough reference and got a thin overview | DONE in 0.7.6. Promoted to a 13-section horizontal-tablist reference: Getting started, Navigation, Editing pages, Annotations, Forms, Signing, OCR, Scanning, Export, Combine, Settings, Troubleshooting, About. Structured TS data behind a discriminated-union sub-section shape (prose / bullets / steps); 140 new en-US localization keys under modals:help.*; coverage test stays green at 58% es-ES (fallback guarantee intact). The Help modal echoes the trust-floor honesty language used elsewhere in the user guide |
| OCR pipeline closure (Phase 5.2) | After the v0.7.13->v0.7.17 OCR-chain arc, three gaps remained: (1) reopen a doc and the confidence overlay was empty until you re-ran OCR; (2) PDFs with non-embedded standard fonts (Helvetica/Times/Symbol) OCR'd at very low confidence because the rasterizer left glyphs blank; (3) the overlay's boxes positioned wrong on rotated pages | DONE in 0.7.18. (1) New ocr:listResultsByJob IPC channel + OcrResultsRepoBridge.listPageResultsByJobId parses words_json into OcrPageResult[]; loadOcrResultsThunk chains the call so reopens hydrate pageResultsByPage and the overlay repaints automatically. (2) The OCR rasterizer now passes standardFontDataUrl + StandardFontDataFactory + cMapUrl + cMapPacked + CMapReaderFactory to pdfjs.getDocument(...) and force-warms font generators via page.getOperatorList() before page.render() — mirrors the export path's v0.6.1 fix. Regression test asserts dark-pixel count > 50 on a Helvetica PDF. (3) OcrConfidenceOverlay accepts a rotation: 0|90|180|270 prop and re-projects pdf-space rects to CSS-pixel space per orientation. PdfCanvas wires props.page.rotation at the call site. +13 net tests, 1921/1921 PASS |
These two items cannot be cleared by the engineering swarm. Each is blocked on a resource or decision outside the codebase, not on remaining work the team can simply do. They are tracked honestly as deferred, not as a to-do list.
| Item | Why it is blocked | Honest current status |
|---|---|---|
| macOS / Linux verification | Requires real Mac and Linux hardware to build and launch on; the build host is Windows-only and a green CI package step does not prove a binary runs | Configs exist (dmg / zip / AppImage / deb) and are produced by the CI build config, but untested on real hardware — see Platform support. The mac icon.icns is wired (mac.icon: build/icon.icns) and the bytes are valid (icns magic + correct declared length), but the embedded-in-a-real-.app proof is a future real-Mac step |
| Windows code-signing certificate | Acquiring an Authenticode certificate is a business/legal step (CA selection, identity verification, key custody policy) outside the engineering swarm's authority. release.yml already has the WIN_CSC_LINK / WIN_CSC_KEY_PASSWORD lines staged as commented placeholders |
The check + download paths against the live release feed work today; only auto-INSTALL of a downloaded update needs the cert. electron-updater correctly refuses to apply an unsigned bundle. Windows SmartScreen will show "unknown publisher" on first run for every 0.7.x binary until the cert is in place |
The full per-feature limitation tables live in the user guide. The phase trust-floor banners surface the realities up front; see user guide → Phase 7 trust floor, Export trust floor, OCR trust floor, and PAdES trust floor for the full mappings.
- Layout-preserving conversion is best-effort. Complex multi-column layouts, embedded vector graphics, intricate tables (especially borderless or merged-cell), and decorative typography may not convert faithfully. The fast
text-onlytier is even more reductive — accurate text in a flat structure with no images, no tables, no headings. Review the output before relying on it for downstream work. - All six export formats now produce valid output end-to-end. As of the 0.7.1 backlog-fix wave, docx / xlsx / pptx / PNG / JPEG / TIFF all work — the production pdf.js source-loader wire landed and the image-export standard-font glyph defect (text came out blank) is fixed. Verified from the packaged 0.7.1 binary: a Helvetica/Times/Courier text page renders to PNG with 25,688 dark pixels (it produced 0 / blank in 0.6.1), and xlsx + docx both write valid OOXML.
- ExportQueue concurrency is currently inline (concurrency=1 IS the contract, but inline execution is not the documented FIFO queue). Julian's Wave 25 H-25.1 finding flagged that the
ExportQueuefromdocs/architecture-phase-6.md §4.6is documented but not implemented. The engine today runs every IPC call inline and rejects new requests at thequeue_fullHARD CAP (default 50). The actual FIFO queue module (~50 LOC) so concurrent requests against the same output path no longer race the.export-tempfile is a later follow-up. The modal surfaces a warning if you try to export to a path that is already running. - Export does NOT mutate the source PDF. The exported docx / xlsx / pptx / image is a NEW file at the path you choose; the source PDF on disk is unchanged. Any prior PAdES signature on the source PDF stays valid (it was never touched). The exported Office file has no signature semantics — those formats either don't support PAdES (docx, xlsx, pptx) or are unsigned by definition (images). If you need a signed Office document, sign it in Office after export.
- Conversion time depends on document complexity. Plan for ~5-30 seconds per page on the layout-preserving tier, ~0.5 seconds per page on the text-only tier. A 100-page magazine with full-color images at layout-preserving can take 30+ minutes; the cancel button is always available; partial output is cleaned up automatically on cancel.
- XFA form values do NOT export. Phase-3-flattened AcroForms produce inline text in the output. XFA forms (read-only in Phase 3) are inaccessible to pdf.js's text extraction; the engine sees only the static template. Workaround: save with the form flattened via
forms:flattenForExportfirst, then export. - OCR status determines text fidelity. If the source PDF has been OCR'd (Phase 5), text exports as native selectable text. If the source is image-only and was NOT OCR'd, the Word / PowerPoint output is mostly raster image with no selectable text. The engine does NOT auto-OCR before export (that would be a silent mutation of the source). Run OCR first, save the searchable PDF, then export.
- macOS / Linux packaging is config-only. Unchanged in 0.7.0 — the
electron-builder.ymlprofile is structurally complete for macOS + Linux, but only Windows is verified. See Platform support; real-hardware verification is the Phase 7.1 work item.
Other carried limitations (full text editing, dark mode, third-party PAdES verification) — see user guide → Known limitations and the roadmap. Items that Phase 7 addressed (accessibility audit, localization, auto-update client, cross-platform build config) are covered in Roadmap status above with their honest partial/unverified states.
- The Phase 5 OCR trust-floor banner (four obligations: low-confidence-may-be-wrong, no-cloud-upload, OCR-text-becomes-part-of-PDF, re-OCR-duplicates) continues to surface on every OCR flow.
- v0.5.0's English-only language-pack-download story is resolved as of 0.7.1: the catalog now carries real SHA-256 hashes for all nine non-bundled languages, so multi-language download works (see Resolved in the 0.7.1–0.7.6 backlog-fix waves).
- Phase 5.1 native WIA scanner integration is RESOLVED as of 0.7.3 — a custom pure-Node-API COM addon (
native/wia-scanner/) ships, enumerates real WIA devices on Windows (validated against a Xerox MFP), and acquires ADF multi-page scans into a single PDF that chains directly into the OCR pipeline. On macOS/Linux the loader degrades toscanner_unavailable(the menu item stays disabled). See user guide → Scanning from a device.
- The Phase 4 PAdES trust-floor banner (four obligations: invalidate-on-edit, cert-zero-on-finally, no-default-TSA, verify-is-informational) continues to surface in 0.6.0 on every signing flow.
- The Phase 4 signature audit log table is unchanged in 0.6.0 (Phase 6 does not touch
signature_audit_log— export is read-only on the source).
- The Phase 3 Forms sidebar status banner's three honesty warnings (JS strip, XFA read-only, signed-fields-invalidated) continue to surface in 0.6.0 on every affected document.
- Mail merge with optional output flatten ships unchanged in 0.6.0.
- MIT
LICENSEfile added at the repo root in Phase 1.1 (matches the existingpackage.jsondeclaration). - Renderer typecheck TS4023 cascade cleared in Phase 1.1.
For full local development setup, build, test, and release instructions see docs/developer-guide.md. The short version:
git clone https://github.com/SuperiorAg/PDF_Viewer_Editor.git
cd PDF_Viewer_Editor
npm install # postinstall runs electron-builder install-app-deps; prepare installs husky hooks
npm run dev # launches Electron with hot reload
npm test # vitest 2.x unit + integration suite (~1790 passing / 5 pre-existing brittle jsdom failures hardened by the 0.7.5 maintenance pass; gated by a pretest Node-version guard)
npm run dist:win # builds release/*.exe on Windows (or push a v*.*.* tag to publish via .github/workflows/release.yml)The remaining brittle test failures are jsdom environment limitations (canvas in use-signature-canvas; duplicate-element ambiguities in annotation-summary-panel, signature-audit-panel, and pades-sign-modal ×2). They were hardened by the 0.7.5 maintenance pass (cross-platform path sanitizer test + targeted RTL fixes) — see the most recent build-report entries. Note on lint: the 0.7.1 backlog-fix wave added a husky pre-commit hook (lint-staged + a tsc-after-autofix safeguard) to prevent lint-debt re-accumulation — see developer guide → CI lint debt. The husky hook is verified active as of the 9ebbf92 commit ("fix(lint): clear import/order warnings; ensure husky hook active").
Use Node 20 LTS — it is the enforced baseline (lock L-003). better-sqlite3 ships matched Electron-ABI and Node-20-ABI prebuilds; Node 24 has neither, which silently broke ~350 db tests across several waves. A pretest guard (scripts/check-node.mjs) now stops the suite with a recovery message when the host Node can't load the binding; on a Node-24-only host, the documented non-destructive escape hatch is node scripts/rebuild-native-for-node.mjs && npm test (then --electron to restore the packaging binary). The CI matrix locks Node 20. See developer guide → Prerequisites and developer guide → Node 24 vs Electron 30 ABI.
| Doc | What it covers |
|---|---|
docs/project-roadmap.md |
Phases 1–7, what ships when |
docs/phase-3-release-notes.md |
What changed in 0.3.0 — historical |
docs/phase-2-release-notes.md |
What changed in 0.2.0 — historical |
docs/build-report.md |
Wave-by-wave build history, every verdict (Phase 7 sections at the end: Wave 27 Riley design, Wave 28a/28b David/Ravi/Riley implement, Wave 29 Diego v0.7.0 packaging + Julian review, Wave 30 Nathan docs) |
docs/code-review.md |
Julian's reviews — Phase 1 + Phase 2 + Phase 3 + Phase 4 + Phase 5 + Phase 6 + Phase 7 (Wave 29 — the final roadmap-phase audit, GREEN) |
ARCHITECTURE.md |
Phase 1 system design, security floor, the four locked decisions |
docs/architecture-phase-2.md |
Phase 2 — edit-replay engine, lynchpin |
docs/architecture-phase-3.md |
Phase 3 — forms, HYBRID commit boundary, mail-merge runner |
docs/architecture-phase-4.md |
Phase 4 — visual + PAdES signatures, expanded annotation toolset, signature audit log |
docs/architecture-phase-5.md |
Phase 5 — file-import OCR via Tesseract.js, text-behind-image authorship, language pack management |
docs/architecture-phase-6.md |
Phase 6 — Export to Office and image formats: per-page streaming engine, 8-step layout extractor, line-grid table detector, CTM-tracking image extractor, four writers (docx / exceljs / pptxgenjs / @napi-rs/canvas + utif), background queue, schema v6 (Wave 23 design) |
docs/architecture-phase-7.md |
Phase 7 — Polish & Cross-Platform: macOS + Linux build config (unverified), auto-update via electron-updater (placeholder publish target), opt-in/default-OFF telemetry, WCAG 2.1 AA a11y, i18next localization, schema v7 (settings-keys-only), the sixth trust-floor instance (Wave 27 design) |
docs/a11y-audit.md |
Phase 7 — WCAG 2.1 AA accessibility audit: eight critical paths, the ARIA tab-pattern remediation map, Windows Narrator expectations, honest known gaps |
docs/i18n-strategy.md |
Phase 7 — i18next localization design: 8 namespaces, typed keys, lazy loading, the es-ES proof locale, pluralization + Intl formatting, RTL deferral |
docs/export-engine.md |
Export engine deep dive — single-funnel pipeline, layout-detect algorithm (X-clustering for columns, MODE-of-bucketed-sizes for headings), table-detect algorithm (5-step line-grid), image-extract (OPS.paintImageXObject walk + CTM stack), per-format writers, atomic .export-temp → rename, job lifecycle, trust-floor obligations |
docs/ocr-engine.md |
OCR engine deep dive |
docs/signature-engine.md |
Signature engine deep dive |
docs/edit-replay-engine.md |
Edit-replay engine deep dive |
docs/form-engine.md |
Form engine deep dive |
docs/api-reference.md |
IPC channel reference card for contributors (Phase 1 + 2 + 3 + 4 + 5 + 6 + 7: update:* / telemetry:* / i18n:*) |
The project itself: MIT — see LICENSE at the repo root. The MIT file was added in Phase 1.1; package.json declares the same ("license": "MIT").
For the licenses of every dependency that ships in the binaries (and the qpdf vendored binary), see the canonical docs/license-manifest.md (Diego, Phase 7.5 Wave 11; signed-off GREEN, audit partner Julian).
The headline Phase 7.5 additions are all permissive:
pdf-libMIT,pdfjs-distApache-2.0,tesseract.jsApache-2.0,electronMIT (unchanged from prior phases).diff-match-patchApache-2.0,pixelmatchISC (the Wave 7 brief said MIT — actual published license is ISC, surfaced honestly per the manifest §1),pngjsMIT — Compare Files (B2).nspellMIT,dictionary-en(MIT AND BSD)— Spell Check (B14).dictionary-esREJECTED on license grounds (GPL-3 / LGPL-3 / MPL-1.1).qpdf11.9.1 Apache-2.0 — bundled binary for encryption + Document Properties Security tab. Per-OS bundling: Windows YES (verified; ~7.5 MB), Linux YES (config-only / unverified per P7-L-1), macOS NO (upstream publishes no macOS binary; falls back to system PATH).- Linux TTS uses
espeak(GPL-3) subprocess-only — we shell out viachild_process.spawn('espeak', args), never link, never bundle. Approved on a no-binary-redistribution basis (FSF-endorsed aggregate-works pattern). The packaging config is hard-constrained never to addespeak*toelectron-builder.yml extraResources.
All deps permissive — no AGPL or commercial SDKs. The earlier LICENSES.md (Phase 1.1 inventory) is unchanged and continues to ship; the new authoritative license trail for Phase 7.5 lives in docs/license-manifest.md.
For the full historical inventory:
The legacy LICENSES.md summary remains: Every direct and transitive dependency is under a permissive license (MIT, Apache-2.0, BSD, ISC, BlueOak-1.0.0, Python-2.0, or similar). No AGPL/GPL/commercial code is bundled. The four new Phase 7 direct dependencies are all MIT and pure-JS (no native module): electron-updater (the auto-update client), i18next (the localization engine), react-i18next (the React bindings — peer-requires i18next ≥ 26.2), and i18next-resources-to-backend (the lazy locale loader). Diego's Wave 29 license walk over the full reachable subtree from these four roots scanned 23 packages — all permissive (MIT / ISC / BlueOak-1.0.0 / Python-2.0), zero AGPL/GPL/LGPL/EPL ingress. Earlier-phase additions remain in place: docx + pptxgenjs (MIT, Phase 6 writers), exceljs / @napi-rs/canvas / utif (MIT, reused across phases). The pre-existing buffers@0.1.1 UNKNOWN-license flag from Phase 3 is unchanged.
PDF_Viewer_Editor stands on permissive open-source work by:
- pdf.js (Mozilla, Apache-2.0) — page rendering; Phase 6 layout + text + operator-list + image extraction inside the export engine
- pdf-lib (MIT) — page-tree editing, edit-replay engine, AcroForm read/fill/flatten/create, visual signature widgets (Phase 4), text-behind-image authoring (Phase 5); Phase 6 reads source-PDF page sizes + form-field objects
- tesseract.js (Apache-2.0) — local OCR engine (Phase 5)
- @tesseract.js-data/eng (Apache-2.0 trained data) — bundled English language pack (Phase 5)
- @napi-rs/canvas (MIT) — Skia-backed canvas for OCR page rasterization (Phase 5); Phase 6 image-format rasterization at chosen DPI
- docx (MIT) — Word document writer (Phase 6); Acknowledgment: Dolan Miu
- pptxgenjs (MIT) — PowerPoint presentation writer (Phase 6); Acknowledgment: Brent Ely
- exceljs (MIT) — XLSX read for mail-merge data sources (Phase 3); Phase 6 xlsx writer (streaming write API for memory-bounded large workbooks)
- utif (MIT) — TIFF first-page decoding (Phase 2); Phase 6 multi-page TIFF encode (
utif.encodeImage+utif.encodefor multi-page bundling) - node-signpdf (MIT) — primary PAdES cryptographic signing engine (Phase 4)
- node-forge (BSD-3-Clause) — PFX / ASN.1 / PKCS#7 (Phase 4)
- pkijs (BSD-3-Clause) — X.509 + CMS for the manual PAdES fallback engine (Phase 4)
- asn1js (BSD-3-Clause) — ASN.1 codec (Phase 4)
- electron-updater (MIT) — auto-update client (Phase 7); wired to the real
SuperiorAg/PDF_Viewer_EditorGitHub release feed as of 0.7.2 (releaseType: draftfor publish safety; check/download paths against the live feed work, the install path needs a code-signing cert) - i18next (MIT) — localization engine: interpolation, plurals, namespaces, fallback (Phase 7)
- react-i18next (MIT) — React bindings for i18next:
useTranslation,<Trans>, Suspense integration (Phase 7) - i18next-resources-to-backend (MIT) — lazy
import()backend for code-split locale chunks (Phase 7) - Electron (MIT) — desktop shell
- React (MIT) — UI layer
- Redux Toolkit (MIT) — state + undo/redo
- better-sqlite3 (MIT) — recents/settings/bookmarks/form-templates/signature-audit-log/ocr-jobs/export-jobs persistence
- dnd-kit (MIT) — drag-and-drop reorder and bookmark tree drag-nest
- Vite and electron-builder (MIT) — build + packaging
- vite-plugin-static-copy (MIT) — build-time pdfjs font + cmap asset copy (Phase 4.1.1); the OCR language-pack-catalog copy in Phase 5; carries through unchanged in Phase 6
- vitest (MIT) — Phase 6 Wave 25 bumped 1.6.x → 2.1.9 for Node 24 host compatibility (CI still runs Node 20)
Full attributions in LICENSES.md.