Skip to content

2. Journeys

The model every scan runs through, and the journeys built on it.

2.1 The model

A few ideas repeat across every segment. Get these and the journeys follow.

Zone. A zone is a named thing a grant points at — "Park Entry", "Class 5A", "Floor 3" — with one or more devices assigned to it. It is not a shape on a map; it is just the devices plus the policy on them. Ten turnstiles at a park entrance are one zone; a single classroom reader is a zone of one. Because grants point at the zone, you can add, swap, or remove devices without touching anyone's grant.

One rail, many effects. Every scan runs the same path: the device reads the palm, Identity says who it is, and Access returns a single allow or deny. What allow does is set by the zone — a set of effects: open a gate, debit a balance, mark attendance, send a notification. A deny means "don't proceed", with a reason to show. Identity logs every scan for audit either way.

flowchart TB
  Scan["Palm scan at a device"] --> Id["Identity — identify (1 to N)"]
  Id -->|not recognized| NR["reader: not recognized"]
  Id -->|recognized| Dec{"Access — allow or deny?"}
  Dec -->|deny| Dn["don't proceed, show reason"]
  Dec -->|allow| Eff["zone effects"]
  Eff --> Open["open gate"]
  Eff --> Debit["debit balance"]
  Eff --> Att["mark attendance"]
  Eff --> Notify["notify"]

Effects combine. A zone fires every effect configured on it, not one of them: a school gate is open + attendance + notify, a canteen till is debit, a classroom reader is attendance alone. The gate opens on the critical path; attendance and notifications happen right after the answer.

One model covers a turnstile, a till, and a classroom reader — they differ only in what allow triggers. Pay is the exception to zones: you spend from your balance at any till, so pay needs no zone grant. Zones gate access and attendance; the balance gates pay.

2.2 Enter

At a gate, allow opens the turnstile.

The visitor holds their palm to the gate. Identity recognizes them and hands the scan to Access through the broker; Access checks whether a valid grant covers this zone right now, and answers allow or deny. On allow the gate opens; on deny it stays shut with a reason.

sequenceDiagram
  participant D as Gate (turnstile)
  participant I as Identity (identify + broker)
  participant A as Link Access
  D->>I: palm scan
  I->>I: identify (1 to N)
  I->>A: authorize(action=entry, device_id)
  A->>A: valid grant for this zone, now?
  A-->>I: allow / deny + message
  I-->>D: open, or "see attendant"
  Note over D: Fallback — attendant scans pass QR, or manual override

A school gate stacks effects. The child scans, the turnstile opens, the scan is recorded as that morning's attendance, and the guardian gets a notification — one scan, one allow, three effects from the zone's configuration.

Fallback. If the palm can't complete — hardware, network, or a face the system can't place — an attendant scans the pass QR from the visitor's app and opens the gate, or uses the manual override on the turnstile. Every pass carries that QR for exactly this.

Frontend: gate device + attendant tool.

2.3 Pay

At a till, allow debits the balance.

The visitor holds their palm to the till reader with the amount attached. Identity recognizes them; Access debits their closed-loop balance and returns allow with the new total, or deny if there aren't enough funds. The debit is idempotent — if the device retries, the same charge never lands twice.

sequenceDiagram
  participant D as Till (POS)
  participant I as Identity (identify + broker)
  participant A as Link Access
  D->>I: palm scan + {amount}
  I->>I: identify (1 to N)
  I->>A: authorize(action=pay, context={amount}, idempotency_key)
  A->>A: debit balance (idempotent)
  A-->>I: allow, "Approved, balance 120 SAR" / deny, "Insufficient"
  I-->>D: show result
  Note over D: Fallback — cashier scans app QR

Fallback. If the palm can't complete, the cashier scans a QR from the visitor's app to charge the same balance.

Frontend: till device.

2.4 Attendance

At a classroom or bus zone, allow means "✓ recorded" (and optionally notifies a guardian) with no barrier to open.

This shows the degenerate form of allow: the reader is a gate-class device bound to the attendance action (or a future reader class). The scan is either recognized and recorded, or not recognized.

Frontend: classroom/bus reader device.

2.5 Enroll

At a kiosk, the visitor enrolls both hands to bind their physical palm to their digital account. Enrollment is device-initiated: the kiosk captures the palms, the user provides mobile+OTP via the app to link the session, and consent is enforced.

sequenceDiagram
  participant K as Kiosk
  participant A as Consumer App
  participant I as Identity Platform
  K->>I: Initiate enrollment (device-initiated, both hands)
  A->>I: Mobile + OTP validation
  Note over I: Enforce consent
  I-->>K: Enrolled

For a park visitor, there is no KYC. The system links the hands to the phone number and the app session.

Frontend: enrollment kiosk + consumer app.

2.6 Grant lifecycle

A grant is an entitlement to a zone, bounded by a validity window. A day pass and a season pass are just single grant instances with different time bounds.

The source of the grant varies entirely by segment (see §2.9), but the states don't:

stateDiagram-v2
  [*] --> issued: created (purchase, roster, pre-reg)
  issued --> active: window opens
  active --> expired: window closes
  issued --> revoked: cancelled or refunded
  active --> revoked: cancelled or refunded
  expired --> [*]
  revoked --> [*]

Only an active grant lets a scan through. Everything else is a deny with a reason.

Frontend: consumer app (buy pass) / operator console (manage).

2.7 Ledger lifecycle

The ledger manages closed-loop funds for a tenant. It runs strictly per-tenant with no cash-out across venues. The lifecycle covers:

  • Top-up: credit via app or kiosk (card).
  • Spend: debit at a till (see §2.3).
  • Refund / withdraw: back to the original source, not as cash.

Every operation is idempotent.

Frontend: consumer app / kiosk (top-up) + till (spend).

2.8 Accounts & relationships

Accounts and relationships sit in Access as a layer over Identity's shared user model.

  • Org accounts: tenant administrators.
  • Member accounts: the individuals (student, employee, visitor, parent).
  • Relationships: guardian parent ↔ student, or group/family links.

These relationships power parent-funding, guardian pickup, and dictate the single app's runtime mode (parent, member, or org-admin).

Frontend: consumer app (modes) / operator console (org).

2.9 Per-segment layer

The shared engine adapts to Parks, Schools, and Offices through configuration.

Segment Enter Pay Attendance Enroll Grant source Funding
Parks Turnstiles Food, merch None Kiosk (no KYC) Buy-pass (app/web) Self top-up
Schools Gates Cafeteria Classrooms, buses Kiosk SIS roster Parent funding
Offices Doors, turnstiles Canteen Desk booking Kiosk HR system Employer / self

Parks detailed. A park visitor buys a pass (the grant) and tops up their balance (the ledger) themselves in the app. Day and season passes are just different validity windows on the entry grant.

Schools & Offices mapped. A school or office syncs users from an upstream SIS or HR system to provision grants and accounts. Funding often comes from parents or employers, and consent is collected out-of-band by the institution.

Not zone outcomes: Some features look like access but aren't. A camera feed for parents is a relationship-scoped app permission (consent-gated), not a zone effect. A library checkout is an optional lending capability.

Future segment features

Guardian two-party correlation (requiring both parent and child scans) and bundled entry+credit packages.