Files
tuio/CLAUDE.md
T
jbandClaude Opus 4.8 3edfaa4ab2 test: add unit tests for config generation and form values
Cover the deploy-critical pure logic:

- GenerateConfigTOML: round-trip decode of values + a guard asserting the
  config port is always containerAppPort (host port must not leak)
- GenerateWireguardConfig: MTU emitted/commented, PROTO default UDP
- WriteConfigFile / WriteWireguardConfigFile: numeric validation rejects
  bad input and does not write a file
- FormStep.Values(): text/password/select resolution and select default
  fallback

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 12:04:31 -03:00

7.0 KiB
Raw Blame History

CLAUDE.md

Guidance for Claude Code when working in this repository.

User-facing docs are in Portuguese (BR): README.md and docs/. This file is in English and is the technical source of truth for how the code works.

What this is

A terminal UI (TUI) installer for the "App do Dono" client middleware. The middleware runs on a tenant's infrastructure and brokers communication between the tenant's servers and davinTI's central server.

The installer is a guided wizard that: checks Docker → logs into the private registry → pulls images → (optionally) sets up a WireGuard tunnel (vproxy) when there is no public IP → collects configuration via terminal forms → generates config files (config.toml, envs) → runs the Docker containers.

It is not the middleware itself — it only provisions and launches it via docker.

Tech stack

  • Go 1.25
  • Bubble Tea v2 (charm.land/bubbletea/v2) — Elm-architecture TUI runtime.
  • Bubbles v2 — textinput, spinner components.
  • Lip Gloss v2 — styling.
  • BurntSushi/toml — read existing config.toml for form defaults.
  • Module path: git.davinti.com.br/davinTI/app-dono/tui.

Layout

cmd/main.go            Entry point; starts the Bubble Tea program.
internal/tui/
  model.go             Model struct, ConfigValues, loadConfig (defaults), InitialModel, Init.
  steps.go             step enum — the ordered wizard stages.
  update.go            Update: global keys + per-step dispatch (handlers).
  view.go              View: header + per-step body + help footer (AltScreen).
  form.go              Generic FormStep/FormField component (text/password/number/select).
  cmds.go              Msg types and async tea.Cmd wrappers around docker/file ops.
  docker.go            os/exec wrappers around the `docker` binary.
  config.go            Generates & writes config.toml and envs (+ numeric validation).
  styles.go            Lip Gloss palette/styles.
Makefile               Multi-arch build + S3 publish.

Architecture (Model–Update–View)

  • Model (model.go) holds all state: currentStep, progress/error flags, one FormStep per form, and configValues (ConfigValues) which accumulates each form's map[string]string output by section.
  • Update (update.go) handles global messages (Ctrl+C, window size, spinner tick) then dispatches on currentStep to per-step handlers. Step transitions happen when a form returns done == true or when an async completion message arrives.
  • View (view.go) renders per-step.
  • Commands (cmds.go) wrap every blocking op (docker calls, file writes) as a tea.Cmd returning a Msg: DockerCheckedMsg, ImageDownloadFinishedMsg, ConfigFileMsg, DockerRunMsg, TickMsg.

Wizard flow

steps.go defines the order. See docs/fluxo.md for full detail.

  1. StepCheckDocker — exec.LookPath("docker"). Missing → StepDockerInstall (instructs manual install and exits; never auto-installs Docker).
  2. StepDockerLogin → StepDownloadImage — docker login + pull of the app image. These registry credentials are reused later for the vproxy image.
  3. StepIPQuestion — "public IP available?"
    • Yes → jump to StepAppConfig.
    • No → vproxy block: StepWireguardConfig → StepGenerateWireguardFile (writes envs) → StepDownloadWireguard → StepRunWireguard.
  4. Config forms: StepAppConfig → StepServerConfig → StepDatabaseConfig → StepCertConfig.
  5. StepGenerateFile — writes config.toml (validates numeric fields first).
  6. StepRunDocker — runs app-dono-cliente container.
  7. StepDone.

Key constants

In update.go:

  • imageName = hub.davinti.com.br:443/app-dono/app-cliente:latest
  • wireguardImageName = hub.davinti.com.br:443/davinti-vproxy:latest
  • configPath = config.toml, wireguardConfigPath = envs

In docker.go: networkName = app-dono_app (all containers join this network; created on demand).

Generated files

  • config.toml — app config, bind-mounted at /app/config.toml. If present at startup it seeds form defaults via loadConfig. Generated by GenerateConfigTOML.
  • envs — vproxy/WireGuard env vars, passed via --env-file. Generated only when there is no public IP. By GenerateWireguardConfig.

Both are gitignored.

Containers

Container Image Notes
app-dono-cliente app-cliente <host port>:8080, mounts config.toml + cert dir, --restart unless-stopped, runs as host uid:gid.
vproxy davinti-vproxy --cap-add=NET_ADMIN, /dev/net/tun, --env-file envs, only without public IP.

seccomp=unconfined is added to either container when the "Modo Compatibilidade" (seccomp_unconfined) select is "Sim" — for old machines.

Gotchas (read before editing)

  • Port: config.toml always writes port = 8080 (hardcoded in GenerateConfigTOML). The form's "Porta" value only sets the host-side port in the docker run mapping (<port>:8080); inside the container the app always listens on 8080.
  • Network name is the networkName constant (app-dono_app) in docker.go; use it rather than re-typing the literal.
  • Registry credentials are collected once (login form) and reused for the vproxy pull — no second prompt.
  • Containers run detached and are verified with docker inspect for running; on failure the last 20 log lines are surfaced.

Build & run

go run ./cmd                 # run from source
go build -o installer ./cmd  # local binary

make build                   # multi-arch (linux/darwin/windows, amd64/arm64) → ./dist
make build VERSION=2.0.0
make clean
make push    S3_BUCKET=<bucket> VERSION=<v>   # sync dist/ to S3 (version + latest)
make release S3_BUCKET=<bucket> VERSION=<v>   # per-binary copy with OS/arch naming

Tests (go test ./...) cover the pure logic in config_test.go (config.toml/envs generation + numeric validation) and form_test.go (FormStep.Values()). The docker wrappers, Update and View are not unit-tested — verify those by running go build ./... and exercising the TUI manually. Fully running the installer requires a working Docker daemon and registry access.

Conventions

  • User-facing strings in the TUI are Portuguese (BR); keep new ones consistent.
  • Keep code comments and identifiers matching the surrounding style (mixed English identifiers, Portuguese user messages).
  • When adding a wizard step: add it to steps.go, a handler in update.go, a render branch in view.go, and any new Msg/Cmd in cmds.go.