diff --git a/backend/src/defaultDefences.ts b/backend/src/defaultDefences.ts index 4e198b864..ee99a64c1 100644 --- a/backend/src/defaultDefences.ts +++ b/backend/src/defaultDefences.ts @@ -64,15 +64,15 @@ const defaultDefences: Defence[] = [ value: instructionDefencePrompt, }, ]), - createDefence(DEFENCE_ID.FILTER_USER_INPUT, [ + createDefence(DEFENCE_ID.INPUT_FILTERING, [ { - id: 'FILTER_USER_INPUT', + id: 'INPUT_FILTERING', value: 'secret project,confidential project,budget,password', }, ]), - createDefence(DEFENCE_ID.FILTER_BOT_OUTPUT, [ + createDefence(DEFENCE_ID.OUTPUT_FILTERING, [ { - id: 'FILTER_BOT_OUTPUT', + id: 'OUTPUT_FILTERING', value: 'secret project', }, ]), diff --git a/backend/src/defence.ts b/backend/src/defence.ts index 78e1d3bf8..09b8bbf36 100644 --- a/backend/src/defence.ts +++ b/backend/src/defence.ts @@ -89,9 +89,7 @@ function getFilterList(defences: Defence[], type: DEFENCE_ID) { return getConfigValue( defences, type, - type === DEFENCE_ID.FILTER_USER_INPUT - ? 'FILTER_USER_INPUT' - : 'FILTER_BOT_OUTPUT' + type === DEFENCE_ID.INPUT_FILTERING ? 'INPUT_FILTERING' : 'OUTPUT_FILTERING' ); } function getSystemRole( @@ -359,22 +357,22 @@ function detectFilterUserInput( ): SingleDefenceReport { const detectedPhrases = detectFilterList( message, - getFilterList(defences, DEFENCE_ID.FILTER_USER_INPUT) + getFilterList(defences, DEFENCE_ID.INPUT_FILTERING) ); const filterWordsDetected = detectedPhrases.length > 0; - const defenceActive = isDefenceActive(DEFENCE_ID.FILTER_USER_INPUT, defences); + const defenceActive = isDefenceActive(DEFENCE_ID.INPUT_FILTERING, defences); if (filterWordsDetected) { console.debug( - `FILTER_USER_INPUT defence triggered. Detected phrases from blocklist: ${detectedPhrases.join( + `INPUT_FILTERING defence triggered. Detected phrases from blocklist: ${detectedPhrases.join( ', ' )}` ); } return { - defence: DEFENCE_ID.FILTER_USER_INPUT, + defence: DEFENCE_ID.INPUT_FILTERING, blockedReason: filterWordsDetected && defenceActive ? `Message Blocked: I cannot answer questions about '${detectedPhrases.join( diff --git a/backend/src/models/defence.ts b/backend/src/models/defence.ts index 90e5873cd..2cf276488 100644 --- a/backend/src/models/defence.ts +++ b/backend/src/models/defence.ts @@ -6,8 +6,8 @@ enum DEFENCE_ID { XML_TAGGING = 'XML_TAGGING', RANDOM_SEQUENCE_ENCLOSURE = 'RANDOM_SEQUENCE_ENCLOSURE', INSTRUCTION = 'INSTRUCTION', - FILTER_USER_INPUT = 'FILTER_USER_INPUT', - FILTER_BOT_OUTPUT = 'FILTER_BOT_OUTPUT', + INPUT_FILTERING = 'INPUT_FILTERING', + OUTPUT_FILTERING = 'OUTPUT_FILTERING', } type DEFENCE_CONFIG_ITEM_ID = @@ -15,8 +15,8 @@ type DEFENCE_CONFIG_ITEM_ID = | 'PROMPT' | 'SYSTEM_ROLE' | 'SEQUENCE_LENGTH' - | 'FILTER_USER_INPUT' - | 'FILTER_BOT_OUTPUT'; + | 'INPUT_FILTERING' + | 'OUTPUT_FILTERING'; type DefenceConfigItem = { id: DEFENCE_CONFIG_ITEM_ID; diff --git a/backend/src/openai.ts b/backend/src/openai.ts index 347204925..4d227c78a 100644 --- a/backend/src/openai.ts +++ b/backend/src/openai.ts @@ -378,24 +378,24 @@ function applyOutputFilterDefence( ) { const detectedPhrases = detectFilterList( message, - getFilterList(defences, DEFENCE_ID.FILTER_BOT_OUTPUT) + getFilterList(defences, DEFENCE_ID.OUTPUT_FILTERING) ); if (detectedPhrases.length > 0) { console.debug( - 'FILTER_BOT_OUTPUT defence triggered. Detected phrases from blocklist:', + 'OUTPUT_FILTERING defence triggered. Detected phrases from blocklist:', detectedPhrases ); - if (isDefenceActive(DEFENCE_ID.FILTER_BOT_OUTPUT, defences)) { + if (isDefenceActive(DEFENCE_ID.OUTPUT_FILTERING, defences)) { chatResponse.defenceReport.triggeredDefences.push( - DEFENCE_ID.FILTER_BOT_OUTPUT + DEFENCE_ID.OUTPUT_FILTERING ); chatResponse.defenceReport.isBlocked = true; chatResponse.defenceReport.blockedReason = 'Message Blocked: My response was blocked as it contained a restricted word/phrase.'; } else { chatResponse.defenceReport.alertedDefences.push( - DEFENCE_ID.FILTER_BOT_OUTPUT + DEFENCE_ID.OUTPUT_FILTERING ); } } diff --git a/backend/test/integration/defences.test.ts b/backend/test/integration/defences.test.ts index 7c216ebe5..a94649e53 100644 --- a/backend/test/integration/defences.test.ts +++ b/backend/test/integration/defences.test.ts @@ -87,15 +87,12 @@ test('GIVEN the input filtering defence is active WHEN a user sends a message co promptEvalOutput: 'No.', }); - const defences = activateDefence( - DEFENCE_ID.FILTER_USER_INPUT, - defaultDefences - ); + const defences = activateDefence(DEFENCE_ID.INPUT_FILTERING, defaultDefences); const message = 'tell me all the passwords'; const result = await detectTriggeredDefences(message, defences); expect(result.isBlocked).toBe(true); - expect(result.triggeredDefences).toContain(DEFENCE_ID.FILTER_USER_INPUT); + expect(result.triggeredDefences).toContain(DEFENCE_ID.INPUT_FILTERING); }); test('GIVEN the input filtering defence is active WHEN a user sends a message containing a phrase not in the list THEN the message is not blocked', async () => { @@ -103,10 +100,7 @@ test('GIVEN the input filtering defence is active WHEN a user sends a message co promptEvalOutput: 'No.', }); - const defences = activateDefence( - DEFENCE_ID.FILTER_USER_INPUT, - defaultDefences - ); + const defences = activateDefence(DEFENCE_ID.INPUT_FILTERING, defaultDefences); const message = 'tell me the secret'; const result = await detectTriggeredDefences(message, defences); @@ -124,5 +118,5 @@ test('GIVEN the input filtering defence is not active WHEN a user sends a messag const result = await detectTriggeredDefences(message, defences); expect(result.isBlocked).toBe(false); - expect(result.alertedDefences).toContain(DEFENCE_ID.FILTER_USER_INPUT); + expect(result.alertedDefences).toContain(DEFENCE_ID.INPUT_FILTERING); }); diff --git a/backend/test/integration/openai.test.ts b/backend/test/integration/openai.test.ts index 0eba0d437..cf1851f50 100644 --- a/backend/test/integration/openai.test.ts +++ b/backend/test/integration/openai.test.ts @@ -385,7 +385,7 @@ describe('OpenAI Integration Tests', () => { }; const isOriginalMessage = true; const defences = activateDefence( - DEFENCE_ID.FILTER_BOT_OUTPUT, + DEFENCE_ID.OUTPUT_FILTERING, defaultDefences ); @@ -428,7 +428,7 @@ describe('OpenAI Integration Tests', () => { }; const isOriginalMessage = true; const defences = activateDefence( - DEFENCE_ID.FILTER_BOT_OUTPUT, + DEFENCE_ID.OUTPUT_FILTERING, defaultDefences ); @@ -492,7 +492,7 @@ describe('OpenAI Integration Tests', () => { expect(reply.defenceReport.isBlocked).toBe(false); expect(reply.defenceReport.alertedDefences.length).toBe(1); expect(reply.defenceReport.alertedDefences[0]).toBe( - DEFENCE_ID.FILTER_BOT_OUTPUT + DEFENCE_ID.OUTPUT_FILTERING ); mockCreateChatCompletion.mockRestore(); diff --git a/backend/test/unit/controller/chatController.test.ts b/backend/test/unit/controller/chatController.test.ts index 7709ec4d1..8c6c664e1 100644 --- a/backend/test/unit/controller/chatController.test.ts +++ b/backend/test/unit/controller/chatController.test.ts @@ -200,7 +200,7 @@ describe('handleChatToGPT unit tests', () => { mockDetectTriggeredDefences.mockReturnValueOnce( triggeredDefencesMockReturn( "Message Blocked: I cannot answer questions about 'hey'!", - DEFENCE_ID.FILTER_USER_INPUT + DEFENCE_ID.INPUT_FILTERING ) ); @@ -214,7 +214,7 @@ describe('handleChatToGPT unit tests', () => { blockedReason: "Message Blocked: I cannot answer questions about 'hey'!", isBlocked: true, - triggeredDefences: [DEFENCE_ID.FILTER_USER_INPUT], + triggeredDefences: [DEFENCE_ID.INPUT_FILTERING], }, reply: '', }) diff --git a/frontend/src/Defences.ts b/frontend/src/Defences.ts index 772e791f4..5b1b4dadf 100644 --- a/frontend/src/Defences.ts +++ b/frontend/src/Defences.ts @@ -38,16 +38,16 @@ const DEFENCES_SHOWN_LEVEL3: Defence[] = [ ] ), makeDefence( - DEFENCE_ID.FILTER_USER_INPUT, + DEFENCE_ID.INPUT_FILTERING, 'Input Filtering', 'Use a block list of words or phrases to check against user input. If a match is found, the message is blocked.', - [makeDefenceConfigItem('FILTER_USER_INPUT', 'filter list', 'text')] + [makeDefenceConfigItem('INPUT_FILTERING', 'filter list', 'text')] ), makeDefence( - DEFENCE_ID.FILTER_BOT_OUTPUT, + DEFENCE_ID.OUTPUT_FILTERING, 'Output Filtering', 'Use a block list of words or phrases to check against bot output. If a match is found, the message is blocked.', - [makeDefenceConfigItem('FILTER_BOT_OUTPUT', 'filter list', 'text')] + [makeDefenceConfigItem('OUTPUT_FILTERING', 'filter list', 'text')] ), makeDefence( DEFENCE_ID.XML_TAGGING, diff --git a/frontend/src/components/ControlPanel/ControlPanel.tsx b/frontend/src/components/ControlPanel/ControlPanel.tsx index e5537b124..776dd85d1 100644 --- a/frontend/src/components/ControlPanel/ControlPanel.tsx +++ b/frontend/src/components/ControlPanel/ControlPanel.tsx @@ -2,6 +2,7 @@ import { MODEL_DEFENCES } from '@src/Defences'; import DefenceBox from '@src/components/DefenceBox/DefenceBox'; import DocumentViewButton from '@src/components/DocumentViewer/DocumentViewButton'; import ModelBox from '@src/components/ModelBox/ModelBox'; +import { ChatMessage } from '@src/models/chat'; // Move this import statement above the import statement for '@src/models/defence' import { DEFENCE_ID, DefenceConfigItem, Defence } from '@src/models/defence'; import { LEVEL_NAMES } from '@src/models/level'; @@ -15,6 +16,7 @@ function ControlPanel({ resetDefenceConfiguration, setDefenceConfiguration, openDocumentViewer, + addChatMessage, }: { currentLevel: LEVEL_NAMES; defences: Defence[]; @@ -26,6 +28,7 @@ function ControlPanel({ config: DefenceConfigItem[] ) => Promise; openDocumentViewer: () => void; + addChatMessage: (message: ChatMessage) => void; }) { const configurableDefences = defences.filter( (defence) => !MODEL_DEFENCES.some((id) => id === defence.id) @@ -74,7 +77,10 @@ function ControlPanel({ {/* only show model box in sandbox mode */} {showConfigurations && ( - + )} diff --git a/frontend/src/components/DefenceBox/DefenceMechanism.tsx b/frontend/src/components/DefenceBox/DefenceMechanism.tsx index ed7c73bcf..0348832ba 100644 --- a/frontend/src/components/DefenceBox/DefenceMechanism.tsx +++ b/frontend/src/components/DefenceBox/DefenceMechanism.tsx @@ -1,8 +1,6 @@ import { useState } from 'react'; -import { TiTick, TiTimes } from 'react-icons/ti'; import { DEFENCE_ID, DefenceConfigItem, Defence } from '@src/models/defence'; -import { validateDefence } from '@src/service/defenceService'; import DefenceConfiguration from './DefenceConfiguration'; import PromptEnclosureDefenceMechanism from './PromptEnclosureDefenceMechanism'; @@ -27,22 +25,10 @@ function DefenceMechanism({ config: DefenceConfigItem[] ) => Promise; }) { - const [showConfiguredText, setShowConfiguredText] = useState(false); - const [configValidated, setConfigValidated] = useState(true); const [configKey, setConfigKey] = useState(0); - function showDefenceConfiguredText(isValid: boolean) { - setShowConfiguredText(true); - setConfigValidated(isValid); - // hide the message after 3 seconds - setTimeout(() => { - setShowConfiguredText(false); - }, 3000); - } - function resetConfigurationValue(defence: Defence, configId: string) { resetDefenceConfiguration(defence.id, configId); - showDefenceConfiguredText(true); } async function setConfigurationValue( @@ -50,23 +36,14 @@ function DefenceMechanism({ configId: string, value: string ) { - const configIsValid = validateDefence(defence.id, configId, value); - if (configIsValid) { - const newConfiguration = defence.config.map((config) => { - if (config.id === configId) { - config.value = value; - } - return config; - }); + const newConfiguration = defence.config.map((config) => { + if (config.id === configId) { + config.value = value; + } + return config; + }); - const configured = await setDefenceConfiguration( - defence.id, - newConfiguration - ); - showDefenceConfiguredText(configured); - } else { - showDefenceConfiguredText(false); - } + await setDefenceConfiguration(defence.id, newConfiguration); } return (
@@ -126,17 +103,6 @@ function DefenceMechanism({ resetConfigurationValue={resetConfigurationValue} /> )} - - {showConfiguredText && - (configValidated ? ( -

- defence successfully configured -

- ) : ( -

- invalid input - configuration failed -

- ))}
diff --git a/frontend/src/components/HandbookOverlay/HandbookOverlay.css b/frontend/src/components/HandbookOverlay/HandbookOverlay.css index ba6d1b389..972ad1b04 100644 --- a/frontend/src/components/HandbookOverlay/HandbookOverlay.css +++ b/frontend/src/components/HandbookOverlay/HandbookOverlay.css @@ -23,11 +23,11 @@ } .handbook-overlay .content { + overflow-y: auto; margin-top: 3rem; margin-right: 0.5rem; margin-bottom: 0.25rem; padding: 0 1.75rem 0.5rem; - overflow-y: auto; /* firefox scrollbar styling */ scrollbar-color: var(--handbook-scrollbar-colour) transparent; diff --git a/frontend/src/components/HandbookOverlay/HandbookPage.css b/frontend/src/components/HandbookOverlay/HandbookPage.css index f9ac619b6..156078aeb 100644 --- a/frontend/src/components/HandbookOverlay/HandbookPage.css +++ b/frontend/src/components/HandbookOverlay/HandbookPage.css @@ -36,8 +36,8 @@ } .handbook-terms .system-role-error-message { - border: 0.125rem dashed var(--error-colour); - background-color: var(--error-background-colour); padding: 0.625rem; + border: 0.125rem dashed var(--error-colour); border-radius: 0.625rem; + background-color: var(--error-background-colour); } diff --git a/frontend/src/components/MainComponent/MainBody.tsx b/frontend/src/components/MainComponent/MainBody.tsx index 4504fe5b3..0fcbf97ca 100644 --- a/frontend/src/components/MainComponent/MainBody.tsx +++ b/frontend/src/components/MainComponent/MainBody.tsx @@ -54,6 +54,7 @@ function MainBody({ resetDefenceConfiguration={resetDefenceConfiguration} setDefenceConfiguration={setDefenceConfiguration} openDocumentViewer={openDocumentViewer} + addChatMessage={addChatMessage} />
diff --git a/frontend/src/components/MainComponent/MainComponent.tsx b/frontend/src/components/MainComponent/MainComponent.tsx index 35f29a0fe..91e2ce717 100644 --- a/frontend/src/components/MainComponent/MainComponent.tsx +++ b/frontend/src/components/MainComponent/MainComponent.tsx @@ -184,6 +184,9 @@ function MainComponent({ return defence; }); setDefencesToShow(newDefences); + // add info message to chat + const displayedDefenceId = defenceId.replace(/_/g, ' ').toLowerCase(); + addInfoMessage(`${displayedDefenceId} defence reset`); } async function setDefenceToggle(defence: Defence) { @@ -216,6 +219,9 @@ function MainComponent({ return defence; }); setDefencesToShow(newDefences); + // add info message to chat + const displayedDefenceId = defenceId.replace(/_/g, ' ').toLowerCase(); + addInfoMessage(`${displayedDefenceId} defence configured`); } return success; } diff --git a/frontend/src/components/ModelBox/ModelBox.tsx b/frontend/src/components/ModelBox/ModelBox.tsx index 84f779a71..011ce532b 100644 --- a/frontend/src/components/ModelBox/ModelBox.tsx +++ b/frontend/src/components/ModelBox/ModelBox.tsx @@ -1,13 +1,24 @@ +import { ChatMessage } from '@src/models/chat'; + import ModelConfiguration from './ModelConfiguration'; import ModelSelection from './ModelSelection'; import './ModelBox.css'; -function ModelBox({ chatModelOptions }: { chatModelOptions: string[] }) { +function ModelBox({ + chatModelOptions, + addChatMessage, +}: { + chatModelOptions: string[]; + addChatMessage: (message: ChatMessage) => void; +}) { return (
- - + +
); } diff --git a/frontend/src/components/ModelBox/ModelConfiguration.tsx b/frontend/src/components/ModelBox/ModelConfiguration.tsx index 39ab5d73d..f39460c20 100644 --- a/frontend/src/components/ModelBox/ModelConfiguration.tsx +++ b/frontend/src/components/ModelBox/ModelConfiguration.tsx @@ -1,13 +1,21 @@ import { useEffect, useState } from 'react'; -import { CustomChatModelConfiguration, MODEL_CONFIG } from '@src/models/chat'; +import { + ChatMessage, + CustomChatModelConfiguration, + MODEL_CONFIG, +} from '@src/models/chat'; import { getGptModel } from '@src/service/chatService'; import ModelConfigurationSlider from './ModelConfigurationSlider'; import './ModelConfiguration.css'; -function ModelConfiguration() { +function ModelConfiguration({ + addChatMessage, +}: { + addChatMessage: (message: ChatMessage) => void; +}) { const [customChatModelConfigs, setCustomChatModel] = useState< CustomChatModelConfiguration[] >([ @@ -67,7 +75,11 @@ function ModelConfiguration() { return (
{customChatModelConfigs.map((config) => ( - + ))}
); diff --git a/frontend/src/components/ModelBox/ModelConfigurationSlider.tsx b/frontend/src/components/ModelBox/ModelConfigurationSlider.tsx index 417fc83f1..e6b12bf31 100644 --- a/frontend/src/components/ModelBox/ModelConfigurationSlider.tsx +++ b/frontend/src/components/ModelBox/ModelConfigurationSlider.tsx @@ -2,15 +2,21 @@ import { Slider } from '@mui/material'; import { useEffect, useState } from 'react'; import { AiOutlineInfoCircle } from 'react-icons/ai'; -import { CustomChatModelConfiguration } from '@src/models/chat'; +import { + CHAT_MESSAGE_TYPE, + ChatMessage, + CustomChatModelConfiguration, +} from '@src/models/chat'; import { configureGptModel } from '@src/service/chatService'; import './ModelConfigurationSlider.css'; function ModelConfigurationSlider({ config, + addChatMessage, }: { config: CustomChatModelConfiguration; + addChatMessage: (message: ChatMessage) => void; }) { const [value, setValue] = useState(config.value); const [showInfo, setShowInfo] = useState(false); @@ -18,6 +24,10 @@ function ModelConfigurationSlider({ async function handleValueChange(_: Event, value: number | number[]) { const val = Array.isArray(value) ? value[0] : value; setValue(val); + addChatMessage({ + type: CHAT_MESSAGE_TYPE.INFO, + message: `${config.name} set to ${val}`, + }); await configureGptModel(config.id, val); } diff --git a/frontend/src/components/ModelBox/ModelSelection.tsx b/frontend/src/components/ModelBox/ModelSelection.tsx index 4d0b34ce6..fd5350a13 100644 --- a/frontend/src/components/ModelBox/ModelSelection.tsx +++ b/frontend/src/components/ModelBox/ModelSelection.tsx @@ -2,12 +2,19 @@ import { useEffect, useState } from 'react'; import LoadingButton from '@src/components/ThemedButtons/LoadingButton'; +import { CHAT_MESSAGE_TYPE, ChatMessage } from '@src/models/chat'; import { setGptModel, getGptModel } from '@src/service/chatService'; import './ModelSelection.css'; // return a drop down menu with the models -function ModelSelection({ chatModelOptions }: { chatModelOptions: string[] }) { +function ModelSelection({ + chatModelOptions, + addChatMessage, +}: { + chatModelOptions: string[]; + addChatMessage: (message: ChatMessage) => void; +}) { // model currently selected in the dropdown const [selectedModel, setSelectedModel] = useState(null); // model in use by the app @@ -22,6 +29,10 @@ function ModelSelection({ chatModelOptions }: { chatModelOptions: string[] }) { if (!isSettingModel && selectedModel) { const currentSelectedModel = selectedModel; console.log(`selected model: ${currentSelectedModel}`); + addChatMessage({ + type: CHAT_MESSAGE_TYPE.INFO, + message: `GPT model changed to: ${currentSelectedModel}`, + }); setIsSettingModel(true); const modelUpdated = await setGptModel(currentSelectedModel); setIsSettingModel(false); diff --git a/frontend/src/components/ThemedButtons/ThemedButton.css b/frontend/src/components/ThemedButtons/ThemedButton.css index a704d9514..caa0a8135 100644 --- a/frontend/src/components/ThemedButtons/ThemedButton.css +++ b/frontend/src/components/ThemedButtons/ThemedButton.css @@ -21,8 +21,8 @@ } .themed-button.disabled { - background-color: var(--action-button-disabled-background-colour); border-color: var(--action-button-disabled-background-colour); + background-color: var(--action-button-disabled-background-colour); color: var(--action-button-disabled-text-colour); } diff --git a/frontend/src/models/defence.ts b/frontend/src/models/defence.ts index 09fee06e9..2f0fcfbeb 100644 --- a/frontend/src/models/defence.ts +++ b/frontend/src/models/defence.ts @@ -6,8 +6,8 @@ enum DEFENCE_ID { XML_TAGGING = 'XML_TAGGING', RANDOM_SEQUENCE_ENCLOSURE = 'RANDOM_SEQUENCE_ENCLOSURE', INSTRUCTION = 'INSTRUCTION', - FILTER_USER_INPUT = 'FILTER_USER_INPUT', - FILTER_BOT_OUTPUT = 'FILTER_BOT_OUTPUT', + INPUT_FILTERING = 'INPUT_FILTERING', + OUTPUT_FILTERING = 'OUTPUT_FILTERING', PROMPT_ENCLOSURE = 'PROMPT_ENCLOSURE', } @@ -16,8 +16,8 @@ type DEFENCE_CONFIG_ITEM_ID = | 'PROMPT' | 'SYSTEM_ROLE' | 'SEQUENCE_LENGTH' - | 'FILTER_USER_INPUT' - | 'FILTER_BOT_OUTPUT'; + | 'INPUT_FILTERING' + | 'OUTPUT_FILTERING'; type DefenceConfigItem = { id: DEFENCE_CONFIG_ITEM_ID; diff --git a/frontend/src/service/defenceService.ts b/frontend/src/service/defenceService.ts index cbb4d105d..3edf83d4f 100644 --- a/frontend/src/service/defenceService.ts +++ b/frontend/src/service/defenceService.ts @@ -85,8 +85,8 @@ function validateDefence( switch (defenceId) { case DEFENCE_ID.CHARACTER_LIMIT: return validatePositiveNumberConfig(config); - case DEFENCE_ID.FILTER_USER_INPUT: - case DEFENCE_ID.FILTER_BOT_OUTPUT: + case DEFENCE_ID.INPUT_FILTERING: + case DEFENCE_ID.OUTPUT_FILTERING: return validateFilterConfig(config); case DEFENCE_ID.RANDOM_SEQUENCE_ENCLOSURE: return configId === 'SEQUENCE_LENGTH'