Tool reference
The browser container check
A client-side container check that reads the ZIP central directory, the mimetype member, the manifest and every declared digest. Nothing is uploaded. It covers the first of three validation layers, and this page records exactly which.
Definition
The browser check is the container conformance layer of the WWD validator, reimplemented in src/scripts/wwd-validate.js against platform APIs only: DecompressionStream for raw DEFLATE and crypto.subtle for SHA-256. It reads the ZIP central directory, the mimetype member, the manifest and the root design document, and it verifies every declared byte length and every declared SHA-256 digest. It emits twenty-one diagnostic codes across the families P01 to P06 and P08. It does not evaluate fields, resolve references, check causal roles, recompute a disposition, apply design rules, or award a conformance class. The file is read in the page and is not uploaded.
The tool itself is at the validator page. Drop a .wwd file on it and it returns a list of findings and a package summary.
This page is the reference for what that list covers.
The check is written in src/scripts/wwd-validate.js and uses platform APIs
only: DataView over the archive bytes, DecompressionStream with
the deflate-raw format, TextDecoder for UTF-8, and crypto.subtle.digest for SHA-256. There is no bundled ZIP library, no
registry, and no request that carries the file. The bytes are read in the tab and stay
there.
Two compression methods are handled: STORED and DEFLATE. Any other method on a declared
entry produces P05_UNREADABLE for that entry rather than a silent pass.
The three layers
The layer table of the reference validator, and which layer runs in the browser.
| Layer | Question | Where it lives | In the browser |
|---|---|---|---|
| 1. Structure | Is the package well-formed? | The JSON Schema set and the container rules | Yes, container only |
| 2. Semantics | Do the references, provenance and causal roles hold together? | validator/wwd/, and validator-ts/src/ | No |
| 3. Physics | Will the design work in a lab? | validator/wwd/dfm.py and validator-ts/src/dfm.ts | No |
A package can pass layer 1 and layer 2 and fail layer 3. A construct can be a well-formed archive with resolvable references and still be too thick for oxygen to reach its core. The browser check answers the first question and reports nothing about the other two.
How it reads a package
Ten steps, in the order the function performs them.
| Step | Action | What happens |
|---|---|---|
| 1 | Locate the End Of Central Directory | A backward scan over the last 66,000 bytes for signature 0x06054b50, which allows for a ZIP comment. |
| 2 | Walk the central directory | Entry count and central-directory offset come from the EOCD. Each record yields name, compression method, CRC, compressed and uncompressed size, and the local header offset. The central directory is read rather than the local headers because entry order is what the mimetype rule is about. |
| 3 | Read the mimetype member | The first entry by central-directory order must be named mimetype, be STORED, and contain application/vnd.wwd+zip. |
| 4 | Read wwd/manifest.json | Inflated through DecompressionStream with the deflate-raw format when the method is DEFLATE, then decoded as UTF-8 and parsed as JSON. |
| 5 | Read the declared version and media type | manifest.wwd and manifest.mediaType. |
| 6 | Verify every declared file | For each record in manifest.files: locate the entry, inflate it, compare the inflated length against bytes, and compare crypto.subtle.digest("SHA-256", data), Base64 encoded and prefixed sha256-, against integrity. |
| 7 | Compare the two directions | Every archive entry that is not mimetype, not wwd/manifest.json and not a directory is checked for a manifest record. |
| 8 | Read the root design document | manifest.root, defaulting to wwd/design.json, is inflated and parsed as JSON. The parsed object is used only to count components. |
| 9 | Read the extension arrays | extensionsRequired and extensionsUsed. |
| 10 | Report package shape | Version, package_id, root name, file count, component count, external record count, and a stage of as-built when wwd/results.json is present and as-designed otherwise. |
Three points stop the run. A file with no locatable End Of Central Directory returns a single P01_NOT_A_ZIP. A missing manifest returns the findings raised so far plus P03_NO_MANIFEST. A manifest that does not parse returns P03_MANIFEST_INVALID_JSON. In all three cases nothing downstream is checked, so
an empty rest of the report means the run stopped, not that the package is clean.
Every code it can emit
21 codes: 16 error, 4 warning, 1 info.
| Code | Severity | Trigger |
|---|---|---|
| P01_NOT_A_ZIP | error | No End Of Central Directory record is found in the last 66,000 bytes, or the central directory cannot be walked. Validation stops here. |
| P02_EMPTY_PACKAGE | error | The central directory lists no entries. |
| P02_MIMETYPE_NOT_FIRST | error | The first central-directory entry is not named mimetype. |
| P02_MIMETYPE_COMPRESSED | error | The mimetype entry is present and first, but its compression method is not STORED. |
| P02_MIMETYPE_WRONG | error | The mimetype entry decodes, after trimming, to something other than application/vnd.wwd+zip. |
| P03_NO_MANIFEST | error | No entry named wwd/manifest.json is in the central directory. Validation stops here. |
| P03_MANIFEST_INVALID_JSON | error | The manifest bytes do not parse as JSON. Validation stops here. |
| P03_NO_DESIGN | error | The entry named by manifest.root, defaulting to wwd/design.json, is absent from the archive. |
| P03_DESIGN_INVALID_JSON | error | The root design document is present but does not parse as JSON. |
| P04_NO_VERSION | error | The manifest carries no wwd member. |
| P04_UNKNOWN_VERSION | warning | The manifest declares a wwd version other than 0.1. |
| P04_MEDIATYPE_MISMATCH | error | The manifest declares a mediaType and it is not application/vnd.wwd+zip. |
| P05_NO_FILES | warning | The manifest files array is absent or empty. |
| P05_MISSING_FILE | error | A manifest file record names an entry that is not in the central directory. |
| P05_UNREADABLE | error | A declared entry cannot be decompressed: a compression method other than STORED or DEFLATE, or a DecompressionStream failure. |
| P05_LENGTH_MISMATCH | error | A record declares a numeric bytes value and the inflated length differs from it. |
| P05_INTEGRITY_MISMATCH | error | A record declares an integrity string beginning sha256- and the recomputed Base64 SHA-256 of the inflated bytes differs. |
| P05_NO_INTEGRITY | warning | A manifest file record has a null or absent integrity member. |
| P06_UNDECLARED_FILE | warning | An archive entry other than mimetype, wwd/manifest.json and directory entries has no manifest file record. |
| P08_REQUIRED_EXT_UNSUPPORTED | error | The manifest lists an extension in extensionsRequired. The browser check implements no extension, so every entry in that array raises this code. |
| P08_OPTIONAL_EXT_IGNORED | info | An extension appears in extensionsUsed and not in extensionsRequired. |
Four names differ from the reference codes in Appendix C: P01_NOT_A_ZIP for P01_NOT_ZIP, P02_MIMETYPE_WRONG for P02_MIMETYPE_CONTENT, P06_UNDECLARED_FILE for P03_UNMANIFESTED, and the P04 version and media-type codes for P03_VERSION and P03_MEDIATYPE. Where a code name has to be quoted,
quote the reference validator.
What it cannot check
By code family, with the reason.
| Family | Subject | Codes and reason |
|---|---|---|
| P07 | Hostile container checks | P07_UNSAFE_PATH, P07_DUPLICATE_ENTRY, P07_TOO_MANY_ENTRIES, P07_COMPRESSION_RATIO, P07_DECOMPRESSION_LIMIT, P07_CREDENTIALS_IN_URI. The browser reader walks the central directory without path, duplicate, entry-count or expansion-ratio limits. |
| P03 remainder | Manifest ghosts and root rules | P03_MANIFEST_GHOST, P03_ROOT_MISSING, P03_NO_ROOT. The browser check reports a missing root under its own P03_NO_DESIGN and has no ghost-record rule. |
| P05_EXTERNAL_INCOMPLETE | External asset records | The browser check counts manifest.external and does not inspect the records. |
| P08 remainder | Extension declaration rules | P08_EXTENSION_NOT_DECLARED, P08_EXTENSION_UNUSED, P08_EXTENSION_URI_UNVERSIONED, P08_PREFIX_UNBOUND, P08_REQUIRED_NOT_IN_USED. |
| P10 to P13 | Asset roles and asset context | P10_NO_ROLE, P10_UNKNOWN_ROLE, P11_ASSET_NO_FRAME, P12_ASSET_NO_UNITS, P13_ASSET_AMBIGUOUS. |
| Everything after P | Semantics | Identity, lineage, interfaces, ports, dimensions, frames, fields, units, causal roles, assays, criteria, results, uncertainty, simulation, sampling and authoring. These are the code families A through Z outside P. |
| DFM | Physics | The fifteen design rules of Appendix C.5. The browser check never loads them. |
| Conformance classes | Section 22 | WWD-Package-Core, WWD-Design-Core, WWD-Field-Evaluator, WWD-As-Built, WWD-Simulation and WWD-Manufacturing-Ready. The browser check awards none of them. |
The reference validator in wwd-spec/validator/wwd/ carries 233 distinct
diagnostic codes, 36 of them in the P family. The browser check emits 21. The
gap is not a defect list: the semantic layer needs the property registry, the assay registry
and the closed vocabularies, and the physics layer needs the design-rule constants and their
citations. Shipping those to a browser tab would make the tool look like a full validator
without making it one.
The conformance vectors
Counted from wwd-spec/test-suite/index.json.
The suite carries 97 vectors: 17 valid packages and 80 invalid ones. Each entry names a file, a SHA-256 digest, the codes a conforming validator must report, the codes it must not report, and the conformance classes the package must and must not reach. 16 of the invalid vectors expect a P-family code. Those 16 are the only ones the browser check is in scope for, and it does not reach all of them.
| Vector | Expected code | Browser result |
|---|---|---|
| invalid-mimetype-not-first | P02_MIMETYPE_NOT_FIRST | Reported, same code |
| invalid-mimetype-compressed | P02_MIMETYPE_COMPRESSED | Reported, same code |
| invalid-no-manifest | P03_NO_MANIFEST | Reported, same code |
| invalid-integrity-mismatch | P05_INTEGRITY_MISMATCH | Reported, same code |
| invalid-required-extension-unsupported | P08_REQUIRED_EXT_UNSUPPORTED | Reported, same code |
| invalid-required-extension-optogenetics | P08_REQUIRED_EXT_UNSUPPORTED | Reported, same code |
| invalid-not-zip | P01_NOT_ZIP | Condition detected, emitted as P01_NOT_A_ZIP |
| invalid-mimetype-content | P02_MIMETYPE_CONTENT | Condition detected, emitted as P02_MIMETYPE_WRONG |
| invalid-unmanifested-file | P03_UNMANIFESTED | Condition detected, emitted as P06_UNDECLARED_FILE at warning severity |
| invalid-required-not-declared-used | P08_REQUIRED_NOT_IN_USED | Not in the browser code set |
| invalid-extension-prefix-unbound | P08_EXTENSION_NOT_DECLARED | Not in the browser code set |
| invalid-extension-uri-unversioned | P08_EXTENSION_URI_UNVERSIONED | Not in the browser code set |
| invalid-path-traversal | P07_UNSAFE_PATH, I01_NO_PACKAGE_ID | Not in the browser code set |
| invalid-geometry-no-frame | P11_ASSET_NO_FRAME | Not in the browser code set |
| invalid-geometry-no-units | P12_ASSET_NO_UNITS | Not in the browser code set |
| invalid-geometry-ambiguous-target | P13_ASSET_AMBIGUOUS | Not in the browser code set |
The browser check reports the exact expected code for 6 vectors and detects the defect under a different code name for 3 more. For the remaining 71 invalid vectors the expected codes are not in the browser code set, so those packages pass the browser check without a finding. A file that opens cleanly here can still be a package the suite classes as invalid.
Running the full check
Two implementations, both offline.
cd wwd-spec/validator
python3 -m venv .venv
./.venv/bin/pip install pytest
# validate one package
./.venv/bin/python -m wwd path/to/package.wwd
# cross-check against the JSON Schemas
./.venv/bin/python -m wwd path/to/package.wwd --schema
# the design rules
./.venv/bin/python -m wwd path/to/package.wwd --dfm
# the causal projection
./.venv/bin/python -m wwd path/to/package.wwd --causal Python 3.11 or later, standard library only at runtime. Three layers, and the README states they must agree.
cd wwd-spec/validator-ts
npm install
npm run build # tsc -> dist/
npm test # the test files under test/
# validate one package
node dist/cli.js path/to/package.wwd
node dist/cli.js --json path/to/package.wwd
# run the published suite
npm run suite Node 18 or later. One runtime dependency, fflate, for raw DEFLATE. It runs in the browser and in Node, and it implements all three layers, so it is the option when a full check is wanted without a Python environment.
python3 wwd-spec/test-suite/run_suite.py --validator "python3 -m wwd --json"
python3 wwd-spec/test-suite/run_suite.py --validator "node dist/cli.js --json"
The runner reads each vector, verifies its SHA-256, invokes the validator named by --validator, and compares the codes reported against the manifest. Reporting a
code the suite does not mention is permitted. Downgrading a listed error to a warning is
not.
What a clean result supports
Claims a browser pass does and does not carry.
| Claim | Status |
|---|---|
| The archive is a readable ZIP with a walkable central directory. | Supported |
| The mimetype member is first, STORED and correct. | Supported |
| A manifest and a root design document are present and parse as JSON. | Supported |
| Every file the manifest declares is present, is the declared length and matches its declared SHA-256 digest. | Supported |
| No file is carried in the archive without a manifest record. | Supported |
| The package reaches WWD-Package-Core. | Not supported |
| The package reaches any conformance class. | Not supported |
| References, identities, units, frames and causal roles hold together. | Not supported |
| The acceptance disposition is what the package says it is. | Not supported |
| The design passes the DFM rules. | Not supported |
| The package is valid WWD 0.1. | Not supported |
The tool prints a disposition of pass, pass with warnings, or fail. That disposition is over the container layer only. It is not the acceptance disposition of section 17, which is recomputed from measured results, and it is not a conformance class under section 22. A package that manufactures correctly and a package with unresolvable references produce the same clean container result.
Questions
Scope, codes and commands.
Is the file uploaded anywhere?
No. The tool reads the file in the page and validates it with DecompressionStream and crypto.subtle. There is no request carrying the bytes. The file never leaves the machine.
What does a clean result mean?
It means the container layer found no error: the archive is a readable ZIP, the mimetype member is first and STORED and correct, a manifest and a root design document parse as JSON, and every declared file is present at the declared length with a matching SHA-256 digest. It does not mean the package is valid WWD 0.1, and it does not award a conformance class.
How many diagnostic codes does the browser check emit?
Twenty-one, across the families P01, P02, P03, P04, P05, P06 and P08. Of those, 16 are raised as errors, 4 as warnings and 1 as info. The Python reference in wwd-spec/validator/wwd/ carries 233 distinct codes, 36 of them in the P family.
Why does the browser check parse the central directory instead of the local headers?
Entry order is normative for the mimetype rule, and the central directory is the authoritative listing of a ZIP archive. The local header is read afterwards for each entry, because its name and extra-field lengths can differ from the central copy and the payload offset depends on them.
Do the browser code names match the codes in Appendix C?
Most do. Four differ: the browser emits P01_NOT_A_ZIP where the reference emits P01_NOT_ZIP, P02_MIMETYPE_WRONG where the reference emits P02_MIMETYPE_CONTENT, P06_UNDECLARED_FILE where the reference emits P03_UNMANIFESTED, and P04_NO_VERSION and P04_MEDIATYPE_MISMATCH where the reference emits P03_VERSION and P03_MEDIATYPE. Compare against the reference validator when a code name matters.
How many conformance vectors would the browser check catch?
The suite has 97 vectors, of which 17 are valid and 80 are invalid. Sixteen invalid vectors expect a P-family code. The browser check emits the exact expected code for six of them, detects the same defect under a different code name for three more, and has no code in its set for the remaining 71 invalid vectors.
How do I run the full check?
The Python reference is python3 -m wwd path/to/package.wwd, with --schema, --dfm and --causal for the other layers. The TypeScript validator is npm install and npm run build in wwd-spec/validator-ts, then node dist/cli.js path/to/package.wwd. Both run the published suite through wwd-spec/test-suite/run_suite.py with a --validator argument.
Which validator should a second implementer test against?
Neither. The conformance suite is the reference: each vector states the codes a conforming validator must report, the codes it must not report, whether the package is valid, and the classes it must and must not reach. A disagreement between an implementation and the suite is a finding about one of the two.
Continue
Related pages.
- The browser tool. Drop a .wwd file and read the findings.
- Conformance. The test vectors and the six conformance classes.
- The WWD file format. Container, manifest, design and results documents.
- Geometry and payloads. The manifest record, media type and SHA-256 integrity that carry a payload.
- Design rules. The physics layer, its thresholds and its sources.
- Downloads. The schemas, the validators, the examples and the suite.
- The WWD 0.1 draft specification. All normative sections with anchors.