Files
CableGUI/README.md
mAi c206a331ec rename: mCables → CableGUI (project + repo + image + paths)
Full project rename per m's call. Single atomic commit because the
codebase rename is a coupled change — go module path, env vars, DB
default, Docker artefact names, and on-disk mDock paths all flip
together.

- go.mod: module mgit.msbls.de/m/mcables → mgit.msbls.de/m/cablegui
- cmd/mcables → cmd/cablegui (git mv)
- All Go imports rewritten to the new module path
- Env vars: MCABLES_ADDR/MCABLES_DB → CABLEGUI_ADDR/CABLEGUI_DB
- DB default path: data/mcables.db → data/cablegui.db
- Dockerfile + docker-compose.yml: image, container_name, env vars,
  bind-mount /home/m/stacks/mcables → /home/m/stacks/cablegui,
  secrets /home/m/secrets/mcables → /home/m/secrets/cablegui
- Makefile: bin target + run/build commands point at cmd/cablegui
- .gitignore + .dockerignore: /mcables → /cablegui
- README, docs/design.md, CLAUDE.md: prose + paths + image name
- web/static/index.html: <title> + brand
- web/static/main.js + web/web.go: header comment
- internal/exporter: Scene.Source "mcables" → "cablegui"
- internal/server/export.go: error-detail secrets path
- internal/db/migrations/*.sql: header comments (mCables vN → CableGUI vN)

Memory group_id kept as "mcables" to preserve existing memory continuity.
Documented as historical in CLAUDE.md.

go build ./... clean; go test -race ./... green
2026-05-16 15:35:42 +02:00

155 lines
5.1 KiB
Markdown

# CableGUI
Cable-management **framework** for m's setup — visual web editor backed by
a single Go binary + SQLite, generating Excalidraw drawings via mExDraw.
Each cable-managed environment (LOFT, OFFICE, …) is a separate CableGUI
*project*; each project is backed by exactly one `.excalidraw` drawing on
mxdrw.msbls.de.
## Status
Slice 1 — bootstrap shipped. Projects + global cable types are
end-to-end; the SVG canvas is intentionally empty until slice 2.
| Slice | What's in it | Status |
|---|---|---|
| 1 | Project CRUD, global cable types, empty SVG canvas, project picker | ✅ |
| 2 | Frames + devices, drag-to-position | pending |
| 3 | Ports + cables (click-port → click-port) | pending |
| 4 | IO markers + cable-type editing | pending |
| 5 | Export to mxdrw.msbls.de | pending |
## Run it
```sh
go run ./cmd/cablegui
# open http://localhost:7777
```
Or built:
```sh
make build
./bin/cablegui
```
The binary serves the frontend from an embedded `web/static/` and the
JSON API under `/api/`. SQLite lives at `./data/cablegui.db` by default.
### Environment
| Var | Default | Notes |
|---|---|---|
| `CABLEGUI_ADDR` | `0.0.0.0:7777` | Listen address. |
| `CABLEGUI_DB` | `./data/cablegui.db` | SQLite path. Parent dir is created on boot. |
| `MEXDRAW_BASE_URL` | `https://mxdrw.msbls.de` | Base URL for mExDraw export. |
| `MEXDRAW_USER` | (unset) | Username for the mxdrw HTTP Basic Auth on export. Required. |
| `MEXDRAW_PASS` | (unset) | Password for the mxdrw HTTP Basic Auth on export. Required. |
### Tests
```sh
make test # go test -race ./...
```
Store-level tests cover projects + cable-types CRUD, the
`drawing_name` auto-default, the `?confirm=<name>` guardrail on
`DELETE /api/projects/:pid`, and the `ON DELETE RESTRICT` on a
referenced cable type.
## API (slice 1)
```
GET /api/healthz → 200 {"status":"ok"}
GET /api/projects → [Project, …]
POST /api/projects ← {name, drawing_name?, description?}
drawing_name defaults to "<name>.excalidraw"
GET /api/projects/:pid → {project, cable_types, frames, devices, …}
PATCH /api/projects/:pid ← partial
DELETE /api/projects/:pid?confirm=<name> ← confirm must equal current name
GET /api/cable-types → [CableType, …] (global)
POST /api/cable-types ← {name, color}
PATCH /api/cable-types/:id ← partial — affects every project
DELETE /api/cable-types/:id ← 409 in_use if any cable references it
```
## Deploy to mDock
CableGUI runs on **mDock** at `http://mdock:7777` as a docker-compose
service under `/home/m/stacks/cablegui/`. Pattern matches the other
mDock services (mgreen-journal, mgeo, msports-garmin, …) — no Dokploy,
no reverse proxy, LAN-trusted.
### Manual deploy
1. **Build + push the image** (image now lives under `m/` in Gitea):
```sh
docker build -t mgit.msbls.de/m/cablegui:latest .
awk '/machine mgit.msbls.de/{getline; getline; print $2}' ~/.netrc \
| docker login mgit.msbls.de -u m --password-stdin
docker push mgit.msbls.de/m/cablegui:latest
```
2. **Prepare directories on mDock** (one-time):
```sh
ssh mdock 'mkdir -p /home/m/stacks/cablegui/data /home/m/secrets/cablegui \
&& touch /home/m/secrets/cablegui/.env \
&& chmod 0600 /home/m/secrets/cablegui/.env'
scp docker-compose.yml mdock:/home/m/stacks/cablegui/docker-compose.yml
```
3. **Pull + start**:
```sh
ssh mdock 'cd /home/m/stacks/cablegui && docker compose pull && docker compose up -d'
```
4. **Verify** from any LAN host:
```sh
curl http://mdock:7777/api/healthz # → {"status":"ok"}
curl http://mdock:7777/api/cable-types # → the 5 seeded types
```
To **update** to a new build: rebuild + push the image, then
`ssh mdock 'cd /home/m/stacks/cablegui && docker compose pull && docker compose up -d'`.
### Persistence
SQLite lives at `/home/m/stacks/cablegui/data/cablegui.db` on the host
(bind-mounted into the container at `/app/data`). Container runs as
UID 1000:1000 to align with `m:m` ownership on mDock — DB files end
up owned by `m`, the host user.
`docker compose restart` keeps the data intact (tested 2026-05-15).
### Automation — follow-up task
This first roll is **manual**. A Gitea Actions workflow on the
self-hosted runner already on mDock (`/home/m/act-runner/`, label
`self-hosted:host`) — build → push → `docker compose up -d` on every
push to `main` — is a separate task per the design's §10. Tracking
spawned by the head if/when wanted.
## Design + project conventions
- `docs/design.md` — full v3 design (schema, API, importer/export
conventions, slices, mDock deploy notes).
- `CLAUDE.md` — project instructions for mai workers.
## Architecture
| Layer | Tech |
|---|---|
| DB | SQLite via `modernc.org/sqlite` (cgo-free), WAL, FKs on |
| Backend | Go 1.22+ `net/http` ServeMux pattern routing, single binary |
| Frontend | Vanilla ES modules + SVG, no build step, embedded via `embed.FS` |
| Export (slice 5) | mExDraw HTTP API on mxdrw.msbls.de |
LAN-trusted, no auth.