export const DEFAULT_FORBIDDEN_BROWSER_ACTION_TEXT = [
    'checkout',
    'check out',
    'pay',
    'payment',
    'place order',
    'confirm',
    'bid',
    'subscribe',
    'book',
    'send',
    'transfer',
    'delete',
    'remove account',
    'add to cart',
    'buy now',
];
/**
 * Owns browser navigation and action policy decisions.
 */
export class BrowserPolicyService {
    config;
    constructor(config) {
        this.config = config;
    }
    evaluateNavigation(url) {
        const hostname = this.hostnameFromUrl(url);
        if (!hostname) {
            return {
                status: 'blocked',
                risk: 'medium',
                reason: `Invalid browser navigation URL: ${url}`,
            };
        }
        if (this.isAllowedHostname(hostname)) {
            return { status: 'allowed', risk: 'low' };
        }
        return this.config.requireApprovalForOffDomainNavigation ?? true
            ? {
                status: 'approvalRequired',
                risk: 'medium',
                reason: `Navigation to ${hostname} is outside the browser domain allowlist.`,
            }
            : {
                status: 'blocked',
                risk: 'medium',
                reason: `Navigation to ${hostname} is outside the browser domain allowlist.`,
            };
    }
    evaluateClick(element) {
        const targetText = [element.name, element.text, element.href].filter(Boolean).join(' ').toLowerCase();
        const forbidden = this.forbiddenActionText().find((pattern) => targetText.includes(pattern.toLowerCase()));
        if (forbidden) {
            return {
                status: 'blocked',
                risk: 'high',
                reason: `Click target matches forbidden browser action text: ${forbidden}`,
            };
        }
        if (!element.href) {
            return this.config.requireApprovalForOffDomainNavigation ?? true
                ? {
                    status: 'approvalRequired',
                    risk: 'medium',
                    reason: 'Click target does not expose a browser navigation URL before execution.',
                }
                : {
                    status: 'blocked',
                    risk: 'medium',
                    reason: 'Click target does not expose a browser navigation URL before execution.',
                };
        }
        const hrefDecision = this.evaluateNavigation(element.href);
        if (hrefDecision.status !== 'allowed') {
            return hrefDecision;
        }
        return { status: 'allowed', risk: 'low' };
    }
    maxElementsPerSnapshot() {
        return this.config.maxElementsPerSnapshot ?? 80;
    }
    forbiddenActionText() {
        return this.config.forbiddenActionText ?? DEFAULT_FORBIDDEN_BROWSER_ACTION_TEXT;
    }
    isAllowedHostname(hostname) {
        const normalizedHostname = hostname.toLowerCase();
        return this.config.allowedDomains
            .map((domain) => domain.toLowerCase())
            .some((domain) => normalizedHostname === domain || normalizedHostname.endsWith(`.${domain}`));
    }
    hostnameFromUrl(url) {
        try {
            return new URL(url).hostname;
        }
        catch {
            return undefined;
        }
    }
}
//# sourceMappingURL=service.js.map