# Caddy на VPS (186.246.51.17) — единственная публичная точка входа.
# Два домена, ОБА с твоими сертификатами; проксируют в SSH-туннели:
#
#   forbiddenstars.ru   → 127.0.0.1:9000  ← Pi  (autossh, постоянно)   PROD
#   forbidden-stars.ru  → 127.0.0.1:9001  ← ПК  (по требованию)        DEV/TEST
#
# Caddy сам терминирует TLS (он и есть edge: видит реального клиента), а вниз к
# приложению передаёт X-Forwarded-Proto=https / X-Forwarded-For / Host —
# приложение это учитывает (uvicorn --proxy-headers). Положи файл в /etc/caddy/Caddyfile.
#
# X-Forwarded-For ПЕРЕЗАПИСЫВАЕМ реальным пиром (header_up ... {remote_host}), а не
# добавляем: иначе клиент мог бы подставить своё левое значение и подменить IP для
# throttle и аудита (#58). Вместе с сужением forwarded-allow-ips в entrypoint.sh это
# делает клиентский IP достоверным.
# Сертификаты — см. deploy/vps/README.md (fullchain = leaf + промежуточные одним файлом).
#
# SSE (/api/events): отдельный handle БЕЗ encode и с flush_interval -1 — иначе сжатие/
# буферизация задержат поток событий (реал-тайм перестанет работать).
#
# Туннель лёг (апстрим недоступен) → reverse_proxy отдаёт 502/503/504, и сниппет (edge)
# подменяет ответ на страницу-заглушку (/etc/caddy/maintenance/maintenance.html) вместо
# «зависшей загрузки» SPA. Тот же сниппет запрещает кэш HTML-документа (Cache-Control: no-store),
# иначе браузер отдаёт старый index.html из кэша и до Caddy/заглушки запрос не доходит.
# Файл заглушки — deploy/vps/maintenance.html.

# Edge-поведение, общее для сайтов: security-заголовки + запрет кэша HTML + заглушка при падении апстрима.
(edge) {
	# Security-заголовки (#61). HSTS — принудительный HTTPS на год с поддоменами; nosniff —
	# запрет MIME-sniffing; frame DENY — защита от кликджекинга (наши страницы нельзя встроить
	# в чужой iframe); Referrer/Permissions — минимизация утечек. Server скрываем, чтобы не
	# светить используемый прокси.
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
		X-Content-Type-Options "nosniff"
		X-Frame-Options "DENY"
		Referrer-Policy "strict-origin-when-cross-origin"
		Permissions-Policy "geolocation=(), microphone=(), camera=()"
		-Server
	}

	# Content-Security-Policy подготовлена, но ВЫКЛЮЧЕНА до проверки на test-клоне: строгая
	# политика легко ломает SPA (инлайновые стили Vite), Telegram-виджет входа (скрипт с
	# telegram.org + iframe oauth.telegram.org) и EventSource (/api/events). Раскомментировать
	# после проверки на forbidden-stars.ru, что вход и реал-тайм работают (#61).
	# header Content-Security-Policy "default-src 'self'; script-src 'self' https://telegram.org https://oauth.telegram.org; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self'; frame-src https://oauth.telegram.org; font-src 'self' data:; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"

	# HTML-документ (навигации, Accept: text/html) НЕ кэшируем. Иначе браузер отдаёт старый
	# SPA из кэша без сетевого запроса → запрос не доходит до Caddy и заглушку не видно.
	# Хэшированные ассеты (JS/CSS) под это не попадают (у них другой Accept) и кэшируются как обычно.
	@html header Accept *text/html*
	header @html Cache-Control "no-store"

	# Туннель лёг (апстрим 502/503/504) → отдаём свою страницу-заглушку со статусом 503.
	handle_errors {
		@down expression `{http.error.status_code} in [502, 503, 504]`
		handle @down {
			root * /etc/caddy/maintenance
			rewrite * /maintenance.html
			header Cache-Control "no-store"
			file_server {
				status 503
			}
		}
	}
}

forbiddenstars.ru {
	tls /etc/caddy/certs/forbiddenstars.ru/fullchain.pem /etc/caddy/certs/forbiddenstars.ru/privkey.pem
	@sse path /api/events
	handle @sse {
		reverse_proxy 127.0.0.1:9000 {
			flush_interval -1
			header_up X-Forwarded-For {remote_host}
		}
	}
	handle {
		encode zstd gzip
		reverse_proxy 127.0.0.1:9000 {
			header_up X-Forwarded-For {remote_host}
		}
	}
	import edge
}

forbidden-stars.ru {
	tls /etc/caddy/certs/forbidden-stars.ru/fullchain.pem /etc/caddy/certs/forbidden-stars.ru/privkey.pem
	@sse path /api/events
	handle @sse {
		reverse_proxy 127.0.0.1:9001 {
			flush_interval -1
			header_up X-Forwarded-For {remote_host}
		}
	}
	handle {
		encode zstd gzip
		reverse_proxy 127.0.0.1:9001 {
			header_up X-Forwarded-For {remote_host}
		}
	}
	import edge
}
