docs: direct-embed vs staging framing contract — serving-layer owns frame-ancestors (direct=* , staging=self); per-host recipes
This commit is contained in:
parent
ee3ebf8700
commit
9cc8053ec2
1 changed files with 25 additions and 0 deletions
|
|
@ -55,3 +55,28 @@ Both are supported on **built** pages. The one "never iframe" rule applies only
|
|||
staging** script (`internal/staging.js`), which mounts elements directly because a dev-server
|
||||
iframe crosses realms (`instanceof` breaks). Built pages have no such problem — the generated
|
||||
staging (`staging-forge.js`) itself uses an iframe stage.
|
||||
|
||||
## Direct-embed vs staging — the framing contract (serving layer)
|
||||
|
||||
The built tree has TWO kinds of page, and they need DIFFERENT framing policy:
|
||||
|
||||
| Surface | Paths | `frame-ancestors` |
|
||||
|---|---|---|
|
||||
| **Direct embed** (the product) | `<bundle>/<profile>/index.html`, `<bundle>/<profile>/<instance>/index.html` — the bare map pages the manifest's `iframeUrl` points at | **`*`** — framable on any partner site (that's the whole point) |
|
||||
| **Staging** (internal preview) | tree root `index.html`, per-bundle `<bundle>/index.html`, the SPA shell | **`'self'`** — preview only |
|
||||
|
||||
`frame-ancestors` can ONLY be set by an HTTP response header (HTML `<meta>` cannot set it), so
|
||||
**the server/CDN owns this split — the bundler cannot enforce it.** Whoever serves the tree must
|
||||
apply it. Rule of thumb: **a path with ≥2 directory segments under the tree root is a direct-embed
|
||||
page → serve it framable.**
|
||||
|
||||
Portable ways to implement the split, by host:
|
||||
- **Traefik** (nuxtbase/go-base): a higher-priority router on `PathRegexp(^/plugin-assets/[^/]+/[^/]+/)`
|
||||
sets `Content-Security-Policy: frame-ancestors *` + clears `X-Frame-Options`. (Live example:
|
||||
`/data/coolify/proxy/dynamic/doxa-maps-embed.yaml`.)
|
||||
- **Cloudflare Pages / Netlify**: a `_headers` file — `/<bundle>/*/* Content-Security-Policy: frame-ancestors *`.
|
||||
- **Nginx**: `location ~ ^/[^/]+/[^/]+/ { add_header Content-Security-Policy "frame-ancestors *"; }`
|
||||
- **GitHub Pages**: serves no custom headers → pages are framable by default (no frame-ancestors), which is already correct for direct embeds.
|
||||
|
||||
If you serve the WHOLE tree with one blanket `frame-ancestors 'self'`, direct embeds break on
|
||||
partner sites (the staging policy leaks onto the product pages). That is the one mistake to avoid.
|
||||
|
|
|
|||
Loading…
Reference in a new issue