# Phase 6: DNS Sync & Reconciliation **Status:** ⬜ Not Started **Parent plan:** [PLAN.md](./PLAN.md) **Domain:** backend ## Objective Implement reconciliation logic that compares expected DNS records (from active consumers) with actual Cloudflare records, and provides a sync endpoint to fix discrepancies. ## Tasks - [ ] Task 1: Add `POST /api/dns/sync` endpoint - Computes expected records from: active instances with proxy + standalone proxies - Fetches actual records from Cloudflare via ListRecords - Creates missing records (consumer exists, no CF record) - Deletes orphaned records (CF record exists, no consumer) — only for records in dns_records table - Updates dns_records table to reflect current state - Returns sync report: created N, deleted N, already_synced N - [ ] Task 2: Add helper to compute expected records - Query all instances where npm_proxy_id > 0 and status = "running" → extract FQDN - Query all standalone proxies → extract domain - Return list of expected FQDNs - [ ] Task 3: Add `DELETE /api/dns/records/{fqdn}` endpoint - Manual deletion of a specific DNS record (for orphan cleanup) - Calls provider.DeleteRecord + removes from dns_records - [ ] Task 4: Wire sync endpoint in `internal/api/dns.go` and router - [ ] Task 5: Add frontend sync button handler in DNS Records page - Call POST /api/dns/sync - Show sync report (toast or inline) - Refresh records list after sync ## Files to Modify/Create - `internal/api/dns.go` — add sync + delete endpoints - `internal/api/router.go` — register new routes - `internal/store/dns_records.go` — add helper queries (list consumers with FQDNs) - `web/src/lib/api.ts` — add syncDnsRecords(), deleteDnsRecord() functions - `web/src/routes/dns/+page.svelte` — wire sync button ## Acceptance Criteria - POST /api/dns/sync creates missing and removes orphaned records - Sync report returned with counts - Manual delete endpoint works for individual records - Frontend sync button triggers reconciliation and refreshes view - Only records tracked in dns_records table are candidates for orphan deletion (don't delete unrelated Cloudflare records) ## Notes - Safety: only delete Cloudflare records that are tracked in our dns_records table (never touch records we didn't create) - Rate limiting: Cloudflare API has rate limits, batch operations where possible - Expected records query needs to join instances + standalone_proxies with settings.domain ## Review Checklist - [ ] All tasks completed - [ ] Code follows project conventions - [ ] No unintended side effects - [ ] Build passes - [ ] Tests pass (new + existing) ## Handoff to Next Phase