custom_domain has no unique index (lnvps_db/migrations/20260725140000_app_deployment_custom_domain.sql:6), and nothing checks that the name belongs to the deployment claiming it.
#307's probe does not close this. It compares addresses, and every deployment's hostname is <name>.<ingress_domain> behind one shared load balancer (lnvps_operator/src/app_deployments.rs:1085), so a CNAME pointed at any deployment's hostname verifies against all of them. Two deployments can both store blog.example.com, both release, and both get an ingress rule for that host in different namespaces; which one nginx serves is then creation-timestamp order. Before #307 the domain was served with no check at all, so this is not a regression, but the gap survives it.
Two separable pieces:
- A
UNIQUE index on custom_domain (over non-deleted rows) makes first claim wins explicit rather than emergent, and gives the second claimant an error instead of silence. Needs a decision on what happens to duplicates already stored.
- Actual ownership needs a per-deployment challenge — a
TXT record at _lnvps-challenge.<domain> carrying a token tied to the deployment id — which is also what would let the probe stop depending on address overlap.
Raised by Goran reviewing #318.
custom_domainhas no unique index (lnvps_db/migrations/20260725140000_app_deployment_custom_domain.sql:6), and nothing checks that the name belongs to the deployment claiming it.#307's probe does not close this. It compares addresses, and every deployment's
hostnameis<name>.<ingress_domain>behind one shared load balancer (lnvps_operator/src/app_deployments.rs:1085), so a CNAME pointed at any deployment's hostname verifies against all of them. Two deployments can both storeblog.example.com, both release, and both get an ingress rule for that host in different namespaces; which one nginx serves is then creation-timestamp order. Before #307 the domain was served with no check at all, so this is not a regression, but the gap survives it.Two separable pieces:
UNIQUEindex oncustom_domain(over non-deleted rows) makes first claim wins explicit rather than emergent, and gives the second claimant an error instead of silence. Needs a decision on what happens to duplicates already stored.TXTrecord at_lnvps-challenge.<domain>carrying a token tied to the deployment id — which is also what would let the probe stop depending on address overlap.Raised by Goran reviewing #318.