kavachos 0.0.2 → 0.0.3

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.
@@ -1,4 +1,4 @@
1
- import { auditLogs, rateLimits } from './chunk-UEE7OYLG.js';
1
+ import { auditLogs, rateLimits } from './chunk-V66UUIA7.js';
2
2
  import { randomUUID } from 'crypto';
3
3
  import { and, eq, gte } from 'drizzle-orm';
4
4
 
@@ -247,5 +247,5 @@ function getPermissionTemplate(name) {
247
247
  }
248
248
 
249
249
  export { createPermissionEngine, getPermissionTemplate, permissionTemplates };
250
- //# sourceMappingURL=chunk-DEVV32BE.js.map
251
- //# sourceMappingURL=chunk-DEVV32BE.js.map
250
+ //# sourceMappingURL=chunk-OVGNZ5OX.js.map
251
+ //# sourceMappingURL=chunk-OVGNZ5OX.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/permission/engine.ts","../src/permission/templates.ts"],"names":["result"],"mappings":"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","file":"chunk-DEVV32BE.js","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { and, eq, gte } from \"drizzle-orm\";\nimport type { Database } from \"../db/database.js\";\nimport { auditLogs, rateLimits } from \"../db/schema.js\";\nimport type {\n\tAgentIdentity,\n\tAuthorizeRequest,\n\tAuthorizeResult,\n\tPermissionConstraints,\n} from \"../types.js\";\n\ninterface PermissionEngineConfig {\n\tdb: Database;\n\tauditAll: boolean;\n}\n\n/**\n * Match a resource pattern against a requested resource.\n *\n * Supports wildcards:\n * - \"mcp:github:*\" matches \"mcp:github:create_issue\"\n * - \"tool:*\" matches \"tool:file_read\"\n * - \"*\" matches everything\n */\nfunction matchResource(pattern: string, resource: string): boolean {\n\tif (pattern === \"*\") return true;\n\n\tconst patternParts = pattern.split(\":\");\n\tconst resourceParts = resource.split(\":\");\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst part = patternParts[i];\n\t\tif (part === \"*\") return true;\n\t\tif (part !== resourceParts[i]) return false;\n\t}\n\n\treturn patternParts.length === resourceParts.length;\n}\n\n/**\n * Check if an action is allowed by a permission's actions list.\n */\nfunction matchAction(allowedActions: string[], requestedAction: string): boolean {\n\treturn allowedActions.includes(requestedAction) || allowedActions.includes(\"*\");\n}\n\n/**\n * Parse an IPv4 address into a 32-bit integer.\n */\nfunction parseIPv4(ip: string): number | null {\n\tconst parts = ip.split(\".\");\n\tif (parts.length !== 4) return null;\n\tlet result = 0;\n\tfor (const part of parts) {\n\t\tconst num = parseInt(part, 10);\n\t\tif (Number.isNaN(num) || num < 0 || num > 255) return null;\n\t\tresult = (result << 8) | num;\n\t}\n\treturn result >>> 0;\n}\n\n/**\n * Check whether an IP matches a CIDR range or exact IP entry.\n * Supports both \"10.0.0.1\" and \"10.0.0.0/8\" notation (IPv4 only).\n */\nfunction matchesIPEntry(entry: string, ip: string): boolean {\n\tconst slashIndex = entry.indexOf(\"/\");\n\tif (slashIndex === -1) {\n\t\treturn entry === ip;\n\t}\n\n\tconst cidrIp = entry.slice(0, slashIndex);\n\tconst prefixLen = parseInt(entry.slice(slashIndex + 1), 10);\n\tif (Number.isNaN(prefixLen) || prefixLen < 0 || prefixLen > 32) return false;\n\n\tconst entryNum = parseIPv4(cidrIp);\n\tconst ipNum = parseIPv4(ip);\n\tif (entryNum === null || ipNum === null) return false;\n\n\tconst mask = prefixLen === 0 ? 0 : (~0 << (32 - prefixLen)) >>> 0;\n\treturn (entryNum & mask) === (ipNum & mask);\n}\n\n/**\n * Check whether an IP is in the allowlist (exact IPs or CIDR ranges).\n */\nfunction isIPAllowed(allowlist: string[], ip: string): boolean {\n\treturn allowlist.some((entry) => matchesIPEntry(entry, ip));\n}\n\n/**\n * Validate argument patterns against the request arguments.\n */\nfunction validateArgPatterns(\n\tpatterns: string[],\n\targs: Record<string, unknown>,\n): { valid: boolean; reason?: string } {\n\tfor (const pattern of patterns) {\n\t\tconst regex = new RegExp(pattern);\n\t\t// Check all string arguments against the pattern\n\t\tfor (const [key, value] of Object.entries(args)) {\n\t\t\tif (typeof value === \"string\" && !regex.test(value)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: `Argument \"${key}\" value \"${value}\" does not match pattern \"${pattern}\"`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\treturn { valid: true };\n}\n\n/**\n * Check rate limits for an agent on a specific resource.\n */\nasync function checkRateLimit(\n\tdb: Database,\n\tagentId: string,\n\tresource: string,\n\tmaxCallsPerHour: number,\n): Promise<{ allowed: boolean; reason?: string }> {\n\tconst oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);\n\n\tconst rows = await db\n\t\t.select()\n\t\t.from(rateLimits)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(rateLimits.agentId, agentId),\n\t\t\t\teq(rateLimits.resource, resource),\n\t\t\t\tgte(rateLimits.windowStart, oneHourAgo),\n\t\t\t),\n\t\t);\n\n\tconst totalCalls = rows.reduce((sum, r) => sum + r.count, 0);\n\n\tif (totalCalls >= maxCallsPerHour) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason: `Rate limit exceeded: ${totalCalls}/${maxCallsPerHour} calls per hour for resource \"${resource}\"`,\n\t\t};\n\t}\n\n\t// Increment counter\n\tconst currentWindow = new Date(Math.floor(Date.now() / (5 * 60 * 1000)) * (5 * 60 * 1000)); // 5-min windows\n\tconst existing = rows.find((r) => r.windowStart.getTime() === currentWindow.getTime());\n\n\tif (existing) {\n\t\tawait db\n\t\t\t.update(rateLimits)\n\t\t\t.set({ count: existing.count + 1 })\n\t\t\t.where(eq(rateLimits.id, existing.id));\n\t} else {\n\t\tawait db.insert(rateLimits).values({\n\t\t\tid: randomUUID(),\n\t\t\tagentId,\n\t\t\tresource,\n\t\t\twindowStart: currentWindow,\n\t\t\tcount: 1,\n\t\t});\n\t}\n\n\treturn { allowed: true };\n}\n\n/**\n * Create the permission/authorization engine.\n */\nexport function createPermissionEngine(config: PermissionEngineConfig) {\n\tconst { db, auditAll } = config;\n\n\t/**\n\t * Check if an agent is authorized to perform an action.\n\t * This is the core authorization function.\n\t */\n\tasync function authorize(\n\t\tagent: AgentIdentity,\n\t\trequest: AuthorizeRequest,\n\t): Promise<AuthorizeResult> {\n\t\tconst startTime = performance.now();\n\t\tconst auditId = randomUUID();\n\n\t\t// Find matching permission\n\t\tconst matchingPermission = agent.permissions.find(\n\t\t\t(p) => matchResource(p.resource, request.resource) && matchAction(p.actions, request.action),\n\t\t);\n\n\t\tif (!matchingPermission) {\n\t\t\tconst result: AuthorizeResult = {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `No permission grants agent \"${agent.name}\" access to \"${request.action}\" on \"${request.resource}\"`,\n\t\t\t\tauditId,\n\t\t\t};\n\t\t\tif (auditAll) {\n\t\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t// Check constraints\n\t\tif (matchingPermission.constraints) {\n\t\t\tconst constraintResult = await evaluateConstraints(\n\t\t\t\tdb,\n\t\t\t\tagent,\n\t\t\t\trequest,\n\t\t\t\tmatchingPermission.constraints,\n\t\t\t);\n\t\t\tif (!constraintResult.allowed) {\n\t\t\t\tconst result: AuthorizeResult = {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\treason: constraintResult.reason,\n\t\t\t\t\tauditId,\n\t\t\t\t};\n\t\t\t\tif (auditAll) {\n\t\t\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tconst result: AuthorizeResult = { allowed: true, auditId };\n\t\tif (auditAll) {\n\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn { authorize };\n}\n\nasync function evaluateConstraints(\n\tdb: Database,\n\tagent: AgentIdentity,\n\trequest: AuthorizeRequest,\n\tconstraints: PermissionConstraints,\n): Promise<{ allowed: boolean; reason?: string }> {\n\t// Rate limit check\n\tif (constraints.maxCallsPerHour) {\n\t\tconst rateResult = await checkRateLimit(\n\t\t\tdb,\n\t\t\tagent.id,\n\t\t\trequest.resource,\n\t\t\tconstraints.maxCallsPerHour,\n\t\t);\n\t\tif (!rateResult.allowed) {\n\t\t\treturn rateResult;\n\t\t}\n\t}\n\n\t// Argument pattern check\n\tif (constraints.allowedArgPatterns && request.arguments) {\n\t\tconst patternResult = validateArgPatterns(constraints.allowedArgPatterns, request.arguments);\n\t\tif (!patternResult.valid) {\n\t\t\treturn { allowed: false, reason: patternResult.reason };\n\t\t}\n\t}\n\n\t// Human-in-the-loop check\n\tif (constraints.requireApproval) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason: \"This action requires human approval before execution\",\n\t\t};\n\t}\n\n\t// Time window check\n\tif (constraints.timeWindow) {\n\t\tconst now = new Date();\n\t\tconst hours = now.getHours();\n\t\tconst minutes = now.getMinutes();\n\t\tconst currentTime = `${String(hours).padStart(2, \"0\")}:${String(minutes).padStart(2, \"0\")}`;\n\n\t\tif (currentTime < constraints.timeWindow.start || currentTime > constraints.timeWindow.end) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `Action is only allowed between ${constraints.timeWindow.start} and ${constraints.timeWindow.end}`,\n\t\t\t};\n\t\t}\n\t}\n\n\t// IP allowlist check\n\tif (constraints.ipAllowlist && constraints.ipAllowlist.length > 0) {\n\t\tif (!request.ip) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: \"IP_NOT_ALLOWED: No IP address provided; resource requires an IP allowlist match\",\n\t\t\t};\n\t\t}\n\t\tif (!isIPAllowed(constraints.ipAllowlist, request.ip)) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `IP_NOT_ALLOWED: IP \"${request.ip}\" is not in the allowlist for this resource`,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { allowed: true };\n}\n\nasync function writeAuditLog(\n\tdb: Database,\n\tagent: AgentIdentity,\n\trequest: AuthorizeRequest,\n\tresult: AuthorizeResult,\n\tstartTime: number,\n\tauditId: string,\n): Promise<void> {\n\tconst durationMs = Math.round(performance.now() - startTime);\n\n\tawait db.insert(auditLogs).values({\n\t\tid: auditId,\n\t\tagentId: agent.id,\n\t\tuserId: agent.ownerId,\n\t\taction: request.action,\n\t\tresource: request.resource,\n\t\tparameters: request.arguments ?? {},\n\t\tresult: result.allowed ? \"allowed\" : \"denied\",\n\t\treason: result.reason ?? null,\n\t\tdurationMs,\n\t\ttimestamp: new Date(),\n\t\tip: request.context?.ip ?? null,\n\t\tuserAgent: request.context?.userAgent ?? null,\n\t});\n}\n","import type { Permission } from \"../types.js\";\n\n/**\n * Pre-built permission templates for common access patterns.\n * Use these as starting points when creating agents.\n */\nexport const permissionTemplates = {\n\t/** Read-only access to all resources */\n\treadonly: [{ resource: \"*\", actions: [\"read\"] }] satisfies Permission[],\n\n\t/** Read and write access to all resources */\n\treadwrite: [{ resource: \"*\", actions: [\"read\", \"write\"] }] satisfies Permission[],\n\n\t/** Full access to all resources and actions */\n\tadmin: [{ resource: \"*\", actions: [\"*\"] }] satisfies Permission[],\n\n\t/** Standard MCP tool access - read + execute */\n\tmcpBasic: [{ resource: \"mcp:*\", actions: [\"read\", \"execute\"] }] satisfies Permission[],\n\n\t/** MCP tool access with write - read + write + execute */\n\tmcpFull: [{ resource: \"mcp:*\", actions: [\"read\", \"write\", \"execute\"] }] satisfies Permission[],\n\n\t/** Rate-limited read access (100 calls/hour) */\n\trateLimitedRead: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"read\"],\n\t\t\tconstraints: { maxCallsPerHour: 100 },\n\t\t},\n\t] satisfies Permission[],\n\n\t/** Approval-required access (human-in-the-loop for everything) */\n\tapprovalRequired: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"*\"],\n\t\t\tconstraints: { requireApproval: true },\n\t\t},\n\t] satisfies Permission[],\n\n\t/** Business hours only access (9am-5pm) */\n\tbusinessHours: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"read\", \"write\", \"execute\"],\n\t\t\tconstraints: { timeWindow: { start: \"09:00\", end: \"17:00\" } },\n\t\t},\n\t] satisfies Permission[],\n} as const;\n\nexport type PermissionTemplateName = keyof typeof permissionTemplates;\n\n/**\n * Get a permission template by name.\n * Returns a fresh copy of the permissions array.\n */\nexport function getPermissionTemplate(name: PermissionTemplateName): Permission[] {\n\treturn JSON.parse(JSON.stringify(permissionTemplates[name])) as Permission[];\n}\n"]}
1
+ {"version":3,"sources":["../src/permission/engine.ts","../src/permission/templates.ts"],"names":["result"],"mappings":"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","file":"chunk-OVGNZ5OX.js","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { and, eq, gte } from \"drizzle-orm\";\nimport type { Database } from \"../db/database.js\";\nimport { auditLogs, rateLimits } from \"../db/schema.js\";\nimport type {\n\tAgentIdentity,\n\tAuthorizeRequest,\n\tAuthorizeResult,\n\tPermissionConstraints,\n} from \"../types.js\";\n\ninterface PermissionEngineConfig {\n\tdb: Database;\n\tauditAll: boolean;\n}\n\n/**\n * Match a resource pattern against a requested resource.\n *\n * Supports wildcards:\n * - \"mcp:github:*\" matches \"mcp:github:create_issue\"\n * - \"tool:*\" matches \"tool:file_read\"\n * - \"*\" matches everything\n */\nfunction matchResource(pattern: string, resource: string): boolean {\n\tif (pattern === \"*\") return true;\n\n\tconst patternParts = pattern.split(\":\");\n\tconst resourceParts = resource.split(\":\");\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst part = patternParts[i];\n\t\tif (part === \"*\") return true;\n\t\tif (part !== resourceParts[i]) return false;\n\t}\n\n\treturn patternParts.length === resourceParts.length;\n}\n\n/**\n * Check if an action is allowed by a permission's actions list.\n */\nfunction matchAction(allowedActions: string[], requestedAction: string): boolean {\n\treturn allowedActions.includes(requestedAction) || allowedActions.includes(\"*\");\n}\n\n/**\n * Parse an IPv4 address into a 32-bit integer.\n */\nfunction parseIPv4(ip: string): number | null {\n\tconst parts = ip.split(\".\");\n\tif (parts.length !== 4) return null;\n\tlet result = 0;\n\tfor (const part of parts) {\n\t\tconst num = parseInt(part, 10);\n\t\tif (Number.isNaN(num) || num < 0 || num > 255) return null;\n\t\tresult = (result << 8) | num;\n\t}\n\treturn result >>> 0;\n}\n\n/**\n * Check whether an IP matches a CIDR range or exact IP entry.\n * Supports both \"10.0.0.1\" and \"10.0.0.0/8\" notation (IPv4 only).\n */\nfunction matchesIPEntry(entry: string, ip: string): boolean {\n\tconst slashIndex = entry.indexOf(\"/\");\n\tif (slashIndex === -1) {\n\t\treturn entry === ip;\n\t}\n\n\tconst cidrIp = entry.slice(0, slashIndex);\n\tconst prefixLen = parseInt(entry.slice(slashIndex + 1), 10);\n\tif (Number.isNaN(prefixLen) || prefixLen < 0 || prefixLen > 32) return false;\n\n\tconst entryNum = parseIPv4(cidrIp);\n\tconst ipNum = parseIPv4(ip);\n\tif (entryNum === null || ipNum === null) return false;\n\n\tconst mask = prefixLen === 0 ? 0 : (~0 << (32 - prefixLen)) >>> 0;\n\treturn (entryNum & mask) === (ipNum & mask);\n}\n\n/**\n * Check whether an IP is in the allowlist (exact IPs or CIDR ranges).\n */\nfunction isIPAllowed(allowlist: string[], ip: string): boolean {\n\treturn allowlist.some((entry) => matchesIPEntry(entry, ip));\n}\n\n/**\n * Validate argument patterns against the request arguments.\n */\nfunction validateArgPatterns(\n\tpatterns: string[],\n\targs: Record<string, unknown>,\n): { valid: boolean; reason?: string } {\n\tfor (const pattern of patterns) {\n\t\tconst regex = new RegExp(pattern);\n\t\t// Check all string arguments against the pattern\n\t\tfor (const [key, value] of Object.entries(args)) {\n\t\t\tif (typeof value === \"string\" && !regex.test(value)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: `Argument \"${key}\" value \"${value}\" does not match pattern \"${pattern}\"`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\treturn { valid: true };\n}\n\n/**\n * Check rate limits for an agent on a specific resource.\n */\nasync function checkRateLimit(\n\tdb: Database,\n\tagentId: string,\n\tresource: string,\n\tmaxCallsPerHour: number,\n): Promise<{ allowed: boolean; reason?: string }> {\n\tconst oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);\n\n\tconst rows = await db\n\t\t.select()\n\t\t.from(rateLimits)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(rateLimits.agentId, agentId),\n\t\t\t\teq(rateLimits.resource, resource),\n\t\t\t\tgte(rateLimits.windowStart, oneHourAgo),\n\t\t\t),\n\t\t);\n\n\tconst totalCalls = rows.reduce((sum, r) => sum + r.count, 0);\n\n\tif (totalCalls >= maxCallsPerHour) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason: `Rate limit exceeded: ${totalCalls}/${maxCallsPerHour} calls per hour for resource \"${resource}\"`,\n\t\t};\n\t}\n\n\t// Increment counter\n\tconst currentWindow = new Date(Math.floor(Date.now() / (5 * 60 * 1000)) * (5 * 60 * 1000)); // 5-min windows\n\tconst existing = rows.find((r) => r.windowStart.getTime() === currentWindow.getTime());\n\n\tif (existing) {\n\t\tawait db\n\t\t\t.update(rateLimits)\n\t\t\t.set({ count: existing.count + 1 })\n\t\t\t.where(eq(rateLimits.id, existing.id));\n\t} else {\n\t\tawait db.insert(rateLimits).values({\n\t\t\tid: randomUUID(),\n\t\t\tagentId,\n\t\t\tresource,\n\t\t\twindowStart: currentWindow,\n\t\t\tcount: 1,\n\t\t});\n\t}\n\n\treturn { allowed: true };\n}\n\n/**\n * Create the permission/authorization engine.\n */\nexport function createPermissionEngine(config: PermissionEngineConfig) {\n\tconst { db, auditAll } = config;\n\n\t/**\n\t * Check if an agent is authorized to perform an action.\n\t * This is the core authorization function.\n\t */\n\tasync function authorize(\n\t\tagent: AgentIdentity,\n\t\trequest: AuthorizeRequest,\n\t): Promise<AuthorizeResult> {\n\t\tconst startTime = performance.now();\n\t\tconst auditId = randomUUID();\n\n\t\t// Find matching permission\n\t\tconst matchingPermission = agent.permissions.find(\n\t\t\t(p) => matchResource(p.resource, request.resource) && matchAction(p.actions, request.action),\n\t\t);\n\n\t\tif (!matchingPermission) {\n\t\t\tconst result: AuthorizeResult = {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `No permission grants agent \"${agent.name}\" access to \"${request.action}\" on \"${request.resource}\"`,\n\t\t\t\tauditId,\n\t\t\t};\n\t\t\tif (auditAll) {\n\t\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t// Check constraints\n\t\tif (matchingPermission.constraints) {\n\t\t\tconst constraintResult = await evaluateConstraints(\n\t\t\t\tdb,\n\t\t\t\tagent,\n\t\t\t\trequest,\n\t\t\t\tmatchingPermission.constraints,\n\t\t\t);\n\t\t\tif (!constraintResult.allowed) {\n\t\t\t\tconst result: AuthorizeResult = {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\treason: constraintResult.reason,\n\t\t\t\t\tauditId,\n\t\t\t\t};\n\t\t\t\tif (auditAll) {\n\t\t\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tconst result: AuthorizeResult = { allowed: true, auditId };\n\t\tif (auditAll) {\n\t\t\tawait writeAuditLog(db, agent, request, result, startTime, auditId);\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn { authorize };\n}\n\nasync function evaluateConstraints(\n\tdb: Database,\n\tagent: AgentIdentity,\n\trequest: AuthorizeRequest,\n\tconstraints: PermissionConstraints,\n): Promise<{ allowed: boolean; reason?: string }> {\n\t// Rate limit check\n\tif (constraints.maxCallsPerHour) {\n\t\tconst rateResult = await checkRateLimit(\n\t\t\tdb,\n\t\t\tagent.id,\n\t\t\trequest.resource,\n\t\t\tconstraints.maxCallsPerHour,\n\t\t);\n\t\tif (!rateResult.allowed) {\n\t\t\treturn rateResult;\n\t\t}\n\t}\n\n\t// Argument pattern check\n\tif (constraints.allowedArgPatterns && request.arguments) {\n\t\tconst patternResult = validateArgPatterns(constraints.allowedArgPatterns, request.arguments);\n\t\tif (!patternResult.valid) {\n\t\t\treturn { allowed: false, reason: patternResult.reason };\n\t\t}\n\t}\n\n\t// Human-in-the-loop check\n\tif (constraints.requireApproval) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason: \"This action requires human approval before execution\",\n\t\t};\n\t}\n\n\t// Time window check\n\tif (constraints.timeWindow) {\n\t\tconst now = new Date();\n\t\tconst hours = now.getHours();\n\t\tconst minutes = now.getMinutes();\n\t\tconst currentTime = `${String(hours).padStart(2, \"0\")}:${String(minutes).padStart(2, \"0\")}`;\n\n\t\tif (currentTime < constraints.timeWindow.start || currentTime > constraints.timeWindow.end) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `Action is only allowed between ${constraints.timeWindow.start} and ${constraints.timeWindow.end}`,\n\t\t\t};\n\t\t}\n\t}\n\n\t// IP allowlist check\n\tif (constraints.ipAllowlist && constraints.ipAllowlist.length > 0) {\n\t\tif (!request.ip) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: \"IP_NOT_ALLOWED: No IP address provided; resource requires an IP allowlist match\",\n\t\t\t};\n\t\t}\n\t\tif (!isIPAllowed(constraints.ipAllowlist, request.ip)) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: `IP_NOT_ALLOWED: IP \"${request.ip}\" is not in the allowlist for this resource`,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { allowed: true };\n}\n\nasync function writeAuditLog(\n\tdb: Database,\n\tagent: AgentIdentity,\n\trequest: AuthorizeRequest,\n\tresult: AuthorizeResult,\n\tstartTime: number,\n\tauditId: string,\n): Promise<void> {\n\tconst durationMs = Math.round(performance.now() - startTime);\n\n\tawait db.insert(auditLogs).values({\n\t\tid: auditId,\n\t\tagentId: agent.id,\n\t\tuserId: agent.ownerId,\n\t\taction: request.action,\n\t\tresource: request.resource,\n\t\tparameters: request.arguments ?? {},\n\t\tresult: result.allowed ? \"allowed\" : \"denied\",\n\t\treason: result.reason ?? null,\n\t\tdurationMs,\n\t\ttimestamp: new Date(),\n\t\tip: request.context?.ip ?? null,\n\t\tuserAgent: request.context?.userAgent ?? null,\n\t});\n}\n","import type { Permission } from \"../types.js\";\n\n/**\n * Pre-built permission templates for common access patterns.\n * Use these as starting points when creating agents.\n */\nexport const permissionTemplates = {\n\t/** Read-only access to all resources */\n\treadonly: [{ resource: \"*\", actions: [\"read\"] }] satisfies Permission[],\n\n\t/** Read and write access to all resources */\n\treadwrite: [{ resource: \"*\", actions: [\"read\", \"write\"] }] satisfies Permission[],\n\n\t/** Full access to all resources and actions */\n\tadmin: [{ resource: \"*\", actions: [\"*\"] }] satisfies Permission[],\n\n\t/** Standard MCP tool access - read + execute */\n\tmcpBasic: [{ resource: \"mcp:*\", actions: [\"read\", \"execute\"] }] satisfies Permission[],\n\n\t/** MCP tool access with write - read + write + execute */\n\tmcpFull: [{ resource: \"mcp:*\", actions: [\"read\", \"write\", \"execute\"] }] satisfies Permission[],\n\n\t/** Rate-limited read access (100 calls/hour) */\n\trateLimitedRead: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"read\"],\n\t\t\tconstraints: { maxCallsPerHour: 100 },\n\t\t},\n\t] satisfies Permission[],\n\n\t/** Approval-required access (human-in-the-loop for everything) */\n\tapprovalRequired: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"*\"],\n\t\t\tconstraints: { requireApproval: true },\n\t\t},\n\t] satisfies Permission[],\n\n\t/** Business hours only access (9am-5pm) */\n\tbusinessHours: [\n\t\t{\n\t\t\tresource: \"*\",\n\t\t\tactions: [\"read\", \"write\", \"execute\"],\n\t\t\tconstraints: { timeWindow: { start: \"09:00\", end: \"17:00\" } },\n\t\t},\n\t] satisfies Permission[],\n} as const;\n\nexport type PermissionTemplateName = keyof typeof permissionTemplates;\n\n/**\n * Get a permission template by name.\n * Returns a fresh copy of the permissions array.\n */\nexport function getPermissionTemplate(name: PermissionTemplateName): Permission[] {\n\treturn JSON.parse(JSON.stringify(permissionTemplates[name])) as Permission[];\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { auditLogs } from './chunk-UEE7OYLG.js';
1
+ import { auditLogs } from './chunk-V66UUIA7.js';
2
2
  import { eq, gte, lte, desc, and, lt } from 'drizzle-orm';
3
3
 
4
4
  function createAuditModule(config) {
@@ -97,5 +97,5 @@ function toAuditEntry(row) {
97
97
  }
98
98
 
99
99
  export { createAuditModule };
100
- //# sourceMappingURL=chunk-N7VZO6SP.js.map
101
- //# sourceMappingURL=chunk-N7VZO6SP.js.map
100
+ //# sourceMappingURL=chunk-SJGSPIAD.js.map
101
+ //# sourceMappingURL=chunk-SJGSPIAD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/audit/audit.ts"],"names":[],"mappings":"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","file":"chunk-N7VZO6SP.js","sourcesContent":["import { and, desc, eq, gte, lt, lte } from \"drizzle-orm\";\nimport type { Database } from \"../db/database.js\";\nimport { auditLogs } from \"../db/schema.js\";\nimport type { AuditEntry, AuditExportOptions, AuditFilter } from \"../types.js\";\n\ninterface AuditModuleConfig {\n\tdb: Database;\n}\n\n/**\n * Create the audit log module.\n * Provides query and export capabilities for the immutable audit trail.\n */\nexport function createAuditModule(config: AuditModuleConfig) {\n\tconst { db } = config;\n\n\tasync function query(filter: AuditFilter): Promise<AuditEntry[]> {\n\t\tconst conditions = [];\n\n\t\tif (filter.agentId) conditions.push(eq(auditLogs.agentId, filter.agentId));\n\t\tif (filter.userId) conditions.push(eq(auditLogs.userId, filter.userId));\n\t\tif (filter.since) conditions.push(gte(auditLogs.timestamp, filter.since));\n\t\tif (filter.until) conditions.push(lte(auditLogs.timestamp, filter.until));\n\t\tif (filter.result) conditions.push(eq(auditLogs.result, filter.result));\n\n\t\tlet q = db.select().from(auditLogs).orderBy(desc(auditLogs.timestamp)).$dynamic();\n\n\t\tif (conditions.length > 0) {\n\t\t\tq = q.where(and(...conditions));\n\t\t}\n\n\t\tif (filter.limit) {\n\t\t\tq = q.limit(filter.limit);\n\t\t}\n\t\tif (filter.offset) {\n\t\t\tq = q.offset(filter.offset);\n\t\t}\n\n\t\tconst rows = await q;\n\n\t\treturn rows\n\t\t\t.filter((row) => {\n\t\t\t\t// Filter by actions if specified\n\t\t\t\tif (filter.actions && filter.actions.length > 0) {\n\t\t\t\t\treturn filter.actions.includes(row.action);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t})\n\t\t\t.map(toAuditEntry);\n\t}\n\n\tasync function exportLogs(options: AuditExportOptions): Promise<string> {\n\t\tconst entries = await query({\n\t\t\tsince: options.since,\n\t\t\tuntil: options.until,\n\t\t\tlimit: 10000, // cap exports\n\t\t});\n\n\t\tif (options.format === \"json\") {\n\t\t\treturn JSON.stringify(entries, null, 2);\n\t\t}\n\n\t\t// CSV format\n\t\tconst headers = [\n\t\t\t\"id\",\n\t\t\t\"agentId\",\n\t\t\t\"userId\",\n\t\t\t\"action\",\n\t\t\t\"resource\",\n\t\t\t\"result\",\n\t\t\t\"reason\",\n\t\t\t\"durationMs\",\n\t\t\t\"tokensCost\",\n\t\t\t\"timestamp\",\n\t\t];\n\t\tconst csvRows = [headers.join(\",\")];\n\n\t\tfor (const entry of entries) {\n\t\t\tcsvRows.push(\n\t\t\t\t[\n\t\t\t\t\tentry.id,\n\t\t\t\t\tentry.agentId,\n\t\t\t\t\tentry.userId,\n\t\t\t\t\tentry.action,\n\t\t\t\t\tentry.resource,\n\t\t\t\t\tentry.result,\n\t\t\t\t\t`\"${(entry as AuditEntry & { reason?: string }).reason ?? \"\"}\"`,\n\t\t\t\t\tentry.durationMs,\n\t\t\t\t\tentry.tokensCost ?? \"\",\n\t\t\t\t\tentry.timestamp.toISOString(),\n\t\t\t\t].join(\",\"),\n\t\t\t);\n\t\t}\n\n\t\treturn csvRows.join(\"\\n\");\n\t}\n\n\t/**\n\t * Delete audit log entries older than the specified retention period.\n\t * Returns the count of deleted rows.\n\t */\n\tasync function cleanup(options: { retentionDays: number }): Promise<{ deleted: number }> {\n\t\tconst cutoff = new Date(Date.now() - options.retentionDays * 24 * 60 * 60 * 1000);\n\n\t\t// Count rows to be deleted before removing them\n\t\tconst toDelete = await db\n\t\t\t.select({ id: auditLogs.id })\n\t\t\t.from(auditLogs)\n\t\t\t.where(lt(auditLogs.timestamp, cutoff));\n\n\t\tif (toDelete.length === 0) {\n\t\t\treturn { deleted: 0 };\n\t\t}\n\n\t\tawait db.delete(auditLogs).where(lt(auditLogs.timestamp, cutoff));\n\n\t\treturn { deleted: toDelete.length };\n\t}\n\n\treturn { query, export: exportLogs, cleanup };\n}\n\nfunction toAuditEntry(row: typeof auditLogs.$inferSelect): AuditEntry {\n\treturn {\n\t\tid: row.id,\n\t\tagentId: row.agentId,\n\t\tuserId: row.userId,\n\t\taction: row.action,\n\t\tresource: row.resource,\n\t\tparameters: (row.parameters as Record<string, unknown>) ?? {},\n\t\tresult: row.result as AuditEntry[\"result\"],\n\t\treason: row.reason ?? undefined,\n\t\tdurationMs: row.durationMs,\n\t\ttokensCost: row.tokensCost ?? undefined,\n\t\ttimestamp: row.timestamp,\n\t};\n}\n"]}
1
+ {"version":3,"sources":["../src/audit/audit.ts"],"names":[],"mappings":"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","file":"chunk-SJGSPIAD.js","sourcesContent":["import { and, desc, eq, gte, lt, lte } from \"drizzle-orm\";\nimport type { Database } from \"../db/database.js\";\nimport { auditLogs } from \"../db/schema.js\";\nimport type { AuditEntry, AuditExportOptions, AuditFilter } from \"../types.js\";\n\ninterface AuditModuleConfig {\n\tdb: Database;\n}\n\n/**\n * Create the audit log module.\n * Provides query and export capabilities for the immutable audit trail.\n */\nexport function createAuditModule(config: AuditModuleConfig) {\n\tconst { db } = config;\n\n\tasync function query(filter: AuditFilter): Promise<AuditEntry[]> {\n\t\tconst conditions = [];\n\n\t\tif (filter.agentId) conditions.push(eq(auditLogs.agentId, filter.agentId));\n\t\tif (filter.userId) conditions.push(eq(auditLogs.userId, filter.userId));\n\t\tif (filter.since) conditions.push(gte(auditLogs.timestamp, filter.since));\n\t\tif (filter.until) conditions.push(lte(auditLogs.timestamp, filter.until));\n\t\tif (filter.result) conditions.push(eq(auditLogs.result, filter.result));\n\n\t\tlet q = db.select().from(auditLogs).orderBy(desc(auditLogs.timestamp)).$dynamic();\n\n\t\tif (conditions.length > 0) {\n\t\t\tq = q.where(and(...conditions));\n\t\t}\n\n\t\tif (filter.limit) {\n\t\t\tq = q.limit(filter.limit);\n\t\t}\n\t\tif (filter.offset) {\n\t\t\tq = q.offset(filter.offset);\n\t\t}\n\n\t\tconst rows = await q;\n\n\t\treturn rows\n\t\t\t.filter((row) => {\n\t\t\t\t// Filter by actions if specified\n\t\t\t\tif (filter.actions && filter.actions.length > 0) {\n\t\t\t\t\treturn filter.actions.includes(row.action);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t})\n\t\t\t.map(toAuditEntry);\n\t}\n\n\tasync function exportLogs(options: AuditExportOptions): Promise<string> {\n\t\tconst entries = await query({\n\t\t\tsince: options.since,\n\t\t\tuntil: options.until,\n\t\t\tlimit: 10000, // cap exports\n\t\t});\n\n\t\tif (options.format === \"json\") {\n\t\t\treturn JSON.stringify(entries, null, 2);\n\t\t}\n\n\t\t// CSV format\n\t\tconst headers = [\n\t\t\t\"id\",\n\t\t\t\"agentId\",\n\t\t\t\"userId\",\n\t\t\t\"action\",\n\t\t\t\"resource\",\n\t\t\t\"result\",\n\t\t\t\"reason\",\n\t\t\t\"durationMs\",\n\t\t\t\"tokensCost\",\n\t\t\t\"timestamp\",\n\t\t];\n\t\tconst csvRows = [headers.join(\",\")];\n\n\t\tfor (const entry of entries) {\n\t\t\tcsvRows.push(\n\t\t\t\t[\n\t\t\t\t\tentry.id,\n\t\t\t\t\tentry.agentId,\n\t\t\t\t\tentry.userId,\n\t\t\t\t\tentry.action,\n\t\t\t\t\tentry.resource,\n\t\t\t\t\tentry.result,\n\t\t\t\t\t`\"${(entry as AuditEntry & { reason?: string }).reason ?? \"\"}\"`,\n\t\t\t\t\tentry.durationMs,\n\t\t\t\t\tentry.tokensCost ?? \"\",\n\t\t\t\t\tentry.timestamp.toISOString(),\n\t\t\t\t].join(\",\"),\n\t\t\t);\n\t\t}\n\n\t\treturn csvRows.join(\"\\n\");\n\t}\n\n\t/**\n\t * Delete audit log entries older than the specified retention period.\n\t * Returns the count of deleted rows.\n\t */\n\tasync function cleanup(options: { retentionDays: number }): Promise<{ deleted: number }> {\n\t\tconst cutoff = new Date(Date.now() - options.retentionDays * 24 * 60 * 60 * 1000);\n\n\t\t// Count rows to be deleted before removing them\n\t\tconst toDelete = await db\n\t\t\t.select({ id: auditLogs.id })\n\t\t\t.from(auditLogs)\n\t\t\t.where(lt(auditLogs.timestamp, cutoff));\n\n\t\tif (toDelete.length === 0) {\n\t\t\treturn { deleted: 0 };\n\t\t}\n\n\t\tawait db.delete(auditLogs).where(lt(auditLogs.timestamp, cutoff));\n\n\t\treturn { deleted: toDelete.length };\n\t}\n\n\treturn { query, export: exportLogs, cleanup };\n}\n\nfunction toAuditEntry(row: typeof auditLogs.$inferSelect): AuditEntry {\n\treturn {\n\t\tid: row.id,\n\t\tagentId: row.agentId,\n\t\tuserId: row.userId,\n\t\taction: row.action,\n\t\tresource: row.resource,\n\t\tparameters: (row.parameters as Record<string, unknown>) ?? {},\n\t\tresult: row.result as AuditEntry[\"result\"],\n\t\treason: row.reason ?? undefined,\n\t\tdurationMs: row.durationMs,\n\t\ttokensCost: row.tokensCost ?? undefined,\n\t\ttimestamp: row.timestamp,\n\t};\n}\n"]}