Free, Open Source, Self-Hosted WhatsApp API Gateway
This report summarizes scanner evidence for rmyndharis/OpenWA, a TypeScript project with 16,420 GitHub stars. SynthScan examined 572,554 lines of code across 2093 source files, recording 1038 pattern matches distributed across 16 syntactic categories. The legacy adjusted pattern signal is 2.9 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 629 finding(s).
Are imports declared and package/API names verified? 154 finding(s).
Are wrappers, guards, and repeated structures necessary? 566 finding(s).
Which changes need focused human review? 1038 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 1038 distinct pattern matches across 16 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/webhooks.e2e-spec.ts | 128 | // ── CRUD over the REST surface ──────────────────────────────────── | COMMENT |
| MEDIUM | test/webhooks.e2e-spec.ts | 229 | // ── auth boundaries ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/webhooks.e2e-spec.ts | 247 | // ── registration validation ─────────────────────────────────────── | COMMENT |
| MEDIUM | test/webhooks.e2e-spec.ts | 283 | // ── dispatch over real HTTP ─────────────────────────────────────── | COMMENT |
| MEDIUM | test/webhooks.e2e-spec.ts | 401 | // ── payload bounds (per-session cap + inline-media shedding) ────── | COMMENT |
| MEDIUM | test/webhooks.e2e-spec.ts | 463 | // ── the test endpoint ───────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 360 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 362 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 369 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 371 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 476 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 478 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 486 | # =========================================== | COMMENT |
| MEDIUM⚡ | docs/10-devops-infrastructure.md | 488 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 387 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 389 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 430 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 432 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 458 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 460 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 523 | # =========================================== | COMMENT |
| MEDIUM | docs/10-devops-infrastructure.md | 525 | # =========================================== | COMMENT |
| MEDIUM | dashboard/src/utils/authLifecycle.test.ts | 87 | // ── App-level auth flow: exactly one /auth/validate per sign-in ────────────── | COMMENT |
| MEDIUM | dashboard/src/utils/sessionActions.test.ts | 100 | // ── replaceSession ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/utils/sessionActions.test.ts | 157 | // ── classifyUnlinkError ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 21 | // ── Query Keys ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 41 | // ── Session Queries ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 88 | // ── Webhook Queries ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 135 | // ── Template Queries ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 183 | // ── API Key Queries ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 253 | // ── Logs Queries ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 268 | // ── Infrastructure Queries ──────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 286 | // ── Plugin Queries ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/hooks/queries.ts | 362 | // ── Stats Queries ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 223 | // ── Live messages and the per-chat position memory ─────────────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 395 | // ── Which scroll events are the reader's ───────────────────────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 484 | // ── Following a live message ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 673 | // ── Media decoding ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 944 | // ── Older pages landing under a position the memory holds ──────────────────── | COMMENT |
| MEDIUM | …shboard/src/hooks/useChatScrollPosition.render.test.ts | 1042 | // ── A thread of message rows ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 29 | // ── Fixtures + fetch stub ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 220 | // ── DOM helpers ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 241 | // ── Harness bootstrap ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 287 | // ── Smoke tests ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 568 | // ── The engine radio's seed source (#1082) ─────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 568 | // ── The engine radio's seed source (#1082) ─────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 641 | // ── A switch saved and not restarted for ───────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 744 | // ── A built-in switch saved and not restarted for ──────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 1391 | // ── One rule for every saved and pinned state ──────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 2153 | // ── Built-in containers the restart stops ──────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 2943 | // ── Restart-flow timer cleanup on unmount ──────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Infrastructure.test.ts | 2969 | // ── Restart outcomes the server reports ────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Plugins.tsx | 397 | // ── Activation ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Plugins.tsx | 415 | // ── Per-session config override ─────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 24 | // ── Fixtures + fetch stub ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 336 | // ── Harness bootstrap ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 391 | // ── Smoke tests ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 1901 | // ── Live feed banner ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 2049 | // ── Auto-reject toggle ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | dashboard/src/pages/Sessions.test.ts | 2378 | // ── Live feed subscription ─────────────────────────────────────────────────── | COMMENT |
| 191 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | dashboard/src/utils/importRefusal.ts | 24 | export function shouldOfferStopOrphansRetry( | CODE |
| LOW | dashboard/src/utils/chatMessages.ts | 490 | export function unacknowledgedIncomingIds( | CODE |
| LOW | dashboard/src/utils/sessionScope.ts | 13 | export function sessionPickerStartsExpanded(selectedIds: readonly string[]): boolean { | CODE |
| LOW | dashboard/src/hooks/queries.ts | 146 | export function useCreateTemplateMutation() { | CODE |
| LOW | dashboard/src/hooks/queries.ts | 157 | export function useUpdateTemplateMutation() { | CODE |
| LOW | dashboard/src/hooks/queries.ts | 173 | export function useDeleteTemplateMutation() { | CODE |
| LOW⚡ | dashboard/src/hooks/queries.ts | 305 | export function useCreateInstanceMutation(pluginId: string) { | CODE |
| LOW⚡ | dashboard/src/hooks/queries.ts | 315 | export function useRegenerateInstanceSecretMutation(pluginId: string) { | CODE |
| LOW⚡ | dashboard/src/hooks/queries.ts | 325 | export function useUpdateInstanceMutation(pluginId: string) { | CODE |
| LOW | dashboard/src/hooks/queries.ts | 336 | export function useDeleteInstanceMutation(pluginId: string) { | CODE |
| LOW | dashboard/src/pages/Chats.test.ts | 215 | function countPagedMessagesFetches(): number { | CODE |
| LOW⚡ | sdk/python/tests/test_webhook.py | 20 | def test_accepts_the_gateway_signature_over_text_or_bytes(): | CODE |
| LOW⚡ | sdk/python/tests/test_webhook.py | 30 | def test_rejects_a_malformed_header(header): | CODE |
| LOW⚡ | sdk/python/tests/test_webhook.py | 34 | def test_rejects_a_changed_body_a_wrong_secret_and_an_empty_secret(): | CODE |
| LOW⚡ | sdk/python/tests/test_webhook.py | 42 | def test_delivery_type_accepts_the_test_event(): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 55 | def test_requires_base_url_and_api_key(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 61 | def test_sends_api_key_header(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 68 | def test_default_headers_cannot_override_api_key(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 211 | def test_strips_trailing_slash(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 217 | def test_sessions_list_sends_name(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 222 | def test_query_params_skip_none(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 235 | def test_build_url_escapes_a_literal_percent_in_a_query_value(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 241 | def test_build_url_refuses_a_path_without_a_leading_slash(self, path): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 250 | def test_build_url_omits_none_valued_params(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 349 | def test_the_api_key_loses_a_trailing_newline_and_an_illegal_one_is_refused_without_being_quoted(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 359 | def test_a_key_with_an_inner_space_is_accepted_as_the_gateway_and_other_clients_take_it(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 363 | def test_a_default_header_the_stack_would_refuse_is_refused_without_quoting_its_value(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 502 | def test_a_remote_http_base_url_warns_and_a_local_or_https_one_does_not(self) -> None: | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 512 | def test_the_context_manager_closes_the_client(self) -> None: | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 521 | def test_exposes_all_resources(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 532 | def test_send_methods_forward_keys_without_changing_json(self, key: str | None) -> None: | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 600 | def test_invalid_send_keys_are_refused_before_transport(self, key: str) -> None: | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 607 | def test_send_text_uses_send_text_path(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 613 | def test_send_text_forwards_mentions_verbatim(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 618 | def test_send_poll_uses_send_poll_path(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 657 | def test_send_template_accepts_template_name(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 662 | def test_list_returns_messages_total_wrapper(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 668 | def test_quoted_message_id_reaches_the_body_on_every_send(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1127 | def test_vote_poll_posts_option_texts(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1133 | def test_star_posts_the_boolean_through(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1139 | def test_pin_and_unpin_post_to_their_routes(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1149 | def test_message_media_fetches_archived_bytes(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1157 | def test_media_fetches_stored_status_bytes(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1241 | def test_chats_pin_reports_refusal(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1245 | def test_chats_mute_sends_epoch_milliseconds_unchanged(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1253 | def test_chats_mute_sends_explicit_null_to_unmute(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1376 | def test_client_exposes_all_resources(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1386 | def test_search_minimal_required_q(self): | CODE |
| LOW⚡ | sdk/python/tests/test_sdk.py | 1395 | def test_search_forwards_all_optional_filters(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 82 | def test_default_headers_cannot_override_api_key_in_another_case(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 105 | def test_path_segments_are_encoded(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 113 | def test_empty_or_dot_ids_are_refused_before_sending(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 129 | def test_raw_request_escape_hatch(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 135 | def test_treats_unfollowed_redirect_as_error(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 174 | def test_a_retry_after_too_long_to_parse_keeps_the_api_error(self, binary: bool) -> None: | CODE |
| LOW | sdk/python/tests/test_sdk.py | 190 | def test_errors_survive_pickle_and_copy(self) -> None: | CODE |
| LOW | sdk/python/tests/test_sdk.py | 261 | def test_raw_request_keeps_a_query_string_in_the_path(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 281 | def test_error_exposes_code_retry_after_and_headers(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 325 | def test_an_error_with_no_body_names_the_status_text_not_none(self): | CODE |
| LOW | sdk/python/tests/test_sdk.py | 334 | def test_an_httpx_timeout_or_a_tuple_is_taken_as_given(self): | CODE |
| 251 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.dev.yml | 1 | # OpenWA - Local smoke / quick-start compose | COMMENT |
| LOW | docker-compose.dev.yml | 41 | - '${BIND_HOST:-127.0.0.1}:${API_PORT:-2785}:2785' | COMMENT |
| LOW | docker-entrypoint.sh | 41 | if [ "$(id -u)" != 0 ]; then | COMMENT |
| LOW | docker-entrypoint.sh | 61 | # "$@" = CMD from Dockerfile (default: node dist/main). | COMMENT |
| LOW | docker-compose.yml | 21 | # PING (health), CONTAINERS (list/inspect/create/start/stop), | COMMENT |
| LOW | docker-compose.yml | 121 | # Database. Forwarded blank by default (`${VAR:-}`) so a dashboard switch saved to | COMMENT |
| LOW | docker-compose.yml | 141 | - DATABASE_SSL=${DATABASE_SSL:-} | COMMENT |
| LOW | docker-compose.yml | 161 | # and use the first-party build served by WhatsApp, or an exact version to pin a specific build. | COMMENT |
| LOW | test/setup-e2e.ts | 1 | // e2e boot environment. Set BEFORE AppModule is imported (setupFiles phase) so the | COMMENT |
| LOW | test/setup-e2e.ts | 21 | // Restoring parallelism means giving each worker its own data root, not just its own database. | COMMENT |
| LOW | charts/openwa/values.yaml | 1 | # replicaCount MUST stay 1. A session lease now stops two pods from launching the same | COMMENT |
| LOW | charts/openwa/values.yaml | 21 | # Non-secret application config, rendered into a ConfigMap and loaded via envFrom. | COMMENT |
| LOW | charts/openwa/values.yaml | 41 | API_MASTER_KEY: "" | COMMENT |
| LOW | charts/openwa/values.yaml | 81 | # enabled), where the bounded teardown stages add up to 63s: drain 3 + ingress reconciler 5 + engines | COMMENT |
| LOW | charts/openwa/values.yaml | 101 | # openwa user (uid/gid 997) via gosu, which needs the capabilities added below. | COMMENT |
| LOW | charts/openwa/values.yaml | 121 | # The entrypoint then skips its chown and privilege drop and runs as that uid; | COMMENT |
| LOW | charts/openwa/templates/statefulset.yaml | 61 | # Budget here is periodSeconds x (failureThreshold - 1) = 5s x (60-1) = 295s — the same | COMMENT |
| LOW | docs/12-troubleshooting-faq.md | 861 | COMMENT | |
| LOW | docs/08-development-guidelines.md | 681 | # Keys the dashboard manages (Dashboard > Infrastructure) are commented out with their defaults: | COMMENT |
| LOW | docs/08-development-guidelines.md | 701 | # Redis and queue disabled by default | COMMENT |
| LOW | docs/08-development-guidelines.md | 721 | COMMENT | |
| LOW | docs/08-development-guidelines.md | 741 | # DATABASE_POOL_SIZE=10 | COMMENT |
| LOW | docs/13-horizontal-scaling.md | 481 | # it limits the privileges the API process holds, not what a plugin inside that process can reach. | COMMENT |
| LOW | docs/03-system-architecture.md | 1581 | #### Standard Profile (.env) | COMMENT |
| LOW | docs/03-system-architecture.md | 1601 | COMMENT | |
| LOW | docs/14-migration-guide.md | 101 | # Step 2: Change the database configuration | COMMENT |
| LOW | docs/14-migration-guide.md | 261 | # Response: { "storageType": "local", "count": 150, "sizeBytes": 15000000 } | COMMENT |
| LOW | docs/14-migration-guide.md | 281 | # S3_ENDPOINT=http://minio:9000 | COMMENT |
| LOW | docs/14-migration-guide.md | 621 | ```bash | COMMENT |
| LOW | docs/14-migration-guide.md | 821 | source checkout, or `docker compose run --rm openwa-api npm run migration:run:main:prod` in the image. | COMMENT |
| LOW | docs/14-migration-guide.md | 1001 | COMMENT | |
| LOW | docs/11-operational-runbooks.md | 221 | COMMENT | |
| LOW | docs/11-operational-runbooks.md | 241 | # every slot they or its own message took, for the life of the process. A reconnect does not free | COMMENT |
| LOW | docs/11-operational-runbooks.md | 301 | # shutdown drain), or, with the queue disabled, stopped by shutdown in a retry backoff that | COMMENT |
| LOW | docs/11-operational-runbooks.md | 361 | # it. The outbox sweep runs only while WEBHOOK_RECONCILE_INTERVAL_MS > 0 (default 60000). It | COMMENT |
| LOW | docs/11-operational-runbooks.md | 381 | # failed > 0: the replay did not deliver, most often because the receiver still rejects it (the | COMMENT |
| LOW | docs/11-operational-runbooks.md | 441 | # BACKUP_DIR defaults to ./backups — it creates no dated subdirectories) | COMMENT |
| LOW | docs/11-operational-runbooks.md | 621 | # the checkout below because an image older than 0.23.7 cannot move its safety snapshot off the | COMMENT |
| LOW | docs/11-operational-runbooks.md | 661 | # a load that fails leaves nothing behind. An archive holding database.schema (a POSTGRES_SCHEMA other | COMMENT |
| LOW | docs/11-operational-runbooks.md | 761 | # - openwa.sqlite — user data (DATABASE_NAME, default ./data/openwa.sqlite; | COMMENT |
| LOW | docs/11-operational-runbooks.md | 781 | # (default: <OPENWA_DATA_DIR>/plugins) | COMMENT |
| LOW | docs/11-operational-runbooks.md | 961 | # defaults and a ./data/... path from ./.env or .env.generated are read under OPENWA_DATA_DIR, | COMMENT |
| LOW | docs/11-operational-runbooks.md | 1001 | # sslmode=prefer accepts any certificate. verify-full also needs PGSSLROOTCERT set to the server's | COMMENT |
| LOW | docs/11-operational-runbooks.md | 1201 | COMMENT | |
| LOW | docs/10-devops-infrastructure.md | 361 | # APPLICATION | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 381 | # DATABASE_NAME=openwa | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 401 | # STORAGE_TYPE accepts only `local` or `s3` — env validation rejects anything else and the app | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 421 | COMMENT | |
| LOW | docs/10-devops-infrastructure.md | 441 | # # (cache, rate limits, queue, WebSocket fan-out) uses it. Private CA: NODE_EXTRA_CA_CERTS in the | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 461 | # ENGINE_TYPE=baileys # whatsapp-web.js (default) | baileys; omit to use the dashboard selection | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 481 | # API_MASTER_KEY= | COMMENT |
| LOW | docs/10-devops-infrastructure.md | 501 | # used when Redis rejects an enqueue is not capped. Queued, it applies to every job attempt | COMMENT |
| LOW | dashboard/src/a11y-controls.test.ts | 1 | import { test } from 'node:test'; | COMMENT |
| LOW | dashboard/src/a11y-controls.test.ts | 21 | // `className="toggle-switch toggle-switch-sm"` modifier fell out of the sweep; `accept="image/*"` | COMMENT |
| LOW | dashboard/src/utils/reloadCoalescer.ts | 1 | // Single-flight reloads with one trailing run: while a reload is out, every call shares ONE follow-up | COMMENT |
| LOW | dashboard/src/utils/sessionActions.ts | 1 | // Which lifecycle actions a session card offers, extracted for direct unit testing (dashboard tests | COMMENT |
| LOW | dashboard/src/utils/sessionActions.ts | 21 | COMMENT | |
| LOW | dashboard/src/utils/mediaUpload.ts | 1 | // Client pre-check before base64-encoding an upload. Aligned with the default request-body limit: base64 | COMMENT |
| LOW | dashboard/src/utils/phoneCountry.ts | 1 | // The country a phone number dials into, for a flag beside it. Like formatPhone, this reads the E.164 | COMMENT |
| LOW | dashboard/src/components/chats/ChatThread.tsx | 161 | ? stops[stops.length - 1] | COMMENT |
| 224 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | README.md | 196 | `YOUR_API_KEY`. Later boots log only a masked prefix. See [API Key](docs/README.md#api-key). | CODE |
| HIGH⚡ | README.md | 356 | Replace `YOUR_API_KEY` with your admin key (see [Quick Start](#-quick-start) for where to find it). | CODE |
| HIGH⚡ | README.md | 363 | -H "X-API-Key: YOUR_API_KEY" \ | CODE |
| HIGH⚡ | README.md | 372 | -H "X-API-Key: YOUR_API_KEY" | CODE |
| HIGH⚡ | README.md | 376 | -H "X-API-Key: YOUR_API_KEY" | CODE |
| HIGH⚡ | README.md | 384 | -H "X-API-Key: YOUR_API_KEY" \ | CODE |
| HIGH | README.md | 396 | -H "X-API-Key: YOUR_API_KEY" \ | CODE |
| HIGH | README.md | 429 | "headers": { "Authorization": "Bearer YOUR_API_KEY" } | CODE |
| HIGH | docs/24-mcp-integration.md | 252 | (gitignored; replace `YOUR_API_KEY` with a dedicated key scoped to the sessions the agent | CODE |
| HIGH | docs/24-mcp-integration.md | 263 | "headers": { "Authorization": "Bearer YOUR_API_KEY" } | CODE |
| HIGH⚡ | docs/README.md | 142 | -H "X-API-Key: your-api-key" \ | CODE |
| HIGH⚡ | docs/README.md | 148 | -H "X-API-Key: your-api-key" | CODE |
| HIGH⚡ | docs/README.md | 152 | -H "X-API-Key: your-api-key" | CODE |
| HIGH⚡ | docs/README.md | 156 | -H "X-API-Key: your-api-key" \ | CODE |
| HIGH | docs/README.md | 167 | extraHeaders: { 'X-API-Key': 'your-api-key' }, | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | sdk/python/tests/conftest.py | 8 | CODE | |
| LOW | sdk/python/tests/test_webhook.py | 3 | CODE | |
| LOW | sdk/python/tests/test_sdk.py | 3 | CODE | |
| LOW | sdk/python/openwa/webhook.py | 3 | CODE | |
| LOW | sdk/python/openwa/_http.py | 10 | CODE | |
| LOW | sdk/python/openwa/_http.py | 18 | CODE | |
| LOW | sdk/python/openwa/client.py | 28 | CODE | |
| LOW | sdk/python/openwa/client.py | 31 | CODE | |
| LOW | sdk/python/openwa/client.py | 37 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 27 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 29 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 30 | CODE | |
| LOW | sdk/python/openwa/__init__.py | 42 | CODE | |
| LOW | sdk/python/openwa/types.py | 11 | CODE | |
| LOW | sdk/python/openwa/types.py | 13 | CODE | |
| LOW | sdk/python/openwa/errors.py | 11 | CODE | |
| LOW | sdk/python/openwa/resources/catalog.py | 10 | CODE | |
| LOW | sdk/python/openwa/resources/catalog.py | 25 | CODE | |
| LOW | sdk/python/openwa/resources/labels.py | 8 | CODE | |
| LOW | sdk/python/openwa/resources/labels.py | 16 | CODE | |
| LOW | sdk/python/openwa/resources/sessions.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/sessions.py | 27 | CODE | |
| LOW | sdk/python/openwa/resources/media.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/media.py | 14 | CODE | |
| LOW | sdk/python/openwa/resources/contacts.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/contacts.py | 22 | CODE | |
| LOW | sdk/python/openwa/resources/health.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/health.py | 13 | CODE | |
| LOW | sdk/python/openwa/resources/profile.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/profile.py | 19 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 7 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 9 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 10 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 11 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 12 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 13 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 14 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 15 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 16 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 17 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 18 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 19 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 20 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 21 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 22 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 23 | CODE | |
| LOW | sdk/python/openwa/resources/__init__.py | 24 | CODE | |
| LOW | sdk/python/openwa/resources/groups.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/groups.py | 27 | CODE | |
| LOW | sdk/python/openwa/resources/templates.py | 6 | CODE | |
| LOW | sdk/python/openwa/resources/templates.py | 14 | CODE | |
| 14 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | …ules/takeover/session-takeover-failed-adoption.spec.ts | 215 | const announced = b.events.emitSessionStatus.mock.calls.filter( | CODE |
| CRITICAL | src/modules/session/session-push-name-sync.spec.ts | 90 | expect(f.hooks.execute.mock.calls.filter(([hook]) => hook === 'session:ready')).toHaveLength(1); | CODE |
| CRITICAL | src/modules/session/session-delete-claim.spec.ts | 431 | expect(a.hooks.execute.mock.calls.some(([event]: [string]) => event === 'session:starting')).toBe(false); | CODE |
| CRITICAL | src/modules/session/session-delete-claim.spec.ts | 498 | expect(a.hooks.execute.mock.calls.some(([event]: [string]) => event === 'session:starting')).toBe(false); | CODE |
| CRITICAL | src/modules/session/session-delete-claim.spec.ts | 2844 | expect(a.hooks.execute.mock.calls.some(([event]) => event === 'session:deleted')).toBe(false); | CODE |
| CRITICAL | src/engine/adapters/baileys.adapter.spec.ts | 7653 | fakeSock.authState.keys.set.mock.calls.filter( | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | openapi.json | 1457 | "pushName": "John Doe", | CODE |
| LOW | openapi.json | 18976 | "example": "John Doe", | CODE |
| LOW | docs/06-api-specification.md | 2159 | { "chatId": "628123456789@c.us", "contactName": "John Doe", "contactNumber": "628987654321" } | CODE |
| LOW | docs/06-api-specification.md | 2551 | "name": "Jane Doe", | CODE |
| LOW | docs/06-api-specification.md | 2589 | "name": "Jane Doe", | CODE |
| LOW | docs/06-api-specification.md | 2668 | "name": "Jane Doe", | CODE |
| LOW | docs/07-api-collection.md | 505 | -d '{ "chatId": "628123456789@c.us", "contactName": "John Doe", "contactNumber": "628987654321" }' | CODE |
| LOW | dashboard/src/a11y-controls.test.ts | 372 | attr(node, 'placeholder') !== undefined || | CODE |
| LOW | dashboard/src/i18n/locales/tr.json | 450 | "placeholder": "ör. pazarlama-botu", | CODE |
| LOW | dashboard/src/i18n/locales/tr.json | 1445 | "placeholder": "Mesajlarda ara…", | CODE |
| LOW | dashboard/src/i18n/locales/de.json | 450 | "placeholder": "z. B. marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/de.json | 1445 | "placeholder": "Nachrichten durchsuchen…", | CODE |
| LOW | dashboard/src/i18n/locales/zh-CN.json | 450 | "placeholder": "例如:marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/zh-CN.json | 1445 | "placeholder": "搜索消息…", | CODE |
| LOW | dashboard/src/i18n/locales/en.json | 450 | "placeholder": "e.g., marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/en.json | 963 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/en.json | 1445 | "placeholder": "Search messages…", | CODE |
| LOW | dashboard/src/i18n/locales/zh-HK.json | 450 | "placeholder": "例如:marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/zh-HK.json | 1445 | "placeholder": "搜尋訊息…", | CODE |
| LOW | dashboard/src/i18n/locales/it.json | 455 | "placeholder": "es., marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/it.json | 969 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/it.json | 1454 | "placeholder": "Cerca messaggi…", | CODE |
| LOW | dashboard/src/i18n/locales/fr.json | 455 | "placeholder": "ex : marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/fr.json | 969 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/fr.json | 1454 | "placeholder": "Rechercher des messages…", | CODE |
| LOW | dashboard/src/i18n/locales/hi.json | 450 | "placeholder": "उदा. marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/hi.json | 963 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/hi.json | 1445 | "placeholder": "संदेश खोजें…", | CODE |
| LOW | dashboard/src/i18n/locales/pt-BR.json | 455 | "placeholder": "ex.: bot-marketing", | CODE |
| LOW | dashboard/src/i18n/locales/pt-BR.json | 919 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/pt-BR.json | 1454 | "placeholder": "Pesquisar mensagens…", | CODE |
| LOW | dashboard/src/i18n/locales/ko.json | 450 | "placeholder": "예: marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/ko.json | 1445 | "placeholder": "메시지 검색…", | CODE |
| LOW | dashboard/src/i18n/locales/he.json | 461 | "placeholder": "לדוגמה: marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/he.json | 1464 | "placeholder": "חיפוש הודעות…", | CODE |
| LOW | dashboard/src/i18n/locales/te.json | 450 | "placeholder": "ఉదాహరణకు, marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/te.json | 963 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/te.json | 1445 | "placeholder": "సందేశాలను శోధించండి…", | CODE |
| LOW | dashboard/src/i18n/locales/id.json | 450 | "placeholder": "mis. marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/id.json | 1445 | "placeholder": "Cari pesan…", | CODE |
| LOW | dashboard/src/i18n/locales/es.json | 455 | "placeholder": "ej., bot-marketing", | CODE |
| LOW | dashboard/src/i18n/locales/es.json | 919 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/es.json | 1454 | "placeholder": "Buscar mensajes…", | CODE |
| LOW | dashboard/src/i18n/locales/ar.json | 471 | "placeholder": "مثال: marketing-bot", | CODE |
| LOW | dashboard/src/i18n/locales/ar.json | 988 | "contactNamePlaceholder": "Jane Doe", | CODE |
| LOW | dashboard/src/i18n/locales/ar.json | 1482 | "placeholder": "ابحث في الرسائل…", | CODE |
| LOW | dashboard/src/pages/Chats.test.ts | 4407 | document.activeElement?.getAttribute('placeholder'), | CODE |
| LOW | dashboard/src/pages/Chats.test.ts | 4723 | document.activeElement?.getAttribute('placeholder') ?? 'body', | CODE |
| LOW | dashboard/src/pages/Chats.test.ts | 4751 | return document.activeElement?.getAttribute('placeholder') ?? 'body'; | CODE |
| LOW | src/modules/message/bulk-message.service.spec.ts | 840 | repo.findOne.mockResolvedValue(imageBatch('https://cdn.example.com/{{name}}.jpg', { name: 'John Doe' })); | CODE |
| LOW⚡ | src/modules/message/message-send.service.spec.ts | 1141 | contactName: 'John Doe', | CODE |
| LOW⚡ | src/modules/message/message-send.service.spec.ts | 1148 | expect.objectContaining({ name: 'John Doe', number: '+628123456789' }), | CODE |
| LOW | src/modules/search/search-terms.spec.ts | 12 | expect(searchTermCount('user@example.com')).toBe(3); | CODE |
| LOW | src/modules/session/session.controller.ts | 442 | pushName: 'John Doe', | CODE |
| LOW | src/modules/session/dto/session-response.dto.ts | 50 | @ApiPropertyOptional({ type: String, example: 'John Doe', nullable: true }) | CODE |
| LOW | src/engine/adapters/baileys.adapter.spec.ts | 1897 | await adapter.sendContactMessage('628111@s.whatsapp.net', { name: 'John Doe', number: '+1 234-567' }); | CODE |
| LOW | src/engine/adapters/baileys.adapter.spec.ts | 1902 | expect(call.contacts.displayName).toBe('John Doe'); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | docs/14-migration-guide.md | 97 | # Step 1: Export all Data DB tables | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 101 | # Step 2: Change the database configuration | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 111 | # Step 3: Restart with the new configuration (.env route) | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 114 | # Step 4: Import data to new database | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 258 | # Step 1: Check current storage file count | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 265 | # Step 2: Export all files as tar.gz | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 275 | # Step 3: Change the storage configuration | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 374 | # Step 1: Read both queues' depth from Bull Board's JSON route. Bull Board takes an ADMIN key only in | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 380 | # Step 2: Wait until waiting, active and delayed are 0 for both webhook-queue and ingress-queue | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 387 | # Step 3: Change Redis configuration | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 390 | # Step 4: Restart application | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 622 | # Step 1: Stop OpenWA | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 625 | # Step 2: Backup current data (both databases + session auth + media) | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 628 | # Step 3: Point OpenWA at PostgreSQL in the project's .env. docker-compose.dev.yml forwards these | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 639 | # Step 4: Start OpenWA once so its migrations create the schema the script writes into, then stop it | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 644 | # Step 5: Copy the rows. Save the "Migration Script (Legacy)" example above as | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 650 | # Step 6: Verify migration | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 654 | # Step 7: Start with PostgreSQL | COMMENT |
| LOW⚡ | docs/14-migration-guide.md | 657 | # Step 8: Verify functionality | COMMENT |
| LOW | docs/14-migration-guide.md | 287 | # Step 4: Restart with the new configuration (.env route) | COMMENT |
| LOW | docs/14-migration-guide.md | 290 | # Step 5: Import files to new storage | COMMENT |
| LOW | dashboard/src/utils/messageFormatter.ts | 56 | // Step 1: peel off code segments, emit nodes between them. | COMMENT |
| LOW⚡ | src/common/docs-governance.spec.ts | 279 | const step1 = between(guide, '# Step 1: Check current storage file count', '# Step 2').replace(/\s+/g, ' '); | CODE |
| LOW⚡ | src/common/docs-governance.spec.ts | 283 | const step2 = between(guide, '# Step 2: Export all files as tar.gz', '# Step 3').replace(/\s+/g, ' '); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | sdk/python/tests/test_sdk.py | 692 | # Known-negative control: without it an implementation that always emitted the key — as null, | COMMENT |
| HIGH | sdk/python/openwa/types.py | 1509 | # provider returns waMessageId/snippet as "" when absent (always str, never null); | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | docker-compose.yml | 30 | # datastore orchestration (Dashboard > Infrastructure built-in toggles), disable | COMMENT |
| MEDIUM | docker-compose.yml | 35 | # DockerService then reports Docker unavailable and orchestration degrades gracefully. | COMMENT |
| MEDIUM | docker-compose.yml | 535 | # Pin explicit volume names so the compose path and the Docker-API orchestration path (which uses | COMMENT |
| MEDIUM | scripts/smoke-test-docker-proxy.sh | 43 | # the proxy admits what orchestration needs is checked from inside openwa-api below. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | sdk/python/openwa/client.py | 78 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | dashboard/src/utils/messageFormatter.ts | 56 | // Step 1: peel off code segments, emit nodes between them. | COMMENT |
| LOW⚡ | src/common/docs-governance.spec.ts | 279 | const step1 = between(guide, '# Step 1: Check current storage file count', '# Step 2').replace(/\s+/g, ' '); | CODE |
| LOW⚡ | src/common/docs-governance.spec.ts | 283 | const step2 = between(guide, '# Step 2: Export all files as tar.gz', '# Step 3').replace(/\s+/g, ' '); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | dashboard/src/components/chats/ChatThread.test.ts | 1390 | // The button is a child of the scroller. Absolutely positioned there it moves with the content, which put it | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/restore.sh | 9 | # Usage: | COMMENT |
| LOW | scripts/backup.sh | 23 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | sdk/python/openwa/__init__.py | 44 | __all__ = [ | CODE |
| LOW | sdk/python/openwa/resources/__init__.py | 26 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | sdk/python/openwa/client.py | 78 | except Exception: | CODE |