Files
pdfcraft/Cargo.toml
T
Tanish MankuandClaude Opus 5 0754740fd9 feat(oracle): make a missing external oracle loud instead of a silent pass
Every test that wanted an external oracle probed for it by hand and chose for itself what to do
when it was missing. The common choice -- print a line and return -- reports as a pass, so a suite
with no oracles installed looked exactly like one in which every oracle agreed.

That was not hypothetical. No CI runner installed qpdf, so `qpdf_agrees` had never executed on a
runner, while README.md said saved output was "independently checked with qpdf". For R2-R4 that
test is the only check of owner-password authentication (Algorithm 7) that does not go through our
own code.

`pdfcraft-oracle` holds the probes and one rule: a missing oracle is a declared skip or a failure,
never a silent pass. `PDFCRAFT_ORACLES_REQUIRED` picks which, on the same convention as
`CRAFT_FONTS_REQUIRED`. CI installs qpdf and sets it, so a skip notice there is now a red build.
The crate has no panicking path of its own; `or_skip!` expands its assert into the caller, which
is test code.

Verified by running the qpdf tests against qpdf 12.4.2 for the first time -- they pass, so the
README claim is now both enforced and true. Both gate directions were watched: absent and
unrequired skips with a notice, absent and required fails with the install command in the message.

Only qpdf is installed in CI, because it is the only tool the test job uses. The Poppler pixel
comparison in crates/organize stays ignored until a change turns it on and verifies it there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 13:56:00 -07:00

114 lines
4.4 KiB
TOML

[workspace]
resolver = "3"
members = ["crates/*", "apps/*", "xtask"]
exclude = ["vendor"]
default-members = ["crates/*", "apps/pdfcraft", "apps/pdfcraft-cli", "xtask"]
[workspace.package]
version = "0.8.0"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.95"
repository = "https://github.com/storytold/pdfcraft"
[workspace.dependencies]
# Shared frontend components; engines remain independent of egui.
craft-ui = { git = "https://github.com/storytold/craft-libs", version = "0.1.0", rev = "5c874d51eeb3de70e735c8ce87a59a7dedd47675", features = ["serde"] }
# Shared system spooler; document composition remains in pdfcraft-print.
craft-print = { git = "https://github.com/storytold/craft-libs", version = "0.1.0", rev = "f03ec27ab2c405969428512178f746183cd55ca0" }
# internal
pdfcraft-geom = { path = "crates/geom", version = "0.8.0" }
pdfcraft-filters = { path = "crates/filters", version = "0.8.0" }
pdfcraft-cos = { path = "crates/cos", version = "0.8.0" }
pdfcraft-crypt = { path = "crates/crypt", version = "0.8.0" }
pdfcraft-organize = { path = "crates/organize", version = "0.8.0" }
pdfcraft-measure = { path = "crates/measure", version = "0.8.0" }
pdfcraft-annot = { path = "crates/annot", version = "0.8.0" }
pdfcraft-audit = { path = "crates/audit", version = "0.8.0" }
pdfcraft-fonts = { path = "crates/fonts", version = "0.8.0" }
pdfcraft-model = { path = "crates/model", version = "0.8.0" }
pdfcraft-content = { path = "crates/content", version = "0.8.0" }
pdfcraft-redact = { path = "crates/redact", version = "0.8.0" }
pdfcraft-print = { path = "crates/print", version = "0.8.0" }
pdfcraft-xfdf = { path = "crates/xfdf", version = "0.8.0" }
pdfcraft-sign = { path = "crates/sign", version = "0.8.0" }
pdfcraft-optimize = { path = "crates/optimize", version = "0.8.0" }
pdfcraft-a11y = { path = "crates/a11y", version = "0.8.0" }
pdfcraft-oracle = { path = "crates/oracle", version = "0.8.0" }
pdfcraft-ocr = { path = "crates/ocr", version = "0.8.0" }
pdfcraft-js = { path = "crates/js", version = "0.8.0" }
pdfcraft-compare = { path = "crates/compare", version = "0.8.0" }
pdfcraft-preflight = { path = "crates/preflight", version = "0.8.0" }
pdfcraft-export = { path = "crates/export", version = "0.8.0" }
pdfcraft-edit = { path = "crates/edit", version = "0.8.0" }
pdfcraft-create = { path = "crates/create", version = "0.8.0" }
pdfcraft-forms = { path = "crates/forms", version = "0.8.0" }
pdfcraft-xfa = { path = "crates/xfa", version = "0.8.0" }
pdfcraft-render = { path = "crates/render", version = "0.8.0" }
pdfcraft-engine = { path = "crates/engine", version = "0.8.0" }
pdfcraft-platform = { path = "crates/platform", version = "0.8.0" }
pdfcraft-ui-egui = { path = "crates/ui-egui", version = "0.8.0" }
pdfcraft-automation = { path = "crates/automation", version = "0.8.0", default-features = false }
# pdf
hayro = "0.7.1"
hayro-syntax = "0.7.2"
lopdf = "0.45"
flate2 = { version = "1.1", default-features = false, features = ["rust_backend"] }
weezl = "0.2"
# foundation
thiserror = "2"
serde = { version = "1", features = ["derive", "rc"] }
serde_json = "1"
log = "0.4"
kurbo = "0.13"
# testing
proptest = "1"
# ui
egui = "0.36"
egui_extras = { version = "0.36", default-features = false, features = ["svg"] }
eframe = { version = "0.36", default-features = false }
egui_kittest = "0.36"
rfd = "0.17"
[workspace.lints.rust]
unsafe_code = "forbid"
[workspace.lints.clippy]
dbg_macro = "warn"
todo = "warn"
# `"*"` matches every non-workspace package: crates.io dependencies and the
# vendored crates under `vendor/` (excluded from the workspace). Our own crates
# keep full debug info. Dependencies keep only line tables, so backtraces still
# show file and line, but debug info for the whole dependency graph stays out of
# every test binary (each UI test binary had a 500-600 MB PDB on Windows, #454).
[profile.dev.package."*"]
opt-level = 2
debug = "line-tables-only"
[profile.dev]
opt-level = 1
[profile.low-disk]
inherits = "dev"
debug = "line-tables-only"
incremental = false
[profile.release]
lto = "thin"
codegen-units = 1
# Vendored, patched third-party crates (see vendor/README.md). Each patch is meant to go upstream.
[patch.crates-io]
hayro-interpret = { path = "vendor/hayro-interpret" }
hayro = { path = "vendor/hayro" }
hayro-syntax = { path = "vendor/hayro-syntax" }
hayro-jbig2 = { path = "vendor/hayro-jbig2" }
lopdf = { path = "vendor/lopdf" }
winit = { path = "vendor/winit" }
egui-wgpu = { path = "vendor/egui-wgpu" }