Core flows
QR & PIN access
At the gate, the host scans the driver's QR code, or types a 6-digit PIN when there is no camera or no signal. Both prove the same thing: this person holds a live booking for this host's spot, right now.
Two credentials, two strengths#
| QR code | 6-digit PIN | |
|---|---|---|
| What it is | A signed token with the booking id and a random one-time id (jti) | HMAC(secret, booking id), shown as 6 digits |
| Lifetime | 120 seconds; the app fetches a new one 15 s before expiry while the pass is open | The whole booking |
| Replay | Each jti is accepted once (Redis SET NX), so a screenshot of an old QR fails | Only valid for this host's listings and the booking's time window |
| Works offline | The driver needs a connection to refresh it | Yes: the driver can always re-display it |
| Stored secret | None: the server signs and verifies | None: re-derived from the booking id on every check |
app/domain/access.pypython
class AccessCodeService: def pin_for(self, booking_id: uuid.UUID) -> str: # Nothing secret is stored in the database; rotating ACCESS_CODE_SECRET invalidates every PIN. digest = int(hmac_hex(self._secret, f"pin:{booking_id}"), 16) return str(digest % 10**self._pin_length).zfill(self._pin_length) def verify_pin(self, booking_id: uuid.UUID, pin: str) -> bool: return constant_time_equals(self.pin_for(booking_id), pin)Check-in at the gate#
Swipe sideways to see the whole figure.
- Check-in opens 15 minutes before the booked start and closes at the booked end.
- Verification is rate limited per host, which matters for PINs: 6 digits are only safe if nobody can try thousands of them.
- If Redis is unavailable, QR check-in fails rather than skip the replay check; the PIN, which needs no Redis, is the fallback at the gate.
Check-out and overstay#
The driver ends the session in the app with POST /bookings/{id}/check-out. The server compares the time with the booked end: 5 minutes of grace, then ₹20 (plus GST) for every started 15-minute block. The final amount, receipt and ledger entries are all written in one transaction.
overstay fee (₹, before GST)
Swipe sideways to see the whole figure.