Skip to content

feat: add ip6 parameter for dual-stack IPv4/IPv6 updates - #207

Merged
willswire merged 1 commit into
mainfrom
feat/ipv6-dual-stack
Mar 4, 2026
Merged

feat: add ip6 parameter for dual-stack IPv4/IPv6 updates#207
willswire merged 1 commit into
mainfrom
feat/ipv6-dual-stack

Conversation

@willswire

@willswire willswire commented Mar 4, 2026

Copy link
Copy Markdown
Owner

Adds an optional ip6 query parameter so UniFi devices on dual-stack networks can update both the A record (via ip) and the AAAA record (via ip6) in a single request. The update function now accepts an array of records and shares the token verification and zone lookup across all updates.

Closes #[IPv6 AAAA record updates issue]

Changes

Checklist

  • I have performed a self-review of my code
  • If it is a new feature, I have added thorough tests.

Closes #181

Adds an optional `ip6` query parameter so UniFi devices on dual-stack
networks can update both the A record (via `ip`) and the AAAA record
(via `ip6`) in a single request. The `update` function now accepts an
array of records and shares the token verification and zone lookup
across all updates.

Closes #[IPv6 AAAA record updates issue]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 100% 65 / 65
🔵 Statements 100% 65 / 65
🔵 Functions 100% 5 / 5
🔵 Branches 100% 44 / 44
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/index.ts 100% 100% 100% 100%
Generated in workflow #107 for commit 2a31104 by the Vitest Coverage Report Action

@willswire
willswire merged commit d7f1fd3 into main Mar 4, 2026
4 checks passed
@willswire
willswire deleted the feat/ipv6-dual-stack branch March 4, 2026 01:50
zachthedev referenced this pull request in zachthedev/uddns Jun 11, 2026
…166)

* feat!: DNS-scoped token auth, per-record IP cache, ip6 and zone params

Closes #151.

Auth: the worker now authenticates with the API token alone. Basic
credentials still work exactly as UniFi sends them, but the username
portion is ignored; raw Bearer tokens are accepted for direct callers.
The SDK never receives an email (it only ever paired one with the
legacy global key anyway).

KV: cache keys move from ip:<email> to ip:<hostname>:<recordType> with
JSON {ip, updatedAt} values and a 30-day expirationTtl on every write,
so stale identities can no longer accumulate (the original #151
complaint). The skip decision is per record: requests where every
record matches its cached IP return without touching the zones API,
and partially cached requests only process the pending records. This
also fixes adding a new hostname while the IP is unchanged, which the
per-user key silently skipped.

Updates and notifications key off the actual DNS delta: when the
existing record already holds the target IP, no update call is made
and no notification fires; the cache is refreshed silently. ntfy
messages cover only records that actually changed.

New query parameters: ip6 adds an AAAA record per hostname for
dual-stack callers (upstream #207 parity); zone optionally restricts
record matching to one zone for parity with UniFi's native Cloudflare
DDNS scoping. Multi-zone discovery remains the default.

Migration: legacy last_ip and ip:<email> KV keys are never read again;
sweep them once with wrangler kv key delete (the namespace is a pure
cache, so wiping it entirely is also safe).

BREAKING CHANGE: Authorization headers must use the Basic scheme (as
UniFi does) or a raw Bearer token; Bearer-wrapped base64 credentials
are no longer accepted. The JSON response no longer includes
previousIp; data.records entries carry per-record updated flags.

* feat!: explicit ip4/ip6 parameters, drop legacy ip/myip/hostname

ip4 and ip6 are now the only address parameters: literals validate
against their family, and auto takes the connecting IP only when it
matches the slot's family, silently skipping otherwise so dual-stack
UniFi devices can send ip4=%i&ip6=auto without flapping (inadyn has a
single %i substitution and no IPv6 variable; verified against inadyn
2.13.0 on the target UDM). hostnames= is the sole hostname parameter.

BREAKING CHANGE: ip, myip, and hostname query parameters are removed;
the ip=auto 500-on-undeterminable path is gone (auto slots skip, and a
request with no resolvable slot is a 422).
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