From a6b5e72bb6854c027dfd35d2cd18e93cd6d90d1e Mon Sep 17 00:00:00 2001 From: Bretton Date: Sat, 3 Oct 2026 17:48:58 -0700 Subject: [PATCH] feat(delegation): reconcile every 15 minutes and add an admin reconcile route The delegation reconciler's Run loop makes a pass at startup without waiting, then every 15 minutes, matching the community reconciler. A failed pass is logged and the loop continues. Passes are serialized with a context-aware slot: a Reconcile call made during a pass waits for it, then runs its own, and a caller cancelled while waiting returns its context error without starting a pass. This is the only guard on the hourly budget, which each pass derives from the created_on timestamps in the NS listing. POST /admin/dns/reconcile sits behind the existing admin bearer and runs one pass synchronously: 200 with the result as JSON, 500 with {error, result} when the pass fails (so a ceiling stop still shows the pending, deferred and ceiling figures), 501 when no reconciler is set. The route has a 10-minute write deadline. Scheduled and forced passes log the same LogPass summary. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.md | 3 +- cmd/tidepool/delegation_test.go | 57 ++++- cmd/tidepool/main.go | 34 +-- internal/config/config.go | 2 +- internal/delegation/reconciler.go | 97 ++++++- internal/delegation/reconciler_test.go | 71 +++-- internal/delegation/run_test.go | 219 ++++++++++++++++ internal/ingest/dns_reconcile_test.go | 341 +++++++++++++++++++++++++ internal/ingest/follow.go | 41 +++ 9 files changed, 800 insertions(+), 65 deletions(-) create mode 100644 internal/delegation/run_test.go create mode 100644 internal/ingest/dns_reconcile_test.go diff --git a/README.md b/README.md index 3144990..576fc97 100644 --- a/README.md +++ b/README.md @@ -323,7 +323,7 @@ Two classes, and the difference matters at boot: | `DNS_PUBLIC_IPV4` | *(unset)* | IPv4 address returned in A answers; required when `DNS_LISTEN` is set | | `DNS_PUBLIC_IPV6` | *(unset)* | optional IPv6 address returned in AAAA answers when DNS is enabled | | `DNS_NAMESERVERS` | `ns1`/`ns2` under `BRIDGE_HOSTNAME` when DNS is enabled | comma-separated nameserver hostnames returned in apex NS answers (first is the SOA primary) | -| `CLOUDFLARE_API_TOKEN` | *(empty; disabled)* | Cloudflare API token with DNS edit on the zone; enables a startup pass creating `