Files
parking_solution/docker-compose.collector.yml
T
julian b485e9870b
CI / check (push) Failing after 40s
Build & push images / images (push) Failing after 32s
Build desktop / desktop (push) Successful in 5m24s
feat(collector): review collector skeleton — apps/collector, its own Komodo stack on the reviewer's host
The far end of the Car Wash review outbox (wiki/concepts/vision-review-outbox.md): a small
Fastify + SQLite service in the monorepo (shares the payload contract and the class
vocabulary via @parking/shared), delivered to art-docker-station by its own stack so
nothing booth-side lands there and nothing of it on a booth.

- POST /ingest: bearer token per booth (constant-time), X-Booth-Id must match, multipart
  meta + JPEG (magic checked, 2 MB cap), meta validated against the contract, idempotent on
  the item id; crop stored at crops/<booth>/<item>.jpg on the volume + one items row.
- /review + /api/*: the reviewer's screen served by the process (Basic auth, one login):
  one pending crop at a time, operator's pick and camera's pick beside it, one button/key
  per vocabulary class + unusable + skip; stats per booth and per hashed operator
  (agree / disagree / unusable — disagree = the reviewer's class is outside the operator's
  category).
- GET /export/labels.csv: reviewed usable rows for training; formula-leading cells are
  neutralised (booth-supplied names). Crops stay on the volume for the trainer on the host.
- Booth payload now carries operatorCategory.classes so the comparison needs no site setup.
- Delivery: apps/collector/Dockerfile (monorepo context), docker-compose.collector.yml
  (bind to the overlay IP; commented `trainer` profile seam for the GPU), a third build
  step in build-images.yml, a `wash-collector` stack in komodo/resources.toml with one
  secret per booth referenced from both the collector's token list and the booth's own
  stack (park-2 lines templated, commented, DNS name for the URL).
- Tests: app.test.ts (ingest ok/dup/refusals, review + stats + export, config). Image
  built and smoke-tested locally (health, ingest, duplicate, auth, verdict, export).

Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
2026-09-07 08:26:22 +02:00

48 lines
2.2 KiB
YAML

# The Car Wash REVIEW COLLECTOR — deployed on the REVIEWER's host (art-docker-station), NOT
# on a booth. Its own Komodo stack ("wash-collector" in komodo/resources.toml) points at this
# file alone, so nothing here reaches a booth and nothing of the booth stack reaches this
# host. See wiki/concepts/vision-review-outbox.md.
#
# Reachability: booths POST to /ingest over the Netbird overlay only. Bind the published
# port to the host's OVERLAY address (COLLECTOR_BIND), never 0.0.0.0 on a host that also
# has a public interface. The Netbird policy should allow booths → this host:8090 and
# nothing else on it.
services:
collector:
image: ${REGISTRY:-git.infra.msai.al/mca/parking_solution}/parking-collector:${TAG:-dev}
restart: unless-stopped
ports:
- "${COLLECTOR_BIND:-127.0.0.1}:8090:8090"
environment:
# "<boothId>:<token>" pairs — one per booth, the booth's CARWASH_REVIEW_TOKEN under its
# pseudonymous CARWASH_REVIEW_BOOTH_ID. A Komodo secret reference in the stack env.
COLLECTOR_BOOTH_TOKENS: ${COLLECTOR_BOOTH_TOKENS:?set COLLECTOR_BOOTH_TOKENS in the stack env}
# The single reviewer login (HTTP Basic over the overlay).
COLLECTOR_REVIEWER_USER: ${COLLECTOR_REVIEWER_USER:-reviewer}
COLLECTOR_REVIEWER_PASS: ${COLLECTOR_REVIEWER_PASS:?set COLLECTOR_REVIEWER_PASS in the stack env}
LOG_LEVEL: ${LOG_LEVEL:-info}
volumes:
- collector-data:/data
# Phase B trainer — a one-off job on this host's GPU, NOT a service (profile "train": it
# only runs when asked: `docker compose --profile train run --rm trainer`). Reads the
# collector's export + crops straight off the same volume; writes the ONNX classifier the
# vision image then bakes in. The image/script are the next increment; this is the seam.
# trainer:
# image: ${REGISTRY:-git.infra.msai.al/mca/parking_solution}/parking-trainer:${TAG:-dev}
# profiles: ["train"]
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all
# capabilities: [gpu]
# volumes:
# - collector-data:/data:ro
# - ./models:/out
volumes:
collector-data: