Skip to content

wardn documentation

Version: v1.2.0

wardn is a physical access control system. Doors keep deciding on their own when the network is down. The cloud stays in charge again once the network comes back.

A door here is anything that opens for a credential. It can be an office door, a parking lane, a yard gate, or a turnstile. The system treats them all the same way. From the controller's point of view, they are the same thing.

This documentation is the reference for the system. It assumes no prior knowledge of the project, of access control, or of the technologies involved. It is written to be read on its own. Everything stated here is what the software actually does today.

Where to start

You are… Start at…
Curious, you want to understand the project 1. The problem
A developer, you want it running this morning 2. Getting started
An architect, evaluating the design 3. Architecture
An integrator, wiring your software into it 9. The API
An operator, keeping it alive 12. Operating
A contributor, about to write code 13. Developing

The full path

flowchart TD
    subgraph U["Understand"]
        A["1. The problem"] --> B["2. Getting started"] --> C["3. Architecture"]
    end
    subgraph F["Feature by feature"]
        D["4. A decision"] --> E["5. Access rights"] --> G["6. Going offline"]
        G --> H["7. The fleet"] --> I["8. The dashboard"] --> J["9. The API"]
    end
    subgraph X["Cross-cutting"]
        K["10. Security"] --> L["11. Personal data"]
        L --> M["12. Operating"] --> N["13. Developing"]
    end
    C --> D
    J --> K

Understand

  1. The problem. Why a door is an interesting problem for software, and the one idea wardn is built around.
  2. Getting started. Install it, run it, open a door with a badge. Ten minutes, nothing to configure.
  3. Architecture. The six components, the message channels between them, and why they are kept separate.

Feature by feature

  1. A decision. What happens between the badge presented and the door rising, rule by rule.
  2. Access rights. Who may enter, how you say so, how it reaches the cabinet, and how the two ends stay in agreement.
  3. Going offline. What happens when the network drops. This is the heart of the project.
  4. The fleet. Watching cabinets, driving them remotely, updating them over the air.
  5. The dashboard. The screens, and the live feed.
  6. The API. The complete integration reference: endpoints, authentication, provisioning, errors, pagination, the live socket.

Cross-cutting

  1. Security. Identities, certificates, confinement between customers, and the limits that are still open.
  2. Personal data. The three journals, retention, right of access, right to erasure.
  3. Operating. Deployment, backups, restores, certificates, monitoring, and the complete configuration reference.
  4. Developing. Repository layout, tests, the executable scenarios, continuous integration.

Two reading conventions

Blocks marked like this explain a design choice that would otherwise look arbitrary:

Why this way? The cloud never decides an opening. It could, technically. But a door that waits for an answer from the network is a door that stays shut the day the 4G link goes down.

And these state a real limit of the system as it stands today:

⚠️ Known limit. OSDP Secure Channel is not implemented. Frames on the RS-485 bus are in the clear.

Neither is decoration. An access control system that hides its limits is a system whose limits get discovered at the worst possible moment. Every known limit in this documentation is collected in 10. Security → What is not there yet.

Conventions used throughout

  • Instants are stored in UTC. Every zone carries an IANA timezone, and that is what an instant is rendered in. A passage at the Lisboa site read in Brussels time is the wrong hour.
  • edge-01 is a device identifier, the name painted on the cabinet and the name it publishes under. The UUID beside it exists only in the database. Both appear, because an operator on site reads one, and a log carries the other.
  • Shell examples assume the local stack, started with make up, with the default ports from .env.example.