# Privacy, security and deployment ## Data flow Colour input, saved palette entries, selected image bytes, decoded pixels and generated exports stay in the browser. The application does not issue API requests, load remote fonts, submit analytics or resolve remote colour references. A saved palette belongs to the current browser origin and is stored until the user clears it or browser storage is removed. Images are in-memory only. The static host still receives ordinary requests for HTML, JavaScript, CSS, icons and worker files on initial load and revalidation. Host logs, reverse proxy logs and browser extension behaviour are outside the application's local processing boundary. DTCG documents and gradient recipes are parsed/generated in memory only. DTCG references are restricted to the same pasted JSON document; no URI or remote token resolver is used. Token/group depth, count and source size are bounded, and cycles stop with diagnostics. Imported names/values and gradient CSS are rendered as text or style values, never injected as HTML. ## Recommended headers Serve the static artifact over HTTPS and apply a policy equivalent to: ```text Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; worker-src 'self' blob:; manifest-src 'self' Cross-Origin-Opener-Policy: same-origin Cross-Origin-Resource-Policy: same-origin Permissions-Policy: camera=(), microphone=(), geolocation=(), usb=(), payment=() Referrer-Policy: no-referrer X-Content-Type-Options: nosniff ``` The shared Toolbox shell uses inline style properties for colour previews, so `style-src 'unsafe-inline'` is currently required. Do not add `script-src 'unsafe-inline'` or third-party script origins. `blob:` is required for local image object URLs and may be used for a worker fallback. Serve `.js` as `text/javascript`, `.json` as `application/json`, `.webmanifest` as `application/manifest+json`, and `.svg` as `image/svg+xml`. Hashed assets may use a long immutable cache lifetime; keep `index.html`, `sw.js` and `toolbox-app.json` on revalidation/no-cache so releases update predictably. ## Reverse-proxy example For an nginx deployment rooted at `/apps/colour/`, use `try_files` only to resolve actual static files and the directory index; do not rewrite missing asset paths to HTML. The application itself uses relative paths and needs no server-side router. Keep the `sw.js` scope at the application directory. If the app is assembled into toolbox-portal, use the portal's release lock and assembly process instead of unpacking files into an existing live directory. Verify the ZIP against its SHA-256 sidecar before assembly. ## File limits and cleanup The image picker enforces encoded-byte, dimension and decoded-pixel limits before expensive processing. Sampling radius and palette colour counts are bounded. Object URLs, decoded buffers and worker requests are released or cancelled when replaced. Browsers and image decoders remain security-sensitive dependencies, so deploy current supported browser versions and publish patched application releases promptly. See [SECURITY.md](../SECURITY.md) for private reporting instructions.