feat: add agent management

This commit is contained in:
lussierj committed 2026-08-27 17:00:56 +00:00
1 parent d9f0da694b
commit b9b5e5e36f
17 files changed
+1644 -1

No files matched your search

@@ -0,0 +1,141 @@
"""Frontend contract tests for Agent Management."""
import unittest
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from app.frontend.router import router
from app.identity import get_current_user, required_page_permission
STATIC_ROOT = Path(__file__).parents[1] / "app" / "frontend" / "static"
class AgentManagementFrontendTests(unittest.TestCase):
def setUp(self):
self.app = FastAPI()
self.app.include_router(router)
self.client = TestClient(self.app)
def authenticate(self, permissions):
self.app.dependency_overrides[get_current_user] = lambda: {
"id": "00000000-0000-4000-8000-000000009001",
"username": "agent-test-user",
"display_name": "Agent Test User",
"role": "Test Role",
"permissions": tuple(permissions),
}
def test_page_requires_agents_view(self):
self.authenticate(("unrelated.permission",))
self.assertEqual(
self.client.get("/agent/management").status_code,
403,
)
self.authenticate(("agents.view",))
response = self.client.get("/agent/management")
self.assertEqual(response.status_code, 200)
self.assertIn("Agent Management", response.text)
self.assertIn('href="/agent/management"', response.text)
def test_manage_controls_follow_agents_manage_permission(self):
self.authenticate(("agents.view",))
restricted = self.client.get("/agent/management").text
self.assertNotIn('id="agentCreateForm"', restricted)
restricted_text = " ".join(restricted.split())
self.assertIn(
"cannot create Agent enrollments.",
restricted_text,
)
self.authenticate(("agents.view", "agents.manage"))
managed = self.client.get("/agent/management").text
self.assertIn('id="agentCreateForm"', managed)
self.assertIn('id="agentSite"', managed)
self.assertIn('id="agentZone"', managed)
self.assertIn('id="agentDisplayName"', managed)
self.assertIn("Linux x64 — coming later", managed)
self.assertIn("Linux ARM64 / Raspberry Pi — coming later", managed)
def test_route_and_asset_contract(self):
self.assertEqual(
required_page_permission("/agent/management"),
"agents.view",
)
self.authenticate(("agents.view",))
page = self.client.get("/agent/management")
self.assertIn(
"/assets/minerops-agent-management.js",
page.text,
)
asset = self.client.get(
"/assets/minerops-agent-management.js"
)
self.assertEqual(asset.status_code, 200)
self.assertEqual(
asset.headers.get("cache-control"),
"no-store",
)
def test_javascript_is_secret_conscious_and_safe_dom_only(self):
source = (
STATIC_ROOT / "agent-management.js"
).read_text(encoding="utf-8")
self.assertIn('api("/api/agents")', source)
self.assertIn('api("/api/agent-enrollments")', source)
self.assertIn(
'api("/api/agent-enrollments", {',
source,
)
for unsafe in (
"innerHTML",
"outerHTML",
"insertAdjacentHTML",
"localStorage",
"sessionStorage",
"console.log",
):
self.assertNotIn(unsafe, source)
self.assertIn(
"el.agentEnrollmentToken.textContent",
source,
)
self.assertIn(
"el.agentEnrollmentToken.textContent = \"\"",
source,
)
def test_agent_management_quiet_actions_have_visible_text(self):
css = (STATIC_ROOT / "app.css").read_text(encoding="utf-8")
self.assertIn(
".agent-management-columns .quiet-button,",
css,
)
self.assertIn(
".agent-enrollment-panel .quiet-button {",
css,
)
self.assertIn(
"color: var(--ink);",
css,
)
if __name__ == "__main__":
unittest.main()