# The collector The collector is how the shop-floor fleet pushes what it knows about itself into ShopDB. It replaced the classic-ASP `api.asp?action=updateCompleteAsset` path. This page is the shape and the guarantees. It is short on purpose: the detail lives in three pages below, and you almost never need more than one of them. ## Which page you want | You are | Open | |---|---| | Rolling reporting out to a fleet, or a bay is returning an error | [COLLECTOR-CLIENT-SETUP](COLLECTOR-CLIENT-SETUP.md) | | Writing or changing a client, or answering "what does this field do" | [COLLECTOR-PAYLOADS](COLLECTOR-PAYLOADS.md) | | Deciding how a PC proves who it is, minting or revoking a credential | [COLLECTOR-AUTH](COLLECTOR-AUTH.md) | | Asking why the contract is shaped this way | [ADR-006](adr/ADR-006-collector-contract.md) | Where all of this sits relative to EventSaver, the backup collectors and the kiosks is [FLEET-ARCHITECTURE](FLEET-ARCHITECTURE.md). ## The shape One dynamic route, `POST /api/collector/`, serves every enabled plugin that returns a collector schema. A plugin declares its identity field and its accepted fields; the dispatcher handles auth, parsing, the audit row and the error envelope, and the plugin handles the upsert. Adding a collector is adding a schema, not adding a route. Two plugins use it on a normal fleet: - `computers` - what this PC is. This is the record everything else hangs off. - `printers` - what print queues this PC actually has. The `endpoints` plugin adds a third, much larger payload for sites running the endpoint agent. ## What it guarantees **Idempotent.** The same report twice changes nothing. A PC is matched by its identity field, so re-imaging a bay updates its record instead of duplicating it, and existing asset relationships survive. **Patch-style, where it says so.** On the computers payload an omitted field leaves the stored value alone, so a report from a bay that could not read its BIOS never blanks a serial number. The printers payload is deliberately the opposite: the reported set REPLACES the host's queues, because "what does this bay have right now" is not a question about history. **Warnings, not failures, for soft problems.** An unmapped pc-type, an unknown OS string or an unknown application name is reported back in `warnings` and the row is still written. The alternative - refusing the report - loses the whole PC over one unrecognised string. **Observed is never assigned.** Nothing a PC reports becomes a statement of what it SHOULD have. A bay that installed the wrong printer cannot make itself right by reporting it; turning observed state into assigned state is always a person's decision. **The report says what the PC is, not where it is on the network.** The bay reports every NIC and takes no view of which matters. Only the server knows the site's addressing, so only the server picks. **Fail-closed on authentication.** A server with no credential configured refuses every request rather than silently accepting unauthenticated data. Credentials go in a header, never a querystring, so they stay out of access logs and proxy history. ## The one thing that changed recently A PC used to authenticate with a key the whole fleet shared. It now authenticates as ITSELF, with a per-PC credential issued by enrollment and revocable one PC at a time. The shared key still works for PCs that have not enrolled, and is refused for any PC that has. If you are adopting this product today, plan on per-PC credentials and treat the shared key as the bootstrap. [COLLECTOR-AUTH](COLLECTOR-AUTH.md) is the whole story.