fix(telemetry): reconcile open door counts in 5-measurement bar with list and filter excluded doors #25

Closed
opened 2026-09-21 13:29:54 +00:00 by gabogg · 0 comments
Owner

📌 Problem Statement

In the Tactical Operations Deck (DUAL_OPS_DECK), two related discrepancies exist between the top 5-measurement bar (#door-measurements-bar) and the active door listings:

  1. Count vs. Listing Mismatch:

    • The number of open doors reported in the 5-measurement bar under ABIERTAS (ACTIVOS) (rendered in #meas-open) does not match the actual number of doors listed in the active views (the open_longest list and #portal-longest-count-badge).
    • For example, the counter may display 3 ABIERTAS, yet the ranking list or live activity view shows 5 doors, or vice versa.
  2. Excluded Doors Not Removed from Listings:

    • Doors flagged as excluded (is_excluded = 1 or exclude_from_rankings = true in SQLite / door settings, such as quarantined, maintenance, or test doors) are not getting removed from the listing.
    • These excluded doors continue to appear in the active door lists, causing confusion for SOC operators and breaking mathematical consistency with the measurement bar.

🔍 Root Cause Analysis

  1. Frontend Exclusion Filtering Omission (telemetry_engine.js):

    • In TelemetryEngine._constructSnapshot(), the openLongest list is generated as:
      const openLongest = doorsList.filter((d) => d.is_open && !d.is_offline);
      
    • It omits checking !d.is_excluded and !d.exclude_from_rankings. Excluded doors are thus retained in snapshot.openLongest.
  2. Fallback Calculation Inconsistency (command_deck_adapter.js):

    • In CommandDeckAdapter.renderMeasurementsBar(), the fallback count uses:
      const openVerified = summary.openVerified ?? doors.filter((d) => d.is_open && !d.is_offline).length;
      
    • In CommandDeckAdapter.renderOpenLongest(), the fallback list uses:
      const list = snapshot.openLongest || (snapshot.doors || []).filter((d) => d.is_open && !d.is_offline);
      
    • Neither checks the exclusion flags, allowing excluded doors to leak into both the count and the rendered DOM elements when fallbacks trigger.
  3. Backend / Frontend State Divergence (door_service.py):

    • In door_service.py, open_doors filters if is_open and not is_excluded:.
    • However, snapshot.doors sent over WebSocket includes all doors with "is_excluded": is_excluded. When the frontend reconciles doors or uses doorsList, the omission of client-side exclusion filters creates discrepancy against open_doors.

🎯 Required Solution

  1. Strict Uniform Exclusion Filtering:
    • Filter out any door where d.is_excluded === true or d.exclude_from_rankings === true across all open door lists and active sensor rankings (openLongest, renderOpenLongest, and the door activity stream).
  2. Synchronize 5-Measurement Bar with Active Listings:
    • Ensure the value rendered in #meas-open (ABIERTAS (ACTIVOS)) is strictly identical to the count rendered in #portal-longest-count-badge and the actual length of the rendered open doors list.
    • If a door is excluded, it must neither be counted in openVerified nor displayed in the ranking.
  3. Reactive Removal on Exclusion Toggle:
    • When an operator or admin excludes a door in the settings/modal, the door must immediately disappear from the open door list and decrement the open door counter without requiring a hard page refresh.

✅ Acceptance Criteria

  • Value in #meas-open (ABIERTAS (ACTIVOS)) matches #portal-longest-count-badge and the exact count of rendered rows in #tactical-open-longest-panel.
  • Excluded doors (is_excluded = 1 / exclude_from_rankings = true) never appear in the open door ranking list.
  • Toggling exclusion on a door immediately updates both the measurement bar and the active door lists.
  • Automated tests added to verify exclusion filtering in both backend snapshots and frontend telemetry engine.
## 📌 Problem Statement In the Tactical Operations Deck (`DUAL_OPS_DECK`), two related discrepancies exist between the top 5-measurement bar (`#door-measurements-bar`) and the active door listings: 1. **Count vs. Listing Mismatch**: - The number of open doors reported in the 5-measurement bar under `ABIERTAS (ACTIVOS)` (rendered in `#meas-open`) does not match the actual number of doors listed in the active views (the `open_longest` list and `#portal-longest-count-badge`). - For example, the counter may display `3 ABIERTAS`, yet the ranking list or live activity view shows 5 doors, or vice versa. 2. **Excluded Doors Not Removed from Listings**: - Doors flagged as excluded (`is_excluded = 1` or `exclude_from_rankings = true` in SQLite / door settings, such as quarantined, maintenance, or test doors) are **not getting removed from the listing**. - These excluded doors continue to appear in the active door lists, causing confusion for SOC operators and breaking mathematical consistency with the measurement bar. --- ## 🔍 Root Cause Analysis 1. **Frontend Exclusion Filtering Omission (`telemetry_engine.js`)**: - In `TelemetryEngine._constructSnapshot()`, the `openLongest` list is generated as: ```javascript const openLongest = doorsList.filter((d) => d.is_open && !d.is_offline); ``` - It omits checking `!d.is_excluded` and `!d.exclude_from_rankings`. Excluded doors are thus retained in `snapshot.openLongest`. 2. **Fallback Calculation Inconsistency (`command_deck_adapter.js`)**: - In `CommandDeckAdapter.renderMeasurementsBar()`, the fallback count uses: ```javascript const openVerified = summary.openVerified ?? doors.filter((d) => d.is_open && !d.is_offline).length; ``` - In `CommandDeckAdapter.renderOpenLongest()`, the fallback list uses: ```javascript const list = snapshot.openLongest || (snapshot.doors || []).filter((d) => d.is_open && !d.is_offline); ``` - Neither checks the exclusion flags, allowing excluded doors to leak into both the count and the rendered DOM elements when fallbacks trigger. 3. **Backend / Frontend State Divergence (`door_service.py`)**: - In `door_service.py`, `open_doors` filters `if is_open and not is_excluded:`. - However, `snapshot.doors` sent over WebSocket includes all doors with `"is_excluded": is_excluded`. When the frontend reconciles doors or uses `doorsList`, the omission of client-side exclusion filters creates discrepancy against `open_doors`. --- ## 🎯 Required Solution 1. **Strict Uniform Exclusion Filtering**: - Filter out any door where `d.is_excluded === true` or `d.exclude_from_rankings === true` across all open door lists and active sensor rankings (`openLongest`, `renderOpenLongest`, and the door activity stream). 2. **Synchronize 5-Measurement Bar with Active Listings**: - Ensure the value rendered in `#meas-open` (`ABIERTAS (ACTIVOS)`) is strictly identical to the count rendered in `#portal-longest-count-badge` and the actual length of the rendered open doors list. - If a door is excluded, it must neither be counted in `openVerified` nor displayed in the ranking. 3. **Reactive Removal on Exclusion Toggle**: - When an operator or admin excludes a door in the settings/modal, the door must immediately disappear from the open door list and decrement the open door counter without requiring a hard page refresh. --- ## ✅ Acceptance Criteria - [ ] Value in `#meas-open` (`ABIERTAS (ACTIVOS)`) matches `#portal-longest-count-badge` and the exact count of rendered rows in `#tactical-open-longest-panel`. - [ ] Excluded doors (`is_excluded = 1` / `exclude_from_rankings = true`) never appear in the open door ranking list. - [ ] Toggling exclusion on a door immediately updates both the measurement bar and the active door lists. - [ ] Automated tests added to verify exclusion filtering in both backend snapshots and frontend telemetry engine.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gabogg/hikcentral#25
No description provided.