Skip to content

Commit 0649409

Browse files
authored
Complete static-site migration: _headers/_redirects for 18 frontends (#1470)
The frontends moved to the @dfinity/static-site (certified-assets) recipe but kept their legacy .ic-assets.json5 configs, which certified-assets ignores — so their security headers were silently dropped and SPA fallback was gone. Replace them per the static-site skill: - Delete the 18 dead .ic-assets.json5 files. - Add frontend/public/_headers: each example's CSP ported verbatim, plus the skill's baseline hardening (X-Frame-Options, X-Content-Type-Options, Referrer-Policy) and caching (immutable assets, revalidated HTML). - Add frontend/public/_redirects with the SPA fallback /* /index.html 200. - Examples that only had a security_policy preset or X-Frame-Options and no explicit CSP (ic-pos, basic_vetkd) get the hardening headers only — no invented CSP, since a default-src 'self' would break ledger/II calls. - image-classification: its .ic-assets.json5 sat in frontend/assets/ (not the Vite publicDir), so it never reached dist even on the legacy recipe; new files go in a real frontend/public/ so its CSP is now effective. - AGENTS.md: document the _headers/_redirects convention. Verified locally (encrypted_notes + image-classification): headers land and are certified, SPA deep-link reload returns the shell. Part of #1458.
1 parent 3b714f7 commit 0649409

55 files changed

Lines changed: 269 additions & 354 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎AGENTS.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,26 @@ icp-cli applies `environment_variables` as canister settings at deploy time. Rea
203203
- Motoko: `Runtime.envVar<system>("PUBLIC_CANISTER_ID:xrc")`
204204
- Rust: `ic_cdk::api::env_var_value("PUBLIC_CANISTER_ID:xrc")` — never `env!()` (compile-time) or `std::env::var()` (no OS environment in WASM)
205205

206+
### Frontend headers and routing
207+
208+
Frontends use the `@dfinity/static-site` recipe (the certified-assets canister). Configure it with two files at the **root of the build's publish dir** — put them in `frontend/public/` (Vite's `public/` is copied to `dist/`), never in a subfolder that only gets bundled:
209+
210+
- `_headers` — security headers and caching, Netlify-style. Certified-assets ships **no default headers**, so declare them explicitly. Baseline (tighten the CSP per app; keep each example's own `connect-src`/`script-src`):
211+
```
212+
/*
213+
X-Frame-Options: DENY
214+
X-Content-Type-Options: nosniff
215+
Referrer-Policy: strict-origin-when-cross-origin
216+
Content-Security-Policy: default-src 'self'; ...
217+
/assets/*
218+
Cache-Control: public, max-age=31536000, immutable
219+
/*.html
220+
Cache-Control: public, max-age=0, must-revalidate
221+
```
222+
- `_redirects` — SPA fallback so deep-link reloads don't 404: `/* /index.html 200` (a `200` rewrite, not a redirect).
223+
224+
Do **not** use `.ic-assets.json5` — that is the legacy asset-canister config; certified-assets ignores it (it gets served as a dead asset). No HSTS in the baseline: `_headers` apply in local dev too, and a canister-served `Strict-Transport-Security` would force HTTPS on `http://…localhost`. Consult the `static-site` skill before changing these (reserved-header list, `_headers` matches the asset key not the URL, etc.).
225+
206226
---
207227

208228
## Motoko conventions

‎hosting/oisy-signer-demo/frontend/public/.ic-assets.json5‎

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
X-Frame-Options: DENY
3+
X-Content-Type-Options: nosniff
4+
Referrer-Policy: strict-origin-when-cross-origin
5+
Content-Security-Policy: default-src 'self';script-src 'self';connect-src 'self' http://localhost:* https://icp0.io https://*.icp0.io https://icp-api.io;img-src 'self' data:;style-src * 'unsafe-inline';style-src-elem * 'unsafe-inline';font-src *;object-src 'none';base-uri 'self';frame-ancestors 'none';form-action 'self';upgrade-insecure-requests;
6+
7+
# Fingerprinted build assets never change - cache them hard
8+
/assets/*
9+
Cache-Control: public, max-age=31536000, immutable
10+
11+
# HTML should revalidate so redeploys are picked up
12+
/*.html
13+
Cache-Control: public, max-age=0, must-revalidate
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* /index.html 200

‎motoko/ic-pos/frontend/public/.ic-assets.json5‎

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
X-Frame-Options: DENY
3+
X-Content-Type-Options: nosniff
4+
Referrer-Policy: strict-origin-when-cross-origin
5+
6+
# Fingerprinted build assets never change - cache them hard
7+
/assets/*
8+
Cache-Control: public, max-age=31536000, immutable
9+
10+
# HTML should revalidate so redeploys are picked up
11+
/*.html
12+
Cache-Control: public, max-age=0, must-revalidate
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* /index.html 200

‎motoko/vetkeys/basic_bls_signing/frontend/public/.ic-assets.json5‎

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
X-Frame-Options: DENY
3+
X-Content-Type-Options: nosniff
4+
Referrer-Policy: strict-origin-when-cross-origin
5+
Content-Security-Policy: default-src 'self';script-src 'self';connect-src 'self' http://localhost:* https://icp0.io https://*.icp0.io https://icp-api.io;img-src 'self';object-src 'none';base-uri 'self';frame-ancestors 'none';form-action 'self';upgrade-insecure-requests;
6+
7+
# Fingerprinted build assets never change - cache them hard
8+
/assets/*
9+
Cache-Control: public, max-age=31536000, immutable
10+
11+
# HTML should revalidate so redeploys are picked up
12+
/*.html
13+
Cache-Control: public, max-age=0, must-revalidate
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* /index.html 200

0 commit comments

Comments
 (0)