Working prototype
This is what's running right now in the dev environment. All URLs are live; you can click and try them.
Try it — admin web
- Open https://attendance.rajyasabha.digital/admin/login.
- Enter any email (e.g.
you@rajyasabha.digital), pick roleadmin, sign in. - You land on the dashboard with live counts of today's punches, late arrivals, absent, pending leaves, and a 7-day trend bar.
- Click into Today / Late / Absent / Pending leaves / Pending tours / Devices / Holidays / Reports via the top tabs.
- Click any employee name to drill into their monthly calendar grid + leave balances + recent applications.
- Click Reports → Download CSV to grab a date-range punch export.
Dev mode lets you pick your role from a dropdown for testing. In production, AUTH_MODE=sso routes login to sb-iam (Parichay) and the role comes from the IDP claim.
Try it — API
Get an API token by creating a user via tinker, or via SSO when enabled. Quick example:
# 1) public probes — no auth
curl https://attendance.rajyasabha.digital/api/healthz
curl https://attendance.rajyasabha.digital/api/auth/mode
# 2) auth'd: get a personal access token via tinker (dev only)
docker compose exec app php artisan tinker --execute='
$u = App\Models\User::firstOrCreate(["email"=>"smoke@rajyasabha.digital"],
["name"=>"Smoke","password"=>bcrypt("dev"),"role"=>"admin","active"=>true,
"employee_id"=>App\Models\AttendanceEmployeeRegister::first()->id]);
echo $u->createToken("smoke",["attendance.punch","attendance.leave"])->plainTextToken;
'
# 3) hit any v1 endpoint
TOK=<paste-token>
curl -H "Authorization: Bearer $TOK" \
https://attendance.rajyasabha.digital/api/v1/me
Try it — full punch flow (curl)
The signed punch flow is exercised end-to-end by /tmp/punch-smoke.sh on the host. It generates a P-256 keypair, registers a device, signs a punch with raw r||s base64, and asserts the verdict matrix:
/tmp/punch-smoke.sh '<your-bearer-token>'
Expected output:
=== 1. /auth/mode (public) === 200
=== 2. /v1/devices/register === 201
=== 3. /v1/devices (list) === 200
=== 4. /v1/punch (IN, inside seed fence) === 201 verdict=accepted
=== 5. replay same nonce -> duplicate === 422 verdict=duplicate
=== 6. /v1/punches/today === 200
=== 7. /v1/leaves/balances === 200
=== 8. /v1/leaves (apply 1 day CL) === 201
=== 9. punch from outside fence -> rejected_geofence 422 verdict=rejected_geofence
Try it — mobile
The Flutter source repo lives at /home/kushal/apps/sanchalan_setu/attendance_mobile/. To run it on a dev machine with Flutter installed:
cd attendance_mobile
./scripts/bootstrap.sh # materialise platform shells, pub get, manifest patches
flutter run \
--dart-define=API_BASE=https://attendance.rajyasabha.digital/api \
--dart-define=IMEI_SALT_FRONTEND=$(openssl rand -hex 16)
What's live in numbers
| Metric | Count |
|---|---|
| Synthetic employees seeded | 2,300 |
| Holidays seeded (2026) | 13 |
| Geofences seeded | 7 (1 main + 4 committee + 2 MP residences) |
| Leave policies seeded | 9 (6 CCS types × applicable employee categories) |
| API endpoints | 18+ (v1 + auth + admin + docs) |
| Admin pages | 9 (Dashboard, Today, Late, Absent, Leaves, Tours, Devices, Holidays, Reports) |
| Mobile screens | 10 (Login, Home, Punch, Today, Month grid, Leave×2, Tour×2, Holidays, Devices, Profile) |
| Tests | 18 phpunit + 4 flutter unit |
Container fleet
$ docker compose ps
attendance_dev-app-1 app Up (healthy) apache + php 8.2 — serves /api/* and /admin/*
attendance_dev-web-1 web Up nginx 1.27-alpine — reverse proxy, port 8092
attendance_dev-worker-1 queue:work Up (healthy) queue runner (jobs not used yet — placeholder)
attendance_dev-audit-1 audit:consume Up (healthy) drains Redis stream sds:audit:events into sds_audit PG
