# Product Requirements Document
# SA Driver's Licence Scanner & Decoder

**Version:** 1.0
**Date:** 2026-03-07
**Author:** John (PM Agent)
**Status:** Draft

---

## 1. Executive Summary

A two-component system that allows a user to scan a South African driver's licence PDF417 barcode using an Android device, decode the barcode data into structured personal information and a photo, and display the result on screen.

The system consists of:
1. A **Laravel REST API** that accepts raw barcode binary data, parses the SA DL TLV format, extracts text fields and the compressed photo, calls the existing `decodephoto` binary to decompress the image, corrects its orientation, and returns a JSON response.
2. A **simple Android app** that uses the Manatee Works PDF417 scanner SDK to scan the barcode, posts the data to the API, and displays the decoded result.

---

## 2. Problem Statement

South African driver's licences contain a PDF417 barcode encoding personal information and a biometric photo in a proprietary binary format. Manually extracting and viewing this data is cumbersome and requires command-line tooling. There is no simple, mobile-friendly way to scan a licence and instantly view the decoded information.

The goal is to make this process as simple as: point camera at barcode → view decoded licence data.

---

## 3. Goals & Success Criteria

| Goal | Success Criterion |
|------|------------------|
| Scan SA DL barcode on Android | Manatee SDK successfully reads PDF417 barcode data |
| Decode barcode on API | All text fields parsed correctly from TLV structure |
| Extract and decode photo | `decodephoto` binary called successfully, returns valid image |
| Correct photo orientation | Decoded image is right-side-up (180° rotation applied) |
| Display result | Android app shows photo and all text fields on screen |
| Round-trip latency | Scan → display result in under 3 seconds on a normal connection |

---

## 4. Scope

### In Scope
- Laravel API endpoint to receive and decode SA DL barcode data
- SA DL TLV barcode parser (text fields + photo blob extraction)
- Integration with existing `decodephoto` compiled binary
- 180° image rotation of decoded photo
- Base64 PNG/JPEG photo in JSON response
- Simple Android app with camera scanner (Manatee SDK)
- Android result display screen showing photo and all text fields

### Out of Scope
- User authentication / API security (deferred — testing phase only)
- Storing or logging licence data
- Supporting non-SA driver's licences
- Offline decoding
- iOS app
- Web frontend

---

## 5. Users

**Primary user:** Jack (sole user during development and testing)
**Use case:** Scan a physical SA driver's licence and view the decoded data on an Android device.

---

## 6. System Architecture Overview

```
Android App
  └─ Manatee PDF417 Scanner SDK
       └─ Scans barcode → raw binary data
            └─ Base64 encode
                 └─ POST /api/decode-licence
                          └─ Laravel API
                               ├─ Base64 decode → binary
                               ├─ Parse SA DL TLV format
                               │    ├─ Extract text fields
                               │    └─ Extract compressed photo blob
                               ├─ Write photo blob to temp file
                               ├─ Shell exec: ./decodephoto input.bin output.pgm
                               ├─ Read PGM output
                               ├─ Rotate 180°
                               ├─ Convert to PNG → base64
                               └─ Return JSON response
                                        └─ Android displays result
```

---

## 7. API Specification

### Endpoint

```
POST /api/decode-licence
Content-Type: application/json
```

### Request Body

```json
{
  "barcode": "<base64-encoded raw PDF417 barcode binary data>"
}
```

### Response Body (Success — HTTP 200)

```json
{
  "success": true,
  "data": {
    "surname": "SANDERS",
    "names": "ANDREW",
    "id_number": "7234560001",
    "birth_date": "1972-03-04",
    "gender": "M",
    "licence_number": "086091351390",
    "issue_date": "2023-01-01",
    "expiry_date": "2028-01-01",
    "vehicle_codes": ["B", "C"],
    "pdp": null,
    "photo": "<base64-encoded PNG image>"
  }
}
```

### Response Body (Failure — HTTP 422)

```json
{
  "success": false,
  "error": "Failed to parse barcode data"
}
```

### Notes
- `photo` is a base64-encoded PNG, 200×250 pixels, grayscale, rotated 180° from raw decoder output
- `vehicle_codes` is an array of licence category strings (e.g. `["B"]`, `["B", "C1"]`)
- `pdp` is `null` if no Professional Driving Permit is present, otherwise a string
- `birth_date`, `issue_date`, `expiry_date` are ISO 8601 format (`YYYY-MM-DD`)

---

## 8. SA Driver's Licence Barcode Format

The SA DL PDF417 barcode uses a TLV (Tag-Length-Value) binary structure. Key fields to extract:

| Tag | Field |
|-----|-------|
| Surname | Last name |
| Names | First/given names |
| ID Number | South African ID number |
| Birth Date | Date of birth |
| Gender | M/F |
| Licence Number | Driving licence number |
| Issue Date | Date licence was issued |
| Expiry Date | Licence expiry date |
| Vehicle Codes | Categories of vehicles permitted |
| PDP | Professional Driving Permit (if any) |
| Image Data | Compressed WSQ photo blob |

Reference implementation and format documentation: https://github.com/yushulx/South-Africa-driving-license

---

## 9. Photo Decoding

The compressed photo blob extracted from the barcode is passed to the existing `decodephoto` compiled binary (located at project root):

```bash
./decodephoto input.bin output.pgm
```

- Input: raw WSQ compressed image bytes written to a temp file
- Output: PGM grayscale image (200×250 pixels, P5 format)
- The API reads the PGM output, applies a 180° rotation, converts to PNG, and base64-encodes it
- Temp files must be cleaned up after each request
- The binary must be executable on the server environment (Linux)

---

## 10. Android App Requirements

### Technology
- Language: Kotlin
- Minimum SDK: Android 8.0 (API 26)
- Scanner SDK: Manatee Works PDF417 Barcode Scanner

### Screens

#### Screen 1 — Scanner
- Full-screen camera view
- PDF417 barcode scanner overlay/targeting reticle
- On successful scan: automatically POST to API and navigate to result screen
- Show loading indicator while API call is in progress
- Show error message if scan fails or API returns error

#### Screen 2 — Result
- Display decoded photo (top of screen, centred)
- Display all text fields below the photo in a readable list:
  - Surname
  - Names
  - ID Number
  - Date of Birth
  - Gender
  - Licence Number
  - Issue Date
  - Expiry Date
  - Vehicle Codes
  - PDP (if present)
- "Scan Again" button to return to scanner screen

### API Integration
- Base URL: configurable (hardcoded for initial development is acceptable)
- Send raw barcode bytes as base64 string in JSON POST body
- Handle HTTP errors and display user-friendly messages

---

## 11. Non-Functional Requirements

| Requirement | Detail |
|-------------|--------|
| Performance | API response within 3 seconds end-to-end |
| Temp file cleanup | Always clean up temp files, even on error (use try/finally) |
| Error handling | API returns structured JSON error, never raw PHP exceptions |
| Process isolation | Shell exec to `decodephoto` must not expose command injection vectors — input must be written to file, never interpolated into shell command |
| Server OS | Linux (binary is compiled for Linux) |

---

## 12. Known Issues / Constraints

- The `decodephoto` binary outputs a 180°-rotated image — the API must correct this before returning
- The `decodephoto` binary is a pre-compiled Linux executable — it cannot be recompiled as part of this project
- No auth on the API for initial development — must be added before any shared/production use
- Manatee Works SDK requires a licence key — Jack to supply

---

## 13. Future Considerations (Out of Scope Now)

- API authentication (Bearer token or API key)
- Persistent storage / history of scanned licences
- iOS support
- Web UI
- Support for other barcode types or document formats
