1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use ;
/// Defense-in-depth response headers applied to every HTTP response (UI + `/api/v1`).
///
/// The daemon serves a browser dashboard whose buttons drive an unauthenticated loopback API
/// (create / trigger / delete routines, `POST /shutdown`), so the served responses are hardened
/// against the cheap framing / sniffing / in-page-injection vectors:
///
/// - `X-Frame-Options: DENY` + CSP `frame-ancestors 'none'` — block clickjacking of the
/// dashboard's destructive controls via `<iframe src="http://localhost:5784/">`.
/// - `X-Content-Type-Options: nosniff` — stop browsers content-sniffing a response into an
/// unintended type.
/// - `Referrer-Policy: no-referrer` — never leak the loopback URL to third parties.
/// - A CSP that locks everything to `'self'` by default and blocks `object-src`, `base-uri`, and
/// `form-action` outright — so an injected `<script>`, `<base>`, or off-origin `<form>` cannot
/// exfiltrate to or act on behalf of the unauthenticated destructive API (issue #406's
/// in-code follow-up, #551).
///
/// Two directives stay loose, by necessity rather than oversight:
///
/// - `script-src` / `style-src` carry `'unsafe-inline'`. The bundled Yew/WASM SPA
/// (`prebuilt.html`, built by `src/build/ui.rs`) self-inlines its entire wasm-bindgen JS glue
/// and base64 WASM payload into a single `<script type="module">` so the daemon ships as one
/// file with no separate static-asset serving; that payload's bytes change on every UI rebuild,
/// so a `sha256-…` hash would have to be regenerated and wired through the build script rather
/// than hardcoded, which is left as further follow-up. The page also has one inline `<style>`
/// block, and the embedded Swagger UI (`utoipa-swagger-ui`) sets inline `style="…"` attributes
/// from its React components at runtime. `script-src` additionally carries
/// `'wasm-unsafe-eval'`, required for the SPA's `WebAssembly.instantiate` call — narrower than
/// `'unsafe-eval'`, it permits WASM compilation without permitting `eval()`/`Function()`.
/// - `style-src` and `font-src` allow `https://fonts.googleapis.com` / `https://fonts.gstatic.com`
/// respectively: the dashboard still loads its webfont from Google Fonts pending #467 (tracked
/// separately in open PR #519); once that self-hosts the font, these CDN allowances should be
/// dropped in favor of `'self'`.
///
/// `img-src` allows `data:` for an inline SVG noise-texture background used by the dashboard CSS.
const SECURITY_HEADERS: & = &;
/// Inject the [`SECURITY_HEADERS`] onto every response.
pub async