# Generated package sanitizer policy

The generated directory is an untrusted boundary. Validation is fail-closed and occurs before ZIP creation. Sanitization may remove unsafe HTML/CSS constructs, but never silently renames archive entries or guesses a MIME type.

## Canonical package

- Entry names are NFC Unicode, forward-slash, relative paths with no empty, `.` or `..` segments, controls, percent-encoded separators, Windows drive prefixes, or trailing slash. Backslashes, absolute paths, symlinks, hard links, devices, FIFOs and sockets are rejected.
- Required files are `index.html`, `document.css`, and `metadata.json`. Other files are confined to `assets/fonts`, `assets/images`, `assets/vectors`, and the optional `assets/runtime` approved-runtime directory.
- Extensions and declared MIME types must agree with the policy. Binary signatures are checked. SVG, HTML, CSS, JSON, and JavaScript must decode as UTF-8. An SVG is treated as active markup and sanitized, never accepted merely because its MIME says image.
- Every local reference must resolve to an existing allowlisted file after canonical normalization. Fragments and `https:`, `mailto:`, and `tel:` links are allowed in navigation. Asset loads are local-only. `javascript:`, `data:`, `blob:`, protocol-relative URLs, credentials, controls, and encoded traversal are rejected.
- HTML event handlers, executable embeds, refresh navigation, inline scripts, and unapproved scripts are forbidden. Scripts are disabled by default; a runtime must be explicitly approved by canonical path and SHA-256 digest. CSS forbids imports, remote URLs, expressions, script schemes, and browser-binding behavior. SVG forbids scripts, event handlers, foreign objects, external references, and animation.
- The emitted CSP is `default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; object-src 'none'; script-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'none'; media-src 'none'; frame-src 'none'; worker-src 'none'; manifest-src 'none'`. Approved runtime scripts require a separately generated hash-based `script-src`; `unsafe-inline`, `unsafe-eval`, wildcard and network sources remain forbidden.

## Default ceilings

Limits are internal safety controls, not advertised product limits: 2,000 files, 64 MiB per file, 256 MiB unpacked total, 128 MiB ZIP, path length 240 UTF-8 bytes, compression ratio 100:1, 2,000,000 DOM nodes, 16 MiB HTML, and 32 MiB CSS. Any missing measurement or exceeded ceiling rejects the package.

## Deterministic ZIP

Entries are sorted by UTF-8 canonical path bytes, unique, and stored without directory records. ZIP64, encryption, comments, extra fields and data descriptors are forbidden. Creator is Unix, regular-file mode is `0644`, timestamp is the DOS epoch `1980-01-01T00:00:00Z`, and compression is DEFLATE level 9. CRC-32 and sizes must match the validated bytes. Extraction repeats canonical-path, type, size, ratio and destination-containment checks rather than trusting central-directory metadata.
