@eeacms/volto-eea-chatbot 2.0.5 → 3.0.1

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.
Files changed (36) hide show
  1. package/.github/workflows/betterleaks.yml +133 -0
  2. package/.gitleaks.toml +89 -0
  3. package/AGENTS.md +230 -0
  4. package/CHANGELOG.md +40 -0
  5. package/README.md +59 -0
  6. package/RELEASE.md +1 -1
  7. package/locales/de/LC_MESSAGES/volto.po +44 -0
  8. package/locales/en/LC_MESSAGES/volto.po +44 -0
  9. package/locales/it/LC_MESSAGES/volto.po +44 -0
  10. package/locales/ro/LC_MESSAGES/volto.po +44 -0
  11. package/locales/volto.pot +46 -2
  12. package/package.json +2 -1
  13. package/src/AISearchInput/AISearchInputEdit.jsx +37 -0
  14. package/src/AISearchInput/AISearchInputView.jsx +130 -0
  15. package/src/AISearchInput/components/DeepResearchToggle.jsx +35 -0
  16. package/src/AISearchInput/components/DisclaimerText.jsx +10 -0
  17. package/src/AISearchInput/components/IntroHeader.jsx +24 -0
  18. package/src/AISearchInput/components/PromptChips.jsx +22 -0
  19. package/src/AISearchInput/components/SearchInput.jsx +53 -0
  20. package/src/AISearchInput/index.js +32 -0
  21. package/src/AISearchInput/messages.js +38 -0
  22. package/src/AISearchInput/schema.jsx +215 -0
  23. package/src/AISearchInput/styles.less +320 -0
  24. package/src/ChatBlock/ChatBlockView.jsx +4 -0
  25. package/src/ChatBlock/chat/ChatWindow.tsx +23 -0
  26. package/src/ChatBlock/packets/MultiToolRenderer.tsx +20 -11
  27. package/src/ChatBlock/services/messageProcessor.ts +32 -14
  28. package/src/ChatBlock/style.less +41 -51
  29. package/src/halloumi/filtering.js +2 -2
  30. package/src/halloumi/generative.test.js +1 -1
  31. package/src/halloumi/middleware.js +2 -2
  32. package/src/halloumi/middleware.test.js +5 -5
  33. package/src/icons/sparkle.svg +3 -0
  34. package/src/index.js +2 -0
  35. package/src/middleware.js +2 -2
  36. package/src/middleware.test.js +11 -11
@@ -0,0 +1,133 @@
1
+ name: Betterleaks
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ scan:
12
+ name: Scan for secrets
13
+ runs-on: ubuntu-latest
14
+ env:
15
+ SMTP_URL: ${{ secrets.SMTP_URL }}
16
+ SMTP_PORT: ${{ secrets.SMTP_PORT || '25' }}
17
+ SMTP_EMAIL: ${{ secrets.SMTP_EMAIL }}
18
+ SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 1
24
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
25
+
26
+ - name: Run Betterleaks
27
+ id: betterleaks
28
+ continue-on-error: true
29
+ uses: dortort/betterleaks-action@v0.1.0
30
+ with:
31
+ github-token: ${{ secrets.GITHUB_TOKEN }}
32
+ scan-mode: dir
33
+ scan-path: .
34
+ config: .gitleaks.toml
35
+ report-format: json
36
+ report-path: betterleaks-report.json
37
+ redact: "true"
38
+ no-color: "true"
39
+ no-banner: "true"
40
+ fail-on-leak: "true"
41
+
42
+ - name: Upload Betterleaks report
43
+ if: always()
44
+ uses: actions/upload-artifact@v4
45
+ with:
46
+ name: betterleaks-report
47
+ path: betterleaks-report.json
48
+ if-no-files-found: ignore
49
+
50
+ - name: Build Betterleaks email summary
51
+ id: leak_summary
52
+ if: steps.betterleaks.outcome == 'failure'
53
+ shell: bash
54
+ run: |
55
+ if [[ -s betterleaks-report.json ]]; then
56
+ jq -r '
57
+ def one_line:
58
+ tostring
59
+ | gsub("[\r\n]+"; " ")
60
+ | if length > 240 then .[0:240] + "..." else . end;
61
+
62
+ .[:20][]
63
+ | "- " + (.RuleID // "unknown-rule")
64
+ + " at " + (.File // "unknown-file")
65
+ + ":" + ((.StartLine // 0) | tostring)
66
+ + "\n match: " + ((.Match // .Secret // "REDACTED") | one_line)
67
+ ' betterleaks-report.json > betterleaks-email-summary.txt
68
+
69
+ count="$(jq 'length' betterleaks-report.json)"
70
+ if (( count > 20 )); then
71
+ {
72
+ echo ""
73
+ echo "... and $((count - 20)) more finding(s). Download the artifact for full details."
74
+ } >> betterleaks-email-summary.txt
75
+ fi
76
+ else
77
+ echo "No JSON report was generated. Download the workflow logs for details." > betterleaks-email-summary.txt
78
+ fi
79
+
80
+ {
81
+ echo "text<<BETTERLEAKS_SUMMARY"
82
+ cat betterleaks-email-summary.txt
83
+ echo "BETTERLEAKS_SUMMARY"
84
+ } >> "$GITHUB_OUTPUT"
85
+
86
+ - name: Resolve committer email
87
+ id: committer
88
+ if: steps.betterleaks.outcome == 'failure'
89
+ shell: bash
90
+ run: |
91
+ committer_email="$(git log -1 --format='%ce')"
92
+ author_email="$(git log -1 --format='%ae')"
93
+ email="$committer_email"
94
+ if [[ -z "$email" || "$email" == *"noreply.github.com"* ]]; then
95
+ email="$author_email"
96
+ fi
97
+ if [[ "$email" =~ ^[^[:space:]@]+@[^[:space:]@]+\.[^[:space:]@]+$ && "$email" != *"noreply.github.com"* ]]; then
98
+ echo "email=$email" >> "$GITHUB_OUTPUT"
99
+ else
100
+ echo "No deliverable committer email found; skipping Betterleaks email notification."
101
+ echo "email=" >> "$GITHUB_OUTPUT"
102
+ fi
103
+
104
+ - name: Email committer on Betterleaks failure
105
+ if: steps.betterleaks.outcome == 'failure' && steps.committer.outputs.email != '' && env.SMTP_URL != '' && env.SMTP_EMAIL != ''
106
+ uses: dawidd6/action-send-mail@v18
107
+ with:
108
+ server_address: ${{ env.SMTP_URL }}
109
+ server_port: ${{ env.SMTP_PORT }}
110
+ secure: ${{ env.SMTP_PORT == '465' }}
111
+ username: ${{ env.SMTP_EMAIL }}
112
+ password: ${{ env.SMTP_PASSWORD }}
113
+ from: ${{ env.SMTP_EMAIL }}
114
+ to: ${{ steps.committer.outputs.email }}
115
+ subject: "[Betterleaks] Secret scan failed in ${{ github.repository }}"
116
+ body: |
117
+ Betterleaks detected one or more potential secrets.
118
+
119
+ Repository: ${{ github.repository }}
120
+ Branch: ${{ github.ref_name }}
121
+ Commit: ${{ github.sha }}
122
+ Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
123
+
124
+ Findings:
125
+ ${{ steps.leak_summary.outputs.text }}
126
+
127
+ Download the betterleaks-report artifact from the workflow run for details.
128
+
129
+ - name: Fail if Betterleaks found leaks
130
+ if: steps.betterleaks.outcome == 'failure'
131
+ run: |
132
+ echo "Betterleaks detected one or more secrets. Download the betterleaks-report artifact from this workflow run for details."
133
+ exit 1
package/.gitleaks.toml ADDED
@@ -0,0 +1,89 @@
1
+ title = "Betterleaks config"
2
+
3
+ [extend]
4
+ useDefault = true
5
+
6
+ [[rules]]
7
+ id = "secret-literal-assignment"
8
+ description = "Secret-like literal assignment in source, YAML, env and config files"
9
+ regex = '''(?i)([A-Za-z0-9_.-]*(?:password|passwd|pwd|api[_-]?key|apikey|access[_-]?key|secret[_-]?access[_-]?key|private[_-]?key|client[_-]?secret|consumer[_-]?key|consumer[_-]?secret|(?:auth|access|refresh|session|api|bearer|id|jwt|csrf|xsrf|oauth)[_-]?token|translate[_-]?auth|translation[_-]?auth|auth[_-]?password|auth[_-]?key|auth[_-]?credentials|database[_-]?url|connection[_-]?string)[A-Za-z0-9_.-]*)[ \t]*[:=][ \t]*["'']?([^"''[:space:]#{}$.][^"''\n#{}]{2,})["'']?'''
10
+ secretGroup = 2
11
+ keywords = [
12
+ "password",
13
+ "passwd",
14
+ "pwd",
15
+ "api_key",
16
+ "apikey",
17
+ "access_key",
18
+ "private_key",
19
+ "client_secret",
20
+ "consumer_key",
21
+ "consumer_secret",
22
+ "auth_token",
23
+ "access_token",
24
+ "refresh_token",
25
+ "session_token",
26
+ "api_token",
27
+ "bearer_token",
28
+ "id_token",
29
+ "jwt_token",
30
+ "csrf_token",
31
+ "xsrf_token",
32
+ "oauth_token",
33
+ "translate_auth",
34
+ "translation_auth",
35
+ "auth_password",
36
+ "auth_key",
37
+ "auth_credentials",
38
+ "database_url",
39
+ "connection_string"
40
+ ]
41
+ tags = ["literal-secret"]
42
+
43
+ [[rules]]
44
+ id = "env-short-secret-assignment"
45
+ description = "Uppercase env-style PASS/TOKEN/SECRET assignment"
46
+ regex = '''\b((?:PASS|TOKEN|SECRET|[A-Z0-9_]*(?:_PASS|_TOKEN|_SECRET|PASS_|TOKEN_|SECRET_)[A-Z0-9_]*))[ \t]*[:=][ \t]*["'']?([^"''[:space:]#{}$.][^"''\n#{}]{2,})["'']?'''
47
+ secretGroup = 2
48
+ keywords = [
49
+ "PASS",
50
+ "TOKEN",
51
+ "SECRET"
52
+ ]
53
+ tags = ["env", "literal-secret"]
54
+
55
+ [[rules]]
56
+ id = "standalone-sk-token"
57
+ description = "Standalone sk-* token not attached to a secret-like variable name"
58
+ regex = '''(?i)\b(sk-[A-Za-z0-9][A-Za-z0-9_-]{20,})\b'''
59
+ secretGroup = 1
60
+ entropy = 2.5
61
+ keywords = ["sk-"]
62
+ tags = ["standalone-token", "generic"]
63
+
64
+ [[rules]]
65
+ id = "dotenv-only-jest-setup"
66
+ description = ".env may only contain the committed Jest setup lines"
67
+ path = '''(?i)(^|/)\.env$'''
68
+ regex = '''(?m)^(.+)$'''
69
+ secretGroup = 1
70
+ tags = ["file", "dotenv"]
71
+ [[rules.allowlists]]
72
+ regexTarget = "match"
73
+ regexes = [
74
+ '''^JEST_USE_SETUP=OFF # Jest configuration variables: ON, OFF\r?$''',
75
+ ]
76
+
77
+ [[rules]]
78
+ id = "forbidden-secret-file"
79
+ description = "Forbidden secret-bearing file committed to repository"
80
+ path = '''(?i)(^|/)(\.env\..*|\.npmrc|\.pypirc|id_rsa|id_ed25519|.*\.(pem|key|p12|pfx|jks|kubeconfig))$'''
81
+ regex = '''(?s).{1,}'''
82
+ tags = ["file", "secret-file"]
83
+
84
+ [[allowlists]]
85
+ description = "Allow Jenkins SonarQube token environment variable reference"
86
+ regexTarget = "match"
87
+ regexes = [
88
+ '''SONAR_AUTH_TOKEN''',
89
+ ]
package/AGENTS.md CHANGED
@@ -87,3 +87,233 @@ and consistency.
87
87
 
88
88
  For more detailed contribution guidelines, refer to `DEVELOP.md`.
89
89
  For release procedures, refer to `RELEASE.md`.
90
+
91
+ ---
92
+
93
+ ## Frontend Development Guide for AI Assistants
94
+
95
+ ### EEA Design System Tokens
96
+
97
+ The EEA Design System provides shared LESS tokens for colors, spacing, typography, borders, and shapes. These are available via `@eeacms/volto-design-tokens`.
98
+
99
+ **Importing tokens:**
100
+
101
+ ```less
102
+ @import '@eeacms/volto-design-tokens/src/colors'; // @blue-6, @grey-0, @green-4, etc.
103
+ @import '@eeacms/volto-design-tokens/src/shapes'; // @radius-1, @radius-3, @radius-round
104
+ @import '@eeacms/volto-design-tokens/src/borders'; // @border-size-1, @border-size-2
105
+ @import '@eeacms/volto-design-tokens/src/fonts'; // @font-size-0, @font-weight-6, @font-lineheight-2
106
+ ```
107
+
108
+ **Pitfall:** Do NOT import `@eeacms/volto-design-tokens/src/sizes` directly — it references `@1px` which is a Semantic UI variable not available in standalone LESS. Instead, inline the spacing tokens you need:
109
+
110
+ ```less
111
+ // Spacing tokens (from sizes.less, inlined to avoid @1px dependency)
112
+ @spacer: 4px;
113
+ @space-05: @spacer * 0.5; // 2px
114
+ @space-1: @spacer * 1; // 4px
115
+ @space-2: @spacer * 2; // 8px
116
+ @space-3: @spacer * 3; // 12px
117
+ @space-4: @spacer * 4; // 16px
118
+ @space-5: @spacer * 5; // 20px
119
+ @space-6: @spacer * 6; // 24px
120
+ @space-8: @spacer * 8; // 32px
121
+ ```
122
+
123
+ **When adding new LESS files that use design tokens, ensure `@eeacms/volto-design-tokens` is listed in `package.json` dependencies:**
124
+
125
+ ```json
126
+ "dependencies": {
127
+ "@eeacms/volto-design-tokens": "*"
128
+ }
129
+ ```
130
+
131
+ ### Rendering Slate (Rich Text) Content
132
+
133
+ Volto stores rich text as Slate JSON. To render it in view components, use `serializeNodes`:
134
+
135
+ ```jsx
136
+ import { serializeNodes } from '@plone/volto-slate/editor/render';
137
+
138
+ // In your component:
139
+ {someSlateContent && serializeNodes(someSlateContent)}
140
+ ```
141
+
142
+ **Do NOT use `SlateViewer` from `@plone/volto/components`** — it does not exist. The `serializeNodes` function is the correct approach (used internally by the ChatBlock's `AIMessage.tsx`).
143
+
144
+ ### Volto Block Registration Pattern
145
+
146
+ When creating a new Volto block:
147
+
148
+ 1. **Schema function** accepts `{ intl, data }` and returns a schema object:
149
+ ```jsx
150
+ export function MyBlockSchema({ intl, data }) {
151
+ return {
152
+ title: intl.formatMessage({ id: 'My Block', defaultMessage: 'My Block' }),
153
+ fieldsets: [{ id: 'default', title: 'Default', fields: ['myField'] }],
154
+ properties: { /* ... */ },
155
+ required: [],
156
+ };
157
+ }
158
+ ```
159
+
160
+ 2. **Edit component** must inject `intl` via `useIntl` and pass it to the schema:
161
+ ```jsx
162
+ import { useIntl } from 'react-intl';
163
+
164
+ const MyBlockEdit = (props) => {
165
+ const intl = useIntl();
166
+ const schema = React.useMemo(
167
+ () => MyBlockSchema({ intl, data: props.data }),
168
+ [props.data, intl],
169
+ );
170
+ // ... render with BlockDataForm
171
+ };
172
+ ```
173
+
174
+ 3. **Block registration** in `index.js`:
175
+ ```js
176
+ export default function installMyBlock(config) {
177
+ config.blocks.blocksConfig.myBlock = {
178
+ id: 'myBlock',
179
+ title: 'My Block',
180
+ icon: someSVG,
181
+ group: 'common',
182
+ view: MyBlockView,
183
+ edit: MyBlockEdit,
184
+ schema: MyBlockSchema,
185
+ // ...
186
+ };
187
+ return config;
188
+ }
189
+ ```
190
+
191
+ 4. **Wire into `src/index.js`**: `installMyBlock(config);`
192
+
193
+ ### Internationalization (i18n)
194
+
195
+ **All user-facing strings MUST use `react-intl`:**
196
+
197
+ ```jsx
198
+ import { FormattedMessage, defineMessages } from 'react-intl';
199
+
200
+ // In JSX:
201
+ <FormattedMessage id="Hello world" defaultMessage="Hello world" />
202
+
203
+ // For message definitions (e.g., in messages.js):
204
+ export default defineMessages({
205
+ greeting: { id: 'Hello world', defaultMessage: 'Hello world' },
206
+ });
207
+ ```
208
+
209
+ After adding new strings, run `make i18n` to extract them into PO files.
210
+
211
+ ### Semantic UI Toggle Checkboxes
212
+
213
+ **Avoid using Semantic UI `<Checkbox toggle>` for custom-styled toggles.** The toggle's internal DOM structure (`.box`, `label:before`) is difficult to style reliably across different background colors, and the default styles often clash with custom themes.
214
+
215
+ **Preferred approach:** Use a pure CSS toggle with a hidden `<input type="checkbox">`:
216
+
217
+ ```jsx
218
+ <label className="my-toggle">
219
+ <input type="checkbox" checked={enabled} onChange={(e) => onChange(e.target.checked)} />
220
+ <span className="my-toggle-slider" />
221
+ Label text
222
+ </label>
223
+ ```
224
+
225
+ ```less
226
+ .my-toggle {
227
+ display: inline-flex;
228
+ align-items: center;
229
+ gap: 8px;
230
+ cursor: pointer;
231
+
232
+ input { display: none; }
233
+
234
+ .my-toggle-slider {
235
+ position: relative;
236
+ width: 28px;
237
+ height: 16px;
238
+ border: 1px solid currentColor;
239
+ border-radius: 1rem;
240
+ background-color: rgba(currentColor, 0.15);
241
+
242
+ &::before {
243
+ position: absolute;
244
+ top: 1px;
245
+ left: 2px;
246
+ width: 12px;
247
+ height: 12px;
248
+ border-radius: 50%;
249
+ background-color: currentColor;
250
+ content: '';
251
+ transition: left 0.2s;
252
+ }
253
+ }
254
+
255
+ input:checked ~ .my-toggle-slider {
256
+ background-color: @green-4;
257
+ border-color: @green-4;
258
+
259
+ &::before { left: 13px; }
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### LESS Styling Conventions
265
+
266
+ - **Property ordering:** Stylelint enforces alphabetical property order. Run `make stylelint-fix` to auto-fix.
267
+ - **`:global()` usage:** Use `:global()` in LESS nesting to target Semantic UI or Volto classes without the parent selector prefix:
268
+ ```less
269
+ .my-component {
270
+ :global(.ui.button) { color: red; }
271
+ }
272
+ // Produces: .my-component .ui.button { color: red; }
273
+ ```
274
+
275
+ ### Testing Patterns
276
+
277
+ **Mocking common dependencies in Jest tests:**
278
+
279
+ ```js
280
+ // react-intl
281
+ jest.mock('react-intl', () => ({
282
+ useIntl: () => ({ formatMessage: ({ defaultMessage }) => defaultMessage }),
283
+ FormattedMessage: ({ defaultMessage }) => <span>{defaultMessage}</span>,
284
+ }));
285
+
286
+ // react-router-dom (Volto uses v5)
287
+ const mockHistory = { push: jest.fn(), replace: jest.fn() };
288
+ jest.mock('react-router-dom', () => ({ useHistory: () => mockHistory }));
289
+
290
+ // Volto components
291
+ jest.mock('@plone/volto/components/manage/Sidebar/SidebarPortal', () => ({
292
+ __esModule: true,
293
+ default: ({ selected, children }) =>
294
+ selected ? <div>{children}</div> : null,
295
+ }));
296
+ ```
297
+
298
+ ### Internal Import Paths
299
+
300
+ Use `@eeacms/volto-eea-chatbot/...` for internal imports (matches the Jest `moduleNameMapper`):
301
+
302
+ ```js
303
+ import SVGIcon from '@eeacms/volto-eea-chatbot/ChatBlock/components/Icon';
304
+ import SendIcon from '@eeacms/volto-eea-chatbot/icons/send.svg';
305
+ ```
306
+
307
+ ### Matomo Tracking
308
+
309
+ Use `trackEvent` from `@eeacms/volto-matomo/utils` for analytics:
310
+
311
+ ```js
312
+ import { trackEvent } from '@eeacms/volto-matomo/utils';
313
+
314
+ trackEvent({
315
+ category: 'Chatbot',
316
+ action: 'Some action',
317
+ name: 'Some name',
318
+ });
319
+ ```
package/CHANGELOG.md CHANGED
@@ -4,6 +4,46 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [3.0.1](https://github.com/eea/volto-eea-chatbot/compare/3.0.0...3.0.1) - 5 August 2026
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix: Add betterleaks github action - refs #304517 [dobri1408 - [`837c461`](https://github.com/eea/volto-eea-chatbot/commit/837c4619bd3dab3ffe06aeaabd0513c50e3066b4)]
12
+
13
+ ## [3.0.0](https://github.com/eea/volto-eea-chatbot/compare/2.0.5...3.0.0) - 7 July 2026
14
+
15
+ #### :bug: Bug Fixes
16
+
17
+ - fix: refine custom toggle switch sizing and proportions [Tiberiu Ichim - [`d4c7499`](https://github.com/eea/volto-eea-chatbot/commit/d4c749964f9a1be063fae930c01b4a34e608909d)]
18
+ - fix: use 50% border-radius for toggle knob instead of @radius-round [Tiberiu Ichim - [`9013d1c`](https://github.com/eea/volto-eea-chatbot/commit/9013d1c889b26715be7b6c8a3b76b9bbc20a96de)]
19
+ - fix: inline spacing tokens to avoid Semantic UI @1px dependency [Tiberiu Ichim - [`7cb8ee6`](https://github.com/eea/volto-eea-chatbot/commit/7cb8ee69710005632f76d6aabc171f0ac70561d8)]
20
+ - fix: add @eeacms/volto-design-tokens as dependency [Tiberiu Ichim - [`5573047`](https://github.com/eea/volto-eea-chatbot/commit/5573047ec574e6a50ec5fb39e673f993b439f237)]
21
+ - fix: replace Semantic UI Checkbox with custom CSS toggle switch [Tiberiu Ichim - [`8b6780b`](https://github.com/eea/volto-eea-chatbot/commit/8b6780b05b5f334142d53b7ce5070565d93e1fc5)]
22
+ - fix: remove custom checkbox styling, use Semantic UI defaults [Tiberiu Ichim - [`c070e90`](https://github.com/eea/volto-eea-chatbot/commit/c070e90142ea3ba7eb281193d32fe71066f6ef40)]
23
+ - fix: make deep research toggle checkbox visible [Tiberiu Ichim - [`793716f`](https://github.com/eea/volto-eea-chatbot/commit/793716ff52708f32b99644c9572975649c4b6a1e)]
24
+ - fix: place prompt chips and deep research toggle on same row [Tiberiu Ichim - [`97c2e82`](https://github.com/eea/volto-eea-chatbot/commit/97c2e82b54b7eb5612ef595bd4e7c83c231e2e8f)]
25
+ - fix: align deep research toggle to the right with flexbox [Tiberiu Ichim - [`64755cd`](https://github.com/eea/volto-eea-chatbot/commit/64755cd9d578081a12259ac991c7d8da67dda5e9)]
26
+ - fix: use EEA green/teal for accent variant instead of blue [Tiberiu Ichim - [`ff0e46c`](https://github.com/eea/volto-eea-chatbot/commit/ff0e46cb1a7c1c2b52e7524a6f95c135dcdd33b7)]
27
+ - fix: pass intl to AISearchInputSchema in edit component [Tiberiu Ichim - [`fd1144d`](https://github.com/eea/volto-eea-chatbot/commit/fd1144d0f351fd9630732b9c465c4ed4219cf1c7)]
28
+ - fix: import EEA Design System color tokens in styles.less [Tiberiu Ichim - [`d84cda9`](https://github.com/eea/volto-eea-chatbot/commit/d84cda9355e911607996a72539279cb53f2524b0)]
29
+ - fix: replace non-existent SlateViewer with serializeNodes from volto-slate [Tiberiu Ichim - [`246ac09`](https://github.com/eea/volto-eea-chatbot/commit/246ac099ebd0cd90879de9f52e4b124c3abbc8d5)]
30
+
31
+ #### :nail_care: Enhancements
32
+
33
+ - refactor: replace hardcoded values with EEA Design System tokens [Tiberiu Ichim - [`723c939`](https://github.com/eea/volto-eea-chatbot/commit/723c939546d8dbbc83b9df13860303d73478893a)]
34
+
35
+ #### :house: Internal changes
36
+
37
+ - chore: bump version to 3.0.0 (EEA design system dependency) [skip ci] [Tiberiu Ichim - [`bc5a8c1`](https://github.com/eea/volto-eea-chatbot/commit/bc5a8c1f72d4e706b096cb96d0d24c2c3f5ac0f8)]
38
+ - chore: [JENKINSFILE] sanitize sonarqube command Refs #305084 [valentinab25 - [`83bf08b`](https://github.com/eea/volto-eea-chatbot/commit/83bf08b7188548a50801b8e464a4d113f0cbbac4)]
39
+
40
+ #### :house: Documentation changes
41
+
42
+ - docs: add frontend development guide for AI assistants [Tiberiu Ichim - [`36a77dc`](https://github.com/eea/volto-eea-chatbot/commit/36a77dcc7c6b551d4f049066ced698ff905fd4ef)]
43
+
44
+ #### :hammer_and_wrench: Others
45
+
46
+ - test: pin Chromium version 149 to work with Cypress [valentinab25 - [`5db1fcc`](https://github.com/eea/volto-eea-chatbot/commit/5db1fcc53c3147cc35c5d8c561c5dd0776e683c7)]
7
47
  ### [2.0.5](https://github.com/eea/volto-eea-chatbot/compare/2.0.4...2.0.5) - 21 June 2026
8
48
 
9
49
  #### :bug: Bug Fixes
package/README.md CHANGED
@@ -162,6 +162,65 @@ See [RELEASE.md](https://github.com/eea/volto-eea-chatbot/blob/master/RELEASE.md
162
162
 
163
163
  See [DEVELOP.md](https://github.com/eea/volto-eea-chatbot/blob/master/DEVELOP.md).
164
164
 
165
+ ## Secret Scanning
166
+
167
+ This repository uses the Betterleaks GitHub Action to scan the current
168
+ repository content on every push and pull request. The scan uses the rules in
169
+ `.gitleaks.toml` and uploads a `betterleaks-report` artifact when a finding is
170
+ detected.
171
+
172
+ If the optional SMTP secrets are configured, failed scans also send an email to
173
+ the last commit committer. The workflow expects these repository or
174
+ organization secrets:
175
+
176
+ - `SMTP_URL`
177
+ - `SMTP_PORT` (optional, defaults to `25`)
178
+ - `SMTP_EMAIL`
179
+ - `SMTP_PASSWORD` (optional if the SMTP server does not require authentication)
180
+
181
+ Port `465` is sent with direct TLS; other ports use the default SMTP handshake.
182
+ The email includes a short finding summary from the redacted Betterleaks report,
183
+ including the redacted matched line from each finding.
184
+
185
+ There are three common outcomes:
186
+
187
+ 1. **Everything is OK.** The `Betterleaks / Scan for secrets` check is green and
188
+ no action is needed. Regular references to runtime values are OK, for example:
189
+
190
+ ```js
191
+ const tokenFromCookie = req.universalCookies.get('auth_token');
192
+ ```
193
+
194
+ 2. **A real secret was found.** The check is red and the workflow log asks you to
195
+ download the `betterleaks-report` artifact. Open the artifact from the GitHub
196
+ Actions run and check the reported file, line and rule. Remove the committed
197
+ value, move it to the proper secret store, and rotate it if it was exposed.
198
+ A report entry looks like this:
199
+
200
+ ```json
201
+ {
202
+ "RuleID": "secret-literal-assignment",
203
+ "File": "src/config.js",
204
+ "StartLine": 12,
205
+ "Secret": "[REDACTED]"
206
+ }
207
+ ```
208
+
209
+ 3. **The finding is a false positive.** Keep the value only if it is clearly not
210
+ sensitive, such as a test fixture, placeholder, or public example. Add
211
+ `betterleaks:allow` on the same line and include a short explanation in the
212
+ pull request.
213
+
214
+ ```js
215
+ const testPassword = 'admin'; //betterleaks:allow
216
+ ```
217
+
218
+ ```yaml
219
+ password: "admin" #betterleaks:allow
220
+ ```
221
+
222
+ Do not add `betterleaks:allow` to real credentials.
223
+
165
224
  ## Copyright and license
166
225
 
167
226
  The Initial Owner of the Original Code is European Environment Agency (EEA).
package/RELEASE.md CHANGED
@@ -33,7 +33,7 @@ Release-it is a tool that automates 4 important steps in the release process:
33
33
  To configure the authentification, you need to export GITHUB_TOKEN for [GitHub](https://github.com/settings/tokens)
34
34
 
35
35
  ```
36
- export GITHUB_TOKEN=XXX-XXXXXXXXXXXXXXXXXXXXXX
36
+ export GITHUB_TOKEN="${GITHUB_TOKEN}"
37
37
  ```
38
38
 
39
39
  To configure npm, you can use the `npm login` command or use a configuration file with a TOKEN :
@@ -11,4 +11,48 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "AI Search Input"
15
+ #: AISearchInput/messages
16
+ msgid "AI Search Input"
17
+ msgstr ""
18
+
19
+ #. Default: "Ask your question..."
20
+ #: AISearchInput/components/SearchInput
21
+ #: AISearchInput/messages
22
+ msgid "Ask your question..."
23
+ msgstr ""
24
+
25
+ #. Default: "Assistant page is not configured. Please contact the site administrator."
26
+ #: AISearchInput/AISearchInputView
27
+ #: AISearchInput/messages
28
+ msgid "Assistant page is not configured. Please contact the site administrator."
29
+ msgstr ""
30
+
31
+ #. Default: "Deep research"
32
+ #: AISearchInput/components/DeepResearchToggle
33
+ #: AISearchInput/messages
34
+ msgid "Deep research"
35
+ msgstr ""
14
36
 
37
+ #. Default: "Deep research on"
38
+ #: AISearchInput/components/DeepResearchToggle
39
+ #: AISearchInput/messages
40
+ msgid "Deep research on"
41
+ msgstr ""
42
+
43
+ #. Default: "Invalid assistant page URL."
44
+ #: AISearchInput/AISearchInputView
45
+ #: AISearchInput/messages
46
+ msgid "Invalid assistant page URL."
47
+ msgstr ""
48
+
49
+ #. Default: "Submit question"
50
+ #: AISearchInput/components/SearchInput
51
+ #: AISearchInput/messages
52
+ msgid "Submit question"
53
+ msgstr ""
54
+
55
+ #. Default: "This assistant uses AI. Responses may contain inaccuracies."
56
+ #: AISearchInput/messages
57
+ msgid "This assistant uses AI. Responses may contain inaccuracies."
58
+ msgstr ""
@@ -11,4 +11,48 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "AI Search Input"
15
+ #: AISearchInput/messages
16
+ msgid "AI Search Input"
17
+ msgstr ""
18
+
19
+ #. Default: "Ask your question..."
20
+ #: AISearchInput/components/SearchInput
21
+ #: AISearchInput/messages
22
+ msgid "Ask your question..."
23
+ msgstr ""
24
+
25
+ #. Default: "Assistant page is not configured. Please contact the site administrator."
26
+ #: AISearchInput/AISearchInputView
27
+ #: AISearchInput/messages
28
+ msgid "Assistant page is not configured. Please contact the site administrator."
29
+ msgstr ""
30
+
31
+ #. Default: "Deep research"
32
+ #: AISearchInput/components/DeepResearchToggle
33
+ #: AISearchInput/messages
34
+ msgid "Deep research"
35
+ msgstr ""
14
36
 
37
+ #. Default: "Deep research on"
38
+ #: AISearchInput/components/DeepResearchToggle
39
+ #: AISearchInput/messages
40
+ msgid "Deep research on"
41
+ msgstr ""
42
+
43
+ #. Default: "Invalid assistant page URL."
44
+ #: AISearchInput/AISearchInputView
45
+ #: AISearchInput/messages
46
+ msgid "Invalid assistant page URL."
47
+ msgstr ""
48
+
49
+ #. Default: "Submit question"
50
+ #: AISearchInput/components/SearchInput
51
+ #: AISearchInput/messages
52
+ msgid "Submit question"
53
+ msgstr ""
54
+
55
+ #. Default: "This assistant uses AI. Responses may contain inaccuracies."
56
+ #: AISearchInput/messages
57
+ msgid "This assistant uses AI. Responses may contain inaccuracies."
58
+ msgstr ""