Intrusion (EZS)¶
category:intrusion = category-defining behavior (an intrusion panel must do this at all). capability:intrusion.* = selected when capabilities-coverage.yaml declares the slug applicable. Event/command names are the canonical PQ taxonomy (Pq.Adapters.Framework/pq-events.yaml).
Generated from the matrix
18 scenarios, from Matrix v9. See Adapter Acceptance Tests for how a scenario is written, what the waves mean, and which verdicts a run can record.
| Scenario | Purpose | Stimulus | Wave |
|---|---|---|---|
| AAT-INTRUSION-ARM-DISARM-01 | Arming a partition from PQ arms it and is confirmed by an event. | pq | 1 |
| AAT-INTRUSION-ARM-DISARM-02 | Disarming a partition from PQ disarms it and is confirmed by an event. | pq | 1 |
| AAT-INTRUSION-ARM-DISARM-03 | Arming at the keypad (not from PQ) is reflected in PQ as a local-origin event. | human | 2 |
| AAT-INTRUSION-ARM-DISARM-04 | Partial/stay arming maps to the correct PQ partial-arm shape. | pq | 1 |
| AAT-INTRUSION-ARM-DISARM-05 | Arming with an open zone is refused (or force-armed) with the correct PQ outcome. | human | 3 |
| AAT-INTRUSION-ARM-DISARM-06 | A redundant arm on an already-armed partition fails fast, without hanging on a confirming event that cannot come. | pq | 1 |
| AAT-INTRUSION-BYPASS-01 | Bypassing a zone from PQ takes effect and is confirmed. | pq | 1 |
| AAT-INTRUSION-BYPASS-02 | Removing a bypass from PQ restores the zone and is confirmed. | pq | 1 |
| AAT-INTRUSION-BYPASS-03 | A bypassed zone does not raise an alarm when violated while armed. | human | 3 |
| AAT-INTRUSION-ALARM-01 | Violating an armed zone raises an alarm on the correct zone/partition. | human | 3 |
| AAT-INTRUSION-ALARM-02 | The alarm's restore/clear is reported, not swallowed. | human | 3 |
| AAT-INTRUSION-ALARM-03 | Acknowledging/resetting an alarm from PQ clears the alarm state. | human | 3 |
| AAT-INTRUSION-ENTRY-EXIT-01 | Entering through the entry path during the delay does not immediately alarm. | human | 3 |
| AAT-INTRUSION-SOUNDER-01 | Muting a sounder from PQ silences it on the rig. | human | 3 |
| AAT-INTRUSION-TARGETING-01 | Arming one partition leaves every other partition untouched. | pq | 1 |
| AAT-INTRUSION-TRANSITION-01 | A disarm issued during the exit delay resolves definitely, without an alarm. | pq | 1 |
| AAT-INTRUSION-FORCE-01 | A force override arms a partition that plain arming refuses, with a distinct outcome. | human | 3 |
| AAT-INTRUSION-DURESS-01 | A panic or duress signal from the keypad surfaces as life safety, not a generic alarm. | human | 2 |
Arm / disarm (category-defining)¶
AAT-INTRUSION-ARM-DISARM-01¶
Arming a partition from PQ arms it and is confirmed by an event.
| Applies when | category:intrusion |
| Stimulus | pq · wave 1 |
| Capability | intrusion.arm_disarm |
| Preconditions | partition_disarmed |
Given. A partition is modeled and disarmed with its zones sealed.
When. An operator issues pq.command.security.arm on the partition.
Then. The partition arms and PQ observes the armed transition on that partition.
PQ-visible behavior. pq.event.intrusion.armed on the partition (or .armed.remote for the remote origin), and the partition status reads armed.
Steps.
- require: thing={partition};state=intrusion.disarmed
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.intrusion.armed;thing={partition}
timeout: 30
- require: thing={partition};state=intrusion.armed
AAT-INTRUSION-ARM-DISARM-02¶
Disarming a partition from PQ disarms it and is confirmed by an event.
| Applies when | category:intrusion |
| Stimulus | pq · wave 1 |
| Capability | intrusion.arm_disarm |
| Preconditions | partition_armed |
Given. A partition is armed.
When. An operator issues pq.command.security.disarm on the partition.
Then. The partition disarms and PQ observes the disarmed transition.
PQ-visible behavior. pq.event.intrusion.disarmed on the partition (or .disarmed.remote), and the partition status reads disarmed.
Steps.
- require: thing={partition};state=intrusion.armed
- command: pq.command.security.disarm
on: {partition}
expect:
- type=pq.event.intrusion.disarmed;thing={partition}
timeout: 30
- require: thing={partition};state=intrusion.disarmed
AAT-INTRUSION-ARM-DISARM-03¶
Arming at the keypad (not from PQ) is reflected in PQ as a local-origin event.
| Applies when | category:intrusion |
| Stimulus | human · wave 2 |
| Capability | intrusion.arm_disarm |
| Hardware | A physical keypad on the rig. |
| Preconditions | partition_disarmed |
| Depends on | AAT-INTRUSION-ARM-DISARM-01 |
Given. A partition is disarmed.
When. The user arms the partition at the physical keypad.
Then. PQ sees the arm as a keypad/local-origin event with the acting user where available.
PQ-visible behavior. pq.event.intrusion.armed on the partition with local/default origin (no .remote suffix), carrying the arming user identity if the protocol reports it.
Physical acts.
keypad_operation— the keypad Thing serving the modeled partition, arming it
Steps.
- require: thing={partition};state=intrusion.disarmed
- stimulus: keypad_operation
expect:
- type=pq.event.intrusion.armed;thing={partition}
reject:
- type=pq.event.intrusion.armed.remote
timeout: 120
AAT-INTRUSION-ARM-DISARM-04¶
Partial/stay arming maps to the correct PQ partial-arm shape.
| Applies when | capability:intrusion.arm_disarm |
| Stimulus | pq · wave 1 |
| Capability | intrusion.arm_disarm |
| Preconditions | partition_disarmed |
Given. The panel supports partial/stay arming and PQ exposes the partial-arm command.
When. An operator issues the partial-arm command the panel exposes (arm.partial, .stay or .sleep).
Then. PQ observes the partial-arm variant, distinct from full away arming.
PQ-visible behavior. pq.event.intrusion.armed.partial (or .partial.stay) on the partition — the partial mode is not flattened into a plain armed event.
Steps.
- require: thing={partition};state=intrusion.disarmed
- command: {any_partial_arm_command}
on: {partition}
expect:
- type=pq.event.intrusion.armed.partial;thing={partition}
timeout: 30
AAT-INTRUSION-ARM-DISARM-05¶
Arming with an open zone is refused (or force-armed) with the correct PQ outcome.
| Applies when | capability:intrusion.arm_disarm |
| Stimulus | human · wave 3 |
| Capability | intrusion.arm_disarm |
| Hardware | A zone the user can hold open during arming. |
| Preconditions | partition_disarmed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ARM-DISARM-01 |
Given. A partition is disarmed and one member zone is held open.
When. An operator issues a normal (non-forced) arm.
Then. PQ shows arming denied/failed for the open zone rather than a false armed state.
PQ-visible behavior. pq.event.intrusion.arming.denied or .arming.failed.close naming the offending zone; the partition does NOT report armed. (Forced arm, if issued, gives armed.forced.bypass instead.)
Physical acts.
trip_zone— a member zone of the modeled partition, held open across the arming attempt
Steps.
- require: thing={partition};state=intrusion.disarmed
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.contact.open;thing={zone}
timeout: 120
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.intrusion.arming.denied|pq.event.intrusion.arming.failed;thing={partition}
reject:
- type=pq.event.intrusion.armed;thing={partition}
timeout: 60
AAT-INTRUSION-ARM-DISARM-06¶
A redundant arm on an already-armed partition fails fast, without hanging on a confirming event that cannot come.
| Applies when | category:intrusion |
| Stimulus | pq · wave 1 |
| Capability | intrusion.arm_disarm |
| Preconditions | partition_armed |
| Since | Matrix v3 |
Given. A partition is already armed.
When. An operator issues pq.command.security.arm on it again.
Then. PQ reports the command failed because the partition is already in the target state — promptly, not after the confirmation timeout — and the partition stays armed with no second armed event.
PQ-visible behavior. pq.event.technical.command.failed carrying a reason that names the already-satisfied target (already armed / no action taken), returned without waiting out the event-confirmation timeout; the partition status stays armed and NO new pq.event.intrusion.armed(.remote) is emitted (no transition happened, so no audited event is fabricated). The framework applies this gate uniformly to every supervised command; a Force-flagged command bypasses it and is sent regardless.
Steps.
- require: thing={partition};state=intrusion.armed
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.technical.command.failed;thing={partition}
reject:
- type=pq.event.intrusion.armed;thing={partition}
timeout: 15
- require: thing={partition};state=intrusion.armed
Bypass (this is where partial verdicts commonly arise)¶
AAT-INTRUSION-BYPASS-01¶
Bypassing a zone from PQ takes effect and is confirmed.
| Applies when | capability:intrusion.bypass |
| Stimulus | pq · wave 1 |
| Capability | intrusion.bypass |
| Preconditions | partition_disarmed |
Given. A partition with a member zone is modeled.
When. An operator issues pq.command.security.bypass on the zone.
Then. The zone is bypassed and PQ reflects the bypassed state.
PQ-visible behavior. pq.event.intrusion.bypassed on the zone. NOTE: some panels confirm a bypass only by a state change and emit no distinct bypass event — that is a legitimate partial (record the observed contract), not a failure.
Steps.
- command: pq.command.security.bypass
on: {zone}
expect:
- type=pq.event.intrusion.bypassed;thing={zone}
timeout: 30
- require: thing={zone};state=intrusion.bypassed
AAT-INTRUSION-BYPASS-02¶
Removing a bypass from PQ restores the zone and is confirmed.
| Applies when | capability:intrusion.bypass |
| Stimulus | pq · wave 1 |
| Capability | intrusion.bypass |
| Preconditions | partition_disarmed |
Given. A zone is currently bypassed.
When. An operator issues pq.command.security.bypass.cancel on the zone.
Then. The bypass is removed and PQ reflects the cleared state.
PQ-visible behavior. pq.event.intrusion.bypassed.cleared on the zone (or a state change back to normal for panels that do not emit a dedicated event → partial).
Steps.
- require: thing={zone};state=intrusion.bypassed
- command: pq.command.security.bypass.cancel
on: {zone}
expect:
- type=pq.event.intrusion.bypassed.cleared;thing={zone}
timeout: 30
AAT-INTRUSION-BYPASS-03¶
A bypassed zone does not raise an alarm when violated while armed.
| Applies when | capability:intrusion.bypass |
| Stimulus | human · wave 3 |
| Capability | intrusion.bypass |
| Hardware | A zone the user can violate. |
| Preconditions | partition_disarmed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-BYPASS-01, AAT-INTRUSION-ARM-DISARM-01 |
Given. A zone is bypassed and its partition is then armed.
When. The user violates the bypassed zone while armed.
Then. No alarm is raised for that zone.
PQ-visible behavior. No pq.event.intrusion.alarm for the bypassed zone during the armed period; the bypass suppression is honored end-to-end.
Physical acts.
trip_zone— the bypassed member zone, while its partition is armed
Steps.
- require: thing={zone};state=intrusion.bypassed
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.intrusion.armed;thing={partition}
timeout: 30
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.contact.open;thing={zone}
timeout: 120
- reject:
- type=pq.event.intrusion.alarm;thing={zone}
timeout: 20
Alarm + restore (category-defining)¶
AAT-INTRUSION-ALARM-01¶
Violating an armed zone raises an alarm on the correct zone/partition.
| Applies when | category:intrusion |
| Stimulus | human · wave 3 |
| Capability | intrusion.alarms_tampers_troubles_restores |
| Hardware | A zone the user can violate while armed. |
| Preconditions | partition_armed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ARM-DISARM-01 |
Given. A partition is armed and a member zone is sealed.
When. The user violates the zone (open contact / trip motion) while armed.
Then. PQ raises an intrusion alarm attributed to the right zone and partition.
PQ-visible behavior. pq.event.intrusion.alarm on the violated zone, associated with its partition, with the device timestamp.
Physical acts.
trip_zone— a sealed member zone of the armed partition
Steps.
- require: thing={partition};state=intrusion.armed
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.alarm;thing={zone}
timeout: 120
AAT-INTRUSION-ALARM-02¶
The alarm's restore/clear is reported, not swallowed.
| Applies when | capability:intrusion.alarms_tampers_troubles_restores |
| Stimulus | human · wave 3 |
| Capability | intrusion.alarms_tampers_troubles_restores |
| Hardware | The same violable zone. |
| Preconditions | partition_armed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ALARM-01 |
Given. An alarm was raised on a zone.
When. The zone returns to normal and/or the alarm is cleared.
Then. PQ observes the restore separately from the alarm.
PQ-visible behavior. pq.event.intrusion.cleared (and/or contact.closed for the zone) after the violation ends — restore routed as its own event.
Physical acts.
restore_zone— the zone violated in the preceding alarm scenario
Steps.
- stimulus: restore_zone
expect:
- type=pq.event.intrusion.cleared|pq.event.intrusion.contact.closed;thing={zone}
timeout: 120
AAT-INTRUSION-ALARM-03¶
Acknowledging/resetting an alarm from PQ clears the alarm state.
| Applies when | capability:intrusion.alarm_reset |
| Stimulus | human · wave 3 |
| Capability | intrusion.alarm_reset |
| Hardware | A zone the user can violate while armed. |
| Preconditions | partition_armed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ALARM-01 |
Given. An alarm is active on the partition.
When. An operator issues pq.command.security.alarm.reset.
Then. The alarm state is acknowledged/reset and PQ reflects it.
PQ-visible behavior. pq.event.intrusion.alarm.acknowledged (or disarmed.alarm) and the partition alarm status clears.
Physical acts.
trip_zone— a sealed member zone of the armed partition, to raise the alarm the reset then clears
Steps.
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.alarm;thing={zone}
timeout: 120
- command: pq.command.security.alarm.reset
on: {partition}
expect:
- type=pq.event.intrusion.alarm.acknowledged|pq.event.intrusion.disarmed.alarm;thing={partition}
timeout: 30
Entry / exit delay¶
AAT-INTRUSION-ENTRY-EXIT-01¶
Entering through the entry path during the delay does not immediately alarm.
| Applies when | capability:intrusion.entry_exit_delay |
| Stimulus | human · wave 3 |
| Capability | intrusion.entry_exit_delay |
| Hardware | An entry-delay zone; the disarm within the delay comes from PQ or the keypad. |
| Preconditions | partition_armed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ARM-DISARM-01 |
Given. A partition is armed with an entry-delay zone.
When. The user opens the entry-delay zone and disarms within the delay.
Then. PQ shows entry-delay in progress and no alarm when disarmed in time.
PQ-visible behavior. pq.event.intrusion.entry (delay running) then a normal disarm; no pq.event.intrusion.alarm when disarmed before the timeout.
Physical acts.
trip_zone— the entry-delay zone of the armed partition
Steps.
- require: thing={partition};state=intrusion.armed
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.entry;thing={partition}
timeout: 120
- command: pq.command.security.disarm
on: {partition}
expect:
- type=pq.event.intrusion.disarmed;thing={partition}
reject:
- type=pq.event.intrusion.alarm
timeout: 30
Sounder / alarm control¶
AAT-INTRUSION-SOUNDER-01¶
Muting a sounder from PQ silences it on the rig.
| Applies when | capability:intrusion.sounder_alarm_control |
| Stimulus | human · wave 3 |
| Capability | intrusion.sounder_alarm_control |
| Hardware | An audible sounder and a zone that can raise it. |
| Preconditions | adapter_connected |
| Depends on | AAT-INTRUSION-ARM-DISARM-01 |
| Since | Matrix v5 |
Given. The panel exposes remote sounder control and a zone violation has brought a sounder up.
When. An operator issues pq.command.alarm.mute.sounder.
Then. The sounder goes quiet and PQ reflects the outcome.
PQ-visible behavior. a successful command result for the mute, and the sounder is audibly silent at the rig; where the panel exposes sounder state, it reads muted. The panel decides whether the command actually silences the siren, so the ear at the rig is the evidence — accepting the command with the siren still sounding is partial with the observed contract.
Physical acts.
trip_zone— a sealed member zone of the armed partition, to bring the sounder up and confirm it falls silent
Steps.
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.alarm;thing={zone}
timeout: 120
- command: pq.command.alarm.mute.sounder
on: {partition}
expect:
- kind=commandResult;result=success
timeout: 30
Addressing fidelity¶
AAT-INTRUSION-TARGETING-01¶
Arming one partition leaves every other partition untouched.
| Applies when | category:intrusion |
| Stimulus | pq · wave 1 |
| Topology | 2× partition on distinct addresses |
| Preconditions | partition_disarmed |
| Since | Matrix v4 |
Given. Two partitions are modeled and both read disarmed.
When. An operator arms partition A only.
Then. Partition A arms and partition B stays disarmed.
PQ-visible behavior. pq.event.intrusion.armed.remote on partition A with its node id, and partition B's status still reads disarmed afterwards. The negative half is admissible here because a partition's state is independently readable by status poll — unlike a door without a contact.
Steps.
- require: thing={partition};state=intrusion.disarmed
- require: thing={partition2};state=intrusion.disarmed
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.intrusion.armed.remote;thing={partition}
reject:
- type=pq.event.intrusion.armed;thing={partition2}
timeout: 30
- require: thing={partition2};state=intrusion.disarmed
Transitional states¶
AAT-INTRUSION-TRANSITION-01¶
A disarm issued during the exit delay resolves definitely, without an alarm.
| Applies when | category:intrusion |
| Stimulus | pq · wave 1 |
| Preconditions | partition_disarmed |
| Since | Matrix v4 |
Given. The partition has an exit delay and is armed from PQ, entering the delay.
When. An operator disarms while the exit delay is still running.
Then. The partition ends disarmed, and the command is answered — not left hanging.
PQ-visible behavior. pq.event.intrusion.disarmed.remote paired to the disarm command, and the partition's final status is disarmed with no alarm event raised. A command that times out waiting for a confirming event that the transitional state cannot produce is a fail — transitional states are where command/event pairing breaks most often.
Steps.
- require: thing={partition};state=intrusion.disarmed
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.intrusion.armed;thing={partition}
timeout: 30
- command: pq.command.security.disarm
on: {partition}
expect:
- type=pq.event.intrusion.disarmed.remote;thing={partition}
reject:
- type=pq.event.intrusion.alarm
timeout: 30
- require: thing={partition};state=intrusion.disarmed
Force arming (pairs with ARM-DISARM-05)¶
AAT-INTRUSION-FORCE-01¶
A force override arms a partition that plain arming refuses, with a distinct outcome.
| Applies when | capability:intrusion.arm_disarm |
| Stimulus | human · wave 3 |
| Capability | intrusion.arm_disarm |
| Hardware | A zone the user can hold open. |
| Preconditions | partition_disarmed, zone_accessible_for_stimulus |
| Depends on | AAT-INTRUSION-ARM-DISARM-01, AAT-INTRUSION-ARM-DISARM-05 |
| Since | Matrix v4 |
Given. A member zone is physically open, so plain arming is refused.
When. An operator issues pq.command.security.arm and, after it is refused, issues the distinct pq.command.security.arm.forced on the same partition.
Then. The plain arm is refused with a reason and the forced arm succeeds.
PQ-visible behavior. pq.command.security.arm yields pq.event.technical.command.failed naming the open zone; pq.command.security.arm.forced yields pq.event.intrusion.armed.remote with the open zone recorded as bypassed or excluded per the protocol. Both outcomes must be distinguishable — a forced arm that silently behaves like a plain arm, or a plain arm that silently forces, is a fail. Force arming is its own command id, not a flag on the plain arm.
Physical acts.
trip_zone— a member zone of the modeled partition, held open
Steps.
- require: thing={partition};state=intrusion.disarmed
- stimulus: trip_zone
expect:
- type=pq.event.intrusion.contact.open;thing={zone}
timeout: 120
- command: pq.command.security.arm
on: {partition}
expect:
- type=pq.event.technical.command.failed;thing={partition}
timeout: 60
- command: pq.command.security.arm.forced
on: {partition}
expect:
- type=pq.event.intrusion.armed.remote;thing={partition}
timeout: 60
Life safety at the keypad¶
AAT-INTRUSION-DURESS-01¶
A panic or duress signal from the keypad surfaces as life safety, not a generic alarm.
| Applies when | category:intrusion |
| Stimulus | human · wave 2 |
| Hardware | A keypad with a panic or duress function. |
| Preconditions | adapter_connected |
| Depends on | AAT-CROSS-CUTTING-UNIVERSAL-01 |
| Since | Matrix v4 |
Given. The panel exposes a keypad panic/duress path.
When. The user triggers panic or duress at the keypad.
Then. PQ shows a life-safety event on the right Thing, distinct from an intrusion alarm.
PQ-visible behavior. pq.event.safety.panic.* (or the medical/hold-up sibling) on the Thing the panel addresses — never collapsed into pq.event.intrusion.alarm. Losing the life-safety distinction is a security regression: an operator triaging alarms would not see that a person is in danger.
Physical acts.
keypad_panic— keypad Thing
Steps.