# How the pieces fit together

ShopDB is a server. Around it are four things that run on shop-floor PCs, each
documented in its own page, and each of those pages assumes you already know how
it relates to the others. This page is that relationship.

## The shape

```
                        +-------------------------------+
                        |   ShopDB (one per site)       |
                        |   Flask API + Vue UI + MySQL  |
                        +-------------------------------+
                          ^      ^        ^         |
              reports     |      |        |         |  serves
              (X-API-Key) |      |        |         v
     +----------------+   |      |        |    +------------------+
     | asset reporter |---+      |        |    | kiosks, displays |
     | on every PC    |          |        |    | (browser, HTTPS) |
     +----------------+          |        |    +------------------+
                                 |        |
     +----------------+          |        |    +------------------+
     | backup         |----------+        +----| EventSaver       |
     | collectors     |  config revisions       | screensaver      |
     +----------------+                         +------------------+
                                                  pulls the slide feed
     +---------------------------+
     | GE-Enforce client         |  pulls its manifest, applies it,
     | scheduled task, SYSTEM    |  reports the cycle back
     +---------------------------+
              ^          |
              |          v
        manifest      the PC's
        (share or     actual state
         HTTPS)
```

Every arrow is one direction on purpose. **Nothing on the server reaches out to
a PC.** The server holds state and answers questions; the fleet asks. That is
what lets a bay behind a firewall, asleep, or on a different network segment be
merely out of date rather than broken - and it is why every one of these tools
degrades to "stale" instead of "failed".

## What each piece is for

| Piece | Direction | What it does | Page |
|---|---|---|---|
| **Asset reporter** | PC to server | Says what this PC is: hostname, serial, type, user, IPs, machine number. Creates the PC record the rest of the system hangs off. | [ADOPTING-AT-ANOTHER-SITE](ADOPTING-AT-ANOTHER-SITE.md) |
| **GE-Enforce client** | both | Pulls the manifest for this PC's type, makes the PC match it, reports what it installed, skipped or failed. | [GE-ENFORCE](GE-ENFORCE.md) |
| **Backup collectors** | PC to server | Post machine configuration (NTLARS/DNC, CMM, part marker, UDC) as revisions, so a controller can be restored and a change can be seen. | [BACKUP-RESTORE](BACKUP-RESTORE.md) |
| **EventSaver** | PC to server | Pulls the slide playlist and shows it when a bay is idle. | [EVENTSAVER](EVENTSAVER.md) |
| **Kiosks and displays** | PC to server | A browser in kiosk mode on a ShopDB route. No client software beyond the browser. | [GE-ENFORCE-DISPLAY](GE-ENFORCE-DISPLAY.md) |

## The three ways a PC talks to the server

**The collector API**, `POST /api/collector/*`, with `X-API-Key`. Used by the
asset reporter and the backup collectors. The key is a managed token scoped to
`collector.ingest` and nothing else, so one recovered off a bay cannot read the
asset register. Idempotent by design: the same report twice changes nothing.
See [COLLECTOR-INTEGRATION](COLLECTOR-INTEGRATION.md) and ADR-006.

**The GE-Enforce API**, `/api/geenforce/*`, with a token scoped to the fetch
scope. Manifests out, cycle reports back. Most PC types still take their
manifest from the SMB share and use this only to report; the display cohort
takes everything over HTTPS, because those PCs have no share.

**Plain public reads.** The slide feed and the kiosk dashboard routes need no
credentials at all, because a screensaver and a wall display have nowhere to
keep one. They are read-only and carry nothing a floor visitor should not see.

## Where the credentials live

Three documents each named a different place, which is what happens when a
credential is described from whichever end the author was working on. Both ends
are here.

| Credential | On the server | On the PC | Rotate by |
|---|---|---|---|
| Collector key | A managed token scoped to `collector.ingest` only. `COLLECTOR_API_KEY` in `.env` also works and is simpler for a pilot, but cannot be revoked per fleet. | `HKLM:\SOFTWARE\GE\ShopDB` value `CollectorKey` | Replacing the token file the fleet reads from, so every PC picks it up on its next cycle. Never put it in the manifest - manifests sync broadly. |
| GE-Enforce fetch token | A managed service token scoped to the GE-Enforce fetch scope | `HKLM:\SOFTWARE\GE\ShopDB` value `ApiToken` | Same path as the collector key |
| Server URL | n/a | `HKLM:\SOFTWARE\GE\ShopDB` value `BaseUrl` | Setting it once at install; nothing should overwrite a bay's own value |
| Application secrets | `.env`: `SECRET_KEY`, `JWT_SECRET_KEY`, `DATABASE_URL`, integration tokens | n/a | See [BACKUP-RESTORE](BACKUP-RESTORE.md) - losing these invalidates every issued token |

Two rules behind that table. A shop-floor PC is not a trusted place, so what it
holds is scoped to exactly what it does: a collector key that leaks buys the
reader the ability to file a PC report, not to read the asset register. And a
credential is delivered, never typed - a value that has to be entered per machine
is a value that is wrong on some machine.

## What owns what

The question that decides most arguments: **who is allowed to change this?**

- **ShopDB owns the record.** What a PC is, what it drives, what it should have.
- **The manifest owns the PC's configuration.** If GE-Enforce enforces a value,
  editing it on the PC is temporary - the next cycle puts it back. That is the
  feature, and it is the single most common surprise.
- **The PC owns its own identity.** Serial, hostname, installed software: the
  server records what it is told rather than deciding.

Where two systems both converge state - GE-Enforce and Intune DSC, say - decide
which owns which layer before deploying both, or they will fight in a way that
is very hard to see. [ADOPTING-AT-ANOTHER-SITE](ADOPTING-AT-ANOTHER-SITE.md) has
the recommended split.

## When something looks wrong

| Symptom | The piece to look at first |
|---|---|
| A PC is missing from ShopDB entirely | Asset reporter: never ran, or no collector key |
| A PC is there but its details are old | Asset reporter: stopped running. The dashboard's "PCs not reporting" card is this |
| A PC has the wrong software | GE-Enforce: check its last cycle report, then its manifest scope |
| A bay shows the wrong thing on screen | EventSaver config, or the kiosk dispatcher - both are per PC type |
| A machine has no recent config backup | Backup collector on the controlling PC. "Backups that have stopped" on the dashboard |
| Two PCs claim one machine number | Neither: it is a claim in progress, or a typo. The dashboard card names both |

Each row is a different program on a different schedule. Knowing which one to
open is most of the diagnosis.
