UC-011: Denied Card Escalation¶
Actor: Member with scheduled access (outside their time window) Priority: Should Status: Implemented (firmware denial tracking + escalation trigger + TOTP keypad)
Summary¶
A member whose card is denied (e.g., outside their scheduled time slot) can escalate by scanning their card repeatedly. After 3 denied scans within 1 minute, a guarantor is notified and can grant access by sharing their TOTP code over the phone. The member enters the guarantor's key-ID and code on the CONLAN M1200 keypad.
Preconditions¶
- Member's NFC card is in the allow-list with SCHEDULED access
- Current time is outside the member's allowed time slots
- ESP32 has network connectivity (for sending the escalation notification)
- At least one guarantor (role >= 0x40) has a TOTP entry in the allow-list
Main Flow¶
- Member arrives outside their scheduled time and scans their NFC card
- ESP32 denies access — red LED + denial buzzer
- Member scans card again within 1 minute — denied again (2nd scan)
- Member scans card a third time within the same 1-minute window
- ESP32 detects escalation threshold reached (3 scans within 60s)
- ESP32 queues escalation event:
{"event": "escalation_triggered", "uid": "...", "timestamp": ...} - LED blinks yellow to indicate "waiting for approval"
- Member calls a guarantor they know (phone number known from community)
- Member explains the situation; guarantor decides whether to approve
- Guarantor opens their authenticator app and reads the current TOTP code
- Guarantor tells the member their key-ID and the 6-digit code over the phone
- Member types
<guarantor_key_id>#<code>#on the CONLAN M1200 keypad - ESP32 looks up the guarantor's TOTP entry, verifies the code locally (wide window T-10 to T+1)
- Code valid — door unlocks, green LED + confirmation beep
- ESP32 clears the denial record for this UID
Alternative Flows¶
A1: Guarantor denies the request¶
- Member calls a guarantor who decides not to approve
- Guarantor does not share a TOTP code
- Member cannot enter a valid code — access remains denied
- Member's subsequent scans restart the escalation cycle if desired
A2: Member stops scanning¶
- After 1 or 2 denied scans, the member gives up and leaves
- No escalation is triggered (threshold not reached)
- Denial record expires when the 1-minute window passes
A3: ESP32 has no network connectivity¶
- Member scans card 3 times, escalation threshold reached
- ESP32 has no network connectivity — escalation event is queued for the next successful sync
- Member calls a guarantor directly (TOTP verification is purely local, no network needed)
- Guarantor shares their key-ID and TOTP code by phone — access granted as normal
A4: Guarantor uses HOTP backup code¶
- Guarantor does not have an authenticator app available
- Guarantor reads an HOTP backup code from a printed list
- Member types the backup code on the keypad
- ESP32 verifies against the HOTP counter — access granted
Error Flows¶
E1: Wrong code entered¶
- Member enters an incorrect code on the keypad
- ESP32 rejects — red LED flash
- Member can retry (up to 3 attempts before keypad lockout)
E2: Keypad locked out¶
- After 3 failed code entries within 5 minutes, keypad is locked for 5 minutes
- NFC card access still works during keypad lockout
- Lockout resets after the 5-minute period
Postconditions¶
- If approved: member gains one-time access via guarantor's TOTP code, door unlocks
- No allow-list modification needed — TOTP grants immediate, one-time access
- Escalation event is logged with the guarantor's key-ID for audit trail
- TOTP counter updated to prevent replay
Access Rule¶
- Escalation works for any card in the allow-list that is denied due to time restrictions
- The mechanism does NOT work for unknown cards (UID not in allow-list)
- Escalation parameters are configurable in
config.h: ESCALATION_SCAN_COUNT— number of denied scans to trigger (default: 3)ESCALATION_SCAN_WINDOW_MS— time window for repeated scans (default: 60s)- TOTP/HOTP parameters in
config.h: TOTP_TIME_STEP— TOTP time step in seconds (default: 30)TOTP_WINDOW_GUARANTOR_BACK— guarantor code back window (default: 10 = 5 min)TOTP_WINDOW_GUARANTOR_FORWARD— guarantor code forward window (default: 1)KEYPAD_MAX_ATTEMPTS— max failed entries before lockout (default: 3)KEYPAD_LOCKOUT_MS— base lockout duration, doubles each time (default: 5 min)
Sequence Diagram¶
Member NFC Terminal ESP32 Backend Guarantor
| | | | |
|--- scan 1 ----->|--- UID ---->| | |
| | |-- DENIED (1/3) --->| |
|<--- red LED ----| | | |
| | | | |
|--- scan 2 ----->|--- UID ---->| | |
| | |-- DENIED (2/3) --->| |
|<--- red LED ----| | | |
| | | | |
|--- scan 3 ----->|--- UID ---->| | |
| | |-- ESCALATION! ---->| |
|<--- yellow LED -| | (queued event) | |
| | | | |
|--- calls guarantor by phone ---------------------------------------->|
| | | | |
|<-- guarantor tells key-ID + TOTP code by phone ------------------|
| | | | |
|--- keypad: 5#287082# -->|---->| | |
| | |-- lookup key 5 | |
| | |-- TOTP verify | |
| | |-- GRANTED | |
|<--- green LED --| | | |
Notes¶
- The member initiates contact — they call a guarantor they know. There is no intercom at the door, so the guarantor cannot contact the member.
- TOTP verification is purely local — no network round-trip needed. Works even without network connectivity.
- TOTP secrets are per-user — the guarantor's key-ID identifies which secret to check. The event log records which guarantor authorized entry.
- The guarantor code uses a wide acceptance window (T-10 to T+1 = 5 min back) to account for phone communication delay.
- Only cards already in the allow-list can trigger escalation. Unknown cards are ignored to prevent abuse.
- The ESP32 tracks up to 4 UIDs simultaneously (
MAX_DENIAL_TRACKS). If all slots are full, the oldest record is evicted. - Future: The ESP32 queues escalation events for backend sync. The backend could forward these to a messenger group channel (e.g., Signal, Telegram) as an additional notification — potentially with smart scheduling (different recipients depending on day of week/month). This is secondary to the direct phone call flow and not yet implemented.
- See ADR-008 for the full TOTP/HOTP design rationale.