Access control¶
category:access = category-defining behavior (an ACS must do this at all). capability:access.* = 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
36 scenarios, from Matrix v17. See Adapter Acceptance Tests for how a scenario is written, what the waves mean, and which verdicts a run can record.
| Scenario | Purpose | Kind | Stimulus | Wave |
|---|---|---|---|---|
| AAT-ACCESS-CREDENTIAL-01 | A synced card is granted access at an authorized door. | behavior | human | 2 |
| AAT-ACCESS-CREDENTIAL-02 | A card with no grant to the door is denied. | behavior | human | 2 |
| AAT-ACCESS-CREDENTIAL-03 | An unknown (unenrolled) card is denied and surfaced as unknown. | behavior | human | 2 |
| AAT-ACCESS-CREDENTIAL-04 | Deleting a credential stops it working at the device. | behavior | human | 2 |
| AAT-ACCESS-CREDENTIAL-05 | A credential update is applied in place, not by duplicate. | technical | pq | 1 |
| AAT-ACCESS-CREDENTIAL-06 | A synchronized PIN with an even number of digits authenticates at the device. | behavior | human | 2 |
| AAT-ACCESS-CREDENTIAL-07 | A synchronized PIN with an odd number of digits authorizes the adapter's access-point unit. | behavior | human | 2 |
| AAT-ACCESS-CARD-FORMATS-01 | A card in a supported format is decoded to the expected PQ number. | behavior | human | 2 |
| AAT-ACCESS-SYNC-MODE-01 | A single credential change takes the sync path the device supports. | behavior | pq | 1 |
| AAT-ACCESS-SYNC-MODE-02 | A sync of one changed credential costs no other credential its access. | behavior | human | 2 |
| AAT-ACCESS-SYNC-ISOLATION-01 | A full synchronization moves the whole owned AAT access dataset and reports the moved identities. | behavior | pq | 1 |
| AAT-ACCESS-SYNC-ISOLATION-02 | Incremental synchronization after one person changes touches only that person and required dependencies. | behavior | pq | 1 |
| AAT-ACCESS-SYNC-ISOLATION-03 | Selective synchronization with multiple pending people moves only the selected person. | behavior | pq | 1 |
| AAT-ACCESS-SYNC-ISOLATION-04 | A sync never deletes a device address it created or updated in the same batch, so changing one person's credential set updates their existing records instead of destroying them. | technical | pq | 1 |
| AAT-ACCESS-RESET-RESTORE-01 | A reset clears the device tables and re-pushes the whole dataset. | behavior | pq | 1 |
| AAT-ACCESS-RESET-RESTORE-02 | Credentials work again on the device after a reset. | behavior | human | 2 |
| AAT-ACCESS-DOUBLE-SYNC-01 | Running sync twice with unchanged input is a no-op on the PQ side. | technical | pq | 1 |
| AAT-ACCESS-DOUBLE-SYNC-02 | A repeated sync leaves the device's credential set working. | technical | human | 2 |
| AAT-ACCESS-SCHEDULES-01 | A schedule the device enforces denies access outside its window. | behavior | human | 2 |
| AAT-ACCESS-SCHEDULES-02 | A schedule-bound grant uploads its time profile to the device (config, distinct from enforcement). | behavior | pq | 1 |
| AAT-ACCESS-ACCESS-LEVELS-01 | An access-level binding grants exactly the access points it covers, and no others. | behavior | human | 2 |
| AAT-ACCESS-HOLIDAYS-01 | A synced holiday calendar changes schedule behavior on the device. | behavior | human | 2 |
| AAT-ACCESS-ANTIPASSBACK-01 | A second entry without an intervening exit is denied on antipassback. | behavior | human | 2 |
| AAT-ACCESS-DOOR-CONTROL-01 | A strike release from PQ opens the door momentarily and is confirmed. | behavior | pq | 1 |
| AAT-ACCESS-DOOR-CONTROL-02 | A permanent-open (unlock) command holds the door open until cancelled. | behavior | pq | 1 |
| AAT-ACCESS-DOOR-CONTROL-03 | Deadbolt lock/unlock is exposed where the protocol has a real lock actuator. | behavior | pq | 1 |
| AAT-ACCESS-DOOR-CONTROL-04 | A forced-open door is reported and its clear is reported. | behavior | human | 3 |
| AAT-ACCESS-DOOR-CONTROL-05 | A held-open (door-open-too-long) condition is reported and clears. | behavior | human | 3 |
| AAT-ACCESS-DOOR-CONTROL-06 | A momentary remote door open can be repeated without leaving stale door state. | behavior | pq | 1 |
| AAT-ACCESS-READER-MODE-01 | Disabling a reader from PQ stops it granting access. | behavior | human | 2 |
| AAT-ACCESS-OWNERSHIP-01 | Synchronization leaves credentials PQ does not own working. | behavior | human | 2 |
| AAT-ACCESS-CASCADE-01 | Deleting a person stops every one of their credentials working, not just the first. | behavior | human | 2 |
| AAT-ACCESS-ENROLLMENT-01 | A card captured at the reader becomes that person's credential in PQ. | behavior | human | 2 |
| AAT-ACCESS-ENROLLMENT-02 | A biometric template captured at the reader becomes that person's credential in PQ. | behavior | human | 2 |
| AAT-ACCESS-ENROLLMENT-03 | An enrollment nobody completes leaves no credential behind. | behavior | pq | 1 |
| AAT-ACCESS-ENROLLMENT-04 | A template enrolled through PQ works at a device it was not captured on. | behavior | human | 2 |
Credential management + access events (category-defining)¶
AAT-ACCESS-CREDENTIAL-01¶
A synced card is granted access at an authorized door.
| Applies when | category:access |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A reader and a physical card matching AAT-Card-1. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05, AAT-ACCESS-DOUBLE-SYNC-01 |
Given. AAT-Tester-1 holds AAT-Card-1, authorized for the door and synced to the device.
When. The user presents AAT-Card-1 at the door reader.
Then. Access is granted and PQ attributes it to the right person and door.
PQ-visible behavior. pq.event.access.granted on the door/reader Thing naming AAT-Tester-1 and the credential; the strike releases.
Physical acts.
present_credential— the reader of the door the credential is authorized for (credential: the synchronized AAT card)
Steps.
AAT-ACCESS-CREDENTIAL-02¶
A card with no grant to the door is denied.
| Applies when | category:access |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A reader and the card. |
| Preconditions | person_without_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05, AAT-ACCESS-DOUBLE-SYNC-01 |
Given. AAT-Tester-1 holds AAT-Card-1 synced but with no access level for the door.
When. The user presents AAT-Card-1 at the door reader.
Then. Access is denied for lack of authorization.
PQ-visible behavior. pq.event.access.denied (or .denied.invalid) on the door, attributed to AAT-Tester-1 where the protocol reports identity; the strike does not release.
Physical acts.
present_credential— the reader of the modeled door (credential: the synchronized AAT card, which holds no grant to that door)
Steps.
- stimulus: present_credential
expect:
- type=pq.event.access.denied;thing={door}
reject:
- type=pq.event.access.granted;thing={door}
timeout: 120
AAT-ACCESS-CREDENTIAL-03¶
An unknown (unenrolled) card is denied and surfaced as unknown.
| Applies when | category:access |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A reader and a card not enrolled in PQ. |
| Preconditions | door_modeled |
| Depends on | AAT-CROSS-CUTTING-UNIVERSAL-07 |
Given. A card the device does not know is used at the reader.
When. The user presents a PQ-unknown card at the door reader.
Then. Access is denied and PQ reports an unknown credential.
PQ-visible behavior. pq.event.access.denied.unknown on the door; where the protocol reports the card number it appears in the payload (card_display) — this is also how the runner captures physical card numbers.
Physical acts.
present_credential— the reader of the modeled door (credential: any card that is not enrolled in PQ)
Steps.
- stimulus: present_credential
expect:
- type=pq.event.access.denied.unknown;thing={door}
timeout: 120
AAT-ACCESS-CREDENTIAL-04¶
Deleting a credential stops it working at the device.
| Applies when | capability:access.credential_management |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A reader and the card. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05, AAT-ACCESS-CASCADE-01 |
Given. AAT-Card-1 currently grants access at the door.
When. The credential is removed in PQ and the sync completes, then the card is presented.
Then. The card no longer grants access.
PQ-visible behavior. After the delete syncs (pq.event.access.credential.deleted / sync fact), presenting AAT-Card-1 yields pq.event.access.denied.unknown (or .invalid), not granted.
Physical acts.
present_credential— the reader of the door the credential used to open (credential: the AAT card deleted in PQ)
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
- stimulus: present_credential
expect:
- type=pq.event.access.denied;thing={door}
reject:
- type=pq.event.access.granted;thing={door}
timeout: 120
AAT-ACCESS-CREDENTIAL-05¶
A credential update is applied in place, not by duplicate.
| Applies when | capability:access.credential_management |
| Stimulus | pq · wave 1 |
| Capability | access.credential_management |
| Preconditions | person_with_card_and_door_access |
Given. AAT-Card-1 is synced to the device.
When. A property of the credential/person is changed in PQ and re-synced.
Then. The device record is updated, not duplicated.
PQ-visible behavior. The sync reports an in-place update (no second device record for AAT-Tester-1); credential count on the device is unchanged. (Full-only panels reload the set — assert no duplication.)
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. That the record was updated rather than duplicated is a count in the sync facts, not a record on the timeline; the steps prove the synchronization completed.
AAT-ACCESS-CREDENTIAL-06¶
A synchronized PIN with an even number of digits authenticates at the device.
| Applies when | capability:access.credential_management |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A device path that authenticates numeric PIN credentials. |
| Preconditions | adapter_connected |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v4 |
Given. The adapter declares numeric PIN credential support and the AAT person holds a PIN with an even digit count, synchronized to the device.
When. The PIN is entered at the device keypad.
Then. It authenticates and is attributed to its enrolled person.
PQ-visible behavior. The entry produces its access or keypad event attributed to the enrolled person — the device accepted the value as stored. Adapters without numeric PIN support record n_a.
Physical acts.
enter_pin— keypad Thing (credential: the AAT even-digit PIN)
Steps.
- stimulus: enter_pin
expect:
- type=pq.event.access.granted|pq.event.intrusion;thing={keypad}
timeout: 120
AAT-ACCESS-CREDENTIAL-07¶
A synchronized PIN with an odd number of digits authorizes the adapter's access-point unit.
| Applies when | capability:access.credential_management |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Topology | 1× door / partition |
| Hardware | A device path that authenticates numeric PIN credentials at a modeled access point. |
| Preconditions | person_with_pin_and_access_point_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v10 |
Given. The adapter declares numeric PIN credential support, and the AAT person holds an odd-digit PIN granted to one modeled access point.
When. The PIN is used at the device path that exercises that access point.
Then. The device accepts the PIN for that access point and attributes the action to its enrolled person where identity is reported.
PQ-visible behavior. The entry produces the access-point behavior for the adapter's authorization unit: a door/gate grants, or an intrusion partition accepts the credential-backed keypad operation such as arm or disarm. This is the case that catches encoding and user-profile defects: protocols that pack digits two per byte need a filler nibble for an odd count, and panels that store rights/profile bytes must receive the grant that lets the credential act on the access point. Adapters whose PIN encoding has no parity sensitivity still run it; those without numeric PIN support record n_a.
Physical acts.
use_credential— the device path serving the modeled access point (credential: the AAT odd-digit PIN)
Steps.
- stimulus: use_credential
expect:
- type=pq.event.access.granted|pq.event.intrusion.armed|pq.event.intrusion.disarmed;thing={access_point}
timeout: 120
What the steps cannot decide. The access point role resolves to the adapter-declared authorization unit. For door-style access, the expected event is the grant at that access point. For partition-style access, the expected event is the accepted keypad operation on that partition. Where the protocol reports a person/user identifier, the event is attributed to AAT-Tester-1.
Card formats¶
AAT-ACCESS-CARD-FORMATS-01¶
A card in a supported format is decoded to the expected PQ number.
| Applies when | capability:access.card_formats |
| Stimulus | human · wave 2 |
| Capability | access.card_formats |
| Hardware | A card of the format under test. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
Given. The device accepts the card format AAT-Card-1 is encoded in.
When. The user presents AAT-Card-1.
Then. The number PQ reads matches the enrolled canonical number.
PQ-visible behavior. pq.event.access.granted carries the same credential/number that was enrolled — facility code and bit length decode per the documented format.
Physical acts.
present_credential— the reader of the modeled door (credential: the AAT card encoded in the format under test)
Steps.
What the steps cannot decide. The verdict is the equality of the number in the event payload with the enrolled canonical number, which the filter does not read; the steps prove the presentation was granted.
Sync mode¶
AAT-ACCESS-SYNC-MODE-01¶
A single credential change takes the sync path the device supports.
| Applies when | capability:access.sync_mode |
| Stimulus | pq · wave 1 |
| Capability | access.sync_mode |
| Preconditions | person_with_card_and_door_access |
| Since | Matrix v5 |
Given. The device's update capability is known (in-place vs full reload).
When. A single credential changes and a sync runs.
Then. The sync completes on the path the device supports.
PQ-visible behavior. The synchronization completes and its PQ-side facts show the path taken: an in-place device moves only the changed record, a full-only device reloads the whole set. This half proves what PQ sent; that the reload cost no other credential its access is AAT-ACCESS-SYNC-MODE-02.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. Which path the sync took is read from its facts, not from a record shape; the steps prove it completed.
AAT-ACCESS-SYNC-MODE-02¶
A sync of one changed credential costs no other credential its access.
| Applies when | capability:access.sync_mode |
| Stimulus | human · wave 2 |
| Capability | access.sync_mode |
| Hardware | A reader and a second card synchronized to the same door. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-SYNC-MODE-01 |
| Since | Matrix v5 |
Given. A second AAT credential holds access to the same door and one credential has just been re-synced.
When. The untouched credential is presented at the reader after that sync.
Then. It still grants — the sync path lost no collateral record.
PQ-visible behavior. pq.event.access.granted for the untouched credential at the door after the sync. Only the device decides whether the record survived the reload, so behavior is the evidence.
Physical acts.
present_credential— the reader of the door both credentials are authorized for (credential: the AAT card that was not changed in the sync)
Steps.
AAT-ACCESS-SYNC-ISOLATION-01¶
A full synchronization moves the whole owned AAT access dataset and reports the moved identities.
| Applies when | capability:access.sync_mode |
| Stimulus | pq · wave 1 |
| Capability | access.sync_mode |
| Preconditions | multi_person_access_dataset |
| Since | Matrix v11 |
Given. The canonical AAT access dataset contains at least two people with supported credentials and grants.
When. A full access synchronization runs.
Then. The adapter uploads the owned dataset and its sync evidence identifies every touched person/entity.
PQ-visible behavior. pq.command.access.synchronize completes, and the synchronization facts/dump/mapping evidence show that all AAT-owned access records required by the current dataset are new, modified, unchanged, or deleted as appropriate. No records outside the adapter-owned AAT dataset are deleted or rewritten.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. Compare sync item facts, generated sync dump, address mappings, and vendor trace where available. The verdict passes only when every wire-affecting item belongs to the AAT dataset or to shared/dependent definitions required by that dataset, and no foreign person-owned record is removed or modified.
AAT-ACCESS-SYNC-ISOLATION-02¶
Incremental synchronization after one person changes touches only that person and required dependencies.
| Applies when | capability:access.sync_mode |
| Stimulus | pq · wave 1 |
| Capability | access.sync_mode |
| Preconditions | multi_person_access_dataset, one_person_access_change |
| Depends on | AAT-ACCESS-SYNC-ISOLATION-01 |
| Since | Matrix v11 |
Given. A clean baseline sync exists, and only AAT-Tester-1 has a pending credential, profile, or access-grant change.
When. A normal access synchronization runs.
Then. Only AAT-Tester-1 and required dependent definitions are uploaded, deleted, or rewritten.
PQ-visible behavior. pq.command.access.synchronize completes, and the synchronization evidence shows no changed, deleted, or rewritten person-owned entities for AAT-Tester-2 or any other unchanged person. A device may rewrite multiple records for AAT-Tester-1 when its record model requires repacking, but the rewrite must stay scoped to that person.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. The verdict is the touched-identity set from sync facts/address mappings plus vendor packet evidence where available. Fail when an unchanged person's owned credential/user/cardholder records are created, updated, deleted, or rewritten. Shared definitions may move only when the changed person still references them and the adapter's access model requires that dependency.
AAT-ACCESS-SYNC-ISOLATION-03¶
Selective synchronization with multiple pending people moves only the selected person.
| Applies when | capability:access.sync_mode |
| Stimulus | pq · wave 1 |
| Capability | access.sync_mode |
| Preconditions | multi_person_access_dataset, two_person_access_changes |
| Depends on | AAT-ACCESS-SYNC-ISOLATION-01 |
| Since | Matrix v11 |
Given. AAT-Tester-1 and AAT-Tester-2 both have pending access-data changes after a clean baseline sync.
When. pq.command.access.synchronize runs with selection containing only AAT-Tester-1.
Then. Only AAT-Tester-1 and required dependent definitions are synchronized; AAT-Tester-2 remains pending.
PQ-visible behavior. The selective sync completes. Evidence shows no upload, delete, rewrite, mapping change, or wire command for AAT-Tester-2's person-owned records. A later sync selecting AAT-Tester-2 is the operation that moves AAT-Tester-2.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. The runner sends the command with selection=[AAT-Tester-1]. Compare before/after address mappings, sync item facts, generated sync dump, and vendor trace where available. Pass only when the touched person-owned identity set excludes AAT-Tester-2 and every non-selected pending person. Record a limitation if the adapter exposes no stable way to map a wire packet back to a person-owned entity; the framework mapping/facts verdict still remains mandatory.
AAT-ACCESS-SYNC-ISOLATION-04¶
A sync never deletes a device address it created or updated in the same batch, so changing one person's credential set updates their existing records instead of destroying them.
| Applies when | capability:access.sync_mode |
| Stimulus | pq · wave 1 |
| Capability | access.sync_mode |
| Preconditions | multi_person_access_dataset, one_person_credential_set_change |
| Depends on | AAT-ACCESS-SYNC-ISOLATION-01 |
| Since | Matrix v13 |
Given. AAT-Tester-1 is fully synchronized holding exactly one supported credential, and a second supported credential of a different type has been added to that same person.
When. A synchronization selecting only AAT-Tester-1 runs, and afterwards the added credential is removed and a second selective sync runs.
Then. Each sync leaves the person's records present on the device. No device address is created or updated and then deleted within the same sync, in either direction of the change.
PQ-visible behavior. Both synchronizations complete. Address mappings after each sync still cover every credential the person holds, and the person's authorization survives — a credential that was valid before the change is still valid after it. An adapter whose record model must repack the person into a different number of records may do so, but the repack is expressed as an update, or as a delete that precedes the create of that same address, never as a create followed by a delete.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. The runner sends the first command with selection=[AAT-Tester-1], then removes the added credential and repeats it. For each sync, build the per-address action sequence from the sync item facts, the generated sync dump, the address mappings before and after, and the vendor packet trace where available. Fail when any single address carries a create or update followed by a delete inside one sync — the reported success is not the verdict, the surviving device state is. Fail as well when the person's address mappings after either sync no longer cover the credentials they hold. This is an address-lifecycle invariant, not a vendor detail: it applies to every adapter whose access model allocates addresses, and it is the shape a record takes when a change of identity key makes an update look to the differ like an unrelated delete plus an unrelated add. Record a limitation, not a pass, if the adapter exposes no way to attribute a device address to a person-owned entity.
Reset & restore¶
AAT-ACCESS-RESET-RESTORE-01¶
A reset clears the device tables and re-pushes the whole dataset.
| Applies when | capability:access.reset_and_restore |
| Stimulus | pq · wave 1 |
| Capability | access.reset_and_restore |
| Preconditions | person_with_card_and_door_access |
| Since | Matrix v5 |
Given. The device holds a synced credential set.
When. pq.command.access.synchronize.reset runs.
Then. The clear is confirmed and a fresh full synchronization follows it.
PQ-visible behavior. The reset command succeeds and a synchronization follows it that completes with the full set re-sent. This half proves what PQ sent; that the panel accepted the reload is AAT-ACCESS-RESET-RESTORE-02. NOTE: wiping every credential off a panel currently raises no audit event — pq.event.access.credential.deleted.all exists in the taxonomy but the reset path does not emit it, so a customer's audit trail shows a synchronization and never the wipe that preceded it. Until that is closed, the scenario asserts the sync, not the wipe.
Steps.
- command: pq.command.access.synchronize.reset
on: {root}
expect:
- kind=commandResult;result=success;thing={root}
- type=pq.event.access.synchronization.completed;thing={root}
order: sequence
timeout: 900
AAT-ACCESS-RESET-RESTORE-02¶
Credentials work again on the device after a reset.
| Applies when | capability:access.reset_and_restore |
| Stimulus | human · wave 2 |
| Capability | access.reset_and_restore |
| Hardware | A reader and the card. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-RESET-RESTORE-01 |
| Since | Matrix v5 |
Given. A reset has cleared the device and the full set has been re-pushed.
When. The synchronized card is presented at the reader after the reset.
Then. It grants — the reloaded dataset is live on the device.
PQ-visible behavior. pq.event.access.granted at the door for the AAT card after the reset completes. Whether the re-pushed record actually landed is the device's answer, given by the door opening.
Physical acts.
present_credential— the reader of the door the credential is authorized for (credential: the AAT card re-pushed by the reset)
Steps.
Double-sync safety¶
AAT-ACCESS-DOUBLE-SYNC-01¶
Running sync twice with unchanged input is a no-op on the PQ side.
| Applies when | capability:access.double_sync_safety |
| Stimulus | pq · wave 1 |
| Capability | access.double_sync_safety |
| Preconditions | person_with_card_and_door_access |
| Since | Matrix v5 |
Given. The credential set is synced and unchanged.
When. pq.command.access.synchronize runs a second time with identical input.
Then. The second sync completes with nothing to do — no error, no second round of writes.
PQ-visible behavior. The second synchronization completes without failure and its facts show no records added or re-sent (idempotent Transform). That the device set survived the repeat is AAT-ACCESS-DOUBLE-SYNC-02.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. That the second run wrote nothing is a count in its facts; the steps prove both runs completed without failure.
AAT-ACCESS-DOUBLE-SYNC-02¶
A repeated sync leaves the device's credential set working.
| Applies when | capability:access.double_sync_safety |
| Stimulus | human · wave 2 |
| Capability | access.double_sync_safety |
| Hardware | A reader and the card. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-DOUBLE-SYNC-01 |
| Since | Matrix v5 |
Given. The same input has been synchronized twice.
When. The synchronized card is presented at the reader after the second sync.
Then. It grants exactly as before — the repeat neither dropped nor duplicated the record.
PQ-visible behavior. pq.event.access.granted at the door, once, for the AAT card. A duplicated or clobbered device record shows up here as a denial or a doubled event; the device's own tables are not readable back, so behavior carries the verdict.
Physical acts.
present_credential— the reader of the door the credential is authorized for (credential: the AAT card synchronized twice)
Steps.
Schedules / time profiles¶
AAT-ACCESS-SCHEDULES-01¶
A schedule the device enforces denies access outside its window.
| Applies when | capability:access.schedules_time_profiles |
| Stimulus | human · wave 2 |
| Capability | access.schedules_time_profiles |
| Hardware | A reader and a card; a schedule window that can be tested. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
Given. AAT-Card-1's grant is bound to a time schedule and synced.
When. The user presents the card outside the scheduled window.
Then. Access is denied for being out of schedule.
PQ-visible behavior. pq.event.access.denied.schedule at the door when presented outside the window; granted inside it.
Physical acts.
present_credential— the reader of the door the schedule-bound grant covers (credential: the schedule-bound AAT card, presented outside its window)
Steps.
- stimulus: present_credential
expect:
- type=pq.event.access.denied.schedule;thing={door}
reject:
- type=pq.event.access.granted;thing={door}
timeout: 120
AAT-ACCESS-SCHEDULES-02¶
A schedule-bound grant uploads its time profile to the device (config, distinct from enforcement).
| Applies when | capability:access.schedules_time_profiles |
| Stimulus | pq · wave 1 |
| Capability | access.schedules_time_profiles |
| Preconditions | person_with_scheduled_grant |
| Since | Matrix v14 |
Given. An AAT grant is bound to a time schedule.
When. An access synchronization runs.
Then. The panel receives the schedule's time-window definition bound to the grant.
PQ-visible behavior. pq.command.access.synchronize completes and the sync evidence shows the grant's time-window definition uploaded and referenced by the grant; an unrestricted grant references none. This half proves the schedule reached the device as configuration; SCHEDULES-01 proves it is then enforced.
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
What the steps cannot decide. The sync facts/dump/vendor trace show the grant's time window uploaded and bound to the grant; a timeless grant uploads no schedule. Passes when the uploaded schedule matches the grant's window.
Access levels / groups¶
AAT-ACCESS-ACCESS-LEVELS-01¶
An access-level binding grants exactly the access points it covers, and no others.
| Applies when | capability:access.access_levels_groups |
| Stimulus | human · wave 2 |
| Capability | access.access_levels_groups |
| Topology | 2× door / partition on distinct addresses |
| Hardware | Two access points a credential can be exercised at. |
| Preconditions | person_with_card_and_door_access, two_access_points_modeled |
| Depends on | AAT-ACCESS-CREDENTIAL-05, AAT-CROSS-CUTTING-COMMAND-TARGETING-01 |
| Since | Matrix v8 |
Given. AAT-Tester-1's access level covers access point A but not access point B.
When. The user exercises AAT-Card-1 at A, then at B.
Then. A grants, B denies.
PQ-visible behavior. pq.event.access.granted at A and pq.event.access.denied at B — the level binding flows through person.Devices, not a static mask. The unit of authorization is the access point (access_point: true), not the door: a panel that authorizes users per partition or floor models those as access points too (MODEL-002), and they carry this scenario exactly as doors do. Restricting it to doors would leave an intrusion panel's per-partition authorization — the mechanism most prone to being faked with a static bitmask — untested.
Physical acts.
present_credential— the readers serving the covered access point and the uncovered one, in turn (credential: the synchronized AAT card)
Steps.
- stimulus: present_credential
expect:
- type=pq.event.access.granted;thing={door}
timeout: 120
- stimulus: present_credential
expect:
- type=pq.event.access.denied;thing={door2}
reject:
- type=pq.event.access.granted;thing={door2}
timeout: 120
Holidays¶
AAT-ACCESS-HOLIDAYS-01¶
A synced holiday calendar changes schedule behavior on the device.
| Applies when | capability:access.holidays |
| Stimulus | human · wave 2 |
| Capability | access.holidays |
| Hardware | A reader, the card, and a schedule whose holiday variant differs from the day's normal rule. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05, AAT-ACCESS-SCHEDULES-01 |
| Since | Matrix v5 |
Given. A holiday calendar is synced, a schedule references it, and the current day is a holiday it defines.
When. The card bound to that schedule is presented on the holiday.
Then. The decision follows the holiday variant of the schedule.
PQ-visible behavior. The access decision on the holiday follows the holiday rule rather than the weekday rule (granted or denied as the rule says), which is the only proof the calendar reached the device — the panel decides on its own calendar and does not hand it back.
Physical acts.
present_credential— the reader of the door the schedule-bound grant covers, on a holiday the calendar defines (credential: the schedule-bound AAT card)
Steps.
What the steps cannot decide. Which decision is correct depends on the holiday rule, so the direction of the outcome — and not its mere arrival — carries the verdict; the step only proves the panel decided.
Antipassback¶
AAT-ACCESS-ANTIPASSBACK-01¶
A second entry without an intervening exit is denied on antipassback.
| Applies when | capability:access.antipassback |
| Stimulus | human · wave 2 |
| Capability | access.antipassback |
| Hardware | An APB-configured reader pair. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
Given. An APB zone is configured and AAT-Tester-1 has entered.
When. The user presents the card to enter again without exiting.
Then. Access is denied for antipassback violation.
PQ-visible behavior. pq.event.access.denied.antipassback on the second entry; a clear via pq.command.access.antipassback.clear restores normal entry.
Physical acts.
present_credential— the entry reader of the APB zone, twice without an intervening exit (credential: the synchronized AAT card)
Steps.
- stimulus: present_credential
expect:
- type=pq.event.access.granted;thing={door}
timeout: 120
- stimulus: present_credential
expect:
- type=pq.event.access.denied.antipassback;thing={door}
timeout: 120
Door control¶
AAT-ACCESS-DOOR-CONTROL-01¶
A strike release from PQ opens the door momentarily and is confirmed.
| Applies when | category:access |
| Stimulus | pq · wave 1 |
| Capability | access.door_control |
| Preconditions | door_modeled |
Given. A door with a controllable strike is modeled.
When. An operator issues pq.command.access.open on the door.
Then. The strike releases briefly and PQ observes the release.
PQ-visible behavior. pq.event.access.door.unsecured.remote on the door, then relock; command outcome confirmed.
Steps.
- command: pq.command.access.open
on: {door}
expect:
- type=pq.event.access.door.unsecured.remote;thing={door}
timeout: 30
AAT-ACCESS-DOOR-CONTROL-02¶
A permanent-open (unlock) command holds the door open until cancelled.
| Applies when | capability:access.door_control |
| Stimulus | pq · wave 1 |
| Capability | access.door_control |
| Preconditions | door_modeled |
Given. A door is modeled and secured.
When. An operator issues pq.command.access.open.permanent, then pq.command.access.lock.
Then. The door holds unsecured, then returns to secured on the closing command.
PQ-visible behavior. pq.event.access.door.unsecured.remote persisting after open.permanent, then pq.event.access.door.secured.remote after the closing command.
Steps.
- command: pq.command.access.open.permanent
on: {door}
expect:
- type=pq.event.access.door.unsecured.remote;thing={door}
timeout: 30
- command: pq.command.access.close
on: {door}
expect:
- type=pq.event.access.door.secured.remote;thing={door}
timeout: 30
AAT-ACCESS-DOOR-CONTROL-03¶
Deadbolt lock/unlock is exposed where the protocol has a real lock actuator.
| Applies when | capability:access.door_control |
| Stimulus | pq · wave 1 |
| Capability | access.door_control |
| Preconditions | door_modeled |
Given. The door has a lock/deadbolt actuator distinct from the strike.
When. An operator issues pq.command.access.lock then pq.command.access.unlock.
Then. The lock engages and disengages with matching PQ events.
PQ-visible behavior. pq.event.access.door.locked.remote then pq.event.access.door.unlocked.remote. If the device has no real lock actuator (strike only), this is n_a (not_supported_by_protocol), not failed.
Steps.
- command: pq.command.access.lock
on: {door}
expect:
- type=pq.event.access.door.locked.remote;thing={door}
timeout: 30
- command: pq.command.access.unlock
on: {door}
expect:
- type=pq.event.access.door.unlocked.remote;thing={door}
timeout: 30
AAT-ACCESS-DOOR-CONTROL-04¶
A forced-open door is reported and its clear is reported.
| Applies when | capability:access.door_control |
| Stimulus | human · wave 3 |
| Capability | access.door_control |
| Hardware | A door with a monitored contact. |
| Preconditions | door_modeled |
| Depends on | AAT-ACCESS-DOOR-CONTROL-01 |
Given. A door with a position/contact sensor is secured.
When. The user forces the door open without a valid grant, then closes it.
Then. PQ reports the forced condition and its clear.
PQ-visible behavior. pq.event.access.door.forced on the forced open, then pq.event.access.door.forced.cleared on close — both routed.
Physical acts.
open_door— the modeled door with a monitored contact, opened without a grant and closed again
Steps.
- stimulus: open_door
expect:
- type=pq.event.access.door.forced;thing={door}
timeout: 120
- stimulus: open_door
restore: True
expect:
- type=pq.event.access.door.forced.cleared;thing={door}
timeout: 120
AAT-ACCESS-DOOR-CONTROL-05¶
A held-open (door-open-too-long) condition is reported and clears.
| Applies when | capability:access.door_control |
| Stimulus | human · wave 3 |
| Capability | access.door_control |
| Hardware | A door with a monitored contact. |
| Preconditions | door_modeled |
| Depends on | AAT-ACCESS-DOOR-CONTROL-01 |
Given. A door with a position sensor and held-open timer.
When. The user holds the door open past the timeout, then closes it.
Then. PQ reports held-open and its clear.
PQ-visible behavior. pq.event.access.door.held after the timeout, then pq.event.access.door.held.cleared on close.
Physical acts.
hold_door— the modeled door with a monitored contact, held past its held-open timeout
Steps.
- stimulus: hold_door
expect:
- type=pq.event.access.door.held;thing={door}
timeout: 180
- stimulus: hold_door
restore: True
expect:
- type=pq.event.access.door.held.cleared;thing={door}
timeout: 120
AAT-ACCESS-DOOR-CONTROL-06¶
A momentary remote door open can be repeated without leaving stale door state.
| Applies when | capability:access.door_control |
| Stimulus | pq · wave 1 |
| Capability | access.door_control |
| Preconditions | commandable_door_at_rest |
| Depends on | AAT-ACCESS-DOOR-CONTROL-01 |
| Since | Matrix v12 |
Given. A controllable door is modeled, online, and no person physically opens the door leaf during the test.
When. An operator issues pq.command.access.open on the same door three times in sequence.
Then. Every command succeeds, every release is observed, and the door returns to a commandable secured state before the next command.
PQ-visible behavior. Each pq.command.access.open produces command.result success and pq.event.access.door.unsecured.remote on the door, then the door reaches lock.secured before the next command. The timeline must not show a stale position.open status caused only by the remote strike-release command; position.open belongs to a real monitored contact opening, not to the command itself.
Steps.
- command: pq.command.access.open
on: {door}
expect:
- kind=commandResult;result=success;thing={door}
- type=pq.event.access.door.unsecured.remote;thing={door}
- states=lifecycle.ready,lock.secured;thing={door}
reject:
- type=pq.event.technical.command.failed;thing={door}
- state=position.open;thing={door}
timeout: 30
- command: pq.command.access.open
on: {door}
expect:
- kind=commandResult;result=success;thing={door}
- type=pq.event.access.door.unsecured.remote;thing={door}
- states=lifecycle.ready,lock.secured;thing={door}
reject:
- type=pq.event.technical.command.failed;thing={door}
- state=position.open;thing={door}
timeout: 30
- command: pq.command.access.open
on: {door}
expect:
- kind=commandResult;result=success;thing={door}
- type=pq.event.access.door.unsecured.remote;thing={door}
- states=lifecycle.ready,lock.secured;thing={door}
reject:
- type=pq.event.technical.command.failed;thing={door}
- state=position.open;thing={door}
timeout: 30
What the steps cannot decide. Run this as an unattended command-loop test. If the door has a real monitored contact and the test rig physically opens the leaf during the command, position.open is valid only for that physical interval and must clear before the next command. A protocol history row that means operator/relay release must not be mapped as physical door-contact position.
Reader mode / enable¶
AAT-ACCESS-READER-MODE-01¶
Disabling a reader from PQ stops it granting access.
| Applies when | capability:access.reader_mode_enable |
| Stimulus | human · wave 2 |
| Capability | access.reader_mode_enable |
| Hardware | A reader and the card. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-CROSS-CUTTING-UNIVERSAL-03, AAT-ACCESS-CREDENTIAL-05 |
Given. AAT-Card-1 normally grants at the reader.
When. An operator issues pq.command.access.disable on the reader, then presents the card.
Then. The disabled reader does not grant; re-enabling restores it.
PQ-visible behavior. After disable, presenting AAT-Card-1 yields no grant (denied/locked or no reaction per protocol); pq.command.access.enable restores pq.event.access.granted.
Physical acts.
present_credential— the disabled reader, and the same reader again after it is re-enabled (credential: the synchronized AAT card)
Steps.
- command: pq.command.access.disable
on: {reader}
expect:
- kind=commandResult;result=success;thing={reader}
timeout: 30
- stimulus: present_credential
reject:
- type=pq.event.access.granted;thing={door}
timeout: 60
- command: pq.command.access.enable
on: {reader}
expect:
- kind=commandResult;result=success;thing={reader}
timeout: 30
- stimulus: present_credential
expect:
- type=pq.event.access.granted;thing={door}
timeout: 120
Synchronization ownership and cascade¶
AAT-ACCESS-OWNERSHIP-01¶
Synchronization leaves credentials PQ does not own working.
| Applies when | capability:access.credential_management |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A credential on the device that PQ did not create and that can be exercised. |
| Preconditions | person_with_card_and_door_access, foreign_record_on_device |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v4 |
Given. The device holds a working credential PQ did not create — an installer-entered user whose PIN or card is known and exercisable — alongside the synchronized AAT records.
When. A synchronization runs, including one that removes an AAT credential.
Then. The foreign credential still authenticates afterwards.
PQ-visible behavior. After the sync, using the foreign credential still produces its granted/armed event, while the removed AAT credential no longer does. Wiping a record PQ does not own is irreversible damage on a customer panel, which is why this is verified by using the credential rather than by trusting the sync report — the report only says what PQ intended.
Physical acts.
use_credential— the reader or keypad the foreign credential belongs to (credential: the credential on the device that PQ did not create)
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
- stimulus: use_credential
expect:
- type=pq.event.access.granted|pq.event.intrusion.disarmed
timeout: 180
AAT-ACCESS-CASCADE-01¶
Deleting a person stops every one of their credentials working, not just the first.
| Applies when | capability:access.credential_management |
| Stimulus | human · wave 2 |
| Capability | access.credential_management |
| Hardware | A reader and keypad, plus the physical credentials. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v4 |
Given. The AAT person holds more than one credential — card and PIN — all synchronized and all proven working.
When. The person is deleted in PQ and synchronization runs.
Then. Every one of that person's credentials is refused.
PQ-visible behavior. Each credential in turn now yields a denial rather than a grant. A single leftover credential means a departed employee still gets in, so every credential the person held is exercised — testing only one would miss exactly the defect this scenario exists to catch.
Physical acts.
use_credential— the reader or keypad each credential belongs to (credential: every credential the deleted AAT person held, in turn)
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
- stimulus: use_credential
expect:
- type=pq.event.access.denied
reject:
- type=pq.event.access.granted
timeout: 180
What the steps cannot decide. Every credential the person held is exercised in turn; the step covers one presentation, so the runner repeats it per credential and the verdict holds only when all of them were refused.
Live credential enrollment¶
AAT-ACCESS-ENROLLMENT-01¶
A card captured at the reader becomes that person's credential in PQ.
| Applies when | capability:access.enrollment |
| Stimulus | human · wave 2 |
| Capability | access.enrollment |
| Hardware | A reader and a physical card. |
| Preconditions | person_synced_without_the_enrolled_credential |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v17 |
Given. AAT-Tester-1 exists and has synchronized to the device, holding no card.
When. A card enrollment is started for that person and a card is presented at the reader.
Then. PQ holds the captured card as that person's credential.
PQ-visible behavior. pq.event.access.credential.enrollment.succeeded on the reader naming AAT-Tester-1. The point of a live capture is that PQ LEARNS the number, so an enrollment that reports success without producing a credential has not done the job - the verdict is the credential, not the event.
Physical acts.
present_credential— the reader the enrollment was started on (credential: a card the person does not already hold, presented while the reader prompts)
Steps.
- command: pq.command.access.enroll.card
on: {reader}
expect:
- type=pq.event.access.credential.enrollment.succeeded;thing={reader}
timeout: 180
What the steps cannot decide. Confirm the person now holds a card credential in PQ carrying the number that was presented. A device that stores the card only on itself, or answers asynchronously over a channel the adapter does not accept, produces the event and no credential; that is a partial pass at best.
AAT-ACCESS-ENROLLMENT-02¶
A biometric template captured at the reader becomes that person's credential in PQ.
| Applies when | capability:access.enrollment |
| Stimulus | human · wave 2 |
| Capability | access.enrollment |
| Hardware | A reader with the biometric sensor, and a person at it. |
| Preconditions | person_synced_without_the_enrolled_credential |
| Depends on | AAT-ACCESS-CREDENTIAL-05 |
| Since | Matrix v17 |
Given. AAT-Tester-1 exists and has synchronized to the device, holding no template.
When. A template enrollment is started for that person and they present at the sensor.
Then. PQ holds the captured template as that person's credential.
PQ-visible behavior. pq.event.access.credential.enrollment.succeeded on the reader naming AAT-Tester-1, and a biometric credential on that person. Some devices keep a template to themselves and hand back only an acknowledgement; there the capture is real but PQ owns nothing, cannot move the template to a second reader and can revoke only by deleting the person - a material difference to state rather than to hide.
Physical acts.
present_credential— the sensor of the reader the enrollment was started on (credential: the person themselves - face, finger or palm per the device)
Steps.
- command: pq.command.access.enroll.face
on: {reader}
expect:
- type=pq.event.access.credential.enrollment.succeeded;thing={reader}
timeout: 180
What the steps cannot decide. The command is the face verb because it is the only template verb in the taxonomy; a device enrolling a different modality extends per protocol. Confirm the person holds a biometric credential afterwards, and record WHAT it holds - a vendor template binds the person to that make of reader, a photograph does not.
AAT-ACCESS-ENROLLMENT-03¶
An enrollment nobody completes leaves no credential behind.
| Applies when | capability:access.enrollment |
| Stimulus | pq · wave 1 |
| Capability | access.enrollment |
| Preconditions | person_synced_without_the_enrolled_credential |
| Depends on | AAT-ACCESS-ENROLLMENT-01 |
| Since | Matrix v17 |
Given. AAT-Tester-1 exists and has synchronized to the device, holding no card.
When. A card enrollment is started and nothing is presented until it expires.
Then. The enrollment fails and PQ gained no credential.
PQ-visible behavior. No pq.event.access.credential.enrollment.succeeded, and the person holds no new credential. This is the cleanup half of the capability: a capture that half-happened must not leave a credential nobody can use, and must not leave a record on the device that PQ does not know about - which would open the door for a card PQ cannot name.
Steps.
- command: pq.command.access.enroll.card
on: {reader}
reject:
- type=pq.event.access.credential.enrollment.succeeded;thing={reader}
timeout: 180
What the steps cannot decide. Confirm afterwards that the person holds no new credential AND that the device holds no credential record from the attempt. The second half matters more: a device that stored the capture anyway leaves a working credential invisible to PQ, which surfaces later as an unattributed grant rather than as an error.
AAT-ACCESS-ENROLLMENT-04¶
A template enrolled through PQ works at a device it was not captured on.
| Applies when | capability:access.enrollment |
| Stimulus | human · wave 2 |
| Capability | access.enrollment |
| Hardware | A reader with the sensor; a second reader makes the verdict stronger. |
| Preconditions | person_with_card_and_door_access |
| Depends on | AAT-ACCESS-ENROLLMENT-02 |
| Since | Matrix v17 |
Given. The AAT person holds a template credential captured through PQ, and a door grant.
When. Synchronization runs and the person then identifies by that template.
Then. They are granted, so the template genuinely travelled from PQ to the device.
PQ-visible behavior. pq.event.access.granted after the sync. This is what makes an enrolled template a CREDENTIAL rather than a local record: PQ can put it on any reader the person may use. Only the device decides whether it really arrived, so behavior is the evidence - a synchronization that reports success while the device silently discards the template looks identical from PQ.
Physical acts.
use_credential— the reader of a door the person is granted, ideally NOT the one they enrolled at (credential: the enrolled template - the person themselves)
Steps.
- command: pq.command.access.synchronize
on: {root}
expect:
- type=pq.event.access.synchronization.completed;thing={root}
timeout: 600
- stimulus: use_credential
expect:
- type=pq.event.access.granted
timeout: 180
What the steps cannot decide. Strongest on a SECOND reader, which no local enrollment could have reached. With one reader available, remove the template from the device first and let the sync put it back, so the grant cannot be explained by what the enrollment itself left behind.