{
	email office@linumiq.com
	on_demand_tls {
		# SECURITY (R2/F3): closed allow-list authorizer. The edge function returns
		# 200 only for reserved hosts (apex/app/api) and subdomains registered in
		# the tunnels table; 403 otherwise. This prevents unbounded on-demand
		# certificate issuance for arbitrary hostnames.
		ask http://supabase-edge-functions:9000/check-subdomain
	}
}

# SECURITY (R4/F10/W5): baseline response-hardening headers applied to the
# LinumIQ-controlled surfaces (apex/app/api). HSTS forces HTTPS for a year and
# is safe for first-party hostnames we fully control.
(security_headers) {
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
		X-Content-Type-Options "nosniff"
		X-Frame-Options "SAMEORIGIN"
		Referrer-Policy "no-referrer"
		Permissions-Policy "geolocation=(), microphone=(), camera=()"
		Cross-Origin-Opener-Policy "same-origin"
		-Server
		-X-Powered-By
	}
}

# Apex -> dashboard redirect
linumiq.net {
	tls {
		on_demand
	}
	import security_headers
	redir https://app.linumiq.net{uri} permanent
}

# Reserved hostname: Next.js dashboard (upstream not yet running in Wave A)
app.linumiq.net {
	tls {
		on_demand
	}
	import security_headers
	reverse_proxy web:3000
}

# Reserved hostname: Supabase API (Kong)
api.linumiq.net {
	tls {
		on_demand
	}
	import security_headers
	# SECURITY (R2): block machine-only webhook functions from the public edge.
	# auth-webhook and stripe-webhook are invoked internally over the docker
	# network (supabase-edge-functions:9000) and must never be callable from the
	# internet. get-node stays public for the Home Assistant add-on.
	@blocked_webhooks path /functions/v1/auth-webhook* /functions/v1/stripe-webhook*
	respond @blocked_webhooks 403
	reverse_proxy supabase-kong:8000
}

# Wildcard tunnel subdomains -> frps vhost HTTP. Per-name HTTP-01 issued on first hit.
# NOTE: only HSTS is injected here; Home Assistant sets its own security headers
# (X-Frame-Options, etc.) and we must not override its CSP / framing behaviour.
*.linumiq.net {
	tls {
		on_demand
	}
	header Strict-Transport-Security "max-age=31536000; includeSubDomains"
	reverse_proxy frps:7080
}

# ============================================================================
# DEV environment (served by this same shared Caddy instance).
# Dev upstreams live on the external "dev_edge" network; Caddy is dual-homed on
# both "edge" (prod) and "dev_edge" (dev). On-demand TLS for these hosts is
# authorized by the global ask endpoint, which recognises the dev hostnames.
# ============================================================================

# Dev dashboard (Next.js, dev build)
app-dev.linumiq.net {
	tls {
		on_demand
	}
	import security_headers
	reverse_proxy web-dev:3000
}

# Dev Supabase API (dev Kong)
api-dev.linumiq.net {
	tls {
		on_demand
	}
	import security_headers
	@blocked_webhooks path /functions/v1/auth-webhook* /functions/v1/stripe-webhook*
	respond @blocked_webhooks 403
	reverse_proxy supabase-dev-kong:8000
}

# Dev wildcard tunnel subdomains -> dev frps vhost HTTP. More specific than
# *.linumiq.net, so dev tunnels match here. Only HSTS injected (HA sets its own
# framing/CSP headers).
*.dev.linumiq.net {
	tls {
		on_demand
	}
	header Strict-Transport-Security "max-age=31536000; includeSubDomains"
	reverse_proxy frps-dev:7080
}
