# Komodo resources — parking appliance fleet (control plane as code) # # Synced into Komodo Core via a ResourceSync pointing at this file. Drives the SAME # compose files the booth runs locally (docker-compose.yml + docker-compose.prod.yml); # Komodo Periphery on each booth executes them. See: # wiki/decisions/fleet-deployment-komodo.md (rationale + threat model) # wiki/decisions/container-deployment.md (image build/tag/registry — unchanged) # # This file mirrors the WORKING park-buzi Stack (built by hand in the Core UI, then # exported to TOML). Field names match the running Komodo version (v2.2). # # NO [[server]] block: servers are created by the AGENT onboarding outbound (a one-time # onboarding key → Periphery self-registers with auto-rotating key pairs). The sync owns # only the Stack; it references the server by the name it onboarded as (`connect_as`). # # Secrets ([[park_buzi_jwt_secret]] etc.) are REFERENCES to Komodo Core's secret store — # per-booth + unique, never inlined here (this file is in git). JWT_SECRET gates login; # EVENT_SIGNING_KEY signs the append-only anti-fraud ledger; BACKUP_KEY encrypts on-site DB # backups (separate from the signing key; escrow it offsite — recovery needs both). # # Deploys are MANUAL + PINNED: park-buzi is the STAGING booth (real-world test of the app), # so it tracks the `stage` branch + the `:stage` image, but is still deployed by hand with a # PINNED immutable TAG=stage- (no webhook). Promotion: merge dev → stage when confident, # CI builds :stage / :stage-, then bump TAG below to that sha and deploy from Komodo Core. # A PRODUCTION booth tracks `main` + manual+pinned `:main-`. See # wiki/decisions/fleet-deployment-komodo.md (dev → stage → main tiers). ############################################################################## # Stack — the deployable unit for booth "park-buzi". One Stack per booth; add a # new [[stack]] block per site (unique name, its own per-booth secret refs). ############################################################################## [[stack]] name = "park-buzi" [stack.config] server = "park-buzi" git_provider = "git.infra.msai.al" git_account = "komodo" repo = "mca/parking_solution" branch = "stage" file_paths = [ "docker-compose.yml", "docker-compose.prod.yml" ] registry_provider = "git.infra.msai.al" registry_account = "komodo" environment = """ REGISTRY=git.infra.msai.al/mca/parking_solution # Staging booth: pinned immutable stage-. After each promotion (merge dev → stage, CI builds # :stage-), bump this to the new sha and re-sync/deploy from Core. The moving `:stage` tag # exists as the pointer; we deploy the sha, not the mover. TAG=stage-4a02e5f COOKIE_SECURE=0 # Venue modules this site is ENTITLED to (vendor decision; the site admin activates within # this set in Setup → Site). Unset = every registered module. See wiki/decisions/venue-modules.md. MODULES_ENTITLED=parking,validation VISION_ENABLED=1 # Desktop app WS handshake: Origin is tauri://localhost (set explicitly by # platform-ws.ts, since the native WS plugin has no page context to auto-attach # one). Linux may also send http://tauri.localhost. See routes/ws.ts anti-CSWSH check. WS_ALLOWED_ORIGINS=tauri://localhost,http://tauri.localhost JWT_SECRET=[[park_buzi_jwt_secret]] EVENT_SIGNING_KEY=[[park_buzi_event_signing_key]] BACKUP_KEY=[[park_buzi_backup_key]] """ ############################################################################## [[stack]] name = "park-2" [stack.config] server = "park-2" git_provider = "git.infra.msai.al" git_account = "komodo" repo = "mca/parking_solution" branch = "stage" file_paths = [ "docker-compose.yml", "docker-compose.prod.yml" ] registry_provider = "git.infra.msai.al" registry_account = "komodo" environment = """ REGISTRY=git.infra.msai.al/mca/parking_solution # Staging booth: pinned immutable stage-. After each promotion (merge dev → stage, CI builds # :stage-), bump this to the new sha and re-sync/deploy from Core. The moving `:stage` tag # exists as the pointer; we deploy the sha, not the mover. TAG=stage-4a02e5f COOKIE_SECURE=0 # Venue modules this site is ENTITLED to (vendor decision; the site admin activates within # this set in Setup → Site). Unset = every registered module. See wiki/decisions/venue-modules.md. # park-2 pilots the Car Wash module (2026-09-05). MODULES_ENTITLED=parking,carwash # Car Wash review outbox (wiki/concepts/vision-review-outbox.md): the collector's ingest URL # on the Netbird overlay, this booth's pseudonymous id, and its token — the SAME secret the # wash-collector stack lists under that id. Leave all three unset to keep the outbox off. CARWASH_REVIEW_URL=http://docker-station.nb.infra:8090/ingest CARWASH_REVIEW_BOOTH_ID=booth-2 CARWASH_REVIEW_TOKEN=[[wash_review_token_booth_2]] # Also send ENTRY reads as training material (gate view, no wash): 1 = every entry (storage # and bandwidth are not the limit; review what you have time for). N = one in N. 0 = off. CARWASH_REVIEW_ENTRY_SAMPLE=1 VISION_ENABLED=1 # Desktop app WS handshake: Origin is tauri://localhost (set explicitly by # platform-ws.ts, since the native WS plugin has no page context to auto-attach # one). Linux may also send http://tauri.localhost. See routes/ws.ts anti-CSWSH check. WS_ALLOWED_ORIGINS=tauri://localhost,http://tauri.localhost JWT_SECRET=[[park_2_jwt_secret]] EVENT_SIGNING_KEY=[[park_2_event_signing_key]] BACKUP_KEY=[[park_2_backup_key]] """ ############################################################################## # Stack — the LAB BENCH (not a booth): a spare Linux box with the field printer and # whatever device is under investigation, so a booth bug can be reproduced on the booth's # exact image before touching a real site. Same compose files + pinned TAG as the staging # booths. No review outbox (the lab is not a site — it must never feed the training pool # under a booth's identity). Its own secrets. See wiki/decisions/fleet-deployment-komodo.md. ############################################################################## [[stack]] name = "park-lab" [stack.config] server = "park-lab" git_provider = "git.infra.msai.al" git_account = "komodo" repo = "mca/parking_solution" branch = "stage" file_paths = [ "docker-compose.yml", "docker-compose.prod.yml" ] registry_provider = "git.infra.msai.al" registry_account = "komodo" environment = """ REGISTRY=git.infra.msai.al/mca/parking_solution # Lab: pinned to the SAME stage- as the booth whose bug is being reproduced (bump # alongside it). A lab may float, but a reproduction must run the booth's exact image. TAG=stage-4a02e5f COOKIE_SECURE=0 # Entitled to Car Wash too, so the wash-desk printer role and till can be exercised on the bench. MODULES_ENTITLED=parking,carwash # NO review outbox on the lab (CARWASH_REVIEW_URL/BOOTH_ID/TOKEN deliberately unset): the # collector's training pool is per-booth, and the bench is not a booth. VISION_ENABLED=1 # Desktop app WS handshake: Origin is tauri://localhost (set explicitly by # platform-ws.ts, since the native WS plugin has no page context to auto-attach # one). Linux may also send http://tauri.localhost. See routes/ws.ts anti-CSWSH check. WS_ALLOWED_ORIGINS=tauri://localhost,http://tauri.localhost JWT_SECRET=[[park_lab_jwt_secret]] EVENT_SIGNING_KEY=[[park_lab_event_signing_key]] BACKUP_KEY=[[park_lab_backup_key]] """ ############################################################################## # Stack — the Car Wash REVIEW COLLECTOR on the reviewer's host (art-docker-station), # NOT a booth. Same repo/branch/TAG promotion as the booths, but its file_paths name # ONLY docker-compose.collector.yml, so nothing booth-side lands here and nothing here # lands on a booth. Booths reach it over the Netbird overlay only (bind to the overlay # address). Its own secrets. See wiki/concepts/vision-review-outbox.md. ############################################################################## [[stack]] name = "wash-collector" [stack.config] server = "art-docker-station" git_provider = "git.infra.msai.al" git_account = "komodo" repo = "mca/parking_solution" branch = "stage" file_paths = [ "docker-compose.collector.yml" ] registry_provider = "git.infra.msai.al" registry_account = "komodo" environment = """ REGISTRY=git.infra.msai.al/mca/parking_solution # Pinned like the booths: bump to the stage- that carries the collector. TAG=stage-2d9bb15 # The host's NETBIRD address (an IP: Docker port bindings take no hostname) — the ingest port # is published on the overlay only. Booths reach it by its Netbird DNS name. COLLECTOR_BIND=100.75.184.156 # ":" pairs, one per booth. ONE secret per booth, referenced here AND in # that booth's own stack as its CARWASH_REVIEW_TOKEN — one value, two consumers, nothing # to keep in sync, and rotating a booth touches one secret. The booth id is the booth's # pseudonymous CARWASH_REVIEW_BOOTH_ID, never a site name. Add a pair per booth. COLLECTOR_BOOTH_TOKENS=booth-2:[[wash_review_token_booth_2]] # Phase-B trainer (the `trainer` service beside the collector; the Training section of /review # is its UI). Only `publish` needs this: a Gitea token with package:write for the model's generic # package. Uncomment when the first model is to be published. #TRAINER_PUBLISH_TOKEN=[[gitea_package_write_token]] COLLECTOR_REVIEWER_USER=reviewer COLLECTOR_REVIEWER_PASS=[[wash_collector_reviewer_pass]] """