docs: refresh README for the current layout; ASCII sweep on SECURITY.md
This commit is contained in:
+9
-9
@@ -5,17 +5,17 @@ as acceptance criteria, not polish.
|
||||
|
||||
## Attack surface
|
||||
|
||||
- **Static output** — no server runtime, no database, no user input, no forms.
|
||||
- **Static output** - no server runtime, no database, no user input, no forms.
|
||||
- Served by `nginx-unprivileged` (uid 101, read-only root filesystem, all Linux
|
||||
capabilities dropped, no service-account token) on Kubernetes.
|
||||
- Exposed **outbound-only via a Cloudflare Tunnel** — no open inbound ports, a single
|
||||
- Exposed **outbound-only via a Cloudflare Tunnel** - no open inbound ports, a single
|
||||
public hostname, no catch-all.
|
||||
|
||||
## Headers
|
||||
|
||||
Split by where they belong:
|
||||
|
||||
**Origin (nginx, ships in the image — `nginx/security-headers.conf`)**
|
||||
**Origin (nginx, ships in the image - `nginx/security-headers.conf`)**
|
||||
|
||||
| Header | Value |
|
||||
|---|---|
|
||||
@@ -23,11 +23,11 @@ Split by where they belong:
|
||||
| X-Content-Type-Options | `nosniff` |
|
||||
| X-Frame-Options | `DENY` |
|
||||
| Referrer-Policy | `strict-origin-when-cross-origin` |
|
||||
| Permissions-Policy | camera/mic/geo/payment/usb… all denied |
|
||||
| Permissions-Policy | camera/mic/geo/payment/usb... all denied |
|
||||
| Cross-Origin-Opener-Policy | `same-origin` |
|
||||
| Cross-Origin-Resource-Policy | `same-origin` |
|
||||
|
||||
**Edge (Cloudflare dashboard)** — HSTS, HTTP→HTTPS redirect, SSL Full, Bot Fight,
|
||||
**Edge (Cloudflare dashboard)** - HSTS, HTTP->HTTPS redirect, SSL Full, Bot Fight,
|
||||
rate-limiting. HSTS ships **without** `includeSubDomains`/`preload` initially because
|
||||
`*.bztmon.com` resolves to the WAN and the subdomain form would brick non-public hosts.
|
||||
|
||||
@@ -36,7 +36,7 @@ rate-limiting. HSTS ships **without** `includeSubDomains`/`preload` initially be
|
||||
- **`script-src 'self'` with zero inline scripts.** All JS (pre-paint theme, toggle,
|
||||
scroll reveal) lives in one external `/site.js`. No `unsafe-inline`, no `unsafe-eval`,
|
||||
no hashes to maintain.
|
||||
- **`style-src` allows `'unsafe-inline'`** — the one conscious exception. Shiki's
|
||||
- **`style-src` allows `'unsafe-inline'`** - the one conscious exception. Shiki's
|
||||
dual-theme syntax highlighting emits per-token CSS custom-properties as inline `style`
|
||||
attributes; hashing them is impractical (they vary per page). The security-critical
|
||||
directive (`script-src`) stays strict. Everything else is self-hosted: fonts are system
|
||||
@@ -55,9 +55,9 @@ Runs in CI before the image is built.
|
||||
|
||||
## Targets (verified post-deploy)
|
||||
|
||||
- securityheaders.com → A+
|
||||
- Mozilla Observatory → A/A+ (small deduction expected for `style-src 'unsafe-inline'`)
|
||||
- Lighthouse ≥ 95 across Performance / Accessibility / Best Practices / SEO
|
||||
- securityheaders.com -> A+
|
||||
- Mozilla Observatory -> A/A+ (small deduction expected for `style-src 'unsafe-inline'`)
|
||||
- Lighthouse >= 95 across Performance / Accessibility / Best Practices / SEO
|
||||
- CSP: zero console violations in a real browser (incl. code blocks + diagrams)
|
||||
|
||||
## Reporting
|
||||
|
||||
Reference in New Issue
Block a user