/**
 * Entity permission management for access control.
 *
 * Provides a generalized system for tracking user approvals for accessing
 * specific entities (e.g., integrations, files, APIs). This enables granular
 * per-entity access control where users can approve access to specific
 * resources rather than blanket permissions.
 */
import { getToolCallSignature } from "../../util/tool-signature.js";
/**
 * Strategy for determining how permissions are scoped by tool.
 *
 * Different strategies enable different granularities:
 * - Per-tool: Each tool requires separate approval
 * - Per-category: All tools in a category share approvals
 * - Per-access: Separate read/write permissions
 */
export class PermissionKeyStrategy {
    /**
     * Format permission key into storage scope string.
     *
     * Default implementation joins components with ':' delimiter.
     *
     * @param key - Permission key components
     * @returns Formatted scope string
     */
    formatScope(key) {
        return key.join(":");
    }
}
/**
 * Action-based strategy: scope permissions by action type (read/write).
 *
 * Groups tools by the action they perform rather than their specific name.
 * This allows users to approve "read" or "write" operations on entities,
 * and all tools performing that action will share the approval.
 *
 * - readOnly tools → "read" scope
 * - Non-readOnly tools → "write" scope
 */
export class ActionBasedPermissionKeyStrategy extends PermissionKeyStrategy {
    getPermissionKey(permission, _input) {
        return [permission.permissionType];
    }
}
/**
 * Session-scoped implementation of entity permission store.
 *
 * Stores approvals in memory for the duration of the session.
 * Approvals are lost when the session ends or the store is cleared.
 *
 * Permissions are scoped, allowing different tools/categories to have
 * independent approval states for the same entity.
 *
 * This implementation is suitable for session-based permission tracking
 * and can be replaced with a persistent implementation if needed.
 */
export class SessionEntityPermissionStore {
    permissions;
    temporaryPermissions; // key is tool call signature
    constructor() {
        this.permissions = new Map();
        this.temporaryPermissions = new Map();
    }
    isToolCallApproved(toolName, input) {
        const toolCallIdentifier = getToolCallSignature(toolName, input);
        return this.temporaryPermissions.has(toolCallIdentifier);
    }
    approveToolCall(toolName, input) {
        const toolCallIdentifier = getToolCallSignature(toolName, input);
        this.temporaryPermissions.set(toolCallIdentifier, { input, toolName });
    }
    revokeToolCall(toolName, input) {
        const toolCallIdentifier = getToolCallSignature(toolName, input);
        this.temporaryPermissions.delete(toolCallIdentifier);
    }
    /**
     * Check if access to a specific entity has been approved for a scope.
     *
     * @param entityType - The type of entity to check
     * @param entityId - The unique identifier of the entity
     * @param scope - Permission scope
     * @returns True if the entity has been approved for this scope
     */
    isApproved(entityType, entityId, scope) {
        const scopedPermissions = this.permissions.get(entityType);
        if (!scopedPermissions) {
            return false;
        }
        const approved = scopedPermissions.get(scope);
        return approved?.has(entityId ?? "*") ?? false;
    }
    /**
     * Approve access to a specific entity for a scope.
     *
     * @param entityType - The type of entity to approve
     * @param entityId - The unique identifier of the entity
     * @param scope - Permission scope
     */
    approve(entityType, entityId, scope) {
        let scopedPermissions = this.permissions.get(entityType);
        if (!scopedPermissions) {
            scopedPermissions = new Map();
            this.permissions.set(entityType, scopedPermissions);
        }
        let approved = scopedPermissions.get(scope);
        if (!approved) {
            approved = new Set();
            scopedPermissions.set(scope, approved);
        }
        approved.add(entityId ?? "*");
    }
    /**
     * Revoke access to a specific entity for a scope.
     *
     * @param entityType - The type of entity to revoke
     * @param entityId - The unique identifier of the entity
     * @param scope - Permission scope
     */
    revoke(entityType, entityId, scope) {
        const scopedPermissions = this.permissions.get(entityType);
        if (!scopedPermissions) {
            return;
        }
        const approved = scopedPermissions.get(scope);
        approved?.delete(entityId ?? "*");
    }
    /**
     * Clear all entity approvals across all scopes.
     */
    clear() {
        this.permissions.clear();
    }
    /**
     * Get all approved entity IDs for a specific entity type and optional scope.
     *
     * @param entityType - The type of entity to list approvals for
     * @param scope - Optional permission scope. If provided, returns only approvals
     *                for that scope. If omitted, returns all approved entities
     *                across all scopes (deduplicated).
     * @returns Array of approved entity IDs for the given type (and scope)
     */
    getApproved(entityType, scope) {
        const scopedPermissions = this.permissions.get(entityType);
        if (!scopedPermissions) {
            return [];
        }
        // If scope provided, return only that scope's entities
        if (scope !== undefined) {
            const approved = scopedPermissions.get(scope);
            return approved ? Array.from(approved) : [];
        }
        // No scope provided - return all entities across all scopes (deduplicated)
        const allEntities = new Set();
        for (const approved of scopedPermissions.values()) {
            for (const entityId of approved) {
                allEntities.add(entityId ?? "*");
            }
        }
        return Array.from(allEntities);
    }
}
//# sourceMappingURL=entity-permissions.js.map