Skip to content

Commit 7e4182c

Browse files
authored
Merge branch 'main' into fix/dbt-tools-esm-package-json
2 parents 210a95f + 6b7070d commit 7e4182c

15 files changed

Lines changed: 1739 additions & 4 deletions
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
export function formatBytes(bytes: number): string {
22
if (bytes === 0) return "0 B"
3+
if (!Number.isFinite(bytes)) return "0 B"
4+
const abs = Math.abs(bytes)
35
const units = ["B", "KB", "MB", "GB", "TB", "PB"]
4-
const i = Math.floor(Math.log(bytes) / Math.log(1024))
6+
const i = Math.max(0, Math.min(Math.floor(Math.log(abs) / Math.log(1024)), units.length - 1))
57
const value = bytes / Math.pow(1024, i)
68
return `${value.toFixed(i === 0 ? 0 : 2)} ${units[i]}`
79
}
810

911
export function truncateQuery(text: string, maxLen: number): string {
1012
if (!text) return "(empty)"
1113
const oneLine = text.replace(/\s+/g, " ").trim()
14+
if (!oneLine) return "(empty)"
15+
if (maxLen <= 0) return ""
16+
if (maxLen < 4) return oneLine.slice(0, maxLen)
1217
if (oneLine.length <= maxLen) return oneLine
1318
return oneLine.slice(0, maxLen - 3) + "..."
1419
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/**
2+
* Tests for finops role-access formatting functions:
3+
* formatGrants, formatHierarchy, formatUserRoles.
4+
*
5+
* These render RBAC data as markdown tables. Incorrect output
6+
* could cause data engineers to miss security issues during audits.
7+
* Tests use Dispatcher.call spying to supply known RBAC data.
8+
*/
9+
import { describe, test, expect, spyOn, afterAll, beforeEach } from "bun:test"
10+
import * as Dispatcher from "../../src/altimate/native/dispatcher"
11+
import {
12+
FinopsRoleGrantsTool,
13+
FinopsRoleHierarchyTool,
14+
FinopsUserRolesTool,
15+
} from "../../src/altimate/tools/finops-role-access"
16+
import { SessionID, MessageID } from "../../src/session/schema"
17+
18+
beforeEach(() => {
19+
process.env.ALTIMATE_TELEMETRY_DISABLED = "true"
20+
})
21+
22+
const ctx = {
23+
sessionID: SessionID.make("ses_test"),
24+
messageID: MessageID.make("msg_test"),
25+
callID: "call_test",
26+
agent: "build",
27+
abort: AbortSignal.any([]),
28+
messages: [],
29+
metadata: () => {},
30+
ask: async () => {},
31+
}
32+
33+
let dispatcherSpy: ReturnType<typeof spyOn>
34+
35+
function mockDispatcher(responses: Record<string, any>) {
36+
dispatcherSpy?.mockRestore()
37+
dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => {
38+
if (responses[method]) return responses[method]
39+
throw new Error(`No mock for ${method}`)
40+
})
41+
}
42+
43+
afterAll(() => {
44+
dispatcherSpy?.mockRestore()
45+
delete process.env.ALTIMATE_TELEMETRY_DISABLED
46+
})
47+
48+
describe("formatGrants: privilege summary and grant rows", () => {
49+
test("renders privilege summary and grant table with standard Snowflake fields", async () => {
50+
mockDispatcher({
51+
"finops.role_grants": {
52+
success: true,
53+
grant_count: 2,
54+
privilege_summary: { SELECT: 2, INSERT: 1 },
55+
grants: [
56+
{ grantee_name: "ANALYST", privilege: "SELECT", object_type: "TABLE", object_name: "orders" },
57+
{ grantee_name: "ADMIN", privilege: "INSERT", object_type: "TABLE", object_name: "users" },
58+
],
59+
},
60+
})
61+
62+
const tool = await FinopsRoleGrantsTool.init()
63+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
64+
65+
expect(result.title).toContain("2 found")
66+
expect(result.output).toContain("Privilege Summary")
67+
expect(result.output).toContain("SELECT: 2")
68+
expect(result.output).toContain("INSERT: 1")
69+
expect(result.output).toContain("ANALYST | SELECT | TABLE | orders")
70+
expect(result.output).toContain("ADMIN | INSERT | TABLE | users")
71+
})
72+
73+
test("uses fallback field aliases (role, granted_on, name)", async () => {
74+
mockDispatcher({
75+
"finops.role_grants": {
76+
success: true,
77+
grant_count: 1,
78+
privilege_summary: {},
79+
grants: [
80+
{ role: "DBA", privilege: "USAGE", granted_on: "WAREHOUSE", name: "compute_wh" },
81+
],
82+
},
83+
})
84+
85+
const tool = await FinopsRoleGrantsTool.init()
86+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
87+
88+
// formatGrants should fall back to r.role, r.granted_on, r.name
89+
expect(result.output).toContain("DBA | USAGE | WAREHOUSE | compute_wh")
90+
})
91+
92+
test("handles empty grants array", async () => {
93+
mockDispatcher({
94+
"finops.role_grants": {
95+
success: true,
96+
grant_count: 0,
97+
privilege_summary: {},
98+
grants: [],
99+
},
100+
})
101+
102+
const tool = await FinopsRoleGrantsTool.init()
103+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
104+
105+
expect(result.output).toContain("No grants found")
106+
})
107+
108+
test("returns error message on Dispatcher failure", async () => {
109+
mockDispatcher({
110+
"finops.role_grants": {
111+
success: false,
112+
error: "Connection refused",
113+
},
114+
})
115+
116+
const tool = await FinopsRoleGrantsTool.init()
117+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
118+
119+
expect(result.title).toContain("FAILED")
120+
expect(result.output).toContain("Connection refused")
121+
})
122+
})
123+
124+
describe("formatHierarchy: recursive role tree rendering", () => {
125+
test("renders two-level nested hierarchy with children key", async () => {
126+
mockDispatcher({
127+
"finops.role_hierarchy": {
128+
success: true,
129+
role_count: 3,
130+
hierarchy: [
131+
{
132+
name: "SYSADMIN",
133+
children: [
134+
{ name: "DBA", children: [] },
135+
{ name: "ANALYST", children: [] },
136+
],
137+
},
138+
],
139+
},
140+
})
141+
142+
const tool = await FinopsRoleHierarchyTool.init()
143+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
144+
145+
expect(result.title).toContain("3 roles")
146+
expect(result.output).toContain("Role Hierarchy")
147+
expect(result.output).toContain("SYSADMIN")
148+
expect(result.output).toContain("-> DBA")
149+
expect(result.output).toContain("-> ANALYST")
150+
})
151+
152+
test("uses granted_roles fallback alias for children", async () => {
153+
mockDispatcher({
154+
"finops.role_hierarchy": {
155+
success: true,
156+
role_count: 2,
157+
hierarchy: [
158+
{
159+
role: "ACCOUNTADMIN",
160+
granted_roles: [{ role: "SECURITYADMIN" }],
161+
},
162+
],
163+
},
164+
})
165+
166+
const tool = await FinopsRoleHierarchyTool.init()
167+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
168+
169+
// Should use r.role as name and r.granted_roles as children
170+
expect(result.output).toContain("ACCOUNTADMIN")
171+
expect(result.output).toContain("-> SECURITYADMIN")
172+
})
173+
174+
test("handles empty hierarchy", async () => {
175+
mockDispatcher({
176+
"finops.role_hierarchy": {
177+
success: true,
178+
role_count: 0,
179+
hierarchy: [],
180+
},
181+
})
182+
183+
const tool = await FinopsRoleHierarchyTool.init()
184+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
185+
186+
expect(result.output).toContain("Role Hierarchy")
187+
// No roles rendered but header is present
188+
expect(result.output).not.toContain("->")
189+
})
190+
})
191+
192+
describe("formatUserRoles: user-role assignment table", () => {
193+
test("renders user assignments with standard fields", async () => {
194+
mockDispatcher({
195+
"finops.user_roles": {
196+
success: true,
197+
assignment_count: 2,
198+
assignments: [
199+
{ grantee_name: "alice@corp.com", role: "ANALYST", granted_by: "SECURITYADMIN" },
200+
{ grantee_name: "bob@corp.com", role: "DBA", granted_by: "ACCOUNTADMIN" },
201+
],
202+
},
203+
})
204+
205+
const tool = await FinopsUserRolesTool.init()
206+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
207+
208+
expect(result.title).toContain("2 assignments")
209+
expect(result.output).toContain("User Role Assignments")
210+
expect(result.output).toContain("alice@corp.com | ANALYST | SECURITYADMIN")
211+
expect(result.output).toContain("bob@corp.com | DBA | ACCOUNTADMIN")
212+
})
213+
214+
test("uses fallback aliases (user_name, role_name, grantor)", async () => {
215+
mockDispatcher({
216+
"finops.user_roles": {
217+
success: true,
218+
assignment_count: 1,
219+
assignments: [
220+
{ user_name: "charlie", role_name: "READER", grantor: "ADMIN" },
221+
],
222+
},
223+
})
224+
225+
const tool = await FinopsUserRolesTool.init()
226+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
227+
228+
// Falls back to r.user_name (via user fallback chain), r.role_name, r.grantor
229+
expect(result.output).toContain("charlie | READER | ADMIN")
230+
})
231+
232+
test("handles empty assignments", async () => {
233+
mockDispatcher({
234+
"finops.user_roles": {
235+
success: true,
236+
assignment_count: 0,
237+
assignments: [],
238+
},
239+
})
240+
241+
const tool = await FinopsUserRolesTool.init()
242+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
243+
244+
expect(result.output).toContain("No user role assignments found")
245+
})
246+
})

0 commit comments

Comments
 (0)