How to integrity tester in developer workflows
- Step 1Verify a PR's artifact without a checkout — When a PR ships a ZIP (an SDK, a sample bundle, a docs export), download it from the PR and drop it into /archive-tools/archive-integrity-tester. You get a per-entry verdict faster than cloning and rebuilding.
- Step 2Gate a release on a clean report — Before publishing a release ZIP, run it through the tester. A
failed: 0report is your corruption gate; anyCRC mismatchormissingentry means rebuild and re-verify rather than ship. - Step 3Pass the password for encrypted bundles — For an AES-256 / ZipCrypto distribution ZIP, enter the password so zip.js decrypts and the plaintext CRC32 is checked. A wrong password is reported as a decryption error, distinct from a corruption failure.
- Step 4Diff contents, not just integrity, when needed — Integrity tells you whether a ZIP is intact; to see what changed between two builds, use archive-diff, which compares two archives entry-by-entry.
- Step 5Make the artifact reproducible — After verifying integrity, normalise entry timestamps with timestamp-normalizer (default
1980-01-01, the ZIP epoch) so the same inputs produce byte-identical output across machines. - Step 6Pin a SHA-256 manifest your CI can re-check — Generate a SHA-256 manifest with checksum-generator and store it. CI can re-hash future builds against it — CRC32 catches accidental corruption; SHA-256 is your strong reproducibility/authenticity check.
Developer workflows and the right tool
Where the integrity tester fits, and which sibling tool handles the adjacent job.
| Goal | Tool | Why |
|---|---|---|
| Is this release ZIP intact? | Archive Integrity Tester | Per-entry CRC32 verdict in JSON |
| What changed between two build ZIPs? | archive-diff | Compares two archives entry-by-entry |
| Make builds byte-reproducible | timestamp-normalizer | Pins entry timestamps to the ZIP epoch |
| Pin an authenticity/reproducibility hash | checksum-generator | SHA-256 manifest CI can re-verify |
| Salvage a partly-corrupt ZIP | corrupted-zip-repair | Rebuilds from recoverable entries |
| What format is this file, really? | auto-format-detector | Confirms ZIP vs 7z/rar before testing |
CLI equivalents and automation
Closest local commands, and what JAD adds. There is no public HTTP API; the runner is the automation path.
| Need | Local CLI | JAD path |
|---|---|---|
| Verify ZIP CRC32 | unzip -t file.zip | Drop ZIP → JSON report |
| Verify non-ZIP (7z/tar) | 7z t / gzip -t | Out of scope — JAD verifies ZIP only |
| Encrypted ZIP | unzip -P pass -t | Password field → zip.js |
| Headless automation | shell script | @jadapps/runner (Pro+), headless browser |
| HTTP API call | n/a | None — apiAvailable: false |
| SHA-256 manifest | sha256sum | checksum-generator |
Cookbook
Developer-shaped runs: the CLI equivalent on the left, the JAD report on the right, plus reproducible-build glue.
Gate a release ZIP before publishing
A pre-publish corruption check. unzip -t does this in a terminal; the JAD report is the same verdict you can attach to the release checklist.
$ unzip -t dist/app-1.8.0.zip
... all entries OK ...
No errors detected.
JAD (app-1.8.0-integrity.json):
{ "totalEntries": 540, "passed": 540, "failed": 0 }
Gate: ship only on failed === 0.Triage a PR artifact without a checkout
A reviewer downloads the SDK ZIP from the PR and verifies it in a tab — no clone, no rebuild — and finds a broken native lib.
Downloaded from PR: sdk-bundle.zip
JAD report:
{ "totalEntries": 96, "passed": 95, "failed": 1,
"results": [
{ "name": "native/linux/libfast.so",
"storedCrc32": "d11a4e90", "passed": false,
"error": "CRC mismatch: computed d11a4e21" } ] }
Review comment: native/linux/libfast.so is corrupt in the
attached bundle — please re-export.Reproducible-build chain
Integrity is step one; reproducibility needs normalised timestamps and a pinned hash. The chain produces a byte-identical, verifiable artifact.
1. archive-integrity-tester → failed: 0 (intact) 2. timestamp-normalizer → all entries set to 1980-01-01 3. checksum-generator (SHA-256): app.zip e3b0c442...98fb (committed to repo) CI on the next build: re-run steps 1-3; assert SHA-256 == committed value.
Encrypted distribution ZIP
A password-protected partner build. zip.js handles AES-256; the CLI uses a flag.
$ unzip -P "$BUILD_PW" -t partner-build.zip
... OK ...
JAD: enter password in password field → Process →
{ "totalEntries": 73, "passed": 73, "failed": 0 }Wrong format in CI artifact storage
An artifact pipeline accidentally stored a 7z under a .zip name. The tester rejects it immediately, which is itself a useful signal.
JAD: drop artifact.zip → Error: "Not a valid ZIP archive." Diagnose: $ file artifact.zip artifact.zip: 7-zip archive data Fix the pipeline to emit ZIP, or verify with 7z t. (Confirm format quickly via /archive-tools/auto-format-detector.)
Edge cases and what actually happens
Expecting a public API to call from CI
No APIArchive tools have no public HTTP endpoint (apiAvailable: false) — you can't POST a ZIP to a JAD URL. For automation, the @jadapps/runner executes the same browser logic headlessly on Pro+ tiers. For a pure CI corruption gate, unzip -t with its exit code is often the simpler fit.
Verifying a 7z / tar.gz artifact
Rejected — not a ZIPThe tester verifies ZIP CRC32 only; a 7z, rar, or tar.gz is rejected because it has no ZIP central directory. Detect the real format with auto-format-detector; for non-ZIP integrity use 7z t / gzip -t or a SHA-256 from checksum-generator.
Confusing integrity with diff
Use archive-diffIntegrity answers 'is this ZIP intact?', not 'what changed between two builds?'. For the latter, archive-diff compares two archives entry-by-entry. Running the integrity tester twice on two builds won't surface added/removed/changed entries — it only reports each one's internal CRC32.
Reproducible build still differs after integrity passes
Normalise timestampsA ZIP can be fully intact (integrity passes) yet differ byte-for-byte between machines because entry timestamps encode build time. Run timestamp-normalizer (default 1980-01-01) before hashing so the SHA-256 is stable across builds.
Large release bundle over the tier cap
Rejected — tier limitA multi-hundred-MB release ZIP exceeds Free's 50 MB. The size and 500-entry checks run before decompression, so it's rejected up front. Pro lifts this to 500 MB / 50,000 entries; Pro-Media/Developer to 2 GB / 500,000 entries.
Encrypted bundle, wrong password
Decryption failedAn incorrect password produces a decryption-failure report, not a CRC mismatch — so don't read a 'failure' here as corruption. Re-check the password (case- and whitespace-sensitive). The CRC32 is verified over decrypted plaintext, so it can only be evaluated once decryption succeeds.
ZIP of many tiny files hits the entry cap
Rejected — tier limitA node_modules-style ZIP can blow past the entry-count cap (Free 500) long before the size cap. The entry limit is enforced separately from file size. Bump to Pro (50,000) for dependency-shaped archives.
Self-extracting / stub-prefixed release ZIP
SupportedAn SFX installer (executable stub + appended ZIP) usually verifies fine because the central directory is located by scanning from the end of the file. If the stub trips the scan you'll see Not a valid ZIP archive — extract the inner ZIP and test that.
Frequently asked questions
Is there a CLI or API equivalent?
The closest local equivalent is unzip -t file.zip, which does the same per-entry CRC32 verification with an exit code. JAD has no public HTTP API (apiAvailable: false); for automation, the @jadapps/runner runs the same browser logic headlessly on Pro+. For a simple CI gate, unzip -t is usually the most direct.
How do I verify a release ZIP as part of CI?
If you want a shell gate, unzip -t dist/app.zip && publish || fail uses the exit code directly. If you want a verifiable artifact, run the JAD tester and store the JSON report; on Pro+ the runner can drive it headlessly. Either way, gate on failed === 0.
Can it tell me what changed between two builds?
No — that's a diff, not an integrity check. Use archive-diff to compare two archives entry-by-entry. The integrity tester only reports whether each entry in a single ZIP matches its own stored CRC32.
How do I make my build artifact reproducible?
Verify integrity, then normalise entry timestamps with timestamp-normalizer (default 1980-01-01, the ZIP epoch) so build-time stamps don't change the bytes. Finally pin a SHA-256 manifest via checksum-generator that CI re-checks on every build.
Why does it reject my .7z / .tar.gz artifact?
It verifies ZIP CRC32 specifically (by parsing the ZIP central directory), so non-ZIP formats return Not a valid ZIP archive. Confirm the format with auto-format-detector. For 7z use 7z t; for .tar.gz use gzip -t (single trailing CRC32) or a SHA-256 over the whole file.
Does CRC32 give me reproducible-build guarantees?
Partly — it tells you the ZIP is intact, but two byte-different ZIPs of the same files can both pass (e.g. different timestamps). For reproducibility, pair integrity with timestamp normalisation and a SHA-256 manifest; SHA-256 is the strong equality check, CRC32 the corruption check.
Can I batch-verify many artifacts at once?
The integrity tester takes one ZIP per run. For checking many archives in a single pass, the analysis family's batch-compression-report accepts multiple files; for headless automation across artifacts, drive the runner on Pro+.
What's the JSON output shape so I can parse it?
{ totalEntries, passed, failed, results: [{ name, storedCrc32, passed, error? }] }. storedCrc32 is 8-character hex; error is present only on failure (CRC mismatch: computed <hex> or missing). It's stable, so jq '.failed' and jq '.results[] | select(.passed == false)' work reliably.
Does it modify my archive?
No. The integrity tester is read-only — it decompresses entries in memory to recompute CRC32 and produces a JSON report. Your ZIP is untouched. To rebuild a salvageable copy of a damaged ZIP, use corrupted-zip-repair.
Is processing actually local for proprietary builds?
Yes. fflate and zip.js run as WebAssembly in your browser tab; the ZIP is read from disk and never uploaded. There's no server-side path, so proprietary or pre-release artifacts stay on your machine. Confirm with DevTools → Network during a run.
What's the largest artifact I can verify?
Free: 50 MB / 500 entries. Pro: 500 MB / 50,000 entries. Pro-Media and Developer: 2 GB / 500,000 entries. The entry-count cap is separate from size and bites first on dependency-style ZIPs full of small files.
Can I verify an encrypted distribution ZIP?
Yes — enter the password in the password field and zip.js decrypts AES-256 / ZipCrypto entries, then the tester verifies each one's plaintext CRC32. A wrong password is reported as a decryption error, not a corruption failure, so the two cases stay distinguishable.
Privacy first
Every JAD Archive tool runs entirely in your browser using fflate, @zip.js/zip.js, and the libarchive WASM bridge. Your archives never leave your device — verified by zero outbound network requests during processing.