#!/usr/bin/env node /** url-whitelist-rules — дом сборки project-URL-whitelist паттернов (config-seam). * База неизменна; проектные домены приходят списком; пусто = fail-CLOSED. Чистый. */ export const DEFAULT_PROJECT_URL_WHITELIST = Object.freeze(['liderra.ru', 'github.com/liderra']); export const BASE_NAVIGATE_HOSTS = Object.freeze(['localhost', '127.0.0.1']); export const BASE_WEBFETCH_WHITELIST_PATTERNS = Object.freeze([ '^https?://docs\\.anthropic\\.com/', '^https?://github\\.com/(?:anthropics|deck|deck-platform)/', '^https?://(?:www\\.)?npmjs\\.com/package/', '^https?://stackoverflow\\.com/questions/', ]); export const WEBFETCH_SCHEME_BLOCK_PATTERNS = Object.freeze(['^data:', '^javascript:']); export const BASE_COMMIT_MSG_FRAGS = Object.freeze([ 'github\\.com/(?:deck|deck-platform)', 'api\\.anthropic\\.com', 'docs\\.anthropic\\.com', ]); /** Экранировать regex-спецсимволы; `/` не трогаем (литеральный разделитель пути). */ export function escapeDomain(d) { return String(d).replace(/[.+^${}()|[\]\\?*]/g, '\\$&'); } function hostOnly(domains) { return (domains || []).filter((d) => typeof d === 'string' && d && !d.includes('/')); } /** navigate: один host-альтернация-паттерн с границей (?:[:/?#]|$); возврат — одноэлементный массив. */ export function buildNavigateWhitelistPatterns(projectDomains) { const hosts = [...BASE_NAVIGATE_HOSTS, ...hostOnly(projectDomains)]; return ['^https?://(?:' + hosts.map(escapeDomain).join('|') + ')(?:[:/?#]|$)']; } /** WebFetch: база + на каждый проектный домен `^https?:///`. */ export function buildWebFetchWhitelistPatterns(projectDomains) { const proj = (projectDomains || []).filter((d) => typeof d === 'string' && d); return [...BASE_WEBFETCH_WHITELIST_PATTERNS, ...proj.map((d) => '^https?://' + escapeDomain(d) + '/')]; } /** commit-message negative-lookahead: блок URL, чей домен НЕ из (база ∪ проект). */ export function buildCommitMessageUrlPattern(projectDomains) { const proj = (projectDomains || []).filter((d) => typeof d === 'string' && d); const frags = [...BASE_COMMIT_MSG_FRAGS, ...proj.map(escapeDomain)]; // Host-terminator (?:[:/?#]|$) after the allowlist alternation closes subdomain-suffix // spoofs (liderra.ru.evil.com / github.com/liderra-evil); mirrors buildNavigateWhitelistPatterns. return new RegExp('\\bhttps?:\\/\\/(?!(?:' + frags.join('|') + ')(?:[:/?#]|$))\\S+', 'i'); }