Skip to content

Comments

feat: improve system status graph and add developer role#1664

Merged
yottahmd merged 2 commits intomainfrom
monitoring-fix
Feb 13, 2026
Merged

feat: improve system status graph and add developer role#1664
yottahmd merged 2 commits intomainfrom
monitoring-fix

Conversation

@yottahmd
Copy link
Collaborator

@yottahmd yottahmd commented Feb 13, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added new "Developer" user role with DAG CRUD and execution permissions
    • Extended resource monitoring with disk and memory total/used byte metrics
    • Reorganized system features (System Status, Webhooks, Audit Logs) with refined role-based access controls
  • Bug Fixes

    • Improved permission checks for tool execution and DAG operations
  • UI/UX Improvements

    • Updated navigation menu to reflect new role structure
    • Enhanced resource charts with additional byte-level metrics display

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

This PR introduces a new "developer" user role throughout the system and propagates it from authentication through agent session management, tool execution, and API endpoints. It adds role-based permission checks on tools and endpoints, extends resource monitoring with disk/memory total metrics, and updates the frontend UI to reflect the new authorization hierarchy.

Changes

Cohort / File(s) Summary
API Schema & Generation
api/v1/api.yaml, api/v1/api.gen.go
Added UserRoleDeveloper constant and extended ResourceHistory with new disk/memory total and used byte fields (MemoryTotalBytes, MemoryUsedBytes, DiskTotalBytes, DiskUsedBytes).
Auth Role System
internal/auth/role.go, internal/auth/role_test.go, internal/auth/user_test.go, internal/cmn/config/config.go, internal/cmn/config/config_test.go
Added RoleDeveloper constant and CanManageAudit() method. Updated role validation, OIDC defaults, and permission logic to include developer role in valid roles, write/execute checks, and audit access.
Agent User Context & Session
internal/agent/api.go, internal/agent/session.go
Modified getUserContextFromRequest to return role; added role propagation through session creation and reactivation. SessionManagerConfig and SessionManager now carry Role field, and UpdateUserContext method propagates role to active loop.
Agent Core Loop & Types
internal/agent/loop.go, internal/agent/loop_test.go, internal/agent/types.go, internal/agent/hooks.go, internal/agent/hooks_test.go
Extended LoopConfig, Loop, ToolContext, and ToolExecInfo with Role field. Added SetUserContext method to Loop for thread-safe role updates. Role propagates through tool execution context.
Agent Tool Authorization
internal/agent/bash.go, internal/agent/bash_test.go, internal/agent/navigate.go, internal/agent/navigate_test.go, internal/agent/patch.go, internal/agent/patch_test.go
Added permission guards: bash requires execute permission, navigate blocks admin-only paths for non-admins, patch requires write permission. Tests verify rejection of unauthorized roles.
Agent System Prompt
internal/agent/system_prompt.go, internal/agent/system_prompt.txt, internal/agent/system_prompt_test.go
Extended GenerateSystemPrompt signature to accept auth.Role parameter. Added UserCapabilities type and buildUserCapabilities helper to expose role and capability flags to the LLM. System prompt now includes authenticated user capabilities block.
Resource Monitoring
internal/service/resource/service.go, internal/service/resource/store.go, internal/service/resource/store_test.go
Extended resource collection to capture memory/disk total and used bytes. Store interface Add method now accepts four additional uint64 parameters; ResourceHistory struct carries new total/used fields; GetHistory populates them in API responses.
Frontend API Authorization
internal/service/frontend/api/v1/api.go, internal/service/frontend/api/v1/audit.go, internal/service/frontend/api/v1/audit_permissions_test.go, internal/service/frontend/api/v1/resources.go, internal/service/frontend/api/v1/services.go, internal/service/frontend/api/v1/webhooks.go, internal/service/frontend/api/v1/webhooks_test.go, internal/service/frontend/api/v1/workers.go
Added requireManagerOrAbove and requireDeveloperOrAbove authorization checks. Audit endpoint requires manager+; webhooks, system-status, workers, and resource endpoints require developer+. Responses include new disk/memory byte fields with safe uint64→int64 conversion.
Frontend Auth & Middleware
internal/service/frontend/auth/builtin.go, internal/service/frontend/auth/middleware_test.go, internal/service/oidcprovision/rolemapper.go, internal/service/oidcprovision/rolemapper_test.go
Extended RequireWrite and RequireExecute middleware to include developer role. OIDC role mapping updated to place developer between manager and operator in priority hierarchy (Admin 5, Manager 4, Developer 3, Operator 2, Viewer 1).
Frontend UI Routes & Auth Context
ui/src/App.tsx, ui/src/components/ProtectedRoute.tsx, ui/src/contexts/AuthContext.tsx
Added DeveloperElement and ManagerElement route wrappers. Exported UserRole type and updated ROLE_HIERARCHY (admin: 5, manager: 4, developer: 3, operator: 2, viewer: 1). Added useCanAccessSystemStatus, useCanManageWebhooks, useCanViewAuditLogs hooks. Changed write threshold from manager to developer.
Frontend UI API Schema & Components
ui/src/api/v1/schema.ts, ui/src/features/dashboard/components/MiniResourceChart.tsx, ui/src/features/system-status/components/ResourceChart.tsx, ui/src/lib/formatBytes.ts
Updated schema with developer role and resource byte fields. Added formatBytes utility for human-readable byte formatting. Extended ResourceChart props with totalBytes/usedBytes and conditional display of usage summary when available.
Frontend UI Menu & Pages
ui/src/menu.tsx, ui/src/pages/api-keys/APIKeyFormModal.tsx, ui/src/pages/audit-logs/index.tsx, ui/src/pages/webhooks/index.tsx, ui/src/pages/users/UserFormModal.tsx, ui/src/pages/system-status/index.tsx
Reorganized menu: moved webhooks and audit logs to new Operations section gated by appropriate permissions. Updated role descriptions in user/API-key forms to include developer and expanded manager. Replaced permission hooks (useIsAdmin → useCanViewAuditLogs/useCanManageWebhooks). System status page passes byte metrics to resource charts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the two main changes: adding a developer role throughout the system and improving system status graph visualization with new resource metrics.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch monitoring-fix

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
internal/service/frontend/api/v1/webhooks.go (1)

29-31: ⚠️ Potential issue | 🟡 Minor

Stale doc comments still say "Requires admin role".

The requireWebhookManagement helper now enforces developer-or-above (Line 396), but the GoDoc comments on ListWebhooks, GetDAGWebhook, CreateDAGWebhook, DeleteDAGWebhook, RegenerateDAGWebhookToken, and ToggleDAGWebhook still say "Requires admin role." Update them to match the actual policy.

Also applies to: 54-56, 81-83, 132-134, 169-171, 205-207

🤖 Fix all issues with AI agents
In `@internal/service/frontend/api/v1/resources.go`:
- Around line 15-17: GetResourceHistory is currently gated by a call to
requireDeveloperOrAbove which blocks operators/viewers and breaks the System
Status page; change the access check so non-developer roles can still read
resource history (either replace requireDeveloperOrAbove with a read-level guard
such as requireViewerOrAbove/requireOperatorOrAbove if available, or introduce a
new lighter-weight check like requireAuthenticatedOrReadOnly and use that in
GetResourceHistory) or alternatively return a 200 with an empty/partial payload
and let the UI hide charts for insufficient roles; update the check in the
GetResourceHistory handler (the call to requireDeveloperOrAbove) accordingly so
the frontend /services/resources/history request succeeds for intended roles.

In `@ui/src/lib/formatBytes.ts`:
- Around line 3-9: The function formatBytes currently computes Math.log(bytes)
which returns NaN for negative inputs leading to outputs like "NaN undefined";
update formatBytes so it guards against negative values (treat bytes <= 0 the
same as zero) by returning "0 B" early, ensuring the rest of the logic (use of
units and k) only runs for positive byte values; keep the existing behavior for
bytes === 0 and decimals parameter and refer to the formatBytes function and
units array when making the change.
🧹 Nitpick comments (10)
ui/src/features/system-status/components/ResourceChart.tsx (1)

132-132: Tooltip formatter type annotation may not match recharts' actual signature.

The recharts Tooltip formatter callback receives (value: number | string | Array<number | string>, ...). Typing the parameter as number will work at runtime but could cause a TypeScript error depending on your recharts version and strict settings.

internal/service/frontend/api/v1/workers.go (1)

16-19: Log statement fires before authorization check.

logger.Info(ctx, "GetWorkers called") on Line 16 executes before the auth gate on Line 17. This means unauthorized requests also produce log entries. Consider moving the log after the auth check, or demoting it to debug level, to reduce noise from unauthorized callers.

internal/agent/patch.go (1)

90-92: Consider using a named constant or method for empty-role checks.

The empty-string sentinel ctx.Role != auth.Role("") appears in three places: patch.go (line 90), navigate.go (line 66), and bash.go (line 145). A helper like Role.IsSet() or a RoleNone constant would be more readable and maintainable if the sentinel value ever changes.

Example approach in internal/auth/role.go
// Add to role.go
const RoleNone Role = ""

func (r Role) IsSet() bool {
    return r != RoleNone
}

Then usage becomes:

-if ctx.Role != auth.Role("") && !ctx.Role.CanWrite() {
+if ctx.Role.IsSet() && !ctx.Role.CanWrite() {
internal/agent/system_prompt_test.go (1)

22-27: Good addition of role-based assertion.

The test correctly verifies the developer role appears in the generated prompt. Consider adding similar role-content assertions in the admin and viewer test cases (lines 38, 47) to verify that different roles produce different capability sections.

internal/agent/session.go (1)

381-403: Note: createLoop reads sm.role (and other fields) without holding sm.mu.

This follows the existing pattern for sm.username, sm.ipAddress, sm.environment, etc., so it's not a new issue. However, if UpdateUserContext is called concurrently with ensureLoop, there's a theoretical data race on these fields since ensureLoop releases the lock at line 361 before calling createLoop. This is a pre-existing concern.

internal/auth/role.go (1)

73-75: Duplicate doc comment on ParseRole.

Line 73-74 has two // ParseRole converts... lines with slightly different wording.

Suggested fix
 // ParseRole converts a string to a Role.
-// ParseRole converts the input string to a Role and verifies it is one of the known roles.
 // If the input is not "admin", "manager", "developer", "operator", or "viewer", it returns an error describing the valid options.
internal/service/frontend/api/v1/audit_permissions_test.go (2)

13-23: Consider reusing setupWebhookTestServer instead of duplicating setup logic.

setupAuditTestServer is nearly identical to setupWebhookTestServer in webhooks_test.go (lines 66-75). The only addition is cfg.Server.Audit.Enabled = true. You could compose this by calling setupWebhookTestServer with an additional config mutator, or extract a shared base helper that accepts variadic config mutators, to avoid duplicating the auth config block.

♻️ Suggested approach

Extract a shared helper (e.g., in a helpers_test.go):

func setupBaseTestServer(t *testing.T, extraMutators ...func(*config.Config)) test.Server {
	t.Helper()
	return test.SetupServer(t, test.WithConfigMutator(func(cfg *config.Config) {
		cfg.Server.Auth.Mode = config.AuthModeBuiltin
		cfg.Server.Auth.Builtin.Admin.Username = "admin"
		cfg.Server.Auth.Builtin.Admin.Password = "adminpass"
		cfg.Server.Auth.Builtin.Token.Secret = "jwt-secret-key"
		cfg.Server.Auth.Builtin.Token.TTL = 24 * time.Hour
		for _, m := range extraMutators {
			m(cfg)
		}
	}))
}

Then in this file:

 func setupAuditTestServer(t *testing.T) test.Server {
 	t.Helper()
-	return test.SetupServer(t, test.WithConfigMutator(func(cfg *config.Config) {
-		cfg.Server.Auth.Mode = config.AuthModeBuiltin
-		cfg.Server.Auth.Builtin.Admin.Username = "admin"
-		cfg.Server.Auth.Builtin.Admin.Password = "adminpass"
-		cfg.Server.Auth.Builtin.Token.Secret = "jwt-secret-key"
-		cfg.Server.Auth.Builtin.Token.TTL = 24 * time.Hour
-		cfg.Server.Audit.Enabled = true
-	}))
+	return setupBaseTestServer(t, func(cfg *config.Config) {
+		cfg.Server.Audit.Enabled = true
+	})
 }

25-65: Consider expanding role coverage for the audit endpoint.

The test verifies that manager is allowed and developer is forbidden, which validates the boundary between these two adjacent roles. However, it doesn't cover operator or viewer (also expected forbidden). Adding these cases—ideally via a table-driven approach—would strengthen confidence that the requireManagerOrAbove check works correctly across the full role hierarchy, consistent with the approach taken in TestWebhooks_RequiresDeveloperOrAbove which tests both operator and viewer.

internal/service/frontend/api/v1/webhooks_test.go (2)

133-207: Good role-based coverage; consider also verifying developer access to the webhook create endpoint.

The test thoroughly covers operator and viewer being forbidden for both GET /api/v1/webhooks and POST /api/v1/dags/.../webhook, but for the developer role it only verifies GET /api/v1/webhooks (line 204-206). Adding a developer-access check for the webhook create POST (after creating a test DAG) would ensure both webhook management endpoints are verified for the new role boundary.

♻️ Suggested addition after line 206
 	// Developer can access webhook management endpoints.
 	server.Client().Get("/api/v1/webhooks").
 		WithBearerToken(developerLogin.Token).
 		ExpectStatus(http.StatusOK).Send(t)
+
+	// Developer can also create webhooks.
+	dagName := "webhook_dev_access_test"
+	createTestDAG(t, server, adminToken, dagName)
+	server.Client().Post("/api/v1/dags/"+dagName+"/webhook", nil).
+		WithBearerToken(developerLogin.Token).
+		ExpectStatus(http.StatusCreated).Send(t)

186-201: Webhook POST tests for operator/viewer rely on a non-existent DAG — intentional but fragile.

Lines 191-193 and 199-201 POST to /api/v1/dags/test-dag/webhook where test-dag doesn't exist. This works because the authorization middleware rejects before DAG lookup, but if middleware ordering ever changes, these assertions could break (returning 404 instead of 403). The existing TestWebhooks_RequiresAuth (line 129-130) uses the same pattern, so this is consistent with the current codebase convention.

@ghansham
Copy link

ghansham commented Feb 13, 2026

What is the difference between developer and exusting manager role?

@yottahmd
Copy link
Collaborator Author

@ghansham It's same at the moment (except for access to audit log).

@yottahmd yottahmd merged commit 7bbf1ce into main Feb 13, 2026
6 checks passed
@yottahmd yottahmd deleted the monitoring-fix branch February 13, 2026 15:37
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

❌ Patch coverage is 93.26923% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.21%. Comparing base (d496dde) to head (e343df8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/service/resource/store.go 72.22% 5 Missing ⚠️
internal/agent/api.go 83.33% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1664      +/-   ##
==========================================
+ Coverage   70.18%   70.21%   +0.02%     
==========================================
  Files         345      345              
  Lines       38664    38736      +72     
==========================================
+ Hits        27135    27197      +62     
- Misses       9361     9368       +7     
- Partials     2168     2171       +3     
Files with missing lines Coverage Δ
internal/agent/bash.go 90.83% <100.00%> (+0.14%) ⬆️
internal/agent/hooks.go 100.00% <ø> (ø)
internal/agent/loop.go 89.08% <100.00%> (+0.56%) ⬆️
internal/agent/navigate.go 100.00% <100.00%> (ø)
internal/agent/patch.go 90.67% <100.00%> (+0.16%) ⬆️
internal/agent/session.go 74.59% <100.00%> (+0.85%) ⬆️
internal/agent/system_prompt.go 84.61% <100.00%> (+9.61%) ⬆️
internal/agent/types.go 100.00% <ø> (ø)
internal/auth/role.go 100.00% <100.00%> (ø)
internal/cmn/config/config.go 76.28% <100.00%> (ø)
... and 4 more

... and 6 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d496dde...e343df8. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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