Skip to content

fix(providers): bind pre-upgrade ledger receipts from live evidence - #10

Merged
reoring merged 1 commit into
mainfrom
fix/legacy-ledger-migration
Sep 12, 2026
Merged

reoring merged 1 commit into
mainfrom
fix/legacy-ledger-migration

Conversation

@reoring

@reoring reoring commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Problem

#8 keys ZoneUnit.status.recordSets[] by recordSetUID. Entries written before #8 have no UID and were ignored entirely, so after the controller roll every record the provider itself had created became Programmed=False:ProviderConflict (pmc-next 2026-09-12: 30/34 RecordSets, 13/14 EndpointRecordSets not Ready, all HTTPPublish dnsReady=false). Deleting such a claim was stuck the same way. No code ever dropped ledger entries whose spec item was gone (pmc-next: 68 entries for 32 claims).

Change

  • Route 53 / Cloudflare: a UID-less entry is a pre-upgrade receipt. It binds to the current claim incarnation in place, without a provider write, only when the receipt names exactly the desired record identity (hosted zone + name + type / record IDs covering every same-type record) and the live record already equals desired. A differing live record stays ProviderConflict. The same evidence authorizes DELETE for a deleting claim whose retained values match. Mismatched non-empty UIDs still never transfer (TestZoneReconcileDoesNotUseNoncurrentRecordSetReceipt keeps that case; its "" case moved to recordset_ledger_test.go as the evidence-bound positive/negative cases).
  • Orphaned ledger entries (no spec item) are pruned once spent: deletionCompleted, the named record absent from the hosted zone (Route 53), or no recorded IDs (Cloudflare). Orphans that still name a live record are kept: core can drop a spec item transiently (TestCloudflareZoneReconcilerCreatesARecordsThroughZoneUnit exercises that), and the entry is the only evidence of a leaked record.
  • docs/design/core-api.md "UID cutover and legacy state" and the RecordSetUID status comment/CRD description updated.

Verification

  • go test ./internal/go/providers/... ./internal/go/core/..., go vet ./..., full go test (CI task test equivalent), gofmt -l, git diff --check: clean.
  • Regenerated CRDs (controller-gen v0.17.2) and synced deploy/charts/dns-api/crds (description-only delta).
  • Not exercised live. On pmc-next the current claims were already rebound through the Zone adoption annotation; this change matters for the remaining orphans and for any other environment upgrading from pre-fix: bind DNS provider state to RecordSet incarnations #8.

Related: appthrust/platform CRD delivery owner change (Argo must render crds/ so the recordSetUID schema ships with the image).

After #8 keyed the ZoneUnit ledger by recordSetUID, UID-less entries written
before the upgrade were ignored entirely, so every record the provider had
created for a still-existing claim became Programmed=False:ProviderConflict
after the controller roll (observed on pmc-next 2026-09-12: 30/34 RecordSets).
Deleting such a claim was stuck for the same reason, and the ledger never
dropped entries whose spec item was gone.

Route 53 and Cloudflare now treat a UID-less entry as a pre-upgrade receipt
and bind it to the current claim incarnation in place when the receipt names
exactly the desired record identity and the live record already equals the
desired state; a differing live record stays a conflict. The same evidence
authorizes deletion for a deleting claim. Mismatched non-empty UIDs still
never transfer.

Providers also prune orphaned ledger entries (no spec item) once they are
spent: deletion completed, the named record is absent (Route 53), or no IDs
are recorded (Cloudflare). Orphans that still name a live record are kept as
the only evidence of a leaked record and because core can drop a spec item
transiently.
@reoring
reoring merged commit d0fb7ad into main Sep 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant