You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Release:v4.6.0-beta1 — published 2026-04-14 Target for stable ship: Netbox 4.6.0 final (ETA unknown, typically 4-6 weeks after beta1) Current PowerNetbox target: 4.5.7 (via netbox-docker 4.0.2)
This issue documents a deep analysis of what needs to change in PowerNetbox to reach full 4.6 compatibility, and proposes a phased test strategy. It is intended as the parent tracking issue — follow-up implementation PRs will carve out the per-area work.
TL;DR
No netbox-docker image exists for 4.6 yet. Both release and develop branches still pin to VERSION=4.0.2 (for Netbox 4.5.x). This is the hard blocker for adding a 4.6 row to .github/workflows/compatibility.yml. We will need to build a custom Dockerfile against netbox:v4.6.0-beta1 ourselves — mirroring the pattern already used for Dockerfile.branching.
3 brand-new models require 12 new PowerNetbox functions (Get/New/Set/Remove × 3): VirtualMachineType, CableBundle, RackGroup (reintroduced as a flat model separate from Location).
2 structural REST API changes touch InvokeNetboxRequest itself — the central helper used by all 522 functions:
ETag + If-Match (#21356) — new response header + opt-in request header for optimistic locking, plus a new 412 Precondition Failed status the error handler must understand.
Cursor-based pagination (start param, #21363) — performance-oriented alternative to offset. Non-breaking, but worth plumbing through -All so large list endpoints stay constant-time.
Django 6.0 upgrade (#20984) is the biggest unmeasured risk. It is infrastructure, not feature work, but historically Django major bumps reshape error bodies, serializer edge cases, and auth backend behavior — exactly the surfaces PowerNetbox's InvokeNetboxRequest and BuildDetailedErrorMessage parse.
1 semi-breaking change on VM creation:#12024 makes cluster optional on VirtualMachine (VMs can now attach to a device without a cluster). New-NBVirtualMachine -Cluster must relax from [Parameter(Mandatory)] to optional.
Parallel to DeviceType for physical hardware. Will likely be FK'd from VirtualMachine via a new type field.
CableBundle (#20151)
/api/dcim/cable-bundles/
Get/New/Set/Remove-NBDCIMCableBundle
Groups cables into managed runs. Explicitly not for individual fiber strands — useful callout for docs.
RackGroup (#20961)
/api/dcim/rack-groups/
Get/New/Set/Remove-NBDCIMRackGroup
Reintroduction of a flat model removed in an earlier version. Independent of Location hierarchy; Rack gets a new optional FK; VLANGroup can scope to RackGroup. Watch for the FK addition on existing endpoints.
Effort estimate: 12 new functions × (implementation + ~6 unit tests each) ≈ 72 new tests. Follow the templates in CLAUDE.md — each function is ~30 LOC of the standard New/Set/Get/Remove pattern.
1.2 REST API structural changes (affect InvokeNetboxRequest)
ETag / If-Match (#21356) — HIGH impact on helper layer
Every GET on a single object now returns an ETag header derived from last_updated. Clients may opt in to optimistic locking by passing If-Match: <etag> on subsequent PUT/PATCH — on mismatch the server returns HTTP 412 Precondition Failed.
Required changes in Functions/Helpers/InvokeNetboxRequest.ps1:
Capture ETag from the response headers and surface it on returned objects (either as PSObject.Properties.Add('_etag', ...) or via a parallel -OutVariable pattern).
Add an optional -IfMatch parameter that injects the If-Match header.
Map HTTP 412 to a new ErrorCategory (probably WriteError with a ConcurrentUpdateDetected error ID) in the central error handler so callers can catch it cleanly.
No Set- function changes are strictly required* — ETag support is opt-in. But we should add a -IfMatch passthrough on Set-* functions that have high concurrent-edit risk (devices, interfaces, IP addresses) in a follow-up PR.
Test coverage gap: we have zero tests for 412 responses today. Add one to ErrorHandling.Tests.ps1.
Cursor-based pagination (start param, #21363) — MEDIUM impact
The new start parameter filters for pk >= start instead of scanning offset rows, so large list endpoints become O(page_size) instead of O(offset + page_size). Existing limit/offset is unchanged.
Options:
A. Do nothing. Existing pagination keeps working. Users on 4.6 just don't get the perf benefit.
B. Add -Start <uint64> to all Get functions. Trivial — one line in BuildURIComponents. Exposes the param surface but most users won't notice.
C. Teach InvokeNetboxRequest -All to prefer start over offset when the connected Netbox is ≥4.6. Biggest win, small risk. This is where PowerNetbox actually differentiates: -All on a device list of 50k rows goes from ~25 roundtrips of growing latency to 25 roundtrips of constant latency.
Recommendation: do B + C. Gate the InvokeNetboxRequest change on \$script:NetboxConfig.ParsedVersion -ge [version]'4.6.0' so it's zero-risk on older servers.
1.3 Enhancements with API-surface impact
#
Change
PowerNetbox impact
#12024
VMs can attach to devices without a cluster
New-NBVirtualMachine -Cluster must become optional. Validate that eitherClusterorDevice is provided via [Parameter(ParameterSetName=...)]. Breaking if we enforce both.
#15513
Bulk creation for IP prefixes
New-NBIPAMPrefix already supports bulk pipelines via Send-NBBulkRequest. Verify the bulk body shape still matches 4.6's expectations — no code change expected, but add an integration test.
#17654
ASN role assignment
Add -Role param to New/Set/Get-NBIPAMASN. ~3 tests.
#19138
NAT addresses included in primary/OOB IP responses
Pure schema enrichment on GET. No code change — existing Get functions pass through unknown fields. Worth documenting as a new field users can access.
#20123
REST options to control adoption/replication of device components
New optional body params (likely adopt / replicate bools). Add to the relevant New-NBDCIM* component functions (Interface, Console/Power Ports, etc.).
#20152
disabled flag on module and device bays
New [switch] (or [bool]?) param on New/Set/Get-NBDCIMDeviceBay and New/Set/Get-NBDCIMModuleBay. Decision needed:[bool]$Disabled is consistent with the 90+ other boolean API params (see memory: `Mark_Utilized` lesson from v4.5.4.2). Use [bool], not [switch].
#20162
Background job option for bulk component adds
New -Background bool on bulk component creation. Medium complexity — response shape changes (returns a job URL instead of the created objects).
#20163
Changelog message for bulk device component creation
New optional -ChangelogMessage param (string). Pair with #21780 (same feature on IP addresses).
#20698
total_vlan_ids on VLAN group
Read-only field, no code change. Passthrough.
#21575
{vc_position} template variable
Templating-only, no REST impact.
#21662
rf_channel_frequency precision bumped to 3 decimals
PowerShell decimal handling should be unaffected (we pass through [object]). Add a test that preserves 3 decimal places round-trip.
#21702
Serialized HTTP request in webhooks
Webhook payloads only — not touched by PowerNetbox. No change.
#21770
Column control on embedded tables
UI-only. No change.
#21771
Partial tag assignment (add_tags / remove_tags) via REST
New opportunity: add Add-NBTag / Remove-NBTag convenience cmdlets. Today users must fetch the object, mutate the tag list, and PATCH the whole thing. This is a quality-of-life win worth shipping separately.
#21780
Changelog message for bulk IP address creation
Pair with #20163.
#21720
HTTP basic auth regex aligned with Django
May affect EnhancedURLValidator-fed custom fields. Test edge cases in SSLVerificationTests.
1.4 Deprecations (ship in 4.6, removed in 4.7)
username and request_id event fields (#21284) — PowerNetbox doesn't consume events directly, so no code impact. Document for users who parse webhook payloads.
housekeeping management command (#21304) — backend only, no impact.
Legacy querystring template tag (#21331) — template-only, no impact.
Serializer error formats. Our BuildDetailedErrorMessage pattern-matches on specific keys (`detail`, `__all__`, per-field arrays). Django 6 may reshape these.
DateTimeField timezone handling. Some endpoints may emit ISO-8601 with different fractional-seconds precision — affects Get-NBCoreObjectChangetime filter.
Auth backend signatures. Custom token authentication may surface different error classes.
HTTP method not allowed now typically returns 405 with a different body shape than Django 5.
URLValidator regex changes (related to #21720 above).
Mitigation: the only reliable check is to run the full integration matrix and observe what breaks. Unit tests mock at InvokeNetboxRequest level so they won't catch Django-layer shifts.
2. Test strategy — phased approach
Phase 0 — Build a 4.6-beta1 Docker image (blocker)
Since netbox-docker has no 4.6-ready image, we need a bespoke build. Two approaches:
Option A (recommended): extend the existing Dockerfile.branching pattern.
Create Dockerfile.46beta:
```dockerfile
Dockerfile.46beta — custom build for Netbox 4.6.0-beta1 compatibility testing
FROM netboxcommunity/netbox:v4.5.7-4.0.2 AS base
Pull 4.6.0-beta1 source over the top of an otherwise-working runtime
This is fragile (base image's Python/PostgreSQL versions may not match 4.6's requirements — specifically Django 6.0 may bump minimum Python), but it's the fastest path to a running instance.
Option B (cleaner but slower): fork netbox-docker at the develop branch and bump its VERSION file + Dockerfile ARGs to 4.6.0-beta1.
This mirrors what netbox-docker maintainers will eventually do. Run ./build.sh v4.6.0-beta1 from the fork and push the image to GHCR under ctrl-alt-automate/netbox-46beta.
Decision needed: start with A for signal, upgrade to B once we see it's viable.
Phase 1 — Smoke test (ValidateSet parity, cheap & fast)
Before any Docker work, run the parity script against the 4.6 source directly:
New interface types (watch for 800G variants — 4.5.6 added 1.6TB, 4.6 may push further)
New status values on VirtualMachine if VirtualMachineType introduces lifecycle states
New cable_type values if CableBundle brings its own
The script's exclusions file (scripts/validateset-parity-exclusions.txt) will need review — new legitimate PowerNetbox-internal values may surface as false positives.
Effort: ~10 minutes. This is the single highest-signal cheap check.
Phase 2 — Core smoke test on 4.6-beta1
Once the Docker image runs:
```bash
NETBOX_VERSION=v4.6.0-beta1-custom docker compose -f docker-compose.ci.yml up -d
Wait for migrations (Django 6.0 may slow first-boot substantially)
```
Run the existing compatibility.yml step inline: Tests 1-8 (Get-NBContentType, Core*, VPN, Wireless, DCIMSite, IPAMPrefix). Expected: all pass.
Then add 4.6-specific probes:
GET /api/virtualization/virtual-machine-types/ → 200
GET /api/dcim/cable-bundles/ → 200
GET /api/dcim/rack-groups/ → 200
GET /api/dcim/devices/1/ and verify response has an ETag header
GET /api/dcim/devices/?start=1&limit=5 → 200 with cursor results
This is where Django 6.0 fallout will surface. Expect 1-5 unexpected failures in areas we don't normally think about:
Error-body parsing in ErrorHandling.Tests.ps1
Date/time round-trips in Get-NBCoreObjectChange
Any test that relies on a specific error-response shape
Treat each failure as a triage item — do not paper over with try/catch at the function level (see CLAUDE.md: error handling is centralized by design).
Phase 4 — Targeted new-feature tests
Once the suite is green, add integration tests for the 3 new models and the 5 enhancement areas (VM without cluster, ASN role, disabled module/device bays, adopt/replicate flags, changelog messages).
Phase 5 — New helper-layer features
Implement in this order (each as a separate PR):
InvokeNetboxRequest ETag capture + -IfMatch passthrough + 412 error mapping → ~1 day, high test coverage on ErrorHandling.Tests.ps1.
Cursor pagination (-Start param + version-gated -All optimization) → ~1 day, focused on BuildURIComponents and the -All loop.
12 new functions for VirtualMachineType, CableBundle, RackGroup → ~3 days, template-driven.
When will netbox-docker publish a 4.6-compatible image? If it's before we ship our compatibility branch, we throw away the custom Dockerfile and use the official image. We should watch the netbox-docker repo's develop branch VERSION file and switch as soon as it bumps.
Does Django 6.0 require a Python version bump? If Netbox 4.6 raises Python minimum beyond what the existing base image ships, Option A Dockerfile fails and we must go straight to Option B.
Will Cluster on New-NBVirtualMachine become optional in a backward-compatible way? Users who rely on PowerShell's [Parameter(Mandatory)] prompt will see behavior change. We should deprecate the old behavior with a Write-Warning in v4.6.0.0 and remove the mandatory marker in v4.6.1.0.
ETag support surface area. Do we expose _etag on every returned object (adds a property everywhere) or only when the caller opts in via -IncludeMetadata? Decision deferred to the implementation PR.
Should 4.6 support land on dev, or on a new beta branch?CLAUDE.md already describes a beta branch reserved for pre-release testing. This is exactly what it was designed for. Proposal: cherry-pick the compatibility branch to beta, run the custom-image matrix there, and merge to dev only when 4.6.0 stable releases.
4. Action items (sub-issues to open after this one)
Phase 0a: Build `Dockerfile.46beta` and verify it boots (Option A)
Phase 0b: Fork netbox-docker and produce a proper build if Option A fails (Option B fallback)
Phase 1: Run Verify-ValidateSetParity.ps1 -NetboxVersion v4.6.0-beta1 and triage findings
Phase 2: Add a 4.6 row to `.github/workflows/compatibility.yml` (gated on the custom image)
Phase 3: Run full integration suite, file bugs for Django 6.0 fallout
Phase 5.6: Enhancement params batch (VM-without-cluster, ASN role, bay disabled, component adopt/replicate, changelog_message on bulk creates)
Phase 5.7 (optional):Add-NBTag / Remove-NBTag cmdlets for #21771
5. Recommendations (the advice part)
Don't rush to ship 4.6 support until the stable release. Beta1 is explicitly marked "no upgrade path to future releases" — building against beta1 means we may need to redo work if beta2/rc1 changes the schema. Use beta1 for discovery, not for delivery.
Run Phase 1 (parity script) this week. It's free signal. Even without a 4.6 Docker image we can validate ValidateSet decorators against the 4.6 choices.py source.
Reserve the beta branch for 4.6 work. CLAUDE.md already describes this pattern. Merge to dev only after 4.6.0 stable + all 94 integration tests green.
The helper-layer work (Phase 5.1 and 5.2) is independently valuable. ETag support and cursor pagination can land on devtoday against 4.5.7 — they're backward-compatible and version-gated. Treat them as standalone improvements rather than waiting for 4.6.
Plan for a 4.7 deprecation issue. When we open this issue, immediately open a companion tracking issue for 4.7 removals (event field username/request_id, housekeeping, legacy Sentry config, etc.). Future-you will thank present-you.
Analysis generated by Claude based on the v4.6.0-beta1 release notes, the current PowerNetbox 4.5.7 codebase, existing compatibility.yml workflow, and scripts/Verify-ValidateSetParity.ps1. Reviewed against netbox-docker's develop branch (VERSION=4.0.2 as of 2026-04-15).
Netbox 4.6.0-beta1 compatibility analysis
Release: v4.6.0-beta1 — published 2026-04-14
Target for stable ship: Netbox 4.6.0 final (ETA unknown, typically 4-6 weeks after beta1)
Current PowerNetbox target: 4.5.7 (via netbox-docker 4.0.2)
This issue documents a deep analysis of what needs to change in PowerNetbox to reach full 4.6 compatibility, and proposes a phased test strategy. It is intended as the parent tracking issue — follow-up implementation PRs will carve out the per-area work.
TL;DR
releaseanddevelopbranches still pin toVERSION=4.0.2(for Netbox 4.5.x). This is the hard blocker for adding a 4.6 row to.github/workflows/compatibility.yml. We will need to build a custom Dockerfile againstnetbox:v4.6.0-beta1ourselves — mirroring the pattern already used forDockerfile.branching.VirtualMachineType,CableBundle,RackGroup(reintroduced as a flat model separate from Location).InvokeNetboxRequestitself — the central helper used by all 522 functions:412 Precondition Failedstatus the error handler must understand.startparam, #21363) — performance-oriented alternative tooffset. Non-breaking, but worth plumbing through-Allso large list endpoints stay constant-time.InvokeNetboxRequestandBuildDetailedErrorMessageparse.#12024makesclusteroptional onVirtualMachine(VMs can now attach to a device without a cluster).New-NBVirtualMachine -Clustermust relax from[Parameter(Mandatory)]to optional.scripts/Verify-ValidateSetParity.ps1 -NetboxVersion v4.6.0-beta1early — it is the cheapest high-signal check we have.1. Impact assessment
1.1 New models → new PowerNetbox functions
VirtualMachineType(#5795)/api/virtualization/virtual-machine-types/Get/New/Set/Remove-NBVirtualMachineTypeDeviceTypefor physical hardware. Will likely be FK'd fromVirtualMachinevia a newtypefield.CableBundle(#20151)/api/dcim/cable-bundles/Get/New/Set/Remove-NBDCIMCableBundleRackGroup(#20961)/api/dcim/rack-groups/Get/New/Set/Remove-NBDCIMRackGroupLocationhierarchy;Rackgets a new optional FK;VLANGroupcan scope toRackGroup. Watch for the FK addition on existing endpoints.Effort estimate: 12 new functions × (implementation + ~6 unit tests each) ≈ 72 new tests. Follow the templates in
CLAUDE.md— each function is ~30 LOC of the standard New/Set/Get/Remove pattern.1.2 REST API structural changes (affect
InvokeNetboxRequest)ETag / If-Match (#21356) — HIGH impact on helper layer
Every GET on a single object now returns an
ETagheader derived fromlast_updated. Clients may opt in to optimistic locking by passingIf-Match: <etag>on subsequent PUT/PATCH — on mismatch the server returns HTTP 412 Precondition Failed.Required changes in
Functions/Helpers/InvokeNetboxRequest.ps1:ETagfrom the response headers and surface it on returned objects (either asPSObject.Properties.Add('_etag', ...)or via a parallel-OutVariablepattern).-IfMatchparameter that injects theIf-Matchheader.ErrorCategory(probablyWriteErrorwith aConcurrentUpdateDetectederror ID) in the central error handler so callers can catch it cleanly.-IfMatchpassthrough onSet-*functions that have high concurrent-edit risk (devices, interfaces, IP addresses) in a follow-up PR.Test coverage gap: we have zero tests for 412 responses today. Add one to
ErrorHandling.Tests.ps1.Cursor-based pagination (
startparam, #21363) — MEDIUM impactThe new
startparameter filters forpk >= startinstead of scanningoffsetrows, so large list endpoints become O(page_size) instead of O(offset + page_size). Existinglimit/offsetis unchanged.Options:
-Start <uint64>to all Get functions. Trivial — one line inBuildURIComponents. Exposes the param surface but most users won't notice.InvokeNetboxRequest -Allto preferstartoveroffsetwhen the connected Netbox is ≥4.6. Biggest win, small risk. This is where PowerNetbox actually differentiates:-Allon a device list of 50k rows goes from ~25 roundtrips of growing latency to 25 roundtrips of constant latency.Recommendation: do B + C. Gate the
InvokeNetboxRequestchange on\$script:NetboxConfig.ParsedVersion -ge [version]'4.6.0'so it's zero-risk on older servers.1.3 Enhancements with API-surface impact
New-NBVirtualMachine -Clustermust become optional. Validate that eitherClusterorDeviceis provided via[Parameter(ParameterSetName=...)]. Breaking if we enforce both.New-NBIPAMPrefixalready supports bulk pipelines viaSend-NBBulkRequest. Verify the bulk body shape still matches 4.6's expectations — no code change expected, but add an integration test.-Roleparam toNew/Set/Get-NBIPAMASN. ~3 tests.adopt/replicatebools). Add to the relevantNew-NBDCIM*component functions (Interface, Console/Power Ports, etc.).disabledflag on module and device bays[switch](or[bool]?) param onNew/Set/Get-NBDCIMDeviceBayandNew/Set/Get-NBDCIMModuleBay. Decision needed:[bool]$Disabledis consistent with the 90+ other boolean API params (see memory: `Mark_Utilized` lesson from v4.5.4.2). Use[bool], not[switch].-Backgroundbool on bulk component creation. Medium complexity — response shape changes (returns a job URL instead of the created objects).-ChangelogMessageparam (string). Pair with #21780 (same feature on IP addresses).total_vlan_idson VLAN group{vc_position}template variablerf_channel_frequencyprecision bumped to 3 decimals[object]). Add a test that preserves 3 decimal places round-trip.add_tags/remove_tags) via RESTAdd-NBTag/Remove-NBTagconvenience cmdlets. Today users must fetch the object, mutate the tag list, and PATCH the whole thing. This is a quality-of-life win worth shipping separately.EnhancedURLValidator-fed custom fields. Test edge cases inSSLVerificationTests.1.4 Deprecations (ship in 4.6, removed in 4.7)
usernameandrequest_idevent fields (#21284) — PowerNetbox doesn't consume events directly, so no code impact. Document for users who parse webhook payloads.housekeepingmanagement command (#21304) — backend only, no impact.querystringtemplate tag (#21331) — template-only, no impact.DEFAULT_ACTION_PERMISSIONS(#21884), legacy view actions (#21887),modelsregistry key (#21890) — all backend/plugin internals, no PowerNetbox impact.Action: no code change required for deprecations in 4.6. Create a follow-up tracking issue for 4.7 to revisit these when they hard-remove.
1.5 Django 6.0 upgrade (#20984) — highest risk, lowest visibility
Django majors historically change:
BuildDetailedErrorMessagepattern-matches on specific keys (`detail`, `__all__`, per-field arrays). Django 6 may reshape these.DateTimeFieldtimezone handling. Some endpoints may emit ISO-8601 with different fractional-seconds precision — affectsGet-NBCoreObjectChangetimefilter.URLValidatorregex changes (related to #21720 above).Mitigation: the only reliable check is to run the full integration matrix and observe what breaks. Unit tests mock at
InvokeNetboxRequestlevel so they won't catch Django-layer shifts.2. Test strategy — phased approach
Phase 0 — Build a 4.6-beta1 Docker image (blocker)
Since
netbox-dockerhas no 4.6-ready image, we need a bespoke build. Two approaches:Option A (recommended): extend the existing
Dockerfile.branchingpattern.Create
Dockerfile.46beta:```dockerfile
Dockerfile.46beta — custom build for Netbox 4.6.0-beta1 compatibility testing
FROM netboxcommunity/netbox:v4.5.7-4.0.2 AS base
Pull 4.6.0-beta1 source over the top of an otherwise-working runtime
RUN cd /opt/netbox &&
git fetch --tags https://github.com/netbox-community/netbox.git v4.6.0-beta1 &&
git checkout v4.6.0-beta1 &&
/opt/netbox/venv/bin/pip install -r requirements.txt &&
/opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py migrate
```
This is fragile (base image's Python/PostgreSQL versions may not match 4.6's requirements — specifically Django 6.0 may bump minimum Python), but it's the fastest path to a running instance.
Option B (cleaner but slower): fork netbox-docker at the develop branch and bump its VERSION file + Dockerfile ARGs to 4.6.0-beta1.
This mirrors what netbox-docker maintainers will eventually do. Run
./build.sh v4.6.0-beta1from the fork and push the image to GHCR underctrl-alt-automate/netbox-46beta.Decision needed: start with A for signal, upgrade to B once we see it's viable.
Phase 1 — Smoke test (ValidateSet parity, cheap & fast)
Before any Docker work, run the parity script against the 4.6 source directly:
```powershell
cd PowerNetbox
./scripts/Verify-ValidateSetParity.ps1 -NetboxVersion v4.6.0-beta1 -FailOnMismatch -OutputFormat Json | Out-File temp/parity-46.json
```
Expected findings:
statusvalues onVirtualMachineifVirtualMachineTypeintroduces lifecycle statescable_typevalues ifCableBundlebrings its ownscripts/validateset-parity-exclusions.txt) will need review — new legitimate PowerNetbox-internal values may surface as false positives.Effort: ~10 minutes. This is the single highest-signal cheap check.
Phase 2 — Core smoke test on 4.6-beta1
Once the Docker image runs:
```bash
NETBOX_VERSION=v4.6.0-beta1-custom docker compose -f docker-compose.ci.yml up -d
Wait for migrations (Django 6.0 may slow first-boot substantially)
```
Run the existing compatibility.yml step inline: Tests 1-8 (Get-NBContentType, Core*, VPN, Wireless, DCIMSite, IPAMPrefix). Expected: all pass.
Then add 4.6-specific probes:
GET /api/virtualization/virtual-machine-types/→ 200GET /api/dcim/cable-bundles/→ 200GET /api/dcim/rack-groups/→ 200GET /api/dcim/devices/1/and verify response has anETagheaderGET /api/dcim/devices/?start=1&limit=5→ 200 with cursor resultsPhase 3 — Full integration suite
Run the existing 94-test integration suite:
```powershell
$env:NETBOX_HOST = 'localhost:8000'
$env:NETBOX_TOKEN = ''
Invoke-Pester ./Tests/Integration.Tests.ps1 -Tag 'Integration'
```
This is where Django 6.0 fallout will surface. Expect 1-5 unexpected failures in areas we don't normally think about:
ErrorHandling.Tests.ps1Get-NBCoreObjectChangeTreat each failure as a triage item — do not paper over with
try/catchat the function level (see CLAUDE.md: error handling is centralized by design).Phase 4 — Targeted new-feature tests
Once the suite is green, add integration tests for the 3 new models and the 5 enhancement areas (VM without cluster, ASN role, disabled module/device bays, adopt/replicate flags, changelog messages).
Phase 5 — New helper-layer features
Implement in this order (each as a separate PR):
InvokeNetboxRequestETag capture +-IfMatchpassthrough + 412 error mapping → ~1 day, high test coverage onErrorHandling.Tests.ps1.-Startparam + version-gated-Alloptimization) → ~1 day, focused onBuildURIComponentsand the-Allloop.VirtualMachineType,CableBundle,RackGroup→ ~3 days, template-driven.Add-NBTag/Remove-NBTagconvenience cmdlets (#21771) → ~0.5 day, opportunistic quality-of-life improvement.3. Risks & open questions
developbranch VERSION file and switch as soon as it bumps.ClusteronNew-NBVirtualMachinebecome optional in a backward-compatible way? Users who rely on PowerShell's[Parameter(Mandatory)]prompt will see behavior change. We should deprecate the old behavior with aWrite-Warningin v4.6.0.0 and remove the mandatory marker in v4.6.1.0._etagon every returned object (adds a property everywhere) or only when the caller opts in via-IncludeMetadata? Decision deferred to the implementation PR.dev, or on a newbetabranch?CLAUDE.mdalready describes abetabranch reserved for pre-release testing. This is exactly what it was designed for. Proposal: cherry-pick the compatibility branch tobeta, run the custom-image matrix there, and merge todevonly when 4.6.0 stable releases.4. Action items (sub-issues to open after this one)
Verify-ValidateSetParity.ps1 -NetboxVersion v4.6.0-beta1and triage findingsInvokeNetboxRequestETag +-IfMatch+ 412 error mapping-Start+ version-gated-All)VirtualMachineTypeendpoint (4 functions)CableBundleendpoint (4 functions)RackGroupendpoint (4 functions + verifyRack.rack_groupFK +VLANGroup.scopebump)disabled, componentadopt/replicate,changelog_messageon bulk creates)Add-NBTag/Remove-NBTagcmdlets for #217715. Recommendations (the advice part)
betabranch for 4.6 work. CLAUDE.md already describes this pattern. Merge todevonly after 4.6.0 stable + all 94 integration tests green.devtoday against 4.5.7 — they're backward-compatible and version-gated. Treat them as standalone improvements rather than waiting for 4.6.username/request_id,housekeeping, legacy Sentry config, etc.). Future-you will thank present-you.Analysis generated by Claude based on the v4.6.0-beta1 release notes, the current PowerNetbox 4.5.7 codebase, existing compatibility.yml workflow, and
scripts/Verify-ValidateSetParity.ps1. Reviewed against netbox-docker's develop branch (VERSION=4.0.2 as of 2026-04-15).