An Eight Mile Services project · open source

RACS

Reader Access Control System

Keep the door moving, even when the network does not.

A camera-first access reader that validates campaign cards locally, stops repeat entry across nearby devices, and reconciles every decision with a central API.

Offline-ready access decisions with a durable retry queue.

Reader

Flutter 3

API

Spring Boot 4

Store

MySQL + SQLite

Sync

WS + WebRTC

RACS Scanner app showing the live camera reader, scan frame and operator controls

At the entrance · 01

One focused flow from camera to decision.

RACS keeps the interface deliberately spare. Operators prepare their campaign once, then each presentation produces a clear outcome while the system handles persistence and synchronisation underneath.

Operator path

campaign → decision

01 · Prepare

Download the campaign

Choose the active campaign and place its authorised card set on every reader.

02 · Read

Frame the code

The full-screen camera focuses the operator on one task: presenting the pass cleanly.

03 · Decide

Validate on device

Format, card state, validity window and prior use are checked against local data.

04 · Reconcile

Share the decision

The scan is stored locally, submitted centrally and broadcast to connected readers.

Legible outcomes · 02

The answer is readable at a glance.

A busy entrance should not require interpretation. Every card ends in a distinct state, while the exact machine flag remains attached for audit and reporting.

Access granted

Valid, current and unused

PASSED_OK

Already presented

Seen by this reader, a peer or the API

DUPLICATE

Access declined

Unknown, expired or invalidated card

REJECTED

Network resilience · 03

The venue can lose signal. The entrance keeps context.

RACS uses the server when it is available and local evidence when it is not. Nearby readers cooperate directly, closing the window where one pass could be accepted twice at separate doors.

Continuity layers

connection optional

Keep admitting offline

local-first

Campaign cards and prior scans live in SQLite on the reader, so a dropped uplink does not stop local checks.

Warn nearby readers

peer-to-peer

Readers form a WebRTC mesh. A successful scan can mark the same card used on peers without waiting on the public network.

Catch up safely

durable retry

Transient API failures enter a local dead-letter queue and retry later; local scan history keeps the attempted decision visible.

Operational control · 04

More than a scanner.

The reader includes the small set of controls a deployment needs: campaign selection, local card management, scan history, queued work, diagnostics and connection settings.

Campaign sync

Select the event campaign, download its cards and see the local count before doors open.

My scans

Review a paginated on-device history with card label, outcome and exact timestamp.

Every attempt retained

Accepted and rejected presentations are stored locally and recorded centrally when reachable.

Retry visibility

Queued requests and application logs give operators evidence when connectivity needs attention.