# USB plugin - CMMC USB check-in/out database contract

The USB plugin tracks removable-media check-in/out for CMMC compliance. Device
and log state live in a **separate, read-write** MySQL database (`cmmc_usb`),
reached with parameterized pymysql via `cmmc_usb_connection()`. Names of people
are resolved from the HR employee directory (see the employees plugin).

The plugin's own reference tables (`usbdevicetypes`, `usbdevices`,
`usbcheckouts`) live in the main app database; only the live check-in/out data
is in `cmmc_usb`.

> **The schema is standardized across sites** - the `cmmc_usb` check-in/out
> solution is the same deployment everywhere, so the tables below match as-is
> and no schema adaptation is needed. The **database name may differ per site**,
> though - set `cmmc_usb_db_name` (default `cmmc_usb`) to match the local name.
> The view recipe at the end is only a fallback for a site that somehow differs.
> (Contrast the employee directory, which genuinely varies per site.)

## Connection

Credentials resolve **settings-first, then environment**, except the password
which is env-only (never stored in the app database).

| Field    | Setting key (editable in the setup wizard) | Env var (fallback)      |
| -------- | ------------------------------------------ | ----------------------- |
| Host     | `cmmc_usb_db_host`                          | `CMMC_USB_DB_HOST`      |
| Database | `cmmc_usb_db_name`                          | `CMMC_USB_DB_NAME`      |
| User     | `cmmc_usb_db_user`                          | `CMMC_USB_DB_USER`      |
| Password | (not stored)                                | `CMMC_USB_DB_PASSWORD`  |

Set the password in `.env`; the setup wizard's Features step shows the exact
line to paste. This database is **read-write** - the app account needs
`SELECT, INSERT, UPDATE`. Engine is MySQL/MariaDB (pymysql).

## Required schema

The plugin runs raw SQL against these tables (or **views** - see below).

### `devices`
| Column            | Type    | Notes                                  |
| ----------------- | ------- | -------------------------------------- |
| `device_id`       | VARCHAR | Primary key; the device serial/tag     |
| `device_desc`     | VARCHAR | Description                            |
| `device_owner`    | VARCHAR | Owner                                 |
| `status`          | VARCHAR | Check-in/out state                    |
| `locker_location` | VARCHAR | Where the device is stored            |

Operations: `SELECT` (list + by id), `INSERT` (register device), `UPDATE`
(edit fields, change status).

### `checkinoutlog`
| Column            | Type      | Notes                              |
| ----------------- | --------- | ---------------------------------- |
| `log_id`          | INT (PK)  | Auto id                            |
| `badge_number`    | VARCHAR   | Person's badge                     |
| `device_id`       | VARCHAR   | FK to `devices.device_id`          |
| `action`          | VARCHAR   | check-in / check-out               |
| `timestamp`       | DATETIME  | When it happened                   |
| `scanned_viruses` | (text/int)| Scan result                        |
| `locker_location` | VARCHAR   | Locker at time of event            |
| `sanitized`       | (bool/int)| Sanitization flag                  |

Operations: `SELECT` (history per device), `INSERT` (log an event).

### `users`
| Column         | Type    | Notes                                 |
| -------------- | ------- | ------------------------------------- |
| `badge_number` | VARCHAR | Primary key; the scanned badge        |
| `first_name`   | VARCHAR | Given name                            |
| `last_name`    | VARCHAR | Surname                               |

Operations: `SELECT` by badge, `INSERT` (auto-add a badge on first scan).

## Employee directory dependency

To turn a scanned badge into a name, the plugin also reads the HR `employees`
directory (via the employees plugin's connection). A badge shaped `0<digits>BZ`
carries a PayNo (the digits); lookups try `employees.SSO` and `employees.PayNo`.
See `plugins/employees/README.md` for that schema and connection.

## Adapting a different site schema (recommended: views)

Sites whose USB-tracking database uses different table/column names should
create read-only/updatable **views** named `devices`, `checkinoutlog`, and
`users` that map local columns to the names above. Example:

```sql
CREATE VIEW devices AS
SELECT
  asset_tag     AS device_id,
  description   AS device_desc,
  owner         AS device_owner,
  state         AS status,
  storage_bay   AS locker_location
FROM usb_assets;
```

Because the plugin writes to `devices`/`checkinoutlog`/`users`, either make the
views updatable (single-table views usually are) or expose real tables with
these column names. Grant the app account `SELECT, INSERT, UPDATE`.

Notes:
- `device_id` and `badge_number` are the natural keys the plugin matches on.
- If `cmmc_usb` is unreachable, USB endpoints return an error and the rest of
  the app keeps working (the feature degrades, it does not crash the app).
