From c4f5e04d83cf4f65b089e97097123a5afaa9ebf1 Mon Sep 17 00:00:00 2001 From: anandgupta42 <93243293+anandgupta42@users.noreply.github.com> Date: Mon, 23 Mar 2026 01:15:36 -0700 Subject: [PATCH] =?UTF-8?q?test:=20finops=20+=20tool-lookup=20=E2=80=94=20?= =?UTF-8?q?RBAC=20formatting=20and=20Zod=20schema=20introspection=20covera?= =?UTF-8?q?ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 14 tests for two untested modules: tool_lookup Zod schema introspection (used by the agent to discover tool contracts) and finops role-access formatting functions (renders RBAC grants, hierarchy, and user-role assignments for audits). Co-Authored-By: Claude Opus 4.6 (1M context) https://claude.ai/code/session_01PnbJpBRPw8DrqSBDxhrCjg --- .../test/altimate/finops-role-access.test.ts | 248 ++++++++++++++++++ .../test/altimate/tool-lookup.test.ts | 149 +++++++++++ 2 files changed, 397 insertions(+) create mode 100644 packages/opencode/test/altimate/finops-role-access.test.ts create mode 100644 packages/opencode/test/altimate/tool-lookup.test.ts diff --git a/packages/opencode/test/altimate/finops-role-access.test.ts b/packages/opencode/test/altimate/finops-role-access.test.ts new file mode 100644 index 000000000..b213bfdd8 --- /dev/null +++ b/packages/opencode/test/altimate/finops-role-access.test.ts @@ -0,0 +1,248 @@ +/** + * Tests for finops role-access formatting functions: + * formatGrants, formatHierarchy, formatUserRoles. + * + * These render RBAC data as markdown tables. Incorrect output + * could cause data engineers to miss security issues during audits. + * Tests use Dispatcher.call spying to supply known RBAC data. + */ +import { describe, test, expect, spyOn, afterAll, beforeEach } from "bun:test" +import * as Dispatcher from "../../src/altimate/native/dispatcher" +import { + FinopsRoleGrantsTool, + FinopsRoleHierarchyTool, + FinopsUserRolesTool, +} from "../../src/altimate/tools/finops-role-access" +import { SessionID, MessageID } from "../../src/session/schema" + +beforeEach(() => { + process.env.ALTIMATE_TELEMETRY_DISABLED = "true" +}) +afterAll(() => { + delete process.env.ALTIMATE_TELEMETRY_DISABLED +}) + +const ctx = { + sessionID: SessionID.make("ses_test"), + messageID: MessageID.make("msg_test"), + callID: "call_test", + agent: "build", + abort: AbortSignal.any([]), + messages: [], + metadata: () => {}, + ask: async () => {}, +} + +let dispatcherSpy: ReturnType + +function mockDispatcher(responses: Record) { + dispatcherSpy?.mockRestore() + dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => { + if (responses[method]) return responses[method] + throw new Error(`No mock for ${method}`) + }) +} + +afterAll(() => { + dispatcherSpy?.mockRestore() +}) + +describe("formatGrants: privilege summary and grant rows", () => { + test("renders privilege summary and grant table with standard Snowflake fields", async () => { + mockDispatcher({ + "finops.role_grants": { + success: true, + grant_count: 2, + privilege_summary: { SELECT: 2, INSERT: 1 }, + grants: [ + { grantee_name: "ANALYST", privilege: "SELECT", object_type: "TABLE", object_name: "orders" }, + { grantee_name: "ADMIN", privilege: "INSERT", object_type: "TABLE", object_name: "users" }, + ], + }, + }) + + const tool = await FinopsRoleGrantsTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + expect(result.title).toContain("2 found") + expect(result.output).toContain("Privilege Summary") + expect(result.output).toContain("SELECT: 2") + expect(result.output).toContain("INSERT: 1") + expect(result.output).toContain("ANALYST | SELECT | TABLE | orders") + expect(result.output).toContain("ADMIN | INSERT | TABLE | users") + }) + + test("uses fallback field aliases (role, granted_on, name)", async () => { + mockDispatcher({ + "finops.role_grants": { + success: true, + grant_count: 1, + privilege_summary: {}, + grants: [ + { role: "DBA", privilege: "USAGE", granted_on: "WAREHOUSE", name: "compute_wh" }, + ], + }, + }) + + const tool = await FinopsRoleGrantsTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + // formatGrants should fall back to r.role, r.granted_on, r.name + expect(result.output).toContain("DBA | USAGE | WAREHOUSE | compute_wh") + }) + + test("handles empty grants array", async () => { + mockDispatcher({ + "finops.role_grants": { + success: true, + grant_count: 0, + privilege_summary: {}, + grants: [], + }, + }) + + const tool = await FinopsRoleGrantsTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + expect(result.output).toContain("No grants found") + }) + + test("returns error message on Dispatcher failure", async () => { + mockDispatcher({ + "finops.role_grants": { + success: false, + error: "Connection refused", + }, + }) + + const tool = await FinopsRoleGrantsTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + expect(result.title).toContain("FAILED") + expect(result.output).toContain("Connection refused") + }) +}) + +describe("formatHierarchy: recursive role tree rendering", () => { + test("renders two-level nested hierarchy with children key", async () => { + mockDispatcher({ + "finops.role_hierarchy": { + success: true, + role_count: 3, + hierarchy: [ + { + name: "SYSADMIN", + children: [ + { name: "DBA", children: [] }, + { name: "ANALYST", children: [] }, + ], + }, + ], + }, + }) + + const tool = await FinopsRoleHierarchyTool.init() + const result = await tool.execute({ warehouse: "test_wh" }, ctx as any) + + expect(result.title).toContain("3 roles") + expect(result.output).toContain("Role Hierarchy") + expect(result.output).toContain("SYSADMIN") + expect(result.output).toContain("-> DBA") + expect(result.output).toContain("-> ANALYST") + }) + + test("uses granted_roles fallback alias for children", async () => { + mockDispatcher({ + "finops.role_hierarchy": { + success: true, + role_count: 2, + hierarchy: [ + { + role: "ACCOUNTADMIN", + granted_roles: [{ role: "SECURITYADMIN" }], + }, + ], + }, + }) + + const tool = await FinopsRoleHierarchyTool.init() + const result = await tool.execute({ warehouse: "test_wh" }, ctx as any) + + // Should use r.role as name and r.granted_roles as children + expect(result.output).toContain("ACCOUNTADMIN") + expect(result.output).toContain("-> SECURITYADMIN") + }) + + test("handles empty hierarchy", async () => { + mockDispatcher({ + "finops.role_hierarchy": { + success: true, + role_count: 0, + hierarchy: [], + }, + }) + + const tool = await FinopsRoleHierarchyTool.init() + const result = await tool.execute({ warehouse: "test_wh" }, ctx as any) + + expect(result.output).toContain("Role Hierarchy") + // No roles rendered but header is present + expect(result.output).not.toContain("->") + }) +}) + +describe("formatUserRoles: user-role assignment table", () => { + test("renders user assignments with standard fields", async () => { + mockDispatcher({ + "finops.user_roles": { + success: true, + assignment_count: 2, + assignments: [ + { grantee_name: "alice@corp.com", role: "ANALYST", granted_by: "SECURITYADMIN" }, + { grantee_name: "bob@corp.com", role: "DBA", granted_by: "ACCOUNTADMIN" }, + ], + }, + }) + + const tool = await FinopsUserRolesTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + expect(result.title).toContain("2 assignments") + expect(result.output).toContain("User Role Assignments") + expect(result.output).toContain("alice@corp.com | ANALYST | SECURITYADMIN") + expect(result.output).toContain("bob@corp.com | DBA | ACCOUNTADMIN") + }) + + test("uses fallback aliases (user_name, role_name, grantor)", async () => { + mockDispatcher({ + "finops.user_roles": { + success: true, + assignment_count: 1, + assignments: [ + { user_name: "charlie", role_name: "READER", grantor: "ADMIN" }, + ], + }, + }) + + const tool = await FinopsUserRolesTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + // Falls back to r.user_name (via user fallback chain), r.role_name, r.grantor + expect(result.output).toContain("charlie | READER | ADMIN") + }) + + test("handles empty assignments", async () => { + mockDispatcher({ + "finops.user_roles": { + success: true, + assignment_count: 0, + assignments: [], + }, + }) + + const tool = await FinopsUserRolesTool.init() + const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any) + + expect(result.output).toContain("No user role assignments found") + }) +}) diff --git a/packages/opencode/test/altimate/tool-lookup.test.ts b/packages/opencode/test/altimate/tool-lookup.test.ts new file mode 100644 index 000000000..2f27ca111 --- /dev/null +++ b/packages/opencode/test/altimate/tool-lookup.test.ts @@ -0,0 +1,149 @@ +/** + * Tests for the tool_lookup tool — Zod schema introspection + * (describeZodSchema, inferZodType, unwrap, getShape). + * + * The agent uses tool_lookup to discover other tools' parameter contracts. + * Incorrect introspection leads to wrong tool calls. + */ +import { describe, test, expect, beforeEach, afterAll } from "bun:test" +import z from "zod" +import { ToolLookupTool } from "../../src/altimate/tools/tool-lookup" +import { ToolRegistry } from "../../src/tool/registry" +import { Instance } from "../../src/project/instance" +import { tmpdir } from "../fixture/fixture" +import { SessionID, MessageID } from "../../src/session/schema" + +beforeEach(() => { + process.env.ALTIMATE_TELEMETRY_DISABLED = "true" +}) +afterAll(() => { + delete process.env.ALTIMATE_TELEMETRY_DISABLED +}) + +const ctx = { + sessionID: SessionID.make("ses_test"), + messageID: MessageID.make("msg_test"), + callID: "call_test", + agent: "build", + abort: AbortSignal.any([]), + messages: [], + metadata: () => {}, + ask: async () => {}, +} + +describe("ToolLookupTool: Zod schema introspection", () => { + test("returns parameter info for tool with mixed types", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const testTool = { + id: "__test_lookup_mixed", + init: async () => ({ + description: "Test tool with mixed params", + parameters: z.object({ + name: z.string().describe("The name"), + count: z.number().describe("How many"), + verbose: z.boolean().optional().describe("Enable verbosity"), + tags: z.array(z.string()).describe("Tags list"), + mode: z.enum(["fast", "slow"]).default("fast").describe("Execution mode"), + }), + execute: async () => ({ title: "", output: "", metadata: {} }), + }), + } + await ToolRegistry.register(testTool) + + const tool = await ToolLookupTool.init() + const result = await tool.execute({ tool_name: "__test_lookup_mixed" }, ctx as any) + + // Required string param + expect(result.output).toContain("name") + expect(result.output).toContain("string") + expect(result.output).toContain("required") + expect(result.output).toContain("The name") + + // Number param + expect(result.output).toContain("count") + expect(result.output).toContain("number") + + // Optional boolean + expect(result.output).toContain("verbose") + expect(result.output).toContain("optional") + + // Array param + expect(result.output).toContain("tags") + expect(result.output).toContain("array") + + // Enum with default — inferZodType unwraps default then hits enum + expect(result.output).toContain("mode") + expect(result.output).toContain("enum") + }, + }) + }) + + test("returns 'Tool not found' with available tools list", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const tool = await ToolLookupTool.init() + const result = await tool.execute({ tool_name: "nonexistent_tool_xyz" }, ctx as any) + expect(result.title).toBe("Tool not found") + expect(result.output).toContain('No tool named "nonexistent_tool_xyz"') + expect(result.output).toContain("Available tools:") + }, + }) + }) + + test("handles tool with empty parameters object", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const testTool = { + id: "__test_lookup_empty", + init: async () => ({ + description: "Tool with empty params", + parameters: z.object({}), + execute: async () => ({ title: "", output: "", metadata: {} }), + }), + } + await ToolRegistry.register(testTool) + + const tool = await ToolLookupTool.init() + const result = await tool.execute({ tool_name: "__test_lookup_empty" }, ctx as any) + expect(result.output).toContain("No parameters") + }, + }) + }) + + test("unwraps nested optional/default wrappers correctly", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const testTool = { + id: "__test_lookup_nested", + init: async () => ({ + description: "Tool with nested wrappers", + parameters: z.object({ + // default wrapping optional wrapping string + deep: z.string().optional().default("hello").describe("Deeply wrapped"), + }), + execute: async () => ({ title: "", output: "", metadata: {} }), + }), + } + await ToolRegistry.register(testTool) + + const tool = await ToolLookupTool.init() + const result = await tool.execute({ tool_name: "__test_lookup_nested" }, ctx as any) + + // Should unwrap to the inner string type + expect(result.output).toContain("deep") + expect(result.output).toContain("Deeply wrapped") + // The outer wrapper is default, so it should show as optional + expect(result.output).toContain("optional") + }, + }) + }) +})