Skip to content

feat(printing): add PDF document printing with signed retrieval - #1

Merged
twlite merged 2 commits into
mainfrom
feat/pdf-document-printing
Oct 17, 2026
Merged

twlite merged 2 commits into
mainfrom
feat/pdf-document-printing

Conversation

@twlite

@twlite twlite commented Oct 17, 2026

Copy link
Copy Markdown
Member

Summary

Adds PDF document printing alongside structured receipts.

  • Protocol: PrintJob.document becomes a union. Receipts keep their exact legacy JSON shape. A PDF is {format: "pdf", source: {type: "url", url, sha256, byteLength}, settings?}. Bytes never travel inside protocol messages. Printer capabilities gain optional documentFormats, paperSizes, customPaperSize, and printOptions.
  • Retrieval: new oppa-documents crate. The agent fetches with an Ed25519-signed request using its existing credential, refuses redirects, enforces the declared length, and verifies SHA-256 before use. Nothing secret is stored in SQLite. @openprinter/server adds verifyDocumentRequest.
  • Rendering: hayro (pure Rust) validates and rasterizes PDFs under size, page, pixel, raster-byte, and deadline limits. Copies, paper (A4/A5/Letter/Legal/custom mm for labels), orientation, scaling, and page ranges are applied.
  • Submission: Unix queues submit natively via lp with IPP options. Windows rasterizes into the existing GDI path. Duplex on Windows fails with document.option_unsupported.
  • Agent: PDF jobs are retrieved and validated before the job is claimed for submission. Failures map to stable document.* codes.
  • Desktop: printer details show the PDF route, paper sizes, and duplex; a PDF test-print form.
  • Docs: print-documents, protocol, and job-delivery pages, plus crate and package READMEs.

Known gaps

  • Page margins are not implemented.
  • Unicode shaping (e.g. Devanagari) is not implemented. PDF text uses embedded fonts; receipt text still uses the 8×8 glyph fallback.
  • packages/sdk (cloud client) does not accept PDF documents.
  • Protocol compatibility: servers with strict schemas reject inventories containing the new capability fields. Upgrade @openprinter/protocol and the server SDK before connecting agents from this release. A follow-up change will gate these fields behind protocol version negotiation.
  • The oppa desktop crate was not compile-verified for Windows (needs a MinGW toolchain for ring). Spooler, discovery, renderer, and Windows print crates pass a Windows target check.
  • CUPS option names (media=Custom.WxHmm, scaling=N) are unverified against a live queue.

Verification

  • cargo fmt --all --check, cargo clippy --workspace --all-targets --all-features -- -D warnings, cargo test --workspace (189 passing)
  • pnpm format:check, pnpm lint, pnpm typecheck, pnpm test (protocol 53, sdk 6, server 19, example 1), schema:check
  • pnpm --filter @oppa/www build

🤖 Generated with Claude Code

Introduce PDF as a document type alongside structured receipts:

- protocol: JobDocument union (receipt or PDF reference), PdfSource with
  HTTPS/loopback URL, SHA-256 and byte length, print settings, and optional
  document capability fields on printer capabilities
- renderer: validate and rasterize PDFs with hayro under size, page,
  pixel, raster-byte, and deadline limits
- spooler: native lp submission on Unix with IPP options; rasterized GDI
  fallback on Windows
- documents: new oppa-documents crate for signed, integrity-checked fetch
- agent: fetch-then-claim PDF job processing and local PDF test prints
- discovery: CUPS paper and duplex options via lpoptions
- desktop: PDF test print, route and paper display
- server SDK: verifyDocumentRequest for agent document requests
- fixtures, schema, and documentation

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
oppa Ready Ready Preview Oct 17, 2026 12:07pm UTC

- bump async-trait to 0.1.92, which no longer triggers double_must_use on
  async trait declarations
- use assert_eq!/len checks instead of assert!(..is_empty()) (assert_is_empty)
- keep fetch_update in bump_revision with an allow(deprecated) and a note,
  since its replacement requires Rust 1.95 and the workspace MSRV is 1.85

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@twlite
twlite merged commit d7293ab into main Oct 17, 2026
11 checks passed
@twlite
twlite deleted the feat/pdf-document-printing branch October 17, 2026 12:23

This branch was successfully deployed

1 active deployment
Preview — 128f2eb4 Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant