agent-nuvira 2.7.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +5 -2453
  2. package/dist/agents/orchestrator.d.ts.map +1 -1
  3. package/dist/agents/orchestrator.js +17 -3
  4. package/dist/agents/orchestrator.js.map +1 -1
  5. package/dist/app.js +26 -0
  6. package/dist/cli/chat.d.ts.map +1 -1
  7. package/dist/cli/chat.js +101 -2
  8. package/dist/cli/chat.js.map +1 -1
  9. package/dist/config/auth.js +18 -0
  10. package/dist/config/jwt.js +24 -0
  11. package/dist/config/keys.js +14 -0
  12. package/dist/gateway/chat-store.d.ts +32 -5
  13. package/dist/gateway/chat-store.d.ts.map +1 -1
  14. package/dist/gateway/chat-store.js +52 -6
  15. package/dist/gateway/chat-store.js.map +1 -1
  16. package/dist/gateway/registry.d.ts.map +1 -1
  17. package/dist/gateway/registry.js +42 -5
  18. package/dist/gateway/registry.js.map +1 -1
  19. package/dist/inference/model-validator.d.ts.map +1 -1
  20. package/dist/inference/model-validator.js +11 -1
  21. package/dist/inference/model-validator.js.map +1 -1
  22. package/dist/inference/tool-call-utils.d.ts +31 -0
  23. package/dist/inference/tool-call-utils.d.ts.map +1 -1
  24. package/dist/inference/tool-call-utils.js +41 -0
  25. package/dist/inference/tool-call-utils.js.map +1 -1
  26. package/dist/learning/reasoning-trace.d.ts +5 -3
  27. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  28. package/dist/learning/reasoning-trace.js +2 -2
  29. package/dist/learning/reasoning-trace.js.map +1 -1
  30. package/dist/middleware/auth.js +30 -0
  31. package/dist/nlu/intent.d.ts.map +1 -1
  32. package/dist/nlu/intent.js +20 -3
  33. package/dist/nlu/intent.js.map +1 -1
  34. package/dist/passport.js +34 -0
  35. package/dist/routes/auth.js +42 -0
  36. package/dist/routes/user.js +31 -0
  37. package/dist/server.js +17 -0
  38. package/dist/tools/pipeline-tool.d.ts.map +1 -1
  39. package/dist/tools/pipeline-tool.js +14 -0
  40. package/dist/tools/pipeline-tool.js.map +1 -1
  41. package/dist/tools/release-sync.d.ts +52 -16
  42. package/dist/tools/release-sync.d.ts.map +1 -1
  43. package/dist/tools/release-sync.js +143 -79
  44. package/dist/tools/release-sync.js.map +1 -1
  45. package/dist/web-dashboard/src/App.js +85 -0
  46. package/dist/web-dashboard/src/admin-auth.test.js +186 -0
  47. package/dist/web-dashboard/src/ansi.js +23 -0
  48. package/dist/web-dashboard/src/ansi.test.js +31 -0
  49. package/dist/web-dashboard/src/api-admin-auth.test.js +172 -0
  50. package/dist/web-dashboard/src/api-admin.test.js +65 -0
  51. package/dist/web-dashboard/src/api-hub.test.js +117 -0
  52. package/dist/web-dashboard/src/api.js +1421 -0
  53. package/dist/web-dashboard/src/api.test.js +51 -0
  54. package/dist/web-dashboard/src/artifacts.js +128 -0
  55. package/dist/web-dashboard/src/artifacts.test.js +139 -0
  56. package/dist/web-dashboard/src/components/AdminPanel.js +567 -0
  57. package/dist/web-dashboard/src/components/AdminPanel.test.js +288 -0
  58. package/dist/web-dashboard/src/components/AgentHub.js +1580 -0
  59. package/dist/web-dashboard/src/components/AgentHub.test.js +343 -0
  60. package/dist/web-dashboard/src/components/BedrockOnboarding.js +320 -0
  61. package/dist/web-dashboard/src/components/BenchmarkCharts.js +228 -0
  62. package/dist/web-dashboard/src/components/ChatPage.js +1586 -0
  63. package/dist/web-dashboard/src/components/ChatPage.test.js +899 -0
  64. package/dist/web-dashboard/src/components/ContactsPage.js +141 -0
  65. package/dist/web-dashboard/src/components/CostDashboard.js +105 -0
  66. package/dist/web-dashboard/src/components/DAGView.js +477 -0
  67. package/dist/web-dashboard/src/components/DAGView.test.js +147 -0
  68. package/dist/web-dashboard/src/components/EnvVarEditor.js +138 -0
  69. package/dist/web-dashboard/src/components/EvalsPage.js +73 -0
  70. package/dist/web-dashboard/src/components/EvalsPage.test.js +120 -0
  71. package/dist/web-dashboard/src/components/ExecutionHistory.js +201 -0
  72. package/dist/web-dashboard/src/components/GatewayPage.js +40 -0
  73. package/dist/web-dashboard/src/components/GatewayPage.test.js +74 -0
  74. package/dist/web-dashboard/src/components/HealthPanel.js +68 -0
  75. package/dist/web-dashboard/src/components/HistoryBrowser.js +34 -0
  76. package/dist/web-dashboard/src/components/Layout.js +50 -0
  77. package/dist/web-dashboard/src/components/Markdown.js +152 -0
  78. package/dist/web-dashboard/src/components/Markdown.test.js +126 -0
  79. package/dist/web-dashboard/src/components/MarkdownZeroDep.js +237 -0
  80. package/dist/web-dashboard/src/components/MemoryPanel.js +81 -0
  81. package/dist/web-dashboard/src/components/ModelTimeline.js +298 -0
  82. package/dist/web-dashboard/src/components/ModelsPanel.js +1484 -0
  83. package/dist/web-dashboard/src/components/ModelsPanel.test.js +460 -0
  84. package/dist/web-dashboard/src/components/Overview.js +123 -0
  85. package/dist/web-dashboard/src/components/PhaseTimeline.js +359 -0
  86. package/dist/web-dashboard/src/components/PhaseTimeline.test.js +234 -0
  87. package/dist/web-dashboard/src/components/PlatformConfigSection.js +384 -0
  88. package/dist/web-dashboard/src/components/PlatformConfigSection.test.js +106 -0
  89. package/dist/web-dashboard/src/components/PlatformsPage.js +250 -0
  90. package/dist/web-dashboard/src/components/QuotaPanel.js +159 -0
  91. package/dist/web-dashboard/src/components/QuotaPanel.test.js +85 -0
  92. package/dist/web-dashboard/src/components/RequestsPanel.js +229 -0
  93. package/dist/web-dashboard/src/components/RequestsPanel.test.js +103 -0
  94. package/dist/web-dashboard/src/components/RoutingInsightsPanel.js +938 -0
  95. package/dist/web-dashboard/src/components/RoutingInsightsPanel.test.js +339 -0
  96. package/dist/web-dashboard/src/components/RoutingWalkthrough.js +408 -0
  97. package/dist/web-dashboard/src/components/RoutingWalkthrough.test.js +209 -0
  98. package/dist/web-dashboard/src/components/TaskConsole.js +119 -0
  99. package/dist/web-dashboard/src/components/TaskConsole.test.js +123 -0
  100. package/dist/web-dashboard/src/components/TasksPage.js +256 -0
  101. package/dist/web-dashboard/src/components/TasksPage.test.js +103 -0
  102. package/dist/web-dashboard/src/components/TracePanel.js +306 -0
  103. package/dist/web-dashboard/src/components/WhatsAppPanel.js +195 -0
  104. package/dist/web-dashboard/src/components/WhatsAppPanel.test.js +122 -0
  105. package/dist/web-dashboard/src/jsonOrNull.js +37 -0
  106. package/dist/web-dashboard/src/main.js +15 -0
  107. package/dist/web-dashboard/src/mask.js +11 -0
  108. package/dist/web-dashboard/vite.config.js +23 -0
  109. package/dist/web-dashboard/vitest.config.js +15 -0
  110. package/package.json +5 -3
@@ -1 +1 @@
1
- {"version":3,"file":"release-sync.js","sourceRoot":"","sources":["../../src/tools/release-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC,iFAAiF;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,CAAC;AAEvE;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,IAAY,EAAE,cAAsB;IACjF,MAAM,IAAI,GAAsB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,aAAa,GAAG,IAAI,KAAK,EAAE,CAAC;IAClC,MAAM,kBAAkB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAElE,sDAAsD;IACtD,MAAM,SAAS,GAAG,qDAAqD,CAAC;IACxE,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI;gBACJ,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC;gBACjC,KAAK,EAAE,IAAI,KAAK,EAAE;gBAClB,QAAQ,EAAE,aAAa;gBACvB,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,uBAAuB;IACvB,MAAM,OAAO,GAAG,kCAAkC,CAAC;IACnD,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI;gBACJ,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC;gBACjC,KAAK,EAAE,IAAI,KAAK,EAAE;gBAClB,QAAQ,EAAE,aAAa;gBACvB,IAAI,EAAE,kBAAkB;aACzB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,6DAA6D;IAC7D,mEAAmE;IACnE,MAAM,KAAK,GAAG,mCAAmC,CAAC;IAClD,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,KAAK,KAAK,kBAAkB,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI;gBACJ,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC;gBACjC,KAAK,EAAE,IAAI,KAAK,IAAI;gBACpB,QAAQ,EAAE,IAAI,kBAAkB,IAAI;gBACpC,IAAI,EAAE,oBAAoB;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iDAAiD;AACjD,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa;IAC/C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc;IAC9C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7B,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,cAAsB,EAAE,GAAgB;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,IAAI,GAAsB,EAAE,CAAC;IAEnC,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI;YAAE,SAAS,CAAC,8CAA8C;QACnE,IAAI,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,EAAE,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,OAAO,4CAA4C,KAAK,sBAAsB,CAAC;IACjF,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,QAAQ,EAAE,CACvF,CAAC;IACF,GAAG,CAAC,IAAI,EAAE,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CACL,qBAAqB,IAAI,CAAC,MAAM,8CAA8C,KAAK,KAAK;QACxF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAChB,2FAA2F,CAC5F,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"release-sync.js","sourceRoot":"","sources":["../../src/tools/release-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = App;
7
+ const react_1 = require("react");
8
+ const react_router_dom_1 = require("react-router-dom");
9
+ const api_1 = require("./api");
10
+ const Layout_1 = __importDefault(require("./components/Layout"));
11
+ const Overview_1 = __importDefault(require("./components/Overview"));
12
+ const DAGView_1 = __importDefault(require("./components/DAGView"));
13
+ const CostDashboard_1 = __importDefault(require("./components/CostDashboard"));
14
+ const BenchmarkCharts_1 = __importDefault(require("./components/BenchmarkCharts"));
15
+ const HealthPanel_1 = __importDefault(require("./components/HealthPanel"));
16
+ const ModelsPanel_1 = __importDefault(require("./components/ModelsPanel"));
17
+ const RoutingInsightsPanel_1 = __importDefault(require("./components/RoutingInsightsPanel"));
18
+ const RequestsPanel_1 = __importDefault(require("./components/RequestsPanel"));
19
+ const TracePanel_1 = __importDefault(require("./components/TracePanel"));
20
+ const AdminPanel_1 = __importDefault(require("./components/AdminPanel"));
21
+ const AgentHub_1 = __importDefault(require("./components/AgentHub"));
22
+ const TasksPage_1 = __importDefault(require("./components/TasksPage"));
23
+ const ChatPage_1 = __importDefault(require("./components/ChatPage"));
24
+ const EvalsPage_1 = __importDefault(require("./components/EvalsPage"));
25
+ const GatewayPage_1 = __importDefault(require("./components/GatewayPage"));
26
+ const PlatformsPage_1 = __importDefault(require("./components/PlatformsPage"));
27
+ const BedrockOnboarding_1 = __importDefault(require("./components/BedrockOnboarding"));
28
+ const ContactsPage_1 = __importDefault(require("./components/ContactsPage"));
29
+ const ModelTimeline_1 = __importDefault(require("./components/ModelTimeline"));
30
+ function App() {
31
+ const [data, setData] = (0, react_1.useState)(null);
32
+ const [connected, setConnected] = (0, react_1.useState)(false);
33
+ const [lastUpdated, setLastUpdated] = (0, react_1.useState)('--');
34
+ const handleData = (0, react_1.useCallback)((d) => {
35
+ setData(d);
36
+ setLastUpdated(new Date().toLocaleTimeString());
37
+ }, []);
38
+ const handleConnection = (0, react_1.useCallback)((c) => {
39
+ setConnected(c);
40
+ }, []);
41
+ (0, react_1.useEffect)(() => {
42
+ // Fetch initial data
43
+ api_1.dashboardAPI.fetchAll().then((d) => {
44
+ if (d)
45
+ handleData(d);
46
+ });
47
+ // Subscribe to SSE updates
48
+ const unsubData = api_1.dashboardAPI.subscribe(handleData);
49
+ const unsubConn = api_1.dashboardAPI.onConnectionChange(handleConnection);
50
+ api_1.dashboardAPI.connect();
51
+ return () => {
52
+ unsubData();
53
+ unsubConn();
54
+ api_1.dashboardAPI.disconnect();
55
+ };
56
+ }, [handleData, handleConnection]);
57
+ return (<Layout_1.default connected={connected} lastUpdated={lastUpdated}>
58
+ <react_router_dom_1.Routes>
59
+ {/* Phase 5 — Chat is the front door; Overview (and every other room)
60
+ stays reachable as a panel, never required. */}
61
+ <react_router_dom_1.Route path="/" element={<ChatPage_1.default />}/>
62
+ <react_router_dom_1.Route path="/overview" element={<Overview_1.default data={data}/>}/>
63
+ <react_router_dom_1.Route path="/chat" element={<react_router_dom_1.Navigate to="/" replace/>}/>
64
+ <react_router_dom_1.Route path="/dag" element={<DAGView_1.default data={data}/>}/>
65
+ <react_router_dom_1.Route path="/costs" element={<CostDashboard_1.default data={data}/>}/>
66
+ <react_router_dom_1.Route path="/benchmarks" element={<BenchmarkCharts_1.default data={data}/>}/>
67
+ <react_router_dom_1.Route path="/models" element={<ModelsPanel_1.default />}/>
68
+ <react_router_dom_1.Route path="/models/timeline" element={<ModelTimeline_1.default />}/>
69
+ <react_router_dom_1.Route path="/routing" element={<RoutingInsightsPanel_1.default data={data}/>}/>
70
+ <react_router_dom_1.Route path="/requests" element={<RequestsPanel_1.default data={data}/>}/>
71
+ <react_router_dom_1.Route path="/traces" element={<TracePanel_1.default />}/>
72
+ <react_router_dom_1.Route path="/hub" element={<AgentHub_1.default />}/>
73
+ <react_router_dom_1.Route path="/tasks" element={<TasksPage_1.default />}/>
74
+ <react_router_dom_1.Route path="/chat" element={<ChatPage_1.default />}/>
75
+ <react_router_dom_1.Route path="/evals" element={<EvalsPage_1.default data={data}/>}/>
76
+ <react_router_dom_1.Route path="/platforms" element={<PlatformsPage_1.default />}/>
77
+ <react_router_dom_1.Route path="/bedrock" element={<BedrockOnboarding_1.default canWrite={true} sessionExpired={(msg) => console.error(msg)}/>}/>
78
+ <react_router_dom_1.Route path="/contacts" element={<ContactsPage_1.default />}/>
79
+ <react_router_dom_1.Route path="/gateway" element={<GatewayPage_1.default />}/>
80
+ <react_router_dom_1.Route path="/system" element={<HealthPanel_1.default data={data}/>}/>
81
+ <react_router_dom_1.Route path="/admin" element={<AdminPanel_1.default />}/>
82
+ <react_router_dom_1.Route path="*" element={<react_router_dom_1.Navigate to="/" replace/>}/>
83
+ </react_router_dom_1.Routes>
84
+ </Layout_1.default>);
85
+ }
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * Admin-auth module tests (Sessions 18 + 19).
4
+ *
5
+ * Session 18: the user-id + password gate (scrypt, env override, Bearer
6
+ * sessions). Session 19: multi-user + RBAC roles — the credential file stores
7
+ * a users map with roles, rbac.json assignments override the stored role (CLI
8
+ * governance parity), and sessions carry the acting role. These tests pin the
9
+ * security properties: passwords never on disk, wrong passwords fail, legacy
10
+ * single-user files migrate, rbac wins over the stored role, and the last
11
+ * admin can't be removed.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const vitest_1 = require("vitest");
15
+ const paths_1 = require("../../config/paths");
16
+ const node_fs_1 = require("node:fs");
17
+ const node_os_1 = require("node:os");
18
+ const node_path_1 = require("node:path");
19
+ const admin_auth_1 = require("./admin-auth");
20
+ (0, vitest_1.describe)('hashAdminPassword / verifyAdminPassword', () => {
21
+ (0, vitest_1.it)('round-trips a password (unique salt per hash)', () => {
22
+ const a = (0, admin_auth_1.hashAdminPassword)('s3cret-pass');
23
+ const b = (0, admin_auth_1.hashAdminPassword)('s3cret-pass');
24
+ (0, vitest_1.expect)(a.salt).not.toBe(b.salt);
25
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdminPassword)('s3cret-pass', a.salt, a.hash)).toBe(true);
26
+ });
27
+ (0, vitest_1.it)('rejects a wrong password and a wrong salt', () => {
28
+ const { salt, hash } = (0, admin_auth_1.hashAdminPassword)('right-password');
29
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdminPassword)('wrong-password', salt, hash)).toBe(false);
30
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdminPassword)('right-password', 'ffffffffffffffff', hash)).toBe(false);
31
+ });
32
+ });
33
+ (0, vitest_1.describe)('multi-user credential store (config-dir scoped)', () => {
34
+ let dir;
35
+ (0, vitest_1.beforeEach)(() => {
36
+ dir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'buff-admin-auth-'));
37
+ });
38
+ (0, vitest_1.afterEach)(() => {
39
+ (0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
40
+ });
41
+ (0, vitest_1.it)('stores users with roles — passwords never on disk', () => {
42
+ const admin = (0, admin_auth_1.writeAdminUser)('admin', 'super-secret-pass', 'admin', dir);
43
+ (0, vitest_1.expect)(admin.role).toBe('admin');
44
+ const op = (0, admin_auth_1.writeAdminUser)('op', 'operator-pass-1', 'operator', dir);
45
+ (0, vitest_1.expect)(op.role).toBe('operator');
46
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, 'dashboard-admin.json'), 'utf-8');
47
+ (0, vitest_1.expect)(raw).not.toContain('super-secret-pass');
48
+ (0, vitest_1.expect)(raw).not.toContain('operator-pass-1');
49
+ const users = (0, admin_auth_1.readAdminUsers)(dir);
50
+ (0, vitest_1.expect)(Object.keys(users).sort()).toEqual(['admin', 'op']);
51
+ (0, vitest_1.expect)(users.admin.role).toBe('admin');
52
+ (0, vitest_1.expect)(users.op.role).toBe('operator');
53
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'super-secret-pass', dir)).toBe(true);
54
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('op', 'operator-pass-1', dir)).toBe(true);
55
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'wrong', dir)).toBe(false);
56
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('ghost', 'super-secret-pass', dir)).toBe(false);
57
+ (0, vitest_1.expect)((0, admin_auth_1.isAdminConfigured)(dir)).toBe(true);
58
+ });
59
+ (0, vitest_1.it)('listAdminUsers excludes salt/hash; removeAdminUser deletes; countAdminRoleUsers counts admins', () => {
60
+ (0, admin_auth_1.writeAdminUser)('admin', 'admin-pass-123', 'admin', dir);
61
+ (0, admin_auth_1.writeAdminUser)('op', 'operator-pass-1', 'operator', dir);
62
+ (0, admin_auth_1.writeAdminUser)('view', 'viewer-pass-12', 'viewer', dir);
63
+ const listed = (0, admin_auth_1.listAdminUsers)(dir);
64
+ (0, vitest_1.expect)(listed).toHaveLength(3);
65
+ for (const u of listed) {
66
+ (0, vitest_1.expect)(u).not.toHaveProperty('salt');
67
+ (0, vitest_1.expect)(u).not.toHaveProperty('hash');
68
+ }
69
+ (0, vitest_1.expect)((0, admin_auth_1.countAdminRoleUsers)(dir)).toBe(1);
70
+ (0, vitest_1.expect)((0, admin_auth_1.removeAdminUser)('op', dir)).toBe(true);
71
+ (0, vitest_1.expect)((0, admin_auth_1.removeAdminUser)('op', dir)).toBe(false);
72
+ (0, vitest_1.expect)((0, admin_auth_1.listAdminUsers)(dir).map((u) => u.user)).toEqual(['admin', 'view']);
73
+ });
74
+ (0, vitest_1.it)('migrates the legacy single-user file shape to an admin user', () => {
75
+ // Session 18 shape: { user, salt, hash, createdAt } (no users wrapper).
76
+ const { salt, hash } = (0, admin_auth_1.hashAdminPassword)('legacy-pass');
77
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, 'dashboard-admin.json'), JSON.stringify({ user: 'admin', salt, hash, createdAt: 123 }), 'utf-8');
78
+ const users = (0, admin_auth_1.readAdminUsers)(dir);
79
+ (0, vitest_1.expect)(users.admin.role).toBe('admin');
80
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'legacy-pass', dir)).toBe(true);
81
+ (0, vitest_1.expect)((0, admin_auth_1.isAdminConfigured)(dir)).toBe(true);
82
+ });
83
+ (0, vitest_1.it)('a corrupt file reads as unconfigured (never throws, never downgrades to open)', () => {
84
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, 'dashboard-admin.json'), '{not json', 'utf-8');
85
+ (0, vitest_1.expect)((0, admin_auth_1.readAdminUsers)(dir)).toBeNull();
86
+ (0, vitest_1.expect)((0, admin_auth_1.isAdminConfigured)(dir)).toBe(false);
87
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'anything', dir)).toBe(false);
88
+ });
89
+ });
90
+ (0, vitest_1.describe)('roleForUser — rbac.json wins over the stored role (CLI parity)', () => {
91
+ let dir;
92
+ (0, vitest_1.beforeEach)(() => {
93
+ dir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'buff-admin-auth-'));
94
+ });
95
+ (0, vitest_1.afterEach)(() => {
96
+ (0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
97
+ });
98
+ (0, vitest_1.it)('uses the credential role when rbac.json has no assignment', () => {
99
+ (0, admin_auth_1.writeAdminUser)('op', 'operator-pass-1', 'operator', dir);
100
+ (0, vitest_1.expect)((0, admin_auth_1.roleForUser)('op', dir)).toBe('operator');
101
+ });
102
+ (0, vitest_1.it)('an rbac.json assignment overrides the stored role (a viewer in rbac is a viewer here)', () => {
103
+ (0, admin_auth_1.writeAdminUser)('op', 'operator-pass-1', 'operator', dir);
104
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, 'rbac.json'), JSON.stringify({ version: 1, users: { op: { role: 'viewer', addedAt: Date.now(), via: 'local' } } }), 'utf-8');
105
+ // rbac wins: the dashboard cannot escalate a user the CLI governs as viewer.
106
+ (0, vitest_1.expect)((0, admin_auth_1.roleForUser)('op', dir)).toBe('viewer');
107
+ });
108
+ (0, vitest_1.it)('unknown users resolve to viewer (deny by default)', () => {
109
+ (0, vitest_1.expect)((0, admin_auth_1.roleForUser)('ghost', dir)).toBe('viewer');
110
+ });
111
+ });
112
+ (0, vitest_1.describe)('env override (with role)', () => {
113
+ const OLD = {
114
+ user: (0, paths_1.envBuff)('DASHBOARD_ADMIN_USER'),
115
+ pass: (0, paths_1.envBuff)('DASHBOARD_ADMIN_PASSWORD'),
116
+ role: (0, paths_1.envBuff)('DASHBOARD_ADMIN_ROLE'),
117
+ };
118
+ (0, vitest_1.afterEach)(() => {
119
+ for (const [k, v] of Object.entries(OLD)) {
120
+ if (v === undefined)
121
+ delete process.env[`BUFF_DASHBOARD_ADMIN_${k.toUpperCase()}`];
122
+ else
123
+ process.env[`BUFF_DASHBOARD_ADMIN_${k.toUpperCase()}`] = v;
124
+ }
125
+ });
126
+ (0, vitest_1.it)('password-only defaults to the admin user + admin role; env wins over the file', () => {
127
+ delete (0, paths_1.envBuff)('DASHBOARD_ADMIN_USER');
128
+ delete (0, paths_1.envBuff)('DASHBOARD_ADMIN_ROLE');
129
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_PASSWORD') = 'env-pass';
130
+ (0, vitest_1.expect)((0, admin_auth_1.envAdminOverride)()).toEqual({ user: 'admin', password: 'env-pass', role: 'admin' });
131
+ (0, vitest_1.expect)((0, admin_auth_1.isAdminConfigured)()).toBe(true);
132
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'env-pass')).toBe(true);
133
+ (0, vitest_1.expect)((0, admin_auth_1.verifyAdmin)('admin', 'file-pass')).toBe(false);
134
+ });
135
+ (0, vitest_1.it)('honors BUFF_DASHBOARD_ADMIN_ROLE and rejects an invalid one (falls back to admin)', () => {
136
+ delete (0, paths_1.envBuff)('DASHBOARD_ADMIN_USER');
137
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_PASSWORD') = 'env-pass';
138
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_ROLE') = 'operator';
139
+ (0, vitest_1.expect)((0, admin_auth_1.envAdminOverride)()?.role).toBe('operator');
140
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_ROLE') = 'superuser';
141
+ (0, vitest_1.expect)((0, admin_auth_1.envAdminOverride)()?.role).toBe('admin');
142
+ });
143
+ (0, vitest_1.it)('roleForUser honors the env override role even with NO credential file (regression — env admins are not viewers)', () => {
144
+ delete (0, paths_1.envBuff)('DASHBOARD_ADMIN_USER');
145
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_ROLE') = 'admin';
146
+ (0, paths_1.envBuff)('DASHBOARD_ADMIN_PASSWORD') = 'env-pass';
147
+ // No dashboard-admin.json exists anywhere — the env role must still apply.
148
+ (0, vitest_1.expect)((0, admin_auth_1.roleForUser)('admin')).toBe('admin');
149
+ (0, vitest_1.expect)((0, admin_auth_1.roleForUser)('someone-else')).toBe('viewer');
150
+ });
151
+ });
152
+ (0, vitest_1.describe)('AdminSessions (role-carrying)', () => {
153
+ (0, vitest_1.it)('issues and validates a token with its role, rejects garbage', () => {
154
+ const s = new admin_auth_1.AdminSessions();
155
+ const token = s.issue('admin', 'admin');
156
+ (0, vitest_1.expect)(s.validate(token)).toEqual({ user: 'admin', role: 'admin' });
157
+ (0, vitest_1.expect)(s.validate('nope')).toBeNull();
158
+ (0, vitest_1.expect)(s.validate(undefined)).toBeNull();
159
+ (0, vitest_1.expect)(s.size()).toBe(1);
160
+ });
161
+ (0, vitest_1.it)('revokes a token', () => {
162
+ const s = new admin_auth_1.AdminSessions();
163
+ const token = s.issue('op', 'operator');
164
+ (0, vitest_1.expect)(s.revoke(token)).toBe(true);
165
+ (0, vitest_1.expect)(s.validate(token)).toBeNull();
166
+ (0, vitest_1.expect)(s.size()).toBe(0);
167
+ });
168
+ (0, vitest_1.it)('rejects expired tokens and reaps them', () => {
169
+ const s = new admin_auth_1.AdminSessions();
170
+ const token = s.issue('admin', 'admin');
171
+ vitest_1.vi.useFakeTimers();
172
+ try {
173
+ vitest_1.vi.advanceTimersByTime(8 * 60 * 60 * 1000 + 1);
174
+ (0, vitest_1.expect)(s.validate(token)).toBeNull();
175
+ (0, vitest_1.expect)(s.size()).toBe(0);
176
+ }
177
+ finally {
178
+ vitest_1.vi.useRealTimers();
179
+ }
180
+ });
181
+ });
182
+ (0, vitest_1.describe)('MIN_ADMIN_PASSWORD_LENGTH', () => {
183
+ (0, vitest_1.it)('is enforced by the server-facing constant (8 chars)', () => {
184
+ (0, vitest_1.expect)(admin_auth_1.MIN_ADMIN_PASSWORD_LENGTH).toBe(8);
185
+ });
186
+ });
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * P2 — ANSI escape stripping for terminal output rendered in the dashboard.
4
+ *
5
+ * The P1 task runner streams a child process's RAW stdout/stderr — chalk
6
+ * colors, cursor-control (progress bars / spinners), and OSC window-title
7
+ * sequences all arrive intact. The task-run card must render clean text, so
8
+ * every escape sequence is removed here (pure string in → string out).
9
+ *
10
+ * Coverage:
11
+ * - CSI sequences ESC [ ... (params) (intermediates) final — `\x1b[32m`,
12
+ * `\x1b[2K` (clear line), `\x1b[1A` (cursor up), `\x1b[?25l` (hide cursor)
13
+ * - OSC sequences ESC ] ... BEL|ST — `\x1b]0;title\x07`
14
+ * - Single-char escapes — `\x1b7` etc.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.stripAnsi = stripAnsi;
18
+ const ANSI_PATTERN = /\x1b(?:\[[0-9;?]*[ -/]*[@-~]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-Z\\-_])/g;
19
+ function stripAnsi(text) {
20
+ if (!text)
21
+ return '';
22
+ return text.replace(ANSI_PATTERN, '');
23
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * P2 — ANSI escape stripping unit tests: the pure string→string function the
4
+ * task-run card uses to render child-process output without chalk colors,
5
+ * cursor-control, or OSC window-title sequences.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const vitest_1 = require("vitest");
9
+ const ansi_1 = require("./ansi");
10
+ (0, vitest_1.describe)('stripAnsi', () => {
11
+ (0, vitest_1.it)('removes SGR color codes (single and multi-param)', () => {
12
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b[32mgreen\x1b[0m')).toBe('green');
13
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b[38;2;255;0;0m rgb \x1b[39m')).toBe(' rgb ');
14
+ });
15
+ (0, vitest_1.it)('removes cursor-control and clear-line sequences (progress bars)', () => {
16
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b[2K\x1b[1A\x1b[2Kprogress 50%')).toBe('progress 50%');
17
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b[?25l\x1b[?25h')).toBe('');
18
+ });
19
+ (0, vitest_1.it)('removes OSC window-title sequences', () => {
20
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b]0;my title\x07content')).toBe('content');
21
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('\x1b]0;another\x1b\\tail')).toBe('tail');
22
+ });
23
+ (0, vitest_1.it)('leaves plain text untouched', () => {
24
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('plain output 123')).toBe('plain output 123');
25
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)('')).toBe('');
26
+ });
27
+ (0, vitest_1.it)('handles mixed lines with multiple sequences', () => {
28
+ const line = '\x1b[1mBOLD\x1b[22m \x1b[31mRED\x1b[0m \x1b[2Kdone';
29
+ (0, vitest_1.expect)((0, ansi_1.stripAnsi)(line)).toBe('BOLD RED done');
30
+ });
31
+ });
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ // @vitest-environment jsdom
3
+ // (token persistence uses localStorage — jsdom; the file-extension default is node)
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ /**
6
+ * Admin write-surface API tests (Session 18).
7
+ *
8
+ * Covers the auth gate + provider write methods on DashboardAPI: auth-status
9
+ * parsing, login/setup persisting the Bearer token, save/delete/test provider
10
+ * sending the token + parsing the (possibly masked) refreshed row, 401 error
11
+ * propagation (the session-expired signal the panel needs), and the same
12
+ * stale-server HTML-200 degradation every other dashboard fetch has.
13
+ */
14
+ const vitest_1 = require("vitest");
15
+ const api_1 = require("./api");
16
+ const jsonResponse = (data, status = 200) => new Response(JSON.stringify(data), {
17
+ status,
18
+ headers: { 'Content-Type': 'application/json' },
19
+ });
20
+ const htmlResponse = () => new Response('<!DOCTYPE html><html><body>SPA fallback</body></html>', {
21
+ status: 200,
22
+ headers: { 'Content-Type': 'text/html' },
23
+ });
24
+ const AUTHED = { configured: true, authenticated: true, user: 'admin', role: 'admin' };
25
+ const USERS = [
26
+ { user: 'admin', role: 'admin', createdAt: 100 },
27
+ { user: 'view', role: 'viewer', createdAt: 200 },
28
+ ];
29
+ const ROW = { type: 'groq', configured: true, keySource: 'config', keyMasked: 'gsk_…abcd', model: 'm1', baseUrl: 'https://api.groq.com' };
30
+ (0, vitest_1.describe)('DashboardAPI admin auth surface', () => {
31
+ (0, vitest_1.afterEach)(() => {
32
+ vitest_1.vi.restoreAllMocks();
33
+ (0, api_1.setAdminToken)(null);
34
+ });
35
+ (0, vitest_1.it)('parses /api/admin/auth-status (configured + authenticated)', async () => {
36
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse(AUTHED));
37
+ const api = new api_1.DashboardAPI('http://test');
38
+ (0, vitest_1.expect)(await api.fetchAdminAuthStatus()).toEqual(AUTHED);
39
+ });
40
+ (0, vitest_1.it)('returns null for a stale server answering HTML — no crash', async () => {
41
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(htmlResponse());
42
+ const api = new api_1.DashboardAPI('http://test');
43
+ (0, vitest_1.expect)(await api.fetchAdminAuthStatus()).toBeNull();
44
+ });
45
+ (0, vitest_1.it)('login persists the token and clears it on logout', async () => {
46
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, user: 'admin', token: 'tok-1' }));
47
+ const api = new api_1.DashboardAPI('http://test');
48
+ const r = await api.adminLogin('admin', 'secret-pass');
49
+ (0, vitest_1.expect)(r.ok).toBe(true);
50
+ (0, vitest_1.expect)((0, api_1.getAdminToken)()).toBe('tok-1');
51
+ await api.adminLogout();
52
+ (0, vitest_1.expect)((0, api_1.getAdminToken)()).toBeNull();
53
+ });
54
+ (0, vitest_1.it)('login surfaces the 401 error message (wrong password) without persisting a token', async () => {
55
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: false, error: 'Invalid username or password.' }, 401));
56
+ const api = new api_1.DashboardAPI('http://test');
57
+ const r = await api.adminLogin('admin', 'wrong');
58
+ (0, vitest_1.expect)(r.ok).toBe(false);
59
+ (0, vitest_1.expect)(r.unauthorized).toBe(true);
60
+ (0, vitest_1.expect)(r.error).toContain('Invalid');
61
+ (0, vitest_1.expect)((0, api_1.getAdminToken)()).toBeNull();
62
+ });
63
+ (0, vitest_1.it)('setup persists the token on success', async () => {
64
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, user: 'admin', token: 'tok-setup' }));
65
+ const api = new api_1.DashboardAPI('http://test');
66
+ const r = await api.adminSetup('admin', 'long-enough-pass');
67
+ (0, vitest_1.expect)(r.ok).toBe(true);
68
+ (0, vitest_1.expect)((0, api_1.getAdminToken)()).toBe('tok-setup');
69
+ });
70
+ });
71
+ (0, vitest_1.describe)('DashboardAPI provider write surface', () => {
72
+ (0, vitest_1.afterEach)(() => {
73
+ vitest_1.vi.restoreAllMocks();
74
+ (0, api_1.setAdminToken)(null);
75
+ });
76
+ const expectAuthHeader = (input, init) => {
77
+ (0, vitest_1.expect)(String(input)).toContain('/api/admin/providers/groq');
78
+ (0, vitest_1.expect)(init?.headers).toMatchObject({ Authorization: 'Bearer tok-auth' });
79
+ };
80
+ (0, vitest_1.it)('saveProvider sends the token and returns the refreshed masked row', async () => {
81
+ (0, api_1.setAdminToken)('tok-auth');
82
+ const spy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, provider: ROW }));
83
+ const api = new api_1.DashboardAPI('http://test');
84
+ const r = await api.saveProvider('groq', { apiKey: 'gsk_new', baseUrl: 'https://api.groq.com' });
85
+ (0, vitest_1.expect)(r.ok).toBe(true);
86
+ (0, vitest_1.expect)(r.provider?.keyMasked).toBe('gsk_…abcd');
87
+ (0, vitest_1.expect)(spy).toHaveBeenCalledTimes(1);
88
+ const [input, init] = spy.mock.calls[0];
89
+ expectAuthHeader(input, init);
90
+ (0, vitest_1.expect)(JSON.parse(init.body)).toMatchObject({ apiKey: 'gsk_new' });
91
+ });
92
+ (0, vitest_1.it)('saveProvider without a token reports unauthorized (401) so the panel shows login', async () => {
93
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: false, error: 'Not authenticated — log in first.' }, 401));
94
+ const api = new api_1.DashboardAPI('http://test');
95
+ const r = await api.saveProvider('groq', { apiKey: 'x' });
96
+ (0, vitest_1.expect)(r.ok).toBe(false);
97
+ (0, vitest_1.expect)(r.unauthorized).toBe(true);
98
+ });
99
+ (0, vitest_1.it)('deleteProvider returns ok + the cleared row', async () => {
100
+ (0, api_1.setAdminToken)('tok-auth');
101
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, cleared: true, provider: { ...ROW, configured: false, keySource: 'none', keyMasked: null } }));
102
+ const api = new api_1.DashboardAPI('http://test');
103
+ const r = await api.deleteProvider('groq');
104
+ (0, vitest_1.expect)(r.ok).toBe(true);
105
+ (0, vitest_1.expect)(r.cleared).toBe(true);
106
+ });
107
+ (0, vitest_1.it)('testProvider parses the model list on success and the error message on failure', async () => {
108
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, models: ['llama-3.3-70b', 'mixtral'] }));
109
+ const api = new api_1.DashboardAPI('http://test');
110
+ const ok = await api.testProvider('groq');
111
+ (0, vitest_1.expect)(ok.ok).toBe(true);
112
+ (0, vitest_1.expect)(ok.models).toHaveLength(2);
113
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: false, error: '401 invalid key' }));
114
+ const bad = await api.testProvider('nim');
115
+ (0, vitest_1.expect)(bad.ok).toBe(false);
116
+ (0, vitest_1.expect)(bad.error).toContain('401');
117
+ });
118
+ (0, vitest_1.it)('degrades to a network-failure message (never throws)', async () => {
119
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockRejectedValue(new TypeError('Failed to fetch'));
120
+ const api = new api_1.DashboardAPI('http://test');
121
+ const r = await api.saveProvider('groq', { apiKey: 'x' });
122
+ (0, vitest_1.expect)(r.ok).toBe(false);
123
+ (0, vitest_1.expect)(r.error).toMatch(/reach/i);
124
+ });
125
+ });
126
+ (0, vitest_1.describe)('DashboardAPI user management (role.manage)', () => {
127
+ (0, vitest_1.afterEach)(() => {
128
+ vitest_1.vi.restoreAllMocks();
129
+ (0, api_1.setAdminToken)(null);
130
+ });
131
+ (0, vitest_1.it)('fetchAdminUsers parses the user list with the token attached', async () => {
132
+ (0, api_1.setAdminToken)('tok-auth');
133
+ const spy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, users: USERS }));
134
+ const api = new api_1.DashboardAPI('http://test');
135
+ const r = await api.fetchAdminUsers();
136
+ (0, vitest_1.expect)(r.ok).toBe(true);
137
+ (0, vitest_1.expect)(r.users).toHaveLength(2);
138
+ (0, vitest_1.expect)(r.users[0]).toMatchObject({ user: 'admin', role: 'admin' });
139
+ const [input, init] = spy.mock.calls[0];
140
+ (0, vitest_1.expect)(String(input)).toContain('/api/admin/users');
141
+ (0, vitest_1.expect)(init?.headers).toMatchObject({ Authorization: 'Bearer tok-auth' });
142
+ });
143
+ (0, vitest_1.it)('addAdminUser POSTs user/password/role and clears the form state on success', async () => {
144
+ (0, api_1.setAdminToken)('tok-auth');
145
+ const spy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true }));
146
+ const api = new api_1.DashboardAPI('http://test');
147
+ const r = await api.addAdminUser('view', 'viewer-pass-12', 'viewer');
148
+ (0, vitest_1.expect)(r.ok).toBe(true);
149
+ const [input, init] = spy.mock.calls[0];
150
+ (0, vitest_1.expect)(String(input)).toContain('/api/admin/users');
151
+ (0, vitest_1.expect)(JSON.parse(init.body)).toEqual({ user: 'view', password: 'viewer-pass-12', role: 'viewer' });
152
+ });
153
+ (0, vitest_1.it)('reports forbidden (403) when the role may not manage users', async () => {
154
+ (0, api_1.setAdminToken)('tok-viewer');
155
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: false, error: "Access denied — role 'viewer' cannot manage users (requires admin)." }, 403));
156
+ const api = new api_1.DashboardAPI('http://test');
157
+ const r = await api.fetchAdminUsers();
158
+ (0, vitest_1.expect)(r.ok).toBe(false);
159
+ (0, vitest_1.expect)(r.forbidden).toBe(true);
160
+ (0, vitest_1.expect)(r.error).toContain('Access denied');
161
+ });
162
+ (0, vitest_1.it)('removeAdminUser DELETEs by name', async () => {
163
+ (0, api_1.setAdminToken)('tok-auth');
164
+ const spy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ ok: true, removed: true }));
165
+ const api = new api_1.DashboardAPI('http://test');
166
+ const r = await api.removeAdminUser('view');
167
+ (0, vitest_1.expect)(r.ok).toBe(true);
168
+ const [input, init] = spy.mock.calls[0];
169
+ (0, vitest_1.expect)(String(input)).toContain('/api/admin/users/view');
170
+ (0, vitest_1.expect)(init?.method).toBe('DELETE');
171
+ });
172
+ });
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Admin command-runner fetch tests (Session 17).
4
+ *
5
+ * fetchAdminChecks() drives the dashboard's /api/admin/checks endpoint — the
6
+ * on-demand execution of ALL state commands (doctor system + enterprise
7
+ * checks + masked provider summary). Regression coverage for the same
8
+ * parseJsonOrNull contract every other dashboard fetch uses: a stale server
9
+ * answering HTML must degrade to null, never crash.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const api_1 = require("./api");
14
+ const jsonResponse = (data) => new Response(JSON.stringify(data), {
15
+ status: 200,
16
+ headers: { 'Content-Type': 'application/json' },
17
+ });
18
+ const htmlResponse = () => new Response('<!DOCTYPE html><html><body>SPA fallback</body></html>', {
19
+ status: 200,
20
+ headers: { 'Content-Type': 'text/html' },
21
+ });
22
+ const VALID_PAYLOAD = {
23
+ system: [{ name: 'Config Directory', status: 'pass', message: '~/.nuvira/ exists' }],
24
+ enterprise: [{ name: 'Secrets Backend', status: 'warn', message: 'keys in config' }],
25
+ providers: [{ type: 'groq', configured: true, keySource: 'env', keyMasked: 'gsk_…abcd' }],
26
+ serverTime: 123,
27
+ };
28
+ (0, vitest_1.describe)('DashboardAPI.fetchAdminChecks', () => {
29
+ (0, vitest_1.afterEach)(() => {
30
+ vitest_1.vi.restoreAllMocks();
31
+ });
32
+ (0, vitest_1.it)('parses a real /api/admin/checks response', async () => {
33
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse(VALID_PAYLOAD));
34
+ const api = new api_1.DashboardAPI('http://test');
35
+ const data = await api.fetchAdminChecks();
36
+ (0, vitest_1.expect)(data).toMatchObject({ serverTime: 123 });
37
+ (0, vitest_1.expect)(data.system[0].status).toBe('pass');
38
+ (0, vitest_1.expect)(data.providers[0].keySource).toBe('env');
39
+ });
40
+ (0, vitest_1.it)('returns null when the server answers HTML (stale server) — no crash', async () => {
41
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(htmlResponse());
42
+ const api = new api_1.DashboardAPI('http://test');
43
+ const data = await api.fetchAdminChecks();
44
+ (0, vitest_1.expect)(data).toBeNull();
45
+ });
46
+ (0, vitest_1.it)('returns null when the payload lacks the checks arrays', async () => {
47
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({ serverTime: 1 }));
48
+ const api = new api_1.DashboardAPI('http://test');
49
+ (0, vitest_1.expect)(await api.fetchAdminChecks()).toBeNull();
50
+ });
51
+ (0, vitest_1.it)('returns null when the payload lacks the providers array (panel would crash on .length)', async () => {
52
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse({
53
+ system: [],
54
+ enterprise: [],
55
+ serverTime: 1,
56
+ }));
57
+ const api = new api_1.DashboardAPI('http://test');
58
+ (0, vitest_1.expect)(await api.fetchAdminChecks()).toBeNull();
59
+ });
60
+ (0, vitest_1.it)('returns null on network failure', async () => {
61
+ vitest_1.vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('down'));
62
+ const api = new api_1.DashboardAPI('http://test');
63
+ (0, vitest_1.expect)(await api.fetchAdminChecks()).toBeNull();
64
+ });
65
+ });