Skip to content

Contents · Next → 2. Getting started

1. The problem

A door that has to open

Somebody arrives at a door and presents a credential. It could be a badge, a plate, or a QR code. The door opens. That is all.

The scene takes three seconds. Nobody thinks about it, until the day it does not happen. Then a queue forms, people are late, someone calls reception. It turns out the door depended on an internet connection nobody had ever mentioned.

That is the problem wardn solves.

A door is whatever opens for a credential: an office door, a lift landing, a parking lane, a yard gate, a turnstile. wardn treats them all the same way. From the controller's point of view they are the same thing. Each is a credential to resolve, a decision to take, a contact to close, a record to keep.

What makes it hard

The site is badly connected. It could be an underground level, a warehouse on an industrial estate, or a building reached by a 4G router or by a customer's own network you have no authority over. An outage is not a rare accident. It is a normal operating condition.

A decision must be made in under half a second. Nobody waits at a door. A round trip to a distant server, plus 4G latency, already eats that budget on a good day. wardn gives itself 300 ms (DECISION_TIMEOUT_MS), and the cabinet measures itself against it.

Nothing may be lost. A passage that goes unrecorded means a wrong invoice, a security investigation with no answer, or a legal obligation left unmet, even if the network was down for four hours.

The data is personal. Who went where, when, with what. That is processing under the GDPR, with everything it implies: retention periods, right of access, right to erasure.

Not every door is alike. Some sites have lanes that are all equivalent. Others have a lobby, a floor, and a server room that each need a different permission. Both are the same product, and the model has to hold both.

There are several customers. One system serves several companies. None may ever see another's data, not even a cabinet identifier.

The one idea

The cloud never decides an opening.

Each site has a small computer: the cabinet, also called the edge controller. It is installed in an enclosure, on a DIN rail, next to the circuit breakers. It holds its own copy of the access rights in a local encrypted database.

When a badge is presented, the cabinet decides on its own. It asks nobody. The network can have been down for a week: the door behaves exactly the same.

flowchart LR
    subgraph BAD["The obvious design"]
        R1["Reader"] --> E1["Cabinet"]
        E1 -->|"asks: may this badge in?"| C1["Cloud"]
        C1 -.->|"answer"| E1
        E1 --> B1["Door"]
    end
    subgraph GOOD["wardn"]
        R2["Reader"] --> E2["Cabinet"]
        E2 -->|"decides locally"| B2["Door"]
        E2 -.->|"afterwards, asynchronously"| C2["Cloud"]
    end

In the first design, every network incident is a site outage. In the second, the network is never in the critical path.

The cloud keeps two roles:

  • it is the source of truth: this is where you declare who may enter, and it pushes those rights to the cabinets concerned;
  • it is the memory: cabinets report every passage to it, and it keeps them, cross-references them, makes them available.

Both roles are asynchronous. Neither sits in the path of a door opening.

Why this way? The alternative, where the cloud decides, is simpler to write. One database, no synchronisation, no conflicts. But it turns every network incident into a site outage, and every millisecond of latency into somebody standing at a door. The choice wardn makes instead spends complexity in the code to remove it on the ground. This documentation describes that complexity, because hiding it would not make it go away.

What follows from that idea

Almost everything else in the system is a consequence of this one choice. It is worth watching them arrive.

flowchart TD
    ROOT["The cabinet decides alone"]
    ROOT --> R1["It needs the rights locally"]
    ROOT --> R2["It must store passages while offline"]
    ROOT --> R3["It cannot check its own clock"]
    ROOT --> R4["It must be watchable from far away"]
    ROOT --> R5["It sits on someone else's network"]
    R1 --> C1["Rights deltas, a fingerprint check,<br/>a nightly full sync"]
    R2 --> C2["A local bounded queue,<br/>replayed and deduplicated"]
    R3 --> C3["A monotonic clock check,<br/>reported to the cloud"]
    R4 --> C4["Telemetry, alerts,<br/>live debug, OTA updates"]
    R5 --> C5["Outbound-only MQTT over mTLS,<br/>no inbound port"]

Each branch has its own chapter: rights, offline, the fleet, security.

The vocabulary

These words appear everywhere. There are not many.

Term What it is
Cabinet (edge controller, device) The box installed on site. It reads credentials, decides, drives the doors, and keeps the journals. It is what makes the system resilient.
Door Whatever opens for a credential, driven by a dry contact: a door, a lane, a gate, a turnstile. One cabinet drives several.
Reader (identification device) The hardware that reads a credential: badge reader, plate camera, QR reader, keypad.
Credential What a person presents: a badge number, a licence plate, a QR code, a PIN.
Access right The authorisation: "this person, with these credentials, may pass at this zone, between these two instants".
Passage (activity log) The record of what happened: credential read, decision, reason, timestamp. Both a grant and a refusal are journalled.
Tenant A customer. A company whose sites wardn controls. Confinement between tenants is a strong guarantee of the system.
Zone A physical site belonging to a tenant: a car park, an office floor, a yard. Carries a timezone, because a passage is read where it happened.
Door group A named subset of a zone's doors. A right naming none reaches every door of its zone.
Store & Forward The mechanism that keeps passages locally while the network is down, then replays them.
Revision A counter, one per cabinet, that says which version of the rights set it holds.
Fingerprint A digest over the rights a cabinet holds, so the cloud can tell agreement from drift without shipping the set back.

What wardn is not

To avoid misunderstandings, here are some explicit exclusions:

  • it is not a booking system: it enforces rights, it does not decide them;
  • it is not a payment or invoicing system;
  • it does not count free spaces or manage occupancy;
  • it does not do video surveillance: it reads a plate through an ANPR camera, it stores no image.

wardn receives access rights. They can come from a booking system, a third-party connector, or be typed by hand in the dashboard. wardn makes sure they are enforced at the door, including when nothing else answers.


You now know what the project is for and why it is built this way. Time to run it.

Next → 2. Getting started