⚠️ This beta is intended for testing purposes only and should not be used in production environments.
v1.11.0b2 is the third beta of Infrahub 1.11.0. It includes everything released in 1.10.7.
Release summary
The theme of 1.11 is scale and performance. Until now, almost any change caused Infrahub to redo work the change could not have affected: merging a branch re-ran every Generator and regenerated every artifact, and a single commit to a linked repository recomputed every Transformation-based computed attribute in the instance. On a large dataset that meant thousands of background tasks and an instance that stayed busy long after the merge finished. 1.11 makes that work proportional to what actually changed.
- Routine changes stay proportional to what changed. A merge, a commit to a linked repository, or a schema update no longer keeps the whole instance busy, so the outputs you are waiting on arrive without queueing behind unrelated work.
- Large branches and large diffs stay workable. A Proposed Change with thousands of changed nodes opens its data diff, and deleting a large branch completes instead of leaving the branch behind.
- Webhook deliveries become first-class tasks you can inspect, retry and cancel. When a downstream system stops acting on an event, you can see what was sent and what came back, then retry it once the configuration is corrected.
- An interrupted merge no longer needs a backup restore. One command returns the branch and its Proposed Change to a reviewable state.
- Large inventories are easier to navigate. Object and IPAM lists sort and filter on the server, and everyone reads timestamps in their own date format and timezone.
- The Infrahub Marketplace is publicly available. You can start from schemas and collections that are tested to load together, instead of building a data model from an empty schema.
- Infrahub Collect gathers support diagnostics in one command. The new read-only CLI produces a single archive from a Docker Compose or Kubernetes deployment, so it is safe to run against a production instance that is already degraded.
Changes since v1.11.0b1
If you already tested b1, these are the changes to retest. Everything else in this document is unchanged from b1.
- A Python Transformation or Generator depends on its own file, not on its directory. Infrahub detects one dependency automatically — the file at
file_path— where earlier versions treated every Git-tracked file in that file's directory as a dependency too. Awatch:declaration written against the old behavior may now be incomplete, so read the Upgrade notes entry onwatchbefore upgrading if you declare it on apython_transformsorgenerator_definitionsentry. - Computed attributes recompute on the values they actually read. A Python computed attribute that reads only a node's
hfidwas never recomputed when thathfidchanged. One that reads adisplay_label, or follows a relationship to a generic, recomputed on any update to those kinds — and on every schema change. - The data diff of a large Proposed Change opens. The Data tab failed with
RangeError: Invalid array lengthonce a diff spanned more than one page, which is any diff of roughly 300 nodes or more, so the larger the change the less likely it could be reviewed in the UI. - Deleting a large branch completes. Past a certain branch size the deletion exceeded the Neo4j transaction memory limit and left the branch in
DELETING, invisible in the branch list, with most of its data still in the graph.infrahub upgradefinishes deleting branches left behind that way. - Event-driven automations keep firing on mutations that change hundreds of objects. An event listing that many related resources was refused, and a refused event closes the event stream — so every automation driven by those events stopped, not just the one for that mutation.
- A rebase runs its schema migrations against the right baseline. Migrations used the destination branch's current schema, so any element added there after the branch forked looked pre-existing and the work to align the branch's data was skipped.
- A number pool can be declared over a range that already contains data. A
CoreNumberPoolused to park permanently on a value created outside the pool: uniqueness rejected it, the failed allocation reserved nothing, and the pool offered the same value again on every later attempt. - A repository whose default branch is not
mainworks. Artifact generation failed and the repository went to an error state on any deployment with more than one worker, and a merge did not reliably reach a non-maindefault branch on the remote. - Date and time preferences render consistently. Detail pages keep the time component of your chosen format, a date far in the future uses that format instead of a relative phrase, the format preview uses the timezone being edited, and a timezone no client can render is rejected at write time.
has_schema_changesis deprecated in favor ofschema_differs_from_default_branchon theBranchandInfrahubBranchGraphQL types. It still returns the same value and is scheduled for removal in 1.14.0.
Before upgrading
Breaking changes
⚠️ Breaking changes in this release
- Artifact workflows after target removal: If your workflow relies on an artifact remaining available after its target is removed from the artifact definition's target group, Infrahub deletes that artifact on the next full generation pass. Capture any required content, or update the workflow, before removing the target.
infrahub git-agent: Scripts or automation that still call this command will no longer work after upgrading. Replace those calls with the task worker.- Generated OpenAPI clients: Code that depends on the previous component schema names in
openapi.jsonneeds to be updated and regenerated.The full Breaking changes section below explains the impact of each and the action to take.
Upgrade preparation
📌 Non-breaking preparation
- Separately managed Neo4j deployments: Upgrade Neo4j to
2026.05.0alongside Infrahub.- Python Transformations and Generators with
watchdeclarations: Awatchdeclaration must now name every file the source depends on beyond the file at its ownfile_path, including helper modules in the same directory. Naming the containing directory covers them in one entry.- Attribute-kind conversions: Normalize existing values before converting an attribute to
IPHost,IPNetwork,IPAddress, orMacAddress.- Deprecated GraphQL field:
has_schema_changesonBranchandInfrahubBranchstill returns the same value and is scheduled for removal in 1.14.0. Move clients toschema_differs_from_default_branch.The Infrahub container image includes Python 3.14 and Neo4j 2026.05.0. Expect a one-time recomputation the first time each Transformation is imported after upgrading.
Regeneration and recompute
Regenerate only affected definitions and members after a merge
When you merge a branch or a Proposed Change, Infrahub now regenerates only the artifact and Generator definitions whose inputs the merge actually changed, and only for the members affected — instead of regenerating every definition for every member.
A merge captures its own diff and uses it 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 change touched. Across the scenarios used to validate this, the number of regeneration tasks a merge produces fell by between 73% and 100%. When a merge runs a Generator, Infrahub waits for it to finish and then regenerates the artifacts built from the objects that Generator created or changed.
The rule the selection follows is that regenerating too much is acceptable and regenerating too little is not.
- Fallback behavior. A missing or unreadable diff, a definition with no fingerprint yet, and an incomplete dependency list each cause Infrahub to regenerate every member of that definition. This creates more tasks than necessary, but no affected artifact is left stale.
- Data referenced through relationships. An interface's description or an owner's name cannot always be resolved to specific members, so Infrahub regenerates all members of the affected definitions. Definitions that render relationship data therefore see a smaller reduction than those built directly from the changed objects.
Selective regeneration is controlled by selective_execution_after_merge (INFRAHUB_SELECTIVE_EXECUTION_AFTER_MERGE) and is enabled by default. Setting it to false restores full regeneration after every merge.
⚠️ Known limitation
If you use a composite artifact that includes content from another artifact, changing the included artifact during a merge does not currently cause the composite artifact to be regenerated.
Re-run only affected Generators after a linked repository is updated
Generators, Transformations, and GraphQL queries usually live together in a repository shared by an automation team, and any commit to it used to re-run every Generator across every member of its target group. Within a Proposed Change, a Generator is now re-run only when the commits in the branch affected its source file, its GraphQL query, or its definition. A typo fixed in an unrelated README no longer re-runs anything.
This extends to Generators the precise regeneration that 1.10 introduced for artifacts. Each decision to run or skip is recorded in the Proposed Change's task log, naming the file, query, or definition field responsible, so a reviewer can see why a Generator ran without tracing the repository themselves. Read-only repositories participate on the same terms, even on branches where sync_with_git is disabled.
Generators imported before this upgrade keep working unchanged. Infrahub applies the narrower dependency checks to a Generator definition the next time it imports that definition; until then it may re-run that Generator on any file change in the repository, so no output goes stale during the transition. Editing .infrahub.yml re-runs every Generator in that repository, because the file defines what each of them depends on.
Infrahub detects one dependency on its own: the file named by the entry's file_path. Everything else a Generator reads — a helper module beside it, a shared package elsewhere in the repository — is declared with the optional watch: key on generator_definitions in .infrahub.yml. A watch entry naming a directory covers every Git-tracked file beneath it, so one line can cover a Generator and the modules it sits with:
generator_definitions:
- name: interface_generator
file_path: "generators/interfaces.py"
class_name: InterfaceGenerator
targets: network-devices
query: device_interfaces
watch:
files:
- "generators/" # directory entries are recursive
- "shared/naming.py"Recompute computed attributes only when their inputs change
Two separate causes of unnecessary recomputation are addressed.
- A commit to a linked repository used to recompute every Transformation-based computed attribute in the instance, for every object of its kind. Infrahub now recomputes only the attributes whose Python Transformation actually changed. An edit and its exact revert leave the Transformation unchanged and trigger no work at all.
- A schema change used to recompute 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, Infrahub falls back to recomputing every computed attribute on the branch, so nothing goes stale.
Underneath both, definitions that produce output from a repository — GraphQL queries, Transformations, artifact definitions and Generator definitions — now include a fingerprint attribute holding a content hash of their inputs. Because the fingerprint is branch-aware, a change to a definition is detected the same way whether it arrived by a Git import, a branch merge, a rebase or a direct edit. A null fingerprint means the definition has not been imported since upgrading.
A Python Transformation that declares no watch key has the commit id folded into its fingerprint, so it continues to recompute on every commit to its repository — scoped to its own attributes only, rather than to every computed attribute in the instance. Declaring watch with an explicit list, including an empty one, opts that Transformation into precise, commit-independent recomputation. Jinja2 Transformations no longer need the empty declaration that 1.10 required, because Infrahub resolves their dependencies from the include, import, and extends graph; a template dependency it cannot resolve still recomputes on every commit.
Infrahub does not read your imports, so the only dependency it detects for a Python Transformation is the file at its file_path. A helper module is a dependency whether it sits in another package or directly beside the Transformation, and either way it has to be declared. Naming the containing directory declares a whole group of them at once:
python_transforms:
- name: cabling_plan
class_name: CablingPlan
file_path: "./transforms/cabling_plan.py"
# cabling_plan.py imports helper modules from transforms/ and from the src
# package. Naming both here completes the dependency list, so the artifact
# regenerates only on a real dependency change.
watch:
files:
- transforms/
- src/infrahub_solution_ai_dc/protocols.pyDeclaring watch on any Transformation is now a best practice, so its outputs are regenerated only when a real dependency changes. The declaration has to carry the files list — a bare watch: with nothing under it reads as no declaration at all. The first import of a Transformation after upgrading recomputes its attributes once; that is a one-time cost, not a per-commit one.
More information can be found in the documentation.
Recompute only on the values a computed attribute reads
A computed attribute is recomputed by triggers derived from the fields its query reads. Three gaps in that derivation are closed, in both directions: a value that never refreshed now does, and values that refreshed on unrelated changes now hold still.
- A
hfida query reads now triggers a recompute. The query analyzer did not recordhfidas a field, so a query that read only thehfidof a node produced no trigger at all and its computed attribute never refreshed when thathfidchanged. - A
display_labela query reads no longer triggers on every update to that kind. Reading adisplay_labelproduced a trigger with no field filter, so any update to a node of that kind started a recompute. Both properties are now reported under the name the schema and the change events use, so a trigger filters on them directly. - A relationship to a generic no longer recomputes on unread member kinds. The analyzer reports every member kind of a generic, including the ones the query reads no field from. Those kinds produced unfiltered triggers, so any update to such a node started a recompute, and the values that recompute wrote could match the same triggers again and cascade. A kind the query reads no field from is now kept as a kind-level dependency: adding or removing that kind still recomputes, and changing a field on it does not.
Before this, a Python computed attribute whose query followed a relationship to a generic was also recomputed on every schema change, because a member kind with no read field made the whole read set imprecise.
Reduce recompute work after a large merge or rebase
Some changes are meant to be broad: updating a device type, a naming convention, or a computed description can touch thousands of objects at once. Merging or rebasing that branch now runs a single combined recompute for computed attributes, display labels and human-friendly IDs, instead of one recompute job per changed node. The work scales with the number of derived values actually affected rather than with how many nodes were touched, and the resulting values are unchanged.
Results are saved in batches rather than through a separate update task and API call for each value, a Python Transformation's Git repository is initialized once per batch instead of once per object, and a value that has not changed is not written at all.
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 vary with the dataset, schema, and automation definitions in each environment.
- Fallback behavior. The recompute runs in one task but is not yet narrowed to the affected nodes. For a computed attribute backed by a Python Transformation, Infrahub still recomputes every node of that attribute's kind.
Validate only the constraints a change can violate
Schema constraint validation during Proposed Change checks, merges and rebases used to run against every kind in the schema, even for a branch that changed only data. It is now scoped twice over: to the kinds the change touched — plus the generics they inherit from and any kind whose uniqueness constraint reads an attribute of a changed kind — and to the fields a constraint actually guards. Changing an attribute that participates in no uniqueness constraint no longer re-validates that kind's uniqueness, and re-parenting a child runs the children check on the parent only when that constraint could be affected.
The amount of validation no longer grows with the total size of your schema, and a schema diff between two identical branches now correctly comes back empty.
Where the performance improvements apply
These changes reduce the regeneration, recomputation, and validation created around a change. They do not make the underlying operations themselves faster.
- Changing a Transformation, artifact definition, or Generator still regenerates every artifact that depends on it.
- The time to compute and apply a merge, rebase, or diff is unchanged; the reduction is in what happens around and after those operations.
- Schema loading itself is unchanged; the reduction applies to the computed-attribute recomputation and constraint validation that follow a schema update.
Task and API priority
Run active change tasks ahead of background work
Background work and the operations a user is waiting on used to share a single queue, so clicking "merge" while the instance worked through a backlog meant waiting behind all of it. Infrahub now runs three priority lanes. Every task required to complete a branch create, merge, rebase, delete or validation operation is processed at the priority of that operation, and the same applies to the tasks created when a Proposed Change is merged.
- High. Branch create, merge, rebase, delete and validate; Proposed Change merges; Generator definition runs; schema load and check; Transformation rendering; and on-demand artifact generation.
- Medium. IPAM reconciliation.
- Low. Profile refresh, and post-merge follow-ups such as Proposed Change cancellation, automatic branch deletion, and artifact and Generator regeneration — which previously inherited the merge's own high priority.
The queues are created automatically on startup, so an upgraded instance needs no manual migration.
Keep the UI responsive when the instance is busy
Heavy background work and the web UI compete for the same finite API and database capacity. Because the API could not tell the two apart, a busy instance could stop serving the UI altogether and the application appeared to hang.
Requests can now declare their priority with an X-Priority header (high, medium or low; anything missing or invalid is treated as medium). Under sustained overload Infrahub asks lower-priority requests to retry first, returning 429 Too Many Requests with a Retry-After header before the request does any work, so interactive traffic keeps flowing. The web UI sends high on its own calls and low on background traffic that can retry later.
An initial data load or a deliberate full regeneration goes through the same back-off, which protects the instance under peak load but can make that run take longer. On a normally loaded deployment no requests are rejected. Admission metrics are published on /metrics, and the whole layer can be switched off with INFRAHUB_API_BACKPRESSURE_ENABLED=false.
Merge protection and recovery
Recover from a failed merge
If the worker running a merge is killed partway through, the instance used to be left with a half-merged default branch, a branch stuck in MERGING, and no way back other than restoring a backup or running manual database queries. 1.11 makes that state detectable, visible, and recoverable.
- Writes are blocked for the duration of 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 until it completes. A blocked write receives a transient message asking the caller to retry shortly, and the block lifts automatically when the merge finishes or is rolled back.
- A stalled merge is detected. Infrahub notices when a merge's worker is no longer running, records the branch as failed, and keeps the default branch protected. Writes then receive a distinct, non-retryable error telling the operator that recovery is required — separate from the transient "merge in progress" case, so a client does not retry forever.
infrahub recover mergeputs things back. The command rolls back the partial merge on the default branch, resets the branch and any associated Proposed Change toOPEN, and lifts the write protection. It shows what it will do and asks for confirmation (--yesto skip), and it is safe to run twice — an interrupted recovery can simply be run again. Object, attribute and relationship timestamps are restored to their pre-merge values, including for objects affected by a schema migration.
The original work stays available for inspection, so once the underlying problem is resolved the same branch goes through the normal validation and review workflow again.
Branch-status rejections now also 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.
Rebase a branch after the default branch changed
A rebase runs schema migrations to bring the branch's data in line with the schema it is being rebased onto. Those migrations used the destination branch's current schema as their baseline, so any schema element added on the destination after the branch forked already looked pre-existing, and the work needed to align the branch's data was skipped. Migrations now run against the schema the branch was created from, which still reflects what changed on either side.
A rebase that fails while running its migrations also restored the wrong schema. The branch was left with the schema it was created from, silently dropping any schema change made on the branch itself, and the recorded schema hash was wrong as a result. The rollback now restores the schema the branch held immediately before the rebase started.
Delete a large branch
Deleting a branch ran as a single database statement whose peak transaction memory grew with the size of the branch. Past a certain size it exceeded the Neo4j transaction memory limit, and because the inner writes had already committed in batches, the failure left the branch in DELETING — invisible in the branch list — with most of its data still in the graph.
The deletion now runs as a series of bounded queries, so peak transaction memory is a function of the batch size rather than of the branch. Naming the relationship type in each batch also lets the branch index serve the match instead of reading every edge in the database. Branches left behind by an earlier failed deletion are finished during infrahub upgrade.
Merge branches when list order is not meaningful
Attribute schemas gain an ordered flag. Setting it to false on a List or JSON-array attribute means reordering that attribute's elements is no longer reported as a conflict during a merge or rebase, while adding or removing an element still is.
The built-in enum, dropdown choices, used_by and restricted_namespaces attributes now use this. That resolves a case where two branches ended up holding the same set of dropdown choices in a different order and the branch still could not be rebased.
Keep event-driven automations running on large mutations
A mutation that changes group membership emits an event listing the members it touched as related resources. A mutation that changed a few hundred members or more produced an event large enough to be refused, and a refused event closes the event stream rather than being dropped on its own — so every automation driven by those events stopped firing, not just the one for that mutation.
Two causes are addressed. The related resources on a group mutation event are now consolidated to one entry per member and per ancestor, and node and group mutation events are truncated to a budget that leaves room for the run-context resources the task manager appends afterwards — the flow run, task run, flow, deployment, work queue, work pool, and one entry per flow-run tag — which it adds after the client-side check has already run. The full member list remains available in the event payload.
Webhook deliveries
When a downstream system stops acting on Infrahub events, the first question is whether the webhook fired at all. The webhook's own Tasks tab used to report no deliveries, a successful delivery recorded no payload or response, and a failure showed a Python traceback with the cause buried inside it.
Every delivery is now its own task, listed in the Tasks tab and in the webhook's related-tasks panel, recording the request URL and headers, the response status code and body, and how long the target took to respond. Large response bodies are truncated. Infrahub masks the signature, any header value sourced from the environment, and well-known credential headers such as Authorization and X-API-Key, so inspecting a delivery does not expose them.
- Failures are readable. 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 remediation hint, such as "The target rejected the request; check the URL and authentication." Unexpected errors keep their stack trace, so a genuine defect still looks like one.
- Deliveries retry on their own. A failed delivery is retried up to three times, two minutes apart, rather than exhausting its retries in a few seconds as before. Every failure is retried, including a
4xxresponse or a header value Infrahub cannot resolve. - You can retry a settled delivery. Retrying replays the payload captured when the event fired, resolves the webhook configuration again so a corrected URL, header or signing key applies, and runs as a new delivery. The original delivery is preserved as a record.
- You can cancel one still running. Infrahub checks for a cancellation before each attempt, so cancelling during the wait stops the remaining ones. A request already sent cannot be recalled, and a delivery that has already settled cannot be cancelled.
Schema and data modeling
Model an IP address without a prefix length
Use the new IPAddress kind when the value represents an address only, such as a DNS record, an NTP or syslog target, a monitoring target, or an ACL entry. Where IPHost normalizes 192.0.2.1 to 192.0.2.1/32, an IPAddress value keeps the address you entered, and a value that includes a prefix length or netmask is rejected. IPv6 values are stored in compressed lowercase form, and values sort lexically rather than numerically.
Normalize values before changing an attribute's kind
If you change an attribute to IPHost, IPNetwork, IPAddress or MacAddress, the existing values must already match the storage format the new kind requires; Infrahub now rejects the conversion when they do not. A Text value of aa-bb-cc-dd-ee-ff, for example, must be normalized before conversion to MacAddress, where the value is stored as AA:BB:CC:DD:EE:FF.
Allocate from a number pool over a range that already contains data
A CoreNumberPool used to park permanently on a value that already existed on the target kind but was created outside the pool: the pool offered the value, the attribute's uniqueness constraint rejected it, and because the failed allocation reserved nothing, the pool offered the same value again on every later attempt.
When the target attribute is unique, the pool now skips values already present on the target and advances to the next free one, so a pool can be declared over a range that already contains data. Attributes that are not unique on their own, including those covered by a per-relationship uniqueness constraint, are unaffected and remain fully allocatable.
See which fields a schema load does not apply
A schema load used to ignore fields it does not apply, so a setting could have no effect with nothing to say why — start_range on a Number attribute was accepted and discarded, and a mistyped field name behaved the same as a correct one. POST /api/schema/load now validates every submitted node, generic and extension against a published write contract and reports what it did not apply.
Fields Infrahub computes and manages, such as inherited, used_by and hierarchy, are accepted, dropped, and reported as warnings, so reading a schema back from Infrahub, editing it, and loading it again keeps working. An unrecognized field name is an error naming the field and its path, and a parameter that belongs to a different attribute kind is rejected rather than discarded silently. infrahubctl schema load and infrahubctl schema check print the warnings, infrahubctl validate schema reports them offline, and the write contract is published as a model in the Python SDK so a payload can be checked before it is submitted.
The exported node JSON Schema now closes every object and declares the read-only fields alongside the rest, marked deprecated. An editor validating a schema file against that document rejects the same typo the load endpoint rejects, and a schema read back from Infrahub still validates.
UI improvements
Sort and filter object and IPAM lists
Object and IPAM lists can now be sorted and filtered from the UI, using the backend ordering support added in 1.10. Sorting runs on the server, so it applies to the complete result set rather than the current page, and stays responsive on large inventories.
From a column header, sort ascending or descending, filter from the same menu, or sort by a supported attribute on a related object when the column references a single related object. From the toolbar, add multiple sort fields, reorder them to change which takes precedence, and remove the ones you no longer need. A device list can be sorted by site and then by role, or a prefix view organized by namespace while you review address capacity.
The selected sort is stored in the page URL, so the resulting view can be bookmarked or shared.
Open the data diff on a large Proposed Change
The Data tab of a Proposed Change failed with RangeError: Invalid array length once the diff spanned more than one page, which is any diff of roughly 300 nodes or more — so the larger the change, the less likely it could be reviewed in the UI at all.
Each page of a diff also carries the ancestors of its own nodes as hierarchy context, so the same node arrives on several pages, and the duplicated entries corrupted the diff tree the tab renders from. Each node is now kept once, preferring its changed entry when a page also delivered it as an unchanged placeholder. On the server side, field summaries for a large diff are retrieved in pages bounded by database.query_size_limit, which reduces the risk of exhausting the Neo4j heap while the same diff is validated.
Set personal and organization-wide date and time preferences
Dates in the UI followed the browser's locale, and an organization had no way to set a house format. Each user can now choose their own date format and timezone from a Preferences card on the account Profile tab, and the choice applies wherever you sign in with the same account. Administrators holding the new manage_global_preferences permission set organization-wide defaults on a Global preferences tab. A field left unset inherits the organization default, and falls back to the browser's setting when no default exists. Personal preferences are private: reading or writing them only ever touches your own record.
A timezone is validated when it is written, so a value that no client can render is rejected through the API and the SDK rather than stored. The Example preview and the source hint in the preferences forms render in the timezone being edited, and the hint reports the browser fallback when your browser cannot render the stored zone. DateTime attributes on a detail page keep the time component of your chosen format, and a date far in the future uses that format instead of a relative phrase.
Choose a prefix length when allocating from a pool
Allocate an IP address or prefix using the prefix length that request needs, rather than always taking the pool default. The prefix length can be set from the allocation form in the UI and inline in a GraphQL mutation. Allocating with a prefix length that conflicts with an existing reservation now returns a clear error instead of silently reusing that reservation.
Also in the UI
- Sort the Proposed Changes list by any sortable field; newest created appears first by default.
- 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 whenINFRAHUB_INITIAL_DEFAULT_BRANCHwas set. - The task status button in the header keeps you on the branch you were working on instead of switching to the default branch.
- Lists show current values immediately after records are created, edited, or deleted.
- Relationship selectors honor the schema's
common_parentproperty, offering only peers that share the parent selected elsewhere in the same form. - The parent filter on a relationship to a hierarchical node starts empty instead of selecting the first available object, and is pre-filled only from an existing relationship value or from parent context.
- Hierarchical relationships show the related kind's label — Region or Site — in place of generic Parent and Children labels.
- Adding a child from a hierarchical object pre-fills the parent field.
- A repository opened from the Git repositories homepage widget opens on its own kind, so its details page and edit form show all of its fields.
- Markdown artifacts render Mermaid diagrams.
- The branch Sync with Git flag explains that it controls whether an Infrahub-created branch is propagated to Git, not whether the branch originated in Git.
Linked repositories
Use a repository whose default branch is not main
A worker with no local copy of a repository clones it on demand, and that path did not carry the branch the repository tracks, so it fell back to the platform default. Git then failed for any repository whose default branch is not main, the repository went to an error state, and artifact generation failed with it. Because each worker keeps its own Git directory, this appeared only on deployments with more than one worker — the worker that added the repository already had a clone and worked normally.
The re-clone path now resolves the ref to check out from the repository object: default_branch for a CoreRepository, ref for a CoreReadOnlyRepository. The lookup runs only when the clone is missing, so an existing clone costs nothing extra. Merging an Infrahub branch also writes the merge back to a non-main default branch on the remote reliably, regardless of which task worker runs the merge. Setting default_branch when connecting a repository is now documented in Connect a repository.
Delete a repository and its related objects
Deleting a repository used to fail, because the objects it imports and generates — Transformations, checks, GraphQL queries, Generators, and the artifact definitions, artifacts, Generator instances and validators below them — are attached by mandatory relationships that Infrahub correctly refuses to break. The only way through was to delete the whole tree manually, leaf first.
Deleting a repository now removes the objects it owns along with it. Infrahub still refuses the deletion, naming the dependency, if one of those objects is required by something outside the repository, and makes no partial deletion. Validators attached to Proposed Changes, and the artifacts and Generator instances they produced, are removed too, which is the intended ownership relationship.
Minor changes
Performance
- When you request only the
idof a cardinality-one relationship's peer, Infrahub no longer builds the full peer node. - For very large merge and rebase diffs, Infrahub retrieves field summaries in pages bounded by
database.query_size_limit, reducing the risk of exhausting the Neo4j heap during validation.
Reliability
- Schema and graph migrations retry a transient database error, such as a deadlock, on a fresh transaction instead of failing the migration — the same retry behavior mutations and resolvers already had.
- A branch imported from a Git repository is created with Sync with Git enabled, so merging it no longer skips the Git side.
- Artifact generation fails with an error naming the Transformation when that Transformation returns no data, instead of storing the text
Noneas the artifact's content. - Repository tests in a Proposed Change run in order of cost: smoke tests, then unit tests, then integration tests, rather than being ordered by resource kind.
- A recompute task keeps the branch and related-node tags it started with, so it stays visible in the task list filtered by branch and in the task list of a node.
- Merging or rebasing a branch that deletes a node refreshes the derived values of the nodes that read it across a relationship, so computed attributes, display labels and human-friendly IDs no longer reference the deleted object.
- Creating a node no longer fails when a Jinja2 computed attribute formats a value allocated from a number pool.
- Infrahub marks a Jinja2 Transformation as updated only when its content has changed.
- Repository synchronization continues when a branch that was already merged in Infrahub still exists on the remote.
- Removing a relationship from the schema closes the underlying relationship data, so stale peers do not reappear if the same identifier is added again later.
- A flow waiting for an automatic retry is given more time before it can be marked as crashed.
- TLS certificate verification failures are reported as TLS errors instead of generic connection errors.
- The object edit form no longer fails with a
profileserror when an object is opened through a kind whose GraphQL type has noprofilesfield.
Telemetry
- The daily anonymous telemetry payload adds adoption and activity signals: active accounts and account groups, open non-system branches, node counts that respect branches and time, and activity from the previous full UTC day. Each field is collected independently, and reporting remains opt-out through
INFRAHUB_TELEMETRY_OPTOUT.
Documentation
- A new Tune performance page collects the settings worth revisiting as an instance grows, each with the symptom it addresses and what you give up in exchange.
- New pages cover developing changes from a Git repository, promoting a change between environments, and running several environments from a single repository.
- New pages cover creating objects and managing them from the CLI.
- The Academy section becomes Learn, split into Tutorials and Infrahub Labs.
- The Python Transformation dependency-tracking documentation is rewritten for the narrowed dependency closure.
Dependencies
- Infrahub uses
@urql/coreinstead of@apollo/clientfor frontend GraphQL requests, reducing the JavaScript bundle size without changing request behavior. - FastAPI moves to
0.141.1, and the OpenTelemetry instrumentation and exporter stack to the0.65b0/1.44.0line. - The container image is smaller: the build toolchain is excluded from the runtime image, and
numpyandpyarroware no longer installed by default.pyarrowremains available through theobject-transferextra forinfrahubctl object load.
Ecosystem updates
Recent releases across the Infrahub tooling during this cycle:
Infrahub Marketplace
The Infrahub Marketplace is the curated catalog of Infrahub schemas and collections for networks, data centers, and cloud infrastructure, and it is now publicly available at marketplace.infrahub.app.
- Start from a working model — collections bundle schemas that are tested to load together, so a new instance starts with a complete data model instead of an empty schema.
- Understand a schema before you load it — preview how a schema or collection models a use case, with versions and dependencies on every page, or download the YAML for closer inspection.
- Extend the model you already run — browse the catalog for the domain you are adding, such as Service Provider, Data Center Fabric, or IPAM, and adapt any schema to fit your model.
- Add a schema from the command line — add a schema or collection, together with the schemas it requires, directly to your Infrahub instance with the
infrahubctl marketplace getcommand in the Infrahub SDK. - Give AI assistants working examples — the schema AI skill now checks the Marketplace for a published schema before designing one from scratch.
Infrahub Collect
Infrahub Collect is a new CLI that gathers everything OpsMill support needs into a single archive with one command, on Docker Compose and Kubernetes alike.
- Read-only collection — it never stops, restarts, or scales a container or pod, so it is safe to run against a production instance, including one that is degraded. If a service is down, collection continues with the remaining services and records the failure.
- Logs and diagnostics from every service — service logs from every replica, including the previous container's logs for a pod that crashed and restarted, together with database, message-queue, cache, and task-manager diagnostics, configuration, schema, and container metrics.
- Works in restricted environments — the self-contained binary uses your existing Docker or
kubectlaccess and makes no network connection beyond the deployment itself. The bundle is a plain local file, so environments with restricted egress can transfer it through whatever channel their security policy allows. - Review before sharing — environment variables and configuration values whose key contains
password,secret,token, orkeyare masked before they are written, and a manifest records a success, failed, or skipped outcome for every collector, so you and support both know exactly what was captured. - Include a backup —
infrahub-collect create --include-backupadds a backup to the same run, so support can reproduce the issue locally.
Infrahub Collect documentation
Infrahub Backup 2.3.0
Infrahub Backup can now delete old backups automatically, restore the newest archive without being told which one it is, and update itself, so a scheduled backup pipeline runs without manual upkeep.
- Set a retention policy: keep backups newer than N days, the N most recent, or both. An archive survives if either rule claims it, and the newest archive is never deleted. The new
prunecommand previews the policy with--dry-runand applies it, or attach it tocreateso each scheduled backup cleans up after itself, on disk and in S3. - Restore the most recent backup with
restore --latestinstead of naming an archive. The Helm chart's restore CronJob uses the same selection, so a staging or demo environment can follow the newest backup another environment produces. - Update the CLI with
infrahub-backup update: it downloads the latest release, verifies its checksum, and replaces the binary in place, leaving the current binary untouched if anything fails. - Four data-integrity defects on the restore path are fixed.
Breaking changes
Read this section before upgrading.
Artifact workflows after target removal
Impact. If your workflow relies on an artifact remaining available after its target is removed from the artifact definition's target group, Infrahub deletes that artifact on the next full generation pass instead of retaining a stale copy.
What to do. Capture any artifact content another workflow still needs, or update that workflow so it no longer depends on the artifact after the target is removed.
Full generation runs after a merge, after an artifact definition update, or when the generate endpoint is called with no node filter. A run limited to specific members does not delete artifacts outside that scope.
infrahub git-agent
Impact. Scripts, deployment automation, or operational procedures that still call infrahub git-agent will no longer work after upgrading, because the deprecated command has been removed.
What to do. Replace any remaining calls with the task worker before upgrading.
Generated OpenAPI clients
Impact. Generated clients or application code that depend on the previous component schema names in openapi.json need to be updated. The response body from GET /api/schema is unchanged.
What to do. Update the renamed component types and regenerate affected clients:
APINodeSchema→NodeSchemaReadAPIGenericSchema→GenericSchemaReadAPIProfileSchema→ProfileSchemaReadAPITemplateSchema→TemplateSchemaRead
Upgrade notes
Runtime versions
If: You run Neo4j separately from the version shipped with Infrahub.
Then: Upgrade Neo4j to 2026.05.0 alongside Infrahub 1.11.
Notes: The container image includes Neo4j 2026.05.0, up from 2025.10.1, and Python 3.14, up from Python 3.13.
Python Transformations, Generators and watch
If: You declare watch on a python_transforms or generator_definitions entry in .infrahub.yml.
Then: Make sure the declaration names every file the source depends on beyond the file at its own file_path, including helper modules that sit in the same directory. Naming the containing directory covers them in one entry.
Notes: Infrahub detects one dependency automatically — the file at file_path. Earlier versions also treated every Git-tracked file in that file's directory as a dependency, which made unrelated sources in a shared directory regenerate each other's output; a declaration written against that behavior may now be incomplete. Without any watch declaration, Infrahub folds the repository's commit id into the fingerprint and recomputes after every commit, so an undeclared source is never stale. Jinja2 Transformations no longer need the empty watch declaration that 1.10 required. After upgrading, the first import of each Transformation recomputes its computed attributes once.
Deprecated GraphQL fields
If: A client, SDK call, or saved GraphQL query reads has_schema_changes on the Branch or InfrahubBranch type.
Then: Move it to schema_differs_from_default_branch, which reports the same value under a name that describes it.
Notes: has_schema_changes still returns the same value and is scheduled for removal in Infrahub 1.14.0.
Attribute-kind conversions
If: You convert an attribute to IPHost, IPNetwork, IPAddress or MacAddress.
Then: Normalize the existing values to the format the new kind requires before changing it.
Branches left behind by a failed deletion
If: A branch deletion failed on an earlier version and left the branch in DELETING, where it does not appear in the branch list.
Then: No action is required. infrahub upgrade finishes deleting those branches and their data.
Migration of an Infrahub instance
Before upgrading:
- Delete branches that are no longer needed, so migrations are not run against unused branches.
- Review the Breaking changes section above.
- Upgrade existing
infrahub-sdkinstallations tovTODO. - Back up the Infrahub instance and verify the restore procedure. See https://docs.infrahub.app/backup
Stop the existing instance:
docker compose downFor Docker Compose deployments, download the updated Compose file:
curl https://infrahub.opsmill.io -o docker-compose.ymlSet the version and start the environment:
export VERSION="1.11.0b2"
docker compose pull
docker compose up -dFor Kubernetes deployments, use the latest Helm chart supplied with this release.
Run the migrations:
docker compose exec infrahub-server infrahub upgradeRestart all Infrahub services:
docker compose restartFull changelog
Added
- Added a
selective_execution_after_mergesetting (envINFRAHUB_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, andCoreGeneratorDefinitionnow include an optional, branch-awarefingerprintattribute 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 a
schema_differs_from_default_branchfield to theBranchandInfrahubBranchGraphQL types. It reports whether a branch's schema differs from the default branch, replacing the misleadingly namedhas_schema_changesfield with a name that reflects what the value actually means. - 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
IPAddressattribute 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_24hsummary of the previous full UTC day. All changes are additive; each field is reported independently, so a single failing source returnsnullfor 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 mergeCLI 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 toOPEN, and removes the write protection. The command is operator-confirmed (--yesto skip) and idempotent. - Branch-status write rejections now include structured GraphQL error codes:
BRANCH_ALREADY_MERGED,BRANCH_NEEDS_REBASE, andMERGE_IN_PROGRESS(HTTP423). - Priority-aware API backpressure. The API accepts an optional
X-Priorityrequest header (high,medium, orlow; defaults tomedium). Under sustained overload the admission layer rejects lower-priority traffic first, returning429 Too Many Requestswith aRetry-Afterheader. Prometheus metric families are published on/metrics, and the layer can be turned off withINFRAHUB_API_BACKPRESSURE_ENABLED=false. - The frontend declares request priority on every API call via the
X-Priorityheader, sendinghighby default andlowfor 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
StandardNodeobjects. A singlePreferencemodel holds both layers: one row per user for that user's overrides, and a separate row for organization-wide defaults (date_format,timezone). TheInfrahubEffectivePreferencesGraphQL 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_preferencesglobal 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
```mermaidcode 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 the file at theirfile_path, so awatch: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, andMacAddress. (#10090) POST /api/schema/loadnow 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/schemaOpenAPI component schemas are renamed toNodeSchemaRead,GenericSchemaRead,ProfileSchemaRead, andTemplateSchemaRead. (#10095)- The exported node JSON Schema now forbids unknown fields and declares the read-only fields the load endpoint accepts and ignores, marked deprecated, so an editor validating against it reaches the same verdict as the load endpoint.
- 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 ongenerator_definitionsentries 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
idof a cardinality-one relationship's peer. (#10062) - Diff node field summaries are now retrieved in pages bounded by
database.query_size_limitinstead 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.
- Deleting a branch now runs as a series of bounded queries driven from Python instead of a single statement, so peak transaction memory is a function of the batch size rather than of the branch. (#9889)
- 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.
- Repository tests in a proposed change now run in order of cost — smoke, then unit, then integration — instead of being ordered by resource kind. (#10170)
- 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).
Deprecated
- Deprecated the
has_schema_changesfield on theBranchandInfrahubBranchGraphQL types. Useschema_differs_from_default_branchinstead.has_schema_changesstill returns the same value and is scheduled for removal in Infrahub 1.14.0.
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)
- A Python Transformation's auto-detected dependency closure is now the file named by its
file_pathalone, rather than every Git-tracked file in the directory containing it. Keeping several Transformations in one directory made every artifact rooted there regenerate on any single-file edit, including edits to files it never used. Helper modules are declared with thewatch.fileskey in.infrahub.yml, where naming the containing directory covers all of them at once. A source that has not declaredwatchstill folds the commit id into its fingerprint, so no safety net is lost. (#9644) - Python computed attributes now recompute when a
hfidthey read changes, and no longer recompute on every update to a kind whosedisplay_labelthey read. A query that only read thehfidof a node got no trigger at all, because the query analyzer did not recordhfidas a field. A query that read adisplay_labelgot a trigger with no field filter, so any update to that kind started a recompute. Both node properties are now reported under the name the schema and the change events use, so the trigger filters on them directly. - Python computed attributes no longer recompute on updates to nodes their query never reads. When a query followed a relationship whose peer is a generic, a trigger was created for every member kind of that generic, including kinds no field was read from. Those triggers carried no field filter, so any update to such a node started a recompute, and the values that recompute wrote could match the same triggers again and cascade. A kind the query reads no field from is now kept as a kind-level dependency, so adding or removing that kind still recomputes and changing a field on it does not. (#10189)
- Fixed the proposed change Data diff tab crashing with
RangeError: Invalid array lengthwhen the diff spans more than one page (300+ nodes). Each page also ships the ancestors of its own nodes as hierarchy context, so the same node could arrive several times; the duplicated entries corrupted the diff tree collection and crashed rendering. Each node is now kept once, preferring its changed entry when a page also delivered it as an unchanged placeholder. (#10155) - Fixed
CoreNumberPoolallocation stalling on a value that already exists on the target kind but was created outside the pool. When the target attribute is unique, the pool now skips values already present on the target and advances to the next free one, so pools can be declared over ranges that already contain data. Attributes that are not unique on their own, including per-relationship uniqueness constraints, are unaffected and remain fully allocatable. (#10179) - Node and group mutation events no longer overflow the task manager's related-resources maximum after it enlarges them. Events were truncated to exactly the configured maximum, and the events worker then appended its own run-context resources — flow run, task run, flow, deployment, work queue, work pool and one per flow-run tag — in place, which skips the client-side validation. The enlarged event was refused, which closes the event stream rather than dropping the single event. Events are now truncated to a budget that leaves room for that append. (#10241)
- Fixed group mutation events (
member_added/member_removed) being silently dropped when a single mutation changed a few hundred members or more. The event's related resources are now consolidated to one entry per member and per ancestor and capped at the task manager's maximum, so the event is always recorded and membership-driven automations keep firing regardless of how many members change at once. The full member list remains available in the event payload. (#10127) - Fixed schema migrations during a branch rebase using the destination branch's current schema as their baseline instead of the schema the branch was created from. Any schema element added on the destination branch after the branch forked already looked pre-existing to the migrations, so the work needed to bring branch data in line was skipped. (#10207)
- Fixed a branch rebase that fails while running its migrations restoring the wrong schema for the branch. The branch was left with the schema it was created from, silently dropping any schema change made on the branch itself, and the recorded schema hash was wrong as a result. The rollback now restores the schema the branch had immediately before the rebase started.
- Fixed deleting a large branch failing with a database out-of-memory error and leaving the branch and its data behind. Branches left behind by an earlier failure are now cleaned up on upgrade. (#9889)
- Schema and graph migrations now retry transient database errors, such as deadlocks, on a fresh transaction instead of failing the migration, matching the retry behavior already applied to mutations and resolvers.
- Fixed artifact generation failing for repositories whose default branch is not named
main. A worker with no local clone resolves the ref to check out from the repository object —default_branchfor aCoreRepository,reffor aCoreReadOnlyRepository— instead of falling back to the platform default. (#8749) - Merging an Infrahub branch now reliably writes the merge back to a repository's non-
maindefault branch on the remote, regardless of which task worker executes the merge. (#9568) - Fixed branches imported from a Git repository being created without the sync with Git flag, which caused merges to skip the Git side. (#10208)
- Fixed artifact generation storing the text
Nonewhen a Transformation returned no data; it now fails with an error naming the Transformation instead. (#5303) - Added an
orderedflag to attribute schemas. When set tofalseon aListor JSON-array attribute, reordering its elements is no longer reported as a conflict during merge and rebase. The built-inenum, dropdownchoices,used_by, andrestricted_namespacesattributes 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/loadnow 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_parentschema property. The options are now filtered to peers that share the same parent as the value picked for the referenced relationship in the same form, instead of listing every peer. (#10039) - Fixed the object creation form auto-selecting the first available object in the parent filter of a relationship to a hierarchical node. The parent filter now starts empty and is only pre-filled from an existing relationship value or parent context. (#9634)
- Fixed the frontend identifying the default branch by the literal name
mainrather than by theis_defaultflag 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)
- Fixed DateTime attributes on object detail pages dropping the time component of the user's preferred date format, or showing a relative phrase, while the list view rendered the full datetime. (#10172)
- Fixed future dates more than a week away rendering as a relative phrase, such as "in 4 years", instead of the user's preferred date format. (#10173)
- Fixed the date-format "Example" preview, and the source info tooltip, in the preferences forms rendering in the browser's timezone instead of the timezone preference being edited, which could show a time off by the zone offset or even the wrong calendar day. (#10175)
- A non-IANA timezone is now rejected when a user or global preference is written, so an unusable zone can no longer be persisted through the API or the SDK. An empty value normalizes to unset. (#10174)
- Fixed the Git repositories homepage widget linking to the generic
CoreGenericRepositorykind: repositories now open on their own kind, so the details page and edit form show all of their fields. - Fixed the object edit form failing with a GraphQL
profileserror when an object is opened through a kind whose GraphQL type has noprofilesfield, such asCoreGenericRepository. - Fixed the task status button in the header sending you to the tasks page on the default branch instead of the branch you were working on.
- Fixed a bulk recompute task dropping its branch tag and related-node tags when it recorded that it had values to write, which removed it from the task list filtered by branch and from the task list of a node. (#10237)
- 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_atandupdated_bymetadata, 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-agentcommand 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
numpyandpyarroware no longer installed by default (pyarrowremains available via the object-transfer extra forinfrahubctl object load). - Replaced the frontend GraphQL transport (
@apollo/client) with the lighter@urql/core, preserving all request behavior. (#10059) - Upgraded FastAPI to
0.141.1and the OpenTelemetry instrumentation and exporter stack to the0.65b0/1.44.0line. - 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
isRelationshipSchematype 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. - Reworked the Learn documentation: the Academy section becomes Learn, split into Tutorials and Infrahub Labs, and new pages cover performance tuning, developing changes from a Git repository, promoting changes between environments, running multiple environments from one repository, creating objects, and managing objects from the CLI.