# brinkhaustools

## Overview

Python package providing common infrastructure for Brinkhaus industrial applications.
Extracted from the internal `pythonuiapphelper` module, simplified to **single-process / multi-threaded** (no multiprocessing IPC).

Publishable to PyPI.

## Project Structure

```
src/brinkhaustools/
├── __init__.py              # Package version
├── common/
│   ├── app.py               # App – central wiring object
│   ├── shutdown.py           # ShutdownHandler – graceful shutdown, signal handling
│   ├── logging.py            # LoggingHelper – RotatingFileHandler + ring buffer
│   ├── settings.py           # Settings – JSON config, hierarchical get/set, dot-notation
│   ├── diagnosis.py          # SelfDiagnosisEngine – error/warning tracking with codes
│   ├── status.py             # StatusEngine + StatusSource ABC – periodic status collection
│   ├── heartbeat.py          # HeartbeatEngine – watchdog for hung threads
│   ├── version.py            # VersionInformation – loads version.json
│   └── fleet/
│       ├── client.py         # FleetMonitorClient – HTTPS ingest (stdlib urllib)
│       └── monitor.py        # StatusMonitor – bridges diagnosis → fleet HTTPS
└── rest/
    └── server.py             # RestServer – Flask + Waitress HTTP server
```

## Key Design Patterns

- **App wiring object** replaces the old singleton-only approach. Components auto-wire via `App(...)`, but each also has `get_instance()` for standalone use.
- **Pass `None`** to skip any component: `App(settings_path=None)` → no settings file.
- **threading only** – all locks are `threading.RLock`, events are `threading.Event`. No `multiprocessing.*`.
- **Settings** supports both list keys (`["section", "key", 0]`) and dot-notation (`"section.key.0"`).
- **Atomic file writes** – Settings persists via `.tmp` + rename, keeps `.bak` backup.
- **Lazy imports** – Flask/Waitress only imported when `brinkhaustools.rest` is used.

## Dependencies

| Scope | Packages |
|-------|----------|
| Core  | _(none – stdlib only)_ |
| `[rest]` extra | `flask`, `flask-cors`, `waitress`, `bcrypt` |
| `[dev]` extra | `pytest`, `pytest-timeout`, `mypy` |

## Fleet Management Protocol

Wire-compatible with BrinkhausFleetManager. HTTPS POST with Bearer token auth.

| Endpoint | Payload |
|----------|---------|
| `POST /api/ingest/{customer}/{machine}/{software}/heartbeat` | `{ts, version, uptime_seconds, pid, ip_addresses}` |
| `POST /api/ingest/{customer}/{machine}/{software}/diagnostics` | `{ts, items: [{code, message, severity}]}` |
| `POST /api/ingest/{customer}/{machine}/{software}/status` | `{ts, status: "running"\|"degraded"\|"stopped"\|..., message}` |

Severity: 0=Info, 1=Warning, 2=Error. Auth: `Authorization: Bearer {token}`.

Config file: `fleetManagementData/config.json` with key `fleetmanagement.*`.
Supports `base_url` key or legacy `broker` key (auto-derives `https://{broker}`).
Env overrides: `STATUS_MONITOR_CUSTOMERID`, `STATUS_MONITOR_MACHINEID`, `FLEET_HOST_IPS`.

## REST Endpoints (brinkhaustools.rest)

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/login` | POST | Authenticate (bcrypt) |
| `/api/password` | POST | Change password |
| `/api/getSettings` | GET | Full settings JSON |
| `/api/setSettings` | POST | Replace settings |
| `/api/getDescription` | GET | Settings schema |
| `/api/version` | GET | version.json |
| `/api/logs/getServiceLog` | GET | Ring buffer (last N log lines) |
| `/api/status/RuntimeTests` | GET | Diagnosis status |
| `/api/status/all` | GET | All StatusEngine data |
| `/api/restartApp` | GET | Trigger shutdown |

Host/port configurable via `RestServer(host=..., port=...)`.

## Default File Paths

| Path | Purpose |
|------|---------|
| `data/settings/settings_main.json` | Main settings |
| `data/logs/` | Rotating log files |
| `helper/version.json` | CI-generated version info |
| `fleetManagementData/config.json` | Fleet management config |

All configurable via App constructor or individual class constructors.

## Commands

```bash
# Install
pip install -e ".[dev,rest]"

# Run tests (standard entry point, produces JUnit XML)
python tests/run-tests.py

# Or directly with pytest
pytest tests/ -v --timeout=30

# Type check
mypy src/

# Build wheel
python -m build
```

## CI Pipeline (.gitlab-ci.yml)

- **test** – runs on every push/MR, produces JUnit XML report
- **typecheck** – mypy on every push/MR (`allow_failure: true`)
- **build** – builds wheel on semver tags (`X.Y.Z`)
- **publish** – auto-publishes to PyPI on semver tags (requires `PYPI_TOKEN` variable)
- **pages** – deploys MkDocs documentation to GitLab Pages on `master`

## Component Dependency Graph

```
ShutdownHandler  (standalone)
├── LoggingHelper
├── Settings
├── SelfDiagnosisEngine
│   └── StatusMonitor → FleetMonitorClient (HTTPS)
├── StatusEngine
│   ├── registers: SelfDiagnosisEngine
│   ├── registers: HeartbeatEngine
│   ├── registers: VersionInformation
│   └── registers: StatusMonitor
├── HeartbeatEngine
└── RestServer (reads from all above)
```

## GitLab

Project ID: **TBD** (https://gitlab.com/brinkhaus/brinkhaustools)

Use `/gitlab` to interact with issues:
- `/gitlab issues <ID>` -- list open issues
- `/gitlab get-issue <ID> 42` -- full details of issue #42
- `/gitlab create-issue <ID> "Title" "Description"`
- `/gitlab close-issue <ID> 42`

## Versioning

When bumping the version, update all three locations:

1. `pyproject.toml` → `version = "X.Y.Z"`
2. `src/brinkhaustools/__init__.py` → `__version__ = "X.Y.Z"`
3. `docs/index.md` → Project Status section

Then tag and push: `git tag X.Y.Z && git push origin X.Y.Z`

## Git

- **Main branch:** `master`
- **Registry:** PyPI (auto-published on semver tags)

## Internal Documentation

Cross-project architecture, infrastructure, and development standards are maintained in a
dedicated repo on GitLab:

- **GitLab:** `git@gitlab.com:brinkhaus/internal-docs.git`
- **Local path (typical):** `../internal-docs`

Key contents:

| Path | Topic |
|------|-------|
| `processes/development-standards.md` | Common development ruleset |
| `processes/release-process.md` | Release workflow |
| `processes/adding-a-project-to-fleet.md` | Fleet onboarding |
| `architecture/system-overview.md` | System architecture |
| `architecture/fleet-protocol.md` | Fleet management protocol |
| `infrastructure/ci-cd.md` | CI/CD setup |
| `infrastructure/servers.md` | Server inventory |

Consult this repo for environment details, process descriptions, and cross-project standards.
