Skip to content

feat(verapdf): add moox/verapdf package with headless install + hardened installer#1006

Open
jbagsik wants to merge 6 commits into
mainfrom
feature/add-verapdf-package
Open

feat(verapdf): add moox/verapdf package with headless install + hardened installer#1006
jbagsik wants to merge 6 commits into
mainfrom
feature/add-verapdf-package

Conversation

@jbagsik

@jbagsik jbagsik commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds moox/verapdf, a standalone package for PDF/A-3 conformance validation via
veraPDF, mirroring moox/kosit-validator. It is fully self-contained — depends
only on moox/core, touches nothing outside packages/verapdf/, and holds no
e-billing/host-app knowledge. veraPDF runs as an arm's-length CLI process
(MPL-2.0, commercial-safe). This PR delivers the package, a headless server
install, and download-integrity hardening.

Package (validation core)

  • Config (config/verapdf.php): base path, launcher location, Java binary.
  • VeraPdfService::validate()VeraPdfResult (passed() + parsed errors;
    PDF/A flavour defaults to 3b).
  • VeraPdfValidation model + morph pivot (verapdf_validatables) via
    RecordVeraPdfValidation, mirroring KositValidation/KositValidatable.
  • Graceful degradation: isInstalled(), javaAvailable(), verapdf:doctor.
  • CLI: verapdf:install, verapdf:validate, verapdf:doctor.
  • VeraPdfRelationConfig for future owner wiring (no Filament resource —
    CLI + persistence only). DE/EN translations included.

Headless / server install

  • verapdf:install targets headless Linux servers (no GUI/X11): an IzPack
    auto-install descriptor selects the veraPDF CLI pack only, excluding the
    desktop/GUI pack.
  • Install is only treated as complete once the CLI pack is present; verapdf:doctor
    confirms a healthy headless setup.

Installer hardening

  • Downloaded veraPDF installer is verified against a pinned checksum
    (InstallerChecksum) before use; a mismatch aborts cleanly.
  • SafeZipExtractor rejects entries resolving outside the target dir (zip-slip)
    and ZIP symlinks; the --force reinstall path is covered against the same.
  • Report basenames sanitized; VeraPdfOutputPath::resolve() rejects ../empty
    segments. No e-billing FQCNs in config/README.

Testing

  • 40 Pest cases, no live JVM: report-fixture parsing, record persistence,
    install-command behavior, checksum-mismatch and zip-slip/symlink rejection,
    auto-install stub, doctor, arch test.

After merge (host apps)

php artisan vendor:publish --tag=verapdf-config --force
php artisan vendor:publish --tag=verapdf-migrations --force
php artisan config:clear

Commits

  • Add moox/verapdf package for PDF/A-3 validation via veraPDF
  • Harden verapdf path handling and drop host-app config comments
  • Select veraPDF CLI pack only for headless server installs
  • Require CLI pack before treating veraPDF as already installed
  • Harden verapdf:install with checksum pin and zip-slip-safe extract
  • Reject ZIP symlinks and cover --force zip-slip abort

jbagsik and others added 6 commits July 17, 2026 12:09
Mirror kosit-validator: headless IzPack install, VeraPdfService + VeraPdfResult, audit model with morph pivot, and Pest fixture tests without a live JVM.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sanitize report basenames, reject output subdirectory traversal, prefer configured Java on PATH for the launcher, and keep config/README free of e-billing references.

Co-authored-by: Cursor <cursoragent@cursor.com>
Pin IzPack auto-install to 1.30+ CLI (exclude GUI), assert CLI layout after install/doctor, and document headless JRE prerequisites.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fail verapdf:install when a launcher exists without bin/*cli*.jar so GUI-only leftovers cannot short-circuit a headless reinstall.

Co-authored-by: Cursor <cursoragent@cursor.com>
Verify the pinned installer SHA-256 before use, reject path-traversal ZIP entries, and defer --force wipe until after integrity checks so failures stay non-destructive.

Co-authored-by: Cursor <cursoragent@cursor.com>
Tighten SafeZipExtractor against symlink and '.' path segments, and assert --force does not wipe an existing install when extraction is refused.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
15.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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