Attendance Sanchalan
Sanchalan Docs
Prototype

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

  1. Open https://attendance.rajyasabha.digital/admin/login.
  2. Enter any email (e.g. you@rajyasabha.digital), pick role admin, sign in.
  3. You land on the dashboard with live counts of today's punches, late arrivals, absent, pending leaves, and a 7-day trend bar.
  4. Click into Today / Late / Absent / Pending leaves / Pending tours / Devices / Holidays / Reports via the top tabs.
  5. Click any employee name to drill into their monthly calendar grid + leave balances + recent applications.
  6. 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

MetricCount
Synthetic employees seeded2,300
Holidays seeded (2026)13
Geofences seeded7 (1 main + 4 committee + 2 MP residences)
Leave policies seeded9 (6 CCS types × applicable employee categories)
API endpoints18+ (v1 + auth + admin + docs)
Admin pages9 (Dashboard, Today, Late, Absent, Leaves, Tours, Devices, Holidays, Reports)
Mobile screens10 (Login, Home, Punch, Today, Month grid, Leave×2, Tour×2, Holidays, Devices, Profile)
Tests18 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