Architecture Overview
Guiding Principles
- API-first. Every feature is exposed as a documented REST endpoint before any UI consumes it. Web and mobile share a single contract.
- Idempotent processing. Attendance records are derived; re-running the processor against the same punches + rules yields the same outputs.
- Scope-aware by default. Every query goes through a policy-scoped repository — you can't forget a
WHERE organization_id = ?. - Everything is audited. No write path bypasses the audit log.
- Degrade gracefully. If the queue is down, raw punches still land. If reporting is busy, check-ins still succeed.
High-Level Components
┌──────────────────────────────────────────────────────────────┐
│ Client Surfaces │
│ ┌──────────┐ ┌────────────┐ ┌──────────────────────┐ │
│ │ React UI │ │ Flutter │ │ Telegram Bot │ │
│ │ (ui/) │ │ (app/) │ │ (PHP webhook) │ │
│ └─────┬────┘ └─────┬──────┘ └──────────┬───────────┘ │
└────────┼───────────────┼──────────────────────┼──────────────┘
│ │ │
│ Sanctum tokens (HTTPS) │
▼ ▼ ▼
┌────────────────────────────────────────── ────────────────────┐
│ Laravel API (server/) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Routes ─► FormRequest ─► Controller ─► Service │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ Domain Services │ │
│ │ (AttendanceProcessor, RosterService, RedFlagEngine) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ Eloquent Models + Policies │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Filament SystemAdmin panel · Horizon queue dashboard │
└──────────────────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Infrastructure │
│ MySQL 8 · Redis (queue + cache) · Object storage (S3) │
│ Nginx · Traefik (TLS) · Prometheus / Loki │
└──────────────────────────────────────────────────────────────┘
Layered Responsibility
| Layer | Contents | Never Contains |
|---|---|---|
| Controllers | HTTP plumbing, auth context, delegation to a Service. | Business rules, DB queries beyond trivial lookups. |
| Form Requests | Validation, authorization (via Policy). | Business rules. |
| API Resources | Shape of response JSON. | Side effects, DB queries. |
| Services | Business rules (attendance processing, roster logic, red flags). | HTTP awareness. |
| Models | Eloquent definitions, relationships, casts, global scopes. | Business rules that span multiple aggregates. |
| Policies | Authorization rules per resource. | Validation. |
| Jobs | Async work (processing, notifications, exports). | User interaction. |
Read / Write Paths
- Write path. Client →
POST /api/v1/attendance/punch→IngestPunchRequest→AttendanceController→PunchIngestService→ persist raw punch → dispatchProcessAttendanceJob. - Async path.
ProcessAttendanceJob→AttendanceProcessorservice → upsertattendancerow → evaluate red flags → attachattendance_flagsrows → audit. - Read path. Client →
GET /api/v1/attendances?...→AttendanceController@index→ scoped repository → API Resource.
Deployment Topology
Docker Compose with Traefik is the V1 topology (already in docker-compose.yml). The same images deploy unchanged to ECS / Kubernetes later. MySQL and Redis are stateful; application containers are stateless.