Skip to content

Infrahub - v1.11.0b1

Pre-release
Pre-release

Choose a tag to compare

@saltas888 saltas888 released this 07 Aug 10:23
85a8439

Infrahub 1.11.0b1 release notes

Release Number 1.11.0b1 (prerelease)
Release Date 04-08-2026
Tag infrahub-v1.11.0b1

Infrahub 1.11.0b1 is now available as a prerelease.

⚠️ This is a prerelease
1.11.0b1 is a beta build, published ahead of the general availability (GA) release of 1.11.0. It is meant for testing and feedback, not for production environments. Anything described in these notes, including the breaking changes below, may still change before GA. Please report issues on GitHub.

This prerelease previews changes that make large environments more predictable to operate. Regeneration, recomputation, and validation now align more closely with the scope of each change, while branch operations and Proposed Changes receive priority over background tasks. New merge recovery and webhook visibility also help you resolve operational issues faster.

⚠️Breaking changes in this prerelease
Artifact generation now deletes an artifact when its target object is no longer a member of the artifact definition's target group.

  • If any workflow reads those artifacts, capture their content before the target is removed from the group. The deletion happens on the next full generation pass over the definition — after a merge, a definition update, or a generate call with no node filter.

See Breaking changes for full details.

⚠️ What to expect after upgrading to this prerelease

The Infrahub container image now includes Python 3.14 (from 3.13) and Neo4j 2026.05.0 (from 2025.10.1). Python Transformations also change how they declare their dependencies.

  • Plan a Neo4j upgrade to 2026.05.0 if you run your own database rather than the version shipped with Infrahub.
  • Declare watch: on any Python Transformation that imports modules from outside its own package directory. Without it, the Transformation recomputes its computed attributes on every commit to its repository. Jinja2 Transformations no longer need it — see Recompute computed attributes only when their inputs change.

See Upgrade notes for full details.

Release highlights

Regeneration and recompute

Task and API priority

Merge protection and recovery

  • Recover a merge whose worker stopped partway through with infrahub recover merge, which rolls back the partial merge and reopens the branch. See Recover from a failed merge.
  • An interrupted merge no longer leaves the default branch half-merged, because writes to both branches are refused while a merge runs. See Recover from a failed merge.

Inspect, retry and cancel webhook deliveries

Schema and data modeling

UI improvements

Regeneration and recompute

Merge a branch, update the schema, or push a commit to a linked repository, and Infrahub regenerates artifacts, re-runs Generators, recomputes derived values, and validates constraints. Each of those is now narrowed to what the change actually affected. Some cases still run in full — see What this does not cover.

Regenerate only what a merge actually changed

Merge a branch and only the artifact and Generator definitions whose inputs that merge changed are regenerated, for only the objects it affected. Merging previously regenerated every definition on the branch, for every member of its target group — one artifact per member. Across the scenarios used to validate this work, the number of regeneration tasks created after a merge fell by between 73% and 100%.

  • A merge reads its diff to decide what to run. A definition is regenerated when its GraphQL query, its definition object, or its code changed, and its members are narrowed to the objects the merge changed.
  • If a merge changes nothing that a definition reads, that definition is not regenerated at all.
  • When a merge runs a Generator, Infrahub waits for the Generator to finish, then regenerates the artifacts built from the objects that Generator created or changed.
  • When Infrahub cannot determine what a change affected, it regenerates every member of that definition rather than leave an artifact stale. A missing diff, a definition that has no fingerprint yet, and an incomplete dependency list each trigger this fallback.
  • Known limitation. A change reached through a relationship — an interface's description, an owner's name — regenerates every member of every affected definition rather than only the members affected. No artifact is left stale, because this regenerates more than is needed rather than less, but artifacts that render relationship data benefit less.
  • Known limitation. A composite artifact that includes another artifact's content stays stale after a merge.

Selective regeneration is controlled by selective_execution_after_merge (INFRAHUB_SELECTIVE_EXECUTION_AFTER_MERGE) and is enabled by default. Set it to false to restore full regeneration on every merge.

Re-run only the Generators a commit affected

Commit to a linked repository and, within a Proposed Change, only the Generators your commit affected re-run — those whose source file, GraphQL query, or definition changed. Correcting a typo in an unrelated README no longer re-runs every Generator across every member of its target group.

  • 1.10 introduced this precise regeneration for artifacts; it now covers Generators as well.
  • Each decision to run or skip is recorded in the Proposed Change's task log, naming the file, query, or definition field responsible.
  • Read-only repositories get the same behavior, even on branches where sync_with_git is disabled.
  • Generators imported before this upgrade keep working unchanged and adopt the precise behavior on their next import. Until then they re-run on any file change in their repository, so no output is left stale during the transition.
  • Known limitation. Editing .infrahub.yml still re-runs everything in that repository.

Infrahub cannot detect every dependency automatically — a helper module imported at runtime from a sibling package, for example. Declare those files with the optional watch: key on generator_definitions in .infrahub.yml:

generator_definitions:
  - name: interface_generator
    file_path: "generators/interfaces.py"
    class_name: InterfaceGenerator
    targets: network-devices
    query: device_interfaces
    watch:
      files:
        - "generators/shared/"          # directory entries are recursive
        - "generators/helpers/naming.py"

Recompute computed attributes only when their inputs change

Commit to a linked repository, or change the schema, and only the computed attributes that change can reach are recomputed. Each of those previously caused a full recompute.

  • A commit to a linked repository previously recomputed every Transformation-based computed attribute in the instance, for every object of its kind. Now only the attributes whose Transformation changed are recomputed, so an edit and its exact revert trigger no recompute.
  • A schema change previously recomputed every computed attribute on the branch. A computed attribute is now recomputed only when the change affects a schema element its value depends on, including elements reached through a relationship. Where the impact cannot be determined, a full recompute still runs.

Both rely on a new fingerprint attribute on the definitions that produce output from a repository: GraphQL queries, transformations, artifact definitions, and Generator definitions. It holds a content hash of the definition's inputs, and it is branch-aware, so a change is detected the same way whether it arrived by a Git import, a merge, a rebase, or a direct edit.

Python Transformations need watch:; Jinja2 Transformations no longer do. A fingerprint is stable only when Infrahub can resolve every file the Transformation depends on. When it cannot, it adds the commit id to the fingerprint, so the Transformation recomputes on every commit to its repository.

  • For a Python Transformation, Infrahub detects only the Transformation's own package directory, so an import from anywhere else needs an explicit watch: list. An empty watch: list opts in.
  • For a Jinja2 Transformation, Infrahub parses the template's include/import/extends graph, so a fully resolved template gets a stable fingerprint without a declaration. The empty watch: {} that 1.10 required is no longer needed. A template with an unresolvable include still recomputes on every commit.

The first import of a Transformation after upgrading recomputes its attributes once. This happens once, not on every commit.

python_transforms:
  - name: cabling_plan
    class_name: CablingPlan
    file_path: "./transforms/cabling_plan.py"
    # Infrahub cannot detect this import from the Transformation's own directory,
    # so declaring it here completes the dependency list.
    watch:
      files:
        - src/infrahub_solution_ai_dc/protocols.py

Learn more: Declaring extra dependencies with watch.

Reduce recompute time after a large merge or rebase

Merge or rebase a branch and the computed attributes, display labels, and human-friendly IDs on the affected nodes recompute in one combined pass. Each changed node previously produced its own recompute job, so a merge across many nodes created many small tasks. The resulting values are identical.

On the reference dataset used during development, a large post-merge recomputation went from about 1,500 background tasks to two, and from about 275 seconds to about one second. Results will vary with the dataset, schema, and automation definitions in each environment.

  • Recomputed values are written in bulk. Each value previously took its own update task and its own API call; results are now saved together.
  • For a computed attribute backed by a Python Transformation, the Transformation's Git repository is initialized once per batch instead of once per object.
  • An object whose recomputed value has not changed is skipped, so it is neither written nor recomputed again.
  • Known limitation. The recompute runs in one task but is not yet narrowed. For a computed attribute backed by a Python Transformation it still recomputes every node of that attribute's kind rather than only the nodes the merge affected. Restricting it to the affected nodes is the next step.

Validate only the constraints a change can violate

Open a Proposed Change, merge, or rebase, and only the constraints that change could break are validated. A branch that changed only data no longer runs every validator in the schema.

  • Only the kinds the change affected are validated, plus the generics they inherit from and any kind whose uniqueness constraint reads an attribute of a changed kind.
  • Within a kind, only the fields a constraint applies to are checked. Changing an attribute that belongs to no uniqueness constraint no longer re-validates that kind's uniqueness, and re-parenting a child no longer runs the children check on the parent.

A uniqueness scan that could not complete on a large dataset now finishes, and a schema diff between two identical branches returns empty.

What this does not cover

The changes above run fewer regenerations and recomputes. None of them makes an individual regeneration or recompute faster.

  • A real change still regenerates every artifact that depends on it. Editing a Transformation, artifact definition, or Generator regenerates every artifact it produces, and this prerelease does not make that regeneration faster.
  • Merge, rebase, and diff are unchanged. This prerelease changes what happens after a merge, not the time it takes to compute and apply the diff.
  • Schema load is unchanged. Computed-attribute recompute and constraint validation are narrowed, but the time to process the schema itself is not. An unrelated schema addition still takes the same time regardless of graph size.

The limitations of each individual change are noted with that change above.

Task and API priority

Interactive operations and background processing previously shared the same task queue and competed for the same API capacity. This prerelease separates them at both levels, so an operation someone is waiting for starts without waiting for the backlog to clear.

Run interactive actions ahead of background work

Start a merge while the instance works through a backlog, and it now runs ahead of that backlog instead of queueing behind it. Infrahub classifies tasks across three priority queues.

  • High — branch operations (create, merge, rebase, delete, validate), Proposed Change merges, Generator definition runs, schema load and check, Transformation rendering, and on-demand artifact generation.
  • Medium — IPAM reconciliation.
  • Low — processing whose result nobody is waiting for: profile refresh, and post-merge follow-ups such as Proposed Change cancellation, automatic branch deletion, and artifact and Generator regeneration. These previously ran at the same high priority as the merge that started them.

A sub-task started by a high-priority operation runs at the same priority, so the priority applies through an entire chain of tasks. The queues are created on startup, so no migration is needed.

Keep the UI responsive when the instance is busy

Keep using the web UI while heavy background processing runs. Because the API previously could not distinguish a UI request from background traffic, a busy instance could stop serving the UI.

  • A request declares its priority with the X-Priority header (high, medium, or low; a missing or invalid value is treated as medium). The web UI sends high on its own calls and low on background calls that opt in.
  • Under sustained overload, lower-priority requests are rejected first, returning 429 Too Many Requests with a Retry-After header before the request does any work.
  • Low-priority requests are rejected before medium ones, and high-priority requests are protected until the database is under extreme load.

An initial data load, or a deliberate full regeneration, now goes through this back-off as well. That protects the instance under peak load, but can make the full run take longer.

On a normally loaded deployment, no requests are rejected. Metrics are published on /metrics, and the whole behavior can be turned off with INFRAHUB_API_BACKPRESSURE_ENABLED=false.

Merge protection and recovery

A merge interrupted by a stopped worker can now be recovered, and a reordered list no longer blocks a merge.

Recover from a failed merge

Recover a merge whose worker stopped partway through, using one command. The instance was previously left with a half-merged default branch and a branch stuck in MERGING, and restoring a backup or running database queries manually was the only option. That state is now detectable, visible, and recoverable.

  • Writes are blocked during a merge. Writes to both the default branch and the source branch are refused while a merge runs, and a new merge or rebase is refused while one is in progress. A blocked write receives an error marked as temporary, asking the caller to retry shortly. The block is removed automatically when the merge finishes or is rolled back.
  • A stalled merge is detected. A merge whose worker is no longer running is recorded as a failed branch, and the default branch stays protected. Writes then receive a distinct, non-retryable error telling the operator that recovery is required.
  • infrahub recover merge restores the previous state. It rolls back the partial merge on the default branch, resets the branch and any associated Proposed Change to OPEN, and removes the write protection. It shows what it will do and asks for confirmation (--yes to skip), and it is safe to run twice. Object, attribute, and relationship timestamps are restored to their pre-merge values, including for objects affected by a schema migration.

Branch-status rejections now include structured GraphQL error codes — BRANCH_ALREADY_MERGED, BRANCH_NEEDS_REBASE, and MERGE_IN_PROGRESS — so API and SDK clients can react to a code instead of matching message text.

Merge branches that reordered the same list

Set the new ordered flag to false on a List or JSON-array attribute so reordering its elements is no longer reported as a conflict during a merge or rebase. Adding or removing an element is still a conflict.

The built-in enum, dropdown choices, used_by, and restricted_namespaces attributes now use this. That resolves a case where two branches held the same set of dropdown choices in a different order, and the branch could not be rebased.

Inspect, retry and cancel webhook deliveries

Open any webhook delivery and see the request Infrahub sent, the response it received, and the number of attempts made. Every delivery is now its own task, visible in the Tasks tab and from the webhook's related-tasks panel.

  • Readable failures. An expected delivery failure — an unreachable target, a TLS problem, a timeout, an HTTP error from the receiver, a misconfiguration — is reported as a named reason with a hint on what to check, instead of a raw Python stack trace. Unexpected errors keep their stack trace, so you can still distinguish a defect in Infrahub from a delivery failure.
  • Automatic retry. A failed delivery retries with a delay between attempts. Retries stop early for failures that cannot succeed on a retry, such as a 4xx response or an invalid configuration.
  • Retry a delivery that has finished. Retrying resends the payload captured when the event occurred, against the webhook's current configuration, so correcting a wrong URL, header, or signing key and then retrying works as expected. The original delivery is kept as a record.
  • Cancel a delivery that is still running. Cancelling stops its remaining attempts.

Schema and data modeling

Store an address without a prefix, and see which fields a schema load does not apply.

Store a bare IP address with the IPAddress kind

Use the new IPAddress attribute kind for a value that is an address and nothing else. Where IPHost normalizes 192.0.2.1 to 192.0.2.1/32, an IPAddress value must not include a prefix length or netmask, and is rejected if it does. DNS records, NTP and syslog targets, monitoring targets, and ACL entries therefore hold the address you entered, with no prefix appended.

IPv6 values are normalized to their compressed lowercase form. Values sort lexically rather than numerically.

Normalize values before changing an attribute's kind

Normalize an attribute's values before converting it to IPHost, IPNetwork, IPAddress, or MacAddress. A conversion is now refused when the existing values are not already stored in the form the new kind requires.

Converting a Text attribute holding aa-bb-cc-dd-ee-ff to MacAddress is rejected, because MacAddress stores AA:BB:CC:DD:EE:FF.

See which fields a schema load does not apply

Submit a schema and see which fields Infrahub did not apply, instead of having them ignored silently. POST /api/schema/load now validates every submitted node, generic, and extension against a published write contract, and reports what it did not apply:

  • A field Infrahub computes and owns — inherited, used_by, hierarchy, and similar — is accepted, dropped, and reported as a warning naming every element that included it. Reading a schema back from Infrahub, editing it, and loading it again keeps working.
  • An unrecognized field name is an error that names the field and its path.
  • An attribute parameter belonging to a different attribute kind, such as start_range on a Number attribute, is now rejected. Earlier versions accepted it and discarded it silently.

infrahubctl schema load and infrahubctl schema check print the warnings, and infrahubctl validate schema reports them offline. The write contract is published as a model in the Python SDK, so a payload can be checked before it is submitted.

UI improvements

Sort and filter large lists from the UI, and choose the date format you read timestamps in.

Sort object lists from the UI

Sort an object list from a column header or from the toolbar, using the backend ordering support added in 1.10. Both controls read the sort from the page URL, so they always agree.

  • From a column header. Clicking a header opens a menu with "Sort ascending", "Sort descending", and "Filter". A column that points at a single related object offers a "Sort by" entry listing that object's sortable attributes. The header shows the active direction; selecting that direction again returns to the default order. Per-column filtering is now the "Filter" item in this menu.
  • From the toolbar. A Sort control beside the Filter control opens a list of sort entries you can add, reorder by dragging, and remove. Dragging changes which field takes precedence. The control shows a count when a sort is active.

A sorted view can be bookmarked and shared. Sorting runs on the server, so it stays fast on large lists. This works in object lists and in the IPAM IP address and prefix lists.

Choose the date and time format for the UI

Choose the date format and timezone you read timestamps in. Dates previously followed the browser's locale, and an organization could not set a default of its own.

  • Set your own date format and timezone from a Preferences card on your account Profile tab. The setting applies on every device you sign in from.
  • Set organization-wide defaults for every user on the Global preferences tab, if you hold the new manage_global_preferences permission.
  • A field you leave unset inherits the organization default, and uses the browser's setting when no default exists. Personal preferences are private: reading or writing them affects only your own record.

Also in the UI

  • Sort the Proposed Changes list by any sortable field. It defaults to newest created first.
  • A branch's details page shows whether you are working on that branch, and offers a one-click switch when you are not.
  • The default branch is identified by the flag the API returns rather than by the name main, which reported the wrong branch when INFRAHUB_INITIAL_DEFAULT_BRANCH was set.
  • Lists show the current data after a write, instead of a deleted row or a stale value until the page was reloaded.
  • Relationship selectors honor the common_parent schema property, offering only peers that share the parent selected elsewhere in the same form.
  • Hierarchical relationships show the related kind's label — "Region" or "Site" — in place of "Parent" and "Children".
  • Adding a child to a hierarchical object pre-fills the parent field with the object you started from.
  • Markdown artifacts render Mermaid diagrams from fenced mermaid code blocks.
  • The branch "Sync with Git" flag explains that it controls whether an Infrahub-created branch is propagated to Git, not whether the branch came from Git.

Delete a repository together with the objects it owns

Delete a repository and the objects it owns are deleted with it. This previously failed. A repository imports and generates objects — Transformations, checks, GraphQL queries, Generators, and the artifact definitions, artifacts, Generator instances, and validators that depend on them. Mandatory relationships attach those objects to the repository, and Infrahub refuses to break a mandatory relationship, so the only way to remove a repository was to delete each of those objects manually, in dependency order.

  • The deletion is still refused, with an error naming the object, if one of those objects is required by something outside the repository, so a partial deletion cannot leave orphaned data.
  • Validators attached to Proposed Changes, and the artifacts and Generator instances they produced, are removed too. That is deliberate: the repository owns those objects.

Minor changes

Performance

  • GraphQL queries that request only the id of a cardinality-one relationship's peer no longer build the full peer node.
  • Diff node field summaries are retrieved in pages bounded by database.query_size_limit, so a very large diff no longer risks exhausting the Neo4j heap during merge and rebase validation.

Reliability

  • Merging or rebasing a branch that deletes a node refreshes the derived values of the nodes that read it across a relationship, so their computed attributes, display labels, and human-friendly IDs no longer name a deleted object.
  • Creating a node no longer fails when a Jinja2 computed attribute formats a value taken from a number pool.
  • Jinja2 transformations are no longer reported as updated on every repository import when their content has not changed.
  • Git repository synchronization no longer stops when a branch that was already merged still exists on the remote.
  • Removing a relationship from a schema closes the underlying relationship data, so stale peers no longer reappear if a relationship with the same identifier is added again later.
  • A flow run waiting for an automatic retry is no longer marked as crashed too early.
  • A TLS certificate verification failure against an external endpoint, such as a webhook target or an SSO provider, is reported as a TLS error rather than a generic connection error.

Telemetry

  • The daily anonymous telemetry payload adds adoption and activity signals: active accounts and account groups, open non-system branches, two node counts that respect branches and time, and a summary of the previous full UTC day. Each field is collected independently, and reporting remains opt-out through INFRAHUB_TELEMETRY_OPTOUT.

Dependencies

  • The frontend GraphQL transport moved from @apollo/client to the lighter @urql/core, reducing the JavaScript bundle size with no change in behavior.
  • The Infrahub container image is smaller: the build toolchain is now in a build stage excluded from the runtime image, and numpy and pyarrow are no longer installed by default. pyarrow remains available through the object-transfer extra for infrahubctl object load.

Breaking changes

Read this section before installing this prerelease. These are the same breaking changes planned for the 1.11.0 GA release, but since this is a beta, treat them as subject to change until GA ships.

Artifacts are deleted when their target leaves the target group

Artifact generation now deletes artifacts whose target object is no longer a member of the artifact definition's target group. Those artifacts were previously kept indefinitely as stale copies — for example after merging a branch that removed the target from the group.

If any workflow reads those leftover artifacts, capture their content before the target is removed from the group. The deletion happens on the next full generation pass over the definition: after a merge, after a definition update, or on a call to the generate endpoint with no node filter.

A related fix limits this cleanup to passes that examined every member, so a generation run narrowed to specific members no longer deletes artifacts it did not examine.

The infrahub git-agent command has been removed

The deprecated infrahub git-agent command has been removed. The task worker replaced it several releases ago. If any script or deployment still calls it, move that call to the task worker before upgrading.

OpenAPI component schemas are renamed

GET /api/schema returns the same response body as before, but its OpenAPI component schemas are renamed to NodeSchemaRead, GenericSchemaRead, ProfileSchemaRead, and TemplateSchemaRead (from APINodeSchema, APIGenericSchema, APIProfileSchema, and APITemplateSchema). If you generate client types from openapi.json, update those type names and regenerate.

Upgrade notes

Runtime versions

If: you run your own Neo4j rather than the version shipped with Infrahub.

Then: plan the database upgrade to 2026.05.0 alongside this upgrade. The container image ships Neo4j 2026.05.0, up from 2025.10.1, and Python 3.14, up from 3.13.

Python Transformations and watch:

If: you use Python transformations that import modules from outside their own package directory.

Then: declare those files with the watch: key on python_transforms entries in .infrahub.yml. An empty watch: list opts in. Without it, Infrahub adds the commit id to the Transformation's fingerprint, and the Transformation recomputes its computed attributes on every commit to its repository. Jinja2 Transformations no longer need watch: — see Recompute computed attributes only when their inputs change.

Notes: the first import of a Transformation after upgrading recomputes its attributes once. This happens once, not on every commit.

Attribute kind conversions

If: you convert an attribute into IPHost, IPNetwork, IPAddress, or MacAddress.

Then: normalize the existing values to the form the new kind stores first. A conversion is now refused when the stored values are not already normalized.

Installing this prerelease

Because 1.11.0b1 is a beta, install it on a staging or test instance, not on production, and use a backup you're comfortable restoring from if something goes wrong.

Before you install this prerelease, we strongly advise you to delete branches that are no longer needed within Infrahub. Deleting old branches helps speed up the upgrade process and avoids running migrations for branches that are no longer needed.

Please read the Breaking changes section above before starting.

Please make sure to upgrade any existing installations of the infrahub-sdk to vTODO.

Please make sure to back up your instance of Infrahub and make sure you are familiar with and have tested the restore procedure. For more information visit https://docs.infrahub.app/backup

First, stop the existing Infrahub instance.

docker compose down

Second, update the Infrahub version running in your environment.

  • For deployments via Docker Compose, download the updated Docker Compose file
    • curl https://infrahub.opsmill.io -o docker-compose.yml
  • Set the VERSION environment variable and start the environment
    • export VERSION="1.11.0b1"; docker compose pull && docker compose up -d
  • For deployments via Kubernetes, use the latest prerelease version of the Helm chart supplied with this build.

Third, once you have the desired version of Infrahub in your environment, run the migrations.

docker compose exec infrahub-server infrahub upgrade

Finally, restart all instances of Infrahub.

docker compose restart

Full changelog

Added

  • Added a selective_execution_after_merge setting (env INFRAHUB_SELECTIVE_EXECUTION_AFTER_MERGE) that narrows post-merge regeneration to the artifact and Generator definitions the merge actually affected, instead of regenerating every definition for every member. When enabled, a merge captures its diff and dispatches only the definitions whose query, definition, or code inputs changed, and only for the affected members. Every uncertain signal falls back to full regeneration, so no affected artifact or Generator can be left stale. On a merge that runs a Generator, the artifacts built from that Generator's output are regenerated after the Generator completes. The setting is enabled by default. (#10033)
  • CoreGraphQLQuery, CoreTransformation, CoreArtifactDefinition, and CoreGeneratorDefinition now include an optional, branch-aware fingerprint attribute holding a content hash of the definition's inputs. A null value means the node predates the feature or has not been re-imported since; nothing is backfilled.
  • Added the ability to request a specific prefix length when allocating from an IP address or IP prefix pool. (#9631)
  • A branch's details page now shows whether you are working on that branch, and lets you switch to it. (#10111)
  • Added a new IPAddress attribute kind that stores a bare IP address, rejecting any value that includes a prefix length or netmask. IPv6 values are normalized to their compressed lowercase form. Values sort lexically rather than numerically. (#10090)
  • The daily anonymous telemetry payload now reports additional adoption and activity signals, including active accounts and account groups, the count of open non-system branches, node counts that respect branches and time, and an activity_24h summary of the previous full UTC day. All changes are additive; each field is reported independently, so a single failing source returns null for that field. (#9805)
  • Added a Sort picker to the Proposed Changes list to order it by any sortable field. The list now defaults to newest created first. (#9915)
  • Webhook deliveries now each run as their own observable task, with automatic retry, a named failure reason, a captured request and response, and operator retry and cancel controls.
  • Writes to the default branch and to the source branch are now blocked for the full duration of a branch merge, and a new merge or rebase is refused while a merge is in progress. Blocked writes receive an error marked as temporary, and the protection is removed automatically once the merge completes or is rolled back.
  • Added the infrahub recover merge CLI command to recover from a failed branch merge. It rolls back the partial merge on the default branch, resets the branch and any associated Proposed Change to OPEN, and removes the write protection. The command is operator-confirmed (--yes to skip) and idempotent.
  • Branch-status write rejections now include structured GraphQL error codes: BRANCH_ALREADY_MERGED, BRANCH_NEEDS_REBASE, and MERGE_IN_PROGRESS (HTTP 423).
  • Priority-aware API backpressure. The API accepts an optional X-Priority request header (high, medium, or low; defaults to medium). Under sustained overload the admission layer rejects lower-priority traffic first, returning 429 Too Many Requests with a Retry-After header. Prometheus metric families are published on /metrics, and the layer can be turned off with INFRAHUB_API_BACKPRESSURE_ENABLED=false.
  • The frontend declares request priority on every API call via the X-Priority header, sending high by default and low for background calls that opt in.
  • Added a database-stress signal derived from the reference permission query, and used it to make API request rejection progressively tiered, with new Prometheus gauges and INFRAHUB_API_BACKPRESSURE_* settings to tune the window, warm-up sample count, per-class thresholds, and per-class caps.
  • Added user and global preferences as internal StandardNode objects. A single Preference model holds both layers: one row per user for that user's overrides, and a separate row for organization-wide defaults (date_format, timezone). The InfrahubEffectivePreferences GraphQL query returns the merged effective values for the calling user.
  • Added a personal Preferences card to the account Profile tab for date format and timezone, a Global preferences tab for administrators, and the manage_global_preferences global permission that governs the organization-wide row.
  • Removing a relationship from a schema now closes the relationship data using that schema instead of leaving it active but unreachable in the graph. (#2474)
  • Markdown artifacts now render Mermaid diagrams from fenced mermaid code blocks.
  • Added an input style variant to the Button component and adopted it for selector triggers so they match the styling of form inputs.

Changed

  • Breaking: artifact generation now deletes artifacts whose target is no longer a member of the artifact definition's target group. Any workflow that relied on reading those leftover artifacts must capture their content before the target is removed. (#9790)
  • Allocating from an IP address or prefix pool with a conflicting prefix length now returns a clear error instead of silently reusing the existing reservation. (#9631)
  • The fingerprint commit-id fold is now builder-aware, so a Jinja2 Transformation whose dependencies are fully resolved produces a stable fingerprint without an explicit watch: declaration. Python Transformations and Generators are unchanged — Infrahub detects only their package directory, so a watch: declaration is still required to omit the commit id. (#10096)
  • Changing an attribute's kind is now rejected when the existing values are not already stored in the form the new kind requires. This affects conversions into IPHost, IPNetwork, IPAddress, and MacAddress. (#10090)
  • POST /api/schema/load now validates every submitted node, generic, and extension against a user-facing write contract, and reports the fields it does not apply instead of ignoring them. The write contract is published as a committed model in the Python SDK. GET /api/schema OpenAPI component schemas are renamed to NodeSchemaRead, GenericSchemaRead, ProfileSchemaRead, and TemplateSchemaRead. (#10095)
  • When a Proposed Change includes commits to a linked repository, Infrahub now re-runs only the Generators whose source, GraphQL query, or definition was actually affected by the change, and records each run-or-skip decision in the Proposed Change's task log. Extra dependencies can be declared with the optional watch: key on generator_definitions entries in .infrahub.yml.
  • When a Git commit changes a Python Transformation, Infrahub now recomputes only the computed attributes whose Transformation actually changed, instead of recomputing every Transformation-based computed attribute on any commit.
  • Merging or rebasing a branch now runs a single combined recompute for computed attributes, display labels, and human-friendly ids instead of one recompute job per changed node, and saves the results in bulk. A node whose recomputed value has not changed is skipped. The recompute runs as one task but is not yet narrowed: for a Python-Transformation computed attribute it still covers every node of that attribute's kind. (#10034)
  • Improved the performance of GraphQL queries that request only the id of a cardinality-one relationship's peer. (#10062)
  • Diff node field summaries are now retrieved in pages bounded by database.query_size_limit instead of a single aggregating query. (#10106)
  • Tasks a user is waiting on now run at high priority; profile refresh and post-merge follow-ups run at low priority, with IPAM reconciliation at medium.
  • Column headers in object lists and IPAM IP address and prefix lists now open a menu to sort the list from the column, and per-column filtering moves into that menu.
  • Hierarchical parent and children relationships now display the related kind's label instead of the generic "Parent" and "Children" everywhere they appear.
  • Added an explanation to the branch "Sync with Git" flag clarifying that it controls whether an Infrahub-created branch is propagated to Git. (#9883)
  • Flow runs that stop sending heartbeats are marked as crashed only after a longer grace period.
  • Upgraded Python to 3.14 (from 3.13). Upgraded Neo4j to 2026.05.0 (from 2025.10.1).

Fixed

  • Branches containing only data changes no longer run every validator across every kind in the schema. Schema diffs between identical branches now return empty. (#2592)
  • Schema constraint validation triggered by a data change now runs only the node-level constraints whose specific field or path was actually modified. (#10019)
  • Computed-attribute recompute is now narrowed to the schema elements a change actually affects, including elements reached through relationships. (#9415)
  • Added an ordered flag to attribute schemas. When set to false on a List or JSON-array attribute, reordering its elements is no longer reported as a conflict during merge and rebase. The built-in enum, dropdown choices, used_by, and restricted_namespaces attributes now use this. (#9764)
  • Merging or rebasing a branch that deletes a node now refreshes the derived values of the nodes that read the deleted node across a relationship. (#9845)
  • Fixed node creation failing when a Jinja2 computed attribute formatted a value taken from a number pool. (#7836)
  • Fixed Jinja2 Transformations always being marked as updated during repository imports even though there were no changes. (#3094)
  • Fixed git repository synchronization stopping when a branch that had been merged still existed on the remote. (#9931)
  • POST /api/schema/load now returns the warnings it collected even when the submitted schema matches the one already loaded. (#10095)
  • Fixed relationship selectors in object forms not honoring the common_parent schema property. (#10039)
  • Fixed the frontend identifying the default branch by the literal name main rather than by the is_default flag the API returns. (#10129)
  • Fixed concurrent GraphQL calls from the frontend sharing a single in-flight request and receiving each other's responses. Every call now gets its own request. (#10136)
  • Artifact generation no longer deletes artifacts that a narrowed run did not examine; the stale-artifact cleanup now runs only for a pass that examined every member.
  • Artifact and Generator regeneration during a Proposed Change no longer fails when a definition references a repository that has no changes in the branch diff.
  • Selective regeneration no longer skips an artifact or Generator when the change affects a node the definition's query reads through a relationship, and now narrows Generator instances to the members actually affected.
  • Fixed display labels and human-friendly ids that read across a relationship not refreshing when they were recomputed by their own id.
  • Rolling back a failed branch merge now fully restores updated_at and updated_by metadata, including for objects affected by a schema migration, and a recovery interrupted partway through can be re-run cleanly.
  • Webhook task runs can now be found from the webhook related-tasks panel.
  • A TLS certificate verification failure when Infrahub connects to an external HTTPS endpoint is now reported as a TLS error instead of a generic connection error.
  • Fixed some GraphQL requests returning an unexpected HTTP 500 error instead of a node-not-found (404) response. (#9926)
  • When adding a child to a hierarchical object, the creation form now pre-fills the parent field with that object.
  • Fixed the focus ring on text inputs being clipped on the left and right edges when an object form is opened inside a sheet.

Removed

  • Removed the infrahub git-agent command line utility, which was deprecated several releases ago and replaced by the task worker. (#5584)

Housekeeping

  • Reduced the size of the Infrahub container image: the build toolchain is now in a dedicated build stage excluded from the runtime image, and numpy and pyarrow are no longer installed by default (pyarrow remains available via the object-transfer extra for infrahubctl object load).
  • Replaced the frontend GraphQL transport (@apollo/client) with the lighter @urql/core, preserving all request behavior. (#10059)
  • Restructured the frontend tooling around a pnpm workspace with one shared lock file, a shared catalog for cross-package versions, and BuildKit cache mounts in the node build stages.
  • Introduced a shared isRelationshipSchema type guard in the frontend schema entity so attribute and relationship discrimination is defined in one tested place.
  • Made the Neo4j Bolt connector thread-pool ceiling tunable in the testcontainers stacks via INFRAHUB_TESTING_DB_BOLT_THREAD_POOL_MAX_SIZE.