Spaces:
Sleeping
Sleeping
| # Ain El Aql Backend - Comprehensive Technical Documentation | |
| ## 1) Purpose and Scope | |
| This document is the single-source technical overview for the Ain El Aql backend. | |
| It covers: | |
| 1. System architecture | |
| 2. Authentication and authorization | |
| 3. Role model and access scope | |
| 4. Endpoint catalog and contracts | |
| 5. End-to-end data flow | |
| 6. Database model and relationships | |
| 7. Validation, errors, and operational behavior | |
| 8. Production readiness guidance | |
| Primary implementation file: | |
| - `API.py` | |
| Supporting documentation: | |
| - `docs/API_REFERENCE.md` | |
| - `docs/BACKEND_ARCHITECTURE.md` | |
| - `docs/ENVIRONMENT_VARIABLES.md` | |
| --- | |
| ## 2) System Architecture | |
| The backend is a FastAPI monolith that combines: | |
| 1. AI inference orchestration (local YOLO or remote model service) | |
| 2. Supabase-backed auth, profile, data persistence, and storage | |
| 3. Parking/session lifecycle and event feeds | |
| 4. Pricing and occupancy engines | |
| 5. Gate/payment decision logic | |
| ### Runtime Components | |
| 1. API framework: FastAPI | |
| 2. CV/ML runtime: OpenCV, NumPy, Ultralytics YOLO | |
| 3. Data/auth/storage backend: Supabase (Auth + PostgREST + Storage) | |
| 4. Payment provider: Paymob (optional) | |
| ### Inference Modes | |
| 1. `MODEL_INFERENCE_PROVIDER=local` | |
| - Inference executed in this service. | |
| 2. `MODEL_INFERENCE_PROVIDER=remote` | |
| - Backend calls external model runtime using `MODEL_SERVICE_URL`. | |
| --- | |
| ## 3) Authentication and Authorization | |
| The backend supports two authentication paths: | |
| 1. Supabase JWT bearer token | |
| 2. Barrier/device static token | |
| ### 3.1 Supabase Token Auth | |
| - Header: `Authorization: Bearer <supabase_access_token>` | |
| - Validation endpoint: Supabase `GET /auth/v1/user` | |
| - On successful verification: | |
| - backend derives user id/email | |
| - backend auto-creates a minimal `profiles` row when missing (best effort) | |
| Why auto-provision profile rows: | |
| - Prevent FK failures on writes referencing `profiles.id`. | |
| - Reduce silent persistence failures when auth users exist but profile rows do not. | |
| ### 3.2 Barrier/Device Token Auth | |
| - Header: `Authorization: Bearer <barrier_token>` | |
| - Token sources: | |
| - `BARRIER_API_TOKEN` (single token) | |
| - `BARRIER_API_TOKENS` (comma-separated tokens) | |
| - Comparison uses constant-time matching (`hmac.compare_digest`). | |
| - Returns synthetic auth context: | |
| - `id = BARRIER_SYNTHETIC_USER_ID` (default `barrier-device`) | |
| - `role = barrier` | |
| - `auth_type = barrier_token` | |
| Important: | |
| - Barrier auth is intended for machine integrations (camera/barrier clients). | |
| - Barrier auth is not a substitute for end-user mobile/web sessions. | |
| --- | |
| ## 4) Role Model and Access Scope | |
| Roles in runtime behavior: | |
| 1. `user` | |
| 2. `admin` | |
| 3. `security` | |
| 4. `developer` | |
| 5. `barrier` (synthetic API role) | |
| ### 4.1 Scope Rules | |
| 1. User scope: | |
| - Own records only | |
| 2. Staff scope (`admin`, `security`): | |
| - Global records | |
| - optional `for_user_id` filtering on feed/history endpoints | |
| 3. Barrier scope (`barrier`): | |
| - Global read scope for operational feeds/history and gate decision checks | |
| - Not treated as staff for privileged maintenance/payment confirmations | |
| 4. Developer scope (`developer`): | |
| - Access to developer endpoints (`/developer/*`) | |
| --- | |
| ## 5) Endpoint Catalog | |
| ### 5.1 Public/Utility | |
| 1. `GET /` | |
| 2. `GET /health` | |
| 3. `GET /supabase/health` | |
| 4. `GET /models` | |
| ### 5.2 Developer | |
| 1. `GET /developer/models` | |
| 2. `POST /developer/predict` | |
| ### 5.3 Authentication | |
| 1. `POST /auth/register` | |
| 2. `POST /auth/login` | |
| 3. `POST /auth/otp/request` | |
| 4. `POST /auth/otp/verify` | |
| 5. `POST /auth/forgot-password` | |
| 6. `POST /auth/reset-password/resolve-token` | |
| 7. `POST /auth/reset-password` | |
| 8. `GET /auth/reset-password-page` | |
| 9. `GET /auth/reset-password-bridge` | |
| ### 5.4 Profile and Vehicles | |
| 1. `PUT /profile/update` | |
| 2. `POST /vehicles/add` | |
| 3. `GET /vehicles/my` | |
| 4. `PUT /vehicles/{vehicle_id}` | |
| 5. `DELETE /vehicles/{vehicle_id}` | |
| 6. `POST /vehicles/verify` | |
| ### 5.5 Notifications | |
| 1. `POST /notifications/fcm-token` | |
| 2. `GET /notifications/my` | |
| ### 5.6 Inference and Model Runtime | |
| 1. `POST /predict` | |
| 2. `POST /model/infer` | |
| ### 5.7 Parking/Events/History | |
| 1. `GET /parking/locations` | |
| 2. `GET /parking/occupancy` | |
| 3. `GET /events/entered-cars` | |
| 4. `GET /events/leaving-cars-within-5-minutes` | |
| 5. `GET /events/new-cars` | |
| 6. `GET /events/left-cars` | |
| 7. `GET /events/inside-cars` | |
| 8. `GET /parking/history` | |
| ### 5.8 Payments and Gate | |
| 1. `POST /payments/paymob/create` | |
| 2. `POST /payments/paymob/webhook` | |
| 3. `POST /payments/manual/cash-confirm` | |
| 4. `POST /gate/decision` | |
| ### 5.9 Maintenance | |
| 1. `POST /admin/maintenance/weekly-refresh` | |
| --- | |
| ## 6) End-to-End Data Flow | |
| ## 6.1 Predict Request Flow (`POST /predict`) | |
| 1. Authenticate request (Supabase token or barrier token). | |
| 2. Validate optional inputs: | |
| - `event_type` in `{entry, exit, ocr_scan}` | |
| - `parking_location` pattern | |
| - `camera_source` pattern | |
| 3. Run inference pipeline (local or remote). | |
| 4. Build normalized plate payload. | |
| 5. Persist output to Supabase: | |
| - upload raw and processed images to storage buckets | |
| - resolve vehicle from OCR plate | |
| - resolve/create session depending on event type | |
| - create `car_events` row | |
| - optionally emit notification events | |
| 6. Compute and return: | |
| - `payment_status` | |
| - `pricing` | |
| - `gate_decision` | |
| - persistence metadata | |
| ## 6.2 Vehicle Resolution Logic | |
| The backend now matches OCR plates using both formats: | |
| 1. Arabic plate fields: `plate_letters_ar + plate_numbers_ar` | |
| 2. English plate fields: `plate_letters_en + plate_numbers_en` | |
| Matching order: | |
| 1. Owner-scoped lookup (when authenticated Supabase user id is available) | |
| 2. Global lookup fallback | |
| Effect: | |
| - Reduces false negatives where OCR returns one language format but not the other. | |
| ## 6.3 Session Lifecycle | |
| 1. `entry` | |
| - create or reuse open session | |
| 2. `exit` | |
| - use open session | |
| - if paid and within 5 minutes: close session (`status=exited`) | |
| - if paid but grace expired: keep open with `status=overstayed` | |
| - if unpaid: keep open (gate deny path) | |
| 3. `ocr_scan` | |
| - read context only, no session state transition | |
| ## 6.4 Unmatched Fallback Flow | |
| When a plate is detected but not linked to a registered vehicle/session: | |
| 1. Event is still stored in `car_events` (with nullable `vehicle_id`/`session_id`). | |
| 2. Backend builds inferred unmatched rows from entry/exit event streams by plate key. | |
| 3. Inferred rows are merged into: | |
| - `GET /parking/locations` | |
| - `GET /parking/occupancy` | |
| - `GET /events/inside-cars` | |
| - `GET /parking/history` | |
| Response markers for inferred rows: | |
| 1. `inferred_unmatched=true` | |
| 2. `plate` object (key/arabic/english) | |
| 3. `event_count` | |
| Occupancy responses also include source breakdown: | |
| 1. `inside_from_registered_sessions` | |
| 2. `inside_from_inferred_unmatched` | |
| --- | |
| ## 7) Database Model (Supabase) | |
| Core relational tables: | |
| 1. `profiles` | |
| - user identity/profile metadata | |
| - role and staff metadata | |
| 2. `vehicles` | |
| - vehicle registration and ownership | |
| 3. `parking_sessions` | |
| - parking lifecycle state | |
| 4. `car_events` | |
| - entry/exit/scan event stream | |
| 5. `payment_transactions` | |
| - payment ledger for paymob/manual cash | |
| Notifications and app links: | |
| 1. `notification_device_tokens` | |
| 2. `notification_events` | |
| 3. `app_links` | |
| ### Key Relationships | |
| 1. `profiles.id` -> `auth.users.id` | |
| 2. `vehicles.owner_id` -> `profiles.id` | |
| 3. `parking_sessions.vehicle_id` -> `vehicles.id` | |
| 4. `car_events.session_id` -> `parking_sessions.id` (nullable) | |
| 5. `car_events.vehicle_id` -> `vehicles.id` (nullable) | |
| ### Storage Buckets | |
| 1. `SUPABASE_RAW_BUCKET` (raw uploads) | |
| 2. `SUPABASE_PROCESSED_BUCKET` (split/admin images) | |
| --- | |
| ## 8) Security and Data Integrity | |
| ### 8.1 RLS and Role Design | |
| - Supabase RLS is enabled for core business tables. | |
| - Backend writes are performed via service role credentials. | |
| - Client-facing authorization is enforced in API layer by user role/scope. | |
| ### 8.2 Notification Event Hardening | |
| Current model: | |
| 1. Notification content is server-owned. | |
| 2. Authenticated users can read own notifications. | |
| 3. Authenticated users can only mark own notifications as read. | |
| 4. Client-side insert/delete/content edits are blocked. | |
| ### 8.3 Created-By FK Protection | |
| For persistence writes: | |
| - `created_by` is now populated only for Supabase-authenticated users. | |
| - Barrier-auth requests do not inject synthetic ids into FK-backed columns. | |
| This prevents FK violations and silent persistence drop scenarios. | |
| --- | |
| ## 9) Validation and Error Contract | |
| Common input validations: | |
| 1. Auth header format (`Bearer ...`) | |
| 2. `event_type` allowed values | |
| 3. parking location format | |
| 4. camera source format | |
| 5. file type and non-empty uploads | |
| 6. payment amount positive integer rules | |
| Common error statuses: | |
| 1. `400` invalid input | |
| 2. `401` auth missing/invalid/expired | |
| 3. `403` role or scope violation | |
| 4. `404` missing session/resource | |
| 5. `502` upstream integration failure | |
| 6. `503` missing critical configuration | |
| --- | |
| ## 10) Production Readiness Checklist | |
| ## 10.1 Required Environment | |
| 1. `SUPABASE_URL` | |
| 2. `SUPABASE_ANON_KEY` | |
| 3. `SUPABASE_SERVICE_ROLE_KEY` | |
| 4. `SUPABASE_ENFORCE_AUTH=true` (recommended) | |
| 5. model runtime config (`MODEL_INFERENCE_PROVIDER` + remote/local settings) | |
| Optional but recommended: | |
| 1. `PASSWORD_RESET_REDIRECT_URL` | |
| 2. `BARRIER_API_TOKEN` or `BARRIER_API_TOKENS` (if device auth is needed) | |
| 3. pricing/capacity config | |
| 4. paymob config if card payments enabled | |
| ## 10.2 Database Migration Baseline | |
| Ensure latest SQL is applied, including: | |
| 1. `supabase/04_auth_profile_vehicle_upgrade.sql` | |
| 2. `supabase/05_multi_vehicle_auth_notifications.sql` | |
| 3. `supabase/06_profile_name_parts_upgrade.sql` | |
| ## 10.3 Smoke Tests | |
| 1. `GET /health` | |
| 2. `GET /supabase/health` | |
| 3. Auth login/register flow | |
| 4. `POST /predict` (entry + exit) | |
| 5. `GET /parking/locations` | |
| 6. `GET /events/inside-cars` | |
| 7. `GET /parking/history` | |
| 8. Gate decision endpoint | |
| 9. Password reset flow (bridge + page + resolver) | |
| ## 10.4 Operational Guardrails | |
| 1. Rotate service secrets and barrier tokens regularly. | |
| 2. Keep `SUPABASE_SERVICE_ROLE_KEY` backend-only. | |
| 3. Monitor `response.supabase.saved` from `/predict` integrations. | |
| 4. Alert on repeated `saved=false` responses and 5xx spikes. | |
| --- | |
| ## 11) Troubleshooting Guide | |
| ### Symptom: feeds/history are empty | |
| Checks: | |
| 1. Confirm requests are authenticated and role scope is correct. | |
| 2. Verify `/predict` responses include `supabase.saved=true`. | |
| 3. Verify vehicle resolution fields (Arabic/English plate matching). | |
| 4. Confirm sessions are being created (`parking_sessions`) and linked to events. | |
| 5. If traffic is mostly unregistered, verify inferred rows are visible (`inferred_unmatched=true`). | |
| ### Symptom: barrier token rejected | |
| Checks: | |
| 1. Token present as Bearer token | |
| 2. `BARRIER_API_TOKEN` or `BARRIER_API_TOKENS` set in deployment env | |
| 3. No hidden whitespace in configured token | |
| ### Symptom: auth user exists but no data persists | |
| Checks: | |
| 1. Confirm `profiles` row exists for that auth user id. | |
| 2. Confirm Supabase service role key is valid and backend can write tables. | |
| 3. Inspect backend logs for persistence exceptions. | |
| --- | |
| ## 12) Notes on Backward Compatibility | |
| 1. Existing Supabase auth clients continue to work unchanged. | |
| 2. Barrier token support is additive. | |
| 3. Feed/history response shape is preserved. | |
| - Added optional inferred markers and source-breakdown fields. | |
| 4. Role checks remain strict for maintenance and payment confirmation endpoints. | |
| --- | |
| ## 13) Recommended Next Improvements | |
| 1. Add structured audit logs for auth path used (`supabase` vs `barrier`). | |
| 2. Add metrics counters for vehicle-match source (`arabic`, `english`, fallback). | |
| 3. Add integration tests for: | |
| - missing-profile auto-provision | |
| - barrier gate decision authorization | |
| - plate matching variants (Arabic-only, English-only, mixed) | |
| 4. Add a migration to introduce an explicit persistent `barrier` app role if database-level modeling is desired. | |