From 2519aec5b60311d9d7ce070b1d6b0ad7683e5fc4 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Thu, 3 Sep 2026 08:15:21 -0500 Subject: [PATCH] feat(doorman): honor local_unlock flag from break-glass scans [#345] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break-glass badges fire the relay locally on the reader host (no HA dependency); the flagged scan still reaches HA for the audit trail but skips re-dispatch. NOTE: deployed while pfv-bms is down — YAML lint clean, ha core check to run at Friday boot before arming. https://projects.knownelement.com/issues/345 --- packages/doorman.yaml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/doorman.yaml b/packages/doorman.yaml index b50a9f3..020916f 100644 --- a/packages/doorman.yaml +++ b/packages/doorman.yaml @@ -155,8 +155,10 @@ automation: checked: roster sensors are not populated. Logged only; whitelist NOT evaluated. Check gitea connectivity / KNEL/access-roster. - # Known + enabled badge: log, then dispatch unlock IF armed - # (founder-level input_boolean). Disarmed = log + notice only. + # Known + enabled badge: log, then dispatch unlock IF armed AND + # the listener didn't already handle it locally (break-glass + # scans carry local_unlock:true — relay already fired on the + # reader host; HA logs without re-dispatching). - conditions: "{{ is_known and is_enabled }}" sequence: - action: logbook.log @@ -166,9 +168,10 @@ automation: Badge {{ badge_id }} ({{ holder }}) accepted at {{ reader }}. - if: - - condition: state - entity_id: input_boolean.doorman_unlock_enabled - state: 'on' + - condition: template + value_template: >- + {{ is_state('input_boolean.doorman_unlock_enabled', 'on') + and not (trigger.json.local_unlock | default(false) | bool(false)) }} then: - action: rest_command.doorman_unlock continue_on_error: true @@ -181,10 +184,11 @@ automation: title: Doorman — badge accepted, UNLOCK dispatched message: "{{ holder }} scanned at {{ reader }} ({{ scanned }}). Door released for the hold window." else: - - action: persistent_notification.create + - action: logbook.log data: - title: Doorman — badge accepted, unlock NOT armed - message: "{{ holder }} scanned at {{ reader }} ({{ scanned }}). Unlock is disarmed — door stayed shut." + name: Doorman + message: >- + No HA dispatch — {{ 'already released locally via break-glass' if trigger.json.local_unlock | default(false) | bool(false) else 'unlock disarmed' }}. # In roster but disabled: flag it loudly (stolen/suspended # badge use is exactly what we want to know about). - conditions: "{{ is_known and not is_enabled }}"