- commit
- 75f5ba02495ce75a6322a568feff8393f04ba2fb
- parent
- 7e83e210ae270e106740f9368a24616b8a5c3039
- author
- Dami <dami.etoile@gmail.com>
| M | ARCHITECTURE.md | 24 | ++++++++++++------------ |
| M | README.md | 6 | +++--- |
| M | SECURITY.md | 21 | +++++++++++---------- |
| M | skills/ | 10 | ++++++---- |
| M | worker/ | 19 | ++++++++++--------- |
@@ -10,10 +10,10 @@ sides canonicalize and hash manifests identically.
1010 flowchart TB1111 CLI["Deno CLI"] -- "bearer API at control host" --> W["Worker"]1212 SHORT(["GET control/2a3f"]) -- "308" --> SITE["https://2a3f.site-domain/"]13- V(["visitor"]) -- "GET site hostname" --> C{"Workers Cache"}14- C -- "hit" --> RESP["public response"]15- C -- "miss" --> W16- W -- "tagged response" --> RESP13+ V(["visitor"]) -- "GET site hostname" --> C{"browser cache"}14+ C -- "fresh" --> RESP["public response"]15+ C -- "miss or revalidate" --> W16+ W --> RESP1717 W --> R2[("R2 blobs")]1818 W --> D1[("D1 state")]1919 ```@@ -50,12 +50,13 @@ bytes. The wildcard route accepts only exact four-character lowercase
5050 hexadecimal hostnames. Management and notification routes are not dispatched on5151 artifact hosts.5252 53-Each artifact hostname is a distinct browser origin. Origin-scoped storage,54-credentials, passkey defaults, and service-worker control therefore stay within55-one site. Artifact responses also disable `document.domain` relaxation. Until56-`SITE_DOMAIN` is registered in the Public Suffix List, WebAuthn still permits a57-site to deliberately choose that parent domain as its RP ID; applications that58-require isolation must explicitly use their exact hostname.53+Each artifact hostname is a distinct browser origin. Origin-scoped storage and54+service-worker control therefore stay within one site, and nzip's `__Host-`55+unlock cookie is host-only. Artifact responses also disable `document.domain`56+relaxation. Until `SITE_DOMAIN` is registered in the Public Suffix List, an57+artifact can still set a parent-domain cookie or deliberately choose that parent58+as its WebAuthn RP ID. Applications that require isolation must use host-only59+cookies and their exact hostname as the RP ID.5960 6061 Serving normally requires one D1 read for site state and two R2 reads for the6162 manifest and file. Public responses use `ETag` revalidation and a 60-second@@ -176,8 +177,7 @@ account-wide and Cloudflare may change them.
176177 177178 | resource | bounding strategy | usage reference |178179 | ------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |179-| Workers | short request path; cache before execution | [Workers limits](https://developers.cloudflare.com/workers/platform/limits/) |180-| Workers Cache | public content only; short TTL; mutation purge | [Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/) |180+| Workers | short path; every browser miss executes the Worker | [Workers limits](https://developers.cloudflare.com/workers/platform/limits/) |181181 | Workers Logs | invocation logs off; deterministic identity sample | [Workers Logs pricing](https://developers.cloudflare.com/workers/observability/logs/workers-logs/#pricing) |182182 | D1 | deduplicated windows, write caps, and seven-day pruning | [D1 pricing](https://developers.cloudflare.com/d1/platform/pricing/) |183183 | R2 | content deduplication, history cap, and daily GC | [R2 pricing](https://developers.cloudflare.com/r2/pricing/) |@@ -110,9 +110,9 @@ nzip
110110 └─ revoke <device-id> [--yes] revoke a notification device111111 ```112112 113-Password and TTL values are committed with content. Omitting `--password` preserves the current114-policy on an existing site; `--no-password` clears it. Directory pushes skip dotfiles and115-`node_modules` and honor a `.nzipignore` file containing one glob per line.113+Password and TTL values are committed with content. On an existing site, omitted settings preserve114+their current values; `--no-password` clears protection explicitly. Directory pushes skip dotfiles115+and `node_modules` and honor a `.nzipignore` file containing one glob per line.116116 117117 See [`cli/README.md`](cli/README.md) for detailed CLI behavior and examples.118118 @@ -7,8 +7,8 @@ enrollment, and observable abuse controls.
77 88 Sites execute at `https://<address>.<site-domain>/`, giving every address a99 distinct browser origin. Origin-scoped localStorage, IndexedDB, OPFS,10-CacheStorage, service workers, cookies, and passkey defaults are isolated11-between sites. The control-plane shorthand10+CacheStorage, service workers, and passkey defaults are isolated between sites.11+nzip's unlock cookies are host-only. The control-plane shorthand1212 `https://<control-origin>/<address>` is redirect-only and never serves artifact1313 bytes.1414 @@ -18,14 +18,15 @@ cross-origin network requests where a target permits them, and can deceive its
1818 visitors. Artifact responses disable `document.domain` relaxation so sibling1919 site hostnames cannot opt back into a shared origin.2020 21-WebAuthn has an additional domain rule: a subdomain may deliberately choose its22-registrable parent as its RP ID. On `2a3f.n.zip`, the safe per-site default is23-`2a3f.n.zip`, and passkey applications should explicitly set24-`rp.id = location.hostname`. Until `n.zip` is accepted into the Public Suffix25-List, an arbitrary site can still request the parent RP ID `n.zip`; it cannot26-request a sibling RP ID such as `ffff.n.zip`. Do not use passkeys on the control27-origin or claim hostile-tenant passkey isolation until that Public Suffix List28-boundary ships in target browsers.21+Cookies and WebAuthn have additional domain rules. Until `n.zip` is accepted22+into the [Public Suffix List](https://publicsuffix.org/), an arbitrary site can23+set a `Domain=n.zip` cookie, and it can request the parent RP ID `n.zip`. It24+cannot request a sibling RP ID such as `ffff.n.zip`. Applications should use25+`__Host-` or otherwise host-only cookies and explicitly set26+`rp.id = location.hostname`; on `2a3f.n.zip`, the RP ID is `2a3f.n.zip`. Do not27+use passkeys or application-defined cookies on the control origin, or claim28+hostile-tenant credential isolation, until that Public Suffix List boundary29+ships in target browsers.2930 3031 ## Reporting a vulnerability3132 @@ -132,10 +132,12 @@ nzip
132132 ```133133 134134 Use password protection when the content or user requires it; `nzip site push` accepts the same135-`--password <pw> | --no-password` flags to set it at publish time. Vault descriptions appear in136-`vault ls` and `status`; use them to pick the right destination, and pass `--no-description` to137-clear one. A vault rename updates the invoking client's default vault, allow-list, and local push138-records, but other clients keep the old name; renaming to a name outside `allowVaults` is refused.135+`--password <pw> | --no-password` flags to set it at publish time. On an existing target, omit136+`--ttl` and password flags to preserve both policies; pass a flag only when the user intends to137+change that setting. Vault descriptions appear in `vault ls` and `status`; use them to pick the138+right destination, and pass `--no-description` to clear one. A vault rename updates the invoking139+client's default vault, allow-list, and local push records, but other clients keep the old name;140+renaming to a name outside `allowVaults` is refused.139141 Treat `revert`, vault renames, password changes, TTL changes, and deletion as state changes; do not140142 perform them while merely diagnosing. Never infer deletion confirmation.141143 @@ -58,7 +58,8 @@ nzip uses two public surfaces:
5858 5959 The control path permanently redirects to the artifact hostname; it never serves6060 artifact bytes. This separation gives every hosted site its own browser storage,61-credentials, service workers, and default passkey relying-party ID.61+service workers, host-only nzip unlock cookie, and default passkey relying-party62+ID.6263 6364 New site builds should use `/` as their deployment base; the address is no6465 longer part of the asset path and no reservation/rebuild/repush cycle is needed.@@ -125,11 +126,13 @@ verify the deployment, and only then consider a one-year duration plus preload.
125126 126127 For passkey applications, use the exact artifact hostname as the RP ID—normally127128 `location.hostname`. Subdomains can deliberately select their registrable128-parent as a WebAuthn RP ID, so per-site origins alone do not make the parent129-domain safe for control-plane passkeys. Before hosting mutually untrusted130-passkey applications, register `SITE_DOMAIN` in the Public Suffix List and wait131-for the change to reach the browsers in scope. Until then, do not use passkeys132-with the parent `SITE_DOMAIN` RP ID.129+parent as a WebAuthn RP ID or set cookies for that parent domain, so per-site130+origins alone do not isolate those two credential mechanisms. Applications131+should use `__Host-` or otherwise host-only cookies and exact-host RP IDs. Before132+hosting mutually untrusted applications, register `SITE_DOMAIN` in the133+[Public Suffix List](https://publicsuffix.org/submit/) and wait for the change to134+reach the browsers in scope. Until then, do not use the parent `SITE_DOMAIN` for135+application cookies or passkeys.133136 134137 ## Free security alert email135138 @@ -289,9 +292,7 @@ or other sensitive data in them.
289292 290293 ```sh291294 # from the repo root292-deno install -g -f -n nzip \293- --allow-net --allow-read --allow-write --allow-env \294- cli/main.ts295+deno install -g -A -f --config deno.json -n nzip cli/main.ts295296 296297 nzip auth --server https://share.demo.dev --token <token-from-step-5>297298 nzip vault add personal # slot 0x0