Wazuh-owned AI context for wazuh-dashboard-security-analytics. Keep it short:
this file points to the source-of-truth docs instead of duplicating them. Read the
linked doc before doing non-trivial work.
A single OpenSearch Dashboards (OSD) plugin — the Wazuh fork of
opensearch-project/security-analytics-dashboards-plugin.
It provides the Security Analytics UI in the Wazuh dashboard (rules, decoders,
integrations, filters, log test, detectors…). It is not the platform — the
platform is the sibling repo wazuh-dashboard (an OSD fork), into which this
plugin is installed under its external ./plugins/ directory (alongside the
plugins from wazuh-dashboard-plugins).
- OSD id:
securityAnalyticsDashboards(opensearch_dashboards.json); config pathopensearch_security_analytics; package nameopensearch_security_analytics_dashboards. - Versioning: OSD base in
package.json→opensearchDashboards.version(e.g.3.6.0) andopensearch_dashboards.json→opensearchDashboardsVersion; Wazuh version inVERSION.jsonandpackage.json→wazuh(e.g.5.0.0, revision04). - Node/Yarn: this plugin has no own
.nvmrc— it uses the toolchain of thewazuh-dashboardcheckout it lives in (Node22.22.0, Yarn v1). Its scripts reference the parent checkout (../../scripts/*,../../node_modules/.bin/*), so it is developed from insidewazuh-dashboard/plugins/, not standalone. - Default branch
main; work happens on version branches (5.0.0,6.0.0, …).
This is one self-contained plugin. Its code splits into layers that are bundled separately:
public/— runs in the browser (React, EUI/OUI,core.http). Uses DOM/window. Holdscomponents/,pages/,hooks/,metrics/,models/,plugin.ts,security_analytics_app.tsx.server/— runs in Node.js (Hapi routes under/api/, services, cluster clients). Usesfs, server context, secrets. Holdsroutes/,services/,clusters/,models/,utils/,plugin.ts.common/— isomorphic code shared by both:constants.ts,helpers.ts,schemas/. No DOM, no Node-only APIs.- Plus
models/andtypes/(shared TS types) andconfig.ts(plugin config schema,@osd/config-schema).
Import rules (strict):
public/must never import fromserver/, andserver/must never import frompublic/. Putting Node code in a browser bundle (or vice-versa) breaks the build/runtime.- Both
public/andserver/may import fromcommon/. Put anything shared incommon/. - Cross-plugin access (e.g. to plugins from
wazuh-dashboard-pluginsor built-in OSD plugins) goes layer-to-layer (public → other/public,server → other/server) and only via a plugin's declaredsetup()/start()contracts +requiredPlugins/optionalPluginsinopensearch_dashboards.json— never reach into internal paths.
They do not import each other — they talk over HTTP: server/routes/*
register endpoints (/api/..., validated with @osd/config-schema) that delegate
to services / cluster clients; public/ calls those routes via OSD core.http.
setup(core, deps) (register routes, saved objects, UI app, services) →
start(core, deps) → stop(). Use core.getStartServices() in mount handlers
instead of storing start references as fields.
This plugin's scripts expect to run at wazuh-dashboard/plugins/<this-plugin>
(they call ../../scripts/* and ../../node_modules/.bin/*). Bootstrap the
platform first, then run per-plugin scripts here:
# From the wazuh-dashboard root (installs deps + builds internal packages):
yarn osd bootstrap
# From this plugin's dir (wazuh-dashboard/plugins/<this-plugin>):
yarn lint # node ../../scripts/eslint . (@elastic/kibana config)
yarn test:jest # jest --config ./test/jest.config.js
yarn test:jest:dev # jest --watch
yarn build # plugin-helpers build → build/security-analytics-dashboards-*.zip
yarn cypress:run # Cypress E2E (also: cypress:open)There is no format, lint:fix, typecheck, or knip script here.
Formatting is enforced on commit by husky + lint-staged (prettier --write
on staged files; .prettierignore skips *.md). Prettier/tsconfig configs are
inherited from the parent OSD checkout (../../.prettierrc, ../../tsconfig.json
via tsconfig.json's extends). To typecheck manually:
../../node_modules/.bin/tsc --noEmit -p tsconfig.json.
This plugin has no dev environment of its own. The canonical way to bring up a
local Wazuh dashboard with this plugin — together with the other additional
single-plugin forks (wazuh-dashboard-notifications, wazuh-dashboard-alerting,
wazuh-dashboard-reporting) — is the Docker dev env owned by
wazuh-dashboard-plugins (docker/osd-dev). Mount this repo into it with -r:
# from the sibling wazuh-dashboard-plugins checkout:
cd ../wazuh-dashboard-plugins/docker/osd-dev
./dev.sh up --base --server-local 0601 --indexer-local 0601 \
-r wazuh-dashboard-security-analytics \
-r wazuh-dashboard-notifications \
-r wazuh-dashboard-alerting--base— build/run thewazuh-dashboardplatform from source (auto-detected from the sibling checkout; or--base /abs/path).--server-local <tag>— Wazuh server-local image tag (here0601).--indexer-local <tag>— packaged indexer image tag.-r <repo>— mount an external plugin repo (repeatable). Shorthand resolves the repo by name under the sibling parent dir (the parent of this checkout); or use-r name=/abs/path. Point to the repository ROOT, not a subfolder.--all-forksauto-discovers and mounts all sibling forks.
Run ./dev.sh --help for all flags. OSD comes up on https://0.0.0.0:5601
(admin:admin).
Enforced by tooling — run the linter/formatter, don't hand-format:
- ESLint config is
.eslintrc(YAML) extending@elastic/kibana. - Filenames follow the upstream OpenSearch convention (PascalCase for
components, e.g.
ContentPanel.tsx) — this differs from the kebab-case used inwazuh-dashboard-plugins. Match the surrounding upstream style when editing. - TypeScript-first; single quotes; semicolons; Prettier defaults from the parent checkout.
- English everywhere (code, comments, commits, docs).
- User-facing copy follows
TERMINOLOGY.md— one noun per concept, one verb per action. Read it before writing any label, column header, button, tooltip or empty state; introducing a synonym for an existing term is a regression. Wazuh-owned file, not upstream.
- Unit tests are colocated as
*.test.ts/*.test.tsxnext to the source (many use jest snapshots under__snapshots__/). Run withyarn test:jest; update snapshots withyarn test:jest:update-snapshots. When you add a source file, add its test beside it. - Functional: Cypress (
.cypress/,cypress.config.js) viayarn cypress:*.
Shared Wazuh Dashboard conventions:
- Branch names:
<type>/<issue#>-<kebab-desc>(fix/,enhancement/,feat/,bug/,change/,doc/). PR base = the target version branch, not alwaysmain— confirm it. - Sign commits (DCO
--signoff). Imperative, capitalized subject. - Open PRs as Draft (CI skips drafts); run lint + tests locally, then "Ready for review". Squash merge for single-purpose PRs.
- UI changes require a screenshot/video in the PR (
### Results and Evidencesection of the PR template); manual verification steps go in### How to Test. - Changelog: maintain
CHANGELOG.mdby hand for user-facing changes; entries link to the issue, not the PR. No entry forinternal-devel-requestsissues or tooling/docs/test-only PRs. - Issues arrive as URLs and may live in another repo. Issues from
internal-devel-requestsare internal: don't expose their link in the PR (leave the## Descriptionclosing reference empty, noCloses #<issue_number>) and add no CHANGELOG entry.
Upstream is opensearch-project/security-analytics-dashboards-plugin. On upstream
syncs, Wazuh content wins and relevant upstream technical notes are folded
into the sections above. Keep this file Wazuh-owned.
- Before proposing a PR:
yarn lint+yarn test:jestpass for the touched code. - Never weaken auth/CSP/security; never commit secrets or credentials.
- Never force-push shared branches; never commit without DCO sign-off.
- Respect the
public/server/commonimport rules above — when in doubt, put shared code incommon/.
DEVELOPER_GUIDE.md,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md.- Platform docs live in the sibling
wazuh-dashboardrepo (DEVELOPER_GUIDE.md,src/core/CONVENTIONS.md,src/core/TESTING.md).