Skip to content
Samar Siddiqui
All projects

2026Personal Project

Airport Valet Management System

  • Kotlin
  • Jetpack Compose
  • Node.js
  • Express
  • PostgreSQL 16
  • AWS S3
  • Docker
field-level encryption for PII
AES-256-GCM
check-ins queue and sync later
Offline-first

At a glance

  • Full-stack airport valet platform: Kotlin/Jetpack Compose Android app + Node.js/Express REST API on PostgreSQL 16, AWS S3, Nginx, containerized with Docker.
  • Offline-first Android client using Room, WorkManager, and MVVM with Hilt: queues unsynced check-ins locally and auto-uploads via background workers when connectivity restores.
  • CameraX + Google ML Kit OCR for guided photo intake that auto-extracts license plates and vehicle details, reducing manual entry at check-in.
  • AES-256-GCM field-level encryption for PII with HMAC-based blind indexing for searchable encrypted fields, plus short-lived S3 presigned URLs for private photo access.
  • Hardened auth: HS256 JWT access/refresh tokens, server-side refresh rotation and revocation, configurable account lockout, and tiered rate limiting on auth and API endpoints.
  • Android release hardening: TLS certificate pinning, EncryptedSharedPreferences token storage, FLAG_SECURE to block screenshots/recents, and disabled ADB backup.
  • Deployment docs covering Docker Compose orchestration, Nginx TLS termination, env var reference, keystore signing, and certificate pin generation workflows.

A native Android valet platform with a hardened Node.js backend: designed so an attendant can pull out a phone at the curb, point at a license plate, and create a complete, encrypted, audit-ready record in under a minute, even with no internet.

Purpose

I built the Airport Valet Management System to solve a real operational problem I saw at airport valet stands: vehicle intake is still done with paper tickets and handwritten plates, which leads to slow check-ins, lost records, and disputes when a car gets damaged or misplaced. I wanted to design a single tool that a valet attendant could pull out at the curb, point at a license plate, and have a complete, encrypted, audit-ready record created in under a minute, even with no internet.

The goals I set going in:

  • Speed at the curb. Intake had to be faster than paper, not slower. That ruled out long forms and pushed me toward camera-first capture with OCR auto-fill.
  • Works without signal. Airport garages have terrible connectivity, so the app could never depend on a live network. Records had to queue locally and sync later without the user thinking about it.
  • Treat customer data like it matters. Names, plates, and vehicle photos are sensitive. I wanted field-level encryption and short-lived signed URLs from day one rather than bolted on later.
  • Realistic enough to deploy. I wanted the project to demonstrate that I can ship a system, not just a demo: admin accounts, role-based access, lockouts, TLS termination, certificate pinning, Docker Compose for the backend.

It also gave me a chance to work end-to-end across a stack I cared about: native Android with modern Jetpack libraries on the client, and a hardened Node.js + PostgreSQL service on the back end.

Development process

  • 1. Problem framing and architecture. I started by mapping the valet workflow on paper (drop-off, photo capture, retrieval, handoff) and identified the two hardest constraints: offline-first behavior and field-level encryption. Those two requirements shaped almost every later decision. I sketched the architecture (Android client → Nginx/TLS → Node/Express → PostgreSQL + S3) before writing any code.
  • 2. Backend first. I built the Node.js/Express API with PostgreSQL 16 and a SQL-migration setup so the schema would be reproducible. Auth was JWT with rotating refresh tokens, account lockout after configurable failed attempts, and per-route rate limiting. Sensitive fields use AES-256-GCM at rest, and license plates are also HMAC-indexed so I can search without decrypting. Vehicle photos go to a private S3 bucket and are only ever served through short-lived presigned URLs.
  • 3. Android client with offline-first as a non-negotiable. The app is Kotlin + Jetpack Compose with MVVM and Hilt for DI. Room is the source of truth on the device: every check-in is written locally first, then WorkManager handles sync with retry/backoff when connectivity returns. CameraX drives photo capture; ML Kit's on-device OCR reads license plates and pre-fills the form so the attendant just confirms.
  • 4. Security hardening pass. Once the happy paths worked, I did a dedicated security pass: certificate pinning in release builds, tokens stored in EncryptedSharedPreferences, FLAG_SECURE to keep the app out of recents and screenshots, allowBackup=false, and CORS + secret-management cleanup on the backend.
  • 5. Deployment ergonomics. I containerized the backend with Docker Compose (Postgres + API + Nginx) so the whole stack stands up with one command, wrote a seed script for the initial admin, and documented the production path including TLS, cert-pin extraction, and signed release builds.
  • 6. Iteration. Recent work focused on UX polish, a redesign pass and edit/delete functionality for existing records, based on walking through the flow myself and noticing where the original screens slowed me down.

Stack at a glance: Kotlin, Jetpack Compose, CameraX, ML Kit, Room, WorkManager, Hilt, Retrofit · Node.js 20, Express, PostgreSQL 16, AWS S3, Nginx, Docker.