docs(wiki): collector live on park-2; secrets shape, DNS vs bind, token format, every-entry sampling, CI extra rule

Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
This commit is contained in:
2026-09-07 10:01:39 +02:00
parent 1a0fe59488
commit f9cb973fe9
3 changed files with 46 additions and 2 deletions
+31 -2
View File
@@ -45,7 +45,12 @@ The wash stream is small; the **entry camera photographs every car**, in exactly
classifier is trained on, with zero domain shift. So the booth can also queue **one in N entry
vehicle reads** as pure training material: the crop and the camera's class, *no* order, *no*
operator, *no* category — same crop-and-blur pipeline, same one-way path, same privacy
properties. `CARWASH_REVIEW_ENTRY_SAMPLE=N` (0/unset = off; needs the three upload settings).
properties. `CARWASH_REVIEW_ENTRY_SAMPLE=N` = one in N entries; **`1` = every entry, and that is
the setting park-2 runs** (user, 2026-09-07: 4 TB on the collector host, bandwidth not an issue —
the only limit was ever the reviewer's time; the reviewer labels what they have time for, the
rest waits and stays useful once a first model exists, as the unlabelled pile it is measured on).
0/unset = off; needs the three upload settings. A washed car arrives twice, as an entry sample
and as the wash decision — intended, the `kind` keeps them apart.
Seam: the core announces every vehicle read (`deviceEvents.emitVehicleRead`, snapshot.ts, entry
and exit) and the Car Wash module decides — it samples entry reads in-process (`sampleEntry()`,
exactly one in N) and calls `enqueueEntry()`; the core never imports the module. Packages carry
@@ -78,6 +83,24 @@ Setup → Car wash show queued / delivered / abandoned + the last error.
is off and **nothing is queued** (an unbounded queue nobody drains is worse than none). Set per
booth in the Komodo stack env; compose forwards them.
- **URL by Netbird DNS name** (`http://docker-station.nb.infra:8090/ingest`): the server container
runs on the host network in prod, so it uses the booth's resolver and Netbird's DNS answers
`*.nb.infra`; a collector that moves address costs no booth change. A failed lookup behaves like
a collector outage (defer, backoff). The collector's own `COLLECTOR_BIND` must be the raw overlay
**IP** — Docker port bindings take no hostname.
- **Secrets: one per booth, two consumers.** `wash_review_token_booth_2` is referenced by the
booth's stack as its `CARWASH_REVIEW_TOKEN` *and* by the collector's stack inside
`COLLECTOR_BOOTH_TOKENS=booth-2:[[wash_review_token_booth_2]],booth-3:[[…]]` — one value, nothing
to keep in sync, rotating a booth touches one secret. (A first cut had one combined secret for
the whole list; replaced the same day — rotation was all-or-nothing and the value lived twice.)
Token format: opaque, `openssl rand -hex 32`; the collector only demands ≥ 16 chars and the list
splits on commas/whitespace, which hex never contains. Never share a token between booths — it
is what names the booth. Total Komodo secrets for one booth + the collector: two (the booth's
token, the reviewer's password).
- **The operator hash needs no variable**: `sha256(boothId + ":" + username)[:16]`, computed on
the booth from values already set; the owner recomputes it from the booth's usernames to map a
hash back, the collector never can.
## The collector — skeleton built 2026-09-06 (`apps/collector`)
A deliberately small Fastify + SQLite service **in this monorepo** (so it imports the payload
@@ -114,4 +137,10 @@ Three surfaces, nothing else — it must not grow into a fleet console:
never `0.0.0.0` on a host with a public interface; Netbird policy: booths → this host:8090 and
nothing else. The host must be onboarded as a Komodo server like the booths. `TAG` is pinned
and promoted with the booths (one sha for all stacks) — fine while the collector stays small;
its own repo the day it needs its own cadence.
its own repo the day it needs its own cadence. Deploy the collector BEFORE a booth that sends a
package kind it does not know (a 422 is abandoned, not retried). The export neutralises cells
that start like a spreadsheet formula (category/service names are booth-supplied text).
**Status (2026-09-07).** Live: the collector runs on `art-docker-station` and park-2 is wired to
it (`stage-dbbb051` on both stacks, every entry sampled). The review screen at
`http://docker-station.nb.infra:8090/review` is filling; no labels reviewed yet.