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.