fix(dns): match apex records stored under any apex spelling

toSource always writes the apex as ".", but listRecords already accepted "" and
"@" as apex spellings on read. The upsert lookup compared sources strictly, so a
record stored under one of the other spellings would not have matched and the
upsert would have created a duplicate apex record instead of updating it.

Normalize the candidate's source before comparing, so read and match agree.

Reported by Greptile on #5257.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guillaume Juge
2026-09-01 16:28:04 +02:00
parent 2bc22c520d
commit be4a5da405
2 changed files with 31 additions and 1 deletions
+8 -1
View File
@@ -71,6 +71,12 @@ const toSource = (name: string, zone: string) => {
const toFqdn = (source: string, zone: string) =>
APEX_SOURCES.has(source) ? zone : `${source}.${zone}`;
// toSource always writes the apex as ".", so an existing record stored under one
// of the other apex spellings has to normalize to the same thing before it can
// be matched.
const normalizeSource = (source: string) =>
APEX_SOURCES.has(source) ? "." : source;
// TXT targets are stored quoted; keep Dokploy's view of them unquoted so that
// editing a record does not stack a new pair of quotes on every save.
const unquoteTarget = (target: string) => {
@@ -146,7 +152,8 @@ export const infomaniakClient: DnsClient<InfomaniakConfig> = {
const existing = await listZoneRecords(config, record.zoneId);
const match = existing.find(
(candidate) =>
candidate.type === record.type && candidate.source === source,
candidate.type === record.type &&
normalizeSource(candidate.source) === source,
);
const body = JSON.stringify(recordPayload(record, record.zoneId));