# lostmind84/openscale architecture

> Architecture diagram of the GitHub repository lostmind84/openscale, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-07-31). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/lostmind84/openscale
- Repository: https://github.com/lostmind84/openscale

## Overview

#### Purpose and Entry Points
OpenScale is a self-service grocery weighing station: select a product on a touchscreen, acquire weight, price it, generate EAN-13, and print a label. It is a standalone Go binary with embedded client and administration UIs. CLI composition and operational commands live in `cmd/openscale/main.go`, `cmd/openscale/serve.go`, and `cmd/openscale/service.go`; `serve` hosts the station and HTTP UI/API.

#### Composition Root and Runtime Boundary
The CLI loads configuration, data directories, drivers, persistence, station workers, and web server. Configuration and platform-specific paths/services are separated from business logic in `cmd/openscale/config.go`, `internal/platform/paths.go`, and `internal/platform/service.go`. The production runtime is Go without cgo, cross-compiled for Windows, Linux, and Linux ARM64; Node/Svelte is build-time only.

#### Domain and Station Orchestration
`internal/domain/` contains stable business types and rules: products, measurements, tare/safeguards, pricing, barcode generation, label templates, and configuration contracts (`internal/domain/product.go`, `internal/domain/pricing.go`, `internal/domain/prepare.go`). `internal/station/` is the application core: it coordinates catalog snapshots, weight events, manual entry, print requests, idempotency, failure handling, and background workers (`internal/station/station.go`, `internal/station/hub.go`, `internal/station/workers.go`). This is the principal boundary between HTTP/hardware adapters and domain decisions.

#### Weigh-to-Label Flow
A client UI/API request identifies a product; station logic obtains a stable scale measurement or permitted manual weight, applies tare and safeguards, computes price, creates the EAN-13/label payload, records the result, and dispatches printing. HTTP endpoints and streaming state are in `internal/web/server.go`, `internal/web/command.go`, and `internal/web/stream.go`. Scale adapters are registered behind a driver interface, with serial and replay implementations in `internal/scale/registry.go`, `internal/scale/serial/scale.go`, and `internal/scale/gramxfoc/gramxfoc.go`. This allows real GRAM serial hardware, absent/replay modes, and isolated new driver additions.

#### Printing Pipeline
The printing subsystem transforms domain label data into layout/render output and delivers bytes through configured transports. Core service/driver selection is in `internal/printing/service.go` and `internal/printing/registry.go`; SATO-oriented SBPL encoding is in `internal/printing/sbpl/sbpl.go`; physical delivery supports TCP, files, device files, and Windows spooler via `internal/printing/transport/transport.go` and `internal/printing/transport/winspool_windows.go`. PDF and raster paths support preview/diagnostics independently of hardware.

#### Catalog and Local Persistence
Each station owns its SQLite-backed operational state, catalog, journals, imports, quarantine, and technical metadata. Storage and migrations are in `internal/store/store.go`, `internal/store/migrations/0001_initial.sql`, and `internal/store/catalog.go`. Catalog ingestion is staged: source discovery/fetch, parsing, assembly/qualification, findings/quarantine, then atomic catalog availability (`internal/catalog/importer/importer.go`, `internal/catalog/assemble.go`, `internal/catalog/quarantine.go`). Supported sources include Odoo CSV, local drop folders with deletion-as-acknowledgment, and WebDAV (`internal/catalog/csvodoo/csvodoo.go`, `internal/catalog/localdrop/localdrop.go`, `internal/catalog/webdav/webdav.go`).

#### Web Interfaces and Operations
Embedded static client/admin assets are served by `internal/web/embed.go`; source Svelte applications are in `web/src/main.ts` and `web/src/admin/mount.ts`. The client consumes catalog and station state; the admin surface controls configuration, catalog, hardware, journal, diagnostics, and updates through server handlers such as `internal/web/admin.go` and `internal/web/update.go`. Diagnostics gather machine, hardware, service, and redacted support reports (`internal/diag/doctor.go`, `internal/diag/report.go`). Update logic discovers GitHub releases, stages verified artifacts, and coordinates safe application (`internal/update/github.go`, `internal/update/stager.go`, `internal/update/service.go`).

#### Deployment and External Dependencies
There is no central backend: weighing works offline once installed. External interactions are local serial ports, network/device/spool printing, optional WebDAV catalog access, and GitHub Releases for updates. Windows installation creates a dedicated account, service, scheduled kiosk task, and hardening through `deploy/windows/install.ps1` and `deploy/windows/openscale-kiosk.xml`; Debian uses systemd units and bootstrap scripts in `deploy/linux/bootstrap.sh` and `deploy/linux/openscale.service`. Kiosk supervision and recovery are isolated in `internal/kiosk/supervisor.go` and `internal/kiosk/rescue.go`.

Main entry points: [`internal/web/server.go`](https://github.com/lostmind84/openscale/blob/main/internal/web/server.go) (HTTP server & commands), [`internal/station/station.go`](https://github.com/lostmind84/openscale/blob/main/internal/station/station.go) (Station orchestration), [`cmd/openscale/serve.go`](https://github.com/lostmind84/openscale/blob/main/cmd/openscale/serve.go) (Serve command), [`cmd/openscale/main.go`](https://github.com/lostmind84/openscale/blob/main/cmd/openscale/main.go) (CLI composition)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Station Runtime"]
  node_cli["CLI composition<br/>Go command<br/>[main.go]"]
  node_serve["Serve command<br/>runtime entry<br/>[serve.go]"]
  node_config_platform["Config &amp; platform<br/>runtime setup<br/>[config.go]"]
  node_web_server["HTTP server &amp; commands<br/>web adapter<br/>[server.go]"]
  node_embedded_ui["Embedded client/admin UI<br/>embedded assets<br/>[embed.go]"]
  node_station{{"Station orchestration<br/>application core<br/>[station.go]"}}
  node_domain{{"Domain rules<br/>business domain<br/>[prepare.go]"}}
end

subgraph group_adapters["Hardware &amp; Output"]
  node_scale_registry["Scale driver registry<br/>hardware adapter<br/>[registry.go]"]
  node_gram_scale["GRAM serial scale<br/>scale driver<br/>[gramxfoc.go]"]
  node_printing["Printing service<br/>output service<br/>[service.go]"]
  node_sbpl["SBPL renderer<br/>label encoder<br/>[sbpl.go]"]
  node_transports["Print transports<br/>device transport<br/>[transport.go]"]
end

subgraph group_catalog["Catalog &amp; Storage"]
  node_sqlite_store[("SQLite operational store<br/>local persistence<br/>[store.go]")]
  node_catalog_importer["Catalog import pipeline<br/>ingestion workflow<br/>[importer.go]"]
  node_catalog_sources["Catalog sources<br/>source adapters<br/>[csvodoo.go]"]
end

subgraph group_operations["Operations"]
  node_diagnostics["Diagnostics &amp; reports<br/>operations service<br/>[doctor.go]"]
  node_updates["Safe updater<br/>update service<br/>[service.go]"]
  node_kiosk["Kiosk supervision<br/>recovery service<br/>[supervisor.go]"]
  node_deployment["OS deployment services<br/>deployment scripts<br/>[install.ps1]"]
end

node_external_devices(("Scale, printer &amp; network<br/>external systems"))

node_cli -->|"runs"| node_serve
node_cli -->|"initializes"| node_config_platform
node_serve -->|"hosts"| node_web_server
node_serve -->|"starts"| node_station
node_web_server -->|"serves"| node_embedded_ui
node_embedded_ui -->|"commands and state"| node_web_server
node_web_server -->|"weigh and admin commands"| node_station
node_station -->|"applies rules"| node_domain
node_station -->|"reads measurements"| node_scale_registry
node_station -->|"dispatches labels"| node_printing
node_station -->|"reads catalog and records results"| node_sqlite_store
node_scale_registry -->|"selects driver"| node_gram_scale
node_gram_scale -->|"serial I/O"| node_external_devices
node_printing -->|"renders labels"| node_sbpl
node_sbpl -->|"print bytes"| node_transports
node_transports -->|"delivers output"| node_external_devices
node_catalog_sources -->|"catalog input"| node_catalog_importer
node_catalog_importer -->|"publishes catalog and findings"| node_sqlite_store
node_catalog_sources -.->|"WebDAV access"| node_external_devices
node_web_server -->|"admin diagnostics"| node_diagnostics
node_web_server -->|"admin updates"| node_updates
node_updates -.->|"GitHub releases"| node_external_devices
node_deployment -->|"installs and supervises"| node_kiosk
node_deployment -->|"runs as service"| node_serve

click node_cli "https://github.com/lostmind84/openscale/blob/main/cmd/openscale/main.go"
click node_serve "https://github.com/lostmind84/openscale/blob/main/cmd/openscale/serve.go"
click node_config_platform "https://github.com/lostmind84/openscale/blob/main/cmd/openscale/config.go"
click node_web_server "https://github.com/lostmind84/openscale/blob/main/internal/web/server.go"
click node_embedded_ui "https://github.com/lostmind84/openscale/blob/main/internal/web/embed.go"
click node_station "https://github.com/lostmind84/openscale/blob/main/internal/station/station.go"
click node_domain "https://github.com/lostmind84/openscale/blob/main/internal/domain/prepare.go"
click node_scale_registry "https://github.com/lostmind84/openscale/blob/main/internal/scale/registry.go"
click node_gram_scale "https://github.com/lostmind84/openscale/blob/main/internal/scale/gramxfoc/gramxfoc.go"
click node_printing "https://github.com/lostmind84/openscale/blob/main/internal/printing/service.go"
click node_sbpl "https://github.com/lostmind84/openscale/blob/main/internal/printing/sbpl/sbpl.go"
click node_transports "https://github.com/lostmind84/openscale/blob/main/internal/printing/transport/transport.go"
click node_sqlite_store "https://github.com/lostmind84/openscale/blob/main/internal/store/store.go"
click node_catalog_importer "https://github.com/lostmind84/openscale/blob/main/internal/catalog/importer/importer.go"
click node_catalog_sources "https://github.com/lostmind84/openscale/blob/main/internal/catalog/csvodoo/csvodoo.go"
click node_diagnostics "https://github.com/lostmind84/openscale/blob/main/internal/diag/doctor.go"
click node_updates "https://github.com/lostmind84/openscale/blob/main/internal/update/service.go"
click node_kiosk "https://github.com/lostmind84/openscale/blob/main/internal/kiosk/supervisor.go"
click node_deployment "https://github.com/lostmind84/openscale/blob/main/deploy/windows/install.ps1"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli,node_serve,node_config_platform,node_web_server,node_embedded_ui,node_station,node_domain toneBlue
class node_scale_registry,node_gram_scale,node_printing,node_sbpl,node_transports toneAmber
class node_sqlite_store,node_catalog_importer,node_catalog_sources toneMint
class node_diagnostics,node_updates,node_kiosk,node_deployment toneRose
class node_external_devices toneNeutral
```

## Components

### Station Runtime

- [CLI composition](https://github.com/lostmind84/openscale/blob/main/cmd/openscale/main.go): Go command · Loads runtime dependencies and runs station commands. · `cmd/openscale/main.go`
- [Serve command](https://github.com/lostmind84/openscale/blob/main/cmd/openscale/serve.go): runtime entry · Hosts the station HTTP UI and API. · `cmd/openscale/serve.go`
- [Config & platform](https://github.com/lostmind84/openscale/blob/main/cmd/openscale/config.go): runtime setup · Resolves configuration, platform paths, and services. · `cmd/openscale/config.go`
- [HTTP server & commands](https://github.com/lostmind84/openscale/blob/main/internal/web/server.go): web adapter · Exposes station commands and streaming state. · `internal/web/server.go`
- [Embedded client/admin UI](https://github.com/lostmind84/openscale/blob/main/internal/web/embed.go): embedded assets · Build-time Svelte interfaces served by the Go binary. · `internal/web/embed.go`
- [Station orchestration](https://github.com/lostmind84/openscale/blob/main/internal/station/station.go): application core · Coordinates weigh, price, label, journal, idempotency, and workers. · `internal/station/station.go`
- [Domain rules](https://github.com/lostmind84/openscale/blob/main/internal/domain/prepare.go): business domain · Products, safeguards, pricing, EAN-13, and label preparation. · `internal/domain/prepare.go`

### Hardware & Output

- [Scale driver registry](https://github.com/lostmind84/openscale/blob/main/internal/scale/registry.go): hardware adapter · Selects registered scale implementations. · `internal/scale/registry.go`
- [GRAM serial scale](https://github.com/lostmind84/openscale/blob/main/internal/scale/gramxfoc/gramxfoc.go): scale driver · `internal/scale/gramxfoc/gramxfoc.go`
- [Printing service](https://github.com/lostmind84/openscale/blob/main/internal/printing/service.go): output service · Selects print drivers and dispatches label output. · `internal/printing/service.go`
- [SBPL renderer](https://github.com/lostmind84/openscale/blob/main/internal/printing/sbpl/sbpl.go): label encoder · Encodes SATO-oriented print bytes. · `internal/printing/sbpl/sbpl.go`
- [Print transports](https://github.com/lostmind84/openscale/blob/main/internal/printing/transport/transport.go): device transport · Delivers through TCP, files, devices, or Windows spooler. · `internal/printing/transport/transport.go`

### Catalog & Storage

- [SQLite operational store](https://github.com/lostmind84/openscale/blob/main/internal/store/store.go): local persistence · Owns catalog, journals, imports, quarantine, and metadata. · `internal/store/store.go`
- [Catalog import pipeline](https://github.com/lostmind84/openscale/blob/main/internal/catalog/importer/importer.go): ingestion workflow · Discovers, parses, qualifies, quarantines, and atomically publishes catalogs. · `internal/catalog/importer/importer.go`
- [Catalog sources](https://github.com/lostmind84/openscale/blob/main/internal/catalog/csvodoo/csvodoo.go): source adapters · Odoo CSV, local drop folders, and WebDAV. · `internal/catalog/csvodoo/csvodoo.go`

### Operations

- [Diagnostics & reports](https://github.com/lostmind84/openscale/blob/main/internal/diag/doctor.go): operations service · Collects hardware, service, and redacted support information. · `internal/diag/doctor.go`
- [Safe updater](https://github.com/lostmind84/openscale/blob/main/internal/update/service.go): update service · Finds releases, verifies artifacts, stages, and applies updates. · `internal/update/service.go`
- [Kiosk supervision](https://github.com/lostmind84/openscale/blob/main/internal/kiosk/supervisor.go): recovery service · Supervises kiosk operation and recovery. · `internal/kiosk/supervisor.go`
- [OS deployment services](https://github.com/lostmind84/openscale/blob/main/deploy/windows/install.ps1): deployment scripts · Installs Windows kiosk/service or Debian systemd runtime. · `deploy/windows/install.ps1`

### Other components

- **Scale, printer & network**: external systems · Serial scale, print endpoints, optional WebDAV, and GitHub Releases.

## Connections

- CLI composition → Serve command: runs
- CLI composition → Config & platform: initializes
- Serve command → HTTP server & commands: hosts
- Serve command → Station orchestration: starts
- HTTP server & commands → Embedded client/admin UI: serves
- Embedded client/admin UI → HTTP server & commands: commands and state
- HTTP server & commands → Station orchestration: weigh and admin commands
- Station orchestration → Domain rules: applies rules
- Station orchestration → Scale driver registry: reads measurements
- Station orchestration → Printing service: dispatches labels
- Station orchestration → SQLite operational store: reads catalog and records results
- Scale driver registry → GRAM serial scale: selects driver
- GRAM serial scale → Scale, printer & network: serial I/O
- Printing service → SBPL renderer: renders labels
- SBPL renderer → Print transports: print bytes
- Print transports → Scale, printer & network: delivers output
- Catalog sources → Catalog import pipeline: catalog input
- Catalog import pipeline → SQLite operational store: publishes catalog and findings
- Catalog sources → Scale, printer & network: WebDAV access
- HTTP server & commands → Diagnostics & reports: admin diagnostics
- HTTP server & commands → Safe updater: admin updates
- Safe updater → Scale, printer & network: GitHub releases
- OS deployment services → Kiosk supervision: installs and supervises
- OS deployment services → Serve command: runs as service
