Jeremy Stretch 1 неделя назад
Родитель
Сommit
9abbebe392

+ 0 - 2
docs/administration/management-commands.md

@@ -28,8 +28,6 @@ python3 netbox/manage.py nbshell
 
 ## populate_image_sizes
 
-!!! info "This command was introduced in NetBox v4.6.4."
-
 Populate the cached file size for image attachments that predate the `image_size` field. Running this once after upgrading is recommended for deployments with many existing attachments on a remote storage backend (such as S3). It is safe to run on a live system and may be re-run; any file that cannot be read is skipped and retried on the next run.
 
 ```

+ 0 - 4
docs/configuration/graphql-api.md

@@ -2,8 +2,6 @@
 
 ## GRAPHQL_DEFAULT_VERSION
 
-!!! note "This parameter was introduced in NetBox v4.5."
-
 Default: `1`
 
 Designates the default version of the GraphQL API served by `/graphql/`. To access a specific version, append the version number to the URL, e.g. `/graphql/v2/`.
@@ -30,8 +28,6 @@ The maximum number of queries that a GraphQL API request may contain.
 
 ## GRAPHQL_MAX_QUERY_DEPTH
 
-!!! note "This parameter was introduced in NetBox v4.6.1."
-
 Default: `None` (no limit)
 
 The maximum allowed depth of any GraphQL query. When set to a positive integer, requests containing queries that exceed this depth will be rejected. Leaving this parameter unset (or setting it to `None` or `0`) disables query depth enforcement.

+ 0 - 2
docs/configuration/miscellaneous.md

@@ -125,8 +125,6 @@ The maximum size (in bytes) of an incoming HTTP request (i.e. `GET` or `POST` da
 
 ## STREAMING_EXPORTS
 
-!!! note "This parameter was introduced in NetBox v4.6."
-
 Default: `False`
 
 When set to `True`, CSV bulk exports are returned as a streaming HTTP response, emitting rows to the client as they are rendered rather than buffering the entire dataset in memory first. This can significantly reduce memory usage and time-to-first-byte for very large exports.

+ 0 - 2
docs/configuration/required-parameters.md

@@ -25,8 +25,6 @@ ALLOWED_HOSTS = ['*']
 
 ## API_TOKEN_PEPPERS
 
-!!! info "This parameter was introduced in NetBox v4.5."
-
 [Cryptographic peppers](https://en.wikipedia.org/wiki/Pepper_(cryptography)) are employed to generate hashes of sensitive values on the server. This parameter defines the peppers used to hash v2 API tokens in NetBox. You must define at least one pepper before creating a v2 API token. See the [API documentation](../integrations/rest-api.md#authentication) for further information about how peppers are used.
 
 ```python

+ 0 - 3
docs/configuration/security.md

@@ -168,9 +168,6 @@ Default: `True`
 
 When enabled, only authenticated users are permitted to access any part of NetBox. Disabling this will allow unauthenticated users to access most areas of NetBox (but not make any changes).
 
-!!! info "Changed in NetBox v4.0.2"
-    Prior to NetBox v4.0.2, this setting was disabled by default.
-
 ---
 
 ## LOGIN_TIMEOUT

+ 1 - 5
docs/configuration/system.md

@@ -86,8 +86,6 @@ Email is sent from NetBox only for critical events or if configured for [logging
 
 ## HOSTNAME
 
-!!! info "This parameter was introduced in NetBox v4.4."
-
 Default: System hostname
 
 The hostname displayed in the user interface identifying the system on which NetBox is running. If not defined, this defaults to the system hostname as reported by Python's `platform.node()`.
@@ -96,8 +94,6 @@ The hostname displayed in the user interface identifying the system on which Net
 
 ## HTTP_CLIENT_IP_HEADERS
 
-!!! info "This parameter was introduced in NetBox v4.6.1."
-
 Default:
 
 ```python
@@ -142,7 +138,7 @@ A list of IP addresses recognized as internal to the system, used to control the
 example, the debugging toolbar will be viewable only when a client is accessing NetBox from one of the listed IP
 addresses (and [`DEBUG`](./development.md#debug) is `True`).
 
-!!! info "New in NetBox v4.6"
+!!! info "Enabling the toolbar for all clients"
     Setting this parameter to an empty list will enable the toolbar for all requests provided debugging is enabled:
 
     ```python

+ 1 - 1
docs/features/context-data.md

@@ -93,7 +93,7 @@ A profile's schema may be authored directly in NetBox or populated from an exter
 
 ## Pre-rendered Caching
 
-!!! info "New in NetBox v4.7"
+!!! info "This feature was introduced in NetBox v4.7."
 
 NetBox pre-renders each device's and virtual machine's merged context data and stores it on the object itself, so most reads can return the result without recomputing the full set of applicable contexts. The cache is initially populated during upgrade (the upgrade script runs the `rebuild_config_context_cache` management command) and is thereafter kept current automatically: whenever an upstream change is detected — a config context being created, modified, or deleted; a device/VM's scope-relevant attribute changing (site, role, tenant, tags, cluster, etc.); or a related object being re-routed in a way that changes which contexts apply — NetBox marks the affected caches invalid and enqueues a non-blocking [background job](./background-jobs.md) to repopulate them.
 

+ 2 - 0
docs/features/cooling.md

@@ -1,5 +1,7 @@
 # Cooling
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 As part of its DCIM feature set, NetBox supports modeling data center cooling infrastructure, from facility plant down to the coolant connections on individual devices. This is used to document liquid- and hybrid-cooled environments (chillers, cooling distribution units, manifolds, rear-door heat exchangers, and cold-plate servers) as a source of truth.
 
 ## Model Overview

+ 0 - 2
docs/features/resource-ownership.md

@@ -1,7 +1,5 @@
 # Resource Ownership
 
-!!! info "This feature was introduced in NetBox v4.5."
-
 Most objects in NetBox can be assigned an owner. An owner is a set of users and/or groups who are responsible for the administration of associated objects. For example, you might designate the operations team at a site as the owner for all prefixes and VLANs deployed at that site. The users and groups assigned to an owner are referred to as its members.
 
 !!! note

+ 0 - 5
docs/integrations/graphql-api.md

@@ -51,9 +51,6 @@ For more detail on constructing GraphQL queries, see the [GraphQL queries docume
 
 ## Filtering
 
-!!! note "Changed in NetBox v4.3"
-    The filtering syntax fo the GraphQL API has changed substantially in NetBox v4.3.
-
 Filters can be specified as key-value pairs within parentheses immediately following the query name. For example, the following will return only active sites:
 
 ```
@@ -139,8 +136,6 @@ The alternative approach is cursor-based pagination, which operates using absolu
 
 To ensure consistent ordering, objects will always be ordered by their primary keys when cursor-based pagination is used.
 
-!!! note "Cursor-based pagination was introduced in NetBox v4.5.2."
-
 Both pagination strategies support an optional `limit` parameter specifying the maximum number of objects to include in the response. The [`MAX_PAGE_SIZE`](../configuration/miscellaneous.md#max_page_size) configuration parameter (default `1000`) sets a hard ceiling on this value; if no limit is specified, up to `MAX_PAGE_SIZE` records are returned.
 
 When `MAX_PAGE_SIZE` is set to `0` or `None`:

+ 20 - 6
docs/integrations/rest-api.md

@@ -253,8 +253,6 @@ Similarly, you can opt to omit only specific fields by passing the `omit` parame
 GET /api/dcim/sites/?omit=circuit_count,device_count,virtualmachine_count
 ```
 
-!!! note "The `omit` parameter was introduced in NetBox v4.5.2."
-
 Strategic use of the `fields` and `omit` parameters can drastically improve REST API performance, as the exclusion of fields which reference related objects reduces the number and complexity of underlying database queries needed to generate the response.
 
 !!! note
@@ -669,9 +667,27 @@ Note that there is no requirement for the attributes to be identical among objec
 !!! note
     The bulk update of objects is an all-or-none operation, meaning that if NetBox fails to successfully update any of the specified objects (e.g. due a validation error), the entire operation will be aborted and none of the objects will be updated.
 
-### Concurrent Update Protection
+### Errors in Bulk Operations
+
+!!! info "This feature was introduced in NetBox v4.7."
 
-!!! info "This feature was introduced in NetBox v4.6."
+When a bulk creation or update fails validation, the response identifies each offending object by its index within the submitted list, so that a client can correct and resubmit only the objects which actually failed. (The operation itself remains all-or-none: No objects are written unless every object validates.)
+
+```json
+{
+    "detail": "1 of 3 objects failed validation.",
+    "errors": [
+        {
+            "index": 1,
+            "errors": {
+                "slug": ["This field may not be blank."]
+            }
+        }
+    ]
+}
+```
+
+### Concurrent Update Protection
 
 To guard against the lost-update problem when multiple clients modify the same object, NetBox returns a weak `ETag` response header on detail-view responses (`GET`, `POST`, `PATCH`, `PUT`) for individual objects. Clients may supply this value back on a subsequent `PATCH` or `PUT` request via the `If-Match` request header. If the object's current ETag does not match any of the values supplied, the server rejects the request with a `412 Precondition Failed` response and includes the current ETag in the response so the client can retry.
 
@@ -693,8 +709,6 @@ A literal `If-Match: *` value matches any current ETag and may be used to assert
 
 ### Adding and Removing Tags
 
-!!! info "This feature was introduced in NetBox v4.6."
-
 In addition to replacing an object's tag set wholesale via the `tags` field, taggable models accept two write-only fields, `add_tags` and `remove_tags`, which apply only the specified additions or removals without disturbing existing tags. This is convenient when concurrent clients each manage a distinct subset of an object's tags.
 
 ```no-highlight

+ 0 - 2
docs/models/dcim/cable.md

@@ -23,8 +23,6 @@ The cable's operational status. Choices include:
 
 ### Profile
 
-!!! note "This field was introduced in NetBox v4.5."
-
 The profile to which the cable conforms. The profile determines the mapping of termination between the two ends and enables logical tracing across complex connections, such as breakout cables. Supported profiles are listed below.
 
 * Straight (single position)

+ 3 - 1
docs/models/dcim/interface.md

@@ -35,6 +35,8 @@ The type of interface. Interfaces may be physical or virtual in nature, but only
 
 ### Channels
 
+!!! info "This field was added in NetBox v4.7."
+
 For a channelized (breakout) interface, the number of physical channels into which the interface is divided. For example, a 40GE interface broken out into four 10GE channels would have `channels` set to four. Each channel is modeled as a channel subinterface bound to this interface via its [channel ID](#channel-id).
 
 A single physical cable terminates to the channelized (parent) interface, occupying one connector shared by all of its channels; NetBox traces a distinct cable path for each channel subinterface. Only one layer of channelization is supported: an interface cannot be both channelized and itself bound to a channel.
@@ -55,7 +57,7 @@ The [virtual routing and forwarding](../ipam/vrf.md) instance to which this inte
 
 The [MAC address](./macaddress.md) assigned to this interface which is designated as its primary.
 
-!!! note "Changed in NetBox v4.2"
+!!! note "MAC address is a property"
     The MAC address of an interface (formerly a concrete database field) is available as a property, `mac_address`, which reflects the value of the primary linked [MAC address](./macaddress.md) object.
 
 ### WWN

+ 2 - 0
docs/models/dcim/module.md

@@ -6,6 +6,8 @@ Similar to devices, modules are instantiated from [module types](./moduletype.md
 
 ## Moving Modules
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 An installed module can be moved to a different module bay after creation. The destination bay must be enabled and unoccupied. Moving a module relocates its entire subtree: the components installed by the module, the module bays belonging to it, and any child modules installed within those bays.
 
 Component names, labels, and module bay positions derived from the module type's templates (for example, names containing `{module}`) are re-resolved for the destination bay. A component is renamed only when its current name matches exactly one of the module type's templates as resolved for the source bay; components whose names do not match any template resolution (including manually renamed components) are preserved as-is. All resulting names are validated against the destination device before the move is applied. A move is rejected when a template-derived name, label, or position would exceed the destination field's maximum length. A move is also rejected when a component's current value matched a template for the source bay but that template cannot be resolved for the destination bay's nesting depth.

+ 2 - 0
docs/models/dcim/modulebaytype.md

@@ -1,5 +1,7 @@
 # Module Bay Types
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 Module bay types are user-defined labels that can be assigned to [module bays](./modulebay.md) and [module types](./moduletype.md) to restrict which modules may be installed into which bays. This is useful for modeling chassis hardware where not every bay accepts every type of line card.
 
 When **both** a module bay and the module type being installed have at least one bay type assigned, NetBox will check for a non-empty intersection. If the two sets share no bay types in common, the installation will be rejected as incompatible.

+ 0 - 2
docs/models/dcim/platform.md

@@ -12,8 +12,6 @@ The assignment of platforms to devices and virtual machines is optional.
 
 ## Parent
 
-!!! "This field was introduced in NetBox v4.4."
-
 The parent platform class to which this platform belongs (optional).
 
 ### Name

+ 0 - 2
docs/models/ipam/iprange.md

@@ -44,8 +44,6 @@ The IP range's operational status. Note that the status of a range does _not_ ha
 
 ### Mark Populated
 
-!!! note "This field was added in NetBox v4.3."
-
 If enabled, NetBox will treat this IP range as being fully populated when calculating available IP space. It will also prevent the creation of IP addresses which fall within the declared range (and assigned VRF, if any).
 
 ### Mark Utilized

+ 2 - 7
docs/models/ipam/service.md

@@ -4,9 +4,8 @@ An application service represents a layer seven application available on a devic
 
 To aid in the efficient creation of application services, users may opt to first create an [application service template](./servicetemplate.md) from which service definitions can be quickly replicated.
 
-!!! note "Changed in NetBox v4.4"
-
-    Previously, application services were referred to simply as "services". The name has been changed in the UI to better reflect their intended use. There is no change to the name of the model or in any programmatic NetBox APIs.
+!!! note "Naming"
+    Application services are referred to simply as "services" in the name of the model and throughout NetBox's programmatic APIs. Only the UI uses the longer name, which better reflects their intended use.
 
 ## Fields
 
@@ -15,10 +14,6 @@ To aid in the efficient creation of application services, users may opt to first
 The parent object to which the application service is assigned. This must be one of [Device](../dcim/device.md),
 [VirtualMachine](../virtualization/virtualmachine.md), or [FHRP Group](./fhrpgroup.md).
 
-!!! note "Changed in NetBox v4.3"
-
-    Previously, `parent` was a property that pointed to either a Device or Virtual Machine. With the capability to assign services to FHRP groups, this is a unified in a concrete field.
-
 ### Name
 
 A service or protocol name.

+ 2 - 2
docs/models/ipam/servicetemplate.md

@@ -2,9 +2,9 @@
 
 Application service templates can be used to instantiate [application services](./service.md) on [devices](../dcim/device.md) and [virtual machines](../virtualization/virtualmachine.md).
 
-!!! note "Changed in NetBox v4.4"
+!!! note "Naming"
 
-    Previously, application service templates were referred to simply as "service templates". The name has been changed in the UI to better reflect their intended use. There is no change to the name of the model or in any programmatic NetBox APIs.
+    Application service templates are referred to simply as "service templates" in the name of the model and throughout NetBox's programmatic APIs. Only the UI uses the longer name, which better reflects their intended use.
 
 ## Fields
 

+ 0 - 3
docs/models/virtualization/virtualmachine.md

@@ -46,9 +46,6 @@ The location or host for this VM. At least one must be specified:
 - **Device only**: The VM runs directly on a physical host device without a cluster (e.g. containers). The site is automatically inferred from the device's site.
 - **Cluster + Device**: The VM belongs to a cluster and is pinned to a specific host device within that cluster. The device must be a registered host of the assigned cluster.
 
-!!! info "New in NetBox v4.6"
-    Virtual machines can now be assigned directly to a device without requiring a cluster. This is particularly useful for modeling VMs running on standalone hosts outside of a cluster.
-
 ### Platform
 
 A VM may be associated with a particular [platform](../dcim/platform.md) to indicate its operating system. If a virtual machine type defines a default platform, it will be applied when the VM is created unless an explicit platform is specified.

+ 1 - 1
docs/models/virtualization/vminterface.md

@@ -31,7 +31,7 @@ If not selected, this interface will be treated as disabled/inoperative.
 
 The [MAC address](../dcim/macaddress.md) assigned to this interface which is designated as its primary.
 
-!!! note "Changed in NetBox v4.2"
+!!! note "MAC address is a property"
     The MAC address of an interface (formerly a concrete database field) is available as a property, `mac_address`, which reflects the value of the primary linked [MAC address](../dcim/macaddress.md) object.
 
 ### MTU

+ 0 - 2
docs/plugins/development/background-jobs.md

@@ -41,8 +41,6 @@ This is the human-friendly names of your background job. If omitted, the class n
 
 ### Logging
 
-!!! info "This feature was introduced in NetBox v4.4."
-
 A Python logger is instantiated by the runner for each job. It can be utilized within a job's `run()` method as needed:
 
 ```python

+ 2 - 0
docs/plugins/development/config-templates.md

@@ -1,5 +1,7 @@
 # Jinja Config Templates
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 NetBox uses [Jinja](https://jinja.palletsprojects.com/) to render [configuration templates](../../features/configuration-rendering.md). Plugins can extend this rendering pipeline in two complementary ways:
 
 1. **Register custom filters** — make new template filters available by name in every config template.

+ 2 - 0
docs/plugins/development/event-rule-actions.md

@@ -1,5 +1,7 @@
 # Event Rule Actions
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 [Event rules](../../models/extras/eventrule.md) dispatch to an *action* when a matching event occurs, such as sending a webhook request or running a script. Plugins can register their own action types to extend the list of actions an event rule can perform, by subclassing NetBox's `EventRuleAction` class.
 
 ```python title="event_rules.py"

+ 1 - 2
docs/plugins/development/filtersets.md

@@ -6,8 +6,7 @@ Filter sets define the mechanisms available for filtering or searching through a
 
 To support additional functionality standard to NetBox models, such as tag assignment and custom field support, the `NetBoxModelFilterSet` class is available for use by plugins. This should be used as the base filter set class for plugin models which inherit from `NetBoxModel`. Within this class, individual filters can be declared as directed by the `django-filters` documentation. An example is provided below.
 
-!!! info "New in NetBox v4.5: FilterSet Registration"
-    NetBox v4.5 introduced the `register_filterset()` utility function. This enables plugins to register their filtersets to receive advanced functionality, such as the automatic attachment of field-specific lookup modifiers on the filter form. Registration is optional: Unregistered filtersets will continue to work as before, but will not receive the enhanced functionality.
+The `register_filterset()` utility function enables plugins to register their filtersets to receive advanced functionality, such as the automatic attachment of field-specific lookup modifiers on the filter form. Registration is optional: Unregistered filtersets will continue to work as before, but will not receive the enhanced functionality.
 
 ```python
 # filtersets.py

+ 4 - 0
docs/plugins/development/forms.md

@@ -212,6 +212,8 @@ In addition to the [form fields provided by Django](https://docs.djangoproject.c
 
 ## Static Choice Fields
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 These fields render a standard HTML `<select>` element (as opposed to the API-backed widgets used by the dynamic object fields below). They extend Django's built-in choice fields to optionally display a short **description** beneath each option's label.
 
 For choice set-backed fields, descriptions are defined per choice using a `Choice` object in the `ChoiceSet` and are rendered automatically. Pass `show_descriptions=False` to suppress them for a particular field.
@@ -261,6 +263,8 @@ status = ChoiceField(choices=StatusChoices)
 
 ## Generic Object Fields
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 `GenericObjectChoiceField` represents a generic foreign key (a `content_type` plus `object_id` pair) as a single, REST API-backed form field. Pair it with `GenericObjectFormMixin` on the form to seed the field's initial value from the model's GFK descriptor and assign the selected object back to it automatically.
 
 ::: utilities.forms.fields.GenericObjectChoiceField

+ 0 - 3
docs/plugins/development/navigation.md

@@ -73,9 +73,6 @@ A `PluginMenuItem` has the following attributes:
 | `staff_only`    | -        | Display only for superusers                          |
 | `buttons`       | -        | An iterable of PluginMenuButton instances to include |
 
-!!! note "Changed in NetBox v4.5"
-    In releases prior to NetBox v4.5, `staff_only` restricted display of a menu item to only users with `is_staff` set to True. In NetBox v4.5, the `is_staff` flag was removed from the user model. Menu items with `staff_only` set to True are now displayed only for superusers.
-
 ## Menu Buttons
 
 Each menu item can include a set of buttons. These can be handy for providing shortcuts related to the menu item. For instance, most items in NetBox's navigation menu include buttons to create and import new objects.

+ 2 - 3
docs/plugins/development/ui-components.md

@@ -1,8 +1,5 @@
 # UI Components
 
-!!! note "New in NetBox v4.6"
-    All UI components described here were introduced in NetBox v4.6. Be sure to set the minimum NetBox version to 4.6.0 for your plugin before incorporating any of these resources.
-
 To simplify the process of designing your plugin's user interface, and to encourage a consistent look and feel throughout the entire application, NetBox provides a set of components that enable programmatic UI design. These make it possible to declare complex page layouts with little or no custom HTML.
 
 ## Page Layout
@@ -55,6 +52,8 @@ class MyView(generic.ObjectView):
 
 ## Breadcrumbs
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 Breadcrumbs are rendered at the top of an object's page to convey its position within a hierarchy and to provide quick navigation to related objects. By default, a single breadcrumb linking to the object's list view is shown. To add object-specific breadcrumbs, pass a list of `Breadcrumb` instances to your layout, just as you would its panels.
 
 A `Breadcrumb` typically references an _accessor_ (rather than a static value), which is resolved against the object being viewed when the page is rendered. The accessor may be a dotted attribute path or a callable. (A breadcrumb may instead define a static `label`; see below.)

+ 0 - 6
docs/plugins/development/views.md

@@ -79,14 +79,8 @@ The NetBox URL registration process has two parts:
 
 ::: utilities.views.register_model_view
 
-!!! note "Changed in NetBox v4.2"
-    In NetBox v4.2, the `register_model_view()` function was extended to support the registration of list views by passing `detail=False`.
-
 ::: utilities.urls.get_model_urls
 
-!!! note "Changed in NetBox v4.2"
-    In NetBox v4.2, the `get_model_urls()` function was extended to support retrieving registered general model views (e.g. for listing objects) by passing `detail=False`.
-
 ### Example Usage
 
 ```python

+ 2 - 0
docs/reference/conditions.md

@@ -103,6 +103,8 @@ The following condition will evaluate as true:
 
 ## Snapshot Conditions (Event Rules)
 
+!!! info "This feature was introduced in NetBox v4.7."
+
 When used in an [event rule](../features/event-rules.md), conditions can also inspect the **pre-change and post-change snapshots** captured at the time of the event. This allows rules to fire only when a specific field actually changes value, rather than whenever it has a particular value.
 
 ### Snapshot Operators

+ 239 - 0
docs/release-notes/version-4.7.md

@@ -0,0 +1,239 @@
+# NetBox v4.7
+
+## v4.7.0-beta1 (2026-08-17)
+
+### Breaking Changes
+
+* PostgreSQL 14 is no longer supported. NetBox now requires PostgreSQL 15 or later.
+* Redis 5.x is no longer supported. NetBox now requires Redis 6.0 or later.
+* Selection and multiple selection custom field values are now returned as objects specifying both the raw value and its human-friendly label (e.g. `{"value": "datacenter", "label": "Data Center"}`) in both the REST and GraphQL APIs. These fields continue to accept the raw value on write.
+* The `protocol` and `ports` fields on the ApplicationService and ApplicationServiceTemplate models have been replaced by a unified `port_mappings` field, which supports multiple protocols per service. The legacy fields are retained (as deprecated) in the REST and GraphQL APIs, but at the ORM level they are now read-only properties derived from `port_mappings`: Passing `protocol` or `ports` to the model raises a `TypeError`, and assigning to `service.ports` raises an `AttributeError`.
+* Because `protocol` is now filtered against the `port_mappings` array rather than a dedicated model field, the character-based REST filter lookups previously generated for it (`protocol__ic`, `protocol__isw`, `protocol__empty`, etc.) are no longer available. The `port__empty` lookup has been removed as well.
+* The GraphQL filters for ApplicationService and ApplicationServiceTemplate have changed shape: The nested `ports` integer lookup has been replaced by the flat `port`, `port__gt`, `port__gte`, `port__lt`, and `port__lte` parameters (each accepting a list of values), alongside the new `port_mappings` parameter. Additionally, the members of `ServiceProtocolEnum` have been renamed to drop a spurious `ROLE_` prefix (e.g. `ROLE_TCP` is now `TCP`).
+* Config context data is now pre-rendered and cached for each device and virtual machine, and is always included in their REST API representations. The `DeviceWithConfigContextSerializer` and `VirtualMachineWithConfigContextSerializer` classes have been removed (merged into the base serializers), and the `?exclude=config_context` query parameter is now silently ignored.
+* Failed bulk create and update operations via the REST API now return a structured response of the form `{"detail": ..., "errors": [{"index": N, "errors": {...}}]}`, correlating each error with the index of the offending object in the submitted list. (Bulk operations remain all-or-none.)
+* API token plaintexts can no longer be specified by the client when creating a token via the REST API. The `token` field is now read-only, and any value supplied is ignored. (This restriction was already in effect in the web UI.)
+* Executing a custom script via the REST API now requires that the calling token have its write ability enabled.
+* Updates to the global search cache are now deferred to a background task. As a result, a newly created or modified object may not appear in search results for a brief period. (When no background worker is running, the index is updated synchronously as before.)
+* Nested group models (Region, SiteGroup, Location, TenantGroup, ContactGroup, WirelessLANGroup, etc.) are now backed by a PostgreSQL `ltree` column rather than django-mptt. The MPTT-backed `NestedGroupModel` base class is retained for backward compatibility with plugins, but is deprecated: New code should use `NestedLtreeGroupModel` instead.
+* django-tables2 has been upgraded to v3.0, which renames its `querystring` template tag to `querystring_replace` and removes the `RelatedLinkColumn` class.
+* The `request` object passed to custom link templates is now a sanitized subset of the current request. Only the `id`, `path`, `path_info`, `method`, `GET`, and `user` attributes are available; cookies, headers, and session state are no longer accessible.
+* URL custom field values are now validated against the [`ALLOWED_URL_SCHEMES`](../configuration/security.md#allowed_url_schemes) configuration parameter. A value entered without a scheme is assumed to use `https` and stored as an absolute URL.
+* Webhooks now support a configurable timeout. If you have lowered `RQ_DEFAULT_TIMEOUT` to 60 seconds or less, you must also set [`WEBHOOK_DEFAULT_TIMEOUT`](../configuration/miscellaneous.md#webhook_default_timeout) to a lower value; NetBox will refuse to start otherwise.
+* The upgrade script now runs the `rebuild_config_context_cache` management command to populate the new config context cache. This may extend the duration of the upgrade for deployments with a large number of devices and virtual machines.
+* Removal of deprecated behavior
+    * The `housekeeping` management command has been removed. (Its constituent tasks are performed by the individual management commands introduced in NetBox v4.6.)
+    * NetBox's custom `querystring` template tag has been removed in favor of Django's built-in tag of the same name.
+    * The legacy Sentry configuration parameters `SENTRY_DSN`, `SENTRY_SAMPLE_RATE`, `SENTRY_SEND_DEFAULT_PII`, and `SENTRY_TRACES_SAMPLE_RATE` have been removed. Use `SENTRY_CONFIG` instead.
+    * The obsolete `DEFAULT_ACTION_PERMISSIONS` constant has been removed.
+    * Support for legacy view action mappings has been dropped, and the `LEGACY_ACTIONS` constant has been removed.
+    * Registered models are no longer populated under `registry['models']`. (Use `ObjectType.objects.public()` instead.) The `registry['denormalized_fields']` store has been removed as well.
+    * The backward compatibility shims for `OptionalLimitOffsetPagination` (now `NetBoxPagination`), `ExpandableIPAddressField` (now `ExpandableIPNetworkField`), and `expand_ipaddress_pattern()` (now `expand_ipnetwork_pattern()`) have been removed.
+    * The `request_id` and `username` keys have been removed from the context available to outgoing webhooks. Use `request.id` and `request.user` instead.
+    * The automatic reverse relationship created by `OwnerMixin` (e.g. `site_set`) has been removed.
+
+### New Features
+
+#### Cooling Infrastructure Modeling ([#22447](https://github.com/netbox-community/netbox/issues/22447))
+
+NetBox has long modeled power distribution end to end, but had no equivalent for cooling. This release introduces a cooling data model which deliberately mirrors the power model, so that the concepts and workflows feel familiar.
+
+Two new top-level models parallel PowerPanel and PowerFeed: **CoolingSource** represents facility-level cooling plant (a chiller, cooling tower, dry cooler, or facility water system) scoped to a site or location, and **CoolingFeed** represents a coolant loop delivered from a source to a rack. Two new device components parallel PowerPort and PowerOutlet: **CoolingIntake** represents a coolant intake on a device (e.g. a server cold-plate connection or a CDU's facility water inlet), and **CoolingOutflow** represents a coolant outlet on a CDU or manifold which supplies downstream equipment. Each intake may reference the upstream outflow which serves it, and both components have corresponding device type templates. CDUs and manifolds are modeled as ordinary devices carrying these components.
+
+Lightweight descriptive attributes have also been added for users who want to record cooling characteristics without modeling the full plumbing: a `cooling_method` field (air, liquid, hybrid, or immersion) on the Device, DeviceType, and ModuleType models, and `cooling_capability` (air-only, hybrid, or liquid-only) and `cooling_capacity` fields on the Rack and RackType models.
+
+#### Channelized Subinterfaces ([#20972](https://github.com/netbox-community/netbox/issues/20972))
+
+Channelized (breakout) interfaces can now be modeled natively. A new `channels` field on the Interface model indicates the number of physical channels into which an interface is divided, and each channel is represented by a subinterface of the new generic `channel` type, bound to its parent via the new `channel_id` field. A single cable terminates to the channelized parent interface, and NetBox traces a distinct cable path for each channel subinterface. Both fields are available on interface templates as well.
+
+#### Multi-Protocol Application Services ([#20285](https://github.com/netbox-community/netbox/issues/20285))
+
+Application services and service templates can now expose the same port on multiple protocols — for example, DNS listening on both `tcp/53` and `udp/53`. The single-protocol `protocol` and `ports` fields have been replaced by a unified `port_mappings` field, represented in the APIs as a flat list of `protocol/port` strings (e.g. `["tcp/80", "udp/53"]`). New `port_mappings`, `protocol`, and `port` filters are available in the UI and in both APIs, with the latter two correlated so that they must be satisfied by a single mapping.
+
+#### Module Bay Types ([#19731](https://github.com/netbox-community/netbox/issues/19731))
+
+A new ModuleBayType model has been introduced to convey which kinds of modules a module bay is able to accommodate (e.g. an SFP28 cage or a PCIe x16 slot). Bay types can be assigned to module bays, module bay templates, and module types; where both a bay and a module type declare bay types, NetBox validates that the two sets share at least one type in common before permitting installation. Bay types assigned to a module bay template propagate automatically to each instantiated module bay.
+
+#### Relocating Installed Modules ([#15289](https://github.com/netbox-community/netbox/issues/15289))
+
+An installed module can now be moved to a different module bay, including a bay on a different device, rather than having to be deleted and recreated. A move relocates the module's entire subtree — its components, its own module bays, and any child modules installed within them — and re-resolves any component names, labels, and positions derived from the module type's templates for the destination bay. Cross-device moves are permitted only where the moved components carry no active topology or device-scoped configuration.
+
+#### Background Processing for REST API Requests ([#21992](https://github.com/netbox-community/netbox/issues/21992))
+
+Bulk write operations via the REST API can now be processed as a background job rather than synchronously, avoiding proxy and gateway timeouts on large batches. Appending `?background=true` to a bulk write request enqueues a job and immediately returns an `HTTP 202 Accepted` response containing the job's ID and URL; the job's `data` field records the response the synchronous request would have returned. Note that validation is deferred to the worker, so a `202` response indicates only that the request was accepted, and the job's final status must be inspected to confirm the outcome.
+
+#### Per-Object Errors for Bulk Operations ([#20054](https://github.com/netbox-community/netbox/issues/20054))
+
+When a bulk create or update via the REST API fails validation, the response now identifies each offending object by its index within the submitted list, along with its specific field errors, rather than reporting only the first failure. This enables clients to correct and resubmit only the objects which actually failed.
+
+#### Pre-Rendered Config Context Data ([#21025](https://github.com/netbox-community/netbox/issues/21025))
+
+Rather than compiling config context data on demand from the full set of applicable ConfigContext instances, NetBox now pre-renders each device's and virtual machine's merged context data and caches it on the object itself. The cache is invalidated automatically whenever an upstream change is detected — a config context being created, modified, or deleted, or a change to an attribute which determines which contexts apply — and repopulated by a non-blocking background job. During the brief window between invalidation and re-render, reads fall back to the original on-demand rendering path, so the data returned is always correct rather than stale.
+
+#### Snapshot-Aware Event Rule Conditions ([#18159](https://github.com/netbox-community/netbox/issues/18159))
+
+Event rule conditions can now inspect the pre-change and post-change snapshots captured at the time of an event, rather than only the object's current data. New `changed` and `unchanged` operators compare an attribute's value across the two snapshots, and the `snapshots.prechange.<attr>` and `snapshots.postchange.<attr>` dot-path syntax exposes either snapshot to any standard operator. This makes it possible to express the long-requested "fire only when status changes _to_ active" rule, avoiding webhooks and scripts triggered by unrelated updates. A new `regex` operator has been added as well, and conditions which reference an attribute that cannot be resolved now fail closed and log an error rather than silently disabling the rule.
+
+### Enhancements
+
+* [#15165](https://github.com/netbox-community/netbox/issues/15165) - Re-render only the affected fieldset, rather than the entire form, when an HTMX-driven selection changes
+* [#18645](https://github.com/netbox-community/netbox/issues/18645) - Support the bulk import of cables having multiple terminations per side
+* [#18821](https://github.com/netbox-community/netbox/issues/18821) - Set or update an interface's primary MAC address in a single operation via the `mac_address` field
+* [#20897](https://github.com/netbox-community/netbox/issues/20897) - Include the label alongside the value for selection custom fields in the REST & GraphQL APIs
+* [#21367](https://github.com/netbox-community/netbox/issues/21367) - Add a read-only `is_primary` field to the MAC address REST API representation
+* [#21712](https://github.com/netbox-community/netbox/issues/21712) - Support description annotations for static choice fields, and permit choices to be declared as dictionaries in `FIELD_CHOICES`
+* [#22205](https://github.com/netbox-community/netbox/issues/22205) - Add an `end_of_life` date field to device types and module types to aid in hardware lifecycle planning
+* [#22231](https://github.com/netbox-community/netbox/issues/22231) - Introduce a `nulls_first` parameter to control the placement of empty values when ordering by a custom field
+* [#22409](https://github.com/netbox-community/netbox/issues/22409) - Disallow client-specified API token plaintexts via the REST API
+* [#22411](https://github.com/netbox-community/netbox/issues/22411) - Enforce token write ability when executing a custom script via the REST API
+* [#22441](https://github.com/netbox-community/netbox/issues/22441) - Record and display the execution time of each background job
+* [#22446](https://github.com/netbox-community/netbox/issues/22446) - Introduce breadcrumbs support for declarative layouts
+* [#22486](https://github.com/netbox-community/netbox/issues/22486) - Support a configurable timeout for webhooks, with a new `WEBHOOK_DEFAULT_TIMEOUT` configuration parameter
+* [#22595](https://github.com/netbox-community/netbox/issues/22595) - Introduce the `BULK_UPDATE_CHUNK_SIZE` configuration parameter to bound the number of rows affected by a single bulk `UPDATE` statement
+* [#22604](https://github.com/netbox-community/netbox/issues/22604) - Document the experimental Python package installation and upgrade workflow
+* [#22607](https://github.com/netbox-community/netbox/issues/22607) - Sanitize the HTTP request passed to the template context when rendering custom links
+* [#22640](https://github.com/netbox-community/netbox/issues/22640) - Enforce `ALLOWED_URL_SCHEMES` when validating URL custom field values
+* [#22757](https://github.com/netbox-community/netbox/issues/22757) - Support arbitrary help text on inline form fields
+* [#22786](https://github.com/netbox-community/netbox/issues/22786) - Publish NetBox releases to the production Python Package Index (PyPI)
+* [#22851](https://github.com/netbox-community/netbox/issues/22851) - Unpin `social-auth-core` to permit the installation of newer PyJWT versions
+
+### Performance Improvements
+
+* [#21326](https://github.com/netbox-community/netbox/issues/21326) - Defer updates to the global search cache to a background job, so that they no longer delay the response
+* [#21355](https://github.com/netbox-community/netbox/issues/21355) - Maintain denormalized field data using PostgreSQL triggers rather than Python signal handlers
+* [#21418](https://github.com/netbox-community/netbox/issues/21418) - Replace django-mptt with a PostgreSQL `ltree` implementation for hierarchical models
+
+### Plugins
+
+* [#19821](https://github.com/netbox-community/netbox/issues/19821) - Introduce `GenericObjectChoiceField` and `GenericObjectFormMixin` to represent a generic foreign key relation as a single form field
+* [#22351](https://github.com/netbox-community/netbox/issues/22351) - Enable plugins to register custom Jinja filters and to inject context variables for config template rendering
+* [#22592](https://github.com/netbox-community/netbox/issues/22592) - Enable plugins to add fields and filters to NetBox's existing core GraphQL types
+* [#22770](https://github.com/netbox-community/netbox/issues/22770) - Enable plugins to register custom Event Rule action types by subclassing `EventRuleAction`
+
+### Deprecations
+
+* [#22288](https://github.com/netbox-community/netbox/issues/22288) - The `JINJA2_FILTERS` configuration parameter has been renamed to `JINJA_FILTERS`. The old name remains supported, but will be removed in NetBox v5.0.
+* [#22593](https://github.com/netbox-community/netbox/issues/22593) - The `form_factor`, `width`, `outer_width`, `outer_height`, `outer_depth`, and `outer_unit` fields on the Rack model have been deprecated, and will be removed in NetBox v5.0. These values will instead be inferred from the rack's assigned rack type, which will become a mandatory assignment.
+* [#22935](https://github.com/netbox-community/netbox/issues/22935) - The custom scripts functionality in core NetBox has been deprecated in favor of a dedicated plugin, and will be removed in NetBox v5.0.
+* The `protocol` and `ports` fields on application services and service templates have been deprecated in favor of `port_mappings`, and will be removed from the REST & GraphQL APIs in NetBox v5.0.
+* The MPTT-backed `NestedGroupModel` base class has been deprecated in favor of `NestedLtreeGroupModel`, and will be removed in a future release.
+
+### Other Changes
+
+* [#19091](https://github.com/netbox-community/netbox/issues/19091) - Remove NetBox's custom `querystring` template tag in favor of Django's built-in tag
+* [#20546](https://github.com/netbox-community/netbox/issues/20546) - Raise the minimum required PostgreSQL version from 14 to 15
+* [#20547](https://github.com/netbox-community/netbox/issues/20547) - Consolidate paired uniqueness constraints on nullable fields into single constraints using PostgreSQL's `NULLS NOT DISTINCT`
+* [#21565](https://github.com/netbox-community/netbox/issues/21565) - Remove the obsolete `housekeeping` management command
+* [#21883](https://github.com/netbox-community/netbox/issues/21883) - Drop support for the deprecated Sentry configuration parameters
+* [#21886](https://github.com/netbox-community/netbox/issues/21886) - Remove the obsolete `DEFAULT_ACTION_PERMISSIONS` constant
+* [#21888](https://github.com/netbox-community/netbox/issues/21888) - Remove support for legacy view actions
+* [#21891](https://github.com/netbox-community/netbox/issues/21891) - Remove the `models` key from the application registry
+* [#21902](https://github.com/netbox-community/netbox/issues/21902) - Upgrade django-tables2 to v3.0
+* [#22052](https://github.com/netbox-community/netbox/issues/22052) - Remove the backward compatibility shim for `OptionalLimitOffsetPagination`
+* [#22053](https://github.com/netbox-community/netbox/issues/22053) - Remove the backward compatibility shim for `ExpandableIPAddressField`
+* [#22054](https://github.com/netbox-community/netbox/issues/22054) - Remove the backward compatibility shim for `expand_ipaddress_pattern()`
+* [#22161](https://github.com/netbox-community/netbox/issues/22161) - Rename the filterset test mixin base classes to use a `*TestMixin` suffix
+* [#22300](https://github.com/netbox-community/netbox/issues/22300) - Drop the automatic reverse relationship defined by `OwnerMixin`
+* [#22393](https://github.com/netbox-community/netbox/issues/22393) - Drop support for Redis 5.x
+* [#22438](https://github.com/netbox-community/netbox/issues/22438) - Omit the "2" suffix from the new Jinja plugin resources (`jinja_filters`, `get_jinja_context()`, `register_jinja_filters()`) for consistency with `JINJA_FILTERS`
+* [#22485](https://github.com/netbox-community/netbox/issues/22485) - Move the search subsystem's signal wiring into `AppConfig.ready()` and break its import cycle
+* [#22571](https://github.com/netbox-community/netbox/issues/22571) - Migrate from django-pglocks to django-pgware
+* [#22615](https://github.com/netbox-community/netbox/issues/22615) - Remove the legacy `request_id` and `username` keys from the webhook context
+* [#22909](https://github.com/netbox-community/netbox/issues/22909) - Tolerate an undefined column when flushing deferred search cache updates
+
+### REST API Changes
+
+* New features:
+    * The `background=true` query parameter requests background processing of a bulk write operation, returning `HTTP 202 Accepted` with the enqueued job's ID and URL
+    * Failed bulk create & update operations now return per-object errors correlated by index
+    * Selection & multiple selection custom field values are now returned as `{value, label}` objects
+    * Config context data is now always included for devices & virtual machines; the `exclude=config_context` query parameter is ignored
+* New endpoints:
+    * `GET/POST /api/dcim/cooling-feeds/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-feeds/<id>/`
+    * `GET/POST /api/dcim/cooling-intakes/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-intakes/<id>/`
+    * `GET/POST /api/dcim/cooling-intake-templates/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-intake-templates/<id>/`
+    * `GET/POST /api/dcim/cooling-outflows/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-outflows/<id>/`
+    * `GET/POST /api/dcim/cooling-outflow-templates/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-outflow-templates/<id>/`
+    * `GET/POST /api/dcim/cooling-sources/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/cooling-sources/<id>/`
+    * `GET/POST /api/dcim/module-bay-types/`
+    * `GET/PUT/PATCH/DELETE /api/dcim/module-bay-types/<id>/`
+* `core.Job`
+    * Add read-only duration field `execution_time`
+* `dcim.Device`
+    * Add optional choice field `cooling_method`
+    * Add read-only JSON field `config_context` (previously available only via `DeviceWithConfigContextSerializer`)
+    * Annotate counts of assigned cooling intakes (`cooling_intake_count`) and outflows (`cooling_outflow_count`)
+* `dcim.DeviceType`
+    * Add optional choice field `cooling_method`
+    * Add optional date field `end_of_life`
+    * Annotate counts of cooling intake & outflow templates (`cooling_intake_template_count`, `cooling_outflow_template_count`)
+* `dcim.Interface`
+    * Add optional integer fields `channels` and `channel_id`
+    * The `mac_address` field is now writable, and creates or updates the interface's primary MAC address
+* `dcim.InterfaceTemplate`
+    * Add optional integer fields `channels` and `channel_id`
+    * Add optional foreign key field `parent`
+* `dcim.MACAddress`
+    * Add read-only boolean field `is_primary`
+* `dcim.Module`
+    * Add read-only boolean field `is_bay_compatible`
+    * A module may now be relocated by patching its `module_bay` (the device is derived from the target bay)
+* `dcim.ModuleBay`
+    * Add many-to-many field `module_bay_types`
+    * Add read-only boolean field `is_module_compatible`
+* `dcim.ModuleBayTemplate`
+    * Add many-to-many field `module_bay_types`
+* `dcim.ModuleType`
+    * Add optional choice field `cooling_method`
+    * Add optional date field `end_of_life`
+    * Add many-to-many field `module_bay_types`
+    * Annotate counts of cooling intake & outflow templates (`cooling_intake_template_count`, `cooling_outflow_template_count`)
+* `dcim.Rack`
+    * Add optional choice field `cooling_capability`
+    * Add optional decimal field `cooling_capacity`
+* `dcim.RackType`
+    * Add optional choice field `cooling_capability`
+    * Add optional decimal field `cooling_capacity`
+* `extras.CustomField`
+    * Add boolean field `nulls_first`
+* `extras.EventRule`
+    * Add read-only boolean field `action_is_available`
+    * The `action_object_type` field is now optional, and is no longer restricted to object types which support event rules
+    * The choices available for `action_type` now include any action types registered by plugins
+* `extras.Webhook`
+    * Add optional integer field `timeout`
+* `ipam.Service`
+    * Add the `port_mappings` list field
+    * The `protocol` and `ports` fields are deprecated; they are populated only for single-protocol services and return null otherwise
+    * The brief representation now includes `port_mappings` in place of `protocol` and `ports`
+* `ipam.ServiceTemplate`
+    * Add the `port_mappings` list field
+    * The `protocol` and `ports` fields are deprecated; they are populated only for single-protocol services and return null otherwise
+    * The brief representation now includes `port_mappings` in place of `protocol` and `ports`
+* `users.Token`
+    * The `token` field is now read-only; a plaintext value can no longer be specified on creation
+* `virtualization.VirtualMachine`
+    * Add read-only JSON field `config_context` (previously available only via `VirtualMachineWithConfigContextSerializer`)
+
+### GraphQL API Changes
+
+* New query fields:
+    * `cooling_feed` / `cooling_feed_list`
+    * `cooling_intake` / `cooling_intake_list`
+    * `cooling_intake_template` / `cooling_intake_template_list`
+    * `cooling_outflow` / `cooling_outflow_list`
+    * `cooling_outflow_template` / `cooling_outflow_template_list`
+    * `cooling_source` / `cooling_source_list`
+    * `module_bay_type` / `module_bay_type_list`
+* Selection & multiple selection custom field values resolved via `custom_fields` are now returned as `{value, label}` objects
+* The `ServiceFilter` and `ServiceTemplateFilter` types now expose the flat `port_mappings`, `protocol`, `port`, `port__gt`, `port__gte`, `port__lt`, and `port__lte` parameters in place of the previous `protocol` and nested `ports` lookups
+* The members of `ServiceProtocolEnum` have been renamed from `ROLE_TCP`, `ROLE_UDP`, and `ROLE_SCTP` to `TCP`, `UDP`, and `SCTP`
+* Interface & interface template types now expose the `channels` and `channel_id` fields
+* Device, device type, module type, rack, and rack type types now expose their new cooling fields, and new enums have been introduced for the cooling choice sets
+* Plugins may now extend core output types and filters (see the [plugin GraphQL API documentation](../plugins/development/graphql-api.md))

+ 1 - 0
mkdocs.yml

@@ -346,6 +346,7 @@ nav:
         - git Cheat Sheet: 'development/git-cheat-sheet.md'
     - Release Notes:
         - Summary: 'release-notes/index.md'
+        - Version 4.7: 'release-notes/version-4.7.md'
         - Version 4.6: 'release-notes/version-4.6.md'
         - Version 4.5: 'release-notes/version-4.5.md'
         - Version 4.4: 'release-notes/version-4.4.md'