Skip to content

Agent network - #684

Merged
braginini merged 19 commits into
mainfrom
agent-network
Jun 27, 2026
Merged

Agent network#684
braginini merged 19 commits into
mainfrom
agent-network

Conversation

@braginini

@braginini braginini commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Issue ticket number and link

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

netbirdio/docs#813

E2E tests

Optional: override the image tags used by the Playwright e2e workflow.
Defaults to main when omitted.

management-cloud-tag: main
reverse-proxy-tag: main

Summary by CodeRabbit

  • New Features
    • Added Agent Network dashboard (Providers, Policies, Usage & Logs, Global Limits, Log Collection) behind feature flags, including sidebar navigation and an Agent Network onboarding flow.
    • Added Agent Network access log filters, expanded access-log details, and “Agent Policy” graph overlay in Control Center.
  • Bug Fixes
    • Improved peers routing by replacing legacy UI with ?kind= redirects and adding a dedicated blocked view.
    • Improved search matching (whitespace-insensitive fuzzy filtering) and date preset labeling; fixed HubSpot portal ID selection.
    • Strengthened instance setup with confirm-password validation.
  • Chores
    • Added a build script to package the dashboard as a Linux/amd64 Docker image tarball; updated Docker build context exclusions and installer link generation.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f4b87be3-8aa3-4b3d-ae29-666c30320df3

📥 Commits

Reviewing files that changed from the base of the PR and between 2da45b3 and 02decf9.

📒 Files selected for processing (1)
  • src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx

📝 Walkthrough

Walkthrough

Adds Agent Network feature flags, shared provider and policy context, new dashboard pages for providers, policies, usage, onboarding, and control-center overlays, plus peers/navigation updates and Docker packaging.

Changes

Agent Network rollout

Layer / File(s) Summary
Feature flags and packaging
config.json, src/utils/config.ts, src/utils/netbird.ts, docker/init_react_envs.sh, src/modules/setup-netbird-modal/*, docker/.dockerignore, build.sh
Agent Network config flags are loaded from JSON and env, runtime helpers expose mode and download URLs, setup download links use the shared URL helper, and the Docker export script packages the prebuilt app.
Shared UI primitives
src/assets/icons/AgentNetworkIcon.tsx, src/components/DatePickerWithRange.tsx, src/components/select/SelectDropdown.tsx, src/components/table/DataTable.tsx
A new Agent Network icon, preset date labels, grouped select rendering, and whitespace-insensitive table search are added.
Shared agent-network domain
src/modules/agent-network/data/mockData.ts, src/modules/agent-network/useProviderCatalog.ts, src/modules/agent-network/AIProviderLogo.tsx, src/modules/agent-network/AIProvidersProvider.tsx
Shared provider, policy, guardrail, budget-rule, and access-log types are defined with the provider catalog hook, logo, and provider context.
Provider management and pages
src/app/(dashboard)/agent-network/providers/page.tsx, src/modules/agent-network/AIProviderModal.tsx, src/modules/agent-network/AgentConnectModal.tsx, src/modules/agent-network/table/AgentProviderActionCell.tsx, src/modules/agent-network/table/AgentProvidersTable.tsx
Provider connection instructions, provider editing, provider tables, row actions, and the providers page are rendered from the shared provider context.
Policies, guardrails, budgets, and configuration
src/app/(dashboard)/agent-network/policies/page.tsx, src/app/(dashboard)/agent-network/configuration/page.tsx, src/modules/agent-network/AgentGuardrailChecksCell.tsx, src/modules/agent-network/AgentGuardrailBrowseModal.tsx, src/modules/agent-network/AgentGuardrailModal.tsx, src/modules/agent-network/AgentPolicyLimitsTab.tsx, src/modules/agent-network/AgentPolicyGuardrailsTab.tsx, src/modules/agent-network/AgentPolicyModal.tsx, src/modules/agent-network/AgentPoliciesTable.tsx, src/modules/agent-network/AgentAccountControlsCard.tsx, src/modules/agent-network/AgentBudgetRuleModal.tsx, src/modules/agent-network/AgentBudgetRulesTable.tsx
Policy, guardrail, budget-rule, and configuration pages render the policy table, editors, global limits, account settings, and log-collection controls.
Access-log analytics
src/app/(dashboard)/agent-network/usage/page.tsx, src/modules/agent-network/agentAccessLogApi.ts, src/modules/agent-network/AccessLogFilters.tsx, src/modules/agent-network/AgentOverviewPanel.tsx, src/modules/agent-network/AgentAccessLogExpandedRow.tsx, src/modules/agent-network/AgentAccessLogTable.tsx
The usage page composes access-log query helpers, shared filters, overview charts, detail rows, and the access-log table.
Control-center overlay
src/modules/control-center/nodes/AgentPolicyNode.tsx, src/modules/control-center/nodes/ProviderNode.tsx, src/modules/control-center/utils/layouts.ts, src/modules/control-center/utils/nodes.ts, src/app/(dashboard)/control-center/page.tsx, src/modules/control-center/FlowSelector.tsx
New graph nodes and layout rules let Control Center overlay agent-network providers and policies, and node clicks open the policy modal.
Agent Network onboarding
src/app/(dashboard)/agent-network/layout.tsx, src/modules/onboarding/OnboardingProvider.tsx, src/modules/onboarding/agent-network/*
Agent Network-only onboarding renders the signup, provider, policy, device, configure, and completion steps and runs first-run setup behind the route gate.
Peers navigation and redirects
src/layouts/Navigation.tsx, src/app/(dashboard)/peers/page.tsx, src/modules/peers/PeersTable.tsx, src/components/ui/AddPeerDropdown.tsx, src/app/(dashboard)/peers/users/page.tsx, src/app/(dashboard)/peers/servers/page.tsx
The peers page, peers table, add-peer dropdown, sidebar navigation, and legacy peer routes are updated around the consolidated peers flow.

Access Control cleanup

Layer / File(s) Summary
Access-control copy and actions
src/app/(dashboard)/access-control/page.tsx, src/modules/access-control/table/AccessControlTable.tsx
The access-control page copy changes and FirewallGPTButton render paths are removed from the access-control table.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • netbirdio/dashboard#514 — Introduces onboarding modules extended by the Agent Network-only onboarding flow and first-run setup in this PR.
  • netbirdio/dashboard#525 — Modifies src/app/(dashboard)/control-center/page.tsx, which this PR extends with agent-network graph overlays and node handling.
  • netbirdio/dashboard#649 — Changes the peers routes and PeersTable flow that this PR further consolidates.

Suggested reviewers

  • mlsmaycon

Poem

🐇 Hop, hop—new routes align,
agents, logs, and graphs all shine.
My carrot cache is neat and fast,
with tidy builds that truly last.
Hoppy deploy day! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.21% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is accurate but too broad to convey the main change set. Use a specific title like "Add agent network dashboard and onboarding flow" to describe the primary change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description matches the template structure and includes docs and E2E tag fields.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent-network

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx

Oops! Something went wrong! :(

ESLint: 9.39.3

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc.json
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/modules/instance-setup/InstanceSetupWizard.tsx (1)

137-152: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clear the confirm-password error when either password field changes.

Once validateForm() sets "Passwords do not match", updating password to match no longer clears that error because handleInputChange only resets the field being edited, and confirmPasswordError gives the stale errors.confirmPassword value priority over the current form state. The UI can therefore keep showing a mismatch after the two values already match.

Suggested fix
   const handleInputChange =
     (field: keyof FormData) => (e: React.ChangeEvent<HTMLInputElement>) => {
-      setFormData((prev) => ({ ...prev, [field]: e.target.value }));
-      if (errors[field]) {
-        setErrors((prev) => ({ ...prev, [field]: undefined }));
-      }
+      const value = e.target.value;
+      setFormData((prev) => ({ ...prev, [field]: value }));
+      setErrors((prev) => ({
+        ...prev,
+        [field]: undefined,
+        ...(field === "password" || field === "confirmPassword"
+          ? { confirmPassword: undefined }
+          : {}),
+      }));
     };

Also applies to: 256-265

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/instance-setup/InstanceSetupWizard.tsx` around lines 137 - 152,
Clear the confirm-password mismatch as soon as either password field changes. In
`InstanceSetupWizard`, update the `handleInputChange`/password handling so
changing `password` also re-evaluates and clears `confirmPassword` mismatch
state when the two values match, not just when editing `confirmPassword`. Also
adjust `confirmPasswordError` so current form state takes precedence over a
stale `errors.confirmPassword` value, ensuring the mismatch message disappears
once `password` and `confirmPassword` are equal.
🟡 Minor comments (7)
src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx-98-100 (1)

98-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clone referralSourceOptions before shuffling.

sort() mutates the imported array in place, so this form can change option order for other onboarding consumers sharing the same module value.

Proposed fix
   const randomizedOptions = useMemo(
-    () => referralSourceOptions.sort(() => Math.random() - 0.5),
+    () => [...referralSourceOptions].sort(() => Math.random() - 0.5),
     [],
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx` around lines
98 - 100, The randomized option generation in AgentNetworkSignupForm mutates the
shared referralSourceOptions array in place, which can affect other consumers of
the module. Update the useMemo logic that builds randomizedOptions to first
clone referralSourceOptions before applying the shuffle/sort, so the imported
source array remains unchanged for other onboarding flows.
src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx-226-249 (1)

226-249: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the hidden “Other” input out of the tab order.

When other is false, the input is only visually collapsed, so keyboard users can still tab into an invisible control.

Proposed fix
                 <Checkbox
                   checked={other}
-                  onCheckedChange={() => {
-                    setOther(!other);
-                    inputRef.current?.focus();
+                  onCheckedChange={(checked) => {
+                    const next = checked === true;
+                    setOther(next);
+                    if (next) {
+                      window.requestAnimationFrame(() => inputRef.current?.focus());
+                    }
                   }}
                 />
@@
               <Input
                 ref={inputRef}
+                disabled={!other}
+                aria-hidden={!other}
+                tabIndex={other ? undefined : -1}
                 placeholder={"e.g. Internal RAG service, MCP tools"}
                 value={otherUseCase}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx` around lines
226 - 249, The hidden “Other” input in AgentNetworkSignupForm should be removed
from the keyboard tab order when other is false. Update the Input rendering so
that the collapsed state also makes it non-focusable and inaccessible, using the
existing other, inputRef, and Input controls in AgentNetworkSignupForm rather
than only changing the wrapper classes. Ensure keyboard users can only tab to
the field when it is actually visible.
src/modules/onboarding/agent-network/OnboardingAgentEnd.tsx-29-33 (1)

29-33: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

The CTA label does not match the destination.

onFinish currently routes to Control Center in src/modules/onboarding/OnboardingProvider.tsx, not Access Logs, so this button text sets the wrong expectation. Either relabel it to match Control Center or change the completion handler to navigate to Usage & Logs.
Based on learnings from the provided cross-file snippet: src/modules/onboarding/OnboardingProvider.tsx:127-143 pushes /control-center or /control-center?tab=networks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/onboarding/agent-network/OnboardingAgentEnd.tsx` around lines 29
- 33, The button label in OnboardingAgentEnd does not match where onFinish
actually navigates. Update the CTA text in OnboardingAgentEnd to reflect the
Control Center destination, or alternatively change the onFinish handler in
OnboardingProvider so it routes to Usage & Logs instead; keep the label and
navigation consistent with the behavior implemented in onFinish.
src/modules/setup-netbird-modal/MacOSTab.tsx-63-67 (1)

63-67: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Add rel="noopener noreferrer" to the external installer link.

Line 66 opens a third-party URL in a new tab without rel, which leaves window.opener available. WindowsTab already closes that gap on the analogous link.

🔒 Proposed fix
               <Link
                 href={pkgsDownloadUrl("macos/universal")}
                 passHref
                 target={"_blank"}
+                rel="noopener noreferrer"
               >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/setup-netbird-modal/MacOSTab.tsx` around lines 63 - 67, The
external installer link in MacOSTab opens a new tab without a rel attribute,
leaving window.opener exposed. Update the Link that uses
pkgsDownloadUrl("macos/universal") to include rel="noopener noreferrer",
matching the safer pattern already used in WindowsTab for the analogous external
download link.
build.sh-42-47 (1)

42-47: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve any pre-existing root .dockerignore.

Lines 45-47 always delete .dockerignore on exit. If the repo already has one, or a developer keeps a local override, this script removes it after the build. Back up the original file and restore it in cleanup() instead of unconditionally deleting it.

Suggested fix
-# The .dockerignore lives under docker/, but Docker reads it from the build
-# context root. Stage it for the duration of the build so node_modules/.next
-# don't get shipped into the build context.
-cleanup() { rm -f .dockerignore; }
-trap cleanup EXIT
-cp docker/.dockerignore .dockerignore
+# The .dockerignore lives under docker/, but Docker reads it from the build
+# context root. Stage it for the duration of the build so node_modules/.next
+# don't get shipped into the build context.
+ORIGINAL_DOCKERIGNORE=""
+if [[ -f .dockerignore ]]; then
+  ORIGINAL_DOCKERIGNORE="$(mktemp)"
+  cp .dockerignore "${ORIGINAL_DOCKERIGNORE}"
+fi
+
+cleanup() {
+  if [[ -n "${ORIGINAL_DOCKERIGNORE}" ]]; then
+    mv "${ORIGINAL_DOCKERIGNORE}" .dockerignore
+  else
+    rm -f .dockerignore
+  fi
+}
+trap cleanup EXIT
+cp docker/.dockerignore .dockerignore
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.sh` around lines 42 - 47, The build.sh staging logic currently
overwrites and then always deletes the root .dockerignore, which can remove an
existing repo file or a developer’s local override. Update the cleanup() flow to
preserve any pre-existing .dockerignore by backing it up before the cp
docker/.dockerignore .dockerignore step and restoring that original file in
cleanup() instead of unconditionally removing it. Use the existing cleanup trap
and the .dockerignore staging block as the place to implement the backup/restore
behavior.
src/app/(dashboard)/agent-network/configuration/page.tsx-30-36 (1)

30-36: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate the tab query param before syncing it into state.

Line 32 and Line 35 accept any tab value from the URL. ?tab=foo leaves VerticalTabs with no matching trigger/content, so the page renders an empty detail pane instead of falling back to a valid tab.

Suggested fix
 const TAB_BUDGET_SETTINGS = "budget-settings";
 const TAB_LOG_SETTINGS = "log-settings";
+const VALID_TABS = new Set([TAB_BUDGET_SETTINGS, TAB_LOG_SETTINGS]);
+
+const normalizeTab = (value: string | null) =>
+  value && VALID_TABS.has(value) ? value : TAB_BUDGET_SETTINGS;

 export default function AgentNetworkConfigurationPage() {
   const { permission } = usePermissions();
   const queryParams = useSearchParams();
   const queryTab = queryParams.get("tab");
-  const [tab, setTab] = useState(queryTab ?? TAB_BUDGET_SETTINGS);
+  const [tab, setTab] = useState(normalizeTab(queryTab));

   useEffect(() => {
-    if (queryTab) setTab(queryTab);
+    setTab(normalizeTab(queryTab));
   }, [queryTab]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/agent-network/configuration/page.tsx around lines 30 -
36, The query param handling in the configuration page is syncing any raw `tab`
value from `useSearchParams` into state, which can leave `VerticalTabs` with no
matching tab. Update the `queryTab`/`setTab` flow in `page.tsx` to validate
against the allowed tab values before initializing or updating state, and fall
back to `TAB_BUDGET_SETTINGS` when the URL value is missing or invalid. Use the
existing `tab`, `setTab`, `queryTab`, and `TAB_BUDGET_SETTINGS` symbols to keep
the tab state consistent.
src/app/(dashboard)/control-center/page.tsx-612-620 (1)

612-620: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Deduplicate peer overlay edges by sourceNodeId.

applyPeerView() calls this helper once per peer group at Line 1147, but all of those calls use the same select-peer-node source. With the current agent-src-${groupId}-${policy.id} key, one agent policy matched through two peer groups produces duplicate overlapping edges from the same source to the same target.

Suggested fix
-      const sourceEdgeId = `agent-src-${groupId}-${policy.id}`;
+      const sourceEdgeId = `agent-src-${sourceNodeId}-${policy.id}`;
       if (!allEdges.some((e) => e.id === sourceEdgeId)) {
         allEdges.push({
           id: sourceEdgeId,
           source: sourceNodeId,
           target: policyNodeId,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/control-center/page.tsx around lines 612 - 620, The peer
overlay edge key in applyPeerView()/the helper that builds agent-src edges is
too specific to groupId, which allows duplicate overlapping edges when the same
sourceNodeId is processed through multiple peer groups. Change the deduplication
logic to key off sourceNodeId and policy.id (or otherwise ensure only one edge
per source-target pair is created), and keep the existing source, target, and
data fields unchanged when pushing into allEdges.
🧹 Nitpick comments (2)
src/modules/agent-network/data/mockData.ts (1)

5-21: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Avoid freezing the provider-id contract in the dashboard.

The comment says the catalog is server-owned, but this union still hard-codes the current ids locally. AIProvidersProvider.fromAPI() already has to cast provider_id back to AIProviderId to make it fit, so any new catalog entry can arrive from management while the dashboard types silently drift. Prefer a plain backend id type (string) for persisted provider ids and only narrow where the UI truly needs special-case handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/agent-network/data/mockData.ts` around lines 5 - 21, The
provider-id contract is still being frozen locally by the AIProviderId union in
mockData, which can drift from the server-owned catalog. Update the
persisted/provider model used by AIProvidersProvider.fromAPI() and related data
shapes to store provider_id as a plain backend string, then only narrow to
specific AIProviderId values at UI branches that need special-case handling.
Remove the need for the cast in fromAPI() by keeping the catalog-facing type
flexible and reserving the union for client-side checks only.
src/app/(dashboard)/peers/page.tsx (1)

70-76: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Build a user lookup before joining peers.

users.find(...) runs once per peer, so large accounts pay an avoidable peers × users cost during render. A Map keeps the join linear.

⚡ Proposed refactor
   const peersWithUser = useMemo(() => {
     if (!peers || !users) return undefined;
+    const usersById = new Map(users.map((user) => [user.id, user]));
     return peers.map((peer) => ({
       ...peer,
-      user: users.find((u) => u.id === peer.user_id),
+      user: peer.user_id ? usersById.get(peer.user_id) : undefined,
       force_approved: peer.id ? isBypassed(peer.id) : false,
     }));
   }, [peers, users, isBypassed]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/peers/page.tsx around lines 70 - 76, The peer-to-user
join in `peersWithUser` is doing a repeated `users.find(...)` for every peer,
which makes the render unnecessarily quadratic for large lists. Build a user
lookup map once inside the `useMemo` block in `page.tsx` (near `peersWithUser`),
keyed by user id, then use that map when mapping peers so each peer resolves its
`user` in constant time while keeping the existing `force_approved` logic
intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(dashboard)/agent-network/providers/page.tsx:
- Around line 169-206: The access check is applied too late because
`RestrictedAccess` only wraps `PageBody`, while `AIProvidersProvider` and
`EndpointHeader` still mount for users without `permission?.services?.read`.
Move the gate in `page.tsx` so the entire providers surface is protected before
rendering `AIProvidersProvider`, `EndpointHeader`, or any content that can fetch
agent-network state, and keep `PageBody` inside the guarded branch.

In `@src/app/`(dashboard)/agent-network/usage/page.tsx:
- Around line 53-56: The tab sync effect in the usage page only updates state
when `queryTab` is present and valid, so `tab` never resets when `?tab=` is
removed. Update the `useEffect` tied to `queryTab` so it also handles the
empty/absent case by restoring the default tab state, while still validating
values against `VALID_TABS`. Use the `tab`, `setTab`, `queryTab`, and
`VALID_TABS` logic in this component to keep deep links and back-forward
navigation in sync.

In `@src/layouts/Navigation.tsx`:
- Around line 180-229: The Agent Network sidebar items are only gated by the
feature flag, but the pages themselves require permissions, so restricted users
can still see and click entries they cannot access. Update Navigation.tsx so the
child SidebarItem entries under the Agent Network section use the same
permission checks as their corresponding pages (for example, the Providers item
should match the page’s services.read guard), and compute the parent section’s
visible state from whichever child items are actually permitted. Keep the
changes anchored around the Agent Network SidebarItem block and the
isAgentNetworkEnabled/isAgentNetworkOnly logic.

In `@src/modules/agent-network/AgentAccessLogTable.tsx`:
- Around line 145-149: Guard the provider lookup memo in AgentAccessLogTable
before iterating because providers can be null on the initial render. Update
providerByConfigId to handle a missing providers value safely, using the same
nullable pattern already used later in the component, so the map is only built
when providers is available and the access-log table does not crash.

In `@src/modules/agent-network/AgentAccountControlsCard.tsx`:
- Around line 61-70: The save flow in onSave should not clear the dirty state
when updateAgentNetworkSettings fails, since that helper handles errors
internally and may still allow execution to continue. Update the onSave logic in
AgentAccountControlsCard so updateRef(...) only runs after a confirmed
successful save, or make updateAgentNetworkSettings return a success/failure
signal that onSave can check before resetting the dirty state.

In `@src/modules/agent-network/AgentBudgetRuleModal.tsx`:
- Around line 115-148: `handleSubmit` in `AgentBudgetRuleModal` closes the modal
unconditionally, even when saving the budget rule fails; update it so
`onSuccess()` only runs after a confirmed successful `addBudgetRule` or
`updateBudgetRule` call. Make sure the submit flow checks the returned result
from `addBudgetRule` and handles errors from `updateBudgetRule` in
`AIProvidersProvider` instead of swallowing them, so failed persistence does not
dismiss the modal and lose edits.

In `@src/modules/agent-network/AgentGuardrailChecksCell.tsx`:
- Around line 49-55: The tooltip in AgentGuardrailChecksCell always shows “PII
redaction” whenever prompt capture is enabled, even when
prompt_capture.redactPii is false. Update the rendering around the prompt
capture tooltip in AgentGuardrailChecksCell to conditionally describe the actual
state using the guardrail data coming from AIProvidersProvider, so the label
only mentions PII redaction when redactPii is enabled and otherwise reflects
plain prompt capture.

In `@src/modules/agent-network/AgentGuardrailModal.tsx`:
- Around line 69-84: The submit flow in AgentGuardrailModal should not close the
modal after a failed save, since addGuardrail can return undefined and
updateGuardrail may also fail. Update handleSubmit so it only calls onSuccess
and onOpenChange(false) when a saved guardrail is actually returned, and keep
the modal open otherwise so the user can retry with their draft preserved.

In `@src/modules/agent-network/AgentOverviewPanel.tsx`:
- Around line 389-409: Normalize `period_start` to the same `YYYY-MM-DD` day key
before storing and looking up entries in `AgentOverviewPanel`’s bucket map so
the gap-filling loop matches API values even when they include timestamps.
Update the `map.set(...)` and `map.get(...)` usage in the date-fill logic to use
a normalized key consistently, and remove or replace the hard `i < 366` cap in
that same loop so valid ranges longer than a year are not truncated.

In `@src/modules/agent-network/AgentPolicyModal.tsx`:
- Around line 166-209: handleSubmit currently always calls onSuccess, so the
modal closes even when addPolicy or updatePolicy fails. Update
AgentPolicyModal’s handleSubmit flow to only invoke onSuccess after a successful
save, and keep the modal open when addPolicy returns undefined or updatePolicy
fails. Use the addPolicy/updatePolicy calls from useAIProviders and ensure any
failure path short-circuits before onSuccess so in-progress edits are preserved.

In `@src/modules/agent-network/AIProviderModal.tsx`:
- Around line 374-384: Catalog-backed providers are still allowing a blank model
row to be added and submitted, so update the model flow in AIProviderModal to
prevent incomplete entries from persisting. Fix this by stopping addModel from
appending a row with an empty id once all catalog presets are used, and also
harden handleSubmit to filter out any incomplete model rows before calling
addProvider so the payload never includes blank models. Use the existing
addModel, handleSubmit, and the provider submit path around addProvider to
locate the changes.

In `@src/modules/agent-network/AIProvidersProvider.tsx`:
- Around line 200-206: The settings mapper in settingsFromAPI is using the wrong
fallback for attributionMode. Update the APIAgentNetworkSettings to
AgentNetworkSettings conversion so that missing attribution_mode uses the
backend management default documented by the shared domain, not "priority". Keep
the change localized to settingsFromAPI in AIProvidersProvider so older rows
without attribution_mode render the correct effective mode in the dashboard.

In `@src/modules/agent-network/useProviderCatalog.ts`:
- Around line 77-80: The provider catalog request in useProviderCatalog is still
firing even when agent network is disabled, which can cause unnecessary
404s/errors in inert deployments. Update this hook to check
isAgentNetworkEnabled() before calling useFetchApi for
/agent-network/catalog/providers, and return an empty/inactive state when the
flag is false so AIProviderLogo and provider cells do not trigger the request
outside agent-network environments.

In `@src/modules/control-center/FlowSelector.tsx`:
- Around line 52-63: The Networks tab is only being hidden in FlowSelector, but
control-center page initialization still allows tab=networks to resolve to
FlowView.NETWORKS. Update the initial view logic in the control-center page
component so it clamps or remaps the selected tab when isAgentNetworkOnly() is
true, preventing old bookmarks and deep links from opening the hidden Networks
flow. Keep the trigger removal in FlowSelector and apply the same guard where
the tab query is translated into FlowView.

In `@src/modules/onboarding/agent-network/AgentNetworkOnboarding.tsx`:
- Line 47: The signup submission flow in AgentNetworkOnboarding is treating
onSignupSubmit as fire-and-forget even though OnboardingProvider persists signup
state asynchronously, so the step can advance too early. Update the
onSignupSubmit prop typing and the submit handling in
AgentNetworkOnboarding/related call sites to await the async result before
continuing the onboarding flow, ensuring signup_form_pending is persisted before
moving past the signup step.

In `@src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx`:
- Around line 103-128: The signup submit flow can currently fire before identity
data is ready, causing `submitForm` in `AgentNetworkSignupForm` to call
`onSubmit([])` and clear pending state with no payload. Update `canSubmit`
and/or `submitForm` so submission is blocked until `loggedInUser` or `user` is
available, and only build/call `onSubmit` with populated `HubspotFormField[]`
once email and form fields can be assembled. Use the existing `canSubmit`,
`submitForm`, and identity checks to keep the parent from receiving an empty
payload.

In `@src/modules/onboarding/agent-network/OnboardingAgentDevice.tsx`:
- Around line 11-14: The onboarding device-ready state is too broad because
OnboardingAgentDevice receives a deviceConnected signal that is currently driven
by account-wide peer count in AgentNetworkOnboarding. Update the readiness flow
so AgentNetworkOnboarding only marks the step complete when the current
machine/device is actually reachable, and adjust OnboardingAgentDevice to use
that device-specific signal rather than any peer from /peers. Keep the
Continue/modal behavior tied to the same device-specific check so existing peers
do not auto-complete the step.

In `@src/modules/onboarding/agent-network/useAgentNetworkFirstRunSetup.ts`:
- Around line 68-75: The deletion logic in useAgentNetworkFirstRunSetup
currently identifies the policy only by DEFAULT_POLICY_NAME, which can remove an
operator-customized policy instead of the seeded allow-all default. Update the
policy selection in the onboarding setup flow to use a stable server-provided
marker or a strict shape check via isSeededDefaultAccessPolicy before calling
policyRequest.del, and only trigger mutate("/policies") after confirming the
matched policy is the seeded default.

In `@src/modules/peers/PeersTable.tsx`:
- Around line 703-725: Reset the table selection when switching peer kind in
PeersTable so hidden rows do not remain selected after filtering changes. Update
the ButtonGroup.Button onClick handlers for the "users" and "servers" toggles to
clear selectedRows alongside setKind, keeping PeerMultiSelect and any bulk
actions aligned with the currently visible peers.
- Around line 292-299: The PeersTable state initialization only uses defaultKind
once, so the toolbar selection can get out of sync when navigating between
subset routes. Update the PeersTable component to keep kind synchronized with
defaultKind (the value derived from the ?kind= query) and reset selectedRows
whenever the subset changes so stale hidden peers do not remain selected. Use
the existing PeersTable, kind/setKind, defaultKind, and selectedRows state to
locate and adjust the sync logic.

---

Outside diff comments:
In `@src/modules/instance-setup/InstanceSetupWizard.tsx`:
- Around line 137-152: Clear the confirm-password mismatch as soon as either
password field changes. In `InstanceSetupWizard`, update the
`handleInputChange`/password handling so changing `password` also re-evaluates
and clears `confirmPassword` mismatch state when the two values match, not just
when editing `confirmPassword`. Also adjust `confirmPasswordError` so current
form state takes precedence over a stale `errors.confirmPassword` value,
ensuring the mismatch message disappears once `password` and `confirmPassword`
are equal.

---

Minor comments:
In `@build.sh`:
- Around line 42-47: The build.sh staging logic currently overwrites and then
always deletes the root .dockerignore, which can remove an existing repo file or
a developer’s local override. Update the cleanup() flow to preserve any
pre-existing .dockerignore by backing it up before the cp docker/.dockerignore
.dockerignore step and restoring that original file in cleanup() instead of
unconditionally removing it. Use the existing cleanup trap and the .dockerignore
staging block as the place to implement the backup/restore behavior.

In `@src/app/`(dashboard)/agent-network/configuration/page.tsx:
- Around line 30-36: The query param handling in the configuration page is
syncing any raw `tab` value from `useSearchParams` into state, which can leave
`VerticalTabs` with no matching tab. Update the `queryTab`/`setTab` flow in
`page.tsx` to validate against the allowed tab values before initializing or
updating state, and fall back to `TAB_BUDGET_SETTINGS` when the URL value is
missing or invalid. Use the existing `tab`, `setTab`, `queryTab`, and
`TAB_BUDGET_SETTINGS` symbols to keep the tab state consistent.

In `@src/app/`(dashboard)/control-center/page.tsx:
- Around line 612-620: The peer overlay edge key in applyPeerView()/the helper
that builds agent-src edges is too specific to groupId, which allows duplicate
overlapping edges when the same sourceNodeId is processed through multiple peer
groups. Change the deduplication logic to key off sourceNodeId and policy.id (or
otherwise ensure only one edge per source-target pair is created), and keep the
existing source, target, and data fields unchanged when pushing into allEdges.

In `@src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx`:
- Around line 98-100: The randomized option generation in AgentNetworkSignupForm
mutates the shared referralSourceOptions array in place, which can affect other
consumers of the module. Update the useMemo logic that builds randomizedOptions
to first clone referralSourceOptions before applying the shuffle/sort, so the
imported source array remains unchanged for other onboarding flows.
- Around line 226-249: The hidden “Other” input in AgentNetworkSignupForm should
be removed from the keyboard tab order when other is false. Update the Input
rendering so that the collapsed state also makes it non-focusable and
inaccessible, using the existing other, inputRef, and Input controls in
AgentNetworkSignupForm rather than only changing the wrapper classes. Ensure
keyboard users can only tab to the field when it is actually visible.

In `@src/modules/onboarding/agent-network/OnboardingAgentEnd.tsx`:
- Around line 29-33: The button label in OnboardingAgentEnd does not match where
onFinish actually navigates. Update the CTA text in OnboardingAgentEnd to
reflect the Control Center destination, or alternatively change the onFinish
handler in OnboardingProvider so it routes to Usage & Logs instead; keep the
label and navigation consistent with the behavior implemented in onFinish.

In `@src/modules/setup-netbird-modal/MacOSTab.tsx`:
- Around line 63-67: The external installer link in MacOSTab opens a new tab
without a rel attribute, leaving window.opener exposed. Update the Link that
uses pkgsDownloadUrl("macos/universal") to include rel="noopener noreferrer",
matching the safer pattern already used in WindowsTab for the analogous external
download link.

---

Nitpick comments:
In `@src/app/`(dashboard)/peers/page.tsx:
- Around line 70-76: The peer-to-user join in `peersWithUser` is doing a
repeated `users.find(...)` for every peer, which makes the render unnecessarily
quadratic for large lists. Build a user lookup map once inside the `useMemo`
block in `page.tsx` (near `peersWithUser`), keyed by user id, then use that map
when mapping peers so each peer resolves its `user` in constant time while
keeping the existing `force_approved` logic intact.

In `@src/modules/agent-network/data/mockData.ts`:
- Around line 5-21: The provider-id contract is still being frozen locally by
the AIProviderId union in mockData, which can drift from the server-owned
catalog. Update the persisted/provider model used by
AIProvidersProvider.fromAPI() and related data shapes to store provider_id as a
plain backend string, then only narrow to specific AIProviderId values at UI
branches that need special-case handling. Remove the need for the cast in
fromAPI() by keeping the catalog-facing type flexible and reserving the union
for client-side checks only.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86508138-bd9f-47df-9129-e1256860e74c

📥 Commits

Reviewing files that changed from the base of the PR and between c325c17 and c5a0fc5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (66)
  • build.sh
  • config.json
  • docker/.dockerignore
  • docker/init_react_envs.sh
  • src/app/(dashboard)/access-control/page.tsx
  • src/app/(dashboard)/agent-network/configuration/page.tsx
  • src/app/(dashboard)/agent-network/layout.tsx
  • src/app/(dashboard)/agent-network/policies/page.tsx
  • src/app/(dashboard)/agent-network/providers/page.tsx
  • src/app/(dashboard)/agent-network/usage/page.tsx
  • src/app/(dashboard)/control-center/page.tsx
  • src/app/(dashboard)/peers/page.tsx
  • src/app/(dashboard)/peers/servers/page.tsx
  • src/app/(dashboard)/peers/users/page.tsx
  • src/assets/icons/AgentNetworkIcon.tsx
  • src/cloud/analytics/Hubspot.tsx
  • src/components/DatePickerWithRange.tsx
  • src/components/select/SelectDropdown.tsx
  • src/components/table/DataTable.tsx
  • src/components/ui/AddPeerDropdown.tsx
  • src/layouts/Navigation.tsx
  • src/modules/access-control/table/AccessControlTable.tsx
  • src/modules/agent-network/AIProviderLogo.tsx
  • src/modules/agent-network/AIProviderModal.tsx
  • src/modules/agent-network/AIProvidersProvider.tsx
  • src/modules/agent-network/AccessLogFilters.tsx
  • src/modules/agent-network/AgentAccessLogExpandedRow.tsx
  • src/modules/agent-network/AgentAccessLogTable.tsx
  • src/modules/agent-network/AgentAccountControlsCard.tsx
  • src/modules/agent-network/AgentBudgetRuleModal.tsx
  • src/modules/agent-network/AgentBudgetRulesTable.tsx
  • src/modules/agent-network/AgentConnectModal.tsx
  • src/modules/agent-network/AgentGuardrailBrowseModal.tsx
  • src/modules/agent-network/AgentGuardrailChecksCell.tsx
  • src/modules/agent-network/AgentGuardrailModal.tsx
  • src/modules/agent-network/AgentOverviewPanel.tsx
  • src/modules/agent-network/AgentPoliciesTable.tsx
  • src/modules/agent-network/AgentPolicyGuardrailsTab.tsx
  • src/modules/agent-network/AgentPolicyLimitsTab.tsx
  • src/modules/agent-network/AgentPolicyModal.tsx
  • src/modules/agent-network/agentAccessLogApi.ts
  • src/modules/agent-network/data/mockData.ts
  • src/modules/agent-network/table/AgentProviderActionCell.tsx
  • src/modules/agent-network/table/AgentProvidersTable.tsx
  • src/modules/agent-network/useProviderCatalog.ts
  • src/modules/control-center/FlowSelector.tsx
  • src/modules/control-center/nodes/AgentPolicyNode.tsx
  • src/modules/control-center/nodes/ProviderNode.tsx
  • src/modules/control-center/utils/layouts.ts
  • src/modules/control-center/utils/nodes.ts
  • src/modules/instance-setup/InstanceSetupWizard.tsx
  • src/modules/onboarding/OnboardingProvider.tsx
  • src/modules/onboarding/agent-network/AgentNetworkOnboarding.tsx
  • src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentConfigure.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentDevice.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentEnd.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentPolicy.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentProvider.tsx
  • src/modules/onboarding/agent-network/OnboardingAgentWelcome.tsx
  • src/modules/onboarding/agent-network/useAgentNetworkFirstRunSetup.ts
  • src/modules/peers/PeersTable.tsx
  • src/modules/setup-netbird-modal/MacOSTab.tsx
  • src/modules/setup-netbird-modal/WindowsTab.tsx
  • src/utils/config.ts
  • src/utils/netbird.ts
💤 Files with no reviewable changes (1)
  • src/modules/access-control/table/AccessControlTable.tsx

Comment thread src/app/(dashboard)/agent-network/providers/page.tsx Outdated
Comment thread src/app/(dashboard)/agent-network/usage/page.tsx
Comment thread src/layouts/Navigation.tsx Outdated
Comment thread src/modules/agent-network/AgentAccessLogTable.tsx
Comment thread src/modules/agent-network/AgentAccountControlsCard.tsx Outdated
Comment thread src/modules/onboarding/agent-network/AgentNetworkSignupForm.tsx
Comment thread src/modules/onboarding/agent-network/OnboardingAgentDevice.tsx
Comment thread src/modules/peers/PeersTable.tsx Outdated
Comment thread src/modules/peers/PeersTable.tsx Outdated
mlsmaycon
mlsmaycon previously approved these changes Jun 27, 2026
mlsmaycon
mlsmaycon previously approved these changes Jun 27, 2026
@braginini
braginini merged commit 944d1b5 into main Jun 27, 2026
8 checks passed
@braginini
braginini deleted the agent-network branch June 27, 2026 17:11
JuliusFreudenberger pushed a commit to JuliusFreudenberger/nix-config that referenced this pull request Jul 2, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [netbirdio/dashboard](https://github.com/netbirdio/dashboard) | minor | `v2.39.0` → `v2.90.3` |
| netbirdio/netbird | minor | `v0.73.2-rootless` → `v0.74.1-rootless` |
| netbirdio/netbird-server | minor | `0.73.2` → `0.74.1` |
| netbirdio/reverse-proxy | minor | `0.73.2` → `0.74.1` |

---

> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/12) for more information.

---

### Release Notes

<details>
<summary>netbirdio/dashboard (netbirdio/dashboard)</summary>

### [`v2.90.3`](https://github.com/netbirdio/dashboard/releases/tag/v2.90.3)

[Compare Source](netbirdio/dashboard@v2.90.2...v2.90.3)

#### What's Changed

- Show reason for peer login expiration events by [@&#8203;bcmmbaga](https://github.com/bcmmbaga) in [#&#8203;694](netbirdio/dashboard#694)
- Reload nginx after patching CSP header by [@&#8203;pappz](https://github.com/pappz) in [#&#8203;687](netbirdio/dashboard#687)
- Fix peer table page reset when switching kind by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;696](netbirdio/dashboard#696)
- Feature/add provider session by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;695](netbirdio/dashboard#695)
- Add Metrics settings tab with metrics push toggle by [@&#8203;pappz](https://github.com/pappz) in [#&#8203;613](netbirdio/dashboard#613)
- Feature/add skip tls verification by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;697](netbirdio/dashboard#697)

**Full Changelog**: <netbirdio/dashboard@v2.90.2...v2.90.3>

### [`v2.90.2`](https://github.com/netbirdio/dashboard/releases/tag/v2.90.2)

[Compare Source](netbirdio/dashboard@v2.90.1...v2.90.2)

#### What's Changed

- Add Claude provider selector and Bedrock by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;691](netbirdio/dashboard#691)
- Prevent gated useFetchApi hooks from overwriting shared cache entries by [@&#8203;bcmmbaga](https://github.com/bcmmbaga) in [#&#8203;692](netbirdio/dashboard#692)

**Full Changelog**: <netbirdio/dashboard@v2.90.1...v2.90.2>

### [`v2.90.1`](https://github.com/netbirdio/dashboard/releases/tag/v2.90.1)

[Compare Source](netbirdio/dashboard@v2.90.0...v2.90.1)

#### What's Changed

- The empty-state peer card now renders AddPeerDropdown by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;686](netbirdio/dashboard#686)
- Support Vertex keyfile upload and agent config by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;688](netbirdio/dashboard#688)
- Prefill Vertex endpoint by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;689](netbirdio/dashboard#689)

**Full Changelog**: <netbirdio/dashboard@v2.90.0...v2.90.1>

### [`v2.90.0`](https://github.com/netbirdio/dashboard/releases/tag/v2.90.0)

[Compare Source](netbirdio/dashboard@v2.80.0...v2.90.0)

#### What's Changed

- Fix CSP blocking OIDC token endpoint by [@&#8203;maxbrc](https://github.com/maxbrc) in [#&#8203;680](netbirdio/dashboard#680)
- Agent Network by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;684](netbirdio/dashboard#684)

#### New Contributors

- [@&#8203;maxbrc](https://github.com/maxbrc) made their first contribution in [#&#8203;680](netbirdio/dashboard#680)

**Full Changelog**: <netbirdio/dashboard@v2.80.0...v2.90.0>

### [`v2.80.0`](https://github.com/netbirdio/dashboard/releases/tag/v2.80.0)

[Compare Source](netbirdio/dashboard@v2.39.0...v2.80.0)

#### What's Changed

- Add Logout URL to the Identity Provider dialog by [@&#8203;TechHutTV](https://github.com/TechHutTV) in [#&#8203;657](netbirdio/dashboard#657)
- Edit banner to IPv6 kh link by [@&#8203;TechHutTV](https://github.com/TechHutTV) in [#&#8203;662](netbirdio/dashboard#662)
- Insert link to remote jobs documentation by [@&#8203;semp26](https://github.com/semp26) in [#&#8203;664](netbirdio/dashboard#664)
- DNS Zones & Setup modal improvements by [@&#8203;braginini](https://github.com/braginini) in [#&#8203;669](netbirdio/dashboard#669)
- Update banner by [@&#8203;heisbrot](https://github.com/heisbrot) in [#&#8203;672](netbirdio/dashboard#672)
- Update announcements.json by [@&#8203;mlsmaycon](https://github.com/mlsmaycon) in [#&#8203;673](netbirdio/dashboard#673)
- Merge NetBird cloud edition into the dashboard by [@&#8203;mlsmaycon](https://github.com/mlsmaycon) in [#&#8203;674](netbirdio/dashboard#674)
- Restrict cloud/licensed-only API calls in open-source mode by [@&#8203;mlsmaycon](https://github.com/mlsmaycon) in [#&#8203;675](netbirdio/dashboard#675)
- Preserve inactivity expiration on partial peer updates by [@&#8203;bcmmbaga](https://github.com/bcmmbaga) in [#&#8203;676](netbirdio/dashboard#676)

#### New Contributors

- [@&#8203;TechHutTV](https://github.com/TechHutTV) made their first contribution in [#&#8203;657](netbirdio/dashboard#657)
- [@&#8203;semp26](https://github.com/semp26) made their first contribution in [#&#8203;664](netbirdio/dashboard#664)

**Full Changelog**: <netbirdio/dashboard@v2.39.0...v2.80.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNTAuMSIsInVwZGF0ZWRJblZlciI6IjQzLjE1MC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.jfreudenberger.de/JuliusFreudenberger/nix-config/pulls/10
Co-authored-by: Renovate Bot <renovate@jfreudenberger.de>
Co-committed-by: Renovate Bot <renovate@jfreudenberger.de>
ocoj added a commit to ocoj/dashboard that referenced this pull request Jul 13, 2026
Upstream features preserved:
- Agent Network (netbirdio#684, netbirdio#708)
- Lazy Connections (netbirdio#706)
- New Traffic Filters (netbirdio#704)
- Cluster one-click deploy (netbirdio#707)
- etc.

i18n preserved:
- All zh.ts/en.ts keys intact
- Control-center, VersionInfo, Navigation translations
- Translation framework (next-intl) retained

Resolved: Navigation t() definition, PeersTable types
ocoj pushed a commit to ocoj/dashboard that referenced this pull request Jul 17, 2026
ocoj added a commit to ocoj/dashboard that referenced this pull request Jul 17, 2026
Upstream features preserved:
- Agent Network (netbirdio#684, netbirdio#708)
- Lazy Connections (netbirdio#706)
- New Traffic Filters (netbirdio#704)
- Cluster one-click deploy (netbirdio#707)
- etc.

i18n preserved:
- All zh.ts/en.ts keys intact
- Control-center, VersionInfo, Navigation translations
- Translation framework (next-intl) retained

Resolved: Navigation t() definition, PeersTable types
ocoj pushed a commit to ocoj/dashboard that referenced this pull request Aug 16, 2026
ocoj added a commit to ocoj/dashboard that referenced this pull request Aug 16, 2026
Upstream features preserved:
- Agent Network (netbirdio#684, netbirdio#708)
- Lazy Connections (netbirdio#706)
- New Traffic Filters (netbirdio#704)
- Cluster one-click deploy (netbirdio#707)
- etc.

i18n preserved:
- All zh.ts/en.ts keys intact
- Control-center, VersionInfo, Navigation translations
- Translation framework (next-intl) retained

Resolved: Navigation t() definition, PeersTable types
ocoj added a commit to ocoj/dashboard that referenced this pull request Aug 16, 2026
Upstream features preserved:
- Agent Network (netbirdio#684, netbirdio#708)
- Lazy Connections (netbirdio#706)
- New Traffic Filters (netbirdio#704)
- Cluster one-click deploy (netbirdio#707)
- etc.

i18n preserved:
- All zh.ts/en.ts keys intact
- Control-center, VersionInfo, Navigation translations
- Translation framework (next-intl) retained

Resolved: Navigation t() definition, PeersTable types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants