Cross-platform native desktop PDF editor with full content editing
Go to file
ai-ad4 ea69535812 feat(m1-ipc): production IPC layer — sandboxed document process + Cap'n Proto RPC
The first M1 (Viewer) increment: lift the Spike E RPC shape into src/ipc as a
Qt-free, unit-testable library implementing the §2.1 process split. The UI
process forks a sandboxed document process, hands it the document fd via
SCM_RIGHTS (§2.1: no FS access beyond handed fds), and talks Cap'n Proto
two-party RPC over a socketpair. The document process installs the seccomp
sandbox, receives the fd, and serves the DocumentProcess interface (open,
getPageCount, ping) backed by QPDF reading from the handed fd.

src/ipc/ (new, Qt-free so testable without QApplication):
- ipc.capnp: M1 protocol — DocumentProcess{open(fd via SCM_RIGHTS, pathHint)
  -> OpenResult{pageCount, pdfVersion}; getPageCount; ping}. ADR-0004 trust
  boundary: the UI validates every response; the doc bounds-checks requests.
- DocumentProcessServer: low-level wrapSocketFd + TwoPartyVatNetwork(SERVER)
  + makeRpcServer (the Spike E proven shape, NOT EzRpcServer which calls
  accept() on a connected socketpair end). QPDF reads from the handed fd.
- DocumentProcessClient: the Qt<->KJ event-loop integration (§2.3) — runs the
  KJ event loop on a dedicated worker thread (low-level makeRpcClient, not
  EzRpcClient which uses a thread-local context that breaks cross-thread
  destruction). Synchronous methods block the caller via std::promise.
- ProcessLauncher: fork + socketpair + send_fd + construct client.
- FdPassing: raw SCM_RIGHTS send/recv, orthogonal to the RPC transport.
- Sandbox: seccomp allow-list lifted from Spike E, +sendmsg/recvmsg (fd
  passing), +fcntl/fstat/lseek/pread64 (QPDF/stdio on the handed fd).

src/app: wire File>Open and the command-line positional arg to launch the
document process off the GUI thread (QtConcurrent) and show the page count in
the status bar (QMetaObject::invokeMethod back to the GUI thread).

test/test_ipc: end-to-end test — launches the sandboxed document process,
opens a real PDF, verifies ping + pageCount + getPageCount. PASSES under the
seccomp sandbox; ASan-clean with sandbox disabled (ASan's pipe2 conflicts
with the allow-list, an ASan-only artefact). Registered as ctest ipc_end_to_end.

Both Spike E (raw protocol) and this (real RPC) now pass under the sandbox.
2026-07-27 11:26:51 +00:00
.gitea/workflows feat(spike-B1): glyph→Unicode ladder on real embedded font; 98% coverage (§4.1 step 1) 2026-07-25 20:57:02 +00:00
LICENSES chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
ci chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
cmake chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
docs feat(spike-E): resolve Cap'n Proto socketpair stall; wire RPC transport (M2 prereq) 2026-07-27 10:54:21 +00:00
packaging chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
spike feat(spike-E): resolve Cap'n Proto socketpair stall; wire RPC transport (M2 prereq) 2026-07-27 10:54:21 +00:00
src feat(m1-ipc): production IPC layer — sandboxed document process + Cap'n Proto RPC 2026-07-27 11:26:51 +00:00
test feat(m1-ipc): production IPC layer — sandboxed document process + Cap'n Proto RPC 2026-07-27 11:26:51 +00:00
.clang-format chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.clang-tidy chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.editorconfig chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.gitattributes chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.gitignore feat(spike-E): resolve Cap'n Proto socketpair stall; wire RPC transport (M2 prereq) 2026-07-27 10:54:21 +00:00
.gitleaks.toml chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.pre-commit-config.yaml chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CMakeLists.txt chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CMakePresets.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CODEOWNERS chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CONTRIBUTING.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
README.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
REUSE.toml build(license): convert dep5 to REUSE.toml; record Spike A result 2026-07-25 20:30:43 +00:00
SECURITY.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
TRADEMARK.md build(license): convert dep5 to REUSE.toml; record Spike A result 2026-07-25 20:30:43 +00:00
vcpkg-configuration.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
vcpkg.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00

README.md

FreePDFEditor

A cross-platform native desktop PDF editor with a true WYSIWYG interface and full content editing: edit existing text with reflow, replace images, manipulate vector objects, plus annotations, forms, signatures, and page assembly.

  • Stack: C++20, Qt 6.7 (Widgets shell, custom canvas), CMake, vcpkg.
  • License: GPL-3.0-or-later (see LICENSES/GPL-3.0-or-later.txt). Qt is dynamically linked under LGPL-3.0.
  • Targets: Windows 10+, macOS 12+ (Intel + Apple Silicon), Linux (X11/Wayland).

This repository contains the source and build infrastructure. The full engineering plan and roadmap live in docs/plan.md; architecture decision records are under docs/adr/.

Status

Pre-M0. This is the initial repository scaffold described in §14 of the plan: CMake + vcpkg skeleton, governance docs, CI matrix, packaging pipeline, an empty-window application shell, the pixel-diff harness scaffolding, and the Spike A (QPDF verbatim round-trip) harness. The feasibility spikes that gate the project run on top of this scaffolding.

Building

cmake --preset default
cmake --build --preset default
ctest --preset default

See CONTRIBUTING.md for the full build setup, gate matrix, and coding standard.

Source control

All code is developed on the project Gitea instance at https://gitea.lm.je/ai-ad4/freepdfeditor per docs/plan.md §13. See SECURITY.md for vulnerability reporting.