# Caddy config for serving the standalone Nosterm client SPA.
#
# In production, replace `:80` with your domain to get automatic HTTPS, e.g.:
#   nosterm.example.com { ... }
#
# The `/relay*` proxy is OPTIONAL. It lets the client reach a relay on the same
# origin (ws://<host>/relay), which sidesteps mixed-content and CORS concerns.
# The upstream is configurable via the RELAY_UPSTREAM env var (default
# `relay:3334`, the service name in this dir's docker-compose.yml). If you point
# the client directly at an external relay via PUBLIC_DEFAULT_RELAYS, you can
# delete the `handle /relay*` block.

:80 {
	encode gzip zstd

	# Tor-overlay relay bridge: proxy to a clearnet→onion bridge sidecar that
	# forwards through Tor to an onion-only relay. Exposing it at a same-origin
	# wss:// path lets a plain browser reach the onion relay without Tor Browser
	# and without an HTTPS-page/insecure-ws mixed-content block. Only wired when
	# RELAY_TOR_UPSTREAM is set (the demo deploy sets it); otherwise it points at
	# a dead default and simply 502s, which is harmless if unused. MUST precede
	# the /relay* block below, which would otherwise swallow this prefix.
	handle /relay-tor* {
		reverse_proxy {$RELAY_TOR_UPSTREAM:tor-bridge:3335}
	}

	# Home relay: proxy WebSocket + NIP-11 requests to the configured relay.
	handle /relay* {
		reverse_proxy {$RELAY_UPSTREAM:relay:3334}
	}

	# Runtime client config: regenerated by the entrypoint from env on startup.
	# Never cache it so per-deployment relay changes take effect immediately.
	handle /config.json {
		root * /srv
		header Cache-Control "no-store"
		file_server
	}

	# Everything else: serve the static SPA with client-side-routing fallback.
	handle {
		root * /srv
		try_files {path} /index.html
		file_server
	}

	# Baseline security headers. No third-party analytics are ever included.
	header {
		X-Content-Type-Options nosniff
		X-Frame-Options DENY
		Referrer-Policy no-referrer

		# Content-Security-Policy for a client-only SPA:
		#  - default-src 'self'          only same-origin by default
		#  - connect-src wss:/ws:        reach ANY relay the user configures (core)
		#  - connect-src https:          NIP-05 verification fetches a domain's
		#                                /.well-known/nostr.json over HTTPS. Read-only
		#                                JSON GETs; no credentials are ever sent.
		#  - script-src 'unsafe-inline'  required for SvelteKit's hydration
		#                                bootstrap + the anti-FOUC theme script,
		#                                which are inlined into the static fallback
		#                                page (not prerendered, so hashes cannot be
		#                                pinned at build time).
		#  - script-src 'unsafe-eval'   required by NDK's event-emitter dependency
		#                                (tseep), which JIT-compiles listener
		#                                dispatch via `new Function`. Only triggers
		#                                once a relay subscription opens. No REMOTE
		#                                scripts are ever allowed, and remote Nostr
		#                                content is never rendered as HTML, so it
		#                                cannot inject code.
		#  - object-src 'none'           no plugins
		Content-Security-Policy "default-src 'self'; connect-src 'self' wss: ws: https:; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
		-Server
	}
}
